Import UltraRogue from the Roguelike Restoration Project (r1490)
This commit is contained in:
parent
c346921c68
commit
11c74c273d
59 changed files with 42044 additions and 0 deletions
138
urogue/LICENSE.TXT
Normal file
138
urogue/LICENSE.TXT
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
Portions Copyright (C) 1985 Michael Morgan, Ken Dalka
|
||||
Portions Copyright (C) 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
Portions Copyright (C) 1993, 1995 Nicholas J. Kisseberth
|
||||
All rights reserved.
|
||||
|
||||
===========================================================================
|
||||
|
||||
UltaRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name(s) of the author(s) nor the names of other contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
4. The name "UltraRogue" and "urogue" must not be used to endorse or
|
||||
promote products derived from this software without prior written
|
||||
permission.
|
||||
5. Products derived from this software may not be called "UltraRogue" or
|
||||
"urogue", nor may "UltraRogue" or "urogue" appear in their name,
|
||||
without prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
===========================================================================
|
||||
|
||||
Portions of this software are based on the work of Michael Morgan and
|
||||
Ken Dalka. Used under license:
|
||||
|
||||
Advanced Rogue
|
||||
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name(s) of the author(s) nor the names of other contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
===========================================================================
|
||||
|
||||
Portions of this software are based on the work of Michael Toy, Ken Arnold
|
||||
and Glenn Wichman. Used under license:
|
||||
|
||||
Rogue: Exploring the Dungeons of Doom
|
||||
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name(s) of the author(s) nor the names of other contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
===========================================================================
|
||||
|
||||
Portions of this software (save/restore game state) are based on the work
|
||||
of Nicholas J. Kisseberth. Used under license:
|
||||
|
||||
Copyright (C) 1993, 1995 Nicholas J. Kisseberth
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name(s) of the author(s) nor the names of other contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
167
urogue/Makefile
Normal file
167
urogue/Makefile
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
# UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
# Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
# All rights reserved.
|
||||
#
|
||||
# See the file LICENSE.TXT for full copyright and licensing information.
|
||||
|
||||
#
|
||||
# Makefile for urogue
|
||||
#
|
||||
|
||||
DISTNAME=urogue1.0.7
|
||||
|
||||
HDRS = dict.h dictutil.h rogue.h
|
||||
OBJS = armor.o \
|
||||
artifact.o \
|
||||
bag.o \
|
||||
chase.o \
|
||||
command.o \
|
||||
daemon.o \
|
||||
daemons.o \
|
||||
dict.o \
|
||||
dictutil.o \
|
||||
encumb.o \
|
||||
fight.o \
|
||||
getplay.o \
|
||||
ident.o \
|
||||
init.o \
|
||||
io.o \
|
||||
list.o \
|
||||
magic.o \
|
||||
main.o \
|
||||
maze.o \
|
||||
memory.o \
|
||||
misc.o \
|
||||
monsdata.o \
|
||||
monsters.o \
|
||||
move.o \
|
||||
newlvl.o \
|
||||
options.o \
|
||||
pack.o \
|
||||
passages.o \
|
||||
player.o \
|
||||
potions.o \
|
||||
random.o \
|
||||
rings.o \
|
||||
rip.o \
|
||||
rooms.o \
|
||||
save.o \
|
||||
scrolls.o \
|
||||
state.o \
|
||||
status.o \
|
||||
sticks.o \
|
||||
things.o \
|
||||
trader.o \
|
||||
verify.o \
|
||||
vers.o \
|
||||
weapons.o \
|
||||
wizard.o
|
||||
|
||||
PROGRAM = ur
|
||||
|
||||
CFILES = armor.c \
|
||||
artifact.c \
|
||||
bag.c \
|
||||
chase.c \
|
||||
command.c \
|
||||
daemon.c \
|
||||
daemons.c \
|
||||
dict.c \
|
||||
dictutil.c \
|
||||
encumb.c \
|
||||
fight.c \
|
||||
getplay.c \
|
||||
ident.c \
|
||||
init.c \
|
||||
io.c \
|
||||
list.c \
|
||||
magic.c \
|
||||
main.c \
|
||||
maze.c \
|
||||
memory.c \
|
||||
misc.c \
|
||||
monsdata.c \
|
||||
monsters.c \
|
||||
move.c \
|
||||
newlvl.c \
|
||||
options.c \
|
||||
pack.c \
|
||||
passages.c \
|
||||
player.c \
|
||||
potions.c \
|
||||
random.c \
|
||||
rings.c \
|
||||
rip.c \
|
||||
rooms.c \
|
||||
save.c \
|
||||
scrolls.c \
|
||||
state.c \
|
||||
status.c \
|
||||
sticks.c \
|
||||
things.c \
|
||||
trader.c \
|
||||
verify.c \
|
||||
vers.c \
|
||||
weapons.c \
|
||||
wizard.c
|
||||
|
||||
MISC= Makefile README LICENSE.TXT history.txt TODO
|
||||
|
||||
CC = gcc
|
||||
CFLAGS= -O3
|
||||
CRLIB = -lcurses
|
||||
RM = rm -f
|
||||
TAR = tar
|
||||
|
||||
urogue: $(OBJS) $(MAKEFILE)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(CRLIB) -o $@
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS) urogue a.out core *.map urogue.exe urogue.cat
|
||||
|
||||
dist.src:
|
||||
make clean
|
||||
tar cf $(DISTNAME)-src.tar $(CFILES) $(HDRS) $(MISC)
|
||||
gzip -f $(DISTNAME)-src.tar
|
||||
|
||||
dist.irix:
|
||||
make clean
|
||||
make CC=cc CFLAGS="-woff 1116 -O3" urogue
|
||||
nroff -man urogue.6 | colcrt - > urogue.cat
|
||||
tar cf $(DISTNAME)-irix.tar urogue urogue.cat README LICENSE.TXT
|
||||
gzip -f $(DISTNAME)-irix.tar
|
||||
|
||||
dist.aix:
|
||||
make clean
|
||||
make CC=xlc CFLAGS="-qmaxmem=16768 -O3 -qstrict" urogue
|
||||
nroff -man urogue.6 | colcrt - > urogue.cat
|
||||
tar cf $(DISTNAME)-aix.tar urogue urogue.cat README LICENSE.TXT
|
||||
gzip -f $(DISTNAME)-aix.tar
|
||||
|
||||
dist.linux:
|
||||
make clean
|
||||
make urogue
|
||||
groff -man urogue.6 | sed -e 's/.\x08//g' > urogue.cat
|
||||
tar cf $(DISTNAME)-linux.tar urogue urogue.cat README LICENSE.TXT
|
||||
gzip -f $(DISTNAME)-linux.tar
|
||||
|
||||
dist.interix:
|
||||
make clean
|
||||
make urogue
|
||||
groff -P-b -P-u -man -Tascii urogue.6 > urogue.cat
|
||||
tar cf $(DISTNAME)-interix.tar urogue urogue.cat README LICENSE.TXT
|
||||
gzip -f $(DISTNAME)-interix.tar
|
||||
|
||||
dist.cygwin:
|
||||
make clean
|
||||
make urogue
|
||||
groff -P-c -man -Tascii urogue.6 | sed -e 's/.\x08//g' > urogue.cat
|
||||
tar cf $(DISTNAME)-cygwin.tar urogue.exe urogue.cat README LICENSE.TXT
|
||||
gzip -f $(DISTNAME)-cygwin.tar
|
||||
|
||||
dist.djgpp:
|
||||
make clean
|
||||
make LDFLAGS="-L$(DJDIR)/LIB" CRLIB="-lpdcurses" urogue
|
||||
groff -man -Tascii urogue.6 | sed -e 's/.\x08//g' > urogue.cat
|
||||
rm -f $(DISTNAME)-djgpp.zip
|
||||
zip $(DISTNAME)-djgpp.zip urogue.exe urogue.cat README LICENSE.TXT
|
||||
74
urogue/README
Normal file
74
urogue/README
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
There are 8 different treasures to be picked up in this version of rogue.
|
||||
The first is on level 25 and is relatively easy to pick up. The last is
|
||||
on level 100 and is very difficult to get. Carrying any one of the
|
||||
unique treasures allows the rogue to go up the stairs, but one has to
|
||||
be very careful. To be a total winner, yu must pick up all 8 and
|
||||
return to the surface again.
|
||||
|
||||
(note: the above may be incorrect, i think the number of levels is
|
||||
reduced to 50 and you have to get all 8 artifacts to go back up)
|
||||
|
||||
The environment variable UROGUE is used to set up the default things
|
||||
for a player. The options that can be set are:
|
||||
|
||||
terse: short output messages
|
||||
flush: flush typeahead when fighting
|
||||
jump: show position only at the end of running
|
||||
inven: inventory style
|
||||
askme: ask about unidentified things
|
||||
stopdoor: stop running when next to something interesting
|
||||
name: the rogue's name (string)
|
||||
fruit: the funny fruit used by the rogue (string)
|
||||
file: default savefile name (string)
|
||||
score: default scorefile name (string)
|
||||
class: default player class (string)
|
||||
|
||||
Something like
|
||||
|
||||
setenv UROGUE "name=George of the Jungle,fruit=peach,noterse,jump"
|
||||
|
||||
does the obvious. The "score" option is ignored unless you start
|
||||
urogue in wizard mode. The class option string can have the following
|
||||
values: "fighter", "illus", "paladin", "ranger", "cleric", "magic",
|
||||
"assasin", "druid", "ninja", and "thief" and is initialized only at
|
||||
startup time. The "inven" option can take the values "slow", "clear",
|
||||
and "overwrite".
|
||||
|
||||
|
||||
About the Author
|
||||
================
|
||||
|
||||
Herb Chong is currently freelance writing and doing some teaching.
|
||||
If you pick up a copy of Windows Sources Magazine, you can usually
|
||||
find something he has written. Starting in October (1993) he will
|
||||
have a regular column. Herb has also just started teaching Adult Ed
|
||||
and undergraduate classes at Mercy College, a small and not very well
|
||||
known college in Westchester, NY.
|
||||
|
||||
Acknowledgements
|
||||
================
|
||||
|
||||
The source code for Rogue 3.6 (by Michael Toy, Ken Arnold and Glenn
|
||||
Wichman) was used as the original basis for this game. A thousand
|
||||
thanks go out to them and their classic adventure game of the early 1980s.
|
||||
|
||||
Modifications of a long forgotten and bastardized nature were taken
|
||||
from Advanced Rogue 1.0 and/or SuperRogue. We believe that the flea market,
|
||||
pools, and maze levels had their origin somewhere around here.
|
||||
|
||||
Chief Architect : Herb Chong
|
||||
|
||||
Major Contributers: Carlton Hommel Mike Cooper Mike Laman
|
||||
Jason Venner Nick Kisseberth
|
||||
|
||||
Other Contributers: Nick Flor Henry Chai Pat Place
|
||||
Michael Maudlin dan@ciprico edjames@ucbshadow
|
||||
Web Dove Tim Haapanen tecot@cmu-cs-k.arpa
|
||||
|
||||
Any omissions or errors are purely unintentional. The above list was
|
||||
compiled by Nick Kisseberth from the change log in UltraRogue through
|
||||
1987 and from correspondense with Herb Chong.
|
||||
23
urogue/TODO
Normal file
23
urogue/TODO
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
%W% %G%
|
||||
|
||||
add_pack() calls ur_free() on the linked list pointer passed
|
||||
to it. Need to go through code and look for cases where we
|
||||
use that pointer after calling add_pack(). Electric
|
||||
fence in guard-free() mode should help.
|
||||
|
||||
Similary throw_away(), discard(), discard_pack() free items...
|
||||
there will be more like this...
|
||||
|
||||
Bug in genocide scroll: don't request list, type letter, etc...
|
||||
|
||||
Implement potion of true sight.
|
||||
|
||||
Bug: apparently when creating a new familiar after a player level
|
||||
change, something isn't begin reset because ur SEGVs when running
|
||||
through the monster list in do_chase() right after the new
|
||||
familiar is created. It appears that the familiar isn't being removed
|
||||
from the monster list.
|
||||
207
urogue/armor.c
Normal file
207
urogue/armor.c
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
armor.c - functions for dealing with armor
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
Based on "Advanced Rogue"
|
||||
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
|
||||
All rights reserved.
|
||||
|
||||
Based on "Rogue: Exploring the Dungeons of Doom"
|
||||
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
wear()
|
||||
The player wants to wear something, so let him/her put it on.
|
||||
*/
|
||||
|
||||
void
|
||||
wear(void)
|
||||
{
|
||||
struct object *obj;
|
||||
|
||||
if (cur_armor != NULL)
|
||||
{
|
||||
msg("You are already wearing some.");
|
||||
|
||||
after = FALSE;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* What does player want to wear? */
|
||||
|
||||
if ((obj = get_object(pack, "wear", ARMOR, NULL)) == NULL)
|
||||
return;
|
||||
|
||||
wear_ok(&player, obj, MESSAGE);
|
||||
waste_time();
|
||||
|
||||
cur_armor = obj;
|
||||
obj->o_flags |= ISKNOW;
|
||||
|
||||
msg("You are now wearing %s.", inv_name(obj, TRUE));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
take_off()
|
||||
Get the armor off of the players back
|
||||
*/
|
||||
|
||||
void
|
||||
take_off(void)
|
||||
{
|
||||
struct object *obj;
|
||||
|
||||
if ((obj = cur_armor) == NULL)
|
||||
{
|
||||
msg("You aren't wearing armor!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dropcheck(cur_armor))
|
||||
return;
|
||||
|
||||
msg("You were wearing %c%c) %s.", ARMOR, print_letters[get_ident(obj)],
|
||||
inv_name(obj, LOWERCASE));
|
||||
|
||||
cur_armor = NULL;
|
||||
|
||||
if (on(player, STUMBLER))
|
||||
{
|
||||
msg("Your foot feels a lot better now.");
|
||||
turn_off(player, STUMBLER);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
wear_ok()
|
||||
enforce player class armor restrictions
|
||||
*/
|
||||
|
||||
int
|
||||
wear_ok(struct thing *wearee, struct object *obj, int print_message)
|
||||
{
|
||||
int which = obj->o_which;
|
||||
int ret_val = TRUE;
|
||||
int class_type = wearee->t_ctype;
|
||||
|
||||
if (obj->o_type != ARMOR)
|
||||
return(FALSE);
|
||||
else
|
||||
switch (class_type)
|
||||
{
|
||||
case C_MAGICIAN: /* cannot wear metal */
|
||||
case C_ILLUSION:
|
||||
switch (which)
|
||||
{
|
||||
case RING_MAIL:
|
||||
case SCALE_MAIL:
|
||||
case PADDED_ARMOR:
|
||||
case CHAIN_MAIL:
|
||||
case BRIGANDINE:
|
||||
case SPLINT_MAIL:
|
||||
case GOOD_CHAIN:
|
||||
case PLATE_MAIL:
|
||||
case PLATE_ARMOR:
|
||||
ret_val = FALSE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
case C_THIEF: /* cannot clank around */
|
||||
case C_ASSASIN:
|
||||
case C_NINJA:
|
||||
switch (which)
|
||||
{
|
||||
case CHAIN_MAIL:
|
||||
case BRIGANDINE:
|
||||
case SPLINT_MAIL:
|
||||
case GOOD_CHAIN:
|
||||
case PLATE_MAIL:
|
||||
case PLATE_ARMOR:
|
||||
ret_val = FALSE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
case C_CLERIC: /* cannot wear plate */
|
||||
case C_DRUID:
|
||||
switch (which)
|
||||
{
|
||||
case PLATE_MAIL:
|
||||
case PLATE_ARMOR:
|
||||
case MITHRIL:
|
||||
ret_val = FALSE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
case C_FIGHTER: /* wear anything */
|
||||
case C_RANGER:
|
||||
break;
|
||||
|
||||
case C_PALADIN: /* cannot wear common stuff */
|
||||
switch (which)
|
||||
{
|
||||
case SOFT_LEATHER:
|
||||
case CUIRBOLILLI:
|
||||
case HEAVY_LEATHER:
|
||||
case STUDDED_LEATHER:
|
||||
case PADDED_ARMOR:
|
||||
case BRIGANDINE:
|
||||
ret_val = FALSE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
case C_MONSTER:
|
||||
break;
|
||||
|
||||
default: /* Unknown class */
|
||||
debug("Unknown class %d.", class_type);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret_val == FALSE && print_message == MESSAGE)
|
||||
switch (class_type)
|
||||
{
|
||||
case C_MAGICIAN:
|
||||
case C_ILLUSION:
|
||||
msg("You cannot regenerate spell points while wearing that!");
|
||||
break;
|
||||
|
||||
case C_THIEF:
|
||||
case C_ASSASIN:
|
||||
case C_NINJA:
|
||||
msg("Don't expect to be stealthy while wearing that!");
|
||||
break;
|
||||
|
||||
case C_CLERIC:
|
||||
case C_DRUID:
|
||||
case C_PALADIN:
|
||||
msg("Your god strongly disapproves of your wearing that!");
|
||||
break;
|
||||
|
||||
case C_FIGHTER:
|
||||
case C_RANGER:
|
||||
case C_MONSTER:
|
||||
break;
|
||||
}
|
||||
|
||||
return(ret_val);
|
||||
}
|
||||
1922
urogue/artifact.c
Normal file
1922
urogue/artifact.c
Normal file
File diff suppressed because it is too large
Load diff
448
urogue/bag.c
Normal file
448
urogue/bag.c
Normal file
|
|
@ -0,0 +1,448 @@
|
|||
/*
|
||||
bag.c - functions for dealing with bags
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* new bag functions
|
||||
*
|
||||
* This is a simple version of bag.c that uses linked lists to perform the bag
|
||||
* functions. The bag is just a linked list of objects (struct object) to be
|
||||
* specific, but most of that is supposed to be hidden from the user, who
|
||||
* should access the bag only through the functions presented here.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* apply_to_bag
|
||||
*
|
||||
* This is the general bag manipulation routine. The bag is subjected to
|
||||
* selection criteria and those objects which pass are processed by an action
|
||||
* routine. The two criteria are type and filter function. The filter
|
||||
* function returns TRUE if the object passes and FALSE otherwise. The filter
|
||||
* function is passed the object and the user-supplied argument. This gives
|
||||
* the user plenty of flexibility in determining which items will be
|
||||
* processed. The action routine is passed the object, the id, and the
|
||||
* user-supplied argument given to apply_to_bag. Specifying NULL for either
|
||||
* the type or filter function means that criterion always selects. A NULL
|
||||
* action routine means no processing is done and the first object which
|
||||
* passes the filter is returned to the user. The action routine returns TRUE
|
||||
* if processing should continue or FALSE if the current item should be
|
||||
* returned to the caller.
|
||||
*
|
||||
* Returns NULL if the bag is empty or if nothing qualified.
|
||||
*
|
||||
* linked_list *bag_p; // linked list of objects
|
||||
* int type; // what is its type (ARMOR, ...)
|
||||
* int (*bff_p)(); // bag filter function
|
||||
* int (*baf_p)(); // bag action routine
|
||||
* long user_arg; // user argument for filter, action
|
||||
*
|
||||
*/
|
||||
|
||||
struct object *
|
||||
apply_to_bag(struct linked_list *bag_p,
|
||||
int type,
|
||||
int (*bff_p)(struct object *obj, bag_arg *user_arg),
|
||||
int (*baf_p)(struct object *obj, bag_arg *user_arg, int id),
|
||||
void *user_arg)
|
||||
{
|
||||
struct object *bag_obj_p = NULL; /* qualifying object */
|
||||
struct object *cur_obj_p; /* current object */
|
||||
bag_arg arg;
|
||||
|
||||
arg.varg = user_arg;
|
||||
|
||||
if (bag_p == NULL)
|
||||
return (NULL);
|
||||
|
||||
for (; bag_p != NULL; bag_p = next(bag_p))
|
||||
{
|
||||
cur_obj_p = OBJPTR(bag_p);
|
||||
|
||||
if (type != 0 && type != cur_obj_p->o_type)
|
||||
continue;
|
||||
|
||||
if (bff_p != NULL && !(*bff_p)(cur_obj_p, &arg))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* At this point, we have an object which qualifies for
|
||||
* processing
|
||||
*/
|
||||
|
||||
bag_obj_p = cur_obj_p; /* in case the user wants it */
|
||||
|
||||
if (baf_p != NULL && (*baf_p)(cur_obj_p, &arg, identifier(bag_obj_p)))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* We have an object which qualifies, quit now!
|
||||
*/
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (bag_p == NULL)
|
||||
return (NULL);
|
||||
|
||||
return (bag_obj_p);
|
||||
}
|
||||
|
||||
/*
|
||||
count_bag()
|
||||
|
||||
Counts up all bag items which meet the selection criteria
|
||||
*/
|
||||
|
||||
int
|
||||
count_bag(linked_list *bag_p,
|
||||
int type,
|
||||
int (*bff_p)(struct object *obj, bag_arg *junk))
|
||||
{
|
||||
int cnt = 0;
|
||||
apply_to_bag(bag_p, type, bff_p, baf_increment, &cnt);
|
||||
|
||||
return(cnt);
|
||||
}
|
||||
|
||||
/*
|
||||
del_bag()
|
||||
|
||||
Removes an object from a bag and throws it away.
|
||||
*/
|
||||
|
||||
void
|
||||
del_bag(linked_list *bag_p, object *obj_p)
|
||||
{
|
||||
pop_bag(&bag_p, obj_p); /* get the thing from the bag */
|
||||
ur_free(obj_p); /* release the memory */
|
||||
}
|
||||
|
||||
/*
|
||||
pop_bag()
|
||||
|
||||
Removes an item from a bag and returns it to the user. If the item is
|
||||
not in the bag, return NULL.
|
||||
*/
|
||||
|
||||
struct object *
|
||||
pop_bag(linked_list **bag_pp, object *obj_p)
|
||||
{
|
||||
linked_list *item_p;
|
||||
|
||||
for (item_p = *bag_pp; item_p != NULL && OBJPTR(item_p) != obj_p;
|
||||
item_p = next(item_p));
|
||||
|
||||
if (item_p == NULL)
|
||||
return (NULL);
|
||||
|
||||
_detach(bag_pp, item_p);
|
||||
|
||||
return (obj_p);
|
||||
}
|
||||
|
||||
/*
|
||||
push_bag()
|
||||
|
||||
stuff another item into the bag
|
||||
*/
|
||||
|
||||
void
|
||||
push_bag(linked_list **bag_pp, object *obj_p)
|
||||
{
|
||||
struct linked_list *item_p = NULL;
|
||||
struct linked_list *new_p = NULL;
|
||||
struct linked_list *best_p = NULL;
|
||||
|
||||
new_p = new_list();
|
||||
new_p->data.obj = obj_p; /* attach our object */
|
||||
identifier(obj_p) = get_ident(obj_p); /* tag this object for */
|
||||
/* inventory */
|
||||
/*
|
||||
* Find a place in the bag - try to match the type, then sort by
|
||||
* identifier
|
||||
*/
|
||||
|
||||
for (item_p = *bag_pp; item_p != NULL; item_p = next(item_p))
|
||||
{
|
||||
if ((OBJPTR(item_p))->o_type == obj_p->o_type)
|
||||
{
|
||||
if (best_p == NULL)
|
||||
best_p = item_p;
|
||||
else if (identifier((OBJPTR(item_p))) >
|
||||
identifier((OBJPTR(best_p))) &&
|
||||
identifier((OBJPTR(item_p))) <
|
||||
identifier(obj_p))
|
||||
best_p = item_p;
|
||||
}
|
||||
}
|
||||
|
||||
_attach_after(bag_pp, best_p, new_p); /* stuff it in the list */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
scan_bag()
|
||||
|
||||
Gets the object from the bag that matches the type and id. The object
|
||||
is not removed from the bag.
|
||||
*/
|
||||
|
||||
struct object *
|
||||
scan_bag(linked_list *bag_p, int type, int id)
|
||||
{
|
||||
object *obj_p = NULL;
|
||||
|
||||
for (; bag_p != NULL; bag_p = next(bag_p))
|
||||
{
|
||||
obj_p = OBJPTR(bag_p);
|
||||
|
||||
if (obj_p->o_type == type && identifier(obj_p) == id)
|
||||
break;
|
||||
}
|
||||
|
||||
if (bag_p == NULL)
|
||||
return(NULL);
|
||||
|
||||
return(obj_p);
|
||||
}
|
||||
|
||||
/*
|
||||
baf_decrement_test()
|
||||
|
||||
Assumes the argument is a pointer to int and it just decrements it.
|
||||
Returns TRUE, except when the count goes to zero.
|
||||
*/
|
||||
|
||||
int
|
||||
baf_decrement_test(struct object *obj_p, bag_arg *count_p, int id)
|
||||
{
|
||||
NOOP(obj_p);
|
||||
NOOP(id);
|
||||
|
||||
if (*count_p->iarg > 0)
|
||||
return(TRUE);
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
baf_identify()
|
||||
|
||||
Bag action function to identify an object. This is needed to conform
|
||||
to bag action routine calling conventions and to put the linked list
|
||||
structure on top of the object before calling whatis()
|
||||
*/
|
||||
|
||||
int
|
||||
baf_identify(struct object *obj_p, bag_arg *junk, int id)
|
||||
{
|
||||
linked_list l;
|
||||
linked_list *lp = &l;
|
||||
|
||||
NOOP(junk);
|
||||
NOOP(id);
|
||||
|
||||
lp->data.obj = obj_p; /* stuff object in the right place */
|
||||
whatis(lp);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
baf_increment()
|
||||
|
||||
Assumes the argument is a pointer to int and it just increments it and
|
||||
returns TRUE
|
||||
*/
|
||||
|
||||
int
|
||||
baf_increment(object *obj_p, bag_arg *count_p, int id)
|
||||
{
|
||||
NOOP(obj_p);
|
||||
NOOP(id);
|
||||
|
||||
(*count_p->iarg)++;
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
baf_print_item()
|
||||
Bag action function to print a single item, inventory style.
|
||||
*/
|
||||
|
||||
int
|
||||
baf_print_item(struct object *obj_p, bag_arg *type, int id)
|
||||
{
|
||||
char inv_temp[3 * LINELEN]; /* plenty of space for paranoid programmers */
|
||||
|
||||
if (*type->iarg == 0)
|
||||
sprintf(inv_temp, "%c%c) %s", obj_p->o_type,
|
||||
print_letters[id], inv_name(obj_p, LOWERCASE), FALSE);
|
||||
else
|
||||
sprintf(inv_temp, "%c) %s", print_letters[id],
|
||||
inv_name(obj_p, LOWERCASE), FALSE);
|
||||
|
||||
add_line(inv_temp);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
bff_group()
|
||||
This bag filter function checks to see if two items can be combined by
|
||||
adjusting the count. Grouped items can be combined if the group numbers
|
||||
match. The only other item that is allowed to have a count is food, and
|
||||
there an exact match is required.
|
||||
*/
|
||||
|
||||
int
|
||||
bff_group(struct object *obj_p, bag_arg *arg)
|
||||
{
|
||||
struct object *new_obj_p = arg->obj;
|
||||
|
||||
if (new_obj_p->o_group > 0 && new_obj_p->o_group == obj_p->o_group)
|
||||
return(TRUE);
|
||||
|
||||
if (new_obj_p->o_type == FOOD &&
|
||||
obj_p->o_type == new_obj_p->o_type &&
|
||||
obj_p->o_which == new_obj_p->o_which)
|
||||
return(TRUE);
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
bff_callable
|
||||
Figures out which items can be callable: current rules are:
|
||||
potions, scrolls, staffs, and rings.
|
||||
*/
|
||||
|
||||
int
|
||||
bff_callable(struct object *obj_p, bag_arg *junk)
|
||||
{
|
||||
NOOP(junk);
|
||||
|
||||
if (obj_p->o_type == POTION || obj_p->o_type == RING ||
|
||||
obj_p->o_type == STICK || obj_p->o_type == SCROLL)
|
||||
return(TRUE);
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
bff_markable()
|
||||
Selects which items can be marked. Current rules exclude only gold.
|
||||
*/
|
||||
|
||||
int
|
||||
bff_markable(struct object *obj_p, bag_arg *junk)
|
||||
{
|
||||
NOOP(junk);
|
||||
|
||||
if (obj_p->o_type == GOLD)
|
||||
return(FALSE);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
bffron()
|
||||
returns TRUE if hero is wearing this ring
|
||||
*/
|
||||
|
||||
int
|
||||
bffron(object *obj_p, bag_arg *junk)
|
||||
{
|
||||
NOOP(junk);
|
||||
|
||||
return(cur_ring[LEFT_1] == obj_p || cur_ring[LEFT_2] == obj_p ||
|
||||
cur_ring[LEFT_3] == obj_p || cur_ring[LEFT_4] == obj_p ||
|
||||
cur_ring[LEFT_5] ||
|
||||
cur_ring[RIGHT_1] == obj_p || cur_ring[RIGHT_2] == obj_p ||
|
||||
cur_ring[RIGHT_3] == obj_p || cur_ring[RIGHT_4] == obj_p ||
|
||||
cur_ring[RIGHT_5]);
|
||||
}
|
||||
|
||||
/*
|
||||
bff_zappable()
|
||||
Selects which items can be zapped. This includes both sticks and
|
||||
magically enhanced weapons with lightning ability.
|
||||
*/
|
||||
|
||||
int
|
||||
bff_zappable(struct object *obj_p, bag_arg *junk)
|
||||
{
|
||||
NOOP(junk);
|
||||
|
||||
if (obj_p->o_type == STICK)
|
||||
return(TRUE);
|
||||
|
||||
if (obj_p->o_type == WEAPON && obj_p->o_flags & ISZAPPED)
|
||||
return(TRUE);
|
||||
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
baf_curse()
|
||||
Curse all non-artifact items in the player's pack
|
||||
*/
|
||||
|
||||
int
|
||||
baf_curse(struct object *obj_p, bag_arg *junk, int id)
|
||||
{
|
||||
NOOP(junk);
|
||||
NOOP(id);
|
||||
|
||||
if (obj_p->o_type != ARTIFACT && rnd(8) == 0)
|
||||
{
|
||||
obj_p->o_flags |= ISCURSED;
|
||||
obj_p->o_flags &= ~ISBLESSED;
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
bafcweapon()
|
||||
bag action routine to fetch the current weapon
|
||||
*/
|
||||
|
||||
int
|
||||
bafcweapon(struct object *obj_p, bag_arg *junk, int id)
|
||||
{
|
||||
NOOP(junk);
|
||||
NOOP(id);
|
||||
|
||||
if (obj_p == cur_weapon)
|
||||
return(FALSE); /* found what we wanted - stop and return it */
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
bafcarmor()
|
||||
bag action routine to fetch the current armor
|
||||
*/
|
||||
|
||||
int
|
||||
bafcarmor(struct object *obj_p, bag_arg *junk, int id)
|
||||
{
|
||||
NOOP(junk);
|
||||
NOOP(id);
|
||||
|
||||
if (obj_p == cur_armor)
|
||||
return(FALSE); /* found what we wanted - stop and return it */
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
1326
urogue/chase.c
Normal file
1326
urogue/chase.c
Normal file
File diff suppressed because it is too large
Load diff
1383
urogue/command.c
Normal file
1383
urogue/command.c
Normal file
File diff suppressed because it is too large
Load diff
327
urogue/daemon.c
Normal file
327
urogue/daemon.c
Normal file
|
|
@ -0,0 +1,327 @@
|
|||
/*
|
||||
daemon.c - functions for dealing with things that happen in the future
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
Based on "Advanced Rogue"
|
||||
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
|
||||
All rights reserved.
|
||||
|
||||
Based on "Rogue: Exploring the Dungeons of Doom"
|
||||
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
/*
|
||||
Needs to be rewritten again to work on a per creature basis.
|
||||
Either each monster will have a list of effect, or each
|
||||
fuse will take a creature pointer and multiple entries
|
||||
for each fuse will be allowed. I tend to want to attach
|
||||
the effects to the creature.
|
||||
*/
|
||||
|
||||
#include "rogue.h"
|
||||
|
||||
int demoncnt;
|
||||
|
||||
struct daemon daemons[DAEMON_MAX] =
|
||||
{
|
||||
{ DAEMON_NULL, NULL },
|
||||
{ DAEMON_DOCTOR, doctor },
|
||||
{ DAEMON_ROLLWAND, rollwand },
|
||||
{ DAEMON_STOMACH, stomach },
|
||||
{ DAEMON_RUNNERS, runners }
|
||||
};
|
||||
|
||||
struct fuse fuses[FUSE_MAX] =
|
||||
{
|
||||
{ FUSE_NULL, NULL },
|
||||
{ FUSE_SWANDER, swander },
|
||||
{ FUSE_UNCONFUSE, unconfuse },
|
||||
{ FUSE_UNSCENT, unscent },
|
||||
{ FUSE_SCENT, scent },
|
||||
{ FUSE_UNHEAR, unhear },
|
||||
{ FUSE_HEAR, hear },
|
||||
{ FUSE_UNSEE, unsee },
|
||||
{ FUSE_UNSTINK, unstink },
|
||||
{ FUSE_UNCLRHEAD, unclrhead },
|
||||
{ FUSE_UNPHASE, unphase },
|
||||
{ FUSE_SIGHT, sight },
|
||||
{ FUSE_RES_STRENGTH, res_strength },
|
||||
{ FUSE_NOHASTE, nohaste },
|
||||
{ FUSE_NOSLOW, noslow },
|
||||
{ FUSE_SUFFOCATE, suffocate },
|
||||
{ FUSE_CURE_DISEASE, cure_disease },
|
||||
{ FUSE_UNITCH, un_itch },
|
||||
{ FUSE_APPEAR, appear },
|
||||
{ FUSE_UNELECTRIFY, unelectrify },
|
||||
{ FUSE_UNBHERO, unbhero },
|
||||
{ FUSE_UNSHERO, unshero },
|
||||
{ FUSE_UNXRAY, NULL },
|
||||
{ FUSE_UNDISGUISE, undisguise },
|
||||
{ FUSE_SHERO, shero },
|
||||
{ FUSE_WGHTCHK, wghtchk },
|
||||
{ FUSE_UNSUMMON, unsummon },
|
||||
{ FUSE_UNGAZE, ungaze },
|
||||
{ FUSE_UNCOLD, uncold },
|
||||
{ FUSE_UNHOT, unhot },
|
||||
{ FUSE_UNFLY, unfly },
|
||||
{ FUSE_UNBREATHE, unbreathe },
|
||||
{ FUSE_UNREGEN, unregen },
|
||||
{ FUSE_UNSUPEREAT, unsupereat },
|
||||
{ FUSE_UNSHIELD, unshield },
|
||||
{ FUSE_UNMSHIELD, unmshield },
|
||||
{ FUSE_UNTRUESEE, untruesee }
|
||||
};
|
||||
|
||||
/*
|
||||
d_slot()
|
||||
Find an empty slot in the daemon/fuse list
|
||||
*/
|
||||
|
||||
struct delayed_action *
|
||||
d_slot(void)
|
||||
{
|
||||
int i;
|
||||
struct delayed_action *dev;
|
||||
|
||||
for (i = 0, dev = d_list; i < MAXDAEMONS; i++, dev++)
|
||||
if (dev->d_type == EMPTY)
|
||||
return(dev);
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
find_slot()
|
||||
Find a particular slot in the table
|
||||
*/
|
||||
|
||||
struct delayed_action *
|
||||
find_slot(int type, int id)
|
||||
{
|
||||
int i;
|
||||
struct delayed_action *dev;
|
||||
|
||||
for (i = 0, dev = d_list; i < MAXDAEMONS; i++, dev++)
|
||||
if ( (dev->d_type == type) && (id == dev->d_id) )
|
||||
return(dev);
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
daemon()
|
||||
Start a daemon, takes a function.
|
||||
*/
|
||||
|
||||
void
|
||||
start_daemon(int id, void *arg, int whendo)
|
||||
{
|
||||
struct delayed_action *dev;
|
||||
|
||||
dev = d_slot();
|
||||
|
||||
if (dev != NULL)
|
||||
{
|
||||
dev->d_type = DAEMON;
|
||||
dev->d_when = whendo;
|
||||
dev->d_id = id;
|
||||
dev->d_arg = arg;
|
||||
dev->d_time = 1;
|
||||
demoncnt += 1; /* update count */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
kill_daemon()
|
||||
Remove a daemon from the list
|
||||
*/
|
||||
|
||||
void
|
||||
kill_daemon(int id)
|
||||
{
|
||||
struct delayed_action *dev;
|
||||
|
||||
if ((dev = find_slot(DAEMON, id)) == NULL)
|
||||
return;
|
||||
|
||||
/* Take it out of the list */
|
||||
|
||||
dev->d_type = EMPTY;
|
||||
demoncnt -= 1; /* update count */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
do_daemons()
|
||||
Run all the daemons that are active with the current flag,
|
||||
passing the argument to the function.
|
||||
*/
|
||||
|
||||
void
|
||||
do_daemons(int now)
|
||||
{
|
||||
struct delayed_action *dev;
|
||||
|
||||
/* Loop through the devil list */
|
||||
|
||||
for (dev = d_list; dev < &d_list[MAXDAEMONS]; dev++)
|
||||
/* Executing each one, giving it the proper arguments */
|
||||
if ( (dev->d_when == now) && (dev->d_type == DAEMON))
|
||||
{
|
||||
if ((dev->d_id < 1) || (dev->d_id >= DAEMON_MAX))
|
||||
printf("Bad daemon id %d\n", dev->d_id);
|
||||
else if (daemons[dev->d_id].func == NULL)
|
||||
printf("No action for daemon %d!!!\n", dev->d_id);
|
||||
else
|
||||
{
|
||||
daemon_arg arg;
|
||||
|
||||
arg.varg = dev->d_arg;
|
||||
daemons[dev->d_id].func(&arg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
fuse()
|
||||
Start a fuse to go off in a certain number of turns
|
||||
*/
|
||||
|
||||
void
|
||||
light_fuse(int id, void *arg, int time, int whendo)
|
||||
{
|
||||
struct delayed_action *wire;
|
||||
|
||||
wire = d_slot();
|
||||
|
||||
if (wire != NULL)
|
||||
{
|
||||
wire->d_type = FUSE;
|
||||
wire->d_when = whendo;
|
||||
wire->d_id = id;
|
||||
wire->d_arg = arg;
|
||||
wire->d_time = time;
|
||||
demoncnt += 1; /* update count */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
lengthen()
|
||||
Increase the time until a fuse goes off
|
||||
*/
|
||||
|
||||
void
|
||||
lengthen_fuse(int id, int xtime)
|
||||
{
|
||||
struct delayed_action *wire;
|
||||
|
||||
if ((wire = find_slot(FUSE,id)) == NULL)
|
||||
return;
|
||||
|
||||
wire->d_time += xtime;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
extinguish()
|
||||
Put out a fuse
|
||||
*/
|
||||
|
||||
void
|
||||
extinguish_fuse(int id)
|
||||
{
|
||||
struct delayed_action *wire;
|
||||
|
||||
if ((wire = find_slot(FUSE,id)) == NULL)
|
||||
return;
|
||||
|
||||
wire->d_type = EMPTY;
|
||||
demoncnt -= 1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
do_fuses()
|
||||
Decrement counters and start needed fuses
|
||||
*/
|
||||
|
||||
void
|
||||
do_fuses(int now)
|
||||
{
|
||||
struct delayed_action *wire;
|
||||
|
||||
/* Step though the list */
|
||||
|
||||
for (wire = d_list; wire < &d_list[MAXDAEMONS]; wire++)
|
||||
{
|
||||
/*
|
||||
* Decrementing counters and starting things we want. We
|
||||
* also need to remove the fuse from the list once it has
|
||||
* gone off.
|
||||
*/
|
||||
|
||||
if( (wire->d_type == FUSE) && (wire->d_when == now) )
|
||||
{
|
||||
if (--wire->d_time <= 0)
|
||||
{
|
||||
fuse_arg arg;
|
||||
|
||||
arg.varg = wire->d_arg;
|
||||
wire->d_type = EMPTY;
|
||||
fuses[wire->d_id].func(&arg);
|
||||
demoncnt -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
activity()
|
||||
Show wizard number of demaons and memory blocks used
|
||||
*/
|
||||
|
||||
void
|
||||
activity(void)
|
||||
{
|
||||
msg("Daemons = %d : Memory Items = %d ", demoncnt, total);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
waste_time()
|
||||
Do nothing but let other things happen
|
||||
*/
|
||||
|
||||
void
|
||||
waste_time(void)
|
||||
{
|
||||
if (inwhgt) /* if from wghtchk then done */
|
||||
return;
|
||||
|
||||
do_daemons(BEFORE);
|
||||
do_fuses(BEFORE);
|
||||
do_daemons(AFTER);
|
||||
do_fuses(AFTER);
|
||||
}
|
||||
999
urogue/daemons.c
Normal file
999
urogue/daemons.c
Normal file
|
|
@ -0,0 +1,999 @@
|
|||
/*
|
||||
daemons.c - All the daemon and fuse functions are in here
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
Based on "Advanced Rogue"
|
||||
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
|
||||
All rights reserved.
|
||||
|
||||
Based on "Rogue: Exploring the Dungeons of Doom"
|
||||
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
doctor()
|
||||
A healing daemon that restors spell and hit points after rest
|
||||
*/
|
||||
|
||||
void
|
||||
doctor(daemon_arg *who)
|
||||
{
|
||||
struct thing *tp = who->thingptr;
|
||||
long ohp; /* turn off ISFLEE? */
|
||||
struct stats *curp; /* current stats pointer */
|
||||
struct stats *maxp; /* max stats pointer */
|
||||
int turns_quiet, new_points;
|
||||
|
||||
curp = &(tp->t_stats);
|
||||
maxp = &(tp->maxstats);
|
||||
|
||||
if (on(*tp, ISINWALL))
|
||||
{
|
||||
tp->t_rest_hpt = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check for regenerating spell points first */
|
||||
|
||||
doctor_spell_points(tp);
|
||||
|
||||
if (curp->s_hpt == maxp->s_hpt)
|
||||
{
|
||||
tp->t_rest_hpt = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
tp->t_rest_hpt++;
|
||||
|
||||
switch (tp->t_ctype)
|
||||
{
|
||||
case C_MAGICIAN:
|
||||
case C_ILLUSION:
|
||||
turns_quiet = 24 - curp->s_lvl;
|
||||
new_points = curp->s_lvl / 2 - 4;
|
||||
break;
|
||||
|
||||
case C_THIEF:
|
||||
case C_ASSASIN:
|
||||
case C_NINJA:
|
||||
turns_quiet = 16 - curp->s_lvl;
|
||||
new_points = curp->s_lvl / 2 - 1;
|
||||
break;
|
||||
|
||||
case C_CLERIC:
|
||||
case C_DRUID:
|
||||
turns_quiet = 16 - curp->s_lvl;
|
||||
new_points = curp->s_lvl / 2 - 2;
|
||||
break;
|
||||
|
||||
case C_FIGHTER:
|
||||
case C_RANGER:
|
||||
case C_PALADIN:
|
||||
turns_quiet = 8 - curp->s_lvl / 2;
|
||||
new_points = curp->s_lvl / 2 - 1;
|
||||
break;
|
||||
|
||||
case C_MONSTER:
|
||||
turns_quiet = 16 - curp->s_lvl;
|
||||
new_points = curp->s_lvl / 2 - 6;
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("What a strange character you are!");
|
||||
return;
|
||||
}
|
||||
|
||||
ohp = curp->s_hpt;
|
||||
|
||||
if (off(*tp, HASDISEASE))
|
||||
{
|
||||
if (curp->s_lvl < 8)
|
||||
{
|
||||
if (tp->t_rest_hpt > turns_quiet)
|
||||
curp->s_hpt++;
|
||||
}
|
||||
else if (tp->t_rest_hpt >= 15)
|
||||
curp->s_hpt += rnd(new_points) + 1;
|
||||
}
|
||||
|
||||
if (tp == &player)
|
||||
{
|
||||
if (curp->s_lvl > 10)
|
||||
turns_quiet = 2;
|
||||
else
|
||||
turns_quiet = rnd(turns_quiet / 6) + 1;
|
||||
|
||||
if (is_wearing(R_REGEN))
|
||||
curp->s_hpt += ring_value(R_REGEN);
|
||||
}
|
||||
|
||||
if (on(*tp, ISREGEN))
|
||||
curp->s_hpt += curp->s_lvl / 5 + 1;
|
||||
|
||||
if (ohp != curp->s_hpt)
|
||||
{
|
||||
if (curp->s_hpt >= maxp->s_hpt)
|
||||
{
|
||||
curp->s_hpt = maxp->s_hpt;
|
||||
|
||||
if (off(*tp, WASTURNED) && on(*tp, ISFLEE)
|
||||
&& tp != &player)
|
||||
{
|
||||
turn_off(*tp, ISFLEE);
|
||||
tp->t_oldpos = tp->t_pos;
|
||||
/* Start our trek over */
|
||||
}
|
||||
}
|
||||
tp->t_rest_hpt = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
doctor_spell_points()
|
||||
A healing daemon that restors spell points
|
||||
*/
|
||||
|
||||
void
|
||||
doctor_spell_points(struct thing *tp)
|
||||
{
|
||||
int turns_quiet, new_points;
|
||||
struct stats *curp; /* current stats pointer */
|
||||
struct stats *maxp; /* max stats pointer */
|
||||
int opower; /* current power */
|
||||
|
||||
curp = &(tp->t_stats);
|
||||
maxp = &(tp->maxstats);
|
||||
opower = curp->s_power;
|
||||
|
||||
/* The right ring will let you regenerate while wearing bad armor */
|
||||
|
||||
if (off(*tp, CANCAST) ||
|
||||
((tp == &player) &&
|
||||
(cur_armor && wear_ok(tp, cur_armor, NOMESSAGE) == FALSE) &&
|
||||
!(is_wearing(R_WIZARD) || is_wearing(R_PIETY))))
|
||||
{
|
||||
tp->t_rest_pow = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
tp->t_rest_pow++;
|
||||
|
||||
switch (tp->t_ctype)
|
||||
{
|
||||
case C_MAGICIAN:
|
||||
case C_ILLUSION:
|
||||
turns_quiet = 18 - curp->s_lvl / 2;
|
||||
new_points = curp->s_lvl / 2;
|
||||
break;
|
||||
case C_CLERIC:
|
||||
case C_DRUID:
|
||||
turns_quiet = 24 - curp->s_lvl;
|
||||
new_points = curp->s_lvl / 2 - 2;
|
||||
break;
|
||||
case C_THIEF:
|
||||
case C_ASSASIN:
|
||||
case C_NINJA:
|
||||
turns_quiet = 32 - curp->s_lvl;
|
||||
new_points = curp->s_lvl / 3 - 3;
|
||||
break;
|
||||
case C_FIGHTER:
|
||||
case C_RANGER:
|
||||
case C_PALADIN:
|
||||
turns_quiet = 32 - curp->s_lvl;
|
||||
new_points = curp->s_lvl / 3 - 4;
|
||||
break;
|
||||
case C_MONSTER:
|
||||
turns_quiet = 24 - curp->s_lvl;
|
||||
new_points = curp->s_lvl - 6;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (curp->s_lvl < 8)
|
||||
{
|
||||
if (tp->t_rest_pow > turns_quiet)
|
||||
curp->s_power++;
|
||||
}
|
||||
else if (tp->t_rest_pow >= 15)
|
||||
curp->s_power += rnd(new_points) + 1;
|
||||
|
||||
if (tp == &player && (is_wearing(R_WIZARD) || is_wearing(R_PIETY)))
|
||||
curp->s_power += ring_value(R_WIZARD) + ring_value(R_PIETY);
|
||||
|
||||
curp->s_power = min(max(0, curp->s_power), maxp->s_power);
|
||||
|
||||
if (curp->s_power != opower)
|
||||
tp->t_rest_pow = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
rollwand()
|
||||
called to roll to see if a wandering monster starts up
|
||||
*/
|
||||
|
||||
daemon
|
||||
rollwand(daemon_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
if ((rnd(6) == 0) && (player.t_ctype != C_THIEF ||
|
||||
(rnd(30) >= pstats.s_dext)))
|
||||
{
|
||||
wanderer();
|
||||
kill_daemon(DAEMON_ROLLWAND);
|
||||
light_fuse(FUSE_SWANDER, 0, WANDERTIME, BEFORE);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
stomach()
|
||||
digest the hero's food
|
||||
*/
|
||||
|
||||
daemon
|
||||
stomach(daemon_arg *arg)
|
||||
{
|
||||
int oldfood, old_hunger;
|
||||
int amount;
|
||||
int power_scale;
|
||||
|
||||
NOOP(arg);
|
||||
|
||||
old_hunger = hungry_state;
|
||||
|
||||
if (food_left <= 0)
|
||||
{
|
||||
/* the hero is fainting */
|
||||
|
||||
if (no_command || rnd(100) > 20)
|
||||
return;
|
||||
|
||||
no_command = rnd(8) + 4;
|
||||
running = FALSE;
|
||||
count = 0;
|
||||
hungry_state = F_FAINT;
|
||||
feed_me(hungry_state);
|
||||
}
|
||||
else
|
||||
{
|
||||
oldfood = food_left;
|
||||
|
||||
amount = ring_eat(LEFT_1) + ring_eat(LEFT_2) +
|
||||
ring_eat(LEFT_3) + ring_eat(LEFT_4) +
|
||||
ring_eat(RIGHT_1) + ring_eat(RIGHT_2) +
|
||||
ring_eat(RIGHT_3) + ring_eat(RIGHT_4) +
|
||||
foodlev;
|
||||
|
||||
if (on(player, SUPEREAT)) /* artifact or regeneration munchies */
|
||||
amount *= 2;
|
||||
|
||||
if (on(player, POWEREAT)) /* Used an artifact power */
|
||||
{
|
||||
amount += 40;
|
||||
turn_off(player, POWEREAT);
|
||||
}
|
||||
|
||||
power_scale = (on(player, POWERDEXT) + on(player, POWERSTR) +
|
||||
on(player, POWERWISDOM) + on(player, POWERINTEL) +
|
||||
on(player, POWERCONST) + 1);
|
||||
|
||||
food_left -= amount * power_scale;
|
||||
|
||||
if (food_left < MORETIME && oldfood >= MORETIME)
|
||||
{
|
||||
hungry_state = F_WEAK;
|
||||
running = FALSE;
|
||||
feed_me(hungry_state);
|
||||
}
|
||||
else if (food_left < 2 * MORETIME && oldfood >= 2 * MORETIME)
|
||||
{
|
||||
hungry_state = F_HUNGRY;
|
||||
running = FALSE;
|
||||
feed_me(hungry_state);
|
||||
}
|
||||
}
|
||||
|
||||
if (old_hunger != hungry_state)
|
||||
updpack();
|
||||
|
||||
wghtchk(NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
runners()
|
||||
Make all the running monsters move. with monsters now fighting
|
||||
each other, this routine have been enhanced and may need more work yet
|
||||
*/
|
||||
|
||||
daemon
|
||||
runners(daemon_arg *arg)
|
||||
{
|
||||
struct linked_list *item;
|
||||
struct thing *tp;
|
||||
|
||||
NOOP(arg);
|
||||
|
||||
for (item = mlist; item != NULL; item = next_mons)
|
||||
{
|
||||
curr_mons = item;
|
||||
next_mons = next(curr_mons);
|
||||
tp = THINGPTR(item);
|
||||
|
||||
if (on(*tp, ISHELD) && rnd(tp->t_stats.s_str +
|
||||
tp->t_stats.s_lvl) > 10 + rnd(50))
|
||||
{
|
||||
turn_off(*tp, ISHELD);
|
||||
turn_off(*tp, ISDISGUISE);
|
||||
turn_on(*tp, ISRUN);
|
||||
tp->t_ischasing = TRUE;
|
||||
tp->t_chasee = &player;
|
||||
tp->t_horde = NULL;
|
||||
|
||||
if (tp->t_stats.s_hpt < rnd(tp->maxstats.s_hpt))
|
||||
turn_on(*tp, ISFLEE);
|
||||
|
||||
if (cansee(tp->t_pos.y, tp->t_pos.x))
|
||||
msg("The %s breaks free!", monsters[tp->t_index].m_name);
|
||||
}
|
||||
|
||||
if (off(*tp, ISHELD) && on(*tp, ISRUN))
|
||||
{
|
||||
int flee = FALSE;
|
||||
|
||||
flee = on(*tp, ISFLEE) ||
|
||||
( (tp->t_chasee == &player) &&
|
||||
on(player, ISINWALL) &&
|
||||
off(*tp, CANINWALL) && off(*tp, ISFAMILIAR) );
|
||||
|
||||
if (off(*tp, ISSLOW) || tp->t_turn)
|
||||
{
|
||||
daemon_arg targ;
|
||||
|
||||
targ.thingptr = tp;
|
||||
doctor(&targ);
|
||||
do_chase(tp, flee);
|
||||
}
|
||||
|
||||
if (curr_mons && (on(*tp, ISHASTE) ||
|
||||
((on(*tp, CANFLY) || on(*tp, ISFAST)) &&
|
||||
DISTANCE(hero, tp->t_pos) >= 4)))
|
||||
{
|
||||
daemon_arg targ;
|
||||
|
||||
targ.thingptr = tp;
|
||||
doctor(&targ);
|
||||
do_chase(tp, flee);
|
||||
}
|
||||
|
||||
if (curr_mons)
|
||||
{
|
||||
tp->t_turn ^= TRUE;
|
||||
tp->t_wasshot ^= FALSE; /* Not shot anymore */
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
curr_mons = next_mons = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
swander()
|
||||
called when it is time to start rolling for wandering monsters
|
||||
*/
|
||||
|
||||
fuse
|
||||
swander(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
start_daemon(DAEMON_ROLLWAND, 0, BEFORE);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
unconfuse
|
||||
release the poor player from his confusion
|
||||
*/
|
||||
|
||||
fuse
|
||||
unconfuse(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
turn_off(player, ISHUH);
|
||||
msg("You feel less confused now.");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
unscent()
|
||||
turn of extra smelling ability
|
||||
*/
|
||||
|
||||
fuse
|
||||
unscent(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
turn_off(player, CANSCENT);
|
||||
msg("The smell of monsters goes away.");
|
||||
}
|
||||
|
||||
/*
|
||||
scent
|
||||
give back the players sense of smell
|
||||
*/
|
||||
|
||||
fuse
|
||||
scent(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
turn_off(player, ISUNSMELL);
|
||||
msg("You begin to smell the damp dungeon air again.");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
unhear
|
||||
player doesn't have extra hearing any more
|
||||
*/
|
||||
|
||||
fuse
|
||||
unhear(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
turn_off(player, CANHEAR);
|
||||
msg("The sounds of monsters fades away.");
|
||||
}
|
||||
|
||||
/*
|
||||
hear()
|
||||
return the players sense of hearing
|
||||
*/
|
||||
|
||||
fuse
|
||||
hear(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
turn_off(player, ISDEAF);
|
||||
msg("You can hear again.");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
unsee
|
||||
He lost his see invisible power
|
||||
|
||||
Need to make monsters invisible again? This
|
||||
was done in Rogue 5.2
|
||||
|
||||
for (th = mlist; th != NULL; th = next(th))
|
||||
if (on(*th, ISINVIS) && see_monst(th))
|
||||
{
|
||||
move(th->t_pos.y, th->t_pos.x);
|
||||
addch(th->t_oldch);
|
||||
}
|
||||
*/
|
||||
|
||||
fuse
|
||||
unsee(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
if (!is_wearing(R_SEEINVIS))
|
||||
{
|
||||
turn_off(player, CANSEE);
|
||||
msg("The tingling feeling leaves your eyes.");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
unstink()
|
||||
Remove to-hit handicap from player
|
||||
*/
|
||||
|
||||
fuse
|
||||
unstink(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
turn_off(player, HASSTINK);
|
||||
}
|
||||
|
||||
/*
|
||||
unclrhead
|
||||
Player is no longer immune to confusion
|
||||
*/
|
||||
|
||||
fuse
|
||||
unclrhead(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
turn_off(player, ISCLEAR);
|
||||
msg("The blue aura about your head fades away.");
|
||||
}
|
||||
|
||||
/*
|
||||
unphase()
|
||||
Player can no longer walk through walls
|
||||
*/
|
||||
|
||||
fuse
|
||||
unphase(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
turn_off(player, CANINWALL);
|
||||
|
||||
msg("Your dizzy feeling leaves you.");
|
||||
|
||||
if (!step_ok(hero.y, hero.x, NOMONST, &player))
|
||||
death(D_PETRIFY);
|
||||
}
|
||||
|
||||
/*
|
||||
sight()
|
||||
He gets his sight back
|
||||
*/
|
||||
|
||||
fuse
|
||||
sight(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
if (on(player, ISBLIND))
|
||||
{
|
||||
extinguish_fuse(FUSE_SIGHT);
|
||||
turn_off(player, ISBLIND);
|
||||
light(&hero);
|
||||
msg("The veil of darkness lifts.");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
res_strength()
|
||||
Restore player's strength
|
||||
*/
|
||||
|
||||
fuse
|
||||
res_strength(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
if (lost_str)
|
||||
{
|
||||
chg_str(lost_str, FALSE, FALSE);
|
||||
lost_str = 0;
|
||||
}
|
||||
else
|
||||
pstats.s_str = max_stats.s_str + ring_value(R_ADDSTR) +
|
||||
(on(player, POWERSTR) ? 10 : 0) +
|
||||
(on(player, SUPERHERO) ? 10 : 0);
|
||||
|
||||
updpack();
|
||||
}
|
||||
|
||||
/*
|
||||
nohaste()
|
||||
End the hasting
|
||||
*/
|
||||
|
||||
fuse
|
||||
nohaste(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
turn_off(player, ISHASTE);
|
||||
msg("You feel yourself slowing down.");
|
||||
}
|
||||
|
||||
/*
|
||||
noslow()
|
||||
End the slowing
|
||||
*/
|
||||
|
||||
fuse
|
||||
noslow(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
turn_off(player, ISSLOW);
|
||||
msg("You feel yourself speeding up.");
|
||||
}
|
||||
|
||||
/*
|
||||
suffocate()
|
||||
If this gets called, the player has suffocated
|
||||
*/
|
||||
|
||||
fuse
|
||||
suffocate(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
death(D_SUFFOCATION);
|
||||
}
|
||||
|
||||
/*
|
||||
cure_disease()
|
||||
daemon for curing the diseased
|
||||
*/
|
||||
|
||||
fuse
|
||||
cure_disease(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
turn_off(player, HASDISEASE);
|
||||
|
||||
if (off(player, HASINFEST))
|
||||
msg("You begin to feel yourself improving again.");
|
||||
}
|
||||
|
||||
/*
|
||||
un_itch()
|
||||
daemon for adding back dexterity
|
||||
*/
|
||||
|
||||
fuse
|
||||
un_itch(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
if (lost_dext)
|
||||
{
|
||||
chg_dext(lost_dext, FALSE, FALSE);
|
||||
lost_dext = 0;
|
||||
turn_off(player, HASITCH);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
appear()
|
||||
Become visible again
|
||||
*/
|
||||
|
||||
fuse
|
||||
appear(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
turn_off(player, ISINVIS);
|
||||
PLAYER = VPLAYER;
|
||||
msg("The tingling feeling leaves your body.");
|
||||
light(&hero);
|
||||
}
|
||||
|
||||
/*
|
||||
unelectrify()
|
||||
stop shooting off sparks
|
||||
*/
|
||||
|
||||
fuse
|
||||
unelectrify(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
turn_off(player, ISELECTRIC);
|
||||
msg("The sparks and violet glow from your body fade away.");
|
||||
light(&hero);
|
||||
}
|
||||
|
||||
/*
|
||||
unshero()
|
||||
super heroism wears off, now do nasty effects
|
||||
*/
|
||||
|
||||
fuse
|
||||
unshero(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
msg("Your feeling of invulnerability goes away.");
|
||||
turn_off(player, SUPERHERO);
|
||||
chg_str(-11, FALSE, FALSE);
|
||||
chg_dext(-6, FALSE, FALSE);
|
||||
food_left -= HEROTIME + rnd(HEROTIME);
|
||||
no_command += 5 + rnd(5);
|
||||
msg("You fall asleep.");
|
||||
}
|
||||
|
||||
/*
|
||||
unbhero()
|
||||
blessed super heroism wears off, no bad effects
|
||||
*/
|
||||
|
||||
fuse
|
||||
unbhero(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
msg("Your feeling of invincibility goes away.");
|
||||
turn_off(player, SUPERHERO);
|
||||
chg_str(-10, FALSE, FALSE);
|
||||
chg_dext(-5, FALSE, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
undisguise()
|
||||
player stops looking like a monster
|
||||
*/
|
||||
|
||||
fuse
|
||||
undisguise(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
msg("Your skin feels itchy for a moment.");
|
||||
turn_off(player, ISDISGUISE);
|
||||
PLAYER = VPLAYER;
|
||||
light(&hero);
|
||||
}
|
||||
|
||||
/*
|
||||
unsummon()
|
||||
Unsummon a monster
|
||||
*/
|
||||
|
||||
void
|
||||
unsummon(fuse_arg *monny)
|
||||
{
|
||||
struct linked_list *monst = monny->ll;
|
||||
struct linked_list *sum_monst = (struct linked_list *) monst;
|
||||
struct thing *tp = THINGPTR(sum_monst);
|
||||
char *mname = monsters[tp->t_index].m_name;
|
||||
|
||||
turn_off(*tp, WASSUMMONED);
|
||||
turn_off(player, HASSUMMONED);
|
||||
msg("Goodbye, master.");
|
||||
msg("The summoned %s phases out of existence", mname);
|
||||
killed(NULL, sum_monst, NOMESSAGE, NOPOINTS);
|
||||
mons_summoned--;
|
||||
}
|
||||
|
||||
/*
|
||||
ungaze()
|
||||
Turn off gaze reflection
|
||||
*/
|
||||
|
||||
fuse
|
||||
ungaze(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
msg("The shiny particles swirl to the floor.");
|
||||
turn_off(player, CANREFLECT);
|
||||
}
|
||||
|
||||
/*
|
||||
shero()
|
||||
restore lost abilities from cursed potion of shero
|
||||
*/
|
||||
|
||||
fuse
|
||||
shero(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
msg("You feel normal again.");
|
||||
chg_str(2, FALSE, TRUE);
|
||||
chg_dext(2, FALSE, TRUE);
|
||||
turn_off(player, ISUNHERO);
|
||||
}
|
||||
|
||||
/*
|
||||
wghtchk()
|
||||
check that the pack weight is OK
|
||||
*/
|
||||
|
||||
fuse
|
||||
wghtchk(fuse_arg *arg)
|
||||
{
|
||||
int dropchk, err = TRUE;
|
||||
char ch;
|
||||
|
||||
NOOP(arg);
|
||||
|
||||
inwhgt = TRUE;
|
||||
|
||||
if (pstats.s_pack > pstats.s_carry)
|
||||
{
|
||||
ch = CCHAR( mvwinch(stdscr, hero.y, hero.x) );
|
||||
|
||||
if ((ch != FLOOR && ch != PASSAGE))
|
||||
{
|
||||
extinguish_fuse(FUSE_WGHTCHK);
|
||||
light_fuse(FUSE_WGHTCHK, (void *)TRUE, 1, AFTER);
|
||||
inwhgt = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
extinguish_fuse(FUSE_WGHTCHK);
|
||||
msg("Your pack is too heavy for you.");
|
||||
|
||||
do
|
||||
{
|
||||
dropchk = drop(NULL);
|
||||
|
||||
if (dropchk == FALSE)
|
||||
{
|
||||
mpos = 0;
|
||||
msg("You must drop something.");
|
||||
}
|
||||
|
||||
if (dropchk == TRUE)
|
||||
err = FALSE;
|
||||
|
||||
}
|
||||
while (err);
|
||||
|
||||
}
|
||||
|
||||
inwhgt = FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
uncold()
|
||||
He lost his cold resistance power
|
||||
*/
|
||||
|
||||
fuse
|
||||
uncold(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
turn_off(player, NOCOLD);
|
||||
|
||||
if (!is_wearing(R_COLDRESIST))
|
||||
msg("You feel a slight chill in the air.");
|
||||
}
|
||||
|
||||
/*
|
||||
unhot()
|
||||
He lost his fire resistance power
|
||||
*/
|
||||
|
||||
fuse
|
||||
unhot(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
turn_off(player, NOFIRE);
|
||||
|
||||
if (!is_wearing(R_FIRERESIST))
|
||||
msg("You feel a flush of warmth.");
|
||||
}
|
||||
|
||||
/*
|
||||
unfly()
|
||||
He stopped flying
|
||||
*/
|
||||
|
||||
fuse
|
||||
unfly(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
turn_off(player, CANFLY);
|
||||
|
||||
if (!is_wearing(R_LEVITATION))
|
||||
msg("You float gently to the ground.");
|
||||
}
|
||||
|
||||
/*
|
||||
unbreathe()
|
||||
He started needing oxygen
|
||||
*/
|
||||
|
||||
fuse
|
||||
unbreathe(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
turn_off(player, HASOXYGEN);
|
||||
|
||||
if (!is_wearing(R_BREATHE))
|
||||
msg("You start huffing and puffing.");
|
||||
}
|
||||
|
||||
/*
|
||||
unregen()
|
||||
He stops being regenerative
|
||||
*/
|
||||
|
||||
fuse
|
||||
unregen(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
turn_off(player, ISREGEN);
|
||||
|
||||
if (!is_wearing(R_REGEN))
|
||||
msg("Your metabolism slows down.");
|
||||
}
|
||||
|
||||
/*
|
||||
unsupereat()
|
||||
He stops being excessively hungry
|
||||
*/
|
||||
|
||||
fuse
|
||||
unsupereat(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
turn_off(player, SUPEREAT);
|
||||
msg("You stop feeling so hungry.");
|
||||
}
|
||||
|
||||
/*
|
||||
unshield()
|
||||
He stops having his AC helped by magic
|
||||
*/
|
||||
|
||||
fuse
|
||||
unshield(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
turn_off(player, HASSHIELD);
|
||||
pstats.s_arm -= pstats.s_acmod;
|
||||
pstats.s_acmod = 0;
|
||||
msg("Your skin feels normal.");
|
||||
}
|
||||
|
||||
/*
|
||||
unmshield()
|
||||
He stops ignoring thrown weapons
|
||||
*/
|
||||
|
||||
fuse
|
||||
unmshield(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
turn_off(player, HASMSHIELD);
|
||||
msg("The fog dissapates.");
|
||||
}
|
||||
|
||||
/*
|
||||
untrue()
|
||||
He lost his true sight power
|
||||
*/
|
||||
|
||||
void
|
||||
untruesee(fuse_arg *arg)
|
||||
{
|
||||
NOOP(arg);
|
||||
|
||||
if (!is_wearing(R_TRUESEE))
|
||||
{
|
||||
turn_off(player, CANTRUESEE);
|
||||
msg("Your sensory perceptions return to normal.");
|
||||
}
|
||||
}
|
||||
1160
urogue/dict.c
Normal file
1160
urogue/dict.c
Normal file
File diff suppressed because it is too large
Load diff
216
urogue/dict.h
Normal file
216
urogue/dict.h
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
dict.h
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
/*-----------------
|
||||
Change history:
|
||||
(AK:04/03/95) - Added hook for extensions to dictionary structure.
|
||||
(AK:04/04/95) - Added dictionary signature, table of contents and parameter
|
||||
structure defintions and fields in DICTIONARY structure
|
||||
-------------------*/
|
||||
|
||||
#ifndef dict_h_included
|
||||
#define dict_h_included
|
||||
|
||||
static char dict_sccsid[] = "%W% %G%";
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#define DICT_NONE 0x00000000 /* no flags set */
|
||||
#define DICT_VALIDATE 0xdeadbeef /* look for this in every dictionary structure */
|
||||
#define DICT_ENTRY_NONE -1 /* index of invalid entry */
|
||||
|
||||
typedef unsigned char BOOLEANC;
|
||||
|
||||
/*------------------
|
||||
string table entry
|
||||
------------------*/
|
||||
typedef struct string_entry {
|
||||
long string_offset; /* offset in string array */
|
||||
long count; /* number of occurrences of string */
|
||||
long next; /* offset of next in hash chain */
|
||||
void *any_ptr; /* free pointer */
|
||||
unsigned long flags; /* user definable flag value for string */
|
||||
unsigned long hash_value; /* hash value of string using hash function */
|
||||
} STRING_ENTRY;
|
||||
|
||||
/*--------------------
|
||||
Dictionary signature (AK:04/04/95)
|
||||
--------------------*/
|
||||
typedef struct dict_sig_ { /* Dictionary signature */
|
||||
unsigned long check_value; /* 0xdeadbeef */
|
||||
int toc_size; /* # of entries in Table of Contents */
|
||||
long nparms; /* # of parameters */
|
||||
unsigned long checksum; /* Checksum for TOC */
|
||||
} DICT_SIG;
|
||||
|
||||
/*----------------------------------
|
||||
Dictionary table of contents entry (AK:04/04/95)
|
||||
----------------------------------*/
|
||||
typedef struct TOC_entry_ { /* Dictionary table of contents entry */
|
||||
char id[5]; /* Field identifier: */
|
||||
long offset; /* Offset (bytes) of entry in file */
|
||||
long size; /* Size (bytes) of entry */
|
||||
void *ptr; /* Where entry is stored in memory */
|
||||
unsigned long checksum; /* Checksum of entry */
|
||||
int type; /* 0=ordinary ; 1=EVECTOR ; 2=NULL */
|
||||
} DICT_TOC_ENTRY;
|
||||
|
||||
/*--------------------------------
|
||||
Dictionary parameter table entry (AK:04/04/95)
|
||||
--------------------------------*/
|
||||
typedef struct dict_parm_entry_ { /* Dictionary parameter table entry */
|
||||
char id[13]; /* Parameter identifier */
|
||||
unsigned long value; /* Parameter value */
|
||||
} DICT_PARM_ENTRY;
|
||||
|
||||
|
||||
/*---------------------------
|
||||
Hash dictionary information
|
||||
---------------------------*/
|
||||
typedef struct dictionary {
|
||||
unsigned long check_value; /* check validation value */
|
||||
unsigned long flags; /* flag values */
|
||||
long entry_count; /* number of used entries in each table */
|
||||
|
||||
char *string_array; /* storage for strings */
|
||||
long array_size; /* number of bytes allocated */
|
||||
long array_used; /* number of bytes occupied */
|
||||
int array_growth_count; /* number of times grown */
|
||||
|
||||
STRING_ENTRY *string_table; /* string table */
|
||||
long string_max; /* max number of entries in string table */
|
||||
long scan_string_index; /* current index into string table for scan */
|
||||
int string_growth_count; /* number of times had to grow string table */
|
||||
|
||||
long *chains; /* vector of array indices to hash entries */
|
||||
int longest_chain_length; /* longest chain length in hash table */
|
||||
int allowable_chain_length; /* chain lengths always < this */
|
||||
long table_size; /* number of elements in hash entries vector */
|
||||
unsigned long hash_mask; /* mask for doing mod() function */
|
||||
int hash_growth_count; /* number of times had to grow hash table */
|
||||
|
||||
void *ext; /* Hook for extensions to the dictionary (AK:04/03/95) */
|
||||
|
||||
DICT_SIG *sig; /* Signature (AK:04/04/95) */
|
||||
DICT_TOC_ENTRY *toc; /* Table of contents (AK:04/04/95) */
|
||||
DICT_PARM_ENTRY *parm; /* Parameters (AK:04/04/95) */
|
||||
|
||||
} DICTIONARY;
|
||||
|
||||
/*--------------------------------------------------------------
|
||||
dict_create: create a dictionary and initialize its structures
|
||||
--------------------------------------------------------------*/
|
||||
extern DICTIONARY *dict_create(
|
||||
const long toc_size,
|
||||
const long initial_string_count,
|
||||
const long initial_hash_entries,
|
||||
const long max_chain_length );
|
||||
|
||||
/*-------------------------------------------------
|
||||
dict_delete: deletes an entry from the dictionary
|
||||
-------------------------------------------------*/
|
||||
extern BOOLEANC dict_delete(
|
||||
const DICTIONARY *dict,
|
||||
const char *s,
|
||||
const long count );
|
||||
|
||||
/*---------------------------------------------------
|
||||
dict_destroy: discard a dictionary and its contents
|
||||
---------------------------------------------------*/
|
||||
extern BOOLEANC dict_destroy(
|
||||
DICTIONARY *dict );
|
||||
|
||||
/*------------------------------------------------
|
||||
dict_export: write a dictionary to an ASCII file
|
||||
------------------------------------------------*/
|
||||
extern BOOLEANC dict_export(
|
||||
DICTIONARY *dict,
|
||||
const char *fname );
|
||||
|
||||
/*-------------------------------------------------
|
||||
dict_import: read a dictionary from an ASCII file
|
||||
-------------------------------------------------*/
|
||||
extern DICTIONARY *dict_import(
|
||||
const char *dict_fname,
|
||||
const long initial_string_count,
|
||||
const long initial_hash_entries,
|
||||
const long max_chain_length );
|
||||
|
||||
/*------------------------------------------------------------------
|
||||
dict_insert: add entries into the dictionary, growing as necessary
|
||||
------------------------------------------------------------------*/
|
||||
extern STRING_ENTRY *dict_insert(
|
||||
DICTIONARY *dict,
|
||||
char *s,
|
||||
const long occurences,
|
||||
const unsigned long flags,
|
||||
void *any_ptr,
|
||||
long *number );
|
||||
|
||||
/*----------------------------------------------------
|
||||
dict_load: read a dictionary from a file into memory
|
||||
----------------------------------------------------*/
|
||||
extern DICTIONARY *dict_load(
|
||||
const char *fname );
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
dict_merge: merges the contents of a dictionary into another one,
|
||||
updating the contents of the destination
|
||||
-----------------------------------------------------------------*/
|
||||
extern BOOLEANC dict_merge(
|
||||
const DICTIONARY *dst,
|
||||
const DICTIONARY *src,
|
||||
const BOOLEANC move );
|
||||
|
||||
/*----------------------------------------------------
|
||||
dict_save: save a dictionary from memory into a file
|
||||
----------------------------------------------------*/
|
||||
extern BOOLEANC dict_save(
|
||||
DICTIONARY *dict,
|
||||
const char *fname );
|
||||
|
||||
/*-----------------------------------------------
|
||||
dict_scan_begin: begin a scan of the dictionary
|
||||
-----------------------------------------------*/
|
||||
extern BOOLEANC dict_scan_begin(
|
||||
DICTIONARY *dict );
|
||||
|
||||
/*--------------------------------------------
|
||||
dict_scan_next: get the next entry in a scan
|
||||
--------------------------------------------*/
|
||||
extern STRING_ENTRY *dict_scan_next(
|
||||
DICTIONARY *dict );
|
||||
|
||||
/*-----------------------------------------------
|
||||
dict_search: look for entries in the dictionary
|
||||
-----------------------------------------------*/
|
||||
extern STRING_ENTRY *dict_search(
|
||||
const DICTIONARY *dict,
|
||||
const char *s,
|
||||
long *number );
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
dict_string_by_number: return string pointer for a given string number
|
||||
----------------------------------------------------------------------*/
|
||||
extern STRING_ENTRY *dict_string_by_number(
|
||||
const DICTIONARY *dict,
|
||||
const long number );
|
||||
|
||||
/*----------------------------------------------------------
|
||||
dict_union: merges contents of 2 dictionaries into a third
|
||||
----------------------------------------------------------*/
|
||||
extern DICTIONARY *dict_union(
|
||||
const DICTIONARY *dict1,
|
||||
const DICTIONARY *dict2 );
|
||||
|
||||
#endif /* dict_h_included */
|
||||
438
urogue/dictutil.c
Normal file
438
urogue/dictutil.c
Normal file
|
|
@ -0,0 +1,438 @@
|
|||
/*
|
||||
dictutil.c
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
/*************************************************************************
|
||||
** Utilities for Dictionary Maintenence Functions
|
||||
*************************************************************************/
|
||||
|
||||
static char sccsid[] = "%W% %G%";
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#if !defined(OS2) && !defined(_WIN32)
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include "dict.h"
|
||||
#include "dictutil.h"
|
||||
#include "rogue.h"
|
||||
|
||||
int trace;
|
||||
FILE *ft;
|
||||
|
||||
|
||||
/***********
|
||||
** Read 'count' characters into 'buffer' at 'offset' in a binary file
|
||||
** Return 0 on success; -1 on failure;
|
||||
***********/
|
||||
|
||||
int block_read( FILE *fi , char *buffer , size_t count , long offset )
|
||||
{
|
||||
if ( fseek(fi,offset,SEEK_SET) == -1 )
|
||||
return( -1 );
|
||||
|
||||
if ( fread(buffer,1,count,fi) != count )
|
||||
return( -1 );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/***********
|
||||
** Write 'count' characters from 'buffer' to a binary file.
|
||||
** Return -1 on failure; 0 on success.
|
||||
***********/
|
||||
|
||||
int block_write( FILE *fo , char *buffer , size_t count )
|
||||
{
|
||||
if ( fwrite(buffer,1,count,fo) != count )
|
||||
return( -1 );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/***********
|
||||
** Load a dictionary table entry with id TOC_id into memory pointed to by block.
|
||||
** Update the dictionary TOC.
|
||||
** If *block=NULL, allocate the block of memory.
|
||||
** Return 0 on success; -1 on failure.
|
||||
** Set dt_entry->ptr to where the block is stored.
|
||||
***********/
|
||||
|
||||
void *dict_load_block( DICTIONARY *dict , char *toc_id ,
|
||||
FILE *fi , void *block )
|
||||
{ DICT_TOC_ENTRY *dt_entry;
|
||||
static void *ptr;
|
||||
int index, ret_code;
|
||||
|
||||
index = dict_toc_index( dict , toc_id );
|
||||
if ( index != -1 ) { /* Found the id */
|
||||
dt_entry = &(dict->toc[index]);
|
||||
} else {
|
||||
signal_error( "dict_load_block: could not find TOC_id" , toc_id , 1 );
|
||||
return( NULL );
|
||||
} /* endif */
|
||||
|
||||
if ( block == NULL ) {
|
||||
ptr = malloc( dt_entry->size );
|
||||
if ( trace > 3 ) {
|
||||
fprintf( ft , "\ndict_load_block allocates %lx bytes at location %p\n" ,
|
||||
dt_entry->size , ptr );
|
||||
} /* endif */
|
||||
} else {
|
||||
ptr = block;
|
||||
if ( trace > 3 ) {
|
||||
fprintf( ft , "\ndict_load_block uses memory at location %p\n" , ptr );
|
||||
} /* endif */
|
||||
} /* endif */
|
||||
if ( ptr == NULL ) {
|
||||
signal_error( "dict_load_block: alloc failed " , toc_id , 1 );
|
||||
return( NULL );
|
||||
} /* endif */
|
||||
|
||||
ret_code = block_read( fi ,
|
||||
(char*)ptr ,
|
||||
dt_entry->size ,
|
||||
dt_entry->offset );
|
||||
if ( ret_code == -1 )
|
||||
return( NULL );
|
||||
|
||||
if ( dt_entry->checksum !=
|
||||
compute_checksum( dt_entry->size , (char*)ptr ) ) {
|
||||
signal_error( "dict_load_block: invalid checksum ", toc_id, 1);
|
||||
return( NULL );
|
||||
} /* endif */
|
||||
|
||||
dt_entry->ptr = ptr;
|
||||
|
||||
if ( trace > 3 ) {
|
||||
fprintf( ft , "\nLoaded block\nTOC entry: id:%s offset:%lx size:%lx ptr:%p checksum:%lx type:%d\n" ,
|
||||
dict->toc[index].id , dict->toc[index].offset ,
|
||||
dict->toc[index].size , dict->toc[index].ptr ,
|
||||
dict->toc[index].checksum , dict->toc[index].type );
|
||||
} /* endif */
|
||||
|
||||
return( ptr );
|
||||
}
|
||||
|
||||
/***********
|
||||
** Save a dictionary table entry.
|
||||
** Update the dictionary TOC entry offset and checksum fields.
|
||||
** Return 0 on success, -1 on failure.
|
||||
** Note: It is assumed that the size and pointer fields in TOC entry are
|
||||
** already up to date; i.e., that they are consistent with the current
|
||||
** location and size of the block being written. This is essential
|
||||
** because the table of contents must have already been written
|
||||
** into the file.
|
||||
***********/
|
||||
|
||||
BOOLEANC dict_save_block( DICTIONARY *dict , char *toc_id , FILE *fo )
|
||||
{ DICT_TOC_ENTRY *dt_entry;
|
||||
int index, ret_code;
|
||||
char *block;
|
||||
|
||||
index = dict_toc_index( dict , toc_id );
|
||||
if ( index == -1 ) {
|
||||
signal_error( "dict_save_block: id not found " , toc_id , 1 );
|
||||
return( FALSE );
|
||||
} /* endif */
|
||||
dt_entry = &(dict->toc[index]);
|
||||
block = (char*)(dt_entry->ptr);
|
||||
|
||||
if ( block == NULL ) {
|
||||
signal_error( "dict_save_block: NULL block " , toc_id , 1 );
|
||||
return( FALSE );
|
||||
} /* endif */
|
||||
|
||||
/* dt_entry->offset = fseek( fo , 0 , SEEK_END ); */
|
||||
dt_entry->checksum = compute_checksum( dt_entry->size , block );
|
||||
ret_code = block_write( fo , dt_entry->ptr , dt_entry->size );
|
||||
if ( ret_code == -1 ) {
|
||||
signal_error( "dict_save_block: block_write failed " , toc_id , 1 );
|
||||
return( FALSE );
|
||||
} /* endif */
|
||||
|
||||
if ( trace > 3 ) {
|
||||
fprintf( ft , "\nStored block\nTOC entry: id:%s offset:%lx size:%lx ptr:%p checksum:%lx type:%d\n" ,
|
||||
dict->toc[index].id , dict->toc[index].offset ,
|
||||
dict->toc[index].size , dict->toc[index].ptr ,
|
||||
dict->toc[index].checksum , dict->toc[index].type );
|
||||
} /* endif */
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
/***********
|
||||
** Look up and id in the table of contents.
|
||||
** Return its index (-1 on failure).
|
||||
***********/
|
||||
|
||||
int dict_toc_index( DICTIONARY *dict , char *toc_id )
|
||||
{ int index;
|
||||
|
||||
for ( index = 0 ; index < dict->sig->toc_size ; index++ ) {
|
||||
if ( strcmp(dict->toc[index].id,toc_id) == 0 )
|
||||
return( index );
|
||||
} /* endfor */
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/***********
|
||||
** Compute a block checksum.
|
||||
** (Currently just returns 0.)
|
||||
***********/
|
||||
|
||||
unsigned long compute_checksum( size_t size , char *block )
|
||||
{
|
||||
NOOP(size);
|
||||
NOOP(block);
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/***********
|
||||
** Create a dictionary paramter entry.
|
||||
***********/
|
||||
|
||||
DICT_PARM_ENTRY *dict_make_parm_entry( char *id , unsigned long value )
|
||||
{ static DICT_PARM_ENTRY *entry;
|
||||
|
||||
entry = (DICT_PARM_ENTRY *) malloc( sizeof(DICT_PARM_ENTRY) );
|
||||
if ( entry == NULL )
|
||||
return(NULL);
|
||||
|
||||
strncpy( entry->id , id , 13 );
|
||||
entry->value = value;
|
||||
|
||||
return( entry );
|
||||
}
|
||||
|
||||
/***********
|
||||
** Look up and id in the parameter array.
|
||||
** Return its index (-1 on failure).
|
||||
***********/
|
||||
|
||||
int dict_parm_index( DICTIONARY *dict , char *parm_id )
|
||||
{ long index;
|
||||
|
||||
for ( index = 0 ; index < dict->sig->nparms ; index++ ) {
|
||||
if ( strcmp( dict->parm[index].id , parm_id ) == 0 )
|
||||
return( (int) index );
|
||||
} /* endfor */
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/***********
|
||||
** Reset table of contents offsets and checksums
|
||||
** in preparation for dict_save().
|
||||
***********/
|
||||
|
||||
BOOLEANC dict_reset_toc_offsets( DICTIONARY *dict )
|
||||
{ int i;
|
||||
long offset;
|
||||
|
||||
offset = sizeof(DICT_SIG)
|
||||
+ dict->sig->toc_size * sizeof(DICT_TOC_ENTRY);
|
||||
for ( i = 0 ; i < dict->sig->toc_size ; i++ ) {
|
||||
dict->toc[i].offset = offset;
|
||||
offset += dict->toc[i].size;
|
||||
dict->toc[i].checksum =
|
||||
compute_checksum( dict->toc[i].size , dict->toc[i].ptr );
|
||||
} /* endfor */
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
/***********
|
||||
** Load the names of the dictionary parameters.
|
||||
** 14 parms
|
||||
***********/
|
||||
|
||||
BOOLEANC dict_set_parm_ids( DICTIONARY *dict )
|
||||
{
|
||||
if ( dict==NULL || dict->sig == NULL ) {
|
||||
signal_error( "dict_set_parm_ids: Allocate dict and signature first." , "" , 0 );
|
||||
return( FALSE );
|
||||
}
|
||||
dict->sig->nparms = 14;
|
||||
strcpy( dict->parm[0].id , "FLAGS_______" );
|
||||
strcpy( dict->parm[1].id , "ENTRY_COUNT_" );
|
||||
strcpy( dict->parm[2].id , "ARRAY_SIZE__" );
|
||||
strcpy( dict->parm[3].id , "ARRAY_USED__" );
|
||||
strcpy( dict->parm[4].id , "ARR_GROW_CT_" );
|
||||
strcpy( dict->parm[5].id , "STRING_MAX__" );
|
||||
strcpy( dict->parm[6].id , "STR_GROW_CT_" );
|
||||
strcpy( dict->parm[7].id , "LONG_CHAIN__" );
|
||||
strcpy( dict->parm[8].id , "ALLOW_CHAIN_" );
|
||||
strcpy( dict->parm[9].id , "HASH_TAB_SIZ" );
|
||||
strcpy( dict->parm[10].id , "HASH_MASK___" );
|
||||
strcpy( dict->parm[11].id , "HASH_GROW_CT" );
|
||||
strcpy( dict->parm[12].id , "CHECK_VALUE_" );
|
||||
strcpy( dict->parm[13].id , "SCAN_STR_IX_" );
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
/***********
|
||||
** Set the dictionary parm structure from the values in the dict structure.
|
||||
** 14 parms
|
||||
***********/
|
||||
|
||||
BOOLEANC dict_set_parm_values( DICTIONARY *dict )
|
||||
{ int index;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"FLAGS_______")) == -1 )
|
||||
return( FALSE );
|
||||
dict->parm[index].value = (unsigned long)dict->flags;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"ENTRY_COUNT_")) == -1 )
|
||||
return( FALSE );
|
||||
dict->parm[index].value = (unsigned long)dict->entry_count;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"ARRAY_SIZE__")) == -1 )
|
||||
return( FALSE );
|
||||
dict->parm[index].value = (unsigned long)dict->array_size;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"ARRAY_USED__")) == -1 )
|
||||
return( FALSE );
|
||||
dict->parm[index].value = (unsigned long)dict->array_used;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"ARR_GROW_CT_")) == -1 )
|
||||
return( FALSE );
|
||||
dict->parm[index].value = (unsigned long)dict->array_growth_count;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"STRING_MAX__")) == -1 )
|
||||
return( FALSE );
|
||||
dict->parm[index].value = (unsigned long)dict->string_max;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"STR_GROW_CT_")) == -1 )
|
||||
return( FALSE );
|
||||
dict->parm[index].value = (unsigned long)dict->string_growth_count;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"LONG_CHAIN__")) == -1 )
|
||||
return( FALSE );
|
||||
dict->parm[index].value = (unsigned long)dict->longest_chain_length;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"ALLOW_CHAIN_")) == -1 )
|
||||
return( FALSE );
|
||||
dict->parm[index].value = (unsigned long)dict->allowable_chain_length;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"HASH_TAB_SIZ")) == -1 )
|
||||
return( FALSE );
|
||||
dict->parm[index].value = (unsigned long)dict->table_size;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"HASH_MASK___")) == -1 )
|
||||
return( FALSE );
|
||||
dict->parm[index].value = (unsigned long)dict->hash_mask;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"HASH_GROW_CT")) == -1 )
|
||||
return( FALSE );
|
||||
dict->parm[index].value = (unsigned long)dict->hash_growth_count;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"CHECK_VALUE_")) == -1 )
|
||||
return( FALSE );
|
||||
dict->parm[index].value = (unsigned long)dict->check_value;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"SCAN_STR_IX_")) == -1 )
|
||||
return( FALSE );
|
||||
dict->parm[index].value = (unsigned long)dict->scan_string_index;
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
|
||||
/***********
|
||||
** Set the values in the dict structure from the dictionary parm structure.
|
||||
** 14 parms
|
||||
***********/
|
||||
|
||||
BOOLEANC dict_set_parm_variables( DICTIONARY *dict )
|
||||
{ int index;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"FLAGS_______")) == -1 )
|
||||
return( FALSE );
|
||||
dict->flags = (unsigned long)dict->parm[index].value;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"ENTRY_COUNT_")) == -1 )
|
||||
return( FALSE );
|
||||
dict->entry_count = (long)dict->parm[index].value;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"ARRAY_SIZE__")) == -1 )
|
||||
return( FALSE );
|
||||
dict->array_size = (long)dict->parm[index].value;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"ARRAY_USED__")) == -1 )
|
||||
return( FALSE );
|
||||
dict->array_used = (long)dict->parm[index].value;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"ARR_GROW_CT_")) == -1 )
|
||||
return( FALSE );
|
||||
dict->array_growth_count = (int)dict->parm[index].value;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"STRING_MAX__")) == -1 )
|
||||
return( FALSE );
|
||||
dict->string_max = (long)dict->parm[index].value ;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"STR_GROW_CT_")) == -1 )
|
||||
return( FALSE );
|
||||
dict->string_growth_count = (int)dict->parm[index].value;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"LONG_CHAIN__")) == -1 )
|
||||
return( FALSE );
|
||||
dict->longest_chain_length = (int)dict->parm[index].value;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"ALLOW_CHAIN_")) == -1 )
|
||||
return( FALSE );
|
||||
dict->allowable_chain_length = (int)dict->parm[index].value;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"HASH_TAB_SIZ")) == -1 )
|
||||
return( FALSE );
|
||||
dict->table_size = (long)dict->parm[index].value;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"HASH_MASK___")) == -1 )
|
||||
return( FALSE );
|
||||
dict->hash_mask = (unsigned long)dict->parm[index].value;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"HASH_GROW_CT")) == -1 )
|
||||
return( FALSE );
|
||||
dict->hash_growth_count = (int)dict->parm[index].value;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"CHECK_VALUE_")) == -1 )
|
||||
return( FALSE );
|
||||
dict->check_value = (unsigned long)dict->parm[index].value;
|
||||
|
||||
if ( (index=dict_parm_index(dict,"SCAN_STR_IX_")) == -1 )
|
||||
return( FALSE );
|
||||
dict->scan_string_index = (long)dict->parm[index].value;
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
/***********
|
||||
** If trace (global) > 0 , signal an error
|
||||
** If severity > 0 , abort
|
||||
***********/
|
||||
|
||||
void signal_error( char *header , char *message , int severity )
|
||||
{
|
||||
FILE *fpe;
|
||||
|
||||
if ( trace > 0 ) {
|
||||
printf( "%s: %s\n" , header , message );
|
||||
fpe = fopen( "ERROR.FIL" , "a" );
|
||||
fprintf( fpe , "\n%s: %s\n" , header , message );
|
||||
fclose( fpe );
|
||||
} /* endif */
|
||||
|
||||
if ( severity > 0 )
|
||||
abort();
|
||||
}
|
||||
116
urogue/dictutil.h
Normal file
116
urogue/dictutil.h
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
dictutil.h
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
/****************************************************************/
|
||||
/* HEADERS FOR DICTIONARY MAINTENENCE ROUTINE UTILITIES */
|
||||
/****************************************************************/
|
||||
|
||||
#ifndef dictutil_h_included
|
||||
#define dictutil_h_included
|
||||
|
||||
static char dictutil_sccsid[] = "%W% %G%";
|
||||
|
||||
#include <stdio.h>
|
||||
#include "dict.h"
|
||||
|
||||
/*-------------------------------
|
||||
Binary read of a block of bytes
|
||||
-------------------------------*/
|
||||
extern int block_read(
|
||||
FILE *fi,
|
||||
char *buffer,
|
||||
size_t count,
|
||||
long offset );
|
||||
|
||||
/*--------------------------------
|
||||
Binary write of a block of bytes
|
||||
--------------------------------*/
|
||||
extern int block_write(
|
||||
FILE *fo,
|
||||
char *buffer,
|
||||
size_t count );
|
||||
|
||||
/*--------------------------------------
|
||||
Compute a checksum of a block of bytes
|
||||
--------------------------------------*/
|
||||
extern unsigned long compute_checksum(
|
||||
size_t size,
|
||||
char *block );
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
Load a block of bytes from a compiled dictionary file into memory
|
||||
-----------------------------------------------------------------*/
|
||||
extern void *dict_load_block(
|
||||
DICTIONARY *dict,
|
||||
char *toc_id,
|
||||
FILE *fi,
|
||||
void *block );
|
||||
|
||||
/*-----------------------------------
|
||||
Create a dictionary parameter entry
|
||||
-----------------------------------*/
|
||||
extern DICT_PARM_ENTRY *dict_make_parm_entry(
|
||||
char *id,
|
||||
unsigned long value );
|
||||
|
||||
/*------------------------------------
|
||||
Look up an id in the parameter array
|
||||
------------------------------------*/
|
||||
extern int dict_parm_index(
|
||||
DICTIONARY *dict,
|
||||
char *parm_id );
|
||||
|
||||
/*-------------------------------
|
||||
Reset table of contents offsets
|
||||
-------------------------------*/
|
||||
extern BOOLEANC dict_reset_toc_offsets(
|
||||
DICTIONARY *dict );
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
Save a block of bytes from memory into a compiled dictionary file
|
||||
-----------------------------------------------------------------*/
|
||||
extern BOOLEANC dict_save_block(
|
||||
DICTIONARY *dict,
|
||||
char *toc_id,
|
||||
FILE *fo );
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Set the dictionary parm values from the values in the dict structure
|
||||
--------------------------------------------------------------------*/
|
||||
extern BOOLEANC dict_set_parm_values(
|
||||
DICTIONARY *dict );
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Set the values in the dict structure from the dictionary parm values
|
||||
--------------------------------------------------------------------*/
|
||||
extern BOOLEANC dict_set_parm_variables(
|
||||
DICTIONARY *dict );
|
||||
|
||||
/*---------------------------
|
||||
Set the dictionary parm ids
|
||||
---------------------------*/
|
||||
extern BOOLEANC dict_set_parm_ids(
|
||||
DICTIONARY *dict );
|
||||
|
||||
/*--------------------------------------
|
||||
Look up an id in the table of contents
|
||||
--------------------------------------*/
|
||||
extern int dict_toc_index(
|
||||
DICTIONARY *dict,
|
||||
char *toc_id );
|
||||
|
||||
/*------------------------------------
|
||||
Record and error and abort if needed
|
||||
------------------------------------*/
|
||||
extern void signal_error(
|
||||
char *header,
|
||||
char *message,
|
||||
int severity );
|
||||
#endif
|
||||
185
urogue/encumb.c
Normal file
185
urogue/encumb.c
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
encumb.c - Stuff to do with encumberance
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
Based on "Advanced Rogue"
|
||||
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
updpack()
|
||||
Update his pack weight and adjust fooduse accordingly
|
||||
*/
|
||||
|
||||
void
|
||||
updpack(void)
|
||||
{
|
||||
int curcarry = packweight();
|
||||
|
||||
pstats.s_carry = totalenc(); /* update max encumb */
|
||||
|
||||
if (is_carrying(TR_PURSE))
|
||||
pstats.s_carry += 1000;
|
||||
|
||||
foodlev = 0;
|
||||
|
||||
switch ((curcarry * 5) / pstats.s_carry) /* % of total capacity */
|
||||
{
|
||||
case 5: /* 100 % */
|
||||
foodlev++;
|
||||
|
||||
case 4: /* 80 % */
|
||||
if (rnd(100) < 80)
|
||||
foodlev++;
|
||||
|
||||
case 3: /* 60 % */
|
||||
if (rnd(100) < 60)
|
||||
foodlev++;
|
||||
|
||||
case 2: /* 40 % */
|
||||
if (rnd(100) < 40)
|
||||
foodlev++;
|
||||
|
||||
case 1: /* 20 % */
|
||||
if (rnd(100) < 20)
|
||||
foodlev++;
|
||||
|
||||
case 0: /* 0 % */
|
||||
foodlev++;
|
||||
}
|
||||
|
||||
pstats.s_pack = curcarry; /* update pack weight */
|
||||
|
||||
if (is_carrying(TR_PURSE)) /* makes pack lighter */
|
||||
foodlev--;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
packweight()
|
||||
Get the total weight of the hero's pack
|
||||
*/
|
||||
|
||||
int
|
||||
packweight(void)
|
||||
{
|
||||
struct linked_list *pc;
|
||||
int weight = 0;
|
||||
|
||||
for (pc = pack; pc != NULL; pc = next(pc))
|
||||
{
|
||||
struct object *obj = OBJPTR(pc);
|
||||
|
||||
weight += itemweight(obj) * obj->o_count;
|
||||
}
|
||||
|
||||
if (weight < 0) /* caused by artifacts or blessed items */
|
||||
weight = 0;
|
||||
|
||||
return (weight);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
itemweight()
|
||||
Get the weight of an object
|
||||
*/
|
||||
|
||||
int
|
||||
itemweight(struct object *wh)
|
||||
{
|
||||
int weight = wh->o_weight; /* get base weight */
|
||||
int ac;
|
||||
|
||||
switch (wh->o_type)
|
||||
{
|
||||
case ARMOR: /* 10% for each plus or minus*/
|
||||
ac = armors[wh->o_which].a_class - wh->o_ac;
|
||||
weight *= (10 - ac) / 10;
|
||||
break;
|
||||
|
||||
case WEAPON:
|
||||
if ((wh->o_hplus + wh->o_dplus) > 0)
|
||||
weight /= 2;
|
||||
}
|
||||
|
||||
if (wh->o_flags & ISCURSED)
|
||||
weight += weight / 2; /* +50% for cursed */
|
||||
else if (wh->o_flags & ISBLESSED)
|
||||
weight -= weight / 5; /* -20% for blessed */
|
||||
|
||||
if (weight < 0)
|
||||
weight = 0;
|
||||
|
||||
return (weight);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
playenc()
|
||||
Get hero's carrying ability above norm 50 units per point of STR
|
||||
over 10, 300 units per plus on R_CARRYING 1000 units for TR_PURSE
|
||||
*/
|
||||
|
||||
int
|
||||
playenc(void)
|
||||
{
|
||||
int ret_val = (pstats.s_str - 10) * 50;
|
||||
|
||||
if (is_wearing(R_CARRYING))
|
||||
ret_val += ring_value(R_CARRYING) * 300;
|
||||
|
||||
return (ret_val);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
totalenc()
|
||||
Get total weight that the hero can carry
|
||||
*/
|
||||
|
||||
int
|
||||
totalenc(void)
|
||||
{
|
||||
int wtotal = 1400 + playenc();
|
||||
|
||||
switch (hungry_state)
|
||||
{
|
||||
case F_OK:
|
||||
case F_HUNGRY: /* no change */
|
||||
break;
|
||||
|
||||
case F_WEAK:
|
||||
wtotal -= wtotal / 4; /* 25% off weak */
|
||||
break;
|
||||
|
||||
case F_FAINT:
|
||||
wtotal /= 2; /* 50% off faint */
|
||||
break;
|
||||
}
|
||||
|
||||
return (wtotal);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
hitweight()
|
||||
Gets the fighting ability according to current weight This
|
||||
returns a +2 hit for very light pack weight, +1 hit
|
||||
for light pack weight, 0 hit for medium pack weight, -1 hit for heavy
|
||||
pack weight, -2 hit for very heavy pack weight
|
||||
*/
|
||||
|
||||
int
|
||||
hitweight(void)
|
||||
{
|
||||
return(3 - foodlev);
|
||||
}
|
||||
2175
urogue/fight.c
Normal file
2175
urogue/fight.c
Normal file
File diff suppressed because it is too large
Load diff
350
urogue/getplay.c
Normal file
350
urogue/getplay.c
Normal file
|
|
@ -0,0 +1,350 @@
|
|||
/*
|
||||
getplay.c - Procedures for saving and retrieving a characters starting
|
||||
attributes, armour, and weapon.
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
/* 11/08/83 ???, S.A. Hester */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "rogue.h"
|
||||
|
||||
#define I_STR 0
|
||||
#define I_INTEL 1
|
||||
#define I_WISDOM 2
|
||||
#define I_DEXT 3
|
||||
#define I_CONST 4
|
||||
#define I_CHARISMA 5
|
||||
#define I_HPT 6
|
||||
#define I_POWER 7
|
||||
#define I_CTYPE 8
|
||||
#define MAXPATT 9 /* Total Number of above defines. */
|
||||
#define MAXPDEF 10 /* Maximum number of pre-defined chars */
|
||||
|
||||
static int def_array[MAXPDEF][MAXPATT]; /* Pre-def'd chars */
|
||||
|
||||
static void get_chr_filename(char *filename, int size)
|
||||
{
|
||||
const char *home;
|
||||
|
||||
home = getenv("HOME");
|
||||
|
||||
if (home) {
|
||||
if ((int)strlen(home) < (size - 12) )
|
||||
{
|
||||
strcpy(filename, home);
|
||||
strcat(filename,"/urogue.chr");
|
||||
}
|
||||
else
|
||||
strncpy(filename,"urogue.chr",size);
|
||||
}
|
||||
else
|
||||
strcpy(filename, "urogue.chr");
|
||||
}
|
||||
|
||||
int
|
||||
geta_player(void)
|
||||
{
|
||||
int i;
|
||||
FILE *fd;
|
||||
char pbuf[2 * LINELEN];
|
||||
char filename[200];
|
||||
|
||||
get_chr_filename(filename, sizeof(filename));
|
||||
|
||||
if ((fd = fopen(filename, "r")) == NULL)
|
||||
return(FALSE);
|
||||
|
||||
fread(def_array, sizeof(def_array), 1, fd);
|
||||
fclose(fd);
|
||||
|
||||
wclear(hw);
|
||||
touchwin(hw);
|
||||
|
||||
print_stored();
|
||||
mvwaddstr(hw, 0, 0, "Do you wish to select a character? ");
|
||||
wrefresh(hw);
|
||||
|
||||
if (readcharw(hw) != 'y')
|
||||
return FALSE;
|
||||
|
||||
do
|
||||
{
|
||||
wmove(hw, LINES - 1, 0);
|
||||
wclrtoeol(hw);
|
||||
mvwaddstr(hw, 0, 0, "Enter the number of a pre-defined character: ");
|
||||
wclrtoeol(hw);
|
||||
wrefresh(hw);
|
||||
get_string(pbuf, hw);
|
||||
i = atoi(pbuf) - 1;
|
||||
|
||||
if (i < 0 || i > MAXPDEF - 1)
|
||||
{
|
||||
wstandout(hw);
|
||||
mvwaddstr(hw, 1, 0, "Please use the range 1 to");
|
||||
wprintw(hw, " %d.", MAXPDEF);
|
||||
wstandend(hw);
|
||||
wclrtoeol(hw);
|
||||
wrefresh(hw);
|
||||
}
|
||||
else if (def_array[i][I_STR] == 0)
|
||||
{
|
||||
wstandout(hw);
|
||||
mvwaddstr(hw,1,0,"Please enter the number of a known character: ");
|
||||
wstandend(hw);
|
||||
wclrtoeol(hw);
|
||||
}
|
||||
else
|
||||
{
|
||||
mvwaddstr(hw, 1, 0, "");
|
||||
wclrtoeol(hw);
|
||||
}
|
||||
|
||||
}
|
||||
while (i < 0 || i > MAXPDEF - 1 || (def_array[i][I_STR] == 0));
|
||||
|
||||
pstats.s_str = def_array[i][I_STR];
|
||||
pstats.s_intel = def_array[i][I_INTEL];
|
||||
pstats.s_wisdom = def_array[i][I_WISDOM];
|
||||
pstats.s_dext = def_array[i][I_DEXT];
|
||||
pstats.s_const = def_array[i][I_CONST];
|
||||
pstats.s_charisma = def_array[i][I_CHARISMA];
|
||||
pstats.s_hpt = def_array[i][I_HPT];
|
||||
pstats.s_power = def_array[i][I_POWER];
|
||||
player.t_ctype = char_type = def_array[i][I_CTYPE];
|
||||
max_stats = pstats;
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
puta_player(void)
|
||||
{
|
||||
FILE *fd;
|
||||
char pbuf[2 * LINELEN];
|
||||
char filename[200];
|
||||
int i;
|
||||
char *class = which_class(player.t_ctype);
|
||||
|
||||
sprintf(pbuf, "You have a %s with the following attributes:", class);
|
||||
mvwaddstr(hw, 2, 0, pbuf);
|
||||
wclrtoeol(hw);
|
||||
|
||||
sprintf(pbuf,
|
||||
"Int: %d Str: %d Wis: %d Dex: %d Con: %d Cha: %d Pow: %d Hpt: %d",
|
||||
pstats.s_intel,
|
||||
pstats.s_str,
|
||||
pstats.s_wisdom,
|
||||
pstats.s_dext,
|
||||
pstats.s_const,
|
||||
pstats.s_charisma,
|
||||
pstats.s_power,
|
||||
pstats.s_hpt );
|
||||
|
||||
mvwaddstr(hw, 3, 0, "");
|
||||
wclrtoeol(hw);
|
||||
mvwaddstr(hw, 4, 0, pbuf);
|
||||
wclrtoeol(hw);
|
||||
mvwaddstr(hw, 5, 0, "");
|
||||
wclrtoeol(hw);
|
||||
mvwaddstr(hw, 0, 0, "Would you like to save this character?");
|
||||
wclrtoeol(hw);
|
||||
|
||||
|
||||
wrefresh(hw);
|
||||
|
||||
if ((readcharw(hw) & 0177) != 'y')
|
||||
return;
|
||||
|
||||
do
|
||||
{
|
||||
mvwaddstr(hw, 0, 0, "Overwrite which number? ");
|
||||
wclrtoeol(hw);
|
||||
wrefresh(hw);
|
||||
get_string(pbuf, hw);
|
||||
i = atoi(pbuf) - 1;
|
||||
|
||||
if (i < 0 || i > MAXPDEF - 1)
|
||||
{
|
||||
wstandout(hw);
|
||||
mvwaddstr(hw, 1, 0, "Use the range 1 to");
|
||||
wprintw(hw, " %d!", MAXPDEF);
|
||||
wstandend(hw);
|
||||
wclrtoeol(hw);
|
||||
wrefresh(hw);
|
||||
}
|
||||
}
|
||||
while (i < 0 || i > MAXPDEF - 1);
|
||||
|
||||
/* Set some global stuff */
|
||||
|
||||
def_array[i][I_STR] = pstats.s_str;
|
||||
def_array[i][I_INTEL] = pstats.s_intel;
|
||||
def_array[i][I_WISDOM] = pstats.s_wisdom;
|
||||
def_array[i][I_DEXT] = pstats.s_dext;
|
||||
def_array[i][I_CONST] = pstats.s_const;
|
||||
def_array[i][I_CHARISMA] = pstats.s_charisma;
|
||||
def_array[i][I_HPT] = pstats.s_hpt;
|
||||
def_array[i][I_POWER] = pstats.s_power;
|
||||
def_array[i][I_CTYPE] = player.t_ctype;
|
||||
|
||||
/* OK. Now let's write this stuff out! */
|
||||
|
||||
get_chr_filename(filename, sizeof(filename));
|
||||
|
||||
|
||||
if ((fd = fopen(filename, "w")) == NULL)
|
||||
{
|
||||
sprintf(pbuf, "I can't seem to open/create urogue.chr.");
|
||||
mvwaddstr(hw, 5, 5, pbuf);
|
||||
mvwaddstr(hw, 6, 5, "However I'll let you play it anyway!");
|
||||
mvwaddstr(hw, LINES - 1, 0, spacemsg);
|
||||
wrefresh(hw);
|
||||
wait_for(' ');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
fwrite(def_array, sizeof(def_array), 1, fd);
|
||||
fclose(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
do_getplayer(void)
|
||||
{
|
||||
print_stored();
|
||||
|
||||
if (char_type == C_NOTSET)
|
||||
do
|
||||
{
|
||||
/* See what type character will be */
|
||||
|
||||
mvwaddstr(hw, 3, 0, "[a] Fighter\t"
|
||||
"[b] Paladin\t"
|
||||
"[c] Ranger\n"
|
||||
"[d] Cleric\t"
|
||||
"[e] Druid\t"
|
||||
"[f] Magician\n"
|
||||
"[g] Illusionist\t"
|
||||
"[h] Thief\t"
|
||||
"[i] Assasin\t"
|
||||
"[j] Ninja");
|
||||
|
||||
mvwaddstr(hw, 0, 0, "What character class do you desire? ");
|
||||
wrefresh(hw);
|
||||
char_type = readcharw(hw) - 'a';
|
||||
|
||||
if (char_type < C_FIGHTER || char_type >= C_MONSTER)
|
||||
{
|
||||
wstandout(hw);
|
||||
mvwaddstr(hw, 1, 0, "Please enter a letter from a - j");
|
||||
wstandend(hw);
|
||||
wclrtoeol(hw);
|
||||
wrefresh(hw);
|
||||
}
|
||||
else
|
||||
{
|
||||
mvwaddstr(hw, 1, 0, "");
|
||||
wclrtoeol(hw);
|
||||
}
|
||||
}
|
||||
while (char_type < C_FIGHTER || char_type >= C_MONSTER);
|
||||
|
||||
player.t_ctype = char_type;
|
||||
}
|
||||
|
||||
void
|
||||
print_stored(void)
|
||||
{
|
||||
int i;
|
||||
char *class;
|
||||
char pbuf[2 * LINELEN];
|
||||
|
||||
wstandout(hw);
|
||||
mvwaddstr(hw, 9, 0, "YOUR CURRENT CHARACTERS:");
|
||||
wstandend(hw);
|
||||
wclrtoeol(hw);
|
||||
|
||||
for (i = 0; i < MAXPDEF; i++)
|
||||
{
|
||||
if (def_array[i][I_STR])
|
||||
{
|
||||
class = which_class(def_array[i][I_CTYPE]);
|
||||
|
||||
sprintf(pbuf,
|
||||
"%2d. (%s): Int: %d Str: %d Wis: %d Dex: %d Con: %d Cha: %d"
|
||||
" Pow: %d Hpt: %d",
|
||||
i + 1,
|
||||
class,
|
||||
def_array[i][I_INTEL],
|
||||
def_array[i][I_STR],
|
||||
def_array[i][I_WISDOM],
|
||||
def_array[i][I_DEXT],
|
||||
def_array[i][I_CONST],
|
||||
def_array[i][I_CHARISMA],
|
||||
def_array[i][I_POWER],
|
||||
def_array[i][I_HPT]);
|
||||
|
||||
mvwaddstr(hw, 11 + i, 0, pbuf);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pbuf, "%2d. ### NONE ###", i + 1);
|
||||
mvwaddstr(hw, 11 + i, 0, pbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
which_class(int c_class)
|
||||
{
|
||||
char *class;
|
||||
|
||||
switch (c_class)
|
||||
{
|
||||
case C_FIGHTER:
|
||||
class = "Fighter";
|
||||
break;
|
||||
case C_MAGICIAN:
|
||||
class = "Magician";
|
||||
break;
|
||||
case C_CLERIC:
|
||||
class = "Cleric";
|
||||
break;
|
||||
case C_THIEF:
|
||||
class = "Thief";
|
||||
break;
|
||||
case C_PALADIN:
|
||||
class = "Paladin";
|
||||
break;
|
||||
case C_RANGER:
|
||||
class = "Ranger";
|
||||
break;
|
||||
case C_DRUID:
|
||||
class = "Druid";
|
||||
break;
|
||||
case C_ILLUSION:
|
||||
class = "Illusionist";
|
||||
break;
|
||||
case C_ASSASIN:
|
||||
class = "Assasin";
|
||||
break;
|
||||
case C_NINJA:
|
||||
class = "Ninja";
|
||||
break;
|
||||
default:
|
||||
class = "Monster";
|
||||
break;
|
||||
}
|
||||
|
||||
return (class);
|
||||
}
|
||||
1469
urogue/history.txt
Normal file
1469
urogue/history.txt
Normal file
File diff suppressed because it is too large
Load diff
136
urogue/ident.c
Normal file
136
urogue/ident.c
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
ident.c - routines to associate an identifier with an object
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1986, 1991, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ident
|
||||
*
|
||||
* This file contains routines to associate an identifier with an object. The
|
||||
* identifiers are organized by type. Once an identifier is attached to an
|
||||
* object, it remains with that object until the object is removed from the
|
||||
* game. The identifiers are small integers, and they are assigned merely by
|
||||
* counting objects of the same type. Allocation picks the next available
|
||||
* integer.
|
||||
*
|
||||
* It is required that the linked list be sorted within types so that gaps can
|
||||
* easily be detected.
|
||||
*/
|
||||
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* Index of 0 is invalid (unused state)
|
||||
*/
|
||||
|
||||
char print_letters[] = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
linked_list *ident_list = NULL; /* master list of all items */
|
||||
|
||||
/*
|
||||
get_ident()
|
||||
|
||||
Gets the identifier for the given object. If an identifier exists, it is
|
||||
returned. If not, one is allocated and returned to the user. The
|
||||
identifier remains constant as long as the object is in the game.
|
||||
*/
|
||||
|
||||
int
|
||||
get_ident(struct object *obj_p)
|
||||
{
|
||||
int obj_type = obj_p->o_type;
|
||||
linked_list *list_p; /* pointer into ident_list */
|
||||
int new_id = 1; /* in case we have to allocate */
|
||||
struct object *tmp_obj_p;
|
||||
struct linked_list *new_place_p = NULL;
|
||||
|
||||
if (identifier(obj_p) != 0)
|
||||
return (identifier(obj_p));
|
||||
|
||||
/* no identifier - must allocate one */
|
||||
|
||||
for (list_p = ident_list; list_p != NULL; list_p = next(list_p))
|
||||
{
|
||||
tmp_obj_p = OBJPTR(list_p);
|
||||
|
||||
if (tmp_obj_p->o_type == obj_type)
|
||||
{
|
||||
if (identifier(tmp_obj_p) == new_id)
|
||||
{
|
||||
/* if this id is taken, try next */
|
||||
new_place_p = list_p;
|
||||
new_id++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we get here, the object is not in the list, and we need to add
|
||||
* it. The proper id is in new_id, and the place to put it is right
|
||||
* after new_place_p.
|
||||
*/
|
||||
|
||||
list_p = new_list();
|
||||
_attach_after(&ident_list, new_place_p, list_p);
|
||||
identifier(obj_p) = new_id;
|
||||
list_p->data.obj = obj_p;
|
||||
return(new_id);
|
||||
}
|
||||
|
||||
/*
|
||||
free_ident()
|
||||
|
||||
Frees up an identifier by removing the list entry that contains that item.
|
||||
If the item isn't found, nothing is done.
|
||||
*/
|
||||
|
||||
void
|
||||
free_ident(struct object *obj_p)
|
||||
{
|
||||
linked_list *list_p;
|
||||
|
||||
for (list_p = ident_list; list_p != NULL; list_p = next(list_p))
|
||||
{
|
||||
if (obj_p == OBJPTR(list_p))
|
||||
{
|
||||
_detach(&ident_list, list_p); /* unlink it from the list */
|
||||
ur_free(list_p); /* release link structure */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
unprint_id()
|
||||
|
||||
Converts a printable id from print_letters to the real thing by getting the
|
||||
index.
|
||||
*/
|
||||
|
||||
int
|
||||
unprint_id(char *print_id)
|
||||
{
|
||||
char *id_p;
|
||||
|
||||
for (id_p = print_letters; id_p != NULL; id_p++)
|
||||
if (*id_p == *print_id)
|
||||
break;
|
||||
|
||||
return( (int) (id_p - print_letters) );
|
||||
}
|
||||
|
||||
/*
|
||||
max_print()
|
||||
|
||||
returns the size of the print list
|
||||
*/
|
||||
|
||||
int
|
||||
max_print(void)
|
||||
{
|
||||
return(sizeof(print_letters) - 2); /* 1 for blank and 1 for EOS string */
|
||||
}
|
||||
1075
urogue/init.c
Normal file
1075
urogue/init.c
Normal file
File diff suppressed because it is too large
Load diff
471
urogue/io.c
Normal file
471
urogue/io.c
Normal file
|
|
@ -0,0 +1,471 @@
|
|||
/*
|
||||
io.c - Various input/output functions
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
Based on "Advanced Rogue"
|
||||
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
|
||||
All rights reserved.
|
||||
|
||||
Based on "Rogue: Exploring the Dungeons of Doom"
|
||||
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include "rogue.h"
|
||||
|
||||
char prbuf[2 * LINELEN]; /* Buffer for sprintfs */
|
||||
static char mbuf[2*LINELEN]; /* Current message buffer */
|
||||
static int newpos = 0; /* index in mbuf to end of msg */
|
||||
|
||||
int mpos = 0; /* 0 = Overwrite existing message */
|
||||
/* >0 = print --More-- at this pos */
|
||||
/* and wait for key */
|
||||
|
||||
int line_cnt = 0;
|
||||
int newpage = FALSE;
|
||||
|
||||
/*
|
||||
msg()
|
||||
Display a message at the top of the screen.
|
||||
*/
|
||||
|
||||
void
|
||||
msg(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
/* if the string is "", just clear the line */
|
||||
|
||||
if (*fmt == '\0')
|
||||
{
|
||||
wmove(cw, 0, 0);
|
||||
wclrtoeol(cw);
|
||||
mpos = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* otherwise add to the message and flush it out */
|
||||
|
||||
va_start(ap, fmt);
|
||||
doadd(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
endmsg();
|
||||
}
|
||||
|
||||
void
|
||||
vmsg(const char *fmt, va_list ap)
|
||||
{
|
||||
/* if the string is "", just clear the line */
|
||||
|
||||
if (*fmt == '\0')
|
||||
{
|
||||
wmove(cw, 0, 0);
|
||||
wclrtoeol(cw);
|
||||
mpos = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* otherwise add to the message and flush it out */
|
||||
|
||||
doadd(fmt, ap);
|
||||
endmsg();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
addmsg()
|
||||
add things to the current message
|
||||
*/
|
||||
|
||||
void
|
||||
addmsg(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
doadd(fmt,ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
endmsg()
|
||||
Display a new msg (giving him a chance to see the previous one
|
||||
if it is up there with the --More--)
|
||||
*/
|
||||
|
||||
void
|
||||
endmsg(void)
|
||||
{
|
||||
strcpy(msgbuf[msg_index], mbuf);
|
||||
|
||||
msg_index = ++msg_index % 10;
|
||||
|
||||
if (mpos)
|
||||
{
|
||||
wmove(cw, 0, mpos);
|
||||
wprintw(cw, (char *) morestr);
|
||||
wrefresh(cw);
|
||||
wait_for(' ');
|
||||
}
|
||||
|
||||
mvwprintw(cw, 0, 0, mbuf);
|
||||
wclrtoeol(cw);
|
||||
|
||||
mpos = newpos;
|
||||
newpos = 0;
|
||||
|
||||
wrefresh(cw);
|
||||
}
|
||||
|
||||
void
|
||||
doadd(const char *fmt, va_list ap)
|
||||
{
|
||||
vsprintf(&mbuf[newpos], fmt, ap);
|
||||
newpos = (int) strlen(mbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
status()
|
||||
Display the important stats line. Keep the cursor where it was.
|
||||
*/
|
||||
|
||||
void
|
||||
status(int display)
|
||||
{
|
||||
static char buf[1024]; /* Temporary buffer */
|
||||
struct stats *stat_ptr, *max_ptr;
|
||||
int oy, ox;
|
||||
|
||||
stat_ptr = &pstats;
|
||||
max_ptr = &max_stats;
|
||||
|
||||
getyx(cw, oy, ox);
|
||||
sprintf(buf,
|
||||
"Int:%d(%d) Str:%d(%d) Wis:%d(%d) Dex:%d(%d) Con:%d(%d) Carry:%d(%d) %d",
|
||||
stat_ptr->s_intel, max_ptr->s_intel,
|
||||
stat_ptr->s_str, max_ptr->s_str,
|
||||
stat_ptr->s_wisdom, max_ptr->s_wisdom,
|
||||
stat_ptr->s_dext, max_ptr->s_dext,
|
||||
stat_ptr->s_const, max_ptr->s_const,
|
||||
stat_ptr->s_pack / 10, stat_ptr->s_carry / 10, foodlev );
|
||||
|
||||
mvwaddstr(cw, LINES - 2, 0, buf);
|
||||
wclrtoeol(cw);
|
||||
|
||||
sprintf(buf, "Lvl:%d Au:%d Hpt:%3d(%3d) Pow:%d(%d) Ac:%d Exp:%d+%ld %s",
|
||||
level,
|
||||
purse,
|
||||
stat_ptr->s_hpt, max_ptr->s_hpt,
|
||||
stat_ptr->s_power, max_ptr->s_power,
|
||||
(cur_armor != NULL ? (cur_armor->o_ac - 10 + stat_ptr->s_arm)
|
||||
: stat_ptr->s_arm) - ring_value(R_PROTECT),
|
||||
stat_ptr->s_lvl,
|
||||
stat_ptr->s_exp,
|
||||
cnames[player.t_ctype][min(stat_ptr->s_lvl - 1, 14)]);
|
||||
|
||||
mvwaddstr(cw, LINES - 1, 0, buf);
|
||||
|
||||
switch(hungry_state)
|
||||
{
|
||||
case F_OK: break;
|
||||
case F_HUNGRY: waddstr(cw, " Hungry");
|
||||
break;
|
||||
case F_WEAK: waddstr(cw, " Weak");
|
||||
break;
|
||||
case F_FAINT: waddstr(cw, " Fainting");
|
||||
break;
|
||||
}
|
||||
|
||||
wclrtoeol(cw);
|
||||
wmove(cw, oy, ox);
|
||||
|
||||
if (display)
|
||||
wrefresh(cw);
|
||||
}
|
||||
|
||||
/*
|
||||
* readchar:
|
||||
* Flushes stdout so that screen is up to date and then returns
|
||||
* getchar().
|
||||
*/
|
||||
|
||||
char
|
||||
readcharw(WINDOW *win)
|
||||
{
|
||||
char ch;
|
||||
|
||||
ch = (char) md_readchar(win);
|
||||
|
||||
if ((ch == 3) || (ch == 0))
|
||||
{
|
||||
quit();
|
||||
return(27);
|
||||
}
|
||||
|
||||
return(ch);
|
||||
}
|
||||
|
||||
char
|
||||
readchar()
|
||||
{
|
||||
return( readcharw(cw) );
|
||||
}
|
||||
|
||||
/*
|
||||
wait_for()
|
||||
Sit around until the guy types the right key
|
||||
*/
|
||||
|
||||
void
|
||||
w_wait_for(WINDOW *w, int ch)
|
||||
{
|
||||
char c;
|
||||
|
||||
if (ch == '\n')
|
||||
while ((c = readcharw(w)) != '\n' && c != '\r')
|
||||
continue;
|
||||
else
|
||||
while (readcharw(w) != ch)
|
||||
continue;
|
||||
}
|
||||
|
||||
void
|
||||
wait_for(int ch)
|
||||
{
|
||||
w_wait_for(cw, ch);
|
||||
}
|
||||
|
||||
/*
|
||||
show_win()
|
||||
function used to display a window and wait before returning
|
||||
*/
|
||||
|
||||
void
|
||||
show_win(WINDOW *scr, char *message)
|
||||
{
|
||||
mvwaddstr(scr, 0, 0, message);
|
||||
touchwin(scr);
|
||||
wmove(scr, hero.y, hero.x);
|
||||
wrefresh(scr);
|
||||
wait_for(' ');
|
||||
clearok(cw, TRUE);
|
||||
touchwin(cw);
|
||||
}
|
||||
|
||||
/*
|
||||
restscr()
|
||||
Restores the screen to the terminal
|
||||
*/
|
||||
|
||||
void
|
||||
restscr(WINDOW *scr)
|
||||
{
|
||||
clearok(scr, TRUE);
|
||||
touchwin(scr);
|
||||
}
|
||||
|
||||
/*
|
||||
add_line()
|
||||
Add a line to the list of discoveries
|
||||
*/
|
||||
|
||||
void
|
||||
add_line(const char *fmt, ...)
|
||||
{
|
||||
WINDOW *tw;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
|
||||
if (line_cnt == 0)
|
||||
{
|
||||
wclear(hw);
|
||||
|
||||
if (inv_type == INV_SLOW)
|
||||
mpos = 0;
|
||||
}
|
||||
|
||||
if (inv_type == INV_SLOW)
|
||||
{
|
||||
if ( (fmt != NULL) && (*fmt != '\0') )
|
||||
vmsg(fmt, ap);
|
||||
line_cnt++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( (line_cnt >= LINES - 2) || (fmt == NULL)) /* end 'o page */
|
||||
{
|
||||
if (fmt == NULL && !newpage && inv_type == INV_OVER)
|
||||
{
|
||||
tw = newwin(line_cnt + 2, COLS, 0, 0);
|
||||
overwrite(hw, tw);
|
||||
wstandout(tw);
|
||||
mvwaddstr(tw, line_cnt, 0, spacemsg);
|
||||
wstandend(tw);
|
||||
touchwin(tw);
|
||||
wrefresh(tw);
|
||||
wait_for(' ');
|
||||
delwin(tw);
|
||||
touchwin(cw);
|
||||
}
|
||||
else
|
||||
{
|
||||
wstandout(hw);
|
||||
mvwaddstr(hw, LINES - 1, 0, spacemsg);
|
||||
wstandend(hw);
|
||||
wrefresh(hw);
|
||||
w_wait_for(hw, ' ');
|
||||
touchwin(cw);
|
||||
wclear(hw);
|
||||
}
|
||||
newpage = TRUE;
|
||||
line_cnt = 0;
|
||||
}
|
||||
|
||||
/* draw line */
|
||||
if (fmt != NULL && !(line_cnt == 0 && *fmt == '\0'))
|
||||
{
|
||||
static char tmpbuf[1024];
|
||||
|
||||
vsprintf(tmpbuf, fmt, ap);
|
||||
mvwprintw(hw, line_cnt++, 0, tmpbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
end_line()
|
||||
End the list of lines
|
||||
*/
|
||||
|
||||
void
|
||||
end_line(void)
|
||||
{
|
||||
if (inv_type != INV_SLOW)
|
||||
add_line(NULL);
|
||||
|
||||
line_cnt = 0;
|
||||
newpage = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
hearmsg()
|
||||
Call msg() only if you are not deaf
|
||||
*/
|
||||
|
||||
void
|
||||
hearmsg(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
|
||||
if (off(player, ISDEAF))
|
||||
vmsg(fmt, ap);
|
||||
else if (wizard)
|
||||
{
|
||||
msg("Couldn't hear: ");
|
||||
vmsg(fmt, ap);
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
seemsg()
|
||||
Call msg() only if you are not blind
|
||||
*/
|
||||
|
||||
void
|
||||
seemsg(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
|
||||
if (off(player, ISBLIND))
|
||||
vmsg(fmt, ap);
|
||||
else if (wizard)
|
||||
{
|
||||
msg("Couldn't see: ");
|
||||
vmsg(fmt, ap);
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
int
|
||||
get_string(char *buffer, WINDOW *win)
|
||||
{
|
||||
char *sp, c;
|
||||
int oy, ox;
|
||||
char buf[2 * LINELEN];
|
||||
|
||||
wrefresh(win);
|
||||
getyx(win, oy, ox);
|
||||
|
||||
/* loop reading in the string, and put it in a temporary buffer */
|
||||
|
||||
for (sp = buf; (c = readcharw(win)) != '\n' &&
|
||||
c != '\r' &&
|
||||
c != '\033' &&
|
||||
c != '\007' &&
|
||||
sp < &buf[LINELEN - 1];
|
||||
wclrtoeol(win), wrefresh(win))
|
||||
{
|
||||
if ((c == '\b') || (c == 0x7f))
|
||||
{
|
||||
if (sp > buf)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
sp--;
|
||||
|
||||
for (i = strlen(unctrl(*sp)); i; i--)
|
||||
waddch(win, '\b');
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (c == '\0')
|
||||
{
|
||||
sp = buf;
|
||||
wmove(win, oy, ox);
|
||||
continue;
|
||||
}
|
||||
else if (sp == buf && c == '-' && win == hw)
|
||||
break;
|
||||
|
||||
*sp++ = c;
|
||||
waddstr(win, unctrl(c));
|
||||
}
|
||||
|
||||
*sp = '\0';
|
||||
|
||||
if (sp > buf) /* only change option if something has been typed */
|
||||
strncpy(buffer, buf, strlen(buf)+1);
|
||||
|
||||
wmove(win, oy, ox);
|
||||
waddstr(win, buffer);
|
||||
waddch(win, '\n');
|
||||
wrefresh(win);
|
||||
|
||||
if (win == cw)
|
||||
mpos += (int)(sp - buf);
|
||||
|
||||
if (c == '-')
|
||||
return(MINUS);
|
||||
else if (c == '\033' || c == '\007')
|
||||
return(QUIT);
|
||||
else
|
||||
return(NORM);
|
||||
}
|
||||
|
||||
69
urogue/lint-curses.h
Normal file
69
urogue/lint-curses.h
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
lint-curses.h
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
|
||||
/* Sufficient info to pass lint */
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
#define getyx(win,y,x) y = win->_cury, x = win->_curx
|
||||
struct screen { int opque_data_type; };
|
||||
typedef struct { int _cury; int _curx; } WINDOW;
|
||||
extern WINDOW *stdscr;
|
||||
extern WINDOW *curscr;
|
||||
extern int LINES;
|
||||
extern int COLS;
|
||||
extern char *unctrl(char c);
|
||||
extern void initscr(void);
|
||||
extern int wmove(WINDOW *window, int Line, int Column);
|
||||
extern int move(int Line, int Column);
|
||||
extern int addch(char c);
|
||||
extern int mvaddch(int y, int x, char c);
|
||||
extern int waddch(WINDOW *window, char c);
|
||||
extern int mvwaddch(WINDOW *window, int y, int x, char c);
|
||||
extern int mvwinch(WINDOW *window, int y, int x);
|
||||
extern int winch(WINDOW *window);
|
||||
extern int mvinch(int y, int x);
|
||||
extern int getch(void);
|
||||
extern int wgetch(WINDOW *window);
|
||||
extern void clear(void);
|
||||
extern void wclear(WINDOW *window);
|
||||
extern void refresh(void);
|
||||
extern void wrefresh(WINDOW *window);
|
||||
extern void clearok(WINDOW *window, int flag);
|
||||
extern void endwin(void);
|
||||
extern void touchwin(WINDOW *window);
|
||||
extern void overlay(WINDOW *w1, WINDOW *w2);
|
||||
extern void wclrtoeol(WINDOW *window);
|
||||
extern void wprintw(WINDOW *window, const char *fmt, ...);
|
||||
extern void mvprintw(int line, int col, char *fmt, ...);
|
||||
extern void mvwprintw(WINDOW *window, int line, int col, char *fmt, ...);
|
||||
extern int mvwaddstr(WINDOW *window, int y, int x, const char *str);
|
||||
extern int mvaddstr(int y, int x, char *str);
|
||||
extern int waddstr(WINDOW *window, char *str);
|
||||
extern int addstr(char *str);
|
||||
extern void standout(void);
|
||||
extern void wstandout(WINDOW *window);
|
||||
extern void standend(void);
|
||||
extern void wstandend(WINDOW *window);
|
||||
extern void noecho(void);
|
||||
extern void cbreak(void);
|
||||
extern void crmode(void);
|
||||
extern void nonl(void);
|
||||
extern void nl(void);
|
||||
extern int wgetch(WINDOW *window);
|
||||
extern WINDOW *newwin(int lines, int cols, int y, int x);
|
||||
extern void overwrite(WINDOW *w1, WINDOW *w2);
|
||||
extern void delwin(WINDOW *window);
|
||||
extern void printw(char *fmt, ...);
|
||||
|
||||
222
urogue/list.c
Normal file
222
urogue/list.c
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
list.c - Functions for dealing with linked lists of goodies
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
Based on "Advanced Rogue"
|
||||
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
|
||||
All rights reserved.
|
||||
|
||||
Based on "Rogue: Exploring the Dungeons of Doom"
|
||||
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "rogue.h"
|
||||
|
||||
static char errbuf[2 * LINELEN];
|
||||
|
||||
/*
|
||||
ur_alloc()
|
||||
ur_free()
|
||||
|
||||
These are just calls to the system alloc and free, and they also adjust
|
||||
the totals. The buffer is cleared out because idents need to be zero
|
||||
before going into the pack, or they will be used as indices!
|
||||
*/
|
||||
|
||||
void *
|
||||
ur_alloc(size_t size)
|
||||
{
|
||||
char *buf_p;
|
||||
|
||||
total++;
|
||||
|
||||
buf_p = mem_malloc(size);
|
||||
|
||||
if (buf_p == NULL)
|
||||
return(NULL);
|
||||
|
||||
memset(buf_p,0,size);
|
||||
|
||||
return(buf_p);
|
||||
}
|
||||
|
||||
void
|
||||
ur_free(void *buf_p)
|
||||
{
|
||||
mem_free(buf_p);
|
||||
total--;
|
||||
}
|
||||
|
||||
/*
|
||||
detach()
|
||||
Takes an item out of whatever linked list it might be in
|
||||
.... function needs to be renamed....
|
||||
*/
|
||||
|
||||
void
|
||||
_detach(struct linked_list **list, struct linked_list *item)
|
||||
{
|
||||
if (*list == item)
|
||||
*list = next(item);
|
||||
|
||||
if (prev(item) != NULL)
|
||||
item->l_prev->l_next = next(item);
|
||||
|
||||
if (next(item) != NULL)
|
||||
item->l_next->l_prev = prev(item);
|
||||
|
||||
item->l_next = NULL;
|
||||
item->l_prev = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
_attach()
|
||||
add an item to the head of a list
|
||||
... this needs to be renamed as well ...
|
||||
*/
|
||||
|
||||
void
|
||||
_attach(struct linked_list **list, struct linked_list *item)
|
||||
{
|
||||
if (*list != NULL)
|
||||
{
|
||||
item->l_next = *list;
|
||||
(*list)->l_prev = item;
|
||||
item->l_prev = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->l_next = NULL;
|
||||
item->l_prev = NULL;
|
||||
}
|
||||
|
||||
*list = item;
|
||||
}
|
||||
|
||||
/*
|
||||
_attach_after()
|
||||
|
||||
Attaches the given item after the supplied one in the list. If the listed
|
||||
item is NULL, the new item is attached at the head of the list.
|
||||
*/
|
||||
|
||||
void
|
||||
_attach_after(linked_list **list_pp, linked_list *list_p, linked_list *new_p)
|
||||
{
|
||||
if (list_p == NULL)
|
||||
{
|
||||
_attach(list_pp, new_p); /* stuff it at the beginning */
|
||||
return;
|
||||
}
|
||||
|
||||
if (next(list_p) != NULL) /* something after this one? */
|
||||
{
|
||||
new_p->l_next = next(list_p);
|
||||
list_p->l_next->l_prev = new_p;
|
||||
}
|
||||
else
|
||||
new_p->l_next = NULL;
|
||||
|
||||
list_p->l_next = new_p;
|
||||
new_p->l_prev = list_p;
|
||||
}
|
||||
|
||||
/*
|
||||
_free_list()
|
||||
Throw the whole blamed thing away
|
||||
*/
|
||||
|
||||
void
|
||||
_free_list(linked_list **ptr)
|
||||
{
|
||||
linked_list *item;
|
||||
|
||||
while(*ptr != NULL)
|
||||
{
|
||||
item = *ptr;
|
||||
*ptr = next(item);
|
||||
discard(item);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
discard()
|
||||
free up an item
|
||||
*/
|
||||
|
||||
void
|
||||
discard(struct linked_list *item)
|
||||
{
|
||||
throw_away(item->data.obj);
|
||||
ur_free(item);
|
||||
}
|
||||
|
||||
/*
|
||||
throw_away()
|
||||
toss out something (like discard, but without the link_list)
|
||||
*/
|
||||
|
||||
void
|
||||
throw_away(struct object *ptr)
|
||||
{
|
||||
free_ident(ptr);
|
||||
ur_free(ptr);
|
||||
}
|
||||
|
||||
/*
|
||||
new_item()
|
||||
get a new item with a specified size
|
||||
*/
|
||||
|
||||
struct linked_list *
|
||||
new_item(int size)
|
||||
{
|
||||
struct linked_list *item;
|
||||
|
||||
if ((item = new_list()) == NULL)
|
||||
msg("Ran out of memory for header after %d items.", total);
|
||||
|
||||
if ((item->data.l_data = new_alloc(size)) == NULL)
|
||||
msg("Ran out of memory for data after %d items.", total);
|
||||
|
||||
item->l_next = item->l_prev = NULL;
|
||||
|
||||
return(item);
|
||||
}
|
||||
|
||||
void *
|
||||
new_alloc(size_t size)
|
||||
{
|
||||
void *space = ur_alloc(size);
|
||||
|
||||
if (space == NULL)
|
||||
{
|
||||
sprintf(errbuf, "Rogue ran out of memory.");
|
||||
fatal(errbuf);
|
||||
}
|
||||
|
||||
return(space);
|
||||
}
|
||||
|
||||
struct linked_list *
|
||||
new_list(void)
|
||||
{
|
||||
union /* ugly_lint_hack */
|
||||
{
|
||||
struct linked_list *ll;
|
||||
void *vptr;
|
||||
} newp;
|
||||
|
||||
newp.vptr = mem_malloc(sizeof(struct linked_list));
|
||||
memset(newp.vptr,0,sizeof(struct linked_list));
|
||||
return(newp.ll);
|
||||
}
|
||||
878
urogue/magic.c
Normal file
878
urogue/magic.c
Normal file
|
|
@ -0,0 +1,878 @@
|
|||
/*
|
||||
magic.c - This file contains functions for casting magic spells
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
Based on "Advanced Rogue"
|
||||
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
|
||||
All rights reserved.
|
||||
|
||||
Based on "Rogue: Exploring the Dungeons of Doom"
|
||||
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
Cost for each level of spells level:
|
||||
*/
|
||||
|
||||
static const int spell_cost[] = {1, 5, 17, 29, 53, 91, 159, 247, 396};
|
||||
|
||||
static struct spells monst_spells[] =
|
||||
{
|
||||
{5, S_SELFTELEP, SCR_MAGIC},
|
||||
{4, P_HEALING, POT_MAGIC | _TWO_},
|
||||
{3, P_REGENERATE, POT_MAGIC},
|
||||
{2, P_HEALING, POT_MAGIC},
|
||||
{4, P_HASTE, POT_MAGIC},
|
||||
{2, P_SEEINVIS, POT_MAGIC},
|
||||
{3, P_SHERO, POT_MAGIC},
|
||||
{5, P_PHASE, POT_MAGIC},
|
||||
{4, P_INVIS, POT_MAGIC},
|
||||
{4, WS_CANCEL, ZAP_MAGIC},
|
||||
|
||||
/* In reverse order of damage ability */
|
||||
{6, WS_ELECT, ZAP_MAGIC | _TWO_},
|
||||
{6, WS_FIRE, ZAP_MAGIC | _TWO_},
|
||||
{6, WS_COLD, ZAP_MAGIC | _TWO_},
|
||||
{6, WS_MISSILE, ZAP_MAGIC | _TWO_},
|
||||
{5, WS_ELECT, ZAP_MAGIC},
|
||||
{5, WS_FIRE, ZAP_MAGIC},
|
||||
{5, WS_COLD, ZAP_MAGIC},
|
||||
{4, WS_ELECT, ZAP_MAGIC | ISCURSED},
|
||||
{4, WS_FIRE, ZAP_MAGIC | ISCURSED},
|
||||
{4, WS_COLD, ZAP_MAGIC | ISCURSED},
|
||||
{3, WS_MISSILE, ZAP_MAGIC},
|
||||
{1, WS_MISSILE, ZAP_MAGIC | ISCURSED},
|
||||
|
||||
{-1, -1, 0}
|
||||
};
|
||||
|
||||
/*
|
||||
Spells that a player can cast Non-mus only know ISKNOW spells until found
|
||||
in the dungeon. Special classes know their spells one level lower, and
|
||||
blessed one above.
|
||||
*/
|
||||
|
||||
static struct spells player_spells[] =
|
||||
{
|
||||
{1, WS_KNOCK, ZAP_MAGIC | ISKNOW},
|
||||
{1, S_SUMFAMILIAR, SCR_MAGIC | SP_DRUID | SP_MAGIC | SP_CLERIC, SP_ILLUSION },
|
||||
{1, S_GFIND, SCR_MAGIC | ISKNOW},
|
||||
{1, P_MONSTDET, POT_MAGIC | ISKNOW | SP_DRUID},
|
||||
{1, P_TREASDET, POT_MAGIC | ISKNOW | SP_MAGIC},
|
||||
{1, S_FOODDET, SCR_MAGIC | ISKNOW | SP_CLERIC},
|
||||
{1, S_LIGHT, SCR_MAGIC | ISKNOW | SP_ILLUSION},
|
||||
|
||||
{2, WS_CLOSE, ZAP_MAGIC | ISKNOW},
|
||||
{2, S_IDENTIFY, SCR_MAGIC | ISKNOW},
|
||||
{2, WS_HIT, ZAP_MAGIC | ISKNOW | SP_PRAYER},
|
||||
{2, P_SHIELD, POT_MAGIC | ISKNOW | SP_MAGIC},
|
||||
{2, P_COLDRESIST, POT_MAGIC | SP_WIZARD},
|
||||
{2, P_SEEINVIS, POT_MAGIC | SP_ILLUSION},
|
||||
{2, S_CONFUSE, SCR_MAGIC | SP_CLERIC},
|
||||
{2, P_SMELL, POT_MAGIC | SP_DRUID},
|
||||
{2, WS_MISSILE, ZAP_MAGIC | SP_MAGIC},
|
||||
{2, P_HEAR, POT_MAGIC},
|
||||
|
||||
{3, P_CLEAR, POT_MAGIC | ISKNOW},
|
||||
{3, P_HEALING, POT_MAGIC | ISKNOW | SP_PRAYER},
|
||||
{3, S_CURING, SCR_MAGIC | ISKNOW | SP_PRAYER},
|
||||
{3, WS_MONSTELEP, ZAP_MAGIC | SP_MAGIC},
|
||||
{3, WS_CANCEL, ZAP_MAGIC | SP_WIZARD},
|
||||
{3, S_SELFTELEP, SCR_MAGIC | SP_WIZARD},
|
||||
{3, P_FIRERESIST, POT_MAGIC | SP_WIZARD | SP_DRUID},
|
||||
{3, S_MAP, SCR_MAGIC | SP_ILLUSION | SP_DRUID},
|
||||
{3, S_REMOVECURSE, SCR_MAGIC | SP_PRAYER},
|
||||
{3, S_HOLD, SCR_MAGIC | SP_CLERIC},
|
||||
{3, S_SLEEP, SCR_MAGIC | SP_DRUID},
|
||||
{3, P_HASOXYGEN, POT_MAGIC | SP_DRUID},
|
||||
{3, WS_XENOHEALING, ZAP_MAGIC | SP_DRUID},
|
||||
{3, P_RESTORE, POT_MAGIC},
|
||||
|
||||
{4, S_MSHIELD, SCR_MAGIC | ISKNOW | SP_ILLUSION},
|
||||
{4, P_INVIS, POT_MAGIC | SP_ILLUSION},
|
||||
{4, S_REFLECT, SCR_MAGIC | SP_ILLUSION},
|
||||
{4, P_TRUESEE, POT_MAGIC | SP_ILLUSION},
|
||||
{4, P_REGENERATE, POT_MAGIC | SP_CLERIC},
|
||||
{4, WS_DRAIN, ZAP_MAGIC | SP_CLERIC},
|
||||
{4, P_HASTE, POT_MAGIC | SP_ILLUSION | SP_CLERIC},
|
||||
{4, P_LEVITATION, POT_MAGIC | SP_WIZARD | SP_DRUID},
|
||||
{4, WS_WEB, ZAP_MAGIC | SP_MAGIC},
|
||||
{4, P_PHASE, POT_MAGIC},
|
||||
|
||||
{5, P_SHERO, POT_MAGIC | ISKNOW},
|
||||
{5, S_PETRIFY, SCR_MAGIC | SP_MAGIC},
|
||||
{5, S_SCARE, SCR_MAGIC | _TWO_ | SP_PRAYER},
|
||||
{5, WS_COLD, ZAP_MAGIC | SP_DRUID},
|
||||
{5, WS_FIRE, ZAP_MAGIC | SP_CLERIC},
|
||||
{5, WS_ELECT, ZAP_MAGIC | SP_WIZARD},
|
||||
{5, WS_ANTIMATTER, ZAP_MAGIC | SP_ILLUSION},
|
||||
{5, S_ELECTRIFY, SCR_MAGIC | SP_ILLUSION},
|
||||
|
||||
{6, WS_DISINTEGRATE, ZAP_MAGIC | ISKNOW},
|
||||
{6, S_OWNERSHIP, SCR_MAGIC | SP_ALL},
|
||||
|
||||
{7, S_ENCHANT, SCR_MAGIC | SP_MAGIC},
|
||||
|
||||
{-1, -1, 0}
|
||||
};
|
||||
|
||||
/*
|
||||
incant()
|
||||
Cast a spell
|
||||
*/
|
||||
|
||||
void
|
||||
incant(struct thing *caster, coord dir)
|
||||
{
|
||||
int i;
|
||||
struct stats *curp;
|
||||
struct stats *maxp;
|
||||
int is_player = (caster == &player);
|
||||
int points_casters;
|
||||
char *casters_name = (on(player, ISBLIND)) ? "it" :
|
||||
monsters[caster->t_index].m_name;
|
||||
struct spells *sp;
|
||||
char *cast_name; /* = spell_name(sp) */
|
||||
char *spell_type; /* spell or prayer */
|
||||
int casting_cost; /* from spell_cost[] */
|
||||
int spell_roll; /* sucess/fail 1D100 die roll */
|
||||
int fumble_chance; /* Spell fumble chance */
|
||||
int num_fumbles = 0; /* for fumble_spell() */
|
||||
int bless_or_curse = ISNORMAL; /* blessed or cursed? */
|
||||
int message_flags = CAST_NORMAL; /* which message to print out */
|
||||
int class_casters; /* For determining ISKNOW */
|
||||
int stat_casters; /* s_intel or s_wisdom */
|
||||
int level_casters; /* spellcasting level */
|
||||
char buf[2 * LINELEN];
|
||||
struct spells sorted_spells[MAX_SPELLS];
|
||||
char spellbuf[2 * LINELEN];
|
||||
char spellbuf2[2 * LINELEN];
|
||||
|
||||
curp = &(caster->t_stats);
|
||||
maxp = &(caster->maxstats);
|
||||
points_casters = curp->s_power;
|
||||
|
||||
if (points_casters <= 0)
|
||||
{
|
||||
if (is_player)
|
||||
msg("You don't have any spell points.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Paladins, Rangers, ringwearers, and monsters cast at 4 levels
|
||||
* below. Other non-specialists at 8 below
|
||||
*/
|
||||
|
||||
level_casters = curp->s_lvl;
|
||||
|
||||
switch (caster->t_ctype)
|
||||
{
|
||||
case C_PALADIN:
|
||||
level_casters -= 4;
|
||||
/* fallthrough */
|
||||
case C_CLERIC:
|
||||
class_casters = SP_CLERIC;
|
||||
stat_casters = curp->s_wisdom;
|
||||
break;
|
||||
case C_RANGER:
|
||||
level_casters -= 4;
|
||||
/* fallthrough */
|
||||
case C_DRUID:
|
||||
class_casters = SP_DRUID;
|
||||
stat_casters = curp->s_wisdom;
|
||||
break;
|
||||
case C_MAGICIAN:
|
||||
class_casters = SP_WIZARD;
|
||||
stat_casters = curp->s_intel;
|
||||
break;
|
||||
case C_ILLUSION:
|
||||
class_casters = SP_ILLUSION;
|
||||
stat_casters = curp->s_intel;
|
||||
break;
|
||||
case C_MONSTER:
|
||||
if (off(*caster, ISUNIQUE))
|
||||
level_casters -= 4;
|
||||
class_casters = 0x0;
|
||||
stat_casters = curp->s_intel;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (is_wearing(R_WIZARD))
|
||||
{
|
||||
level_casters -= 4;
|
||||
class_casters = (rnd(4) ? SP_WIZARD : SP_ILLUSION);
|
||||
stat_casters = curp->s_intel;
|
||||
}
|
||||
else if (is_wearing(R_PIETY))
|
||||
{
|
||||
level_casters -= 4;
|
||||
class_casters = (rnd(4) ? SP_CLERIC : SP_DRUID);
|
||||
stat_casters = curp->s_wisdom;
|
||||
}
|
||||
else
|
||||
{
|
||||
level_casters -= 8;
|
||||
class_casters = 0x0;
|
||||
stat_casters = (rnd(2) ? curp->s_wisdom : curp->s_intel);
|
||||
}
|
||||
}
|
||||
|
||||
/* Bug - What about when WIS == INT? */
|
||||
|
||||
spell_type = (stat_casters == curp->s_intel) ? "spell" : "prayer";
|
||||
|
||||
if (!is_player && (sp = pick_monster_spell(caster)) == NULL)
|
||||
return;
|
||||
else if (is_player)
|
||||
{
|
||||
int num_spells = -1; /* num of spells cheap enough */
|
||||
|
||||
sorted_spells[0].sp_cost = -1;
|
||||
|
||||
for (sp = player_spells; sp->sp_level != -1; sp++)
|
||||
{
|
||||
if (sp->sp_flags & class_casters) /* Does class know spell? */
|
||||
{
|
||||
int rnd_number = rnd(2 * sp->sp_level) - sp->sp_level;
|
||||
|
||||
/* Knows normal spell one level below others */
|
||||
|
||||
casting_cost = spell_cost[sp->sp_level - 1] + rnd_number;
|
||||
|
||||
if (points_casters >= casting_cost)
|
||||
{
|
||||
sorted_spells[++num_spells] = *sp;
|
||||
sorted_spells[num_spells].sp_cost = casting_cost;
|
||||
sorted_spells[num_spells].sp_level = sp->sp_level - 1;
|
||||
}
|
||||
|
||||
/* Knows blessed spell one level above others */
|
||||
|
||||
casting_cost = spell_cost[sp->sp_level + 1] + rnd_number;
|
||||
|
||||
if (points_casters >= casting_cost)
|
||||
{
|
||||
sorted_spells[++num_spells] = *sp;
|
||||
sorted_spells[num_spells].sp_level = sp->sp_level + 1;
|
||||
sorted_spells[num_spells].sp_cost = casting_cost;
|
||||
sorted_spells[num_spells].sp_flags |= ISBLESSED;
|
||||
}
|
||||
} /* If class doesn't know spell, see if its a ISKNOW */
|
||||
else if (sp->sp_flags & ISKNOW)
|
||||
{
|
||||
int rnd_number = rnd(4 * sp->sp_level) - sp->sp_level;
|
||||
|
||||
casting_cost = spell_cost[sp->sp_level] + rnd_number;
|
||||
|
||||
if (points_casters >= casting_cost)
|
||||
{
|
||||
sorted_spells[++num_spells] = *sp;
|
||||
sorted_spells[num_spells].sp_cost = casting_cost;
|
||||
}
|
||||
}
|
||||
/* else this spell is unknown */
|
||||
}
|
||||
|
||||
if (sorted_spells[0].sp_cost == -1)
|
||||
{
|
||||
msg("You don't have enough %s points.", spell_type);
|
||||
after = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
qsort(sorted_spells,num_spells + 1,sizeof(struct spells),sort_spells);
|
||||
|
||||
do /* Prompt for spells */
|
||||
{
|
||||
struct spells *which_spell = NULL;
|
||||
|
||||
buf[0] = '\0';
|
||||
msg("");/* Get rid of --More-- */
|
||||
msg("Which %s are you casting [%d points left] (* for list)? ",
|
||||
spell_type, points_casters);
|
||||
|
||||
switch(get_string(buf, cw))
|
||||
{
|
||||
case NORM: break;
|
||||
case QUIT: return; /* ESC - lose turn */
|
||||
default: continue;
|
||||
}
|
||||
|
||||
if (buf[0] == '*') /* print list */
|
||||
{
|
||||
add_line("Cost Abbreviation Full Name");
|
||||
|
||||
for (i = 0; i <= num_spells; i++)
|
||||
{
|
||||
sp = &sorted_spells[i];
|
||||
sprintf(buf, "[%3d] %-12s\t%s",
|
||||
sp->sp_cost, spell_abrev(sp,spellbuf2),
|
||||
spell_name(sp,spellbuf));
|
||||
add_line(buf);
|
||||
}
|
||||
end_line();
|
||||
sp = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isupper(buf[0])) /* Uppercase Abbreviation */
|
||||
{
|
||||
for (i = 0; i <= num_spells; i++)
|
||||
{
|
||||
sp = &sorted_spells[i];
|
||||
|
||||
if ((strcmp(spell_abrev(sp,spellbuf2), buf) == 0))
|
||||
{
|
||||
which_spell = sp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* Full Spell Name */
|
||||
{
|
||||
for (i = 0; i <= num_spells; i++)
|
||||
{
|
||||
sp = &sorted_spells[i];
|
||||
|
||||
if ((strcmp(spell_name(sp,spellbuf), buf) == 0))
|
||||
{
|
||||
which_spell = sp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sp = which_spell;
|
||||
}
|
||||
while (sp == NULL);
|
||||
}
|
||||
|
||||
/* Common monster and player code */
|
||||
|
||||
cast_name = spell_name(sp,spellbuf);
|
||||
|
||||
fumble_chance = (10 * sp->sp_level / 4 - 10 * level_casters / 13) * 5;
|
||||
|
||||
if (cur_weapon != NULL && wield_ok(caster, cur_weapon, FALSE) == FALSE)
|
||||
{
|
||||
switch (caster->t_ctype)
|
||||
{
|
||||
case C_MAGICIAN:
|
||||
case C_ILLUSION:
|
||||
msg("You should have both hands free.");
|
||||
fumble_chance += rnd(level_casters) * 5;
|
||||
break;
|
||||
|
||||
case C_CLERIC:
|
||||
case C_DRUID:
|
||||
case C_PALADIN:
|
||||
msg("Your god looks askance at the weapon you wield.");
|
||||
fumble_chance += rnd(level_casters) * 5;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fumble_chance >= MAX_FUMBLE_CHANCE)
|
||||
fumble_chance = MAX_FUMBLE_CHANCE;
|
||||
else if (fumble_chance <= MIN_FUMBLE_CHANCE + sp->sp_level)
|
||||
fumble_chance = MIN_FUMBLE_CHANCE + sp->sp_level;
|
||||
|
||||
if (fumble_chance > (30 + rnd(50)))
|
||||
{
|
||||
if (is_player)
|
||||
{
|
||||
int answer;
|
||||
|
||||
msg("Are you sure you want to try for that hard a %s? [n]",
|
||||
spell_type);
|
||||
|
||||
answer = readchar();
|
||||
|
||||
if (tolower(answer) != 'y')
|
||||
{
|
||||
after = FALSE;
|
||||
return;
|
||||
}
|
||||
else
|
||||
msg("Here goes...");
|
||||
}
|
||||
else /* Only if the monster is desperate */
|
||||
{
|
||||
if (curp->s_hpt > maxp->s_hpt / 2)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* casting costs food energy */
|
||||
|
||||
food_left -= sp->sp_cost;
|
||||
|
||||
spell_roll = rnd(100);
|
||||
|
||||
debug("%s(%d) cast '%s' fumble %%%d (rolled %d) ",
|
||||
monsters[caster->t_index].m_name, curp->s_power, cast_name,
|
||||
fumble_chance, spell_roll);
|
||||
|
||||
caster->t_rest_hpt = caster->t_rest_pow = 0;
|
||||
|
||||
if (!is_player) /* Stop running. */
|
||||
{
|
||||
running = FALSE;
|
||||
msg("The %s is casting '%s'.", casters_name, cast_name);
|
||||
}
|
||||
|
||||
/* The Crown of Might insures that your spells never fumble */
|
||||
|
||||
if (spell_roll < fumble_chance)
|
||||
{
|
||||
if (is_carrying(TR_CROWN))
|
||||
message_flags |= CAST_CROWN;
|
||||
else
|
||||
{
|
||||
message_flags |= CAST_CURSED;
|
||||
|
||||
curp->s_power -= min(curp->s_power,
|
||||
(2 * sp->sp_cost)); /* 2x cost */
|
||||
num_fumbles = rnd(((fumble_chance - spell_roll) / 10)
|
||||
+ 1) + rnd(sp->sp_level) + rnd(curp->s_lvl);
|
||||
num_fumbles = min(10, max(0, num_fumbles));
|
||||
|
||||
if (num_fumbles >= 6 && rnd(1) == 0)
|
||||
bless_or_curse = ISCURSED;
|
||||
else if (num_fumbles < 4)
|
||||
{
|
||||
if (is_player)
|
||||
msg("Your %s fails.", spell_type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (spell_roll > MAX_FUMBLE_CHANCE)
|
||||
{
|
||||
if (is_player)
|
||||
{
|
||||
message_flags |= CAST_BLESSED;
|
||||
pstats.s_exp += 3 * sp->sp_cost * curp->s_lvl;
|
||||
check_level();
|
||||
}
|
||||
|
||||
maxp->s_power += sp->sp_cost;
|
||||
bless_or_curse = ISBLESSED;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_player) /* extra exp for sucessful spells */
|
||||
{
|
||||
if (player.t_ctype == C_MAGICIAN || player.t_ctype == C_ILLUSION)
|
||||
{
|
||||
pstats.s_exp += sp->sp_cost * curp->s_lvl;
|
||||
check_level();
|
||||
}
|
||||
}
|
||||
|
||||
bless_or_curse = sp->sp_flags & ISBLESSED;
|
||||
curp->s_power -= sp->sp_cost;
|
||||
}
|
||||
|
||||
/* The Sceptre of Might blesses all your spells */
|
||||
|
||||
if (is_player && ((bless_or_curse & ISBLESSED) == 0) &&
|
||||
is_carrying(TR_SCEPTRE))
|
||||
{
|
||||
message_flags |= CAST_SEPTRE;
|
||||
bless_or_curse = ISBLESSED;
|
||||
}
|
||||
|
||||
if (sp->sp_flags & POT_MAGIC)
|
||||
quaff(caster, sp->sp_which, bless_or_curse);
|
||||
else if (sp->sp_flags & SCR_MAGIC)
|
||||
read_scroll(caster, sp->sp_which, bless_or_curse);
|
||||
else if (sp->sp_flags & ZAP_MAGIC)
|
||||
{
|
||||
if (is_player)
|
||||
{
|
||||
do /* Must pick a direction */
|
||||
{
|
||||
msg("Which direction?");
|
||||
}
|
||||
while (get_dir() == FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
delta.x = dir.x;
|
||||
delta.y = dir.y;
|
||||
}
|
||||
do_zap(caster, sp->sp_which, bless_or_curse);
|
||||
}
|
||||
else
|
||||
msg("What a strange %s!", spell_type);
|
||||
|
||||
/*
|
||||
* Print messages and take fumbles *after* spell has gone off. This
|
||||
* makes ENCHANT, etc more dangerous
|
||||
*/
|
||||
|
||||
if (is_player)
|
||||
{
|
||||
if (message_flags & CAST_SEPTRE)
|
||||
msg("The Sceptre enhanced your %s.", spell_type);
|
||||
if (message_flags & CAST_CROWN)
|
||||
msg("The Crown wordlessly corrected your %s.",
|
||||
spell_type);
|
||||
|
||||
switch (message_flags & 0x1)
|
||||
{
|
||||
case CAST_CURSED:
|
||||
msg("You botched your '%s' %s.", cast_name,
|
||||
spell_type);
|
||||
fumble_spell(caster, num_fumbles);
|
||||
break;
|
||||
case CAST_NORMAL:
|
||||
msg("You sucessfully cast your '%s' %s.",
|
||||
cast_name, spell_type);
|
||||
break;
|
||||
|
||||
case CAST_BLESSED:
|
||||
msg("Your '%s' %s went superbly.", cast_name,
|
||||
spell_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
spell_name()
|
||||
returns pointer to spell name
|
||||
*/
|
||||
|
||||
char *
|
||||
spell_name(struct spells *sp, char *buf)
|
||||
{
|
||||
if (buf == NULL)
|
||||
return("UltraRogue Bug #105");
|
||||
|
||||
if (sp->sp_flags & POT_MAGIC)
|
||||
strcpy(buf, p_magic[sp->sp_which].mi_name);
|
||||
else if (sp->sp_flags & SCR_MAGIC)
|
||||
strcpy(buf, s_magic[sp->sp_which].mi_name);
|
||||
else if (sp->sp_flags & ZAP_MAGIC)
|
||||
strcpy(buf, ws_magic[sp->sp_which].mi_name);
|
||||
else
|
||||
strcpy(buf, "unknown spell type");
|
||||
|
||||
if (sp->sp_flags & ISBLESSED)
|
||||
strcat(buf, " 2");
|
||||
|
||||
return(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
spell_abrev()
|
||||
returns pointer to capital letter spell abbreviation
|
||||
*/
|
||||
|
||||
char *
|
||||
spell_abrev(struct spells *sp, char *buf)
|
||||
{
|
||||
if (buf == NULL)
|
||||
return("UltraRogue Bug #106");
|
||||
|
||||
if (sp->sp_flags & POT_MAGIC)
|
||||
strcpy(buf, p_magic[sp->sp_which].mi_abrev);
|
||||
else if (sp->sp_flags & SCR_MAGIC)
|
||||
strcpy(buf, s_magic[sp->sp_which].mi_abrev);
|
||||
else if (sp->sp_flags & ZAP_MAGIC)
|
||||
strcpy(buf, ws_magic[sp->sp_which].mi_abrev);
|
||||
else
|
||||
strcpy(buf, "?????");
|
||||
|
||||
if (sp->sp_flags & ISBLESSED)
|
||||
strcat(buf, " 2");
|
||||
|
||||
return(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
fumble_spell()
|
||||
he blew it. Make him pay
|
||||
*/
|
||||
|
||||
void
|
||||
fumble_spell(struct thing *caster, int num_fumbles)
|
||||
{
|
||||
struct stats *curp = &(caster->t_stats);
|
||||
struct stats *maxp = &(caster->maxstats);
|
||||
int is_player = (caster == &player);
|
||||
|
||||
debug("Taking %d fumbles.", num_fumbles);
|
||||
|
||||
switch (num_fumbles)
|
||||
{
|
||||
case 10: /* Lose ability */
|
||||
if (rnd(5) == 0)
|
||||
quaff(caster, P_GAINABIL, ISCURSED);
|
||||
break;
|
||||
|
||||
case 9: /* Lose max spell points */
|
||||
|
||||
if (rnd(4) == 0)
|
||||
{
|
||||
maxp->s_power -= rnd(10);
|
||||
|
||||
if (maxp->s_power <= 5)
|
||||
maxp->s_power = 5;
|
||||
}
|
||||
break;
|
||||
|
||||
case 8: /* Lose all current spell points */
|
||||
|
||||
if (rnd(3) == 0)
|
||||
curp->s_power = 0;
|
||||
else
|
||||
curp->s_power /= 2;
|
||||
break;
|
||||
|
||||
case 7: /* Freeze */
|
||||
|
||||
if (rnd(2) == 0)
|
||||
{
|
||||
if (is_player)
|
||||
no_command++;
|
||||
else
|
||||
caster->t_no_move++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 6: /* Cast a cursed spell - see below */
|
||||
break;
|
||||
|
||||
case 5: /* Become dazed and confused */
|
||||
|
||||
if (rnd(5) == 0)
|
||||
quaff(caster, P_CLEAR, ISCURSED);
|
||||
break;
|
||||
|
||||
case 4: /* Lose hit points */
|
||||
|
||||
if (is_player)
|
||||
feel_message();
|
||||
if ((curp->s_hpt -= rnd(10)) <= 0)
|
||||
{
|
||||
if (is_player)
|
||||
death(D_SPELLFUMBLE);
|
||||
else
|
||||
killed(caster, find_mons(caster->t_pos.y, caster->t_pos.x),
|
||||
NOMESSAGE, NOPOINTS);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: /* Spell fails */
|
||||
break;
|
||||
|
||||
case 2: /* Freeze */
|
||||
|
||||
if (is_player)
|
||||
no_command++;
|
||||
else
|
||||
caster->t_no_move++;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
case 1: /* Take double spell points - handled in incant() */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
learn_new_spells()
|
||||
go through player_spells and ISKNOW identified potions,
|
||||
scrolls, and sticks
|
||||
*/
|
||||
|
||||
void
|
||||
learn_new_spells(void)
|
||||
{
|
||||
struct spells *sp;
|
||||
int kludge = 0;
|
||||
char spellbuf[2*LINELEN];
|
||||
|
||||
for (sp = player_spells; sp->sp_level != -1; sp++)
|
||||
{
|
||||
if (sp->sp_flags & POT_MAGIC)
|
||||
kludge = TYP_POTION;
|
||||
else if (sp->sp_flags & SCR_MAGIC)
|
||||
kludge = TYP_SCROLL;
|
||||
else if (sp->sp_flags & ZAP_MAGIC)
|
||||
kludge = TYP_STICK;
|
||||
|
||||
if (know_items[kludge][sp->sp_which])
|
||||
{
|
||||
if ((sp->sp_flags & ISKNOW) == FALSE)
|
||||
debug("Learned new spell '%s'", spell_name(sp,spellbuf));
|
||||
sp->sp_flags |= ISKNOW;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
pick_monster_spell()
|
||||
decide which spell from monst_spells will be cast
|
||||
returns pointer to spell in monst_spells
|
||||
*/
|
||||
|
||||
struct spells *
|
||||
pick_monster_spell(struct thing *caster)
|
||||
{
|
||||
struct spells *sp = NULL;
|
||||
struct stats *curp = &(caster->t_stats);
|
||||
int points_casters = curp->s_power;
|
||||
|
||||
/* Discover castable spells */
|
||||
|
||||
for (sp = monst_spells; sp->sp_level != -1; sp++)
|
||||
{
|
||||
int rnd_number = rnd(2 * sp->sp_level) - sp->sp_level;
|
||||
int casting_cost = spell_cost[sp->sp_level] + rnd_number;
|
||||
|
||||
if (points_casters >= casting_cost)
|
||||
sp->sp_flags |= ISKNOW;
|
||||
}
|
||||
|
||||
/* Decide which spell to cast */
|
||||
|
||||
if (curp->s_hpt < rnd(caster->maxstats.s_hpt)) /* think defense */
|
||||
{
|
||||
int i;
|
||||
static const int run_or_heal[NUM_RUN] =
|
||||
{ M_SELFTELEP, M_HLNG2, M_HLNG, M_REGENERATE };
|
||||
|
||||
for (i = 0; i < NUM_RUN; i++)
|
||||
{
|
||||
sp = &monst_spells[run_or_heal[i]];
|
||||
|
||||
if ((sp->sp_flags & ISKNOW) && rnd(1))
|
||||
return(sp);
|
||||
}
|
||||
}
|
||||
|
||||
if (on(*caster, ISSLOW)) /* cancel a slow */
|
||||
{
|
||||
sp = &monst_spells[M_HASTE];
|
||||
|
||||
if (sp->sp_flags & ISKNOW)
|
||||
return (sp);
|
||||
}
|
||||
|
||||
if (on(*caster, ISFLEE)) /* stop running away */
|
||||
{
|
||||
sp = &monst_spells[M_SHERO];
|
||||
|
||||
if (sp->sp_flags & ISKNOW)
|
||||
return (sp);
|
||||
}
|
||||
|
||||
if (on(player, ISINVIS) || on(player, ISDISGUISE))
|
||||
{
|
||||
if (off(*caster, CANSEE)) /* look for him */
|
||||
{
|
||||
sp = &monst_spells[M_SEEINVIS];
|
||||
|
||||
if (sp->sp_flags & ISKNOW)
|
||||
return (sp);
|
||||
}
|
||||
else if (off(*caster, ISINVIS)) /* go invisible */
|
||||
{
|
||||
sp = &monst_spells[M_INVIS];
|
||||
|
||||
if (sp->sp_flags & ISKNOW)
|
||||
return (sp);
|
||||
}
|
||||
}
|
||||
|
||||
if (on(player, CANINWALL) && (off(*caster, CANINWALL)) &&
|
||||
(rnd(5) == 0))
|
||||
{
|
||||
sp = &monst_spells[M_PHASE];
|
||||
|
||||
if (sp->sp_flags & ISKNOW)
|
||||
return (sp);
|
||||
}
|
||||
|
||||
if (rnd(5) == 0 && has_defensive_spell(player))
|
||||
{
|
||||
sp = &monst_spells[M_CANCEL];
|
||||
|
||||
if (sp->sp_flags & ISKNOW)
|
||||
return (sp);
|
||||
}
|
||||
|
||||
/* Cast an offensive spell */
|
||||
|
||||
for (sp = &monst_spells[M_OFFENSE]; sp->sp_level != 1; sp++)
|
||||
{
|
||||
if ((rnd(3) == 0) && (sp->sp_flags & ISKNOW))
|
||||
return (sp);
|
||||
|
||||
if ((rnd(3) == 0) && (sp->sp_flags & ISKNOW))
|
||||
{
|
||||
if (sp->sp_which != WS_MISSILE &&
|
||||
DISTANCE(caster->t_pos, hero) > BOLT_LENGTH)
|
||||
continue;
|
||||
else
|
||||
return(sp);
|
||||
}
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
sort_spells()
|
||||
called by qsort()
|
||||
*/
|
||||
|
||||
int
|
||||
sort_spells(const void *a, const void *b)
|
||||
{
|
||||
struct spells *sp1, *sp2;
|
||||
int diff;
|
||||
char spellbuf[2 * LINELEN];
|
||||
char spellbuf2[2 * LINELEN];
|
||||
|
||||
union /* hack to prevent 'lint' from complaining */
|
||||
{
|
||||
struct spells *s;
|
||||
const void *vptr;
|
||||
} s1,s2;
|
||||
|
||||
s1.vptr = a;
|
||||
s2.vptr = b;
|
||||
|
||||
sp1 = s1.s;
|
||||
sp2 = s2.s;
|
||||
|
||||
diff = sp1->sp_cost - sp2->sp_cost;
|
||||
|
||||
if (diff != 0)
|
||||
return(diff);
|
||||
else
|
||||
return(strcmp(spell_name(sp1,spellbuf), spell_name(sp1,spellbuf2)));
|
||||
}
|
||||
278
urogue/main.c
Normal file
278
urogue/main.c
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
/*
|
||||
main.c - setup code
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
Based on "Advanced Rogue"
|
||||
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
|
||||
All rights reserved.
|
||||
|
||||
Based on "Rogue: Exploring the Dungeons of Doom"
|
||||
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#define _ALL_SOURCE
|
||||
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include "rogue.h"
|
||||
|
||||
FILE *fd_score = NULL;
|
||||
|
||||
/* Command line options */
|
||||
|
||||
int prscore; /* Print scores */
|
||||
int prversion; /* Print version info */
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int x;
|
||||
char *env;
|
||||
time_t lowtime;
|
||||
time_t now;
|
||||
int rflag = 0;
|
||||
char *nm;
|
||||
float scale;
|
||||
|
||||
for (x = 1; x < argc; x++)
|
||||
{
|
||||
if (argv[x][0] != '-')
|
||||
break;
|
||||
|
||||
switch (argv[x][1])
|
||||
{
|
||||
case 's':
|
||||
prscore = TRUE;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
prversion = TRUE;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
rflag = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr,"%s: Unknown option '%c'.\n",argv[0],argv[x][1]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!rflag)
|
||||
{
|
||||
argc -= (x - 1);
|
||||
argv += (x - 1);
|
||||
}
|
||||
|
||||
/* Get default score file */
|
||||
|
||||
strcpy(score_file, "urogue.scr");
|
||||
|
||||
fd_score = fopen(score_file, "r+");
|
||||
|
||||
if (fd_score == NULL)
|
||||
fd_score = fopen(score_file, "a+");
|
||||
|
||||
if ((env = getenv("OPTIONS")) != NULL)
|
||||
parse_opts(env);
|
||||
|
||||
nm = getenv("USER");
|
||||
|
||||
if (nm != NULL)
|
||||
strcpy(whoami,nm);
|
||||
else
|
||||
strcpy(whoami,"anonymous");
|
||||
|
||||
lowtime = time(&now);
|
||||
|
||||
dnum = (wizard && getenv("SEED") != NULL ? atoi( getenv("SEED")) : (int)lowtime);
|
||||
|
||||
ur_srandom(dnum);
|
||||
|
||||
if (env == NULL || fruit[0] == '\0')
|
||||
{
|
||||
static const char *funfruit[] =
|
||||
{
|
||||
"candleberry", "caprifig", "dewberry", "elderberry",
|
||||
"gooseberry", "guanabana", "hagberry", "ilama", "imbu",
|
||||
"jaboticaba", "jujube", "litchi", "mombin", "pitanga",
|
||||
"prickly pear", "rambutan", "sapodilla", "soursop",
|
||||
"sweetsop", "whortleberry"
|
||||
};
|
||||
|
||||
strcpy(fruit, funfruit[rnd(sizeof(funfruit) / sizeof(funfruit[0]))]);
|
||||
}
|
||||
|
||||
/* put a copy of fruit in the right place */
|
||||
|
||||
fd_data[1].mi_name = md_strdup(fruit);
|
||||
|
||||
/* print scores */
|
||||
|
||||
if (prscore)
|
||||
{
|
||||
waswizard = TRUE;
|
||||
score(0L, 0, SCOREIT, 0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* check for version option */
|
||||
|
||||
if (prversion)
|
||||
{
|
||||
printf("UltraRogue Version %s.\n", release);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (wizard)
|
||||
printf("Hello %s, welcome to dungeon #%d", whoami, dnum);
|
||||
else
|
||||
printf("Hello %s, just a moment while I dig the dungeon...", whoami);
|
||||
|
||||
mem_debug(2);
|
||||
mem_tracking(1);
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
init_things(); /* Set up probabilities of things */
|
||||
init_fd(); /* Set up food probabilities */
|
||||
init_colors(); /* Set up colors of potions */
|
||||
init_stones(); /* Set up stone settings of rings */
|
||||
init_materials(); /* Set up materials of wands */
|
||||
initscr(); /* Start up cursor package */
|
||||
refresh();
|
||||
init_names(); /* Set up names of scrolls */
|
||||
cbreak();
|
||||
crmode(); /* Cbreak mode */
|
||||
noecho(); /* Echo off */
|
||||
nonl();
|
||||
|
||||
scale = (float) (LINES * COLS) / (80.0F * 25.0F); /* get food right for */
|
||||
/* different screen sizes */
|
||||
|
||||
food_left = (int) (food_left * scale);
|
||||
|
||||
/* Set up windows */
|
||||
|
||||
cw = newwin(LINES, COLS, 0, 0);
|
||||
mw = newwin(LINES, COLS, 0, 0);
|
||||
hw = newwin(LINES, COLS, 0, 0);
|
||||
|
||||
if (argc == 2 && argv[1][0] != '\0' && !restore(argv[1]))
|
||||
/* Note: restore returns on error only */
|
||||
exit(1);
|
||||
|
||||
waswizard = wizard; /* set wizard flags */
|
||||
|
||||
init_player(); /* look up things and outfit pack */
|
||||
|
||||
resurrect = pstats.s_const;
|
||||
init_exp(); /* set first experience level change */
|
||||
init_flags(); /* set initial flags */
|
||||
wclear(hw);
|
||||
wrefresh(hw);
|
||||
new_level(POSTLEV,0); /* Draw current level */
|
||||
|
||||
/* Start up daemons and fuses */
|
||||
|
||||
start_daemon(DAEMON_DOCTOR, &player, AFTER);
|
||||
|
||||
light_fuse(FUSE_SWANDER, 0, WANDERTIME, AFTER);
|
||||
|
||||
start_daemon(DAEMON_STOMACH, 0, AFTER);
|
||||
start_daemon(DAEMON_RUNNERS, 0, AFTER);
|
||||
|
||||
char_type = player.t_ctype;
|
||||
player.t_oldpos = hero;
|
||||
oldrp = roomin(hero);
|
||||
after = TRUE;
|
||||
|
||||
signal(SIGINT, quit_handler);
|
||||
|
||||
while(playing)
|
||||
{
|
||||
do_daemons(BEFORE);
|
||||
do_fuses(BEFORE);
|
||||
|
||||
command(); /* Command execution */
|
||||
|
||||
if (after)
|
||||
do_after_effects();
|
||||
}
|
||||
|
||||
fatal("");
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
fatal()
|
||||
Exit the program, printing a message.
|
||||
*/
|
||||
|
||||
void
|
||||
fatal(char *s)
|
||||
{
|
||||
clear();
|
||||
move(LINES - 2, 0);
|
||||
printw("%s", s);
|
||||
wrefresh(stdscr);
|
||||
endwin();
|
||||
printf("\n"); /* So the cursor doesn't stop at the end of the line */
|
||||
exit(100);
|
||||
}
|
||||
|
||||
/*
|
||||
rnd()
|
||||
Pick a very random number.
|
||||
*/
|
||||
|
||||
unsigned char
|
||||
ucrnd(unsigned char range)
|
||||
{
|
||||
return (unsigned char)(range <= 0 ? 0 : (ur_random() & 0x7fffffffL) % range);
|
||||
}
|
||||
|
||||
short
|
||||
srnd(short range)
|
||||
{
|
||||
return (short)(range <= 0 ? 0 : (ur_random() & 0x7fffffffL) % range);
|
||||
}
|
||||
|
||||
int
|
||||
rnd(int range)
|
||||
{
|
||||
return (range <= 0 ? 0 : (ur_random() & 0x7fffffffL) % range);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
ulrnd(unsigned long range)
|
||||
{
|
||||
return(range <= 0 ? 0 : (ur_random() & 0x7fffffffL) % range);
|
||||
}
|
||||
|
||||
/*
|
||||
roll()
|
||||
roll a number of dice
|
||||
*/
|
||||
|
||||
int
|
||||
roll(int number, int sides)
|
||||
{
|
||||
int dtotal = 0;
|
||||
|
||||
while (number--)
|
||||
dtotal += rnd(sides) + 1;
|
||||
|
||||
return(dtotal);
|
||||
}
|
||||
333
urogue/maze.c
Normal file
333
urogue/maze.c
Normal file
|
|
@ -0,0 +1,333 @@
|
|||
/*
|
||||
maze.c - functions for dealing with armor
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
Based on "Advanced Rogue"
|
||||
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "rogue.h"
|
||||
|
||||
static char *frontier;
|
||||
static char *bits;
|
||||
static int urlines;
|
||||
static int urcols;
|
||||
|
||||
/*
|
||||
domaze()
|
||||
Draw the maze on this level.
|
||||
*/
|
||||
|
||||
void
|
||||
do_maze(void)
|
||||
{
|
||||
int i, least;
|
||||
struct room *rp;
|
||||
struct linked_list *item;
|
||||
struct object *obj;
|
||||
struct thing *mp;
|
||||
int treas;
|
||||
coord tp;
|
||||
|
||||
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
|
||||
{
|
||||
rp->r_nexits = 0; /* no exits */
|
||||
rp->r_flags = ISGONE; /* kill all rooms */
|
||||
rp->r_fires = 0; /* no fires */
|
||||
}
|
||||
|
||||
rp = &rooms[0]; /* point to only room */
|
||||
rp->r_flags = ISDARK; /* mazes always dark */
|
||||
rp->r_pos.x = 0; /* room fills whole screen */
|
||||
rp->r_pos.y = 1;
|
||||
rp->r_max.x = COLS - 1;
|
||||
rp->r_max.y = LINES - 3;
|
||||
draw_maze(); /* put maze into window */
|
||||
|
||||
/* add some gold to make it worth looking for */
|
||||
|
||||
item = spec_item(GOLD, 0, 0, 0);
|
||||
obj = OBJPTR(item);
|
||||
obj->o_count *= (rnd(10) + 5); /* add in one large hunk */
|
||||
|
||||
do
|
||||
{
|
||||
rnd_pos(rp, &tp);
|
||||
}
|
||||
while( mvwinch(stdscr, tp.y, tp.x) != FLOOR);
|
||||
|
||||
obj->o_pos = tp;
|
||||
add_obj(item, tp.y, tp.x);
|
||||
|
||||
/* add in some food to make sure he has enough */
|
||||
|
||||
item = spec_item(FOOD, 0, 0, 0);
|
||||
obj = OBJPTR(item);
|
||||
|
||||
do
|
||||
{
|
||||
rnd_pos(rp, &tp);
|
||||
}
|
||||
while( mvwinch(stdscr, tp.y, tp.x) != FLOOR);
|
||||
|
||||
obj->o_pos = tp;
|
||||
add_obj(item, tp.y, tp.x);
|
||||
|
||||
if (rnd(100) < 5) /* 5% for treasure maze level */
|
||||
{
|
||||
treas = TRUE;
|
||||
least = 20;
|
||||
debug("Treasure maze.");
|
||||
}
|
||||
else /* normal maze level */
|
||||
{
|
||||
least = 1;
|
||||
treas = FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < level + least; i++)
|
||||
{
|
||||
if (!treas && rnd(100) < 50) /* put in some little buggers */
|
||||
continue;
|
||||
|
||||
/* Put the monster in */
|
||||
|
||||
item = new_item(sizeof *mp);
|
||||
|
||||
mp = THINGPTR(item);
|
||||
|
||||
do
|
||||
{
|
||||
rnd_pos(rp, &tp);
|
||||
}
|
||||
while(mvwinch(stdscr, tp.y, tp.x) != FLOOR);
|
||||
|
||||
new_monster(item, randmonster(NOWANDER, NOGRAB), &tp, NOMAXSTATS);
|
||||
|
||||
/* See if we want to give it a treasure to carry around. */
|
||||
|
||||
if (rnd(100) < monsters[mp->t_index].m_carry)
|
||||
attach(mp->t_pack, new_thing());
|
||||
|
||||
/* If it carries gold, give it some */
|
||||
|
||||
if (on(*mp, CARRYGOLD))
|
||||
{
|
||||
item = spec_item(GOLD, 0, 0, 0);
|
||||
obj = OBJPTR(item);
|
||||
obj->o_count = GOLDCALC + GOLDCALC + GOLDCALC;
|
||||
obj->o_pos = mp->t_pos;
|
||||
attach(mp->t_pack, item);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
draw_maze()
|
||||
Generate and draw the maze on the screen
|
||||
*/
|
||||
|
||||
void
|
||||
draw_maze(void)
|
||||
{
|
||||
int i, j, more;
|
||||
char *ptr;
|
||||
|
||||
urlines = (LINES - 3) / 2;
|
||||
urcols = (COLS - 1) / 2;
|
||||
|
||||
bits = ur_alloc((unsigned int) ((LINES - 3) * (COLS - 1)));
|
||||
frontier = ur_alloc((unsigned int) (urlines * urcols));
|
||||
ptr = frontier;
|
||||
|
||||
while (ptr < (frontier + (urlines * urcols)))
|
||||
*ptr++ = TRUE;
|
||||
|
||||
for (i = 0; i < LINES - 3; i++)
|
||||
{
|
||||
for (j = 0; j < COLS - 1; j++)
|
||||
{
|
||||
if (i % 2 == 1 && j % 2 == 1)
|
||||
*moffset(i, j) = FALSE; /* floor */
|
||||
else
|
||||
*moffset(i, j) = TRUE; /* wall */
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < urlines; i++)
|
||||
{
|
||||
for (j = 0; j < urcols; j++)
|
||||
{
|
||||
do
|
||||
more = findcells(i, j);
|
||||
while (more != 0);
|
||||
}
|
||||
}
|
||||
|
||||
crankout();
|
||||
ur_free(frontier);
|
||||
ur_free(bits);
|
||||
}
|
||||
|
||||
/*
|
||||
moffset()
|
||||
Calculate memory address for bits
|
||||
*/
|
||||
|
||||
char *
|
||||
moffset(int y, int x)
|
||||
{
|
||||
return (bits + (y * (COLS - 1)) + x);
|
||||
}
|
||||
|
||||
/*
|
||||
foffset()
|
||||
Calculate memory address for frontier
|
||||
*/
|
||||
|
||||
char *
|
||||
foffset(int y, int x)
|
||||
{
|
||||
return (frontier + (y * urcols) + x);
|
||||
}
|
||||
|
||||
/*
|
||||
findcells()
|
||||
Figure out cells to open up
|
||||
*/
|
||||
|
||||
int
|
||||
findcells(int y, int x)
|
||||
{
|
||||
int rtpos, i;
|
||||
|
||||
struct
|
||||
{
|
||||
int num_pos; /* number of frontier cells next to you */
|
||||
|
||||
struct
|
||||
{
|
||||
int y_pos;
|
||||
int x_pos;
|
||||
} conn[4]; /* the y,x position of above cell */
|
||||
} mborder;
|
||||
|
||||
*foffset(y, x) = FALSE;
|
||||
mborder.num_pos = 0;
|
||||
|
||||
if (y < urlines - 1) { /* look below */
|
||||
if (*foffset(y + 1, x))
|
||||
{
|
||||
mborder.conn[mborder.num_pos].y_pos = y + 1;
|
||||
mborder.conn[mborder.num_pos].x_pos = x;
|
||||
mborder.num_pos += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (y > 0) /* look above */
|
||||
{
|
||||
if (*foffset(y - 1, x))
|
||||
{
|
||||
mborder.conn[mborder.num_pos].y_pos = y - 1;
|
||||
mborder.conn[mborder.num_pos].x_pos = x;
|
||||
mborder.num_pos += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (x < urcols - 1) /* look right */
|
||||
{
|
||||
if (*foffset(y, x + 1))
|
||||
{
|
||||
mborder.conn[mborder.num_pos].y_pos = y;
|
||||
mborder.conn[mborder.num_pos].x_pos = x + 1;
|
||||
mborder.num_pos += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (x > 0) /* look left */
|
||||
{
|
||||
if (*foffset(y, x - 1))
|
||||
{
|
||||
mborder.conn[mborder.num_pos].y_pos = y;
|
||||
mborder.conn[mborder.num_pos].x_pos = x - 1;
|
||||
mborder.num_pos += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (mborder.num_pos == 0)/* no neighbors available */
|
||||
return(0);
|
||||
else
|
||||
{
|
||||
i = rnd(mborder.num_pos);
|
||||
rtpos = mborder.num_pos - 1;
|
||||
rmwall(mborder.conn[i].y_pos, mborder.conn[i].x_pos, y, x);
|
||||
return(rtpos);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
rmwall()
|
||||
Removes appropriate walls from the maze
|
||||
*/
|
||||
|
||||
void
|
||||
rmwall(int newy, int newx, int oldy, int oldx)
|
||||
{
|
||||
int xdif, ydif;
|
||||
|
||||
xdif = newx - oldx;
|
||||
ydif = newy - oldy;
|
||||
|
||||
*moffset((oldy * 2) + ydif + 1, (oldx * 2) + xdif + 1) = FALSE;
|
||||
|
||||
findcells(newy, newx);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
crankout()
|
||||
Does actual drawing of maze to window
|
||||
*/
|
||||
|
||||
void
|
||||
crankout(void)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
for (y = 0; y < LINES - 3; y++)
|
||||
{
|
||||
move(y + 1, 0);
|
||||
|
||||
for (x = 0; x < COLS - 1; x++)
|
||||
{
|
||||
if (*moffset(y, x)) /* here is a wall */
|
||||
{
|
||||
if (y == 0 || y == LINES - 4) /* top or bottom line */
|
||||
addch('-');
|
||||
else if (x == 0 || x == COLS - 2) /* left | right side */
|
||||
addch('|');
|
||||
else if (y % 2 == 0 && x % 2 == 0)
|
||||
{
|
||||
if (*moffset(y, x - 1) || *moffset(y, x + 1))
|
||||
addch('-');
|
||||
else
|
||||
addch('|');
|
||||
}
|
||||
else if (y % 2 == 0)
|
||||
addch('-');
|
||||
else
|
||||
addch('|');
|
||||
}
|
||||
else
|
||||
addch(FLOOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
1270
urogue/mdport.c
Normal file
1270
urogue/mdport.c
Normal file
File diff suppressed because it is too large
Load diff
420
urogue/memory.c
Normal file
420
urogue/memory.c
Normal file
|
|
@ -0,0 +1,420 @@
|
|||
/*
|
||||
memory.c
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dict.h"
|
||||
#include "memory.h"
|
||||
#include "rogue.h"
|
||||
|
||||
static char sccsid[] = "%W%\t%G%";
|
||||
|
||||
/* Debugging memory allocation code that tries to trap common memory problems
|
||||
like overwriting storage and stepping on memory pointer chains. If code
|
||||
doesn't use malloc, free, and realloc a lot, these routines can be left in
|
||||
as added protection against undetected storage bugs.
|
||||
*/
|
||||
|
||||
/* FENCE_SIZE should be a multiple of sizeof(size_t) to prevent alignment problems.
|
||||
The code assumes that malloc and realloc return pointers aligned at least on size_t
|
||||
sized boundaries and that a pointer needs alignment no more strict than that of an
|
||||
object needed to hold a size_t.
|
||||
*/
|
||||
|
||||
#define FENCE_SIZE (sizeof(size_t) * 1024)
|
||||
|
||||
static int memdebug_level = 0;
|
||||
static DICTIONARY *allocations = NULL;
|
||||
static FILE *trace_file = NULL;
|
||||
|
||||
/* set the debug level */
|
||||
void mem_debug(const int level)
|
||||
{
|
||||
memdebug_level = level;
|
||||
|
||||
if (trace_file == NULL)
|
||||
trace_file = fopen("trace", "w");
|
||||
|
||||
/* all except 0, 1, and unknown fall through */
|
||||
switch(memdebug_level) {
|
||||
case 2:
|
||||
fprintf(trace_file, "+++ Memory tracking possible, ");
|
||||
case 1:
|
||||
fprintf(trace_file, "+++ Memory debugging enabled, ");
|
||||
break;
|
||||
case 0:
|
||||
fprintf(trace_file, "+++ Memory debugging disabled, ");
|
||||
break;
|
||||
default:
|
||||
fprintf(trace_file, "!!! Unknown memory debug level set, enabling level 1, ");
|
||||
memdebug_level = 1;
|
||||
break;
|
||||
}
|
||||
fprintf(trace_file, "fence size = %d\n", FENCE_SIZE);
|
||||
}
|
||||
|
||||
/* set memory tracking on or off */
|
||||
/* turning it off deletes all tracking data */
|
||||
void mem_tracking(int flag)
|
||||
{
|
||||
/* do nothing if debuglevel is too low */
|
||||
if (memdebug_level < 2)
|
||||
return;
|
||||
|
||||
/* turn on tracking */
|
||||
if (flag > 0) {
|
||||
if (allocations != NULL) {
|
||||
dict_destroy(allocations);
|
||||
allocations = NULL;
|
||||
}
|
||||
allocations = dict_create(8, 100, 4, 20);
|
||||
if (allocations == NULL) {
|
||||
fprintf(trace_file, "!!! Unable to allocate tracking table!\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
/* turn off tracking */
|
||||
else if (allocations != NULL) {
|
||||
dict_destroy(allocations);
|
||||
allocations = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* go through all pointers and see if they are OK, aborting if not */
|
||||
/* always returns 1 if not aborting so that it can be included in */
|
||||
/* if statement boolean expressions */
|
||||
int mem_check(char *fname, int linenum)
|
||||
{
|
||||
STRING_ENTRY *se;
|
||||
|
||||
/* scan of a NULL dictionary always succeeds */
|
||||
if (allocations == NULL)
|
||||
return TRUE;
|
||||
|
||||
if (!dict_scan_begin(allocations)) {
|
||||
fprintf(trace_file, "!!! Dictionary scan initialization failed!\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
fprintf(trace_file, "\n+++ --- Starting pointer scan\n");
|
||||
fprintf(trace_file, "+++ --- At %s, %d\n", fname, linenum);
|
||||
|
||||
/* mem_validate aborts if there is a problem */
|
||||
while((se = dict_scan_next(allocations)) != NULL)
|
||||
mem_validate(se->any_ptr);
|
||||
|
||||
fprintf(trace_file, "+++ --- Done pointer scan\n\n");
|
||||
|
||||
/* always return a good value if execution arrives here */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* allocate some memory and initialize header and trailer */
|
||||
void *mem_malloc(const size_t bytes)
|
||||
{
|
||||
char *mem_temp;
|
||||
size_t real_size = bytes + (FENCE_SIZE << 1);
|
||||
|
||||
/* allocate including guard bytes to detect some ways of overwriting of memory areas */
|
||||
mem_temp = (void *)malloc(real_size);
|
||||
if (memdebug_level > 0) {
|
||||
fprintf(trace_file, "+++ Requested size of %ld bytes\n", bytes);
|
||||
fprintf(trace_file, "+++ Actual malloc of %ld bytes located at %p\n", real_size, mem_temp);
|
||||
}
|
||||
|
||||
/* if allocation succeeded, set management data */
|
||||
if (mem_temp != NULL) {
|
||||
size_t i;
|
||||
char *end;
|
||||
|
||||
/* do beginning marker bytes */
|
||||
for (i = 0; i < FENCE_SIZE - sizeof(size_t); i++)
|
||||
*mem_temp++ = 145;
|
||||
|
||||
/* save size in header too */
|
||||
if (memdebug_level > 0)
|
||||
fprintf(trace_file, "*** Requested memory size stored at %p\n", mem_temp);
|
||||
*(size_t *)mem_temp = bytes;
|
||||
|
||||
/* finally, point to storage we are going to hand out */
|
||||
mem_temp += sizeof(size_t);
|
||||
|
||||
/* now, point to trailer bytes and do them */
|
||||
end = mem_temp + bytes;
|
||||
for (i = 0; i < FENCE_SIZE; i++)
|
||||
*end++ = 145;
|
||||
|
||||
/* now zap contents to zero */
|
||||
for (i = 0; i < bytes; i++)
|
||||
mem_temp[i] = 0;
|
||||
}
|
||||
|
||||
/* track pointer if needed */
|
||||
if (memdebug_level > 1 && allocations != NULL) {
|
||||
char key[16];
|
||||
long temp;
|
||||
|
||||
sprintf(key, "%p", mem_temp);
|
||||
if (dict_insert(allocations, key, 1, (const unsigned long) bytes, mem_temp, &temp) == NULL) {
|
||||
fprintf(trace_file, "!!! Insert of pointer tracking info failed\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/* allow caller to do error handling */
|
||||
if (memdebug_level > 0) {
|
||||
fprintf(trace_file, "--- Returning pointer of %p\n", mem_temp);
|
||||
fflush(trace_file);
|
||||
}
|
||||
return (void *)mem_temp;
|
||||
}
|
||||
|
||||
/* release some memory, making sure that it was properly allocated */
|
||||
void mem_free(const void *ptr)
|
||||
{
|
||||
char *mem_temp;
|
||||
size_t mem_size;
|
||||
size_t i;
|
||||
|
||||
if (memdebug_level > 0)
|
||||
fprintf(trace_file, "+++ Free of memory located at %p\n", ptr);
|
||||
if (ptr == NULL) {
|
||||
if (memdebug_level > 0) {
|
||||
fprintf(trace_file, "!!! Freeing NULL pointer\n");
|
||||
fflush(trace_file);
|
||||
}
|
||||
abort();
|
||||
}
|
||||
|
||||
mem_validate(ptr); /* doesn't return on error */
|
||||
|
||||
/* get location of size of area */
|
||||
mem_temp = (char *)ptr - sizeof(size_t);
|
||||
|
||||
/* get and calculate real size */
|
||||
mem_size = *(size_t *)mem_temp + (FENCE_SIZE << 1);
|
||||
|
||||
/* if doing memory tracking */
|
||||
if (memdebug_level > 1 && allocations != NULL) {
|
||||
char key[16];
|
||||
STRING_ENTRY *se;
|
||||
long temp;
|
||||
|
||||
sprintf(key, "%p", ptr);
|
||||
|
||||
if ((se = dict_search(allocations, key, &temp)) == NULL) {
|
||||
fprintf(trace_file, "!!! Deleting pointer not found in tracking info\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
if (se->count == 0) {
|
||||
fprintf(trace_file, "!!! Freeing a pointer that has already been freed!\n");
|
||||
abort();
|
||||
}
|
||||
else if (se->flags != mem_size - (FENCE_SIZE << 1)) {
|
||||
fprintf(trace_file, "!!! Stored size different from tracking size!\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
/* remember deleted stuff by zeroing the allocation count */
|
||||
se->count = 0;
|
||||
se->flags = 0;
|
||||
}
|
||||
|
||||
/* zap bytes being freed */
|
||||
for (i = 0, mem_temp = (char *)ptr - FENCE_SIZE; i < mem_size; i++, mem_temp++)
|
||||
*mem_temp = 243;
|
||||
|
||||
if (memdebug_level > 0)
|
||||
fflush(trace_file);
|
||||
|
||||
mem_temp = (char *)ptr - FENCE_SIZE;
|
||||
free((void *)mem_temp);
|
||||
}
|
||||
|
||||
/* reallocate some memory, making sure that it was properly allocated */
|
||||
void *mem_realloc(const void *ptr, const size_t new_size)
|
||||
{
|
||||
char *mem_temp = (char *)ptr;
|
||||
size_t real_size = new_size + (FENCE_SIZE << 1);
|
||||
size_t mem_size;
|
||||
long i;
|
||||
|
||||
if (memdebug_level > 0) {
|
||||
fprintf(trace_file, "+++ Requested size of %ld bytes\n", new_size);
|
||||
fprintf(trace_file, "+++ Actual realloc of %ld bytes located at %p\n", real_size, mem_temp);
|
||||
}
|
||||
if (ptr == NULL) {
|
||||
if (memdebug_level > 0) {
|
||||
fprintf(trace_file, "!!! Reallocating NULL pointer\n");
|
||||
fflush(trace_file);
|
||||
}
|
||||
abort();
|
||||
}
|
||||
|
||||
mem_validate(ptr); /* doesn't return on error */
|
||||
|
||||
/* if doing memory tracking */
|
||||
if (memdebug_level > 1 && allocations != NULL) {
|
||||
char key[16];
|
||||
STRING_ENTRY *se;
|
||||
long temp;
|
||||
|
||||
sprintf(key, "%p", ptr);
|
||||
|
||||
if ((se = dict_search(allocations, key, &temp)) == NULL) {
|
||||
fprintf(trace_file, "!!! Deleting a pointer not found in tracking info!\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
/* point to size bytes */
|
||||
mem_temp = (char *)ptr - sizeof(size_t);
|
||||
|
||||
/* get user size */
|
||||
mem_size = *(size_t *)mem_temp;
|
||||
|
||||
if (se->count == 0) {
|
||||
fprintf(trace_file, "!!! Freeing a pointer that has already been freed!\n");
|
||||
abort();
|
||||
}
|
||||
else if (se->flags != mem_size) {
|
||||
fprintf(trace_file, "!!! Stored size different from tracking size!\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
/* remember deleted stuff by zeroing the allocation count */
|
||||
se->count = 0;
|
||||
se->flags = 0;
|
||||
}
|
||||
|
||||
|
||||
/* header marker bytes will be copied by the realloc */
|
||||
mem_temp = (char *)ptr - FENCE_SIZE;
|
||||
mem_temp = realloc((void *)mem_temp, real_size);
|
||||
|
||||
if (mem_temp != NULL) {
|
||||
char *end;
|
||||
|
||||
/* save size in header too */
|
||||
mem_temp += FENCE_SIZE - sizeof(size_t);
|
||||
if (memdebug_level > 0)
|
||||
fprintf(trace_file, "*** Requested memory size stored at %p\n", mem_temp);
|
||||
*(size_t *)mem_temp = new_size;
|
||||
|
||||
/* finally, point to storage we are going to hand out */
|
||||
mem_temp += sizeof(size_t);
|
||||
|
||||
/* now, point to trailer bytes and do them */
|
||||
end = mem_temp + new_size;
|
||||
for (i = 0; i < FENCE_SIZE; i++)
|
||||
*end++ = 145;
|
||||
}
|
||||
|
||||
if (memdebug_level > 1 && allocations != NULL) {
|
||||
char key[16];
|
||||
long temp;
|
||||
|
||||
sprintf(key, "%p", mem_temp);
|
||||
if (dict_insert(allocations, key, 1, (const unsigned long)new_size, mem_temp, &temp) == NULL) {
|
||||
fprintf(trace_file, "!!! Insert of pointer tracking info failed\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
if (memdebug_level > 0) {
|
||||
fprintf(trace_file, "--- Returning pointer of %p\n", mem_temp);
|
||||
fflush(trace_file);
|
||||
}
|
||||
return (void *)mem_temp;
|
||||
}
|
||||
|
||||
/* check a pointer to be sure all check bytes are OK. abort if not */
|
||||
/* always returns 1 if not aborting so that it can be included in */
|
||||
/* if statement boolean expressions */
|
||||
int mem_validate(void *ptr)
|
||||
{
|
||||
unsigned char *mem_temp = (unsigned char *)ptr;
|
||||
size_t mem_size;
|
||||
size_t i;
|
||||
|
||||
/* NULL pointers are always valid */
|
||||
if (ptr == NULL)
|
||||
return 1;
|
||||
|
||||
if (memdebug_level > 0)
|
||||
fprintf(trace_file, "+++ Checking %p as pointer\n", ptr);
|
||||
|
||||
|
||||
if (memdebug_level > 1 && allocations != NULL) {
|
||||
char key[16];
|
||||
STRING_ENTRY *se;
|
||||
long temp;
|
||||
|
||||
sprintf(key, "%p", ptr);
|
||||
|
||||
if ((se = dict_search(allocations, key, &temp)) == NULL) {
|
||||
fprintf(trace_file, "!!! Pointer not found in tracking info!\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
/* point to size bytes */
|
||||
mem_temp = (unsigned char *)ptr - sizeof(size_t);
|
||||
|
||||
/* get user size */
|
||||
mem_size = *(size_t *)mem_temp;
|
||||
|
||||
if (se->count == 0) {
|
||||
fprintf(trace_file, "!!! Checking pointer has been freed!\n");
|
||||
abort();
|
||||
}
|
||||
else if (se->flags != mem_size) {
|
||||
fprintf(trace_file, "!!! Stored size different from tracking size!\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/* check the header bytes */
|
||||
mem_temp = (unsigned char *) ptr - FENCE_SIZE;
|
||||
if (memdebug_level > 0)
|
||||
fprintf(trace_file, "+++ Real pointer at %p\n", mem_temp);
|
||||
|
||||
|
||||
for (i = 0; i < FENCE_SIZE - sizeof(size_t); i++)
|
||||
if (*mem_temp++ != 145) {
|
||||
if (memdebug_level > 0) {
|
||||
fprintf(trace_file, "!!! The user pointer at %p has been overwritten\n", ptr);
|
||||
fprintf(trace_file, "!!! Header offset %ld has been changed\n", i - 1);
|
||||
fflush(trace_file);
|
||||
}
|
||||
abort();
|
||||
}
|
||||
|
||||
/* check size */
|
||||
i = *(size_t *)mem_temp;
|
||||
if (memdebug_level > 0)
|
||||
fprintf(trace_file, "*** Stored memory size of %ld bytes in header\n", i);
|
||||
|
||||
|
||||
/* now point to where trailer should be */
|
||||
mem_temp = (unsigned char *)ptr + i;
|
||||
for (i = 0; i < FENCE_SIZE; i++)
|
||||
if (*mem_temp++ != 145) {
|
||||
if (memdebug_level > 0) {
|
||||
fprintf(trace_file, "!!! The user pointer at %p has been overwritten\n", ptr);
|
||||
fprintf(trace_file, "!!! Trailer offset %ld has been changed\n", i - 1);
|
||||
fflush(trace_file);
|
||||
}
|
||||
abort();
|
||||
}
|
||||
if (memdebug_level > 0)
|
||||
fflush(trace_file);
|
||||
return 1;
|
||||
}
|
||||
1208
urogue/misc.c
Normal file
1208
urogue/misc.c
Normal file
File diff suppressed because it is too large
Load diff
2878
urogue/monsdata.c
Normal file
2878
urogue/monsdata.c
Normal file
File diff suppressed because it is too large
Load diff
1497
urogue/monsters.c
Normal file
1497
urogue/monsters.c
Normal file
File diff suppressed because it is too large
Load diff
1837
urogue/move.c
Normal file
1837
urogue/move.c
Normal file
File diff suppressed because it is too large
Load diff
676
urogue/newlvl.c
Normal file
676
urogue/newlvl.c
Normal file
|
|
@ -0,0 +1,676 @@
|
|||
/*
|
||||
newlvl.c - Dig and draw a new level
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
Based on "Advanced Rogue"
|
||||
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
|
||||
All rights reserved.
|
||||
|
||||
Based on "Rogue: Exploring the Dungeons of Doom"
|
||||
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
/*
|
||||
Notes
|
||||
|
||||
Add treasure room code from Rogue 5.2,
|
||||
put in #ifdef 0/#endif bracket at end of code
|
||||
*/
|
||||
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
new_level()
|
||||
Dig and draw a new level
|
||||
*/
|
||||
|
||||
void
|
||||
new_level(LEVTYPE ltype, int special)
|
||||
{
|
||||
int rm, i, cnt;
|
||||
struct linked_list *item, *nitem;
|
||||
struct thing *tp;
|
||||
struct linked_list *fpack = NULL;
|
||||
int going_down = TRUE;
|
||||
coord stairs;
|
||||
|
||||
/* Start player off right */
|
||||
|
||||
turn_off(player, ISHELD);
|
||||
turn_off(player, ISFLEE);
|
||||
extinguish_fuse(FUSE_SUFFOCATE);
|
||||
hold_count = 0;
|
||||
trap_tries = 0;
|
||||
no_food++;
|
||||
|
||||
if (level >= max_level)
|
||||
max_level = level;
|
||||
else
|
||||
going_down = FALSE;
|
||||
|
||||
/* Free up the monsters on the last level */
|
||||
|
||||
if (fam_ptr != NULL) /* save what familiar is carrying */
|
||||
{
|
||||
fpack = (THINGPTR(fam_ptr))->t_pack;
|
||||
(THINGPTR(fam_ptr))->t_pack = NULL;
|
||||
fam_ptr = NULL; /* just in case */
|
||||
}
|
||||
|
||||
for (i = 1; i <= mons_summoned; i++)
|
||||
extinguish_fuse(FUSE_UNSUMMON);
|
||||
|
||||
mons_summoned = 0;
|
||||
|
||||
for (item = mlist; item != NULL; item = nitem)
|
||||
{
|
||||
tp = THINGPTR(item);
|
||||
nitem = next(item);
|
||||
|
||||
if (on(*tp, ISUNIQUE)) /* Put alive UNIQUE on next level */
|
||||
monsters[tp->t_index].m_normal = TRUE;
|
||||
|
||||
killed(NULL, item, NOMESSAGE, NOPOINTS);
|
||||
}
|
||||
|
||||
free_list(lvl_obj); /* Free up previous objects (if any) */
|
||||
|
||||
wclear(cw);
|
||||
wclear(mw);
|
||||
clear();
|
||||
refresh();
|
||||
levtype = ltype;
|
||||
|
||||
switch (ltype)
|
||||
{
|
||||
case THRONE:
|
||||
do_throne(special); /* do monster throne stuff */
|
||||
break;
|
||||
|
||||
case MAZELEV:
|
||||
do_maze();
|
||||
break;
|
||||
|
||||
case POSTLEV:
|
||||
do_post();
|
||||
levtype = ltype = NORMLEV;
|
||||
level++;
|
||||
|
||||
default:
|
||||
do_rooms(); /* Draw rooms */
|
||||
do_passages(); /* Draw passages */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Place the staircase down. */
|
||||
|
||||
cnt = 0;
|
||||
|
||||
do
|
||||
{
|
||||
rm = rnd_room();
|
||||
rnd_pos(&rooms[rm], &stairs);
|
||||
}
|
||||
while (!(mvinch(stairs.y, stairs.x) == FLOOR || cnt++ > 5000));
|
||||
|
||||
addch(STAIRS);
|
||||
|
||||
put_things(ltype); /* Place objects (if any) */
|
||||
|
||||
if (has_artifact && level == 1)
|
||||
create_lucifer(&stairs);
|
||||
|
||||
/* Place the traps */
|
||||
|
||||
ntraps = 0; /* No traps yet */
|
||||
|
||||
if (levtype == NORMLEV)
|
||||
{
|
||||
if (rnd(10) < level)
|
||||
{
|
||||
char ch = 0;
|
||||
|
||||
i = ntraps = min(MAXTRAPS, rnd(level / 2) + 1);
|
||||
|
||||
/* maybe a lair */
|
||||
|
||||
if (level > 35 && ltype == NORMLEV && rnd(wizard ? 3 : 10) == 0)
|
||||
{
|
||||
cnt = 0;
|
||||
|
||||
do
|
||||
{
|
||||
rm = rnd_room();
|
||||
|
||||
if (rooms[rm].r_flags & ISTREAS)
|
||||
continue;
|
||||
|
||||
rnd_pos(&rooms[rm], &stairs);
|
||||
}
|
||||
while (!(mvinch(stairs.y, stairs.x) == FLOOR || cnt++ > 5000));
|
||||
|
||||
addch(LAIR);
|
||||
i--;
|
||||
traps[i].tr_flags = 0;
|
||||
traps[i].tr_type = LAIR;
|
||||
traps[i].tr_show = FLOOR;
|
||||
traps[i].tr_pos = stairs;
|
||||
}
|
||||
|
||||
while (i--)
|
||||
{
|
||||
cnt = 0;
|
||||
|
||||
do
|
||||
{
|
||||
rm = rnd_room();
|
||||
|
||||
if (rooms[rm].r_flags & ISTREAS)
|
||||
continue;
|
||||
|
||||
rnd_pos(&rooms[rm], &stairs);
|
||||
}
|
||||
while (!(mvinch(stairs.y, stairs.x) == FLOOR || cnt++ > 5000));
|
||||
|
||||
traps[i].tr_flags = 0;
|
||||
|
||||
switch (rnd(11))
|
||||
{
|
||||
case 0:
|
||||
ch = TRAPDOOR;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
ch = BEARTRAP;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ch = SLEEPTRAP;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
ch = ARROWTRAP;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
ch = TELTRAP;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
ch = DARTTRAP;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
ch = POOL;
|
||||
|
||||
if (rnd(10))
|
||||
traps[i].tr_flags = ISFOUND;
|
||||
|
||||
break;
|
||||
|
||||
case 7:
|
||||
ch = MAZETRAP;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
ch = FIRETRAP;
|
||||
break;
|
||||
|
||||
case 9:
|
||||
ch = POISONTRAP;
|
||||
break;
|
||||
|
||||
case 10:
|
||||
ch = RUSTTRAP;
|
||||
break;
|
||||
}
|
||||
|
||||
addch(ch);
|
||||
traps[i].tr_type = ch;
|
||||
traps[i].tr_show = FLOOR;
|
||||
traps[i].tr_pos = stairs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do /* Position hero */
|
||||
{
|
||||
rm = rnd_room();
|
||||
|
||||
if (levtype != THRONE && (rooms[rm].r_flags & ISTREAS))
|
||||
continue;
|
||||
|
||||
rnd_pos(&rooms[rm], &hero);
|
||||
}
|
||||
while(!(winat(hero.y, hero.x) == FLOOR &&
|
||||
DISTANCE(hero, stairs) > 16));
|
||||
|
||||
oldrp = &rooms[rm]; /* Set the current room */
|
||||
player.t_oldpos = player.t_pos; /* Set the current position */
|
||||
|
||||
if (levtype != POSTLEV && levtype != THRONE)
|
||||
{
|
||||
if (on(player, BLESSMAP) && rnd(5) == 0)
|
||||
{
|
||||
read_scroll(&player, S_MAP, ISNORMAL);
|
||||
|
||||
if (rnd(3) == 0)
|
||||
turn_off(player, BLESSMAP);
|
||||
}
|
||||
|
||||
if (player.t_ctype == C_THIEF || on(player, BLESSGOLD) && rnd(5) == 0)
|
||||
{
|
||||
read_scroll(&player, S_GFIND, ISNORMAL);
|
||||
|
||||
if (rnd(3) == 0)
|
||||
turn_off(player, BLESSGOLD);
|
||||
}
|
||||
|
||||
if (player.t_ctype == C_RANGER || on(player, BLESSFOOD) && rnd(5) == 0)
|
||||
{
|
||||
read_scroll(&player, S_FOODDET, ISNORMAL);
|
||||
|
||||
if (rnd(3) == 0)
|
||||
turn_off(player, BLESSFOOD);
|
||||
}
|
||||
|
||||
if (player.t_ctype == C_MAGICIAN || player.t_ctype == C_ILLUSION ||
|
||||
on(player, BLESSMAGIC) && rnd(5) == 0)
|
||||
{
|
||||
quaff(&player, P_TREASDET, ISNORMAL);
|
||||
|
||||
if (rnd(3) == 0)
|
||||
turn_off(player, BLESSMAGIC);
|
||||
}
|
||||
|
||||
if (player.t_ctype == C_DRUID || on(player, BLESSMONS) && rnd(5) == 0)
|
||||
{
|
||||
quaff(&player, P_MONSTDET, ISNORMAL);
|
||||
|
||||
if (rnd(3) == 0)
|
||||
turn_off(player, BLESSMONS);
|
||||
}
|
||||
else if (player.t_ctype == C_CLERIC ||
|
||||
player.t_ctype == C_PALADIN || is_wearing(R_PIETY))
|
||||
undead_sense();
|
||||
}
|
||||
|
||||
if (is_wearing(R_AGGR))
|
||||
aggravate();
|
||||
|
||||
if (is_wearing(R_ADORNMENT) ||
|
||||
cur_armor != NULL && cur_armor->o_which == MITHRIL)
|
||||
{
|
||||
int greed = FALSE;
|
||||
|
||||
for (item = mlist; item != NULL; item = next(item))
|
||||
{
|
||||
tp = THINGPTR(item);
|
||||
|
||||
if (on(*tp, ISGREED))
|
||||
{
|
||||
turn_on(*tp, ISRUN);
|
||||
turn_on(*tp, ISMEAN);
|
||||
tp->t_ischasing = TRUE;
|
||||
tp->t_chasee = &player;
|
||||
greed = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (greed)
|
||||
msg("An uneasy feeling comes over you.");
|
||||
}
|
||||
|
||||
if (is_carrying(TR_PALANTIR)) /* Palantir shows all */
|
||||
{
|
||||
msg("The Palantir reveals all!");
|
||||
|
||||
overlay(stdscr, cw); /* Wizard mode 'f' command */
|
||||
overlay(mw, cw); /* followed by 'm' command */
|
||||
}
|
||||
|
||||
if (is_carrying(TR_PHIAL)) /* Phial lights your way */
|
||||
{
|
||||
if (!is_carrying(TR_PALANTIR))
|
||||
msg("The Phial banishes the darkness!");
|
||||
|
||||
for (i = 0; i < MAXROOMS; i++)
|
||||
rooms[i].r_flags &= ~ISDARK;
|
||||
}
|
||||
|
||||
if (is_carrying(TR_AMULET)) /* Amulet describes the level */
|
||||
{
|
||||
level_eval();
|
||||
}
|
||||
|
||||
|
||||
wmove(cw, hero.y, hero.x);
|
||||
waddch(cw, PLAYER);
|
||||
light(&hero);
|
||||
|
||||
/* Summon familiar if player has one */
|
||||
|
||||
if (on(player, HASFAMILIAR))
|
||||
{
|
||||
summon_monster((short) fam_type, FAMILIAR, MESSAGE);
|
||||
|
||||
if (fam_ptr != NULL) /* add old pack to new */
|
||||
{
|
||||
tp = THINGPTR(fam_ptr);
|
||||
|
||||
if (tp->t_pack == NULL)
|
||||
tp->t_pack = fpack;
|
||||
else if (fpack != NULL)
|
||||
{
|
||||
for (item = tp->t_pack; item->l_next != NULL;item = next(item))
|
||||
;
|
||||
|
||||
item->l_next = fpack;
|
||||
debug("new_level: l_prev = %p",item);
|
||||
fpack->l_prev = item;
|
||||
}
|
||||
}
|
||||
else
|
||||
free_list(fpack);
|
||||
}
|
||||
|
||||
mem_check(__FILE__,__LINE__);
|
||||
status(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
put_things()
|
||||
put potions and scrolls on this level
|
||||
*/
|
||||
|
||||
void
|
||||
put_things(LEVTYPE ltype)
|
||||
{
|
||||
int i, rm, cnt;
|
||||
struct linked_list *item;
|
||||
struct object *cur;
|
||||
int got_unique = FALSE;
|
||||
int length, width, maxobjects;
|
||||
coord tp;
|
||||
|
||||
/*
|
||||
* Once you have found an artifact, the only way to get new stuff is
|
||||
* go down into the dungeon.
|
||||
*/
|
||||
|
||||
if (has_artifact && level < max_level && ltype != THRONE)
|
||||
return;
|
||||
|
||||
/*
|
||||
* There is a chance that there is a treasure room on this level
|
||||
* Increasing chance after level 10
|
||||
*/
|
||||
|
||||
if (ltype != MAZELEV && rnd(50) < level - 10)
|
||||
{
|
||||
int n, j;
|
||||
struct room *rp;
|
||||
|
||||
/* Count the number of free spaces */
|
||||
n = 0; /* 0 tries */
|
||||
|
||||
do
|
||||
{
|
||||
rp = &rooms[rnd_room()];
|
||||
width = rp->r_max.y - 2;
|
||||
length = rp->r_max.x - 2;
|
||||
}
|
||||
while(!((width * length <= MAXTREAS) || (n++ > MAXROOMS * 4)));
|
||||
|
||||
/* Mark the room as a treasure room */
|
||||
|
||||
rp->r_flags |= ISTREAS;
|
||||
|
||||
/* Make all the doors secret doors */
|
||||
|
||||
for (n = 0; n < rp->r_nexits; n++)
|
||||
{
|
||||
move(rp->r_exit[n].y, rp->r_exit[n].x);
|
||||
addch(SECRETDOOR);
|
||||
}
|
||||
|
||||
/* Put in the monsters and treasures */
|
||||
|
||||
for (j = 1; j < rp->r_max.y - 1; j++)
|
||||
for (n = 1; n < rp->r_max.x - 1; n++)
|
||||
{
|
||||
coord trp;
|
||||
|
||||
trp.y = rp->r_pos.y + j;
|
||||
trp.x = rp->r_pos.x + n;
|
||||
|
||||
/* Monsters */
|
||||
|
||||
if ((rnd(100) < (MAXTREAS * 100) /
|
||||
(width * length)) &&
|
||||
(mvwinch(mw, rp->r_pos.y + j,
|
||||
rp->r_pos.x + n) == ' '))
|
||||
{
|
||||
struct thing *th;
|
||||
|
||||
/* Make a monster */
|
||||
|
||||
item = new_item(sizeof *th);
|
||||
th = THINGPTR(item);
|
||||
|
||||
/*
|
||||
* Put it there and aggravate it
|
||||
* (unless it can escape) only put
|
||||
* one UNIQUE per treasure room at
|
||||
* most
|
||||
*/
|
||||
|
||||
if (got_unique)
|
||||
new_monster(item, randmonster(NOWANDER, GRAB), &trp,
|
||||
NOMAXSTATS);
|
||||
else
|
||||
{
|
||||
new_monster(item, randmonster(NOWANDER, NOGRAB), &trp,
|
||||
NOMAXSTATS);
|
||||
|
||||
if (on(*th, ISUNIQUE))
|
||||
got_unique = TRUE;
|
||||
}
|
||||
|
||||
turn_off(*th, ISFRIENDLY);
|
||||
turn_on(*th, ISMEAN);
|
||||
|
||||
if (off(*th, CANINWALL))
|
||||
{
|
||||
th->t_ischasing = TRUE;
|
||||
th->t_chasee = &player;
|
||||
turn_on(*th, ISRUN);
|
||||
}
|
||||
}
|
||||
|
||||
/* Treasures */
|
||||
|
||||
if ((rnd(100) < (MAXTREAS * 100) /
|
||||
(width * length)) &&
|
||||
(mvinch(rp->r_pos.y + j,
|
||||
rp->r_pos.x + n) == FLOOR))
|
||||
{
|
||||
item = new_thing();
|
||||
cur = OBJPTR(item);
|
||||
cur->o_pos = trp;
|
||||
add_obj(item, trp.y, trp.x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Do MAXOBJ attempts to put things on a level, maybe */
|
||||
|
||||
maxobjects = (ltype == THRONE) ? rnd(3 * MAXOBJ) + 35 : MAXOBJ;
|
||||
|
||||
for (i = 0; i < maxobjects; i++)
|
||||
if (rnd(100) < 40 || ltype == THRONE)
|
||||
{
|
||||
/* Pick a new object and link it in the list */
|
||||
|
||||
item = new_thing();
|
||||
cur = OBJPTR(item);
|
||||
|
||||
/* Put it somewhere */
|
||||
|
||||
cnt = 0;
|
||||
|
||||
do
|
||||
{
|
||||
rm = rnd_room();
|
||||
rnd_pos(&rooms[rm], &tp);
|
||||
}
|
||||
while(!(winat(tp.y, tp.x) == FLOOR || cnt++ > 500));
|
||||
|
||||
cur->o_pos = tp;
|
||||
add_obj(item, tp.y, tp.x);
|
||||
}
|
||||
|
||||
/*
|
||||
* If he is really deep in the dungeon and he hasn't found an
|
||||
* artifact yet, put it somewhere on the ground
|
||||
*/
|
||||
|
||||
if (make_artifact())
|
||||
{
|
||||
item = new_item(sizeof *cur);
|
||||
cur = OBJPTR(item);
|
||||
new_artifact(-1, cur);
|
||||
cnt = 0;
|
||||
|
||||
do
|
||||
{
|
||||
rm = rnd_room();
|
||||
rnd_pos(&rooms[rm], &tp);
|
||||
}
|
||||
while(!(winat(tp.y, tp.x) == FLOOR || cnt++ > 500));
|
||||
|
||||
cur->o_pos = tp;
|
||||
add_obj(item, tp.y, tp.x);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
do_throne()
|
||||
Put a monster's throne room and monsters on the screen
|
||||
*/
|
||||
|
||||
void
|
||||
do_throne(int special)
|
||||
{
|
||||
coord mp;
|
||||
int save_level;
|
||||
int i;
|
||||
struct room *rp;
|
||||
struct thing *tp;
|
||||
struct linked_list *item;
|
||||
int throne_monster;
|
||||
|
||||
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
|
||||
{
|
||||
rp->r_nexits = 0; /* no exits */
|
||||
rp->r_flags = ISGONE; /* kill all rooms */
|
||||
}
|
||||
|
||||
rp = &rooms[0]; /* point to only room */
|
||||
rp->r_flags = 0; /* this room NOT gone */
|
||||
rp->r_max.x = 40;
|
||||
rp->r_max.y = 10; /* 10 * 40 room */
|
||||
rp->r_pos.x = (COLS - rp->r_max.x) / 2; /* center horizontal */
|
||||
rp->r_pos.y = 3; /* 2nd line */
|
||||
draw_room(rp); /* draw the only room */
|
||||
|
||||
save_level = level;
|
||||
level = max(2 * level, level + roll(4, 6));
|
||||
|
||||
if (special == 0) /* Who has he offended? */
|
||||
do
|
||||
throne_monster = nummonst - roll(1, NUMSUMMON);
|
||||
while(!monsters[throne_monster].m_normal);
|
||||
else
|
||||
throne_monster = special;
|
||||
|
||||
/* Create summoning monster */
|
||||
|
||||
item = new_item(sizeof *tp);
|
||||
|
||||
tp = THINGPTR(item);
|
||||
|
||||
do
|
||||
{
|
||||
rnd_pos(rp, &mp);
|
||||
}
|
||||
while(mvwinch(stdscr, mp.y, mp.x) != FLOOR);
|
||||
|
||||
new_monster(item, throne_monster, &mp, MAXSTATS);
|
||||
turn_on(*tp, CANSEE);
|
||||
turn_off(*tp, ISFRIENDLY);
|
||||
|
||||
if (on(*tp, CANSUMMON)) /* summon his helpers */
|
||||
summon_help(tp, FORCE);
|
||||
else
|
||||
{
|
||||
for (i = roll(4, 10); i >= 0; i--)
|
||||
{
|
||||
item = new_item(sizeof *tp);
|
||||
tp = THINGPTR(item);
|
||||
|
||||
do
|
||||
{
|
||||
rnd_pos(rp, &mp);
|
||||
}
|
||||
while(mvwinch(stdscr, mp.y, mp.x) != FLOOR);
|
||||
|
||||
new_monster(item, randmonster(NOWANDER, NOGRAB), &mp, MAXSTATS);
|
||||
turn_on(*tp, CANSEE);
|
||||
turn_off(*tp, ISFRIENDLY);
|
||||
}
|
||||
}
|
||||
|
||||
level = save_level + roll(2, 3); /* send the hero down */
|
||||
aggravate();
|
||||
}
|
||||
|
||||
/*
|
||||
create_lucifer()
|
||||
special surprise on the way back up create Lucifer
|
||||
with more than the usual god abilities
|
||||
*/
|
||||
|
||||
void
|
||||
create_lucifer(coord *stairs)
|
||||
{
|
||||
struct linked_list *item = new_item(sizeof(struct thing));
|
||||
struct thing *tp = THINGPTR(item);
|
||||
|
||||
new_monster(item, nummonst + 1, stairs, MAXSTATS);
|
||||
turn_on(*tp, CANINWALL);
|
||||
turn_on(*tp, CANHUH);
|
||||
turn_on(*tp, CANBLINK);
|
||||
turn_on(*tp, CANSNORE);
|
||||
turn_on(*tp, CANDISEASE);
|
||||
turn_on(*tp, NOCOLD);
|
||||
turn_on(*tp, TOUCHFEAR);
|
||||
turn_on(*tp, BMAGICHIT);
|
||||
turn_on(*tp, NOFIRE);
|
||||
turn_on(*tp, NOBOLT);
|
||||
turn_on(*tp, CANBLIND);
|
||||
turn_on(*tp, CANINFEST);
|
||||
turn_on(*tp, CANSMELL);
|
||||
turn_on(*tp, CANPARALYZE);
|
||||
turn_on(*tp, CANSTINK);
|
||||
turn_on(*tp, CANCHILL);
|
||||
turn_on(*tp, CANFRIGHTEN);
|
||||
turn_on(*tp, CANHOLD);
|
||||
turn_on(*tp, CANBRANDOM);
|
||||
}
|
||||
519
urogue/options.c
Normal file
519
urogue/options.c
Normal file
|
|
@ -0,0 +1,519 @@
|
|||
/*
|
||||
options.c - This file has all the code for the option command
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
Based on "Advanced Rogue"
|
||||
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
|
||||
All rights reserved.
|
||||
|
||||
Based on "Rogue: Exploring the Dungeons of Doom"
|
||||
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "rogue.h"
|
||||
|
||||
#define NUM_OPTS (sizeof optlist / sizeof (OPTION))
|
||||
#define EQSTR(a, b, c) (strncmp(a, b, c) == 0)
|
||||
|
||||
/* description of an option and what to do with it */
|
||||
static OPTION optlist[] =
|
||||
{
|
||||
{"jump","Show position only at end of run (jump): ", &jump,put_bool,get_bool},
|
||||
{"inven","Style of inventories (inven): ", &inv_type, put_inv, get_inv},
|
||||
{"askme","Ask me about unidentified things (askme): ",&askme,put_bool,get_bool},
|
||||
{"doorstop","Stop running when adjacent (doorstop): ",&doorstop,put_bool,get_bool},
|
||||
{"name", "Name (name): ", &whoami, put_str, get_str},
|
||||
{"fruit", "Fruit (fruit): ", &fruit, put_str, get_str},
|
||||
{"file", "Save file (file): ", &file_name, put_str, get_str},
|
||||
{"score", "Score file (score): ", &score_file, put_str, get_str},
|
||||
{"class", "Character class (class): ",&char_type, put_abil, get_abil}
|
||||
};
|
||||
|
||||
/*
|
||||
option()
|
||||
print and then set options from the terminal
|
||||
*/
|
||||
|
||||
void
|
||||
option(void)
|
||||
{
|
||||
OPTION *op;
|
||||
int retval;
|
||||
|
||||
wclear(hw);
|
||||
touchwin(hw);
|
||||
|
||||
/* Display current values of options */
|
||||
|
||||
for (op = optlist; op < &optlist[NUM_OPTS]; op++)
|
||||
{
|
||||
waddstr(hw, op->o_prompt);
|
||||
(*op->o_putfunc)(&op->o_opt, hw);
|
||||
waddch(hw, '\n');
|
||||
}
|
||||
|
||||
/* Set values */
|
||||
|
||||
wmove(hw, 0, 0);
|
||||
|
||||
for (op = optlist; op < &optlist[NUM_OPTS]; op++)
|
||||
{
|
||||
waddstr(hw, op->o_prompt);
|
||||
|
||||
retval = (*op->o_getfunc)(&op->o_opt, hw);
|
||||
|
||||
if (retval)
|
||||
if (retval == QUIT)
|
||||
break;
|
||||
else if (op > optlist) /* MINUS */
|
||||
{
|
||||
wmove(hw, (int)(op - optlist) - 1, 0);
|
||||
op -= 2;
|
||||
}
|
||||
else /* trying to back up beyond the top */
|
||||
{
|
||||
putchar('\007');
|
||||
wmove(hw, 0, 0);
|
||||
op--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Switch back to original screen */
|
||||
|
||||
mvwaddstr(hw, LINES - 1, 0, spacemsg);
|
||||
wrefresh(hw);
|
||||
wait_for(' ');
|
||||
clearok(cw, TRUE);
|
||||
touchwin(cw);
|
||||
}
|
||||
|
||||
/*
|
||||
put_bool()
|
||||
put out a boolean
|
||||
*/
|
||||
|
||||
void
|
||||
put_bool(opt_arg *opt, WINDOW *win)
|
||||
{
|
||||
waddstr(win, *opt->iarg ? "True" : "False");
|
||||
}
|
||||
|
||||
/*
|
||||
put_str()
|
||||
put out a string
|
||||
*/
|
||||
|
||||
void
|
||||
put_str(opt_arg *opt, WINDOW *win)
|
||||
{
|
||||
waddstr(win, opt->str);
|
||||
}
|
||||
|
||||
/*
|
||||
put_abil()
|
||||
print the character type
|
||||
*/
|
||||
|
||||
void
|
||||
put_abil(opt_arg *opt, WINDOW *win)
|
||||
{
|
||||
char *abil;
|
||||
|
||||
switch(*opt->iarg)
|
||||
{
|
||||
case C_FIGHTER:
|
||||
abil = "Fighter";
|
||||
break;
|
||||
case C_MAGICIAN:
|
||||
abil = "Magic User";
|
||||
break;
|
||||
case C_CLERIC:
|
||||
abil = "Cleric";
|
||||
break;
|
||||
case C_THIEF:
|
||||
abil = "Thief";
|
||||
break;
|
||||
case C_PALADIN:
|
||||
abil = "Paladin";
|
||||
break;
|
||||
case C_RANGER:
|
||||
abil = "Ranger";
|
||||
break;
|
||||
case C_ILLUSION:
|
||||
abil = "Illusionist";
|
||||
break;
|
||||
case C_ASSASIN:
|
||||
abil = "Assasin";
|
||||
break;
|
||||
case C_NINJA:
|
||||
abil = "Ninja";
|
||||
break;
|
||||
case C_DRUID:
|
||||
abil = "Druid";
|
||||
break;
|
||||
default:
|
||||
abil = "(unknown)";
|
||||
}
|
||||
waddstr(win, abil);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
get_bool()
|
||||
allow changing a boolean option and print it out
|
||||
*/
|
||||
|
||||
int
|
||||
get_bool(opt_arg *opt, WINDOW *win)
|
||||
{
|
||||
int oy, ox;
|
||||
int op_bad;
|
||||
|
||||
op_bad = TRUE;
|
||||
getyx(win, oy, ox);
|
||||
waddstr(win, *opt->iarg ? "True" : "False");
|
||||
|
||||
while(op_bad)
|
||||
{
|
||||
wmove(win, oy, ox);
|
||||
wrefresh(win);
|
||||
|
||||
switch (readcharw(win))
|
||||
{
|
||||
case 't':
|
||||
case 'T':
|
||||
*opt->iarg = TRUE;
|
||||
op_bad = FALSE;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
case 'F':
|
||||
*opt->iarg = FALSE;
|
||||
op_bad = FALSE;
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
case '\r':
|
||||
op_bad = FALSE;
|
||||
break;
|
||||
|
||||
case '\033':
|
||||
case '\007':
|
||||
return QUIT;
|
||||
|
||||
case '-':
|
||||
return MINUS;
|
||||
|
||||
default:
|
||||
mvwaddstr(win, oy, ox + 10, "(T or F)");
|
||||
}
|
||||
}
|
||||
|
||||
wmove(win, oy, ox);
|
||||
wclrtoeol(win);
|
||||
waddstr(win, *opt->iarg ? "True" : "False");
|
||||
waddch(win, '\n');
|
||||
|
||||
return(NORM);
|
||||
}
|
||||
|
||||
/*
|
||||
get_str()
|
||||
set a string option
|
||||
*/
|
||||
|
||||
int
|
||||
get_str(opt_arg *opt, WINDOW *win)
|
||||
{
|
||||
return( get_string(opt->str, win) );
|
||||
}
|
||||
|
||||
/*
|
||||
get_abil()
|
||||
The ability field is read-only
|
||||
*/
|
||||
|
||||
int
|
||||
get_abil(opt_arg *opt, WINDOW *win)
|
||||
{
|
||||
int oy, ox, ny, nx;
|
||||
int op_bad;
|
||||
|
||||
op_bad = TRUE;
|
||||
getyx(win, oy, ox);
|
||||
put_abil(opt, win);
|
||||
getyx(win, ny, nx);
|
||||
|
||||
while(op_bad)
|
||||
{
|
||||
wmove(win, oy, ox);
|
||||
wrefresh(win);
|
||||
|
||||
switch(readcharw(win))
|
||||
{
|
||||
case '\n':
|
||||
case '\r':
|
||||
op_bad = FALSE;
|
||||
break;
|
||||
|
||||
case '\033':
|
||||
case '\007':
|
||||
return(QUIT);
|
||||
|
||||
case '-':
|
||||
return(MINUS);
|
||||
|
||||
default:
|
||||
mvwaddstr(win, ny, nx + 5, "(no change allowed)");
|
||||
}
|
||||
}
|
||||
|
||||
wmove(win, ny, nx + 5);
|
||||
wclrtoeol(win);
|
||||
wmove(win, ny, nx);
|
||||
waddch(win, '\n');
|
||||
|
||||
return(NORM);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
parse_opts()
|
||||
parse options from string, usually taken from the environment. the
|
||||
string is a series of comma seperated values, with booleans being
|
||||
stated as "name" (true) or "noname" (false), and strings being
|
||||
"name=....", with the string being defined up to a comma or the
|
||||
end of the entire option string.
|
||||
*/
|
||||
|
||||
void
|
||||
parse_opts(char *str)
|
||||
{
|
||||
char *sp;
|
||||
const OPTION *op;
|
||||
size_t len;
|
||||
|
||||
while (*str)
|
||||
{
|
||||
for (sp = str; isalpha(*sp); sp++)
|
||||
continue;
|
||||
|
||||
len = sp - str;
|
||||
|
||||
/* Look it up and deal with it */
|
||||
|
||||
for (op = optlist; op < &optlist[NUM_OPTS]; op++)
|
||||
if (EQSTR(str, op->o_name, len))
|
||||
{
|
||||
if (op->o_putfunc == put_bool)
|
||||
*op->o_opt.iarg = TRUE;
|
||||
else /* string option */
|
||||
{
|
||||
char *start;
|
||||
char value[80];
|
||||
|
||||
/* Skip to start of string value */
|
||||
|
||||
for (str = sp + 1; *str == '='; str++)
|
||||
continue;
|
||||
|
||||
start = (char *) value;
|
||||
|
||||
/* Skip to end of string value */
|
||||
|
||||
for (sp = str + 1; *sp && *sp != ','; sp++)
|
||||
continue;
|
||||
|
||||
strncpy(start, str, sp - str);
|
||||
|
||||
/* Put the value into the option field */
|
||||
|
||||
if (op->o_putfunc != put_abil &&
|
||||
op->o_putfunc != put_inv)
|
||||
strcpy(op->o_opt.str, value);
|
||||
|
||||
if (op->o_putfunc == put_inv)
|
||||
{
|
||||
int *opt = op->o_opt.iarg;
|
||||
|
||||
len = strlen(value);
|
||||
|
||||
if (isupper(value[0]))
|
||||
value[0] = (char) tolower(value[0]);
|
||||
if (EQSTR(value, "overwrite",len))
|
||||
*opt = INV_OVER;
|
||||
if (EQSTR(value, "slow", len))
|
||||
*opt = INV_SLOW;
|
||||
if (EQSTR(value, "clear", len))
|
||||
*opt = INV_CLEAR;
|
||||
}
|
||||
else if (*op->o_opt.iarg == -1)
|
||||
{
|
||||
int *opt = op->o_opt.iarg;
|
||||
|
||||
len = strlen(value);
|
||||
|
||||
if (isupper(value[0]))
|
||||
value[0] = (char) tolower(value[0]);
|
||||
if (EQSTR(value, "fighter", len))
|
||||
*opt = C_FIGHTER;
|
||||
else if (EQSTR(value, "magic", min(len, 5)))
|
||||
*opt = C_MAGICIAN;
|
||||
else if (EQSTR(value, "illus", min(len, 5)))
|
||||
*opt = C_ILLUSION;
|
||||
else if (EQSTR(value, "cleric", len))
|
||||
*opt = C_CLERIC;
|
||||
else if (EQSTR(value, "thief", len))
|
||||
*opt = C_THIEF;
|
||||
else if (EQSTR(value, "paladin", len))
|
||||
*opt = C_PALADIN;
|
||||
else if (EQSTR(value, "ranger", len))
|
||||
*opt = C_RANGER;
|
||||
else if (EQSTR(value, "assasin", len))
|
||||
*opt = C_ASSASIN;
|
||||
else if (EQSTR(value, "druid", len))
|
||||
*opt = C_DRUID;
|
||||
else if (EQSTR(value, "ninja", len))
|
||||
*opt = C_NINJA;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (op->o_putfunc == put_bool
|
||||
&& EQSTR(str, "no", 2) &&
|
||||
EQSTR(str + 2, op->o_name, len - 2))
|
||||
{
|
||||
*op->o_opt.iarg = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* skip to start of next option name */
|
||||
|
||||
while (*sp && !isalpha(*sp))
|
||||
sp++;
|
||||
|
||||
str = sp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
put_inv()
|
||||
print the inventory type
|
||||
*/
|
||||
|
||||
void
|
||||
put_inv(opt_arg *opt, WINDOW *win)
|
||||
{
|
||||
char *style;
|
||||
|
||||
switch(*opt->iarg)
|
||||
{
|
||||
case INV_OVER:
|
||||
style = "Overwrite";
|
||||
break;
|
||||
|
||||
case INV_SLOW:
|
||||
style = "Slow";
|
||||
break;
|
||||
|
||||
case INV_CLEAR:
|
||||
style = "Clear Screen";
|
||||
break;
|
||||
|
||||
default:
|
||||
style = "(unknown)";
|
||||
}
|
||||
|
||||
waddstr(win, style);
|
||||
}
|
||||
|
||||
/*
|
||||
get_inv()
|
||||
The inventory field.
|
||||
*/
|
||||
|
||||
int
|
||||
get_inv(opt_arg *opt, WINDOW *win)
|
||||
{
|
||||
int oy, ox, ny, nx;
|
||||
int op_bad;
|
||||
|
||||
op_bad = TRUE;
|
||||
getyx(win, oy, ox);
|
||||
put_inv(opt, win);
|
||||
getyx(win, ny, nx);
|
||||
|
||||
while(op_bad)
|
||||
{
|
||||
wmove(win, oy, ox);
|
||||
wrefresh(win);
|
||||
|
||||
switch(readcharw(win))
|
||||
{
|
||||
case '\n':
|
||||
case '\r':
|
||||
op_bad = FALSE;
|
||||
break;
|
||||
|
||||
case '\033':
|
||||
case '\007':
|
||||
return(QUIT);
|
||||
|
||||
case '-':
|
||||
return(MINUS);
|
||||
|
||||
case 'O':
|
||||
case 'o':
|
||||
*opt->iarg = INV_OVER;
|
||||
op_bad = FALSE;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
case 's':
|
||||
*opt->iarg = INV_SLOW;
|
||||
op_bad = FALSE;
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
case 'c':
|
||||
*opt->iarg = INV_CLEAR;
|
||||
op_bad = FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
mvwaddstr(win, ny, nx + 5, "(Use: o, s, or c)");
|
||||
}
|
||||
}
|
||||
|
||||
wmove(win, oy, ox);
|
||||
wclrtoeol(win);
|
||||
|
||||
switch(*opt->iarg)
|
||||
{
|
||||
case INV_SLOW:
|
||||
waddstr(win, "Slow\n");
|
||||
break;
|
||||
|
||||
case INV_CLEAR:
|
||||
waddstr(win, "Clear Screen\n");
|
||||
break;
|
||||
|
||||
case INV_OVER:
|
||||
waddstr(win, "Overwrite\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
waddstr(win, "Unknown\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return(NORM);
|
||||
}
|
||||
683
urogue/pack.c
Normal file
683
urogue/pack.c
Normal file
|
|
@ -0,0 +1,683 @@
|
|||
/*
|
||||
pack.c - Routines to deal with the pack.
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
Based on "Advanced Rogue"
|
||||
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
|
||||
All rights reserved.
|
||||
|
||||
Based on "Rogue: Exploring the Dungeons of Doom"
|
||||
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
/*
|
||||
Notes
|
||||
|
||||
The new pack is implemented through the use of bags,
|
||||
and items are classed by their types (see rogue.h) which also
|
||||
happen to be their display character.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include "rogue.h"
|
||||
|
||||
#define ESCAPE_EXIT(x) if (x == ESCAPE) {after = FALSE; msg(""); return(NULL);}
|
||||
#define BAD_NEWS -1
|
||||
#define BAD_LIST ((struct linked_list *) BAD_NEWS)
|
||||
#define GOOD_NEWS 0
|
||||
|
||||
static char type_list[] = "!?])/=:,"; /* things to inventory */
|
||||
|
||||
/*
|
||||
swap_top()
|
||||
Takes an stacked object and exchanges places with the top
|
||||
object. <node> must belong to the <top>'s stacked object list.
|
||||
*/
|
||||
|
||||
void
|
||||
swap_top(struct linked_list *top, struct linked_list *node)
|
||||
{
|
||||
struct object *obt, *obn;
|
||||
|
||||
obt = OBJPTR(top);
|
||||
obn = OBJPTR(node);
|
||||
|
||||
detach((obt->next_obj), node); /* Take it out of the stack */
|
||||
attach(lvl_obj, node); /* and put it into the level */
|
||||
detach(lvl_obj, top); /* Remove item from level */
|
||||
|
||||
obn->next_obj = obt->next_obj;
|
||||
|
||||
if (obn->next_obj)
|
||||
obn->next_obj->l_prev = NULL;
|
||||
|
||||
attach((obn->next_obj), top);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
get_all()
|
||||
Get as many stacked items as possible.
|
||||
*/
|
||||
|
||||
void
|
||||
get_all(struct linked_list *top)
|
||||
{
|
||||
struct linked_list *node;
|
||||
struct object *obt;
|
||||
|
||||
while (top)
|
||||
{
|
||||
obt = OBJPTR(top);
|
||||
node = obt->next_obj;
|
||||
|
||||
rem_obj(top, FALSE);
|
||||
|
||||
if (!add_pack(top, FALSE))
|
||||
return;
|
||||
|
||||
top = node;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
get_stack()
|
||||
Allows the user to chose from a stack of items.
|
||||
*/
|
||||
|
||||
struct linked_list *
|
||||
get_stack(struct linked_list *item)
|
||||
{
|
||||
struct object *obj;
|
||||
char buf[2 * LINELEN];
|
||||
int i = 0, j;
|
||||
struct linked_list *ll;
|
||||
mpos = 0;
|
||||
obj = OBJPTR(item);
|
||||
|
||||
ll = obj->next_obj;
|
||||
|
||||
sprintf(buf, "You are standing on top of the following items: ");
|
||||
add_line(buf);
|
||||
sprintf(buf, "%d) -- %s", i, inv_name(obj, TRUE));
|
||||
add_line(buf);
|
||||
|
||||
while (ll)
|
||||
{
|
||||
i++;
|
||||
obj = OBJPTR(ll);
|
||||
sprintf(buf, "%d) -- %s", i, inv_name(obj, TRUE));
|
||||
add_line(buf);
|
||||
ll = next(ll);
|
||||
}
|
||||
|
||||
end_line();
|
||||
|
||||
msg("Which one do you want to pick up? [* for all] ");
|
||||
|
||||
switch(get_string(buf, cw))
|
||||
{
|
||||
case NORM:
|
||||
break;
|
||||
case QUIT: /* pick up nothing */
|
||||
msg("");
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (buf[0] == '*')
|
||||
{
|
||||
get_all(item);
|
||||
msg("");
|
||||
return(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
i = atoi(buf);
|
||||
|
||||
if (i)
|
||||
{
|
||||
obj = OBJPTR(item);
|
||||
ll = obj->next_obj;
|
||||
j = 1;
|
||||
|
||||
while (ll && (j != i))
|
||||
{
|
||||
ll = next(ll);
|
||||
j++;
|
||||
}
|
||||
|
||||
if (ll)
|
||||
{
|
||||
swap_top(item, ll);
|
||||
return(ll);
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("Got past last item while picking up.");
|
||||
return(item);
|
||||
}
|
||||
}
|
||||
else
|
||||
return (item);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
add_pack()
|
||||
Pick up an object and add it to the pack. If the argument is
|
||||
non-null use it as the linked_list pointer instead of getting it off the
|
||||
ground.
|
||||
*/
|
||||
|
||||
int
|
||||
add_pack(struct linked_list *item, int print_message)
|
||||
{
|
||||
struct object *obj, *op;
|
||||
int from_floor;
|
||||
|
||||
if (item == NULL)
|
||||
{
|
||||
from_floor = TRUE;
|
||||
|
||||
if ((item = find_obj(hero.y, hero.x)) == NULL)
|
||||
{
|
||||
msg("Nothing to pick up.");
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
from_floor = FALSE;
|
||||
|
||||
if (from_floor)
|
||||
{
|
||||
item = get_stack(item);
|
||||
|
||||
if (!item)
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
obj = OBJPTR(item);
|
||||
|
||||
/* If it is gold, just add its value to rogue's purse and get rid of */
|
||||
|
||||
if (obj->o_type == GOLD)
|
||||
{
|
||||
struct linked_list *mitem;
|
||||
struct thing *tp;
|
||||
|
||||
if (print_message)
|
||||
{
|
||||
if (!terse)
|
||||
addmsg("You found ");
|
||||
|
||||
msg("%d gold pieces.", obj->o_count);
|
||||
}
|
||||
|
||||
/*
|
||||
* First make sure no greedy monster is after this gold. If
|
||||
* so, make the monster run after the rogue instead.
|
||||
*/
|
||||
|
||||
for (mitem = mlist; mitem != NULL; mitem = next(mitem))
|
||||
{
|
||||
tp = THINGPTR(mitem);
|
||||
|
||||
if (tp->t_horde==obj)
|
||||
{
|
||||
tp->t_ischasing = TRUE;
|
||||
tp->t_chasee = &player;
|
||||
tp->t_horde = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This will cause problems if people are able to drop and
|
||||
* pick up gold, or when GOLDSTEAL monsters are killed.
|
||||
*/
|
||||
|
||||
/* Thieves get EXP for gold they pick up */
|
||||
|
||||
if (player.t_ctype == C_THIEF)
|
||||
{
|
||||
pstats.s_exp += obj->o_count / 4;
|
||||
check_level();
|
||||
}
|
||||
|
||||
purse += obj->o_count;
|
||||
|
||||
if (from_floor)
|
||||
rem_obj(item, TRUE); /* Remove object from the level */
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/* see if he can carry any more weight */
|
||||
|
||||
if (itemweight(obj) + pstats.s_pack > pstats.s_carry)
|
||||
{
|
||||
msg("Too much for you to carry.");
|
||||
|
||||
if (print_message)
|
||||
{
|
||||
msg("%s onto %s", terse ? "Moved" : "You moved",
|
||||
inv_name(obj, LOWERCASE));
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Link it into the pack. If the item can be grouped, try to find its
|
||||
* neighbors and bump the count. A special case is food, which can't
|
||||
* be grouped, but an exact match allows the count to get
|
||||
* incremented.
|
||||
*/
|
||||
|
||||
if ((op = apply_to_bag(pack, obj->o_type, bff_group, NULL, obj)) != NULL)
|
||||
{
|
||||
op->o_count += obj->o_count; /* add it to the rest */
|
||||
|
||||
if (from_floor)
|
||||
rem_obj(item, FALSE);
|
||||
|
||||
pack_report(op, print_message, "You now have ");
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/* Check for and deal with scare monster scrolls */
|
||||
|
||||
if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
|
||||
if (obj->o_flags & ISCURSED)
|
||||
{
|
||||
msg("The scroll turns to dust as you pick it up.");
|
||||
rem_obj(item, TRUE);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/* Check if there is room */
|
||||
|
||||
if (count_bag(pack, obj->o_type, NULL) == max_print())
|
||||
{
|
||||
msg("You have no room for more %s.", name_type(obj->o_type));
|
||||
|
||||
if (print_message)
|
||||
{
|
||||
obj = OBJPTR(item);
|
||||
msg("%s onto %s.", terse ? "Moved" : "You moved",
|
||||
inv_name(obj, LOWERCASE));
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* finally, add the new item to the bag, and free up the linked list
|
||||
* on top of it.
|
||||
*/
|
||||
|
||||
if (from_floor)
|
||||
rem_obj(item, FALSE);
|
||||
|
||||
push_bag(&pack, obj);
|
||||
pack_report(obj, print_message, "You now have ");
|
||||
ur_free(item);
|
||||
|
||||
return(TRUE); /* signal success */
|
||||
}
|
||||
|
||||
/*
|
||||
pack_report()
|
||||
Notify the user about the results of the pack operation and do some
|
||||
post processing.
|
||||
*/
|
||||
|
||||
void
|
||||
pack_report(object *obj, int print_message, char *message)
|
||||
{
|
||||
/* Notify the user */
|
||||
|
||||
if (print_message)
|
||||
{
|
||||
if (!terse)
|
||||
addmsg(message);
|
||||
|
||||
msg("(%c%c) %s.", obj->o_type, print_letters[get_ident(obj)],
|
||||
inv_name(obj, !terse));
|
||||
}
|
||||
|
||||
if (obj->o_type == ARTIFACT)
|
||||
{
|
||||
has_artifact |= (1 << obj->o_which);
|
||||
picked_artifact |= (1 << obj->o_which);
|
||||
|
||||
if (!(obj->ar_flags & ISUSED))
|
||||
{
|
||||
obj->ar_flags |= ISUSED;
|
||||
pstats.s_exp += arts[obj->o_which].ar_worth / 10;
|
||||
check_level();
|
||||
}
|
||||
}
|
||||
|
||||
updpack();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
inventory()
|
||||
list what is in the pack
|
||||
*/
|
||||
|
||||
void
|
||||
inventory(struct linked_list *container, int type)
|
||||
{
|
||||
int cnt;
|
||||
|
||||
if (type == 0)
|
||||
{
|
||||
msg("What kind of item <%s> to inventory (* for all)?", type_list);
|
||||
|
||||
type = readchar();
|
||||
|
||||
if (type == ESCAPE)
|
||||
{
|
||||
after = FALSE;
|
||||
msg("");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a list of items to print out. If the user selects '*', list
|
||||
* them all.
|
||||
*/
|
||||
|
||||
if (type == '*')
|
||||
type = 0; /* no type passed ->use them all */
|
||||
|
||||
mpos = 0;
|
||||
|
||||
if ((cnt = count_bag(container, type, NULL)) == 0)
|
||||
msg("You don't have any %s.", name_type(type));
|
||||
else
|
||||
{
|
||||
apply_to_bag(container, type, NULL, baf_print_item, &type);
|
||||
end_line();
|
||||
msg("");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
pick_up()
|
||||
Add something to characters pack.
|
||||
*/
|
||||
|
||||
void
|
||||
pick_up(char ch)
|
||||
{
|
||||
switch(ch)
|
||||
{
|
||||
default:
|
||||
debug("Where did you pick that up???");
|
||||
break;
|
||||
|
||||
case GOLD:
|
||||
case ARMOR:
|
||||
case POTION:
|
||||
case FOOD:
|
||||
case WEAPON:
|
||||
case SCROLL:
|
||||
case ARTIFACT:
|
||||
case RING:
|
||||
case STICK:
|
||||
add_pack(NULL, MESSAGE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
get_object()
|
||||
|
||||
Pick something out of a pack for a purpose. The basic idea is to
|
||||
list all the possibilities, let the user select one, get that item
|
||||
from the container, and pass it back to the calling routine.
|
||||
*/
|
||||
|
||||
struct object *
|
||||
get_object(struct linked_list *container, char *purpose, int type, int (*bff_p)(struct object *obj, bag_arg *junk))
|
||||
/* char *container; what container has what we want */
|
||||
/* char *purpose; a message (verb) to print if we cant find any */
|
||||
/* char type; type (o_type) to pick out (NULL = any) */
|
||||
/* int (*bff_p) (); bag filter function to test item */
|
||||
{
|
||||
struct object *obj_p = NULL;
|
||||
char sel_id; /* selected type and id */
|
||||
int sel_type;
|
||||
char response;
|
||||
|
||||
if (container == NULL)
|
||||
{
|
||||
msg("There isn't anything in there.");
|
||||
after = FALSE;
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Make sure we have at least one item that qualifies! */
|
||||
|
||||
if (apply_to_bag(container, type, bff_p, NULL, NULL) == NULL)
|
||||
{
|
||||
msg("You seem to have nothing to %s.", purpose);
|
||||
after = FALSE;
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
while (obj_p == NULL)
|
||||
{
|
||||
if (type == 0)
|
||||
{
|
||||
msg("What kind of item <%s> do you want to %s (* for list)?", type_list, purpose);
|
||||
|
||||
response = readchar();
|
||||
ESCAPE_EXIT(response);
|
||||
msg("");
|
||||
|
||||
if (response == '*')
|
||||
{
|
||||
add_line("! Potion");
|
||||
add_line("? Scroll");
|
||||
add_line("= Ring");
|
||||
add_line("/ Stick");
|
||||
add_line("] Armor");
|
||||
add_line(") Weapon");
|
||||
add_line(": Food");
|
||||
end_line();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (!is_member(type_list, response)) { beep();
|
||||
continue; }
|
||||
|
||||
|
||||
if (count_bag(container, response, NULL) == 0)
|
||||
{
|
||||
msg("You don't have any %s.", name_type(response));
|
||||
continue;
|
||||
}
|
||||
|
||||
type = response;
|
||||
}
|
||||
|
||||
while(obj_p == NULL)
|
||||
{
|
||||
msg("What item do you want to %s (* for list)?", purpose);
|
||||
response = readchar();
|
||||
msg("");
|
||||
ESCAPE_EXIT(response);
|
||||
|
||||
if (response == '*')
|
||||
{
|
||||
mpos = 0;
|
||||
apply_to_bag(container, type, bff_p, baf_print_item, &type);
|
||||
end_line();
|
||||
continue;
|
||||
}
|
||||
|
||||
sel_type = type;
|
||||
sel_id = response;
|
||||
|
||||
obj_p = scan_bag(container, sel_type,unprint_id(&sel_id));
|
||||
}
|
||||
}
|
||||
|
||||
mpos = 0;
|
||||
msg("");
|
||||
return(obj_p);
|
||||
}
|
||||
|
||||
/*
|
||||
get_item()
|
||||
|
||||
This is only an interim function that serves as an interface to
|
||||
the old function get_item and its replacement get_object. It
|
||||
assumes a NULL action routine and allocates a linked_list
|
||||
structure on top of the object pointer.
|
||||
*/
|
||||
|
||||
struct linked_list *
|
||||
get_item(char *purpose, int type)
|
||||
{
|
||||
struct object *obj_p;
|
||||
|
||||
if ((obj_p = get_object(pack, purpose, type, NULL)) == NULL)
|
||||
return(NULL);
|
||||
|
||||
return(make_item(obj_p));
|
||||
}
|
||||
|
||||
/*
|
||||
del_pack()
|
||||
Take something out of the hero's pack and throw it away.
|
||||
*/
|
||||
|
||||
void
|
||||
del_pack(struct linked_list *what)
|
||||
{
|
||||
rem_pack(OBJPTR(what));
|
||||
discard(what);
|
||||
}
|
||||
|
||||
/*
|
||||
discard_pack
|
||||
take an object from the pack and throw it away (like del_pack,
|
||||
but without the linked_list structure)
|
||||
*/
|
||||
|
||||
void
|
||||
discard_pack(struct object *obj_p)
|
||||
{
|
||||
rem_pack(obj_p);
|
||||
throw_away(obj_p);
|
||||
}
|
||||
|
||||
/*
|
||||
rem_pack()
|
||||
Removes an item from the pack.
|
||||
*/
|
||||
|
||||
void
|
||||
rem_pack(struct object *obj_p)
|
||||
{
|
||||
cur_null(obj_p); /* check for current stuff */
|
||||
pop_bag(&pack, obj_p);
|
||||
updpack();
|
||||
return; /* tell caller an item has been removed */
|
||||
}
|
||||
|
||||
/*
|
||||
cur_null()
|
||||
This updates cur_weapon etc for dropping things
|
||||
*/
|
||||
|
||||
void
|
||||
cur_null(struct object *op)
|
||||
{
|
||||
if (op == cur_weapon)
|
||||
cur_weapon = NULL;
|
||||
else if (op == cur_armor)
|
||||
cur_armor = NULL;
|
||||
else if (op == cur_ring[LEFT_1])
|
||||
cur_ring[LEFT_1] = NULL;
|
||||
else if (op == cur_ring[LEFT_2])
|
||||
cur_ring[LEFT_2] = NULL;
|
||||
else if (op == cur_ring[LEFT_3])
|
||||
cur_ring[LEFT_3] = NULL;
|
||||
else if (op == cur_ring[LEFT_4])
|
||||
cur_ring[LEFT_4] = NULL;
|
||||
else if (op == cur_ring[LEFT_5])
|
||||
cur_ring[LEFT_5] = NULL;
|
||||
else if (op == cur_ring[RIGHT_1])
|
||||
cur_ring[RIGHT_1] = NULL;
|
||||
else if (op == cur_ring[RIGHT_2])
|
||||
cur_ring[RIGHT_2] = NULL;
|
||||
else if (op == cur_ring[RIGHT_3])
|
||||
cur_ring[RIGHT_3] = NULL;
|
||||
else if (op == cur_ring[RIGHT_4])
|
||||
cur_ring[RIGHT_4] = NULL;
|
||||
else if (op == cur_ring[RIGHT_5])
|
||||
cur_ring[RIGHT_5] = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
idenpack()
|
||||
Identify all the items in the pack
|
||||
*/
|
||||
|
||||
void
|
||||
idenpack(void)
|
||||
{
|
||||
apply_to_bag(pack, 0, NULL, baf_identify, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
show_floor()
|
||||
Print out the item on the floor. Used by the move command.
|
||||
*/
|
||||
|
||||
void
|
||||
show_floor(void)
|
||||
{
|
||||
struct linked_list *item;
|
||||
struct object *obj;
|
||||
|
||||
item = find_obj(hero.y, hero.x);
|
||||
|
||||
if (item != NULL)
|
||||
{
|
||||
addmsg("%s onto ", terse ? "Moved" : "You moved");
|
||||
|
||||
obj = OBJPTR(item);
|
||||
|
||||
if (obj->next_obj != NULL)
|
||||
msg("a stack of things.");
|
||||
else if (obj->o_type == GOLD)
|
||||
msg("%d gold pieces.", obj->o_count);
|
||||
else
|
||||
{
|
||||
addmsg(inv_name(obj, TRUE));
|
||||
addmsg(".");
|
||||
endmsg();
|
||||
}
|
||||
}
|
||||
}
|
||||
320
urogue/passages.c
Normal file
320
urogue/passages.c
Normal file
|
|
@ -0,0 +1,320 @@
|
|||
/*
|
||||
passages.c - Draw the connecting passages
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
Based on "Advanced Rogue"
|
||||
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
|
||||
All rights reserved.
|
||||
|
||||
Based on "Rogue: Exploring the Dungeons of Doom"
|
||||
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "rogue.h"
|
||||
|
||||
#define cmov(xy) move((xy).y, (xy).x)
|
||||
|
||||
/*
|
||||
do_passages()
|
||||
Draw all the passages on a level.
|
||||
*/
|
||||
|
||||
void
|
||||
do_passages(void)
|
||||
{
|
||||
struct rdes *r1, *r2 = NULL;
|
||||
int i, j;
|
||||
int roomcount;
|
||||
|
||||
static struct rdes rdes[MAXROOMS] =
|
||||
{
|
||||
{{ 0, 1, 0, 1, 0, 0, 0, 0, 0},
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0},
|
||||
{{ 1, 0, 1, 0, 1, 0, 0, 0, 0},
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0},
|
||||
{{ 0, 1, 0, 0, 0, 1, 0, 0, 0},
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0},
|
||||
{{ 1, 0, 0, 0, 1, 0, 1, 0, 0},
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0},
|
||||
{{ 0, 1, 0, 1, 0, 1, 0, 1, 0},
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0},
|
||||
{{ 0, 0, 1, 0, 1, 0, 0, 0, 1},
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0},
|
||||
{{ 0, 0, 0, 1, 0, 0, 0, 1, 0},
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0},
|
||||
{{ 0, 0, 0, 0, 1, 0, 1, 0, 1},
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0},
|
||||
{{ 0, 0, 0, 0, 0, 1, 0, 1, 0},
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0}
|
||||
};
|
||||
|
||||
/* reinitialize room graph description */
|
||||
|
||||
for (r1 = rdes; r1 < &rdes[MAXROOMS]; r1++)
|
||||
{
|
||||
for (j = 0; j < MAXROOMS; j++)
|
||||
r1->isconn[j] = FALSE;
|
||||
|
||||
r1->ingraph = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* starting with one room, connect it to a random adjacent room and
|
||||
* then pick a new room to start with.
|
||||
*/
|
||||
|
||||
roomcount = 1;
|
||||
r1 = &rdes[rnd(MAXROOMS)];
|
||||
r1->ingraph = TRUE;
|
||||
|
||||
do
|
||||
{
|
||||
j = 0;
|
||||
|
||||
for (i = 0; i < MAXROOMS; i++)
|
||||
if (r1->conn[i] && !rdes[i].ingraph && rnd(++j) == 0)
|
||||
r2 = &rdes[i];
|
||||
|
||||
/*
|
||||
* if no adjacent rooms are outside the graph, pick a new
|
||||
* room to look from
|
||||
*/
|
||||
|
||||
if (j == 0)
|
||||
do
|
||||
{
|
||||
r1 = &rdes[rnd(MAXROOMS)];
|
||||
}
|
||||
while (!r1->ingraph);
|
||||
|
||||
/*
|
||||
* otherwise, connect new room to the graph, and draw a
|
||||
* tunnel to it
|
||||
*/
|
||||
else
|
||||
{
|
||||
r2->ingraph = TRUE;
|
||||
i = (int)(r1 - rdes);
|
||||
j = (int)(r2 - rdes);
|
||||
conn(i, j);
|
||||
r1->isconn[j] = TRUE;
|
||||
r2->isconn[i] = TRUE;
|
||||
roomcount++;
|
||||
}
|
||||
}
|
||||
while (roomcount < MAXROOMS);
|
||||
|
||||
/*
|
||||
* attempt to add passages to the graph a random number of times so
|
||||
* that there isn't just one unique passage through it.
|
||||
*/
|
||||
|
||||
for (roomcount = rnd(5); roomcount > 0; roomcount--)
|
||||
{
|
||||
r1 = &rdes[rnd(MAXROOMS)]; /* a random room to look from */
|
||||
|
||||
/*
|
||||
* find an adjacent room not already connected
|
||||
*/
|
||||
|
||||
j = 0;
|
||||
for (i = 0; i < MAXROOMS; i++)
|
||||
if (r1->conn[i] && !r1->isconn[i] && rnd(++j) == 0)
|
||||
r2 = &rdes[i];
|
||||
|
||||
/*
|
||||
* if there is one, connect it and look for the next added
|
||||
* passage
|
||||
*/
|
||||
|
||||
if (j != 0)
|
||||
{
|
||||
i = (int)(r1 - rdes);
|
||||
j = (int)(r2 - rdes);
|
||||
conn(i, j);
|
||||
r1->isconn[j] = TRUE;
|
||||
r2->isconn[i] = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
conn()
|
||||
Draw a corridor from a room in a certain direction.
|
||||
*/
|
||||
|
||||
void
|
||||
conn(int r1, int r2)
|
||||
{
|
||||
struct room *rpf, *rpt = NULL;
|
||||
int rmt;
|
||||
int distance = 0, turn_spot = 0, turn_distance = 0;
|
||||
int rm;
|
||||
char direc;
|
||||
coord delt = {0,0}, curr, turn_delta = {0,0}, spos = {0,0}, epos = {0,0};
|
||||
|
||||
if (r1 < r2)
|
||||
{
|
||||
rm = r1;
|
||||
|
||||
if (r1 + 1 == r2)
|
||||
direc = 'r';
|
||||
else
|
||||
direc = 'd';
|
||||
}
|
||||
else
|
||||
{
|
||||
rm = r2;
|
||||
|
||||
if (r2 + 1 == r1)
|
||||
direc = 'r';
|
||||
else
|
||||
direc = 'd';
|
||||
}
|
||||
|
||||
rpf = &rooms[rm];
|
||||
|
||||
/*
|
||||
* Set up the movement variables, in two cases: first drawing one
|
||||
* down.
|
||||
*/
|
||||
|
||||
if (direc == 'd')
|
||||
{
|
||||
rmt = rm + 3; /* room # of dest */
|
||||
rpt = &rooms[rmt]; /* room pointer of dest */
|
||||
delt.x = 0; /* direction of move */
|
||||
delt.y = 1;
|
||||
spos.x = rpf->r_pos.x; /* start of move */
|
||||
spos.y = rpf->r_pos.y;
|
||||
epos.x = rpt->r_pos.x; /* end of move */
|
||||
epos.y = rpt->r_pos.y;
|
||||
|
||||
if (!(rpf->r_flags & ISGONE)) /* if not gone pick door pos */
|
||||
{
|
||||
spos.x += rnd(rpf->r_max.x - 2) + 1;
|
||||
spos.y += rpf->r_max.y - 1;
|
||||
}
|
||||
|
||||
if (!(rpt->r_flags & ISGONE))
|
||||
epos.x += rnd(rpt->r_max.x - 2) + 1;
|
||||
|
||||
distance = abs(spos.y - epos.y) - 1; /* distance to move */
|
||||
turn_delta.y = 0; /* direction to turn */
|
||||
turn_delta.x = (spos.x < epos.x ? 1 : -1);
|
||||
turn_distance = abs(spos.x - epos.x); /* how far to turn */
|
||||
turn_spot = rnd(distance - 1) + 1; /* where turn starts */
|
||||
}
|
||||
else if (direc == 'r') /* setup for moving right */
|
||||
{
|
||||
rmt = rm + 1;
|
||||
rpt = &rooms[rmt];
|
||||
delt.x = 1;
|
||||
delt.y = 0;
|
||||
spos.x = rpf->r_pos.x;
|
||||
spos.y = rpf->r_pos.y;
|
||||
epos.x = rpt->r_pos.x;
|
||||
epos.y = rpt->r_pos.y;
|
||||
|
||||
if (!(rpf->r_flags & ISGONE))
|
||||
{
|
||||
spos.x += rpf->r_max.x - 1;
|
||||
spos.y += rnd(rpf->r_max.y - 2) + 1;
|
||||
}
|
||||
|
||||
if (!(rpt->r_flags & ISGONE))
|
||||
epos.y += rnd(rpt->r_max.y - 2) + 1;
|
||||
|
||||
distance = abs(spos.x - epos.x) - 1;
|
||||
turn_delta.y = (spos.y < epos.y ? 1 : -1);
|
||||
turn_delta.x = 0;
|
||||
turn_distance = abs(spos.y - epos.y);
|
||||
turn_spot = rnd(distance - 1) + 1;
|
||||
}
|
||||
else
|
||||
debug("Error in connection tables.");
|
||||
|
||||
/*
|
||||
* Draw in the doors on either side of the passage or just put #'s if
|
||||
* the rooms are gone.
|
||||
*/
|
||||
|
||||
if (!(rpf->r_flags & ISGONE))
|
||||
door(rpf, &spos);
|
||||
else
|
||||
{
|
||||
cmov(spos);
|
||||
addch('#');
|
||||
}
|
||||
|
||||
if (!(rpt->r_flags & ISGONE))
|
||||
door(rpt, &epos);
|
||||
else
|
||||
{
|
||||
cmov(epos);
|
||||
addch('#');
|
||||
}
|
||||
|
||||
/* Get ready to move... */
|
||||
|
||||
curr.x = spos.x;
|
||||
curr.y = spos.y;
|
||||
|
||||
while (distance)
|
||||
{
|
||||
/* Move to new position */
|
||||
|
||||
curr.x += delt.x;
|
||||
curr.y += delt.y;
|
||||
|
||||
/* Check if we are at the turn place, if so do the turn */
|
||||
|
||||
if (distance == turn_spot && turn_distance > 0)
|
||||
while (turn_distance--)
|
||||
{
|
||||
cmov(curr);
|
||||
addch(PASSAGE);
|
||||
curr.x += turn_delta.x;
|
||||
curr.y += turn_delta.y;
|
||||
}
|
||||
|
||||
/* Continue digging along */
|
||||
|
||||
cmov(curr);
|
||||
addch(PASSAGE);
|
||||
distance--;
|
||||
}
|
||||
|
||||
curr.x += delt.x;
|
||||
curr.y += delt.y;
|
||||
|
||||
if (!ce(curr, epos))
|
||||
msg("Warning, connectivity problem on this level.");
|
||||
}
|
||||
|
||||
/*
|
||||
door()
|
||||
Add a door or possibly a secret door also enters the door in the exits
|
||||
array of the room.
|
||||
*/
|
||||
|
||||
void
|
||||
door(struct room *rm, coord *cp)
|
||||
{
|
||||
char a_door;
|
||||
|
||||
cmov(*cp);
|
||||
|
||||
a_door = (rnd(10)<level - 1 && rnd(100) < 20) ? SECRETDOOR : DOOR;
|
||||
|
||||
addch(a_door);
|
||||
|
||||
rm->r_exit[rm->r_nexits++] = *cp;
|
||||
}
|
||||
538
urogue/player.c
Normal file
538
urogue/player.c
Normal file
|
|
@ -0,0 +1,538 @@
|
|||
/*
|
||||
player.c - functions for dealing with special player abilities
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
Based on "Advanced Rogue"
|
||||
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
|
||||
All rights reserved.
|
||||
|
||||
Based on "Rogue: Exploring the Dungeons of Doom"
|
||||
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* Pray to a deity
|
||||
*
|
||||
* 00-10 Good stuff happens
|
||||
* 11-40 A good deity answers
|
||||
* 41-60 Nothing happens
|
||||
* 61-90 A bad deity answers, but with good results
|
||||
* 91-99 You were better off before
|
||||
*/
|
||||
|
||||
void
|
||||
prayer(void)
|
||||
{
|
||||
int chance, i, times;
|
||||
char num_str[20];
|
||||
int ch;
|
||||
struct linked_list *item;
|
||||
struct thing *tp;
|
||||
int is_godly;
|
||||
|
||||
if (player.t_praycnt > pstats.s_lvl)
|
||||
{
|
||||
msg("Are you sure you want to bother the gods?");
|
||||
ch = readchar();
|
||||
|
||||
if (tolower(ch) != 'y')
|
||||
{
|
||||
after = FALSE;
|
||||
return;
|
||||
}
|
||||
else
|
||||
msg("Here goes...");
|
||||
}
|
||||
|
||||
msg("You are surrounded by orange smoke...");
|
||||
|
||||
if (rnd(3) == 0)
|
||||
luck--;
|
||||
|
||||
if (is_wearing(R_PIETY) || (rnd(luck) == 0 &&
|
||||
(player.t_ctype == C_DRUID || player.t_ctype == C_CLERIC ||
|
||||
((player.t_ctype == C_PALADIN || player.t_ctype == C_RANGER)
|
||||
&& pstats.s_lvl > 8))))
|
||||
is_godly = ISBLESSED;
|
||||
else
|
||||
is_godly = ISNORMAL;
|
||||
|
||||
if (is_wearing(R_PIETY))
|
||||
player.t_praycnt += rnd(2);
|
||||
else
|
||||
player.t_praycnt++;
|
||||
|
||||
if (wizard)
|
||||
{
|
||||
msg("What roll?[0..%d] ", 99);
|
||||
ch = get_string(num_str, cw);
|
||||
|
||||
if (ch == QUIT)
|
||||
{
|
||||
msg("");
|
||||
return;
|
||||
}
|
||||
chance = atoi(num_str);
|
||||
}
|
||||
else
|
||||
{
|
||||
chance = rnd(100) + roll(10, luck) - 5;
|
||||
|
||||
if (player.t_praycnt > pstats.s_lvl)
|
||||
chance += 50;
|
||||
|
||||
if (is_godly)
|
||||
chance -= 50;
|
||||
}
|
||||
|
||||
chance = max(0, min(chance, 100));
|
||||
|
||||
if (chance == 0)
|
||||
{
|
||||
msg("The heavens open and glorious radiance surrounds you!");
|
||||
|
||||
pstats.s_hpt = max_stats.s_hpt;
|
||||
pstats.s_power = max_stats.s_power;
|
||||
|
||||
if (is_godly)
|
||||
times = 8;
|
||||
else
|
||||
times = 1;
|
||||
|
||||
/*
|
||||
* kill all monsters surrounding the hero except unique ones
|
||||
* This will change when I implement the deity option. If
|
||||
* The deity is "stronger" than the unique monster, then the
|
||||
* monster will be killed.
|
||||
*/
|
||||
|
||||
for (i = 0; i < times; i++)
|
||||
{
|
||||
item = f_mons_a(player.t_pos.y, player.t_pos.x, TRUE);
|
||||
|
||||
if (item)
|
||||
{
|
||||
tp = THINGPTR(item);
|
||||
|
||||
msg("A bolt of eldritch energy strikes down the %s!",
|
||||
monsters[tp->t_index].m_name);
|
||||
|
||||
killed(NULL, item, NOMESSAGE, POINTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (chance == 2)
|
||||
{
|
||||
msg("Aule, Lord of Crafts, hears your call.");
|
||||
read_scroll(&player, S_MAKEITEMEM, is_godly);
|
||||
}
|
||||
|
||||
/* Save 3-9 for other wonderful stuff */
|
||||
else if (chance < 15)
|
||||
{
|
||||
msg("Orome, Lord of Forests, hears your call.");
|
||||
read_scroll(&player, S_SUMMON, is_godly);
|
||||
}
|
||||
else if (chance < 20)
|
||||
{
|
||||
msg("Hermes, the Winged Messenger, hears your call.");
|
||||
quaff(&player, P_HASTE, is_godly);
|
||||
}
|
||||
else if (chance < 25)
|
||||
{
|
||||
msg("Lorien, Master of Dreams, hears your call.");
|
||||
read_scroll(&player, S_SLEEP, is_godly);
|
||||
}
|
||||
else if (chance < 30)
|
||||
{
|
||||
msg("Este, Lady of Healing, hears your call.");
|
||||
quaff(&player, P_RESTORE, is_godly);
|
||||
quaff(&player, P_HEALING, is_godly);
|
||||
}
|
||||
else if (chance < 35)
|
||||
{
|
||||
msg("Thor, God of Thunder, hears your call.");
|
||||
msg("A bolt of lighting strikes you!");
|
||||
read_scroll(&player, S_ELECTRIFY, is_godly);
|
||||
}
|
||||
else if (chance < 40)
|
||||
{
|
||||
msg("Lorien, Master of Illusion, hears your call.");
|
||||
quaff(&player, P_DISGUISE, is_godly);
|
||||
}
|
||||
else if (chance < 60) /* Nothing happens */
|
||||
{
|
||||
msg("Boccob, the Uncaring, ignores you.");
|
||||
}
|
||||
|
||||
/* You don't really want one of these gods answering your call */
|
||||
|
||||
else if (chance < 65)
|
||||
{
|
||||
msg("Jubilex, Master of Slimes and Oozes, hears your call.");
|
||||
read_scroll(&player, S_HOLD, is_godly);
|
||||
luck++;
|
||||
}
|
||||
else if (chance < 70)
|
||||
{
|
||||
msg("Sauron, Lord of the Ring, hears your call.");
|
||||
quaff(&player, P_INVIS, is_godly);
|
||||
luck++;
|
||||
}
|
||||
else if (chance < 75)
|
||||
{
|
||||
msg("Orcus, Lord of Undead, hears your call.");
|
||||
quaff(&player, P_PHASE, is_godly);
|
||||
luck++;
|
||||
}
|
||||
else if (chance < 80)
|
||||
{
|
||||
msg("Incabulos, God of Evil Sendings, hears your call.");
|
||||
quaff(&player, P_CLEAR, is_godly);
|
||||
luck++;
|
||||
}
|
||||
else if (chance < 85)
|
||||
{
|
||||
msg("Raxivort, Night Flutterer, hears your call.");
|
||||
quaff(&player, P_SEEINVIS, is_godly);
|
||||
luck++;
|
||||
}
|
||||
else if (chance < 90)
|
||||
{
|
||||
msg("Morgoth, Lord of Fire, hears your call.");
|
||||
quaff(&player, P_FIRERESIST, is_godly);
|
||||
luck++;
|
||||
}
|
||||
else if (chance < 100) /* You are in for it now! */
|
||||
{
|
||||
msg("You fall into a horrible trance-like state.");
|
||||
no_command += SLEEPTIME;
|
||||
}
|
||||
if (chance == 100)
|
||||
{
|
||||
msg("The heavens open - but wait!");
|
||||
msg("A bolt of eldritch energy strikes you!");
|
||||
|
||||
if (pstats.s_hpt > 1)
|
||||
pstats.s_hpt /= 2;
|
||||
|
||||
msg("The gods must be angry with you.");
|
||||
}
|
||||
}
|
||||
|
||||
/* Routines for thieves */
|
||||
|
||||
/*
|
||||
gsense()
|
||||
Sense gold returns TRUE if gold was detected
|
||||
*/
|
||||
|
||||
int
|
||||
gsense(void)
|
||||
{
|
||||
if (lvl_obj != NULL)
|
||||
{
|
||||
struct linked_list *gitem;
|
||||
struct object *cur;
|
||||
int gtotal = 0;
|
||||
|
||||
wclear(hw);
|
||||
|
||||
for (gitem = lvl_obj; gitem != NULL; gitem = next(gitem))
|
||||
{
|
||||
cur = OBJPTR(gitem);
|
||||
|
||||
if (cur->o_type == GOLD)
|
||||
{
|
||||
gtotal += cur->o_count;
|
||||
mvwaddch(hw, cur->o_pos.y, cur->o_pos.x, GOLD);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (gtotal)
|
||||
{
|
||||
msg("You sense gold!");
|
||||
overlay(hw, cw);
|
||||
return(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
nothing_message(ISNORMAL);
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
is_stealth()
|
||||
is player quiet about something
|
||||
*/
|
||||
|
||||
int
|
||||
is_stealth(struct thing *tp)
|
||||
{
|
||||
return (rnd(25) < tp->t_stats.s_dext ||
|
||||
(tp == &player && is_wearing(R_STEALTH)));
|
||||
}
|
||||
|
||||
/*
|
||||
steal()
|
||||
Steal in direction given in delta
|
||||
*/
|
||||
|
||||
void
|
||||
steal(void)
|
||||
{
|
||||
struct linked_list *item;
|
||||
struct thing *tp;
|
||||
coord new_pos;
|
||||
short thief_bonus;
|
||||
char *unsuccess = "";
|
||||
char *gain = "";
|
||||
char *notice = "is not";
|
||||
|
||||
new_pos.y = hero.y + delta.y;
|
||||
new_pos.x = hero.x + delta.x;
|
||||
|
||||
/* Anything there? */
|
||||
|
||||
if (new_pos.y < 0 || new_pos.y > LINES - 3 ||
|
||||
new_pos.x < 0 || new_pos.x > COLS - 1 ||
|
||||
mvwinch(mw, new_pos.y, new_pos.x) == ' ')
|
||||
{
|
||||
msg("There is no one to steal from.");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((item = find_mons(new_pos.y, new_pos.x)) == NULL)
|
||||
return;
|
||||
|
||||
tp = THINGPTR(item);
|
||||
|
||||
/* Can player steal something unnoticed? */
|
||||
|
||||
if (player.t_ctype == C_THIEF || player.t_ctype == C_NINJA)
|
||||
thief_bonus = 10;
|
||||
else
|
||||
thief_bonus = -50;
|
||||
|
||||
if (rnd(50) >= 3 * pstats.s_dext + thief_bonus)
|
||||
{
|
||||
chase_it(&new_pos, &player);
|
||||
turn_off(*tp, ISFRIENDLY);
|
||||
notice = "is";
|
||||
}
|
||||
|
||||
if (rnd(100) <
|
||||
(thief_bonus + 2 * pstats.s_dext + 5 * pstats.s_lvl -
|
||||
5 * (tp->t_stats.s_lvl - 3)))
|
||||
{
|
||||
struct linked_list *s_item, *pack_ptr;
|
||||
int cnt = 0;
|
||||
|
||||
s_item = NULL; /* Start stolen goods out as nothing */
|
||||
|
||||
/* Find a good item to take */
|
||||
|
||||
if (tp->t_pack != NULL)
|
||||
{
|
||||
/* Count up the number of items in the monster's pack */
|
||||
|
||||
for (pack_ptr = tp->t_pack; pack_ptr != NULL; pack_ptr = next(pack_ptr))
|
||||
cnt++;
|
||||
|
||||
/* Pick one */
|
||||
cnt = rnd(cnt);
|
||||
|
||||
/* Take it from the monster */
|
||||
|
||||
for (pack_ptr = tp->t_pack; --cnt == 0; pack_ptr = next(pack_ptr))
|
||||
;
|
||||
|
||||
s_item = pack_ptr;
|
||||
detach(tp->t_pack, s_item);
|
||||
|
||||
/* Give it to player */
|
||||
|
||||
if (add_pack(s_item, MESSAGE) == FALSE)
|
||||
{
|
||||
(OBJPTR(s_item))->o_pos = hero;
|
||||
fall(&player, s_item, TRUE, FALSE);
|
||||
}
|
||||
|
||||
/* Get points for stealing from unfriendly monsters */
|
||||
|
||||
if (off(*tp, ISFRIENDLY))
|
||||
{
|
||||
if (player.t_ctype == C_THIEF)
|
||||
pstats.s_exp += 2 * tp->t_stats.s_exp / 3;
|
||||
else
|
||||
pstats.s_exp += tp->t_stats.s_exp / min(pstats.s_lvl, 10);
|
||||
|
||||
check_level();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gain = " gains you nothing and";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsuccess = " unsuccessful";
|
||||
}
|
||||
|
||||
msg("Your%s attempt%s %s noticed.", unsuccess, gain, notice);
|
||||
}
|
||||
|
||||
/*
|
||||
affect()
|
||||
cleric affecting undead
|
||||
*/
|
||||
|
||||
void
|
||||
affect(void)
|
||||
{
|
||||
struct linked_list *item;
|
||||
struct thing *tp;
|
||||
char *mname;
|
||||
coord new_pos;
|
||||
int is_godly;
|
||||
int effective_level;
|
||||
|
||||
if (player.t_ctype != C_CLERIC && player.t_ctype != C_PALADIN &&
|
||||
!is_wearing(R_PIETY))
|
||||
{
|
||||
msg("Only clerics and paladins can affect undead.");
|
||||
return;
|
||||
}
|
||||
|
||||
is_godly = (player.t_ctype == C_CLERIC || player.t_ctype == C_PALADIN);
|
||||
|
||||
if (is_godly && is_wearing(R_PIETY))
|
||||
effective_level = 2 * pstats.s_lvl;
|
||||
else
|
||||
effective_level = pstats.s_lvl;
|
||||
|
||||
new_pos.y = hero.y + delta.y;
|
||||
new_pos.x = hero.x + delta.x;
|
||||
|
||||
/* Anything there? */
|
||||
|
||||
if (new_pos.y < 0 || new_pos.y > LINES - 3 ||
|
||||
new_pos.x < 0 || new_pos.x > COLS - 1 ||
|
||||
mvwinch(mw, new_pos.y, new_pos.x) == ' ')
|
||||
{
|
||||
msg("Nothing to affect.");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((item = find_mons(new_pos.y, new_pos.x)) == NULL)
|
||||
{
|
||||
debug("Affect what @ %d,%d?", new_pos.y, new_pos.x);
|
||||
return;
|
||||
}
|
||||
|
||||
tp = THINGPTR(item);
|
||||
mname = monsters[tp->t_index].m_name;
|
||||
|
||||
if (off(*tp, ISUNDEAD))
|
||||
{
|
||||
msg("Your holy symbol has no effect on the %s.", mname);
|
||||
goto annoy;
|
||||
}
|
||||
|
||||
if (on(*tp, WASTURNED))
|
||||
{
|
||||
msg("Your holy symbol merely enrages the %s.", mname);
|
||||
goto annoy;
|
||||
}
|
||||
|
||||
/* Can cleric destroy it? */
|
||||
|
||||
if (effective_level >= 3 * tp->t_stats.s_lvl)
|
||||
{
|
||||
msg("You have destroyed the %s.", mname);
|
||||
killed(&player, item, NOMESSAGE, POINTS);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Can cleric turn it? */
|
||||
|
||||
if (rnd(100) + 1 >
|
||||
(100 * ((2 * tp->t_stats.s_lvl) - effective_level)) /
|
||||
effective_level)
|
||||
{
|
||||
msg("You have turned the %s.", mname);
|
||||
turn_on(*tp, WASTURNED); /* One turn per monster */
|
||||
turn_on(*tp, ISRUN);
|
||||
turn_on(*tp, ISFLEE);
|
||||
|
||||
/* If monster was suffocating, stop it */
|
||||
if (on(*tp, DIDSUFFOCATE))
|
||||
{
|
||||
turn_off(*tp, DIDSUFFOCATE);
|
||||
extinguish_fuse(FUSE_SUFFOCATE);
|
||||
}
|
||||
|
||||
/* If monster held us, stop it */
|
||||
if (on(*tp, DIDHOLD) && (--hold_count == 0))
|
||||
turn_off(player, ISHELD);
|
||||
|
||||
turn_off(*tp, DIDHOLD);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
msg("The %s momentarily recoils from your holy symbol.", mname);
|
||||
|
||||
annoy:
|
||||
|
||||
if (off(*tp, WASTURNED))
|
||||
chase_it(&new_pos, &player);
|
||||
}
|
||||
|
||||
/*
|
||||
undead_sense()
|
||||
cleric or paladin finding the ungodly
|
||||
*/
|
||||
|
||||
void
|
||||
undead_sense(void)
|
||||
{
|
||||
struct linked_list *item;
|
||||
struct thing *tp;
|
||||
int showit = FALSE;
|
||||
|
||||
wclear(hw);
|
||||
|
||||
for (item = mlist; item != NULL; item = next(item))
|
||||
{
|
||||
tp = THINGPTR(item);
|
||||
|
||||
if (on(*tp, ISUNDEAD))
|
||||
{
|
||||
mvwaddch(hw, tp->t_pos.y, tp->t_pos.x, '&');
|
||||
showit = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (showit)
|
||||
{
|
||||
msg("You feel the presense of the ungodly.");
|
||||
overlay(hw, cw);
|
||||
wrefresh(cw);
|
||||
wclear(hw);
|
||||
}
|
||||
}
|
||||
1516
urogue/potions.c
Normal file
1516
urogue/potions.c
Normal file
File diff suppressed because it is too large
Load diff
23
urogue/random.c
Normal file
23
urogue/random.c
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
random.c - random and associated routines
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include "rogue.h"
|
||||
|
||||
void
|
||||
ur_srandom(unsigned x)
|
||||
{
|
||||
md_srandom(x);
|
||||
}
|
||||
|
||||
long
|
||||
ur_random(void)
|
||||
{
|
||||
return( md_random() );
|
||||
}
|
||||
354
urogue/rings.c
Normal file
354
urogue/rings.c
Normal file
|
|
@ -0,0 +1,354 @@
|
|||
/*
|
||||
rings.c - Routines dealing specificaly with rings
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
Based on "Advanced Rogue"
|
||||
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
|
||||
All rights reserved.
|
||||
|
||||
Based on "Rogue: Exploring the Dungeons of Doom"
|
||||
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "rogue.h"
|
||||
|
||||
void
|
||||
ring_on(void)
|
||||
{
|
||||
struct object *obj;
|
||||
struct linked_list *item;
|
||||
int ring;
|
||||
char buf[2 * LINELEN];
|
||||
|
||||
if ((item = get_item("put on", RING)) == NULL)
|
||||
return;
|
||||
|
||||
obj = OBJPTR(item);
|
||||
|
||||
if (obj->o_type != RING)
|
||||
{
|
||||
msg("You can't put that on!");
|
||||
return;
|
||||
}
|
||||
|
||||
/* find out which hand to put it on */
|
||||
|
||||
if (is_current(obj))
|
||||
{
|
||||
msg("Already wearing that!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (cur_ring[LEFT_1] == NULL)
|
||||
ring = LEFT_1;
|
||||
else if (cur_ring[LEFT_2] == NULL)
|
||||
ring = LEFT_2;
|
||||
else if (cur_ring[LEFT_3] == NULL)
|
||||
ring = LEFT_3;
|
||||
else if (cur_ring[LEFT_4] == NULL)
|
||||
ring = LEFT_4;
|
||||
else if (cur_ring[LEFT_5] == NULL)
|
||||
ring = LEFT_5;
|
||||
else if (cur_ring[RIGHT_1] == NULL)
|
||||
ring = RIGHT_1;
|
||||
else if (cur_ring[RIGHT_2] == NULL)
|
||||
ring = RIGHT_2;
|
||||
else if (cur_ring[RIGHT_3] == NULL)
|
||||
ring = RIGHT_3;
|
||||
else if (cur_ring[RIGHT_4] == NULL)
|
||||
ring = RIGHT_4;
|
||||
else if (cur_ring[RIGHT_5] == NULL)
|
||||
ring = RIGHT_5;
|
||||
else
|
||||
{
|
||||
msg("You already have on ten rings.");
|
||||
return;
|
||||
}
|
||||
|
||||
cur_ring[ring] = obj;
|
||||
|
||||
/* Calculate the effect it has on the poor guy. */
|
||||
|
||||
switch (obj->o_which)
|
||||
{
|
||||
case R_ADDSTR:
|
||||
pstats.s_str += obj->o_ac;
|
||||
break;
|
||||
case R_ADDHIT:
|
||||
pstats.s_dext += obj->o_ac;
|
||||
break;
|
||||
case R_ADDINTEL:
|
||||
pstats.s_intel += obj->o_ac;
|
||||
break;
|
||||
case R_ADDWISDOM:
|
||||
pstats.s_wisdom += obj->o_ac;
|
||||
break;
|
||||
case R_FREEDOM:
|
||||
turn_off(player, ISHELD);
|
||||
hold_count = 0;
|
||||
break;
|
||||
case R_TRUESEE:
|
||||
if (off(player, PERMBLIND))
|
||||
{
|
||||
turn_on(player, CANTRUESEE);
|
||||
msg("You become more aware of your surroundings.");
|
||||
sight(NULL);
|
||||
light(&hero);
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
}
|
||||
break;
|
||||
|
||||
case R_SEEINVIS:
|
||||
if (off(player, PERMBLIND))
|
||||
{
|
||||
turn_on(player, CANTRUESEE);
|
||||
msg("Your eyes begin to tingle.");
|
||||
sight(NULL);
|
||||
light(&hero);
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
}
|
||||
break;
|
||||
|
||||
case R_AGGR:
|
||||
aggravate();
|
||||
break;
|
||||
|
||||
case R_CARRYING:
|
||||
updpack();
|
||||
break;
|
||||
|
||||
case R_LEVITATION:
|
||||
msg("You begin to float in the air!");
|
||||
break;
|
||||
|
||||
case R_LIGHT:
|
||||
if (roomin(hero) != NULL)
|
||||
{
|
||||
light(&hero);
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
}
|
||||
}
|
||||
|
||||
status(FALSE);
|
||||
|
||||
if (know_items[TYP_RING][obj->o_which] &&
|
||||
guess_items[TYP_RING][obj->o_which])
|
||||
{
|
||||
mem_free(guess_items[TYP_RING][obj->o_which]);
|
||||
guess_items[TYP_RING][obj->o_which] = NULL;
|
||||
}
|
||||
else if (!know_items[TYP_RING][obj->o_which] &&
|
||||
askme &&
|
||||
(obj->o_flags & ISKNOW) == 0 &&
|
||||
guess_items[TYP_RING][obj->o_which] == NULL)
|
||||
{
|
||||
mpos = 0;
|
||||
msg("What do you want to call it? ");
|
||||
|
||||
if (get_string(buf, cw) == NORM)
|
||||
{
|
||||
guess_items[TYP_RING][obj->o_which] =
|
||||
new_alloc(strlen(buf) + 1);
|
||||
strcpy(guess_items[TYP_RING][obj->o_which], buf);
|
||||
}
|
||||
msg("");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ring_off(void)
|
||||
{
|
||||
struct object *obj;
|
||||
struct linked_list *item;
|
||||
|
||||
if (cur_ring[LEFT_1] == NULL && cur_ring[LEFT_2] == NULL &&
|
||||
cur_ring[LEFT_3] == NULL && cur_ring[LEFT_4] == NULL &&
|
||||
cur_ring[LEFT_5] == NULL &&
|
||||
cur_ring[RIGHT_1] == NULL && cur_ring[RIGHT_2] == NULL &&
|
||||
cur_ring[RIGHT_3] == NULL && cur_ring[RIGHT_4] == NULL &&
|
||||
cur_ring[RIGHT_5] == NULL)
|
||||
{
|
||||
msg("You aren't wearing any rings.");
|
||||
return;
|
||||
}
|
||||
else if ((item = get_item("remove", RING)) == NULL)
|
||||
return;
|
||||
|
||||
mpos = 0;
|
||||
obj = OBJPTR(item);
|
||||
|
||||
if ((obj = OBJPTR(item)) == NULL)
|
||||
msg("You are not wearing that!");
|
||||
|
||||
if (dropcheck(obj))
|
||||
{
|
||||
switch (obj->o_which)
|
||||
{
|
||||
case R_SEEINVIS:
|
||||
msg("Your eyes stop tingling.");
|
||||
break;
|
||||
|
||||
case R_CARRYING:
|
||||
updpack();
|
||||
break;
|
||||
|
||||
case R_LEVITATION:
|
||||
msg("You float gently to the ground.");
|
||||
break;
|
||||
|
||||
case R_LIGHT:
|
||||
if (roomin(hero) != NULL)
|
||||
{
|
||||
light(&hero);
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
}
|
||||
break;
|
||||
|
||||
case R_TRUESEE:
|
||||
msg("Your sensory perceptions return to normal.");
|
||||
break;
|
||||
}
|
||||
|
||||
msg("Was wearing %s.", inv_name(obj, LOWERCASE));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
ring_eat()
|
||||
how much food does this ring use up?
|
||||
*/
|
||||
|
||||
int
|
||||
ring_eat(int hand)
|
||||
{
|
||||
int ret_val = 0;
|
||||
int ac;
|
||||
|
||||
if (cur_ring[hand] != NULL)
|
||||
{
|
||||
switch (cur_ring[hand]->o_which)
|
||||
{
|
||||
case R_REGEN:
|
||||
case R_VREGEN:
|
||||
ret_val = rnd(pstats.s_lvl > 10 ? 10 : pstats.s_lvl);
|
||||
|
||||
case R_DIGEST:
|
||||
|
||||
ac = cur_ring[hand]->o_ac;
|
||||
|
||||
if (ac < 0 && rnd(1 - (ac / 3)) == 0)
|
||||
ret_val = -ac + 1;
|
||||
else if (rnd((ac / 2) + 2) == 0)
|
||||
ret_val = -1 - ac;
|
||||
break;
|
||||
|
||||
case R_SEARCH:
|
||||
ret_val = rnd(100) < 33;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret_val = 1;
|
||||
}
|
||||
}
|
||||
|
||||
ret_val += rnd(luck);
|
||||
|
||||
return(ret_val);
|
||||
}
|
||||
|
||||
/*
|
||||
ring_num()
|
||||
print ring bonuses
|
||||
*/
|
||||
|
||||
char *
|
||||
ring_num(struct object *obj, char *buf)
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
if (buf == NULL)
|
||||
return("A bug in UltraRogue #101");
|
||||
|
||||
buf[0] = 0;
|
||||
|
||||
if (obj->o_flags & ISKNOW)
|
||||
{
|
||||
switch (obj->o_which)
|
||||
{
|
||||
case R_SEARCH:
|
||||
case R_PROTECT:
|
||||
case R_ADDSTR:
|
||||
case R_ADDDAM:
|
||||
case R_ADDHIT:
|
||||
case R_ADDINTEL:
|
||||
case R_ADDWISDOM:
|
||||
case R_CARRYING:
|
||||
case R_VREGEN:
|
||||
case R_RESURRECT:
|
||||
case R_TELCONTROL:
|
||||
case R_REGEN:
|
||||
case R_PIETY:
|
||||
case R_WIZARD:
|
||||
buf[0] = ' ';
|
||||
strcpy(&buf[1], num(obj->o_ac, 0,buffer));
|
||||
break;
|
||||
|
||||
case R_DIGEST:
|
||||
buf[0] = ' ';
|
||||
strcpy(&buf[1], num(obj->o_ac < 0 ?
|
||||
obj->o_ac : obj->o_ac - 1, 0, buffer));
|
||||
break;
|
||||
|
||||
default:
|
||||
if (obj->o_flags & ISCURSED)
|
||||
strcpy(buf, " cursed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
ring_value()
|
||||
Return the effect of the specified ring
|
||||
*/
|
||||
|
||||
#define ISRING(h, r) (cur_ring[h] != NULL && cur_ring[h]->o_which == r)
|
||||
|
||||
int
|
||||
ring_value(int type)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (ISRING(LEFT_1, type))
|
||||
result += cur_ring[LEFT_1]->o_ac;
|
||||
if (ISRING(LEFT_2, type))
|
||||
result += cur_ring[LEFT_2]->o_ac;
|
||||
if (ISRING(LEFT_3, type))
|
||||
result += cur_ring[LEFT_3]->o_ac;
|
||||
if (ISRING(LEFT_4, type))
|
||||
result += cur_ring[LEFT_4]->o_ac;
|
||||
if (ISRING(LEFT_5, type))
|
||||
result += cur_ring[LEFT_5]->o_ac;
|
||||
if (ISRING(RIGHT_1, type))
|
||||
result += cur_ring[RIGHT_1]->o_ac;
|
||||
if (ISRING(RIGHT_2, type))
|
||||
result += cur_ring[RIGHT_2]->o_ac;
|
||||
if (ISRING(RIGHT_3, type))
|
||||
result += cur_ring[RIGHT_3]->o_ac;
|
||||
if (ISRING(RIGHT_4, type))
|
||||
result += cur_ring[RIGHT_4]->o_ac;
|
||||
if (ISRING(RIGHT_5, type))
|
||||
result += cur_ring[RIGHT_5]->o_ac;
|
||||
|
||||
return(result);
|
||||
}
|
||||
661
urogue/rip.c
Normal file
661
urogue/rip.c
Normal file
|
|
@ -0,0 +1,661 @@
|
|||
/*
|
||||
rip.c - File for the fun ends Death or a total win
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
Based on "Advanced Rogue"
|
||||
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
|
||||
All rights reserved.
|
||||
|
||||
Based on "Rogue: Exploring the Dungeons of Doom"
|
||||
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
#include "rogue.h"
|
||||
|
||||
static struct sc_ent
|
||||
{
|
||||
int sc_lvl;
|
||||
long sc_score;
|
||||
char sc_name[76];
|
||||
long sc_gold;
|
||||
int sc_flags;
|
||||
int sc_level;
|
||||
int sc_artifacts;
|
||||
int sc_monster;
|
||||
} top_ten[10];
|
||||
|
||||
|
||||
static const char *rip[] =
|
||||
{
|
||||
" __________",
|
||||
" / \\",
|
||||
" / REST \\",
|
||||
" / IN \\",
|
||||
" / PEACE \\",
|
||||
" / \\",
|
||||
" | |",
|
||||
" | |",
|
||||
" | killed by |",
|
||||
" | |",
|
||||
" | 1993 |",
|
||||
" *| * * * | *",
|
||||
" ________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______",
|
||||
0
|
||||
};
|
||||
|
||||
/*
|
||||
death()
|
||||
Do something really fun when he dies
|
||||
*/
|
||||
|
||||
void
|
||||
death(int monst)
|
||||
{
|
||||
char **dp = (char **) rip, *killer;
|
||||
struct tm *lt;
|
||||
time_t date;
|
||||
char buf[80];
|
||||
int c;
|
||||
|
||||
if (is_wearing(R_RESURRECT) || rnd(wizard ? 3 : 67) == 0)
|
||||
{
|
||||
int die = TRUE;
|
||||
|
||||
if (resurrect-- == 0)
|
||||
msg("You've run out of lives.");
|
||||
else if (!save_resurrect(ring_value(R_RESURRECT)))
|
||||
msg("Your attempt to return from the grave fails.");
|
||||
else
|
||||
{
|
||||
struct linked_list *item;
|
||||
struct linked_list *next_item;
|
||||
struct object *obj;
|
||||
int rm, flags;
|
||||
coord pos;
|
||||
|
||||
die = FALSE;
|
||||
msg("You feel a sudden warmth and then nothingness.");
|
||||
teleport();
|
||||
|
||||
if (ring_value(R_RESURRECT) > 1 && rnd(10))
|
||||
{
|
||||
pstats.s_hpt = 2 * pstats.s_const;
|
||||
pstats.s_const = max(pstats.s_const - 1, 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (item = pack; item != NULL; item = next_item)
|
||||
{
|
||||
obj = OBJPTR(item);
|
||||
|
||||
if (obj->o_flags & ISOWNED || obj->o_flags & ISPROT)
|
||||
{
|
||||
next_item = next(item);
|
||||
continue;
|
||||
}
|
||||
|
||||
flags = obj->o_flags;
|
||||
obj->o_flags &= ~ISCURSED;
|
||||
dropcheck(obj);
|
||||
obj->o_flags = flags;
|
||||
next_item = next(item);
|
||||
rem_pack(obj);
|
||||
|
||||
if (obj->o_type == ARTIFACT)
|
||||
has_artifact &= ~(1 << obj->o_which);
|
||||
|
||||
do
|
||||
{
|
||||
rm = rnd_room();
|
||||
rnd_pos(&rooms[rm], &pos);
|
||||
}
|
||||
while(winat(pos.y, pos.x) != FLOOR);
|
||||
|
||||
obj->o_pos = pos;
|
||||
add_obj(item, obj->o_pos.y, obj->o_pos.x);
|
||||
}
|
||||
|
||||
pstats.s_hpt = pstats.s_const;
|
||||
pstats.s_const = max(pstats.s_const - roll(2, 2), 3);
|
||||
}
|
||||
|
||||
chg_str(roll(1, 4), TRUE, FALSE);
|
||||
pstats.s_lvl = max(pstats.s_lvl, 1);
|
||||
no_command += 2 + rnd(4);
|
||||
|
||||
if (on(player, ISHUH))
|
||||
lengthen_fuse(FUSE_UNCONFUSE, rnd(8) + HUHDURATION);
|
||||
else
|
||||
light_fuse(FUSE_UNCONFUSE, 0, rnd(8) + HUHDURATION, AFTER);
|
||||
|
||||
turn_on(player, ISHUH);
|
||||
light(&hero);
|
||||
}
|
||||
|
||||
if (die)
|
||||
{
|
||||
wmove(cw, mpos, 0);
|
||||
waddstr(cw, morestr);
|
||||
wrefresh(cw);
|
||||
wait_for(' ');
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
time(&date);
|
||||
lt = localtime(&date);
|
||||
clear();
|
||||
wclear(cw);
|
||||
move(8, 0);
|
||||
|
||||
while (*dp)
|
||||
printw("%s\n", *dp++);
|
||||
|
||||
mvaddstr(14, 28 - ((int)(strlen(whoami) + 1) / 2), whoami);
|
||||
sprintf(buf, "%d+%ld Points", pstats.s_lvl, pstats.s_exp);
|
||||
mvaddstr(15, 28 - ((int)(strlen(buf) + 1) / 2), buf);
|
||||
killer = killname(monst,buf);
|
||||
mvaddstr(17, 28 - ((int)(strlen(killer) + 1) / 2), killer);
|
||||
mvaddstr(18, 28, (sprintf(prbuf, "%2d", lt->tm_year), prbuf));
|
||||
move(LINES - 1, 0);
|
||||
|
||||
mvaddstr(LINES - 1, 0, retstr);
|
||||
|
||||
while ((c = readcharw(stdscr)) != '\n' && c != '\r')
|
||||
continue;
|
||||
idenpack();
|
||||
wrefresh(cw);
|
||||
refresh();
|
||||
|
||||
score(pstats.s_exp, pstats.s_lvl, KILLED, monst);
|
||||
byebye();
|
||||
}
|
||||
|
||||
/*
|
||||
score()
|
||||
figure score and post it.
|
||||
*/
|
||||
|
||||
void
|
||||
score(long amount, int lvl, int flags, int monst) /*ARGSUSED*/
|
||||
{
|
||||
struct sc_ent *scp=NULL, *sc2=NULL;
|
||||
int i;
|
||||
char *killer;
|
||||
char buf[1024];
|
||||
|
||||
static const char *reason[] =
|
||||
{
|
||||
"killed",
|
||||
"quit",
|
||||
"a winner",
|
||||
"a total winner"
|
||||
};
|
||||
|
||||
char *packend;
|
||||
|
||||
if (flags != WINNER && flags != TOTAL && flags != SCOREIT)
|
||||
{
|
||||
if (flags == CHICKEN)
|
||||
packend = "when you quit";
|
||||
else
|
||||
packend = "at your untimely demise";
|
||||
|
||||
noecho();
|
||||
nl();
|
||||
refresh();
|
||||
showpack(packend);
|
||||
}
|
||||
|
||||
/* Open file and read list */
|
||||
|
||||
if (fd_score == NULL)
|
||||
{
|
||||
printf("No score file opened\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (scp = top_ten; scp < &top_ten[10]; scp++)
|
||||
{
|
||||
scp->sc_lvl = 0L;
|
||||
scp->sc_score = 0L;
|
||||
|
||||
for (i = 0; i < 76; i++)
|
||||
scp->sc_name[i] = ucrnd(255);
|
||||
|
||||
scp->sc_gold = 0L;
|
||||
scp->sc_flags = rnd(10);
|
||||
scp->sc_level = rnd(10);
|
||||
scp->sc_monster = srnd(10);
|
||||
scp->sc_artifacts = 0;
|
||||
}
|
||||
|
||||
if (flags != SCOREIT)
|
||||
{
|
||||
mvaddstr(LINES - 1, 0, retstr);
|
||||
refresh();
|
||||
fflush(stdout);
|
||||
wait_for('\n');
|
||||
}
|
||||
|
||||
fseek(fd_score, 0L, SEEK_SET);
|
||||
fread(top_ten, sizeof(top_ten), 1, fd_score);
|
||||
|
||||
/* Insert player in list if need be */
|
||||
|
||||
if (!waswizard)
|
||||
{
|
||||
for (scp = top_ten; scp < &top_ten[10]; scp++)
|
||||
{
|
||||
if (lvl > scp->sc_lvl)
|
||||
break;
|
||||
|
||||
if (lvl == scp->sc_lvl && amount > scp->sc_score)
|
||||
break;
|
||||
}
|
||||
|
||||
if (scp < &top_ten[10])
|
||||
{
|
||||
if (flags == WINNER)
|
||||
sc2 = &top_ten[9]; /* LAST WINNER ALWAYS MAKES IT */
|
||||
|
||||
while (sc2 > scp)
|
||||
{
|
||||
*sc2 = sc2[-1];
|
||||
sc2--;
|
||||
}
|
||||
|
||||
scp->sc_lvl = lvl;
|
||||
scp->sc_gold = purse;
|
||||
scp->sc_score = amount;
|
||||
strcpy(scp->sc_name, whoami);
|
||||
strcat(scp->sc_name,", ");
|
||||
strcat(scp->sc_name, which_class(player.t_ctype));
|
||||
scp->sc_flags = flags;
|
||||
|
||||
if (flags == WINNER)
|
||||
scp->sc_level = max_level;
|
||||
else
|
||||
scp->sc_level = level;
|
||||
|
||||
scp->sc_monster = monst;
|
||||
scp->sc_artifacts = has_artifact;
|
||||
|
||||
sc2 = scp;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags != SCOREIT)
|
||||
{
|
||||
clear();
|
||||
refresh();
|
||||
endwin();
|
||||
}
|
||||
|
||||
/* Print the list */
|
||||
|
||||
printf("\nTop Ten Adventurers:\n%4s %15s %10s %s\n",
|
||||
"Rank", "Score", "Gold", "Name");
|
||||
|
||||
for (scp = top_ten; scp < &top_ten[10]; scp++)
|
||||
{
|
||||
if (scp->sc_score)
|
||||
{
|
||||
char lev[20];
|
||||
|
||||
sprintf(lev, "%ld+%ld", scp->sc_lvl, scp->sc_score);
|
||||
printf("%4d %15s %10ld %s:", scp - top_ten + 1,
|
||||
lev,
|
||||
scp->sc_gold,
|
||||
scp->sc_name);
|
||||
|
||||
if (scp->sc_artifacts)
|
||||
{
|
||||
char thangs[80];
|
||||
int n;
|
||||
int first = TRUE;
|
||||
|
||||
thangs[0] = '\0';
|
||||
|
||||
for (n = 0; n <= maxartifact; n++)
|
||||
{
|
||||
if (scp->sc_artifacts & (1 << n))
|
||||
{
|
||||
if (strlen(thangs))
|
||||
strcat(thangs, ", ");
|
||||
|
||||
if (first)
|
||||
{
|
||||
strcat(thangs, "retrieved ");
|
||||
first = FALSE;
|
||||
}
|
||||
|
||||
if (45 - strlen(thangs) < strlen(arts[n].ar_name))
|
||||
{
|
||||
printf("%s\n%32s", thangs," ");
|
||||
thangs[0] = '\0';
|
||||
}
|
||||
strcat(thangs, arts[n].ar_name);
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen(thangs))
|
||||
printf("%s,", thangs);
|
||||
|
||||
printf("\n%32s"," ");
|
||||
}
|
||||
|
||||
printf("%s on level %d",reason[scp->sc_flags],scp->sc_level);
|
||||
|
||||
if (scp->sc_flags == 0)
|
||||
{
|
||||
printf(" by \n%32s"," ");
|
||||
killer = killname(scp->sc_monster, buf);
|
||||
printf(" %s", killer);
|
||||
}
|
||||
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
if (sc2 != NULL)
|
||||
{
|
||||
fseek(fd_score, 0L, SEEK_SET);
|
||||
/* Update the list file */
|
||||
fwrite(top_ten, sizeof(top_ten), 1, fd_score);
|
||||
}
|
||||
|
||||
fclose(fd_score);
|
||||
}
|
||||
|
||||
void
|
||||
total_winner(void)
|
||||
{
|
||||
struct linked_list *item;
|
||||
struct object *obj;
|
||||
int worth, oldpurse;
|
||||
char c;
|
||||
struct linked_list *bag = NULL;
|
||||
|
||||
clear();
|
||||
standout();
|
||||
addstr(" \n");
|
||||
addstr(" @ @ @ @ @ @@@ @ @ \n");
|
||||
addstr(" @ @ @@ @@ @ @ @ @ \n");
|
||||
addstr(" @ @ @@@ @ @ @ @ @ @@@ @@@@ @@@ @ @@@ @ \n");
|
||||
addstr(" @@@@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ \n");
|
||||
addstr(" @ @ @ @ @ @ @ @@@@ @ @ @@@@@ @ @ @ \n");
|
||||
addstr(" @ @ @ @ @ @@ @ @ @ @ @ @ @ @ @ @ \n");
|
||||
addstr(" @@@ @@@ @@ @ @ @ @@@@ @@@@ @@@ @@@ @@ @ \n");
|
||||
addstr(" \n");
|
||||
addstr(" Congratulations, you have made it to the light of day! \n");
|
||||
standend();
|
||||
addstr("\nYou have joined the elite ranks of those who have \n");
|
||||
addstr("escaped the Dungeons of Doom alive. You journey home \n");
|
||||
addstr("and sell all your loot at a great profit.\n");
|
||||
addstr("The White Council approves the recommendation of\n");
|
||||
|
||||
if (player.t_ctype == C_FIGHTER)
|
||||
addstr("the fighters guild and appoints you Lord Protector\n");
|
||||
else if (player.t_ctype == C_ASSASIN)
|
||||
addstr("the assassins guild and appoints you Master Murderer\n");
|
||||
else if (player.t_ctype == C_NINJA)
|
||||
addstr("the ninja guild and appoints you Master of the Wind\n");
|
||||
else if (player.t_ctype == C_ILLUSION)
|
||||
addstr("the illusionists guild and appoints you Master Wizard\n");
|
||||
else if (player.t_ctype == C_MAGICIAN)
|
||||
addstr("the magicians guild and appoints you Master Wizard\n");
|
||||
else if (player.t_ctype == C_CLERIC)
|
||||
addstr("the temple priests and appoints you Master of the Flowers\n");
|
||||
else if (player.t_ctype == C_DRUID)
|
||||
addstr("the temple priests and appoints you Master of the Flowers\n");
|
||||
else if (player.t_ctype == C_RANGER)
|
||||
addstr("the rangers guild and appoints you Master Ranger\n");
|
||||
else if (player.t_ctype == C_PALADIN)
|
||||
addstr("the paladins guild and appoints you Master Paladin\n");
|
||||
else if (player.t_ctype == C_THIEF)
|
||||
{
|
||||
addstr("the thieves guild under protest and appoints you\n");
|
||||
addstr("Master of the Highways\n");
|
||||
}
|
||||
|
||||
addstr("of the Land Between the Mountains.\n");
|
||||
mvaddstr(LINES - 1, 0, spacemsg);
|
||||
refresh();
|
||||
wait_for(' ');
|
||||
clear();
|
||||
idenpack();
|
||||
oldpurse = purse;
|
||||
mvaddstr(0, 0, " Worth Item");
|
||||
|
||||
for (c = 'a', item = pack; item != NULL; c++, item = next(item))
|
||||
{
|
||||
obj = OBJPTR(item);
|
||||
worth = get_worth(obj);
|
||||
purse += worth;
|
||||
|
||||
if (obj->o_type == ARTIFACT && obj->o_which == TR_PURSE)
|
||||
bag = obj->o_bag;
|
||||
|
||||
mvprintw(c - 'a' + 1, 0, "%c) %8d %s", c,
|
||||
worth, inv_name(obj, UPPERCASE));
|
||||
}
|
||||
|
||||
if (bag != NULL)
|
||||
{
|
||||
mvaddstr(LINES - 1, 0, morestr);
|
||||
refresh();
|
||||
wait_for(' ');
|
||||
clear();
|
||||
mvprintw(0, 0, "Contents of the Magic Purse of Yendor:\n");
|
||||
|
||||
for (c = 'a', item = bag; item != NULL; c++, item = next(item))
|
||||
{
|
||||
obj = OBJPTR(item);
|
||||
worth = get_worth(obj);
|
||||
whatis(item);
|
||||
purse += worth;
|
||||
mvprintw(c - 'a' + 1, 0, "%c) %8d %s\n", c,
|
||||
worth, inv_name(obj, UPPERCASE));
|
||||
}
|
||||
}
|
||||
|
||||
mvprintw(c - 'a' + 1, 0, " %6d Gold Pieces ", oldpurse);
|
||||
refresh();
|
||||
|
||||
if (has_artifact == 255)
|
||||
score(pstats.s_exp, pstats.s_lvl, TOTAL, 0);
|
||||
else
|
||||
score(pstats.s_exp, pstats.s_lvl, WINNER, 0);
|
||||
|
||||
byebye();
|
||||
}
|
||||
|
||||
char *
|
||||
killname(int monst, char *buf)
|
||||
{
|
||||
if (buf == NULL)
|
||||
return("A bug in UltraRogue #102");
|
||||
|
||||
if (monst >= 0)
|
||||
{
|
||||
switch (monsters[monst].m_name[0])
|
||||
{
|
||||
case 'a':
|
||||
case 'e':
|
||||
case 'i':
|
||||
case 'o':
|
||||
case 'u':
|
||||
sprintf(buf, "an %s", monsters[monst].m_name);
|
||||
break;
|
||||
default:
|
||||
sprintf(buf, "a %s", monsters[monst].m_name);
|
||||
}
|
||||
|
||||
return(buf);
|
||||
}
|
||||
else
|
||||
switch(monst)
|
||||
{
|
||||
case D_ARROW:
|
||||
strcpy(buf, "an arrow"); break;
|
||||
case D_DART:
|
||||
strcpy(buf, "a dart"); break;
|
||||
case D_BOLT:
|
||||
strcpy(buf, "a bolt"); break;
|
||||
case D_POISON:
|
||||
strcpy(buf, "poison"); break;
|
||||
case D_POTION:
|
||||
strcpy(buf, "a cursed potion"); break;
|
||||
case D_PETRIFY:
|
||||
strcpy(buf, "petrification"); break;
|
||||
case D_SUFFOCATION:
|
||||
strcpy(buf, "suffocation"); break;
|
||||
case D_INFESTATION:
|
||||
strcpy(buf, "a parasite"); break;
|
||||
case D_DROWN:
|
||||
strcpy(buf, "drowning"); break;
|
||||
case D_FALL:
|
||||
strcpy(buf, "falling"); break;
|
||||
case D_FIRE:
|
||||
strcpy(buf, "slow boiling in oil"); break;
|
||||
case D_SPELLFUMBLE:
|
||||
strcpy(buf, "a botched spell"); break;
|
||||
case D_DRAINLIFE:
|
||||
strcpy(buf, "a drain life spell"); break;
|
||||
case D_ARTIFACT:
|
||||
strcpy(buf, "an artifact of the gods"); break;
|
||||
case D_GODWRATH:
|
||||
strcpy(buf, "divine retribution"); break;
|
||||
case D_CLUMSY:
|
||||
strcpy(buf, "excessive clumsyness"); break;
|
||||
default:
|
||||
strcpy(buf, "stupidity"); break;
|
||||
}
|
||||
|
||||
return(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
showpack()
|
||||
Display the contents of the hero's pack
|
||||
*/
|
||||
|
||||
void
|
||||
showpack(char *howso)
|
||||
{
|
||||
char *iname;
|
||||
unsigned int worth;
|
||||
int cnt, ch, oldpurse;
|
||||
struct linked_list *item;
|
||||
struct object *obj;
|
||||
struct linked_list *bag = NULL;
|
||||
|
||||
cnt = 1;
|
||||
clear();
|
||||
mvprintw(0, 0, "Contents of your pack %s:\n", howso);
|
||||
ch = 0;
|
||||
oldpurse = purse;
|
||||
purse = 0;
|
||||
|
||||
for (item = pack; item != NULL; item = next(item))
|
||||
{
|
||||
obj = OBJPTR(item);
|
||||
worth = get_worth(obj);
|
||||
whatis(item);
|
||||
purse += worth;
|
||||
|
||||
if (obj->o_type == ARTIFACT && obj->o_which == TR_PURSE)
|
||||
bag = obj->o_bag;
|
||||
|
||||
iname = inv_name(obj, UPPERCASE);
|
||||
mvprintw(cnt, 0, "%d) %s\n", ch, iname);
|
||||
ch += 1;
|
||||
|
||||
if (++cnt > LINES - 5 && next(item) != NULL)
|
||||
{
|
||||
cnt = 1;
|
||||
mvaddstr(LINES - 1, 0, morestr);
|
||||
refresh();
|
||||
wait_for(' ');
|
||||
clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (bag != NULL)
|
||||
{
|
||||
mvaddstr(LINES - 1, 0, morestr);
|
||||
refresh();
|
||||
wait_for(' ');
|
||||
clear();
|
||||
cnt = 1;
|
||||
ch = 0;
|
||||
|
||||
mvprintw(0, 0, "Contents of the Magic Purse of Yendor %s:\n", howso);
|
||||
|
||||
for (item = bag; item != NULL; item = next(item))
|
||||
{
|
||||
obj = OBJPTR(item);
|
||||
worth = get_worth(obj);
|
||||
whatis(item);
|
||||
purse += worth;
|
||||
mvprintw(cnt, 0, "%d) %s\n", ch, inv_name(obj, UPPERCASE));
|
||||
ch += 1;
|
||||
|
||||
if (++cnt > LINES - 5 && next(item) != NULL)
|
||||
{
|
||||
cnt = 1;
|
||||
mvaddstr(LINES - 1, 0, morestr);
|
||||
refresh();
|
||||
wait_for(' ');
|
||||
clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mvprintw(cnt + 1, 0, "Carrying %d gold pieces", oldpurse);
|
||||
mvprintw(cnt + 2, 0, "Carrying objects worth %d gold pieces", purse);
|
||||
purse += oldpurse;
|
||||
refresh();
|
||||
}
|
||||
|
||||
void
|
||||
byebye(void)
|
||||
{
|
||||
endwin();
|
||||
printf("\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
save_resurrect()
|
||||
chance of resurrection according to modifed D&D probabilities
|
||||
*/
|
||||
|
||||
int
|
||||
save_resurrect(int bonus)
|
||||
{
|
||||
int need, adjust;
|
||||
|
||||
adjust = pstats.s_const + bonus - luck;
|
||||
|
||||
if (adjust > 17)
|
||||
return(TRUE);
|
||||
else if (adjust < 14)
|
||||
need = 5 * (adjust + 5);
|
||||
else
|
||||
need = 90 + 2 * (adjust - 13);
|
||||
|
||||
return(roll(1, 100) < need);
|
||||
}
|
||||
1815
urogue/rogue.h
Normal file
1815
urogue/rogue.h
Normal file
File diff suppressed because it is too large
Load diff
315
urogue/rooms.c
Normal file
315
urogue/rooms.c
Normal file
|
|
@ -0,0 +1,315 @@
|
|||
/*
|
||||
rooms.c - Draw the nine rooms on the screen
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
Based on "Advanced Rogue"
|
||||
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
|
||||
All rights reserved.
|
||||
|
||||
Based on "Rogue: Exploring the Dungeons of Doom"
|
||||
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "rogue.h"
|
||||
|
||||
void
|
||||
do_rooms(void)
|
||||
{
|
||||
int i;
|
||||
struct room *rp;
|
||||
struct linked_list *item;
|
||||
struct thing *tp;
|
||||
int left_out;
|
||||
coord top;
|
||||
coord bsze;
|
||||
coord mp;
|
||||
|
||||
/* bsze is the maximum room size */
|
||||
|
||||
bsze.x = COLS / 3;
|
||||
bsze.y = (LINES - 2) / 3;
|
||||
|
||||
/* Clear things for a new level */
|
||||
|
||||
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
|
||||
rp->r_nexits = rp->r_flags = rp->r_fires = 0;
|
||||
|
||||
/* Put the gone rooms, if any, on the level */
|
||||
|
||||
left_out = rnd(3);
|
||||
|
||||
for (i = 0; i < left_out; i++)
|
||||
rooms[rnd_room()].r_flags |= ISGONE;
|
||||
|
||||
/* dig and populate all the rooms on the level */
|
||||
|
||||
for (i = 0, rp = rooms; i < MAXROOMS; rp++, i++)
|
||||
{
|
||||
int has_gold = FALSE;
|
||||
|
||||
/* Find upper left corner of box that this room goes in */
|
||||
|
||||
top.x = (i % 3) * bsze.x;
|
||||
top.y = i / 3 * bsze.y + 1;
|
||||
|
||||
if (rp->r_flags & ISGONE)
|
||||
{
|
||||
/*
|
||||
* Place a gone room. Make certain that there is a
|
||||
* blank line for passage drawing.
|
||||
*/
|
||||
|
||||
do
|
||||
{
|
||||
rp->r_pos.x = top.x + rnd(bsze.x - 2) + 1;
|
||||
rp->r_pos.y = top.y + rnd(bsze.y - 2) + 1;
|
||||
rp->r_max.x = -COLS;
|
||||
rp->r_max.x = -LINES;
|
||||
}
|
||||
while (rp->r_pos.y < 1 || rp->r_pos.y > LINES - 3);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rnd(40) < level - 5)
|
||||
rp->r_flags |= ISDARK;
|
||||
|
||||
/* Find a place and size for a random room */
|
||||
|
||||
do
|
||||
{
|
||||
rp->r_max.x = rnd(bsze.x - 4) + 4;
|
||||
rp->r_max.y = rnd(bsze.y - 4) + 4;
|
||||
rp->r_pos.x = top.x + rnd(bsze.x - rp->r_max.x);
|
||||
rp->r_pos.y = top.y + rnd(bsze.y - rp->r_max.y);
|
||||
}
|
||||
while (rp->r_pos.y == 0);
|
||||
|
||||
/* Draw the room */
|
||||
|
||||
draw_room(rp);
|
||||
|
||||
/* Put the gold in */
|
||||
|
||||
if (rnd(10) < 3 && (!has_artifact || level >= max_level))
|
||||
{
|
||||
struct linked_list *itm;
|
||||
struct object *cur;
|
||||
coord tpos;
|
||||
|
||||
has_gold = TRUE; /* This room has gold in it */
|
||||
|
||||
itm = spec_item(GOLD, 0, 0, 0);
|
||||
cur = OBJPTR(itm);
|
||||
|
||||
/* Put it somewhere */
|
||||
|
||||
rnd_pos(rp, &tpos);
|
||||
cur->o_pos = tpos;
|
||||
|
||||
/* Put the gold into the level list of items */
|
||||
|
||||
add_obj(itm, tpos.y, tpos.x);
|
||||
|
||||
if (roomin(tpos) != rp)
|
||||
{
|
||||
endwin();
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/* Put the monster in */
|
||||
|
||||
if (rnd(100) < (has_gold ? 80 : 40))
|
||||
{
|
||||
int which;
|
||||
int n, cnt;
|
||||
|
||||
item = new_item(sizeof *tp);
|
||||
tp = THINGPTR(item);
|
||||
|
||||
do
|
||||
rnd_pos(rp, &mp);
|
||||
while (mvwinch(stdscr, mp.y, mp.x) != FLOOR);
|
||||
|
||||
which = randmonster(NOWANDER, NOGRAB);
|
||||
new_monster(item, which, &mp, NOMAXSTATS);
|
||||
|
||||
/* See if we want to give it a treasure to carry around. */
|
||||
|
||||
if (rnd(100) < monsters[tp->t_index].m_carry)
|
||||
attach(tp->t_pack, new_thing());
|
||||
|
||||
/* If it has a fire, mark it */
|
||||
|
||||
if (on(*tp, HASFIRE))
|
||||
{
|
||||
rp->r_flags |= HASFIRE;
|
||||
rp->r_fires++;
|
||||
}
|
||||
|
||||
/* If it carries gold, give it some */
|
||||
|
||||
if (on(*tp, CARRYGOLD))
|
||||
{
|
||||
struct object *cur;
|
||||
|
||||
item = spec_item(GOLD, 0, 0, 0);
|
||||
cur = OBJPTR(item);
|
||||
cur->o_count = GOLDCALC + GOLDCALC + GOLDCALC;
|
||||
cur->o_pos = tp->t_pos;
|
||||
attach(tp->t_pack, item);
|
||||
}
|
||||
|
||||
n = rnd(7);
|
||||
|
||||
if (on(*tp, ISSWARM) && n < 5)
|
||||
cnt = roll(2, 4);
|
||||
else if (on(*tp, ISFLOCK) && n < 5)
|
||||
cnt = roll(1, 4);
|
||||
else
|
||||
cnt = 0;
|
||||
|
||||
for (n = 1; n <= cnt; n++)
|
||||
{
|
||||
coord pos;
|
||||
|
||||
if (place_mons(mp.y, mp.x, &pos)!= FALSE)
|
||||
{
|
||||
struct linked_list *nitem;
|
||||
|
||||
nitem = new_item(sizeof(struct thing));
|
||||
new_monster(nitem, which, &pos, NOMAXSTATS);
|
||||
|
||||
/* If the monster is on a trap, trap it */
|
||||
|
||||
if (isatrap(mvinch(pos.y, pos.x)))
|
||||
be_trapped(THINGPTR(nitem), mp);
|
||||
|
||||
if (on(*tp, ISFRIENDLY))
|
||||
turn_on(*(THINGPTR(nitem)), ISFRIENDLY);
|
||||
else
|
||||
turn_off(*(THINGPTR(nitem)), ISFRIENDLY);
|
||||
}
|
||||
}
|
||||
|
||||
if (cnt > 0)
|
||||
{
|
||||
int boost = rnd(3) + 1;
|
||||
|
||||
if (on(*tp, LOWCAST) || on(*tp, MEDCAST) || on(*tp, HIGHCAST))
|
||||
turn_on(*tp, CANCAST);
|
||||
|
||||
tp->t_stats.s_hpt += 3 * boost;
|
||||
tp->t_stats.s_arm -= 2 * boost;
|
||||
tp->t_stats.s_lvl += 2 * boost;
|
||||
tp->t_stats.s_str += 2 * boost;
|
||||
tp->t_stats.s_intel += 2 * boost;
|
||||
tp->t_stats.s_exp += 4 * boost * monsters[which].m_add_exp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
draw_room()
|
||||
Draw a box around a room
|
||||
*/
|
||||
|
||||
void
|
||||
draw_room(struct room *rp)
|
||||
{
|
||||
int j, k;
|
||||
|
||||
move(rp->r_pos.y, rp->r_pos.x + 1);
|
||||
vert(rp->r_max.y - 2); /* Draw left side */
|
||||
move(rp->r_pos.y + rp->r_max.y - 1, rp->r_pos.x);
|
||||
horiz(rp->r_max.x); /* Draw bottom */
|
||||
move(rp->r_pos.y, rp->r_pos.x);
|
||||
horiz(rp->r_max.x); /* Draw top */
|
||||
vert(rp->r_max.y - 2); /* Draw right side */
|
||||
|
||||
/* Put the floor down */
|
||||
|
||||
for (j = 1; j < rp->r_max.y - 1; j++)
|
||||
{
|
||||
move(rp->r_pos.y + j, rp->r_pos.x + 1);
|
||||
|
||||
for (k = 1; k < rp->r_max.x - 1; k++)
|
||||
addch(FLOOR);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
horiz()
|
||||
draw a horizontal line
|
||||
*/
|
||||
|
||||
void
|
||||
horiz(int cnt)
|
||||
{
|
||||
while(cnt--)
|
||||
addch('-');
|
||||
}
|
||||
|
||||
/*
|
||||
vert()
|
||||
draw a vertical line
|
||||
*/
|
||||
|
||||
void
|
||||
vert(int cnt)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
getyx(stdscr, y, x);
|
||||
|
||||
x--;
|
||||
|
||||
while(cnt--)
|
||||
{
|
||||
move(++y, x);
|
||||
addch('|');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
rnd_pos()
|
||||
pick a random spot in a room
|
||||
*/
|
||||
|
||||
void
|
||||
rnd_pos(struct room *rp, coord *cp)
|
||||
{
|
||||
cp->x = rp->r_pos.x + rnd(rp->r_max.x - 2) + 1;
|
||||
cp->y = rp->r_pos.y + rnd(rp->r_max.y - 2) + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
rnd_room()
|
||||
Pick a room that is really there
|
||||
*/
|
||||
|
||||
int
|
||||
rnd_room(void)
|
||||
{
|
||||
int rm;
|
||||
|
||||
if (levtype != NORMLEV)
|
||||
rm = 0;
|
||||
else
|
||||
do
|
||||
{
|
||||
rm = rnd(MAXROOMS);
|
||||
}
|
||||
while (rooms[rm].r_flags & ISGONE);
|
||||
|
||||
return(rm);
|
||||
}
|
||||
135
urogue/save.c
Normal file
135
urogue/save.c
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
save.c - save and restore routines
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
Based on "Advanced Rogue"
|
||||
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
|
||||
All rights reserved.
|
||||
|
||||
Based on "Rogue: Exploring the Dungeons of Doom"
|
||||
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#define _ALL_SOURCE /* need to remove need for this AIXism */
|
||||
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include "rogue.h"
|
||||
|
||||
int
|
||||
save_game(void)
|
||||
{
|
||||
FILE *savefd;
|
||||
char buf[2 * LINELEN];
|
||||
char oldfile[2*LINELEN];
|
||||
|
||||
/* get file name */
|
||||
|
||||
strcpy(oldfile,file_name);
|
||||
|
||||
do
|
||||
{
|
||||
mpos = 0;
|
||||
|
||||
if (oldfile[0] != '\0')
|
||||
msg("Save file [%s]: ", file_name);
|
||||
else
|
||||
msg("Save file as: ");
|
||||
|
||||
mpos = 0;
|
||||
buf[0] = '\0';
|
||||
|
||||
if (get_string(buf, cw) == QUIT)
|
||||
{
|
||||
msg("");
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if ( (buf[0] == 0) && (oldfile[0] != 0) )
|
||||
strcpy(file_name, oldfile);
|
||||
else if (buf[0] != 0)
|
||||
strcpy(file_name, buf);
|
||||
else
|
||||
{
|
||||
msg("");
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
wclear(hw);
|
||||
wmove(hw, LINES - 1, 0);
|
||||
wrefresh(hw);
|
||||
|
||||
if ((savefd = fopen(file_name, "w")) == NULL)
|
||||
msg(strerror(errno)); /* fake perror() */
|
||||
}
|
||||
while (savefd == NULL);
|
||||
|
||||
/* write out [compressed?] file */
|
||||
|
||||
save_file(savefd);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
int
|
||||
restore(char *file)
|
||||
{
|
||||
FILE *infd;
|
||||
char *sp;
|
||||
|
||||
if (strcmp(file, "-r") == 0)
|
||||
file = file_name;
|
||||
|
||||
if ((infd = fopen(file, "r")) == NULL)
|
||||
{
|
||||
perror(file);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if ( restore_file(infd) == FALSE )
|
||||
return(FALSE);
|
||||
|
||||
/*
|
||||
* we do not close the file so that we will have a hold of the inode
|
||||
* for as long as possible
|
||||
*/
|
||||
|
||||
if (remove(file) < 0)
|
||||
{
|
||||
printf("Cannot unlink file\n");
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if ((sp = getenv("OPTIONS")) != NULL)
|
||||
parse_opts(sp);
|
||||
|
||||
strcpy(file_name, file);
|
||||
|
||||
clearok(cw, TRUE);
|
||||
touchwin(cw);
|
||||
noecho();
|
||||
nonl();
|
||||
|
||||
while(playing)
|
||||
{
|
||||
do_daemons(BEFORE);
|
||||
do_fuses(BEFORE);
|
||||
|
||||
command(); /* Command execution */
|
||||
|
||||
if (after)
|
||||
do_after_effects();
|
||||
}
|
||||
|
||||
fatal("");
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
1491
urogue/scrolls.c
Normal file
1491
urogue/scrolls.c
Normal file
File diff suppressed because it is too large
Load diff
1445
urogue/state.c
Normal file
1445
urogue/state.c
Normal file
File diff suppressed because it is too large
Load diff
52
urogue/status.c
Normal file
52
urogue/status.c
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
status.c - functions for complex status determination of monsters/objects
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
has_defensive_spell()
|
||||
has monster cast a defensive spell.
|
||||
Any flags added here must also be in player_powers[].
|
||||
*/
|
||||
|
||||
int
|
||||
has_defensive_spell(struct thing th)
|
||||
{
|
||||
if (on(th, HASOXYGEN))
|
||||
return(TRUE);
|
||||
if (on(th, CANFLY))
|
||||
return(TRUE);
|
||||
if (on(th, CANINWALL))
|
||||
return(TRUE);
|
||||
if (on(th, CANREFLECT))
|
||||
return(TRUE);
|
||||
if (on(th, CANSEE))
|
||||
return(TRUE);
|
||||
if (on(th, HASMSHIELD))
|
||||
return(TRUE);
|
||||
if (on(th, HASSHIELD))
|
||||
return(TRUE);
|
||||
if (on(th, ISHASTE))
|
||||
return(TRUE);
|
||||
if (on(th, ISREGEN))
|
||||
return(TRUE);
|
||||
if (on(th, ISDISGUISE))
|
||||
return(TRUE);
|
||||
if (on(th, ISINVIS))
|
||||
return(TRUE);
|
||||
if (on(th, NOCOLD))
|
||||
return(TRUE);
|
||||
if (on(th, NOFIRE))
|
||||
return(TRUE);
|
||||
if (on(th, ISELECTRIC))
|
||||
return(TRUE);
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
1796
urogue/sticks.c
Normal file
1796
urogue/sticks.c
Normal file
File diff suppressed because it is too large
Load diff
935
urogue/things.c
Normal file
935
urogue/things.c
Normal file
|
|
@ -0,0 +1,935 @@
|
|||
/*
|
||||
things.c - functions for dealing with things like potions and scrolls
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
Based on "Advanced Rogue"
|
||||
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
|
||||
All rights reserved.
|
||||
|
||||
Based on "Rogue: Exploring the Dungeons of Doom"
|
||||
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
inv_name()
|
||||
return the name of something as it would appear in an inventory.
|
||||
*/
|
||||
|
||||
char *
|
||||
inv_name(struct object *obj, int lowercase)
|
||||
{
|
||||
char *pb;
|
||||
char buf[1024];
|
||||
|
||||
switch(obj->o_type)
|
||||
{
|
||||
case SCROLL:
|
||||
if (obj->o_count == 1)
|
||||
sprintf(prbuf, "A %s%sscroll ",
|
||||
obj->o_flags & CANRETURN ? "claimed " : "",
|
||||
blesscurse(obj->o_flags));
|
||||
else
|
||||
sprintf(prbuf, "%d %s%sscrolls ",
|
||||
obj->o_count,
|
||||
obj->o_flags & CANRETURN ? "claimed " : "",
|
||||
blesscurse(obj->o_flags));
|
||||
|
||||
pb = &prbuf[strlen(prbuf)];
|
||||
|
||||
if (know_items[TYP_SCROLL][obj->o_which])
|
||||
sprintf(pb, "of %s", s_magic[obj->o_which].mi_name);
|
||||
else if (guess_items[TYP_SCROLL][obj->o_which])
|
||||
sprintf(pb, "called %s", guess_items[TYP_SCROLL][obj->o_which]);
|
||||
else
|
||||
sprintf(pb, "titled '%s'", s_names[obj->o_which]);
|
||||
break;
|
||||
|
||||
case POTION:
|
||||
if (obj->o_count == 1)
|
||||
sprintf(prbuf, "A %s%spotion ",
|
||||
obj->o_flags & CANRETURN ? "claimed " : "",
|
||||
blesscurse(obj->o_flags));
|
||||
else
|
||||
sprintf(prbuf, "%d %s%spotions ",
|
||||
obj->o_count,
|
||||
obj->o_flags & CANRETURN ? "claimed " : "",
|
||||
blesscurse(obj->o_flags));
|
||||
|
||||
pb = &prbuf[strlen(prbuf)];
|
||||
|
||||
if (know_items[TYP_POTION][obj->o_which])
|
||||
sprintf(pb, "of %s(%s)", p_magic[obj->o_which].mi_name,
|
||||
p_colors[obj->o_which]);
|
||||
else if (guess_items[TYP_POTION][obj->o_which])
|
||||
sprintf(pb, "called %s(%s)", guess_items[TYP_POTION][obj->o_which],
|
||||
p_colors[obj->o_which]);
|
||||
else
|
||||
{
|
||||
if (obj->o_count == 1)
|
||||
sprintf(prbuf, "A%s %s potion",
|
||||
obj->o_flags & CANRETURN ? " claimed" :
|
||||
(char *) vowelstr(p_colors[obj->o_which]),
|
||||
p_colors[obj->o_which]);
|
||||
else
|
||||
sprintf(prbuf, "%d %s%s potions",
|
||||
obj->o_count,
|
||||
obj->o_flags & CANRETURN ? "claimed " : "",
|
||||
(char *) p_colors[obj->o_which]);
|
||||
}
|
||||
break;
|
||||
|
||||
case FOOD:
|
||||
if (obj->o_count == 1)
|
||||
sprintf(prbuf, "A%s %s",
|
||||
obj->o_flags & CANRETURN ? " claimed" :
|
||||
(char *) vowelstr(fd_data[obj->o_which].mi_name),
|
||||
fd_data[obj->o_which].mi_name);
|
||||
else
|
||||
sprintf(prbuf, "%d %s%ss", obj->o_count,
|
||||
obj->o_flags & CANRETURN ? "claimed " : "",
|
||||
fd_data[obj->o_which].mi_name);
|
||||
break;
|
||||
|
||||
case WEAPON:
|
||||
if (obj->o_count > 1)
|
||||
sprintf(prbuf, "%d ", obj->o_count);
|
||||
else if ((obj->o_flags & (ISZAPPED | CANRETURN | ISPOISON | ISSILVER | ISTWOH)) ||
|
||||
((obj->o_flags & (ISKNOW | ISZAPPED)) == (ISKNOW | ISZAPPED)))
|
||||
strcpy(prbuf, "A ");
|
||||
else
|
||||
sprintf(prbuf, "A%s ", vowelstr(weaps[obj->o_which].w_name));
|
||||
|
||||
pb = &prbuf[strlen(prbuf)];
|
||||
|
||||
if ((obj->o_flags & ISKNOW) && (obj->o_flags & ISZAPPED))
|
||||
sprintf(pb, "charged%s ", charge_str(obj,buf));
|
||||
|
||||
pb = &prbuf[strlen(prbuf)];
|
||||
|
||||
if (obj->o_flags & CANRETURN)
|
||||
sprintf(pb, "claimed ");
|
||||
|
||||
pb = &prbuf[strlen(prbuf)];
|
||||
|
||||
if (obj->o_flags & ISPOISON)
|
||||
sprintf(pb, "poisoned ");
|
||||
|
||||
pb = &prbuf[strlen(prbuf)];
|
||||
|
||||
if (obj->o_flags & ISSILVER)
|
||||
sprintf(pb, "silver ");
|
||||
|
||||
if (obj->o_flags & ISTWOH)
|
||||
sprintf(pb, "two-handed ");
|
||||
|
||||
pb = &prbuf[strlen(prbuf)];
|
||||
|
||||
if (obj->o_flags & ISKNOW)
|
||||
sprintf(pb, "%s %s", num(obj->o_hplus, obj->o_dplus, buf),
|
||||
weaps[obj->o_which].w_name);
|
||||
else
|
||||
sprintf(pb, "%s", weaps[obj->o_which].w_name);
|
||||
|
||||
if (obj->o_count > 1)
|
||||
strcat(prbuf, "s");
|
||||
|
||||
break;
|
||||
|
||||
case ARMOR:
|
||||
if (obj->o_flags & ISKNOW)
|
||||
sprintf(prbuf, "%s%s %s",
|
||||
obj->o_flags & CANRETURN ? "claimed " : "",
|
||||
num(armors[obj->o_which].a_class - obj->o_ac, 0, buf),
|
||||
armors[obj->o_which].a_name);
|
||||
else
|
||||
sprintf(prbuf, "%s%s",
|
||||
obj->o_flags & CANRETURN ? "claimed " : "",
|
||||
armors[obj->o_which].a_name);
|
||||
|
||||
break;
|
||||
|
||||
case ARTIFACT:
|
||||
sprintf(prbuf, "the %s", arts[obj->o_which].ar_name);
|
||||
|
||||
if (obj->o_flags & CANRETURN)
|
||||
strcat(prbuf, " (claimed)");
|
||||
|
||||
break;
|
||||
|
||||
case STICK:
|
||||
sprintf(prbuf, "A %s%s%s ",
|
||||
obj->o_flags & CANRETURN ? "claimed " : "",
|
||||
blesscurse(obj->o_flags), ws_type[obj->o_which]);
|
||||
|
||||
pb = &prbuf[strlen(prbuf)];
|
||||
|
||||
if (know_items[TYP_STICK][obj->o_which])
|
||||
sprintf(pb, "of %s%s(%s)", ws_magic[obj->o_which].mi_name,
|
||||
charge_str(obj,buf), ws_made[obj->o_which]);
|
||||
else if (guess_items[TYP_STICK][obj->o_which])
|
||||
sprintf(pb, "called %s(%s)", guess_items[TYP_STICK][obj->o_which],
|
||||
ws_made[obj->o_which]);
|
||||
else
|
||||
sprintf(&prbuf[2], "%s%s %s",
|
||||
obj->o_flags & CANRETURN ? "claimed " : "",
|
||||
ws_made[obj->o_which],
|
||||
ws_type[obj->o_which]);
|
||||
|
||||
break;
|
||||
|
||||
case RING:
|
||||
if (know_items[TYP_RING][obj->o_which])
|
||||
sprintf(prbuf, "A%s%s ring of %s(%s)",
|
||||
obj->o_flags & CANRETURN ? " claimed" : "", ring_num(obj,buf),
|
||||
r_magic[obj->o_which].mi_name, r_stones[obj->o_which]);
|
||||
else if (guess_items[TYP_RING][obj->o_which])
|
||||
sprintf(prbuf, "A %sring called %s(%s)",
|
||||
obj->o_flags & CANRETURN ? "claimed " : "",
|
||||
guess_items[TYP_RING][obj->o_which], r_stones[obj->o_which]);
|
||||
else
|
||||
sprintf(prbuf, "A%s %s ring",
|
||||
obj->o_flags & CANRETURN ? "claimed " :
|
||||
(char *)vowelstr(r_stones[obj->o_which]),
|
||||
r_stones[obj->o_which]);
|
||||
break;
|
||||
|
||||
case GOLD:
|
||||
sprintf(prbuf, "%d gold pieces", obj->o_count);
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("Picked up something funny.");
|
||||
sprintf(prbuf, "Something bizarre %s", unctrl(obj->o_type));
|
||||
break;
|
||||
}
|
||||
|
||||
/* Is it marked? */
|
||||
|
||||
if (obj->o_mark[0])
|
||||
{
|
||||
pb = &prbuf[strlen(prbuf)];
|
||||
sprintf(pb, " <%s>", obj->o_mark);
|
||||
}
|
||||
|
||||
if (obj == cur_armor)
|
||||
strcat(prbuf, " (being worn)");
|
||||
|
||||
if (obj == cur_weapon)
|
||||
strcat(prbuf, " (weapon in hand)");
|
||||
|
||||
if (obj == cur_ring[LEFT_1])
|
||||
strcat(prbuf, " (on left hand)");
|
||||
else if (obj == cur_ring[LEFT_2])
|
||||
strcat(prbuf, " (on left hand)");
|
||||
else if (obj == cur_ring[LEFT_3])
|
||||
strcat(prbuf, " (on left hand)");
|
||||
else if (obj == cur_ring[LEFT_4])
|
||||
strcat(prbuf, " (on left hand)");
|
||||
else if (obj == cur_ring[LEFT_5])
|
||||
strcat(prbuf, " (on left hand)");
|
||||
else if (obj == cur_ring[RIGHT_1])
|
||||
strcat(prbuf, " (on right hand)");
|
||||
else if (obj == cur_ring[RIGHT_2])
|
||||
strcat(prbuf, " (on right hand)");
|
||||
else if (obj == cur_ring[RIGHT_3])
|
||||
strcat(prbuf, " (on right hand)");
|
||||
else if (obj == cur_ring[RIGHT_4])
|
||||
strcat(prbuf, " (on right hand)");
|
||||
else if (obj == cur_ring[RIGHT_5])
|
||||
strcat(prbuf, " (on right hand)");
|
||||
|
||||
if (obj->o_flags & ISPROT)
|
||||
strcat(prbuf, " [protected]");
|
||||
|
||||
if (lowercase && isupper(prbuf[0]))
|
||||
prbuf[0] = (char) tolower(prbuf[0]);
|
||||
else if (!lowercase && islower(*prbuf))
|
||||
*prbuf = (char) toupper(*prbuf);
|
||||
|
||||
if (!lowercase)
|
||||
strcat(prbuf, ".");
|
||||
|
||||
return(prbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
rem_obj()
|
||||
Remove an object from the level.
|
||||
*/
|
||||
|
||||
void
|
||||
rem_obj(struct linked_list *item, int dis)
|
||||
{
|
||||
struct linked_list *llptr;
|
||||
struct object *objptr, *op;
|
||||
int x, y;
|
||||
|
||||
if (item == NULL)
|
||||
return;
|
||||
|
||||
detach(lvl_obj, item);
|
||||
objptr = OBJPTR(item);
|
||||
|
||||
if ( (llptr = objptr->next_obj) != NULL )
|
||||
{
|
||||
detach((objptr->next_obj), llptr);
|
||||
attach(lvl_obj, llptr);
|
||||
|
||||
op = OBJPTR(llptr);
|
||||
|
||||
op->next_obj = objptr->next_obj;
|
||||
|
||||
if (op->next_obj)
|
||||
objptr->next_obj->l_prev = NULL;
|
||||
|
||||
y = op->o_pos.y;
|
||||
x = op->o_pos.x;
|
||||
|
||||
if (cansee(y, x))
|
||||
mvwaddch(cw, y, x, op->o_type);
|
||||
|
||||
mvaddch(y, x, op->o_type);
|
||||
}
|
||||
else
|
||||
{
|
||||
y = objptr->o_pos.y;
|
||||
x = objptr->o_pos.x;
|
||||
|
||||
/* problems if dropped in rock */
|
||||
|
||||
mvaddch(y,x,(roomin((objptr->o_pos)) == NULL ? PASSAGE : FLOOR));
|
||||
}
|
||||
|
||||
if (dis)
|
||||
discard(item);
|
||||
}
|
||||
|
||||
/*
|
||||
add_obj()
|
||||
adds an object to the level
|
||||
*/
|
||||
|
||||
void
|
||||
add_obj(struct linked_list *item, int y, int x)
|
||||
{
|
||||
struct linked_list *llptr;
|
||||
struct object*objptr;
|
||||
|
||||
llptr = find_obj(y, x);
|
||||
|
||||
if (llptr)
|
||||
{
|
||||
objptr = OBJPTR(llptr);
|
||||
attach((objptr->next_obj), item);
|
||||
}
|
||||
else
|
||||
{
|
||||
attach(lvl_obj, item);
|
||||
objptr = OBJPTR(item);
|
||||
objptr->next_obj = NULL;
|
||||
objptr->o_pos.y = y;
|
||||
objptr->o_pos.x = x;
|
||||
mvaddch(y, x, objptr->o_type);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
drop()
|
||||
put something down
|
||||
*/
|
||||
|
||||
int
|
||||
drop(struct linked_list *item)
|
||||
{
|
||||
char ch = CCHAR( mvwinch(stdscr, hero.y, hero.x) );
|
||||
struct object *obj;
|
||||
|
||||
switch (ch)
|
||||
{
|
||||
case GOLD:
|
||||
case POTION:
|
||||
case SCROLL:
|
||||
case FOOD:
|
||||
case WEAPON:
|
||||
case ARMOR:
|
||||
case RING:
|
||||
case STICK:
|
||||
case FLOOR:
|
||||
case PASSAGE:
|
||||
case POOL:
|
||||
case ARTIFACT:
|
||||
if (item == NULL && (item = get_item("drop", 0)) == NULL)
|
||||
return(FALSE);
|
||||
break;
|
||||
|
||||
default:
|
||||
msg("You can't drop something here.");
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
obj = OBJPTR(item);
|
||||
|
||||
if (!dropcheck(obj))
|
||||
return(FALSE);
|
||||
|
||||
/* Curse a dropped scare monster scroll */
|
||||
|
||||
if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
|
||||
{
|
||||
if (obj->o_flags & ISBLESSED)
|
||||
obj->o_flags &= ~ISBLESSED;
|
||||
else
|
||||
obj->o_flags |= ISCURSED;
|
||||
}
|
||||
|
||||
/* Take it out of the pack */
|
||||
|
||||
if (obj->o_count >= 2 && obj->o_group == 0)
|
||||
{
|
||||
struct linked_list *nitem = new_item(sizeof *obj);
|
||||
|
||||
obj->o_count--;
|
||||
obj = OBJPTR(nitem);
|
||||
*obj = *(OBJPTR(item));
|
||||
obj->o_count = 1;
|
||||
item = nitem;
|
||||
}
|
||||
else
|
||||
rem_pack(obj);
|
||||
|
||||
if (ch == POOL)
|
||||
{
|
||||
msg("The pool bubbles briefly as your %s sinks out of sight.",
|
||||
inv_name(obj, TRUE));
|
||||
discard(item);
|
||||
item = NULL;
|
||||
}
|
||||
else /* Link it into the level object list */
|
||||
{
|
||||
add_obj(item, hero.y, hero.x);
|
||||
mvaddch(hero.y, hero.x, obj->o_type);
|
||||
}
|
||||
|
||||
if (obj->o_type == ARTIFACT)
|
||||
has_artifact &= ~(1 << obj->o_which);
|
||||
|
||||
updpack();
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
dropcheck()
|
||||
do special checks for dropping or unweilding|unwearing|unringing
|
||||
*/
|
||||
|
||||
int
|
||||
dropcheck(struct object *op)
|
||||
{
|
||||
if (op == NULL)
|
||||
return(TRUE);
|
||||
|
||||
if (op != cur_armor && op != cur_weapon &&
|
||||
op != cur_ring[LEFT_1] && op != cur_ring[LEFT_2] &&
|
||||
op != cur_ring[LEFT_3] && op != cur_ring[LEFT_4] &&
|
||||
op != cur_ring[LEFT_5] &&
|
||||
op != cur_ring[RIGHT_1] && op != cur_ring[RIGHT_2] &&
|
||||
op != cur_ring[RIGHT_3] && op != cur_ring[RIGHT_4] &&
|
||||
op != cur_ring[RIGHT_5])
|
||||
return(TRUE);
|
||||
|
||||
if (op->o_flags & ISCURSED)
|
||||
{
|
||||
msg("You can't. It appears to be cursed.");
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (op == cur_weapon)
|
||||
cur_weapon = NULL;
|
||||
else if (op == cur_armor)
|
||||
{
|
||||
waste_time();
|
||||
cur_armor = NULL;
|
||||
}
|
||||
else if (op == cur_ring[LEFT_1] || op == cur_ring[LEFT_2] ||
|
||||
op == cur_ring[LEFT_3] || op == cur_ring[LEFT_4] ||
|
||||
op == cur_ring[LEFT_5] ||
|
||||
op == cur_ring[RIGHT_1] || op == cur_ring[RIGHT_2] ||
|
||||
op == cur_ring[RIGHT_3] || op == cur_ring[RIGHT_4] ||
|
||||
op == cur_ring[RIGHT_5])
|
||||
{
|
||||
if (op == cur_ring[LEFT_1])
|
||||
cur_ring[LEFT_1] = NULL;
|
||||
else if (op == cur_ring[LEFT_2])
|
||||
cur_ring[LEFT_2] = NULL;
|
||||
else if (op == cur_ring[LEFT_3])
|
||||
cur_ring[LEFT_3] = NULL;
|
||||
else if (op == cur_ring[LEFT_4])
|
||||
cur_ring[LEFT_4] = NULL;
|
||||
else if (op == cur_ring[LEFT_5])
|
||||
cur_ring[LEFT_5] = NULL;
|
||||
else if (op == cur_ring[RIGHT_1])
|
||||
cur_ring[RIGHT_1] = NULL;
|
||||
else if (op == cur_ring[RIGHT_2])
|
||||
cur_ring[RIGHT_2] = NULL;
|
||||
else if (op == cur_ring[RIGHT_3])
|
||||
cur_ring[RIGHT_3] = NULL;
|
||||
else if (op == cur_ring[RIGHT_4])
|
||||
cur_ring[RIGHT_4] = NULL;
|
||||
else if (op == cur_ring[RIGHT_5])
|
||||
cur_ring[RIGHT_5] = NULL;
|
||||
|
||||
switch (op->o_which)
|
||||
{
|
||||
case R_ADDSTR:
|
||||
chg_str(-op->o_ac, FALSE, FALSE);
|
||||
break;
|
||||
case R_ADDHIT:
|
||||
chg_dext(-op->o_ac, FALSE, FALSE);
|
||||
break;
|
||||
case R_ADDINTEL:
|
||||
pstats.s_intel -= op->o_ac;
|
||||
break;
|
||||
case R_ADDWISDOM:
|
||||
pstats.s_wisdom -= op->o_ac;
|
||||
break;
|
||||
|
||||
case R_SEEINVIS:
|
||||
if (find_slot(FUSE_UNSEE,FUSE) == NULL)
|
||||
{
|
||||
turn_off(player, CANSEE);
|
||||
msg("The tingling feeling leaves your eyes.");
|
||||
}
|
||||
|
||||
light(&hero);
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
break;
|
||||
|
||||
case R_LIGHT:
|
||||
if (roomin(hero) != NULL)
|
||||
{
|
||||
light(&hero);
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
new_thing()
|
||||
return a new thing
|
||||
*/
|
||||
|
||||
struct linked_list *
|
||||
new_thing(void)
|
||||
{
|
||||
int j, k;
|
||||
struct linked_list *item;
|
||||
struct object *cur;
|
||||
short blesschance = srnd(100);
|
||||
short cursechance = srnd(100);
|
||||
|
||||
item = new_item(sizeof *cur);
|
||||
cur = OBJPTR(item);
|
||||
cur->o_hplus = cur->o_dplus = 0;
|
||||
cur->o_damage = cur->o_hurldmg = "0d0";
|
||||
cur->o_ac = 11;
|
||||
cur->o_count = 1;
|
||||
cur->o_group = 0;
|
||||
cur->o_flags = 0;
|
||||
cur->o_weight = 0;
|
||||
cur->o_mark[0] = '\0';
|
||||
|
||||
/*
|
||||
* Decide what kind of object it will be If we haven't had food for a
|
||||
* while, let it be food.
|
||||
*/
|
||||
|
||||
switch (no_food > 3 ? TYP_FOOD : pick_one(things, numthings))
|
||||
{
|
||||
case TYP_POTION:
|
||||
cur->o_type = POTION;
|
||||
cur->o_which = pick_one(p_magic, maxpotions);
|
||||
cur->o_weight = things[TYP_POTION].mi_wght;
|
||||
|
||||
if (cursechance < p_magic[cur->o_which].mi_curse)
|
||||
cur->o_flags |= ISCURSED;
|
||||
else if (blesschance < p_magic[cur->o_which].mi_bless)
|
||||
cur->o_flags |= ISBLESSED;
|
||||
break;
|
||||
|
||||
case TYP_SCROLL:
|
||||
cur->o_type = SCROLL;
|
||||
cur->o_which = pick_one(s_magic, maxscrolls);
|
||||
cur->o_weight = things[TYP_SCROLL].mi_wght;
|
||||
|
||||
if (cursechance < s_magic[cur->o_which].mi_curse)
|
||||
cur->o_flags |= ISCURSED;
|
||||
else if (blesschance < s_magic[cur->o_which].mi_bless)
|
||||
cur->o_flags |= ISBLESSED;
|
||||
break;
|
||||
|
||||
case TYP_FOOD:
|
||||
no_food = 0;
|
||||
cur->o_type = FOOD;
|
||||
cur->o_which = pick_one(fd_data, maxfoods);
|
||||
cur->o_weight = 2;
|
||||
cur->o_count += extras();
|
||||
break;
|
||||
|
||||
case TYP_WEAPON:
|
||||
cur->o_type = WEAPON;
|
||||
cur->o_which = rnd(maxweapons);
|
||||
init_weapon(cur, cur->o_which);
|
||||
|
||||
if (cursechance < 10)
|
||||
{
|
||||
short bad = (rnd(10) < 1) ? 2 : 1;
|
||||
|
||||
cur->o_flags |= ISCURSED;
|
||||
cur->o_hplus -= bad;
|
||||
cur->o_dplus -= bad;
|
||||
}
|
||||
else if (blesschance < 15)
|
||||
{
|
||||
short good = (rnd(10) < 1) ? 2 : 1;
|
||||
|
||||
cur->o_hplus += good;
|
||||
cur->o_dplus += good;
|
||||
}
|
||||
break;
|
||||
|
||||
case TYP_ARMOR:
|
||||
cur->o_type = ARMOR;
|
||||
|
||||
for (j = 0; j < maxarmors; j++)
|
||||
if (blesschance < armors[j].a_prob)
|
||||
break;
|
||||
|
||||
if (j == maxarmors)
|
||||
{
|
||||
debug("Picked a bad armor %d", blesschance);
|
||||
j = 0;
|
||||
}
|
||||
|
||||
cur->o_which = j;
|
||||
cur->o_ac = armors[j].a_class;
|
||||
|
||||
if (((k = rnd(100)) < 20) && j != MITHRIL)
|
||||
{
|
||||
cur->o_flags |= ISCURSED;
|
||||
cur->o_ac += rnd(3) + 1;
|
||||
}
|
||||
else if (k < 28 || j == MITHRIL)
|
||||
cur->o_ac -= rnd(3) + 1;
|
||||
|
||||
if (j == MITHRIL)
|
||||
cur->o_flags |= ISPROT;
|
||||
|
||||
cur->o_weight = armors[j].a_wght;
|
||||
|
||||
break;
|
||||
|
||||
case TYP_RING:
|
||||
cur->o_type = RING;
|
||||
cur->o_which = pick_one(r_magic, maxrings);
|
||||
cur->o_weight = things[TYP_RING].mi_wght;
|
||||
|
||||
if (cursechance < r_magic[cur->o_which].mi_curse)
|
||||
cur->o_flags |= ISCURSED;
|
||||
else if (blesschance < r_magic[cur->o_which].mi_bless)
|
||||
cur->o_flags |= ISBLESSED;
|
||||
|
||||
switch (cur->o_which)
|
||||
{
|
||||
case R_ADDSTR:
|
||||
case R_ADDWISDOM:
|
||||
case R_ADDINTEL:
|
||||
case R_PROTECT:
|
||||
case R_ADDHIT:
|
||||
case R_ADDDAM:
|
||||
case R_CARRYING:
|
||||
cur->o_ac = rnd(2) + 1; /* From 1 to 3 */
|
||||
|
||||
if (cur->o_flags & ISCURSED)
|
||||
cur->o_ac = -cur->o_ac;
|
||||
|
||||
if (cur->o_flags & ISBLESSED)
|
||||
cur->o_ac++;
|
||||
|
||||
break;
|
||||
|
||||
case R_RESURRECT:
|
||||
case R_TELCONTROL:
|
||||
case R_VREGEN:
|
||||
case R_REGEN:
|
||||
case R_PIETY:
|
||||
case R_WIZARD:
|
||||
cur->o_ac = 0;
|
||||
|
||||
if (cur->o_flags & ISCURSED)
|
||||
cur->o_ac = -1;
|
||||
|
||||
if (cur->o_flags & ISBLESSED)
|
||||
cur->o_ac = 1;
|
||||
|
||||
break;
|
||||
|
||||
case R_DIGEST:
|
||||
|
||||
if (cur->o_flags & ISCURSED)
|
||||
cur->o_ac = -1;
|
||||
else if (cur->o_flags & ISBLESSED)
|
||||
cur->o_ac = 2;
|
||||
else
|
||||
cur->o_ac = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
cur->o_ac = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case TYP_STICK:
|
||||
cur->o_type = STICK;
|
||||
cur->o_which = pick_one(ws_magic, maxsticks);
|
||||
fix_stick(cur);
|
||||
|
||||
if (cursechance < ws_magic[cur->o_which].mi_curse)
|
||||
cur->o_flags |= ISCURSED;
|
||||
else if (blesschance < ws_magic[cur->o_which].mi_bless)
|
||||
cur->o_flags |= ISBLESSED;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("Picked a bad kind of object");
|
||||
wait_for(' ');
|
||||
}
|
||||
|
||||
return(item);
|
||||
}
|
||||
|
||||
/*
|
||||
spec_item()
|
||||
provide a new item tailored to specification
|
||||
*/
|
||||
|
||||
struct linked_list *
|
||||
spec_item(char type, int which, int hitp, int damage)
|
||||
{
|
||||
struct linked_list *item;
|
||||
struct object *obj;
|
||||
|
||||
item = new_item(sizeof *obj);
|
||||
obj = OBJPTR(item);
|
||||
|
||||
obj->o_count = 1;
|
||||
obj->o_group = 0;
|
||||
obj->o_type = type;
|
||||
obj->o_which = which;
|
||||
obj->o_damage = obj->o_hurldmg = "0d0";
|
||||
obj->o_hplus = 0;
|
||||
obj->o_dplus = 0;
|
||||
obj->o_flags = 0;
|
||||
obj->o_mark[0] = '\0';
|
||||
obj->o_text = NULL;
|
||||
obj->o_launch = 0;
|
||||
obj->o_weight = 0;
|
||||
|
||||
switch(type) /* Handle special characteristics */
|
||||
{
|
||||
case WEAPON:
|
||||
init_weapon(obj, which);
|
||||
obj->o_hplus = hitp;
|
||||
obj->o_dplus = damage;
|
||||
obj->o_ac = 10;
|
||||
break;
|
||||
|
||||
case ARMOR:
|
||||
obj->o_ac = armors[which].a_class - hitp;
|
||||
break;
|
||||
|
||||
case RING:
|
||||
obj->o_ac = hitp;
|
||||
break;
|
||||
|
||||
case STICK:
|
||||
fix_stick(obj);
|
||||
obj->o_charges = hitp;
|
||||
break;
|
||||
|
||||
case GOLD:
|
||||
obj->o_type = GOLD;
|
||||
obj->o_count = GOLDCALC;
|
||||
obj->o_ac = 11;
|
||||
break;
|
||||
}
|
||||
|
||||
if (hitp > 0 || damage > 0)
|
||||
obj->o_flags |= ISBLESSED;
|
||||
else if (hitp < 0 || damage < 0)
|
||||
obj->o_flags |= ISCURSED;
|
||||
|
||||
return(item);
|
||||
}
|
||||
|
||||
/*
|
||||
pick_one()
|
||||
pick an item out of a list of nitems possible magic items
|
||||
*/
|
||||
|
||||
int
|
||||
pick_one(struct magic_item *magic, int nitems)
|
||||
{
|
||||
int i;
|
||||
struct magic_item *end;
|
||||
struct magic_item *start = magic;
|
||||
|
||||
for (end = &magic[nitems], i = rnd(1000); magic < end; magic++)
|
||||
if (i <= magic->mi_prob)
|
||||
break;
|
||||
|
||||
if (magic == end)
|
||||
{
|
||||
if (wizard)
|
||||
{
|
||||
add_line("Bad pick_one: %d from %d items", i, nitems);
|
||||
|
||||
for (magic = start; magic < end; magic++)
|
||||
add_line("%s: %d%%", magic->mi_name, magic->mi_prob);
|
||||
|
||||
end_line();
|
||||
}
|
||||
magic = start;
|
||||
}
|
||||
|
||||
return((int)(magic - start));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
blesscurse()
|
||||
returns whether the object is blessed or cursed
|
||||
*/
|
||||
|
||||
char *
|
||||
blesscurse(long flags)
|
||||
{
|
||||
if (flags & ISKNOW)
|
||||
{
|
||||
if (flags & ISCURSED)
|
||||
return("cursed ");
|
||||
|
||||
if (flags & ISBLESSED)
|
||||
return("blessed ");
|
||||
|
||||
return("normal ");
|
||||
}
|
||||
|
||||
return("");
|
||||
}
|
||||
|
||||
/*
|
||||
extras()
|
||||
Return the number of extra food items to be created
|
||||
*/
|
||||
|
||||
int
|
||||
extras(void)
|
||||
{
|
||||
int i = rnd(100);
|
||||
|
||||
if (i < 10)
|
||||
return(2);
|
||||
else if (i < 20)
|
||||
return(1);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
name_type()
|
||||
Returns a string identifying a pack item's type
|
||||
*/
|
||||
|
||||
char *
|
||||
name_type(int type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case ARMOR:
|
||||
return ("armor");
|
||||
|
||||
case WEAPON:
|
||||
return ("weapons");
|
||||
|
||||
case SCROLL:
|
||||
return ("scrolls");
|
||||
|
||||
case RING:
|
||||
return ("rings");
|
||||
|
||||
case STICK:
|
||||
return ("staffs");
|
||||
|
||||
case POTION:
|
||||
return ("potions");
|
||||
|
||||
case FOOD:
|
||||
return ("food");
|
||||
|
||||
case GOLD:
|
||||
return ("gold");
|
||||
|
||||
default:
|
||||
return ("items");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
make_item()
|
||||
adds a linked_list structure to the top of an object for interfacing
|
||||
with other routines
|
||||
*/
|
||||
|
||||
linked_list *
|
||||
make_item(object *obj_p)
|
||||
{
|
||||
linked_list *item_p = new_list();
|
||||
|
||||
item_p->l_next = item_p->l_prev = NULL;
|
||||
|
||||
item_p->data.obj = obj_p;
|
||||
|
||||
return(item_p);
|
||||
}
|
||||
|
||||
/*
|
||||
is_member()
|
||||
Checks to see if a character is a member of an array
|
||||
*/
|
||||
|
||||
int
|
||||
is_member(char *list_p, int member)
|
||||
{
|
||||
while (*list_p != 0)
|
||||
{
|
||||
if (*list_p++ == member)
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
808
urogue/trader.c
Normal file
808
urogue/trader.c
Normal file
|
|
@ -0,0 +1,808 @@
|
|||
/*
|
||||
trader.c - Anything to do with trading posts
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
Based on "Advanced Rogue"
|
||||
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
|
||||
All rights reserved.
|
||||
|
||||
Based on "Rogue: Exploring the Dungeons of Doom"
|
||||
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include "rogue.h"
|
||||
|
||||
#define EFFECTIVE_PURSE ((player.t_ctype==C_PALADIN)?(9 * purse / 10) : purse)
|
||||
|
||||
/*
|
||||
do_post()
|
||||
Buy and sell things in a trading post
|
||||
*/
|
||||
|
||||
void
|
||||
display_postinfo(void)
|
||||
{
|
||||
wclear(hw);
|
||||
wstandout(hw);
|
||||
mvwaddstr(hw, 0, COLS / 2 - 30,
|
||||
"Welcome to Friendly Fiend's Flea Market" );
|
||||
wstandend(hw);
|
||||
wclrtoeol(hw);
|
||||
trans_line();
|
||||
}
|
||||
|
||||
void
|
||||
do_post(void)
|
||||
{
|
||||
int bad_letter = FALSE;
|
||||
|
||||
player.t_trans = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (!open_market())
|
||||
return;
|
||||
|
||||
display_postinfo();
|
||||
|
||||
if (bad_letter)
|
||||
{
|
||||
bad_letter = FALSE;
|
||||
wstandout(hw);
|
||||
mvwaddstr(hw, 7, 0, "Type 'i' or 'I' to inventory, "
|
||||
"'l' to leave, 'b' to buy, or 's' to sell");
|
||||
wstandend(hw);
|
||||
}
|
||||
|
||||
mvwaddstr(hw, 6, 0, "Do you wish to buy, sell, inventory, or leave?");
|
||||
wrefresh(hw);
|
||||
|
||||
switch(readcharw(hw))
|
||||
{
|
||||
case 'b':
|
||||
mvwaddstr(hw, 7, 0,
|
||||
"Lets go into the buying section of the store...");
|
||||
touchwin(hw);
|
||||
wrefresh(hw);
|
||||
buy_it('\0', ISNORMAL);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
mvwaddstr(hw, 7, 0,
|
||||
"Lets go into the selling section of the store...");
|
||||
touchwin(hw);
|
||||
wrefresh(hw);
|
||||
sell_it();
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
inventory(pack, '*');
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
wclear(hw);
|
||||
wrefresh(hw);
|
||||
inventory(pack, 0);
|
||||
msg(" ");
|
||||
msg("");
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
wclear(hw);
|
||||
wrefresh(hw);
|
||||
return;
|
||||
|
||||
default:
|
||||
bad_letter = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
buy_it(char itemtype, int flags)
|
||||
{
|
||||
int i;
|
||||
int blessed = flags & ISBLESSED;
|
||||
int cursed = flags & ISCURSED;
|
||||
int is_spell = flags & SCR_MAGIC;
|
||||
int array_size; /* # of items within type */
|
||||
int which_type = 0; /* Which type to buy */
|
||||
int which_one; /* Which one within type */
|
||||
int plus_or_minus = 0; /* for magic items */
|
||||
const struct magic_item *magic_array = NULL;
|
||||
struct linked_list *item;
|
||||
struct object *obj;
|
||||
char buf[2 * LINELEN];
|
||||
|
||||
buy_more:
|
||||
|
||||
display_postinfo();
|
||||
|
||||
do
|
||||
{
|
||||
array_size = 0;
|
||||
|
||||
if (itemtype == '\0')
|
||||
{
|
||||
mpos = 0;
|
||||
wmove(hw,10,0);
|
||||
wclrtoeol(hw);
|
||||
mvwaddstr(hw, 11, 0, "WHAT\tTYPE\n! Potion\n? Scroll\n"
|
||||
"= Ring\n/ Stick\n] Armor\n) Weapon\n: Food");
|
||||
|
||||
if (wizard)
|
||||
mvwaddstr(hw, 19, 0, ", Artifact");
|
||||
|
||||
mvwaddstr(hw, 9, 0, "What type of item do you want? ");
|
||||
wclrtoeol(hw);
|
||||
touchwin(hw);
|
||||
wrefresh(hw);
|
||||
itemtype = readcharw(hw);
|
||||
}
|
||||
|
||||
switch(itemtype)
|
||||
{
|
||||
case POTION:
|
||||
which_type = TYP_POTION;
|
||||
array_size = maxpotions;
|
||||
magic_array = p_magic;
|
||||
break;
|
||||
|
||||
case SCROLL:
|
||||
which_type = TYP_SCROLL;
|
||||
array_size = maxscrolls;
|
||||
magic_array = s_magic;
|
||||
break;
|
||||
|
||||
case FOOD:
|
||||
which_type = TYP_FOOD;
|
||||
array_size = maxfoods;
|
||||
magic_array = fd_data;
|
||||
break;
|
||||
|
||||
case WEAPON:
|
||||
which_type = TYP_WEAPON;
|
||||
array_size = maxweapons;
|
||||
break;
|
||||
|
||||
case ARMOR:
|
||||
which_type = TYP_ARMOR;
|
||||
array_size = maxarmors;
|
||||
break;
|
||||
|
||||
case RING:
|
||||
which_type = TYP_RING;
|
||||
array_size = maxrings;
|
||||
magic_array = r_magic;
|
||||
break;
|
||||
|
||||
case STICK:
|
||||
which_type = TYP_STICK;
|
||||
array_size = maxsticks;
|
||||
magic_array = ws_magic;
|
||||
break;
|
||||
|
||||
case ARTIFACT:
|
||||
if (!wizard)
|
||||
{
|
||||
itemtype = '\0';
|
||||
continue;
|
||||
}
|
||||
|
||||
which_type = TYP_ARTIFACT;
|
||||
array_size = maxartifact;
|
||||
break;
|
||||
|
||||
case ESCAPE:
|
||||
return;
|
||||
|
||||
default:
|
||||
wstandout(hw);
|
||||
mvwaddstr(hw, 10, 0, "We don't stock any of those.");
|
||||
wstandend(hw);
|
||||
itemtype = '\0';
|
||||
continue;
|
||||
}
|
||||
}
|
||||
while (array_size == 0);
|
||||
|
||||
which_one = array_size;
|
||||
|
||||
do
|
||||
{
|
||||
const struct magic_item *m_item;
|
||||
|
||||
display_postinfo();
|
||||
|
||||
mpos = 0;
|
||||
sprintf(buf, "Which kind of %s do you wish to have (* for list)? ",
|
||||
things[which_type].mi_name);
|
||||
|
||||
mvwaddstr(hw, 9, 0, buf);
|
||||
|
||||
touchwin(hw);
|
||||
wrefresh(hw);
|
||||
buf[0] = '\0';
|
||||
|
||||
switch (get_string(buf, hw))
|
||||
{
|
||||
case QUIT:
|
||||
case ESCAPE:
|
||||
itemtype = '\0';
|
||||
goto buy_more;
|
||||
}
|
||||
|
||||
if (buf[0] == '*') /* print list */
|
||||
{
|
||||
add_line(" ID BASECOST NAME");
|
||||
|
||||
switch (which_type)
|
||||
{
|
||||
case TYP_RING:
|
||||
case TYP_POTION:
|
||||
case TYP_STICK:
|
||||
case TYP_SCROLL:
|
||||
case TYP_FOOD:
|
||||
|
||||
for(i=0,m_item=magic_array; i < array_size; i++, m_item++)
|
||||
if (!is_spell && m_item->mi_worth > 0)
|
||||
{
|
||||
sprintf(buf, "%3d) %8d %s", i, m_item->mi_worth,
|
||||
m_item->mi_name);
|
||||
add_line(buf);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYP_ARMOR:
|
||||
for (i = 0; i < array_size; i++)
|
||||
if (!is_spell && armors[i].a_worth > 0)
|
||||
{
|
||||
sprintf(buf, "%3d) %8d %s", i, armors[i].a_worth,
|
||||
armors[i].a_name);
|
||||
|
||||
add_line(buf);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYP_WEAPON:
|
||||
for (i = 0; i < array_size; i++)
|
||||
if (!is_spell && weaps[i].w_worth > 0)
|
||||
{
|
||||
sprintf(buf, "%3d) %8d %s", i, weaps[i].w_worth,
|
||||
weaps[i].w_name);
|
||||
add_line(buf);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYP_ARTIFACT:
|
||||
for (i = 0; i < array_size; i++)
|
||||
{
|
||||
sprintf(buf, "%3d) %8d %s", i, arts[i].ar_worth,
|
||||
arts[i].ar_name);
|
||||
add_line(buf);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
add_line("What a strange type.");
|
||||
}
|
||||
|
||||
end_line();
|
||||
touchwin(hw);
|
||||
wrefresh(hw);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isdigit(buf[0]))
|
||||
which_one = atoi(buf);
|
||||
else
|
||||
switch (which_type)
|
||||
{
|
||||
case TYP_RING:
|
||||
case TYP_POTION:
|
||||
case TYP_STICK:
|
||||
case TYP_SCROLL:
|
||||
case TYP_FOOD:
|
||||
for (i=0,m_item=magic_array; i < array_size; i++, m_item++)
|
||||
if (strcmp(buf, m_item->mi_name) == 0)
|
||||
which_one = i;
|
||||
break;
|
||||
|
||||
case TYP_ARMOR:
|
||||
for (i = 0; i < array_size; i++)
|
||||
if (strcmp(buf, armors[i].a_name) == 0)
|
||||
which_one = i;
|
||||
break;
|
||||
|
||||
case TYP_WEAPON:
|
||||
for (i = 0; i < array_size; i++)
|
||||
if (strcmp(buf, weaps[i].w_name) == 0)
|
||||
which_one = i;
|
||||
break;
|
||||
|
||||
case TYP_ARTIFACT:
|
||||
for (i = 0; i < array_size; i++)
|
||||
if (strcmp(buf, arts[i].ar_name) == 0)
|
||||
which_one = i;
|
||||
break;
|
||||
|
||||
default:
|
||||
msg("What a strange type.");
|
||||
}
|
||||
|
||||
if (which_one < 0 || which_one >= array_size)
|
||||
{
|
||||
wstandout(hw);
|
||||
mvwaddstr(hw, 10, 0, "Type the name or an ID number.");
|
||||
wstandend(hw);
|
||||
}
|
||||
}
|
||||
while (which_one < 0 || which_one >= array_size);
|
||||
|
||||
item = new_item(sizeof *obj);
|
||||
obj = OBJPTR(item);
|
||||
|
||||
if (which_type == TYP_ARTIFACT)
|
||||
{
|
||||
new_artifact(which_one, obj);
|
||||
add_pack(item, NOMESSAGE);
|
||||
itemtype = '\0';
|
||||
goto buy_more;
|
||||
}
|
||||
|
||||
obj->o_type = itemtype;
|
||||
obj->o_which = which_one;
|
||||
obj->o_mark[0] = '\0';
|
||||
obj->o_group = 0;
|
||||
obj->o_count = 1;
|
||||
obj->o_weight = 0;
|
||||
obj->o_dplus = obj->o_hplus = 0;
|
||||
obj->o_worth = 0;
|
||||
|
||||
if (!is_spell)
|
||||
{
|
||||
plus_or_minus = -100;
|
||||
|
||||
do
|
||||
{
|
||||
mvwaddstr(hw, 10, 0, "Do you want the cursed, blessed, or normal"
|
||||
" version? (c, b, n) [n]");
|
||||
touchwin(hw);
|
||||
wrefresh(hw);
|
||||
|
||||
blessed = cursed = FALSE;
|
||||
switch (readcharw(hw))
|
||||
{
|
||||
case ESCAPE:
|
||||
discard(item);
|
||||
itemtype = '\0';
|
||||
goto buy_more;
|
||||
|
||||
case 'c':
|
||||
cursed = TRUE;
|
||||
plus_or_minus = 0;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
blessed = TRUE;
|
||||
plus_or_minus = 0;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
case ' ':
|
||||
plus_or_minus = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
wstandout(hw);
|
||||
mvwaddstr(hw,11,0,"Type 'c' for cursed, 'b' for blessed, "
|
||||
"or 'n' for normal");
|
||||
wstandend(hw);
|
||||
}
|
||||
}
|
||||
while (plus_or_minus == -100);
|
||||
}
|
||||
|
||||
/* else used blessed, cursed from flags parameter */
|
||||
|
||||
if (which_type == TYP_WEAPON)
|
||||
init_weapon(obj, which_one);
|
||||
|
||||
obj->o_flags |= ISKNOW;
|
||||
|
||||
if (cursed)
|
||||
{
|
||||
plus_or_minus = -(rnd(2) + 1);
|
||||
obj->o_flags |= ISCURSED;
|
||||
}
|
||||
else if (blessed)
|
||||
{
|
||||
plus_or_minus = (rnd(3) + 1);
|
||||
obj->o_flags |= ISBLESSED;
|
||||
}
|
||||
else
|
||||
{
|
||||
plus_or_minus = 0;
|
||||
obj->o_flags |= ISNORMAL;
|
||||
}
|
||||
|
||||
switch (which_type)
|
||||
{
|
||||
case TYP_WEAPON:
|
||||
obj->o_hplus += plus_or_minus;
|
||||
obj->o_dplus += plus_or_minus;
|
||||
break;
|
||||
|
||||
case TYP_ARMOR:
|
||||
obj->o_weight = armors[which_one].a_wght;
|
||||
obj->o_ac = armors[which_one].a_class - plus_or_minus;
|
||||
break;
|
||||
|
||||
case TYP_STICK:
|
||||
fix_stick(obj);
|
||||
break;
|
||||
|
||||
case TYP_RING:
|
||||
obj->o_ac = plus_or_minus;
|
||||
break;
|
||||
|
||||
case TYP_SCROLL:
|
||||
case TYP_POTION:
|
||||
obj->o_weight = things[which_type].mi_wght;
|
||||
break;
|
||||
|
||||
case TYP_FOOD:
|
||||
break;
|
||||
|
||||
default:
|
||||
msg("That's a strange thing to try to own.");
|
||||
discard(item);
|
||||
itemtype = '\0';
|
||||
goto buy_more;
|
||||
}
|
||||
|
||||
obj->o_worth = get_worth(obj) * (luck + level / 15 + 1);
|
||||
describe_it(obj);
|
||||
|
||||
if (!wizard && obj->o_worth > EFFECTIVE_PURSE)
|
||||
{
|
||||
wstandout(hw);
|
||||
mvwaddstr(hw, 12, 0, "Unfortunately, you can't afford it.");
|
||||
wstandend(hw);
|
||||
wclrtoeol(hw);
|
||||
touchwin(hw);
|
||||
wrefresh(hw);
|
||||
wait_for(' ');
|
||||
discard(item);
|
||||
itemtype = '\0';
|
||||
goto buy_more;
|
||||
}
|
||||
|
||||
mvwaddstr(hw, 12, 0, "Do you want it? [y] ");
|
||||
wclrtoeol(hw);
|
||||
touchwin(hw);
|
||||
wrefresh(hw);
|
||||
|
||||
switch (readcharw(hw))
|
||||
{
|
||||
case ESCAPE:
|
||||
case 'n':
|
||||
msg("");
|
||||
discard(item);
|
||||
itemtype = '\0';
|
||||
goto buy_more;
|
||||
}
|
||||
|
||||
/* The hero bought the item here */
|
||||
|
||||
mpos = 0;
|
||||
|
||||
if (add_pack(item, NOMESSAGE) && !is_spell)
|
||||
{
|
||||
if (!wizard)
|
||||
{
|
||||
purse -= obj->o_worth; /* take his money */
|
||||
++player.t_trans;
|
||||
}
|
||||
|
||||
trans_line(); /* show remaining deals */
|
||||
|
||||
switch(which_type)
|
||||
{
|
||||
case TYP_RING:
|
||||
case TYP_STICK:
|
||||
case TYP_SCROLL:
|
||||
case TYP_POTION:
|
||||
know_items[which_type][which_one] = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
sell_it()
|
||||
Sell an item to the trading post
|
||||
*/
|
||||
|
||||
void
|
||||
sell_it(void)
|
||||
{
|
||||
struct object *obj;
|
||||
struct linked_list *item;
|
||||
char buf[2 * LINELEN];
|
||||
|
||||
wclear(cw);
|
||||
|
||||
if ((item = get_item("sell", 0)) == NULL)
|
||||
return;
|
||||
|
||||
obj = OBJPTR(item);
|
||||
msg("");
|
||||
display_postinfo();
|
||||
touchwin(hw);
|
||||
wrefresh(hw);
|
||||
|
||||
if ((obj->o_type == ARTIFACT) || (obj->o_worth = get_worth(obj)) == 0)
|
||||
{
|
||||
mpos = 0;
|
||||
msg("We don't buy those.");
|
||||
|
||||
if (is_wearing(R_ADORNMENT) && rnd(10) < 4)
|
||||
msg("How about that %s ring instead?", r_stones[R_ADORNMENT]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
describe_it(obj);
|
||||
mvwaddstr(hw, 12, 0, "Do you want to sell it? [n] ");
|
||||
touchwin(hw);
|
||||
wrefresh(hw);
|
||||
|
||||
switch( readcharw(hw) )
|
||||
{
|
||||
case 'y':
|
||||
break;
|
||||
default:
|
||||
msg("");
|
||||
if (is_wearing(R_ADORNMENT))
|
||||
msg("How about that %s ring instead?",
|
||||
r_stones[R_ADORNMENT]);
|
||||
return;
|
||||
}
|
||||
|
||||
rem_pack(obj);
|
||||
purse += obj->o_worth; /* give him his money */
|
||||
++player.t_trans;
|
||||
|
||||
sprintf(buf, "Sold %s. Hit space to continue.",
|
||||
inv_name(obj, LOWERCASE));
|
||||
discard(item);
|
||||
|
||||
mvwaddstr(hw, 13, 0, buf);
|
||||
touchwin(hw);
|
||||
wrefresh(hw);
|
||||
wait_for(' ');
|
||||
}
|
||||
|
||||
/*
|
||||
describe_it()
|
||||
Laud or condemn the object
|
||||
*/
|
||||
|
||||
extern char *inv_name();
|
||||
|
||||
void
|
||||
describe_it(struct object *obj)
|
||||
{
|
||||
static char *cursed_d[] =
|
||||
{
|
||||
"worthless hunk of junk",
|
||||
"shoddy piece of trash",
|
||||
"piece of rusty garbage",
|
||||
"example of terrible workmanship",
|
||||
"cheap hack"
|
||||
};
|
||||
|
||||
static char *normal_d[] =
|
||||
{
|
||||
"journeyman's piece",
|
||||
"fine deal",
|
||||
"great bargain",
|
||||
"good find",
|
||||
"real value",
|
||||
"piece of honest workmanship",
|
||||
"steal",
|
||||
"purchase worth making",
|
||||
"inexpensive product"
|
||||
};
|
||||
|
||||
static char *blessed_d[] =
|
||||
{
|
||||
"magnificant masterpiece",
|
||||
"quality product",
|
||||
"exceptional find",
|
||||
"unbeatable value",
|
||||
"rare beauty",
|
||||
"superior product",
|
||||
"well-crafted item"
|
||||
};
|
||||
|
||||
char *charp;
|
||||
char buf[2 * LINELEN];
|
||||
|
||||
if (obj->o_flags & ISBLESSED)
|
||||
charp = blessed_d[rnd(sizeof(blessed_d) / sizeof(char *))];
|
||||
else if (obj->o_flags & ISCURSED)
|
||||
charp = cursed_d[rnd(sizeof(cursed_d) / sizeof(char *))];
|
||||
else
|
||||
charp = normal_d[rnd(sizeof(normal_d) / sizeof(char *))];
|
||||
|
||||
sprintf(buf, "It's a%s %s worth %d pieces of gold.",
|
||||
vowelstr(charp), charp, obj->o_worth);
|
||||
|
||||
mvwaddstr(hw, 10, 0, inv_name(obj, TRUE));
|
||||
mvwaddstr(hw, 11, 0, buf);
|
||||
wclrtoeol(hw);
|
||||
}
|
||||
|
||||
/*
|
||||
open_market()
|
||||
Retruns TRUE when ok do to transacting
|
||||
*/
|
||||
|
||||
int
|
||||
open_market(void)
|
||||
{
|
||||
int maxtrans = is_wearing(R_ADORNMENT) ? MAXPURCH + 4 : MAXPURCH;
|
||||
|
||||
if (wizard || player.t_trans < maxtrans || (level == 0))
|
||||
return(TRUE);
|
||||
else
|
||||
{
|
||||
msg("The market is closed. The stairs are that-a-way.");
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
get_worth()
|
||||
Calculate an objects worth in gold
|
||||
*/
|
||||
|
||||
int
|
||||
get_worth(struct object *obj)
|
||||
{
|
||||
long worth = 0;
|
||||
int wh = obj->o_which;
|
||||
int blessed = obj->o_flags & ISBLESSED;
|
||||
int cursed = obj->o_flags & ISCURSED;
|
||||
|
||||
switch (obj->o_type)
|
||||
{
|
||||
case FOOD:
|
||||
if (wh < maxfoods)
|
||||
{
|
||||
worth = obj->o_count * fd_data[wh].mi_worth;
|
||||
if (blessed)
|
||||
worth *= 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case WEAPON:
|
||||
if (wh < maxweapons)
|
||||
{
|
||||
worth = weaps[wh].w_worth;
|
||||
worth *= obj->o_count * (2 +
|
||||
(4 * obj->o_hplus +
|
||||
4 * obj->o_dplus));
|
||||
|
||||
if (obj->o_flags & ISSILVER)
|
||||
worth *= 2;
|
||||
|
||||
if (obj->o_flags & ISPOISON)
|
||||
worth *= 2;
|
||||
|
||||
if (obj->o_flags & ISZAPPED)
|
||||
worth += 20 * obj->o_charges;
|
||||
}
|
||||
break;
|
||||
|
||||
case ARMOR:
|
||||
if (wh < maxarmors)
|
||||
{
|
||||
int plusses = armors[wh].a_class - obj->o_ac;
|
||||
|
||||
worth = armors[wh].a_worth;
|
||||
|
||||
if (plusses > 0)
|
||||
worth *= (1 + (10 *
|
||||
(armors[wh].a_class - obj->o_ac)));
|
||||
}
|
||||
break;
|
||||
|
||||
case SCROLL:
|
||||
if (wh < maxscrolls)
|
||||
worth = s_magic[wh].mi_worth;
|
||||
break;
|
||||
|
||||
case POTION:
|
||||
if (wh < maxpotions)
|
||||
worth = p_magic[wh].mi_worth;
|
||||
break;
|
||||
|
||||
case RING:
|
||||
if (wh < maxrings)
|
||||
{
|
||||
worth = r_magic[wh].mi_worth;
|
||||
worth += obj->o_ac * 40;
|
||||
}
|
||||
break;
|
||||
|
||||
case STICK:
|
||||
if (wh < maxsticks)
|
||||
{
|
||||
worth = ws_magic[wh].mi_worth;
|
||||
worth += 20 * obj->o_charges;
|
||||
}
|
||||
break;
|
||||
|
||||
case ARTIFACT:
|
||||
if (wh < maxartifact)
|
||||
worth = arts[wh].ar_worth;
|
||||
break;
|
||||
|
||||
default:
|
||||
worth = 0;
|
||||
}
|
||||
|
||||
if (obj->o_flags & ISPROT) /* 300% more for protected */
|
||||
worth *= 3;
|
||||
|
||||
if (blessed) /* 250% more for blessed */
|
||||
worth = 5 * worth / 2;
|
||||
else if (cursed) /* half for cursed */
|
||||
worth /= 2;
|
||||
|
||||
if (obj->o_flags & (CANRETURN | ISOWNED))
|
||||
worth *= 4;
|
||||
else if (obj->o_flags & CANRETURN)
|
||||
worth *= 2;
|
||||
else if (obj->o_flags & ISLOST)
|
||||
worth /= 3;
|
||||
|
||||
return(max(0, worth)); /* anything is worth at least one gold piece */
|
||||
}
|
||||
|
||||
/*
|
||||
trans_line()
|
||||
Show how many transactions the hero has left
|
||||
*/
|
||||
|
||||
void
|
||||
trans_line(void)
|
||||
{
|
||||
char buf[2 * LINELEN];
|
||||
int adorned = is_wearing(R_ADORNMENT);
|
||||
|
||||
if (level == 0 && purse > 0)
|
||||
sprintf(buf, "You still have %d pieces of gold left.", purse);
|
||||
else if (purse == 0)
|
||||
sprintf(buf, "You have no money left.");
|
||||
else if (!wizard)
|
||||
sprintf(buf, "You have %d transactions and %d gold pieces remaining.",
|
||||
max(0, (adorned ? MAXPURCH + 4 : MAXPURCH) - player.t_trans),
|
||||
EFFECTIVE_PURSE);
|
||||
else
|
||||
sprintf(buf, "You have infinite transactions remaining.");
|
||||
|
||||
mvwaddstr(hw, LINES - 2, 0, buf);
|
||||
}
|
||||
288
urogue/urogue.6
Normal file
288
urogue/urogue.6
Normal file
|
|
@ -0,0 +1,288 @@
|
|||
.\"
|
||||
.\" Last Modified: 06/16/86
|
||||
.\"
|
||||
.TH UROGUE 6 "1.03 Draft"
|
||||
.SH NAME
|
||||
urogue \- UltraRogue \- Exploring the dungeons of doom.
|
||||
.SH SYNTAX
|
||||
.B urogue
|
||||
[
|
||||
.I save-file
|
||||
]
|
||||
[
|
||||
.B \-k
|
||||
]
|
||||
[
|
||||
.B \-s
|
||||
]
|
||||
[
|
||||
.B \-n
|
||||
]
|
||||
[
|
||||
.B \-v
|
||||
]
|
||||
[
|
||||
.B \-r
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
.I UltraRogue
|
||||
is a advanced version of one of the more standard rogue games.
|
||||
It is much more difficult and interesting to play than the
|
||||
original version on which it is based (Advanced Rogue 2.0).
|
||||
Some of it's unique features include 10 player character classes,
|
||||
several hundred monsters, charmable monsters, etc.
|
||||
.PP
|
||||
To win the game
|
||||
you must locate 8 artifacts which start appearing from level 25
|
||||
down. You must then bring all artifacts back up out of the dungeon.
|
||||
These artifacts also may be
|
||||
.I applied
|
||||
to use some of their great powers! Be warned, though, sometimes these
|
||||
powers back-fire on you.
|
||||
.SH ENVIRONMENT
|
||||
The environment variable
|
||||
.B $UROGUE
|
||||
(the person installing
|
||||
.I UltraRogue
|
||||
may have changed this for your site)
|
||||
is checked to set certain default options for
|
||||
.I UltraRogue.
|
||||
The following may be set in the
|
||||
.B $UROGUE:
|
||||
.IP "\fBterse\fR (\fIboolean\fR)"
|
||||
Short output messages.
|
||||
.IP "\fBflush\fR (\fIboolean\fR)"
|
||||
Flush typeahead when fighting.
|
||||
.IP "\fBjump\fR (\fIboolean\fR)"
|
||||
Show position only at the end of running.
|
||||
.IP "\fBinven\fR (\fIstring\fR)"
|
||||
Inventory style.
|
||||
.IP "\fBaskme\fR (\fIboolean\fR)"
|
||||
Ask about unidentified things.
|
||||
.IP "\fBstopdoor\fR (\fIboolean\fR)"
|
||||
Stop running when next to something interesting.
|
||||
.IP "\fBname\fR (\fIstring\fR)"
|
||||
The rogue's name.
|
||||
.IP "\fBfruit\fR (\fIstring\fR)"
|
||||
The funny fruit used by the rogue.
|
||||
.IP "\fBfile\fR (\fIstring\fR)"
|
||||
Default savefile name.
|
||||
.IP "\fBscore\fR (\fIstring\fR)"
|
||||
Default scorefile name.
|
||||
.IP "\fBclass\fR (\fIstring\fR)"
|
||||
Default player class.
|
||||
.sp
|
||||
.PP
|
||||
Something like
|
||||
.nf
|
||||
.sp
|
||||
.in +.5in
|
||||
setenv UROGUE "name=VAX Killer,fruit=Peach,noterse,jump"
|
||||
.in -.5in
|
||||
.sp
|
||||
.fi
|
||||
does the obvious. The ``score'' option is ignored unless you start
|
||||
urogue in wizard mode. The class option string can have the following
|
||||
values: ``fighter'', ``illus'', ``paladin'', ``ranger'', ``cleric'', ``magic'',
|
||||
``assasin'', ``druid'', ``ninja'', and ``thief'' and is initialized only at
|
||||
startup time. The ``inven'' option can take the values ``slow'', ``clear'',
|
||||
and ``overwrite''.
|
||||
.PP
|
||||
You may change most of these values while playing with the
|
||||
.B ``o''
|
||||
command.
|
||||
.SH OPTIONS
|
||||
.PP
|
||||
If a
|
||||
.I save_file
|
||||
is specified,
|
||||
urogue will be restored from the specified saved game file.
|
||||
If the save file is named ``-r'', the default saved game file of
|
||||
.I ~/rogue.save
|
||||
is restored.
|
||||
The other options are:
|
||||
.IP \-k
|
||||
Place the terminal's kaypad into
|
||||
.I auxilary
|
||||
or
|
||||
.I applications
|
||||
mode. Once this is done, the keypad may be used for movement instead
|
||||
of the normal letter movement keys.
|
||||
The directions are ``1'' move left and down, ``2'' move down, ``3'' move
|
||||
right and down, ``6'' move right, ``9'' move right and up, ``8'' move up,
|
||||
``7'' move up, and ``4'' move left. If the user hits the <RUN> key
|
||||
(key ``5'') and then a direction, then the rogue will run in the specified
|
||||
direction.
|
||||
When the game ends the keypad is restored
|
||||
to normal
|
||||
.I numeric
|
||||
mode if \-k was specified. The user may also place the keypad into
|
||||
.I auxilary
|
||||
or
|
||||
.I applications
|
||||
mode manually and then may use the keypad without specifing the
|
||||
\-k option.
|
||||
.IP \-s
|
||||
Display the list of scores.
|
||||
.IP \-n
|
||||
Display the urogue news file.
|
||||
This is a file containing information on currently known bugs,
|
||||
changes, fixes, and enhancements to look for from the last version.
|
||||
.IP \-v
|
||||
Display the urogue version information.
|
||||
.SH COMMANDS
|
||||
The following is a list of commands for
|
||||
.I UltraRogue.
|
||||
You may see a similiar list during a
|
||||
.I UltraRogue
|
||||
game by using the
|
||||
.B ``?''
|
||||
command.
|
||||
A
|
||||
.I <direction>
|
||||
is one of
|
||||
\fB``h'', ``j'', ``k'', ``l'', ``y'', ``u'', ``b'', \fRor\fB
|
||||
``n''.\fR
|
||||
.IP \fB?\fR
|
||||
Print out a list of commands.
|
||||
.IP \fB/\fR
|
||||
Identify objects.
|
||||
.IP \fBh\fR
|
||||
Move left.
|
||||
.IP \fBj\fR
|
||||
Move down.
|
||||
.IP \fBk\fR
|
||||
Move up.
|
||||
.IP \fBl\fR
|
||||
Move right.
|
||||
.IP \fBy\fR
|
||||
Move up and left.
|
||||
.IP \fBu\fR
|
||||
Move up and right.
|
||||
.IP \fBb\fR
|
||||
Move down and left.
|
||||
.IP \fBn\fR
|
||||
Move down and right.
|
||||
.IP \fB<SHIFT><direction>\fR
|
||||
Run in
|
||||
.I <direction>.
|
||||
.IP \fBm<direction>\fR
|
||||
Move in
|
||||
.I <direction>
|
||||
without picking anything up.
|
||||
.IP \fBt<direction>\fR
|
||||
Throw something in
|
||||
.I <direction>.
|
||||
.IP \fBz<direction>\fR
|
||||
Zap a wand or staff in
|
||||
.I <direction>.
|
||||
.IP \fB>\fR
|
||||
Go down a staircase.
|
||||
.IP \fB<\fR
|
||||
Go up a staircase.
|
||||
You must possess at least one Artifact to go up a staircase.
|
||||
.IP \fBs\fR
|
||||
Search for a trap/secrect door.
|
||||
.IP \fB.\fR
|
||||
Rest (do nothing) for one turn.
|
||||
.IP \fBi\fR
|
||||
General inventory.
|
||||
.IP \fBI\fR
|
||||
Inventory a single item.
|
||||
.IP \fBq\fR
|
||||
Quaff a potion.
|
||||
.IP \fBr\fR
|
||||
Read paper.
|
||||
.IP \fBe\fR
|
||||
Eat one ration of food.
|
||||
.IP \fBw\fR
|
||||
Wield a weapon.
|
||||
.IP \fBW\fR
|
||||
Wear armor.
|
||||
.IP \fBT\fR
|
||||
Take armor off.
|
||||
.IP \fBP\fR
|
||||
Put on a ring.
|
||||
.IP \fBR\fR
|
||||
Remove a ring.
|
||||
.IP \fBA\fR
|
||||
Apply an Artifact.
|
||||
.IP \fBd\fR
|
||||
Drop an object.
|
||||
.IP \fBc\fR
|
||||
Call object (generic).
|
||||
.IP \fBM\fR
|
||||
Mark object (specific).
|
||||
.IP \fBo\fR
|
||||
Examine/set options.
|
||||
.IP \fBC\fR
|
||||
Cast a spell/say a prayer.
|
||||
.IP \fBp\fR
|
||||
Pray to a deity.
|
||||
.IP \fBa\fR
|
||||
Affect the undead.
|
||||
.IP \fB^\fR
|
||||
Set a trap.
|
||||
.IP \fBD\fR
|
||||
Dip something in a pool.
|
||||
.IP \fB^T\fR
|
||||
Take (steal) from
|
||||
.I <direction>.
|
||||
.IP \fB^R\fR
|
||||
Redraw screen.
|
||||
.IP \fB^P\fR
|
||||
Print last message.
|
||||
May go up to the last 10 messages.
|
||||
.IP \fB<ESCAPE>\fR
|
||||
Cancel current command.
|
||||
.IP \fBv\fR
|
||||
Print
|
||||
.I UltraRogue
|
||||
version information.
|
||||
.IP \fB!\fR
|
||||
Create a shell. Uses $SHELL if present in your environment.
|
||||
.IP \fBS\fR
|
||||
Save the current game.
|
||||
.IP \fBQ\fR
|
||||
Quit the current game.
|
||||
.IP \fB=\fR
|
||||
Listen for monsters.
|
||||
.IP \fBf<direction>\fR
|
||||
Fight monster in
|
||||
.I <direction>.
|
||||
.IP \fBF<direction>\fR
|
||||
Fight monster to death in
|
||||
.I <direction>.
|
||||
.IP \fB#\fR
|
||||
Buy the object the rogue is standing on.
|
||||
Used when in Friendly Fiend's Flea Market.
|
||||
.IP \fB$\fR
|
||||
Price the object the rogue is standing on.
|
||||
Used when in Friendly Fiend's Flea Market.
|
||||
.IP \fB%\fR
|
||||
Sell an object from the rogue's pack.
|
||||
Used when in Friendly Fiend's Flea Market.
|
||||
.SH FILES
|
||||
.DT
|
||||
.ta \w'/usr/games/lib/urogue/scorefile\ \ \ 'u
|
||||
/usr/games/lib/urogue/scorefile \- Score file
|
||||
.br
|
||||
.ta \w'/usr/games/lib/urogue/motd\ \ \ 'u
|
||||
/usr/games/lib/urogue/motd \- Message of the day
|
||||
.br
|
||||
.ta \w'/usr/games/lib/urogue/news\ \ \ 'u
|
||||
/usr/games/lib/urogue/news \- News file
|
||||
.br
|
||||
\fB~\fP/rogue.save \- Default save file
|
||||
.ST
|
||||
.SH SEE ALSO
|
||||
rogue(6),
|
||||
.br
|
||||
.I "A Guide to the Dungeons of Doom."
|
||||
.SH COPYRIGHT
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
.br
|
||||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
.br
|
||||
All rights reserved.
|
||||
20
urogue/urogue.sln
Normal file
20
urogue/urogue.sln
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||
# Visual C++ Express 2005
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "urogue", "urogue.vcproj", "{A428D711-A9BE-4A4E-9013-3AC25A18502D}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{A428D711-A9BE-4A4E-9013-3AC25A18502D}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{A428D711-A9BE-4A4E-9013-3AC25A18502D}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{A428D711-A9BE-4A4E-9013-3AC25A18502D}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{A428D711-A9BE-4A4E-9013-3AC25A18502D}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
440
urogue/urogue.vcproj
Normal file
440
urogue/urogue.vcproj
Normal file
|
|
@ -0,0 +1,440 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="urogue"
|
||||
ProjectGUID="{A428D711-A9BE-4A4E-9013-3AC25A18502D}"
|
||||
RootNamespace="urogue"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="1"
|
||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
InlineFunctionExpansion="0"
|
||||
AdditionalIncludeDirectories="../pdcurses"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;SCOREFILE;ALLSCORES"
|
||||
StringPooling="true"
|
||||
MinimalRebuild="true"
|
||||
ExceptionHandling="0"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
BufferSecurityCheck="true"
|
||||
EnableFunctionLevelLinking="true"
|
||||
DisableLanguageExtensions="false"
|
||||
ForceConformanceInForLoopScope="true"
|
||||
UsePrecompiledHeader="0"
|
||||
BrowseInformation="0"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="4"
|
||||
CompileAs="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="Ws2_32.lib pdcurses.lib advapi32.lib shfolder.lib user32.lib"
|
||||
OutputFile="$(OutDir)/rogue54.exe"
|
||||
LinkIncremental="2"
|
||||
AdditionalLibraryDirectories="../pdcurses"
|
||||
IgnoreDefaultLibraryNames="LIBC.LIB"
|
||||
GenerateDebugInformation="true"
|
||||
ProgramDatabaseFile="$(OutDir)/rogue54.pdb"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="1"
|
||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
InlineFunctionExpansion="1"
|
||||
OmitFramePointers="true"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
|
||||
StringPooling="true"
|
||||
RuntimeLibrary="0"
|
||||
EnableFunctionLevelLinking="true"
|
||||
UsePrecompiledHeader="2"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/rogue54.exe"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
|
||||
>
|
||||
<File
|
||||
RelativePath="armor.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\artifact.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\bag.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="chase.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="command.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="daemon.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="daemons.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\dict.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\dictutil.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\encumb.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="fight.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\getplay.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ident.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="init.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="io.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="list.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\magic.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="main.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\maze.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mdport.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\memory.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="misc.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\monsdata.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="monsters.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="move.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\newlvl.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="options.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="pack.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="passages.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\player.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="potions.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\random.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rings.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rip.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rooms.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="save.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="scrolls.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="state.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\status.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="sticks.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="things.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\trader.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\verify.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="vers.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="weapons.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="wizard.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\xcrypt.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\dict.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\dictutil.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\lint-curses.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rogue.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\history.txt"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="LICENSE.TXT"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="Makefile"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\README"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\TODO"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\urogue.6"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
19
urogue/verify.c
Normal file
19
urogue/verify.c
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
verify.c - exiting functions
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1995 Herb Chong
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
static char sccsid[] = "%W% %G%";
|
||||
|
||||
#include "rogue.h"
|
||||
|
||||
void verify_function(const char *file, const int line)
|
||||
{
|
||||
char s[80];
|
||||
|
||||
sprintf(s, "Verify failure in %s at line %d\n", file, line);
|
||||
fatal(s);
|
||||
}
|
||||
21
urogue/vers.c
Normal file
21
urogue/vers.c
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
vers.c - version number
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
Based on "Advanced Rogue"
|
||||
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
|
||||
All rights reserved.
|
||||
|
||||
Based on "Rogue: Exploring the Dungeons of Doom"
|
||||
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
const char *save_format = "UltraRogue Portable Save File Release 001\04";
|
||||
const char *version = "UltraRogue 1.06a October 1995";
|
||||
const char *release = "1.06 Alpha (October 1995)";
|
||||
556
urogue/weapons.c
Normal file
556
urogue/weapons.c
Normal file
|
|
@ -0,0 +1,556 @@
|
|||
/*
|
||||
weapons.c - Functions for dealing with problems brought about by weapons
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
Based on "Advanced Rogue"
|
||||
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
|
||||
All rights reserved.
|
||||
|
||||
Based on "Rogue: Exploring the Dungeons of Doom"
|
||||
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
missile()
|
||||
Fire a missile in a given direction
|
||||
*/
|
||||
|
||||
void
|
||||
missile(int ydelta, int xdelta, struct linked_list *item, struct thing *tp)
|
||||
{
|
||||
struct object *obj;
|
||||
struct linked_list *nitem;
|
||||
|
||||
if (item == NULL) /* Get which thing we are hurling */
|
||||
return;
|
||||
|
||||
obj = OBJPTR(item);
|
||||
|
||||
if (!dropcheck(obj) || is_current(obj))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Get rid of the thing. If it is a non-multiple item object, or if
|
||||
* it is the last thing, just drop it. Otherwise, create a new item
|
||||
* with a count of one.
|
||||
*/
|
||||
|
||||
if (obj->o_count < 2)
|
||||
{
|
||||
if (tp->t_pack == pack)
|
||||
rem_pack(obj);
|
||||
else
|
||||
detach(tp->t_pack, item);
|
||||
}
|
||||
else
|
||||
{
|
||||
obj->o_count--;
|
||||
nitem = (struct linked_list *) new_item(sizeof *obj);
|
||||
obj = OBJPTR(nitem);
|
||||
*obj = *(OBJPTR(item));
|
||||
obj->o_count = 1;
|
||||
item = nitem;
|
||||
}
|
||||
|
||||
switch (obj->o_type)
|
||||
{
|
||||
case ARTIFACT:
|
||||
has_artifact &= ~(1 << obj->o_which);
|
||||
break;
|
||||
|
||||
case SCROLL:
|
||||
if (obj->o_which == S_SCARE && obj->o_flags & ISBLESSED)
|
||||
obj->o_flags &= ~ISBLESSED;
|
||||
else
|
||||
obj->o_flags |= ISCURSED;
|
||||
}
|
||||
|
||||
updpack();
|
||||
obj->o_pos = do_motion(obj->o_type, ydelta, xdelta, tp);
|
||||
|
||||
/*
|
||||
* AHA! Here it has hit something. If it is a wall or a door, or if
|
||||
* it misses (combat) the monster, put it on the floor
|
||||
*/
|
||||
|
||||
if (!hit_monster(obj->o_pos.y, obj->o_pos.x, obj, tp))
|
||||
{
|
||||
if (obj->o_type == WEAPON && obj->o_which == GRENADE)
|
||||
{
|
||||
hearmsg("BOOOM!");
|
||||
aggravate();
|
||||
|
||||
if (ntraps + 1 < 2 * MAXTRAPS &&
|
||||
fallpos(obj->o_pos, &traps[ntraps].tr_pos))
|
||||
{
|
||||
mvaddch(traps[ntraps].tr_pos.y, traps[ntraps].tr_pos.x,
|
||||
TRAPDOOR);
|
||||
traps[ntraps].tr_type = TRAPDOOR;
|
||||
traps[ntraps].tr_flags = ISFOUND;
|
||||
traps[ntraps].tr_show = TRAPDOOR;
|
||||
ntraps++;
|
||||
light(&hero);
|
||||
}
|
||||
discard(item);
|
||||
}
|
||||
else if (obj->o_flags & ISLOST)
|
||||
{
|
||||
if (obj->o_type == WEAPON)
|
||||
addmsg("The %s", weaps[obj->o_which].w_name);
|
||||
else
|
||||
addmsg(inv_name(obj, LOWERCASE));
|
||||
|
||||
msg(" vanishes in a puff of greasy smoke.");
|
||||
discard(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
fall(&player, item, TRUE, TRUE);
|
||||
|
||||
if (obj->o_flags & CANRETURN)
|
||||
msg("You have %s.", inv_name(obj, LOWERCASE));
|
||||
}
|
||||
}
|
||||
else if (obj->o_flags & ISOWNED)
|
||||
{
|
||||
add_pack(item, NOMESSAGE);
|
||||
msg("You have %s.", inv_name(obj, LOWERCASE));
|
||||
}
|
||||
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
}
|
||||
|
||||
/*
|
||||
do_motion()
|
||||
do the actual motion on the screen done by an object
|
||||
traveling across the room
|
||||
*/
|
||||
|
||||
coord
|
||||
do_motion(int ob, int ydelta, int xdelta, struct thing *tp)
|
||||
{
|
||||
coord pos;
|
||||
/* Come fly with us ... */
|
||||
|
||||
pos = tp->t_pos;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int ch;
|
||||
|
||||
/* Erase the old one */
|
||||
|
||||
if (!ce(pos, tp->t_pos) &&
|
||||
cansee(pos.y, pos.x) &&
|
||||
mvwinch(cw, pos.y, pos.x) != ' ')
|
||||
{
|
||||
mvwaddch(cw, pos.y, pos.x, show(pos.y, pos.x));
|
||||
}
|
||||
|
||||
/* Get the new position */
|
||||
|
||||
pos.y += ydelta;
|
||||
pos.x += xdelta;
|
||||
|
||||
if (shoot_ok(ch = winat(pos.y, pos.x)) &&
|
||||
ch != DOOR && !ce(pos, hero))
|
||||
{
|
||||
/* It hasn't hit anything yet, so display it if it alright. */
|
||||
|
||||
if (cansee(pos.y, pos.x) &&
|
||||
mvwinch(cw, pos.y, pos.x) != ' ')
|
||||
{
|
||||
mvwaddch(cw, pos.y, pos.x, ob);
|
||||
wrefresh(cw);
|
||||
}
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return(pos);
|
||||
}
|
||||
|
||||
/*
|
||||
fall()
|
||||
Drop an item someplace around here.
|
||||
*/
|
||||
|
||||
void
|
||||
fall(struct thing *tp, struct linked_list *item, int pr, int player_owned)
|
||||
{
|
||||
struct object *obj;
|
||||
struct room *rp;
|
||||
coord fpos;
|
||||
|
||||
obj = OBJPTR(item);
|
||||
rp = roomin(tp->t_pos);
|
||||
|
||||
if (player_owned && obj->o_flags & CANRETURN)
|
||||
{
|
||||
add_pack(item, NOMESSAGE);
|
||||
msg("You have %s.", inv_name(obj, LOWERCASE));
|
||||
return;
|
||||
}
|
||||
else if (fallpos(obj->o_pos, &fpos))
|
||||
{
|
||||
if (obj->o_flags & CANBURN && obj->o_type == WEAPON
|
||||
&& obj->o_which == MOLOTOV
|
||||
&& ntraps + 1 < 2 * MAXTRAPS)
|
||||
{
|
||||
mvaddch(fpos.y, fpos.x, FIRETRAP);
|
||||
traps[ntraps].tr_type = FIRETRAP;
|
||||
traps[ntraps].tr_flags = ISFOUND;
|
||||
traps[ntraps].tr_show = FIRETRAP;
|
||||
traps[ntraps].tr_pos = fpos;
|
||||
ntraps++;
|
||||
|
||||
if (rp != NULL)
|
||||
rp->r_flags &= ~ISDARK;
|
||||
}
|
||||
else
|
||||
{
|
||||
obj->o_pos = fpos;
|
||||
add_obj(item, fpos.y, fpos.x);
|
||||
}
|
||||
|
||||
if (rp != NULL &&
|
||||
(!(rp->r_flags & ISDARK) ||
|
||||
(rp->r_flags & HASFIRE)))
|
||||
{
|
||||
light(&hero);
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* get here only if there isn't a place to put it */
|
||||
|
||||
if (pr)
|
||||
{
|
||||
if (cansee(obj->o_pos.y, obj->o_pos.x))
|
||||
{
|
||||
if (obj->o_type == WEAPON)
|
||||
addmsg("The %s", weaps[obj->o_which].w_name);
|
||||
else
|
||||
addmsg(inv_name(obj, LOWERCASE));
|
||||
|
||||
msg(" vanishes as it hits the ground.");
|
||||
}
|
||||
}
|
||||
discard(item);
|
||||
}
|
||||
|
||||
/*
|
||||
init_weapon()
|
||||
Set up the initial goodies for a weapon
|
||||
*/
|
||||
|
||||
void
|
||||
init_weapon(struct object *weap, int type)
|
||||
{
|
||||
struct init_weps *iwp = &weaps[type];
|
||||
|
||||
weap->o_damage = iwp->w_dam;
|
||||
weap->o_hurldmg = iwp->w_hrl;
|
||||
weap->o_launch = iwp->w_launch;
|
||||
weap->o_flags = iwp->w_flags;
|
||||
weap->o_weight = iwp->w_wght;
|
||||
|
||||
if (weap->o_flags & ISMANY)
|
||||
{
|
||||
weap->o_count = rnd(8) + 8;
|
||||
weap->o_group = ++group;
|
||||
}
|
||||
else
|
||||
weap->o_count = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
hit_monster()
|
||||
does the missile hit the target?
|
||||
*/
|
||||
|
||||
int
|
||||
hit_monster(int y, int x, struct object *weapon, struct thing *thrower)
|
||||
{
|
||||
struct linked_list *mon;
|
||||
coord target;
|
||||
|
||||
target.y = y;
|
||||
target.x = x;
|
||||
|
||||
if (thrower == &player)
|
||||
return(fight(&target, weapon, THROWN));
|
||||
|
||||
if (ce(target, hero))
|
||||
{
|
||||
if (good_monster(*thrower))
|
||||
{
|
||||
if (on(*thrower, ISFAMILIAR))
|
||||
msg("Please get out of the way, Master! I nearly hit you.");
|
||||
else
|
||||
msg("Get out of the way %s!", whoami);
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
return(attack(thrower, weapon, THROWN));
|
||||
}
|
||||
|
||||
if ((mon = find_mons(y, x)) != NULL)
|
||||
return(mon_mon_attack(thrower, mon, weapon, THROWN));
|
||||
else
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
num()
|
||||
Figure out the plus number for armor/weapons
|
||||
*/
|
||||
|
||||
char *
|
||||
num(int n1, int n2, char *buf)
|
||||
{
|
||||
if (buf == NULL)
|
||||
return("UltraRogue Error #104");
|
||||
|
||||
if (n1 == 0 && n2 == 0)
|
||||
{
|
||||
strcpy(buf,"+0");
|
||||
return(buf);
|
||||
}
|
||||
|
||||
if (n2 == 0)
|
||||
sprintf(buf, "%s%d", n1 < 0 ? "" : "+", n1);
|
||||
else
|
||||
sprintf(buf, "%s%d, %s%d", n1 < 0 ? "" : "+",
|
||||
n1, n2 < 0 ? "" : "+", n2);
|
||||
|
||||
return(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
wield()
|
||||
Pull out a certain weapon
|
||||
*/
|
||||
|
||||
void
|
||||
wield(void)
|
||||
{
|
||||
struct linked_list *item;
|
||||
struct object *obj, *oweapon;
|
||||
|
||||
oweapon = cur_weapon;
|
||||
|
||||
if (!dropcheck(cur_weapon))
|
||||
{
|
||||
cur_weapon = oweapon;
|
||||
return;
|
||||
}
|
||||
|
||||
cur_weapon = oweapon;
|
||||
|
||||
if ((item = get_item("wield", WEAPON)) == NULL)
|
||||
{
|
||||
after = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
obj = OBJPTR(item);
|
||||
|
||||
if (is_current(obj))
|
||||
{
|
||||
after = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
wield_ok(&player, obj, TRUE);
|
||||
|
||||
msg("You are now wielding %s.", inv_name(obj, LOWERCASE));
|
||||
|
||||
cur_weapon = obj;
|
||||
}
|
||||
|
||||
/*
|
||||
fallpos()
|
||||
pick a random position around the given (y, x) coordinates
|
||||
*/
|
||||
|
||||
int
|
||||
fallpos(coord pos, coord *newpos) /*ARGSUSED*/
|
||||
{
|
||||
int y, x, cnt;
|
||||
coord places[9];
|
||||
|
||||
cnt = 0;
|
||||
|
||||
/* look for all the places that qualify */
|
||||
|
||||
for (y = pos.y - 1; y <= pos.y + 1; y++)
|
||||
{
|
||||
for (x = pos.x - 1; x <= pos.x + 1; x++)
|
||||
{
|
||||
switch(CCHAR(mvwinch(stdscr,y,x)))
|
||||
{
|
||||
case GOLD:
|
||||
case POTION:
|
||||
case SCROLL:
|
||||
case FOOD:
|
||||
case WEAPON:
|
||||
case ARMOR:
|
||||
case RING:
|
||||
case STICK:
|
||||
case FLOOR:
|
||||
case PASSAGE:
|
||||
case ARTIFACT:
|
||||
places[cnt].y = y;
|
||||
places[cnt].x = x;
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* now, pick one of the places, if there are any */
|
||||
|
||||
if (cnt > 0)
|
||||
{
|
||||
int which = rnd(cnt);
|
||||
|
||||
newpos->y = places[which].y;
|
||||
newpos->x = places[which].x;
|
||||
|
||||
debug("Dropping object at %d, %d", newpos->y, newpos->x);
|
||||
}
|
||||
|
||||
return(cnt);
|
||||
}
|
||||
|
||||
/*
|
||||
wield_ok()
|
||||
enforce player class weapons restrictions
|
||||
*/
|
||||
|
||||
int
|
||||
wield_ok(struct thing *wieldee, struct object *obj, int print_message)
|
||||
{
|
||||
int ret_val = TRUE;
|
||||
int class_type = wieldee->t_ctype;
|
||||
|
||||
if (obj->o_type != WEAPON)
|
||||
{
|
||||
ret_val = FALSE;
|
||||
return(ret_val);
|
||||
}
|
||||
else
|
||||
switch (class_type)
|
||||
{
|
||||
case C_MAGICIAN: /* need one hand free */
|
||||
case C_ILLUSION:
|
||||
if (obj->o_flags & ISTWOH)
|
||||
ret_val = FALSE;
|
||||
break;
|
||||
|
||||
case C_THIEF: /* need portable weapon */
|
||||
case C_ASSASIN:
|
||||
case C_NINJA:
|
||||
if (obj->o_flags & ISTWOH)
|
||||
ret_val = FALSE;
|
||||
break;
|
||||
|
||||
case C_CLERIC: /* No sharp weapons */
|
||||
if (obj->o_flags & ISSHARP)
|
||||
ret_val = FALSE;
|
||||
break;
|
||||
|
||||
case C_DRUID: /* No non-silver metal weapons */
|
||||
if (obj->o_flags & ISMETAL && !(obj->o_flags & ISSILVER))
|
||||
ret_val = FALSE;
|
||||
break;
|
||||
|
||||
case C_PALADIN: /* must wield sharp stuff */
|
||||
if ((obj->o_flags & ISSHARP) == FALSE)
|
||||
ret_val = FALSE;
|
||||
break;
|
||||
|
||||
case C_FIGHTER: /* wield anything */
|
||||
case C_RANGER:
|
||||
case C_MONSTER:
|
||||
break;
|
||||
|
||||
default: /* Unknown class */
|
||||
debug("Unknown class %d.", class_type);
|
||||
break;
|
||||
}
|
||||
|
||||
if (itemweight(obj) > 18 * pstats.s_str)
|
||||
{
|
||||
if (wieldee == &player && print_message == TRUE)
|
||||
msg("That is too heavy for you to swing effectively!");
|
||||
|
||||
ret_val = FALSE;
|
||||
return(ret_val);
|
||||
}
|
||||
|
||||
if (ret_val == FALSE && print_message == MESSAGE)
|
||||
switch (class_type)
|
||||
{
|
||||
case C_MAGICIAN:
|
||||
case C_ILLUSION:
|
||||
msg("You'll find it hard to cast spells while wielding that!");
|
||||
break;
|
||||
|
||||
case C_THIEF:
|
||||
case C_ASSASIN:
|
||||
case C_NINJA:
|
||||
msg("Don't expect to backstab anyone while wielding that!");
|
||||
break;
|
||||
|
||||
case C_CLERIC:
|
||||
case C_DRUID:
|
||||
case C_PALADIN:
|
||||
msg("Your god strongly disapproves of your wielding that!");
|
||||
break;
|
||||
|
||||
case C_FIGHTER:
|
||||
case C_RANGER:
|
||||
case C_MONSTER:
|
||||
break;
|
||||
}
|
||||
|
||||
return(ret_val);
|
||||
}
|
||||
|
||||
/*
|
||||
shoot_ok()
|
||||
returns true if it is ok for type to shoot over ch
|
||||
*/
|
||||
|
||||
int
|
||||
shoot_ok(int ch)
|
||||
{
|
||||
switch(ch)
|
||||
{
|
||||
case ' ':
|
||||
case '|':
|
||||
case '-':
|
||||
case SECRETDOOR:
|
||||
return(FALSE);
|
||||
|
||||
default:
|
||||
return(!isalpha(ch));
|
||||
}
|
||||
}
|
||||
238
urogue/wizard.c
Normal file
238
urogue/wizard.c
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
wizard.c - Special wizard commands
|
||||
|
||||
UltraRogue: The Ultimate Adventure in the Dungeons of Doom
|
||||
Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
|
||||
All rights reserved.
|
||||
|
||||
Based on "Advanced Rogue"
|
||||
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
|
||||
All rights reserved.
|
||||
|
||||
Based on "Rogue: Exploring the Dungeons of Doom"
|
||||
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
All rights reserved.
|
||||
|
||||
See the file LICENSE.TXT for full copyright and licensing information.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
whatis()
|
||||
What a certain object is
|
||||
*/
|
||||
|
||||
void
|
||||
whatis(struct linked_list *what)
|
||||
{
|
||||
struct object *obj;
|
||||
int kludge;
|
||||
int print_message = FALSE;
|
||||
|
||||
if (what == NULL)
|
||||
{
|
||||
print_message = TRUE;
|
||||
|
||||
while ((what = get_item("identify", 0)) == NULL)
|
||||
;
|
||||
}
|
||||
|
||||
obj = OBJPTR(what);
|
||||
obj->o_flags |= ISKNOW;
|
||||
|
||||
switch (obj->o_type)
|
||||
{
|
||||
case SCROLL: kludge = TYP_SCROLL; break;
|
||||
case POTION: kludge = TYP_POTION; break;
|
||||
case STICK: kludge = TYP_STICK; break;
|
||||
case RING: kludge = TYP_RING; break;
|
||||
case WEAPON:
|
||||
case ARMOR:
|
||||
default: kludge = -1; break;
|
||||
}
|
||||
|
||||
if (kludge != -1)
|
||||
{
|
||||
know_items[kludge][obj->o_which] = TRUE;
|
||||
|
||||
if (guess_items[kludge][obj->o_which])
|
||||
{
|
||||
ur_free(guess_items[kludge][obj->o_which]);
|
||||
guess_items[kludge][obj->o_which] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (print_message)
|
||||
msg(inv_name(obj, UPPERCASE));
|
||||
}
|
||||
|
||||
/*
|
||||
teleport()
|
||||
Bamf the hero someplace else
|
||||
*/
|
||||
|
||||
void
|
||||
teleport(void)
|
||||
{
|
||||
struct room *new_rp = NULL, *old_rp = roomin(hero);
|
||||
|
||||
int rm, which;
|
||||
coord c;
|
||||
int is_lit = FALSE; /* For saving room light state */
|
||||
int rand_position = TRUE;
|
||||
|
||||
c = hero;
|
||||
|
||||
mvwaddch(cw, hero.y, hero.x, mvwinch(stdscr, hero.y, hero.x));
|
||||
|
||||
if (is_wearing(R_TELCONTROL))
|
||||
{
|
||||
msg("Where do you wish to teleport to? (* for help)");
|
||||
wmove(cw, hero.y, hero.x);
|
||||
wrefresh(cw);
|
||||
|
||||
which = (short) (readchar() & 0177);
|
||||
|
||||
while (which != (short) ESCAPE && which != (short) LINEFEED
|
||||
&& which != (short) CARRIAGE_RETURN)
|
||||
{
|
||||
switch(which)
|
||||
{
|
||||
case 'h': c.x--; break;
|
||||
case 'j': c.y++; break;
|
||||
case 'k': c.y--; break;
|
||||
case 'l': c.x++; break;
|
||||
case 'y': c.x--;
|
||||
c.y--; break;
|
||||
case 'u': c.x++;
|
||||
c.y--; break;
|
||||
case 'b': c.x--;
|
||||
c.y++; break;
|
||||
case 'n': c.x++;
|
||||
c.y++; break;
|
||||
case '*':
|
||||
msg("Use h,j,k,l,y,u,b,n to position cursor, then hit"
|
||||
"return.");
|
||||
}
|
||||
|
||||
c.y = max(c.y, 1);
|
||||
c.y = min(c.y, LINES - 3);
|
||||
c.x = max(c.x, 1);
|
||||
c.x = min(c.x, COLS - 1);
|
||||
wmove(cw, c.y, c.x);
|
||||
wrefresh(cw);
|
||||
which = (short) (readchar() & 0177);
|
||||
}
|
||||
|
||||
which = winat(c.y, c.x);
|
||||
|
||||
if ((which == FLOOR || which == PASSAGE || which == DOOR) &&
|
||||
((ring_value(R_TELCONTROL) == 0 && rnd(10) < 6)
|
||||
|| (ring_value(R_TELCONTROL) > 0 && rnd(10) < 9)))
|
||||
{
|
||||
rand_position = FALSE;
|
||||
msg("You attempt succeeds.");
|
||||
hero = c;
|
||||
new_rp = roomin(hero);
|
||||
}
|
||||
else
|
||||
msg("Your attempt fails.");
|
||||
}
|
||||
|
||||
if (rand_position)
|
||||
{
|
||||
do
|
||||
{
|
||||
rm = rnd_room();
|
||||
rnd_pos(&rooms[rm], &hero);
|
||||
}
|
||||
while (winat(hero.y, hero.x) != FLOOR);
|
||||
|
||||
new_rp = &rooms[rm];
|
||||
}
|
||||
|
||||
/* If hero gets moved, darken old room */
|
||||
|
||||
if (old_rp && old_rp != new_rp)
|
||||
{
|
||||
if (!(old_rp->r_flags & ISDARK))
|
||||
is_lit = TRUE;
|
||||
|
||||
old_rp->r_flags |= ISDARK; /* Fake darkness */
|
||||
light(&c);
|
||||
|
||||
if (is_lit)
|
||||
old_rp->r_flags &= ~ISDARK; /* Restore light state */
|
||||
}
|
||||
|
||||
light(&hero);
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
|
||||
/* turn off ISHELD in case teleportation was done while fighting */
|
||||
|
||||
if (on(player, ISHELD))
|
||||
{
|
||||
struct linked_list *ip, *nip;
|
||||
struct thing *mp;
|
||||
|
||||
turn_off(player, ISHELD);
|
||||
hold_count = 0;
|
||||
|
||||
for (ip = mlist; ip; ip = nip)
|
||||
{
|
||||
mp = THINGPTR(ip);
|
||||
nip = next(ip);
|
||||
|
||||
if (on(*mp, DIDHOLD))
|
||||
{
|
||||
turn_off(*mp, DIDHOLD);
|
||||
turn_on(*mp, CANHOLD);
|
||||
}
|
||||
|
||||
turn_off(*mp, DIDSUFFOCATE);
|
||||
}
|
||||
}
|
||||
|
||||
extinguish_fuse(FUSE_SUFFOCATE);
|
||||
player.t_no_move = 0; /* not trapped anymore */
|
||||
count = 0;
|
||||
running = FALSE;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
passwd()
|
||||
see if user knows password
|
||||
*/
|
||||
|
||||
int
|
||||
passwd(void)
|
||||
{
|
||||
char *sp, c;
|
||||
char buf[2 * LINELEN];
|
||||
|
||||
msg("Wizard's Password:");
|
||||
mpos = 0;
|
||||
sp = buf;
|
||||
|
||||
while ((c = (readchar() & 0177)) != '\n' && c != '\r' && c != '\033')
|
||||
{
|
||||
if (c == '\0')
|
||||
sp = buf;
|
||||
else if (c == '\b' && sp > buf)
|
||||
sp--;
|
||||
else
|
||||
*sp++ = c;
|
||||
}
|
||||
|
||||
if (sp == buf)
|
||||
return(FALSE);
|
||||
|
||||
*sp = '\0';
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
685
urogue/xcrypt.c
Normal file
685
urogue/xcrypt.c
Normal file
|
|
@ -0,0 +1,685 @@
|
|||
/*
|
||||
* FreeSec: libcrypt
|
||||
*
|
||||
* Copyright (C) 1994 David Burren
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name(s) of the author(s) nor the names of other contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* This is an original implementation of the DES and the crypt(3) interfaces
|
||||
* by David Burren <davidb@werj.com.au>.
|
||||
*
|
||||
* An excellent reference on the underlying algorithm (and related
|
||||
* algorithms) is:
|
||||
*
|
||||
* B. Schneier, Applied Cryptography: protocols, algorithms,
|
||||
* and source code in C, John Wiley & Sons, 1994.
|
||||
*
|
||||
* Note that in that book's description of DES the lookups for the initial,
|
||||
* pbox, and final permutations are inverted (this has been brought to the
|
||||
* attention of the author). A list of errata for this book has been
|
||||
* posted to the sci.crypt newsgroup by the author and is available for FTP.
|
||||
*
|
||||
* NOTE:
|
||||
* This file has a static version of des_setkey() so that crypt.o exports
|
||||
* only the crypt() interface. This is required to make binaries linked
|
||||
* against crypt.o exportable or re-exportable from the USA.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
|
||||
extern unsigned long int md_ntohl(unsigned long int x);
|
||||
extern unsigned long int md_htonl(unsigned long int x);
|
||||
|
||||
#define _PASSWORD_EFMT1 '_'
|
||||
|
||||
static unsigned char IP[64] = {
|
||||
58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
|
||||
62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
|
||||
57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
|
||||
61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7
|
||||
};
|
||||
|
||||
static unsigned char inv_key_perm[64];
|
||||
static unsigned char key_perm[56] = {
|
||||
57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18,
|
||||
10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36,
|
||||
63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22,
|
||||
14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4
|
||||
};
|
||||
|
||||
static unsigned char key_shifts[16] = {
|
||||
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
|
||||
};
|
||||
|
||||
static unsigned char inv_comp_perm[56];
|
||||
static unsigned char comp_perm[48] = {
|
||||
14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10,
|
||||
23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2,
|
||||
41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
|
||||
44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
|
||||
};
|
||||
|
||||
/*
|
||||
* No E box is used, as it's replaced by some ANDs, shifts, and ORs.
|
||||
*/
|
||||
|
||||
static unsigned char u_sbox[8][64];
|
||||
static unsigned char sbox[8][64] = {
|
||||
{
|
||||
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
|
||||
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
|
||||
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
|
||||
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
|
||||
},
|
||||
{
|
||||
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
|
||||
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
|
||||
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
|
||||
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
|
||||
},
|
||||
{
|
||||
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
|
||||
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
|
||||
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
|
||||
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
|
||||
},
|
||||
{
|
||||
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
|
||||
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
|
||||
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
|
||||
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
|
||||
},
|
||||
{
|
||||
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
|
||||
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
|
||||
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
|
||||
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
|
||||
},
|
||||
{
|
||||
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
|
||||
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
|
||||
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
|
||||
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
|
||||
},
|
||||
{
|
||||
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
|
||||
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
|
||||
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
|
||||
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
|
||||
},
|
||||
{
|
||||
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
|
||||
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
|
||||
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
|
||||
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
|
||||
}
|
||||
};
|
||||
|
||||
static unsigned char un_pbox[32];
|
||||
static unsigned char pbox[32] = {
|
||||
16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,
|
||||
2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25
|
||||
};
|
||||
|
||||
static unsigned int bits32[32] =
|
||||
{
|
||||
0x80000000, 0x40000000, 0x20000000, 0x10000000,
|
||||
0x08000000, 0x04000000, 0x02000000, 0x01000000,
|
||||
0x00800000, 0x00400000, 0x00200000, 0x00100000,
|
||||
0x00080000, 0x00040000, 0x00020000, 0x00010000,
|
||||
0x00008000, 0x00004000, 0x00002000, 0x00001000,
|
||||
0x00000800, 0x00000400, 0x00000200, 0x00000100,
|
||||
0x00000080, 0x00000040, 0x00000020, 0x00000010,
|
||||
0x00000008, 0x00000004, 0x00000002, 0x00000001
|
||||
};
|
||||
|
||||
static unsigned char bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
|
||||
|
||||
static unsigned int saltbits;
|
||||
static int old_salt;
|
||||
static unsigned int *bits28, *bits24;
|
||||
static unsigned char init_perm[64], final_perm[64];
|
||||
static unsigned int en_keysl[16], en_keysr[16];
|
||||
static unsigned int de_keysl[16], de_keysr[16];
|
||||
static int des_initialised = 0;
|
||||
static unsigned char m_sbox[4][4096];
|
||||
static unsigned int psbox[4][256];
|
||||
static unsigned int ip_maskl[8][256], ip_maskr[8][256];
|
||||
static unsigned int fp_maskl[8][256], fp_maskr[8][256];
|
||||
static unsigned int key_perm_maskl[8][128], key_perm_maskr[8][128];
|
||||
static unsigned int comp_maskl[8][128], comp_maskr[8][128];
|
||||
static unsigned int old_rawkey0, old_rawkey1;
|
||||
|
||||
static unsigned char ascii64[] =
|
||||
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
/* 0000000000111111111122222222223333333333444444444455555555556666 */
|
||||
/* 0123456789012345678901234567890123456789012345678901234567890123 */
|
||||
|
||||
static __inline int
|
||||
ascii_to_bin(char ch)
|
||||
{
|
||||
if (ch > 'z')
|
||||
return(0);
|
||||
if (ch >= 'a')
|
||||
return(ch - 'a' + 38);
|
||||
if (ch > 'Z')
|
||||
return(0);
|
||||
if (ch >= 'A')
|
||||
return(ch - 'A' + 12);
|
||||
if (ch > '9')
|
||||
return(0);
|
||||
if (ch >= '.')
|
||||
return(ch - '.');
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void
|
||||
des_init()
|
||||
{
|
||||
int j, b, k, inbit, obit;
|
||||
unsigned int *p, *il, *ir, *fl, *fr;
|
||||
unsigned char i;
|
||||
|
||||
old_rawkey0 = old_rawkey1 = 0;
|
||||
saltbits = 0;
|
||||
old_salt = 0;
|
||||
bits24 = (bits28 = bits32 + 4) + 4;
|
||||
|
||||
/*
|
||||
* Invert the S-boxes, reordering the input bits.
|
||||
*/
|
||||
for (i = 0; i < 8; i++)
|
||||
for (j = 0; j < 64; j++) {
|
||||
b = (j & 0x20) | ((j & 1) << 4) | ((j >> 1) & 0xf);
|
||||
u_sbox[i][j] = sbox[i][b];
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the inverted S-boxes into 4 arrays of 8 bits.
|
||||
* Each will handle 12 bits of the S-box input.
|
||||
*/
|
||||
for (b = 0; b < 4; b++)
|
||||
for (i = 0; i < 64; i++)
|
||||
for (j = 0; j < 64; j++)
|
||||
m_sbox[b][(i << 6) | j] =
|
||||
(u_sbox[(b << 1)][i] << 4) |
|
||||
u_sbox[(b << 1) + 1][j];
|
||||
|
||||
/*
|
||||
* Set up the initial & final permutations into a useful form, and
|
||||
* initialise the inverted key permutation.
|
||||
*/
|
||||
for (i = 0; i < 64; i++) {
|
||||
init_perm[final_perm[i] = IP[i] - 1] = i;
|
||||
inv_key_perm[i] = 255;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invert the key permutation and initialise the inverted key
|
||||
* compression permutation.
|
||||
*/
|
||||
for (i = 0; i < 56; i++) {
|
||||
inv_key_perm[key_perm[i] - 1] = i;
|
||||
inv_comp_perm[i] = 255;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invert the key compression permutation.
|
||||
*/
|
||||
for (i = 0; i < 48; i++) {
|
||||
inv_comp_perm[comp_perm[i] - 1] = i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the OR-mask arrays for the initial and final permutations,
|
||||
* and for the key initial and compression permutations.
|
||||
*/
|
||||
for (k = 0; k < 8; k++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
*(il = &ip_maskl[k][i]) = 0;
|
||||
*(ir = &ip_maskr[k][i]) = 0;
|
||||
*(fl = &fp_maskl[k][i]) = 0;
|
||||
*(fr = &fp_maskr[k][i]) = 0;
|
||||
for (j = 0; j < 8; j++) {
|
||||
inbit = 8 * k + j;
|
||||
if (i & bits8[j]) {
|
||||
if ((obit = init_perm[inbit]) < 32)
|
||||
*il |= bits32[obit];
|
||||
else
|
||||
*ir |= bits32[obit-32];
|
||||
if ((obit = final_perm[inbit]) < 32)
|
||||
*fl |= bits32[obit];
|
||||
else
|
||||
*fr |= bits32[obit - 32];
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 128; i++) {
|
||||
*(il = &key_perm_maskl[k][i]) = 0;
|
||||
*(ir = &key_perm_maskr[k][i]) = 0;
|
||||
for (j = 0; j < 7; j++) {
|
||||
inbit = 8 * k + j;
|
||||
if (i & bits8[j + 1]) {
|
||||
if ((obit = inv_key_perm[inbit]) == 255)
|
||||
continue;
|
||||
if (obit < 28)
|
||||
*il |= bits28[obit];
|
||||
else
|
||||
*ir |= bits28[obit - 28];
|
||||
}
|
||||
}
|
||||
*(il = &comp_maskl[k][i]) = 0;
|
||||
*(ir = &comp_maskr[k][i]) = 0;
|
||||
for (j = 0; j < 7; j++) {
|
||||
inbit = 7 * k + j;
|
||||
if (i & bits8[j + 1]) {
|
||||
if ((obit=inv_comp_perm[inbit]) == 255)
|
||||
continue;
|
||||
if (obit < 24)
|
||||
*il |= bits24[obit];
|
||||
else
|
||||
*ir |= bits24[obit - 24];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Invert the P-box permutation, and convert into OR-masks for
|
||||
* handling the output of the S-box arrays setup above.
|
||||
*/
|
||||
for (i = 0; i < 32; i++)
|
||||
un_pbox[pbox[i] - 1] = i;
|
||||
|
||||
for (b = 0; b < 4; b++)
|
||||
for (i = 0; i < 256; i++) {
|
||||
*(p = &psbox[b][i]) = 0;
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (i & bits8[j])
|
||||
*p |= bits32[un_pbox[8 * b + j]];
|
||||
}
|
||||
}
|
||||
|
||||
des_initialised = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
setup_salt(int salt)
|
||||
{
|
||||
unsigned int obit, saltbit;
|
||||
int i;
|
||||
|
||||
if (salt == old_salt)
|
||||
return;
|
||||
old_salt = salt;
|
||||
|
||||
saltbits = 0;
|
||||
saltbit = 1;
|
||||
obit = 0x800000;
|
||||
for (i = 0; i < 24; i++) {
|
||||
if (salt & saltbit)
|
||||
saltbits |= obit;
|
||||
saltbit <<= 1;
|
||||
obit >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
des_setkey(const unsigned char *key)
|
||||
{
|
||||
unsigned int k0, k1, rawkey0, rawkey1;
|
||||
int shifts, round;
|
||||
|
||||
if (!des_initialised)
|
||||
des_init();
|
||||
|
||||
rawkey0 = md_ntohl(*(unsigned int *) key);
|
||||
rawkey1 = md_ntohl(*(unsigned int *) (key + 4));
|
||||
|
||||
if ((rawkey0 | rawkey1)
|
||||
&& rawkey0 == old_rawkey0
|
||||
&& rawkey1 == old_rawkey1) {
|
||||
/*
|
||||
* Already setup for this key.
|
||||
* This optimisation fails on a zero key (which is weak and
|
||||
* has bad parity anyway) in order to simplify the starting
|
||||
* conditions.
|
||||
*/
|
||||
return(0);
|
||||
}
|
||||
old_rawkey0 = rawkey0;
|
||||
old_rawkey1 = rawkey1;
|
||||
|
||||
/*
|
||||
* Do key permutation and split into two 28-bit subkeys.
|
||||
*/
|
||||
k0 = key_perm_maskl[0][rawkey0 >> 25]
|
||||
| key_perm_maskl[1][(rawkey0 >> 17) & 0x7f]
|
||||
| key_perm_maskl[2][(rawkey0 >> 9) & 0x7f]
|
||||
| key_perm_maskl[3][(rawkey0 >> 1) & 0x7f]
|
||||
| key_perm_maskl[4][rawkey1 >> 25]
|
||||
| key_perm_maskl[5][(rawkey1 >> 17) & 0x7f]
|
||||
| key_perm_maskl[6][(rawkey1 >> 9) & 0x7f]
|
||||
| key_perm_maskl[7][(rawkey1 >> 1) & 0x7f];
|
||||
k1 = key_perm_maskr[0][rawkey0 >> 25]
|
||||
| key_perm_maskr[1][(rawkey0 >> 17) & 0x7f]
|
||||
| key_perm_maskr[2][(rawkey0 >> 9) & 0x7f]
|
||||
| key_perm_maskr[3][(rawkey0 >> 1) & 0x7f]
|
||||
| key_perm_maskr[4][rawkey1 >> 25]
|
||||
| key_perm_maskr[5][(rawkey1 >> 17) & 0x7f]
|
||||
| key_perm_maskr[6][(rawkey1 >> 9) & 0x7f]
|
||||
| key_perm_maskr[7][(rawkey1 >> 1) & 0x7f];
|
||||
/*
|
||||
* Rotate subkeys and do compression permutation.
|
||||
*/
|
||||
shifts = 0;
|
||||
for (round = 0; round < 16; round++) {
|
||||
unsigned int t0, t1;
|
||||
|
||||
shifts += key_shifts[round];
|
||||
|
||||
t0 = (k0 << shifts) | (k0 >> (28 - shifts));
|
||||
t1 = (k1 << shifts) | (k1 >> (28 - shifts));
|
||||
|
||||
de_keysl[15 - round] =
|
||||
en_keysl[round] = comp_maskl[0][(t0 >> 21) & 0x7f]
|
||||
| comp_maskl[1][(t0 >> 14) & 0x7f]
|
||||
| comp_maskl[2][(t0 >> 7) & 0x7f]
|
||||
| comp_maskl[3][t0 & 0x7f]
|
||||
| comp_maskl[4][(t1 >> 21) & 0x7f]
|
||||
| comp_maskl[5][(t1 >> 14) & 0x7f]
|
||||
| comp_maskl[6][(t1 >> 7) & 0x7f]
|
||||
| comp_maskl[7][t1 & 0x7f];
|
||||
|
||||
de_keysr[15 - round] =
|
||||
en_keysr[round] = comp_maskr[0][(t0 >> 21) & 0x7f]
|
||||
| comp_maskr[1][(t0 >> 14) & 0x7f]
|
||||
| comp_maskr[2][(t0 >> 7) & 0x7f]
|
||||
| comp_maskr[3][t0 & 0x7f]
|
||||
| comp_maskr[4][(t1 >> 21) & 0x7f]
|
||||
| comp_maskr[5][(t1 >> 14) & 0x7f]
|
||||
| comp_maskr[6][(t1 >> 7) & 0x7f]
|
||||
| comp_maskr[7][t1 & 0x7f];
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
do_des(unsigned int l_in, unsigned int r_in, unsigned int *l_out,
|
||||
unsigned int *r_out, int count)
|
||||
{
|
||||
/*
|
||||
* l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format.
|
||||
*/
|
||||
unsigned int l, r, *kl, *kr, *kl1, *kr1;
|
||||
unsigned int f = 0, r48l, r48r;
|
||||
int round;
|
||||
|
||||
if (count == 0) {
|
||||
return(1);
|
||||
} else if (count > 0) {
|
||||
/*
|
||||
* Encrypting
|
||||
*/
|
||||
kl1 = en_keysl;
|
||||
kr1 = en_keysr;
|
||||
} else {
|
||||
/*
|
||||
* Decrypting
|
||||
*/
|
||||
count = -count;
|
||||
kl1 = de_keysl;
|
||||
kr1 = de_keysr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do initial permutation (IP).
|
||||
*/
|
||||
l = ip_maskl[0][l_in >> 24]
|
||||
| ip_maskl[1][(l_in >> 16) & 0xff]
|
||||
| ip_maskl[2][(l_in >> 8) & 0xff]
|
||||
| ip_maskl[3][l_in & 0xff]
|
||||
| ip_maskl[4][r_in >> 24]
|
||||
| ip_maskl[5][(r_in >> 16) & 0xff]
|
||||
| ip_maskl[6][(r_in >> 8) & 0xff]
|
||||
| ip_maskl[7][r_in & 0xff];
|
||||
r = ip_maskr[0][l_in >> 24]
|
||||
| ip_maskr[1][(l_in >> 16) & 0xff]
|
||||
| ip_maskr[2][(l_in >> 8) & 0xff]
|
||||
| ip_maskr[3][l_in & 0xff]
|
||||
| ip_maskr[4][r_in >> 24]
|
||||
| ip_maskr[5][(r_in >> 16) & 0xff]
|
||||
| ip_maskr[6][(r_in >> 8) & 0xff]
|
||||
| ip_maskr[7][r_in & 0xff];
|
||||
|
||||
while (count--) {
|
||||
/*
|
||||
* Do each round.
|
||||
*/
|
||||
kl = kl1;
|
||||
kr = kr1;
|
||||
round = 16;
|
||||
while (round--) {
|
||||
/*
|
||||
* Expand R to 48 bits (simulate the E-box).
|
||||
*/
|
||||
r48l = ((r & 0x00000001) << 23)
|
||||
| ((r & 0xf8000000) >> 9)
|
||||
| ((r & 0x1f800000) >> 11)
|
||||
| ((r & 0x01f80000) >> 13)
|
||||
| ((r & 0x001f8000) >> 15);
|
||||
|
||||
r48r = ((r & 0x0001f800) << 7)
|
||||
| ((r & 0x00001f80) << 5)
|
||||
| ((r & 0x000001f8) << 3)
|
||||
| ((r & 0x0000001f) << 1)
|
||||
| ((r & 0x80000000) >> 31);
|
||||
/*
|
||||
* Do salting for crypt() and friends, and
|
||||
* XOR with the permuted key.
|
||||
*/
|
||||
f = (r48l ^ r48r) & saltbits;
|
||||
r48l ^= f ^ *kl++;
|
||||
r48r ^= f ^ *kr++;
|
||||
/*
|
||||
* Do sbox lookups (which shrink it back to 32 bits)
|
||||
* and do the pbox permutation at the same time.
|
||||
*/
|
||||
f = psbox[0][m_sbox[0][r48l >> 12]]
|
||||
| psbox[1][m_sbox[1][r48l & 0xfff]]
|
||||
| psbox[2][m_sbox[2][r48r >> 12]]
|
||||
| psbox[3][m_sbox[3][r48r & 0xfff]];
|
||||
/*
|
||||
* Now that we've permuted things, complete f().
|
||||
*/
|
||||
f ^= l;
|
||||
l = r;
|
||||
r = f;
|
||||
}
|
||||
r = l;
|
||||
l = f;
|
||||
}
|
||||
/*
|
||||
* Do final permutation (inverse of IP).
|
||||
*/
|
||||
*l_out = fp_maskl[0][l >> 24]
|
||||
| fp_maskl[1][(l >> 16) & 0xff]
|
||||
| fp_maskl[2][(l >> 8) & 0xff]
|
||||
| fp_maskl[3][l & 0xff]
|
||||
| fp_maskl[4][r >> 24]
|
||||
| fp_maskl[5][(r >> 16) & 0xff]
|
||||
| fp_maskl[6][(r >> 8) & 0xff]
|
||||
| fp_maskl[7][r & 0xff];
|
||||
*r_out = fp_maskr[0][l >> 24]
|
||||
| fp_maskr[1][(l >> 16) & 0xff]
|
||||
| fp_maskr[2][(l >> 8) & 0xff]
|
||||
| fp_maskr[3][l & 0xff]
|
||||
| fp_maskr[4][r >> 24]
|
||||
| fp_maskr[5][(r >> 16) & 0xff]
|
||||
| fp_maskr[6][(r >> 8) & 0xff]
|
||||
| fp_maskr[7][r & 0xff];
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
des_cipher(const unsigned char *in, unsigned char *out, int salt, int count)
|
||||
{
|
||||
unsigned int l_out, r_out, rawl, rawr;
|
||||
unsigned int x[2];
|
||||
int retval;
|
||||
|
||||
if (!des_initialised)
|
||||
des_init();
|
||||
|
||||
setup_salt(salt);
|
||||
|
||||
memcpy(x, in, sizeof x);
|
||||
rawl = md_ntohl(x[0]);
|
||||
rawr = md_ntohl(x[1]);
|
||||
retval = do_des(rawl, rawr, &l_out, &r_out, count);
|
||||
|
||||
x[0] = md_htonl(l_out);
|
||||
x[1] = md_htonl(r_out);
|
||||
memcpy(out, x, sizeof x);
|
||||
return(retval);
|
||||
}
|
||||
|
||||
char *
|
||||
xcrypt(const char *key, const char *setting)
|
||||
{
|
||||
int i;
|
||||
unsigned int count, salt, l, r0, r1, keybuf[2];
|
||||
unsigned char *p, *q;
|
||||
static unsigned char output[21];
|
||||
|
||||
if (!des_initialised)
|
||||
des_init();
|
||||
|
||||
/*
|
||||
* Copy the key, shifting each character up by one bit
|
||||
* and padding with zeros.
|
||||
*/
|
||||
q = (unsigned char *) keybuf;
|
||||
while ((q - (unsigned char *) keybuf) < sizeof(keybuf)) {
|
||||
if ((*q++ = *key << 1))
|
||||
key++;
|
||||
}
|
||||
if (des_setkey((unsigned char *) keybuf))
|
||||
return(NULL);
|
||||
|
||||
if (*setting == _PASSWORD_EFMT1) {
|
||||
/*
|
||||
* "new"-style:
|
||||
* setting - underscore, 4 bytes of count, 4 bytes of salt
|
||||
* key - unlimited characters
|
||||
*/
|
||||
for (i = 1, count = 0; i < 5; i++)
|
||||
count |= ascii_to_bin(setting[i]) << (i - 1) * 6;
|
||||
|
||||
for (i = 5, salt = 0; i < 9; i++)
|
||||
salt |= ascii_to_bin(setting[i]) << (i - 5) * 6;
|
||||
|
||||
while (*key) {
|
||||
/*
|
||||
* Encrypt the key with itself.
|
||||
*/
|
||||
if (des_cipher((unsigned char*)keybuf, (unsigned char*)keybuf, 0, 1))
|
||||
return(NULL);
|
||||
/*
|
||||
* And XOR with the next 8 characters of the key.
|
||||
*/
|
||||
q = (unsigned char *) keybuf;
|
||||
while (((q - (unsigned char *) keybuf) < sizeof(keybuf)) &&
|
||||
*key)
|
||||
*q++ ^= *key++ << 1;
|
||||
|
||||
if (des_setkey((unsigned char *) keybuf))
|
||||
return(NULL);
|
||||
}
|
||||
strncpy((char *)output, setting, 9);
|
||||
|
||||
/*
|
||||
* Double check that we weren't given a short setting.
|
||||
* If we were, the above code will probably have created
|
||||
* wierd values for count and salt, but we don't really care.
|
||||
* Just make sure the output string doesn't have an extra
|
||||
* NUL in it.
|
||||
*/
|
||||
output[9] = '\0';
|
||||
p = output + strlen((const char *)output);
|
||||
} else {
|
||||
/*
|
||||
* "old"-style:
|
||||
* setting - 2 bytes of salt
|
||||
* key - up to 8 characters
|
||||
*/
|
||||
count = 25;
|
||||
|
||||
salt = (ascii_to_bin(setting[1]) << 6)
|
||||
| ascii_to_bin(setting[0]);
|
||||
|
||||
output[0] = setting[0];
|
||||
/*
|
||||
* If the encrypted password that the salt was extracted from
|
||||
* is only 1 character long, the salt will be corrupted. We
|
||||
* need to ensure that the output string doesn't have an extra
|
||||
* NUL in it!
|
||||
*/
|
||||
output[1] = setting[1] ? setting[1] : output[0];
|
||||
|
||||
p = output + 2;
|
||||
}
|
||||
setup_salt(salt);
|
||||
/*
|
||||
* Do it.
|
||||
*/
|
||||
if (do_des(0, 0, &r0, &r1, count))
|
||||
return(NULL);
|
||||
/*
|
||||
* Now encode the result...
|
||||
*/
|
||||
l = (r0 >> 8);
|
||||
*p++ = ascii64[(l >> 18) & 0x3f];
|
||||
*p++ = ascii64[(l >> 12) & 0x3f];
|
||||
*p++ = ascii64[(l >> 6) & 0x3f];
|
||||
*p++ = ascii64[l & 0x3f];
|
||||
|
||||
l = (r0 << 16) | ((r1 >> 16) & 0xffff);
|
||||
*p++ = ascii64[(l >> 18) & 0x3f];
|
||||
*p++ = ascii64[(l >> 12) & 0x3f];
|
||||
*p++ = ascii64[(l >> 6) & 0x3f];
|
||||
*p++ = ascii64[l & 0x3f];
|
||||
|
||||
l = r1 << 2;
|
||||
*p++ = ascii64[(l >> 12) & 0x3f];
|
||||
*p++ = ascii64[(l >> 6) & 0x3f];
|
||||
*p++ = ascii64[l & 0x3f];
|
||||
*p = 0;
|
||||
|
||||
return((char *)output);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue