Import Advanced Rogue 7.7 from the Roguelike Restoration Project (r1490)
This commit is contained in:
parent
6af92da76a
commit
cf121ade21
51 changed files with 37593 additions and 0 deletions
179
arogue7/LICENSE.TXT
Normal file
179
arogue7/LICENSE.TXT
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
Portions Copyright (C) 1984 Robert D. Kindelberger
|
||||
Portions Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
Portions Copyright (C) 2005 Nicholas J. Kisseberth
|
||||
Portions Copyright (C) 1994 David Burren
|
||||
All rights reserved.
|
||||
|
||||
===========================================================================
|
||||
|
||||
Advanced Rogue
|
||||
Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
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 "Advanced Rogue" and "ARogue" 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 "Advanced Rogue" or
|
||||
"ARogue", nor may "Advanced Rogue" or "ARogue 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 Robert D. Kindelberger.
|
||||
Used under license:
|
||||
|
||||
Super-Rogue
|
||||
Copyright (C) 1984 Robert D. Kindelberger
|
||||
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 "Super-Rogue" 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 "Super-Rogue",
|
||||
nor may "Super-Rogue" 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 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 (state.c, mdport.c) are based on the work
|
||||
of Nicholas J. Kisseberth. Used under license:
|
||||
|
||||
Copyright (C) 2005 Nicholas J. Kisseberth
|
||||
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 (xcrypt.c) are based on the work
|
||||
of David Burren. Used under license:
|
||||
|
||||
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
|
||||
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.
|
||||
193
arogue7/Makefile
Normal file
193
arogue7/Makefile
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
#
|
||||
# Makefile for rogue
|
||||
#
|
||||
# Advanced Rogue
|
||||
# Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# Makefile for rogue
|
||||
#
|
||||
|
||||
|
||||
DISTNAME=arogue7.7.1
|
||||
PROGRAM=arogue77
|
||||
|
||||
O=o
|
||||
|
||||
HDRS= rogue.h mach_dep.h network.h
|
||||
|
||||
OBJS1 = vers.$(O) actions.$(O) chase.$(O) command.$(O) daemon.$(O) \
|
||||
daemons.$(O) eat.$(O) effects.$(O) encumb.$(O) fight.$(O) init.$(O) \
|
||||
io.$(O) list.$(O) main.$(O) maze.$(O) mdport.$(O) misc.$(O) \
|
||||
monsters.$(O)
|
||||
OBJS2 = move.$(O) new_level.$(O) options.$(O) outside.$(O) pack.$(O) \
|
||||
passages.$(O) player.$(O) potions.$(O) rings.$(O) rip.$(O) rogue.$(O) \
|
||||
rooms.$(O) save.$(O) scrolls.$(O) state.$(O) sticks.$(O) things.$(O) \
|
||||
trader.$(O) util.$(O) weapons.$(O) wear.$(O) wizard.$(O) xcrypt.$(O)
|
||||
OBJS = $(OBJS1) $(OBJS2)
|
||||
|
||||
CFILES= vers.c actions.c chase.c command.c daemon.c \
|
||||
daemons.c eat.c effects.c encumb.c fight.c init.c \
|
||||
io.c list.c main.c maze.c mdport.c misc.c monsters.c \
|
||||
move.c new_level.c options.c outside.c pack.c \
|
||||
passages.c player.c potions.c rings.c rip.c rogue.c \
|
||||
rooms.c save.c scrolls.c state.c sticks.c things.c \
|
||||
trader.c util.c weapons.c wear.c wizard.c xcrypt.c
|
||||
MISC_C=
|
||||
DOCSRC= aguide.mm
|
||||
DOCS = $(PROGRAM).doc $(PROGRAM).html
|
||||
MISC = Makefile $(MISC_C) LICENSE.TXT $(PROGRAM).sln $(PROGRAM).vcproj $(DOCS)\
|
||||
$(DOCSRC)
|
||||
|
||||
CC = gcc
|
||||
ROPTS =
|
||||
COPTS = -O3
|
||||
CFLAGS= $(COPTS) $(ROPTS)
|
||||
LIBS = -lcurses
|
||||
RM = rm -f
|
||||
|
||||
.SUFFIXES: .obj
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) /c $*.c
|
||||
|
||||
$(PROGRAM): $(HDRS) $(OBJS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
|
||||
|
||||
clean:
|
||||
$(RM) $(OBJS1)
|
||||
$(RM) $(OBJS2)
|
||||
$(RM) core a.exe a.out a.exe.stackdump $(PROGRAM) $(PROGRAM).exe $(PROGRAM).lck
|
||||
$(RM) $(PROGRAM).tar $(PROGRAM).tar.gz $(PROGRAM).zip
|
||||
|
||||
dist.src:
|
||||
make clean
|
||||
tar cf $(DISTNAME)-src.tar $(CFILES) $(HDRS) $(MISC)
|
||||
gzip -f $(DISTNAME)-src.tar
|
||||
|
||||
doc.nroff:
|
||||
tbl aguide.mm | nroff -mm | colcrt - > arogue77.doc
|
||||
|
||||
doc.groff:
|
||||
groff -P-c -t -mm -Tascii aguide.mm | sed -e 's/.\x08//g' > arogue77.doc
|
||||
groff -t -mm -Thtml aguide.mm > arogue77.ht
|
||||
|
||||
dist.irix:
|
||||
make clean
|
||||
make CC=cc COPTS="-woff 1116 -O3" $(PROGRAM)
|
||||
tar cf $(DISTNAME)-irix.tar $(PROGRAM) LICENSE.TXT $(DOCS)
|
||||
gzip -f $(DISTNAME)-irix.tar
|
||||
|
||||
dist.aix:
|
||||
make clean
|
||||
make CC=xlc COPTS="-qmaxmem=16768 -O3 -qstrict" $(PROGRAM)
|
||||
tar cf $(DISTNAME)-aix.tar $(PROGRAM) LICENSE.TXT $(DOCS)
|
||||
gzip -f $(DISTNAME)-aix.tar
|
||||
|
||||
dist.linux:
|
||||
make clean
|
||||
make $(PROGRAM)
|
||||
tar cf $(DISTNAME)-linux.tar $(PROGRAM) LICENSE.TXT $(DOCS)
|
||||
gzip -f $(DISTNAME)-linux.tar
|
||||
|
||||
dist.interix:
|
||||
@$(MAKE) clean
|
||||
@$(MAKE) COPTS="-ansi" $(PROGRAM)
|
||||
tar cf $(DISTNAME)-interix.tar $(PROGRAM) LICENSE.TXT $(DOCS)
|
||||
gzip -f $(DISTNAME)-interix.tar
|
||||
|
||||
dist.cygwin:
|
||||
@$(MAKE) --no-print-directory clean
|
||||
@$(MAKE) --no-print-directory $(PROGRAM)
|
||||
tar cf $(DISTNAME)-cygwin.tar $(PROGRAM).exe LICENSE.TXT $(DOCS)
|
||||
gzip -f $(DISTNAME)-cygwin.tar
|
||||
|
||||
#
|
||||
# Use MINGW32-MAKE to build this target
|
||||
#
|
||||
dist.mingw32:
|
||||
@$(MAKE) --no-print-directory RM="cmd /c del" clean
|
||||
@$(MAKE) --no-print-directory LIBS="-lpdcurses" $(PROGRAM)
|
||||
cmd /c del $(DISTNAME)-mingw32.zip
|
||||
zip $(DISTNAME)-mingw32.zip $(PROGRAM).exe LICENSE.TXT $(DOCS)
|
||||
|
||||
dist.msys:
|
||||
@$(MAKE) --no-print-directory clean
|
||||
@$(MAKE) --no-print-directory LIBS="-lcurses" $(PROGRAM)
|
||||
tar cf $(DISTNAME)-msys.tar $(PROGRAM).exe LICENSE.TXT $(DOCS)
|
||||
gzip -f $(DISTNAME)-msys.tar
|
||||
|
||||
dist.djgpp:
|
||||
@$(MAKE) --no-print-directory clean
|
||||
@$(MAKE) --no-print-directory LDFLAGS="-L$(DJDIR)/LIB" \
|
||||
LIBS="-lpdcurses" $(PROGRAM)
|
||||
rm -f $(DISTNAME)-djgpp.zip
|
||||
zip $(DISTNAME)-djgpp.zip $(PROGRAM).exe LICENSE.TXT $(DOCS)
|
||||
|
||||
#
|
||||
# Use NMAKE to build this targer
|
||||
#
|
||||
dist.win32:
|
||||
@$(MAKE) /NOLOGO O="obj" RM="-del" clean
|
||||
@$(MAKE) /NOLOGO O="obj" CC="CL" \
|
||||
LIBS="..\pdcurses\pdcurses.lib shfolder.lib user32.lib Advapi32.lib" \
|
||||
COPTS="-nologo -I..\pdcurses \
|
||||
-Ox -wd4033 -wd4716" $(PROGRAM)
|
||||
-del $(DISTNAME)-win32.zip
|
||||
zip $(DISTNAME)-win32.zip $(PROGRAM).exe LICENSE.TXT $(DOCS)
|
||||
|
||||
|
||||
actions.o: rogue.h
|
||||
chase.o: rogue.h
|
||||
command.o: rogue.h
|
||||
command.o: mach_dep.h
|
||||
daemon.o: rogue.h
|
||||
daemons.o: rogue.h
|
||||
eat.o: rogue.h
|
||||
edit.o: mach_dep.h
|
||||
edit.o: rogue.h
|
||||
effects.o: rogue.h
|
||||
encumb.o: rogue.h
|
||||
fight.o: rogue.h
|
||||
init.o: rogue.h
|
||||
init.o: mach_dep.h
|
||||
io.o: rogue.h
|
||||
list.o: rogue.h
|
||||
main.o: mach_dep.h
|
||||
main.o: network.h
|
||||
main.o: rogue.h
|
||||
maze.o: rogue.h
|
||||
misc.o: rogue.h
|
||||
monsters.o: rogue.h
|
||||
move.o: rogue.h
|
||||
new_level.o: rogue.h
|
||||
options.o: rogue.h
|
||||
outside.o: rogue.h
|
||||
pack.o: rogue.h
|
||||
passages.o: rogue.h
|
||||
player.o: rogue.h
|
||||
potions.o: rogue.h
|
||||
rings.o: rogue.h
|
||||
rip.o: mach_dep.h
|
||||
rip.o: network.h
|
||||
rip.o: rogue.h
|
||||
rogue.o: rogue.h
|
||||
rooms.o: rogue.h
|
||||
save.o: rogue.h
|
||||
save.o: mach_dep.h
|
||||
scrolls.o: rogue.h
|
||||
sticks.o: rogue.h
|
||||
things.o: rogue.h
|
||||
trader.o: rogue.h
|
||||
util.o: rogue.h
|
||||
weapons.o: rogue.h
|
||||
wear.o: rogue.h
|
||||
wizard.o: rogue.h
|
||||
982
arogue7/actions.c
Normal file
982
arogue7/actions.c
Normal file
|
|
@ -0,0 +1,982 @@
|
|||
/*
|
||||
* actions.c - functions for dealing with monster actions
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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 <limits.h>
|
||||
#include "curses.h"
|
||||
#include "rogue.h"
|
||||
#define MAXINT INT_MAX
|
||||
#define MININT INT_MIN
|
||||
/*
|
||||
* Did we disrupt a spell?
|
||||
*/
|
||||
dsrpt_monster(tp, always, see_him)
|
||||
register struct thing *tp;
|
||||
bool always, see_him;
|
||||
{
|
||||
switch (tp->t_action) {
|
||||
case A_SUMMON:
|
||||
case A_MISSILE:
|
||||
case A_SLOW:
|
||||
tp->t_action = A_NIL; /* Just make the old fellow start over again */
|
||||
tp->t_no_move = movement(tp);
|
||||
tp->t_using = NULL;/* Just to be on the safe side */
|
||||
turn_on(*tp, WASDISRUPTED);
|
||||
if (see_him)
|
||||
msg("%s's spell has been disrupted.",prname(monster_name(tp),TRUE));
|
||||
/*
|
||||
* maybe choose something else to do next time since player
|
||||
* is disrupting us
|
||||
*/
|
||||
tp->t_summon *= 2;
|
||||
tp->t_cast /= 2;
|
||||
return;
|
||||
}
|
||||
|
||||
/* We may want to disrupt other actions, too */
|
||||
if (always) {
|
||||
tp->t_action = A_NIL; /* Just make the old fellow start over again */
|
||||
tp->t_no_move = movement(tp);
|
||||
tp->t_using = NULL;/* Just to be on the safe side */
|
||||
}
|
||||
}
|
||||
|
||||
dsrpt_player()
|
||||
{
|
||||
int which, action;
|
||||
struct linked_list *item;
|
||||
struct object *obj;
|
||||
|
||||
action = player.t_action;
|
||||
which = player.t_selection;
|
||||
|
||||
switch (action) {
|
||||
case C_CAST: /* Did we disrupt a spell? */
|
||||
case C_PRAY:
|
||||
case C_CHANT:
|
||||
{
|
||||
msg("Your %s was disrupted!", action == C_CAST ? "spell" : "prayer");
|
||||
|
||||
/* Charge him anyway */
|
||||
if (action == C_CAST)
|
||||
spell_power += magic_spells[which].s_cost;
|
||||
else if (action == C_PRAY)
|
||||
pray_time += cleric_spells[which].s_cost;
|
||||
else if (action == C_CHANT)
|
||||
chant_time += druid_spells[which].s_cost;
|
||||
}
|
||||
when C_COUNT: /* counting of gold? */
|
||||
{
|
||||
if (purse > 0) {
|
||||
msg("Your gold goes flying everywhere!");
|
||||
do {
|
||||
item = spec_item(GOLD, NULL, NULL, NULL);
|
||||
obj = OBJPTR(item);
|
||||
obj->o_count = min(purse, rnd(10)+1);
|
||||
purse -= obj->o_count;
|
||||
obj->o_pos = hero;
|
||||
fall(item, FALSE);
|
||||
} while (purse > 0 && rnd(10) != 1);
|
||||
}
|
||||
}
|
||||
when C_EAT:
|
||||
msg("You gag on your food for a moment.");
|
||||
del_pack(player.t_using);
|
||||
|
||||
when A_PICKUP:
|
||||
msg("You drop what you are picking up!");
|
||||
|
||||
when C_SEARCH: /* searching for traps and secret doors... */
|
||||
msg("Oww....You decide to stop searching.");
|
||||
count = 0; /* don't search again */
|
||||
|
||||
when C_SETTRAP:
|
||||
msg("Oww....You can't get a trap set.");
|
||||
|
||||
when A_NIL:
|
||||
default:
|
||||
return;
|
||||
}
|
||||
player.t_no_move = movement(&player); /* disoriented for a while */
|
||||
player.t_action = A_NIL;
|
||||
player.t_selection = 0;
|
||||
player.t_using = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* m_act:
|
||||
* If the critter isn't doing anything, choose an action for it.
|
||||
* Otherwise, let it perform its chosen action.
|
||||
*/
|
||||
|
||||
m_act(tp)
|
||||
register struct thing *tp;
|
||||
{
|
||||
struct object *obj;
|
||||
bool flee; /* Are we scared? */
|
||||
|
||||
/* What are we planning to do? */
|
||||
switch (tp->t_action) {
|
||||
default:
|
||||
/* An unknown action! */
|
||||
msg("Unknown monster action (%d)", tp->t_action);
|
||||
|
||||
/* Fall through */
|
||||
|
||||
case A_NIL:
|
||||
/* If the monster is fairly intelligent and about to die, it
|
||||
* may turn tail and run. But if we are a FRIENDLY creature
|
||||
* in the hero's service, don't run.
|
||||
*/
|
||||
if (off(*tp, ISFLEE) &&
|
||||
tp->t_stats.s_hpt < tp->maxstats.s_hpt &&
|
||||
tp->t_stats.s_hpt < max(10, tp->maxstats.s_hpt/6) &&
|
||||
(off(*tp, ISFRIENDLY) || tp->t_dest != &hero) &&
|
||||
rnd(25) < tp->t_stats.s_intel) {
|
||||
turn_on(*tp, ISFLEE);
|
||||
|
||||
/* It is okay to turn tail */
|
||||
tp->t_oldpos = tp->t_pos;
|
||||
}
|
||||
|
||||
/* Should the monster run away? */
|
||||
flee = on(*tp, ISFLEE) ||
|
||||
((tp->t_dest == &hero) && on(player, ISINWALL) &&
|
||||
off(*tp, CANINWALL));
|
||||
|
||||
m_select(tp, flee); /* Select an action */
|
||||
return;
|
||||
|
||||
when A_ATTACK:
|
||||
/*
|
||||
* We're trying to attack the player or monster at t_newpos
|
||||
* if the prey moved, do nothing
|
||||
*/
|
||||
obj = tp->t_using ? OBJPTR(tp->t_using) : NULL;
|
||||
if (ce(tp->t_newpos, hero)) {
|
||||
attack(tp, obj, FALSE);
|
||||
}
|
||||
else if (mvwinch(mw, tp->t_newpos.y, tp->t_newpos.x) &&
|
||||
step_ok(tp->t_newpos.y, tp->t_newpos.x, FIGHTOK, tp)) {
|
||||
skirmish(tp, &tp->t_newpos, obj, FALSE);
|
||||
}
|
||||
|
||||
when A_SELL:
|
||||
/* Is the player still next to us? */
|
||||
if (ce(tp->t_newpos, hero)) sell(tp);
|
||||
|
||||
/* The darned player moved away */
|
||||
else if (off(player, ISBLIND) &&
|
||||
cansee(unc(tp->t_pos)) &&
|
||||
(off(*tp, ISINVIS) || on(player, CANSEE)) &&
|
||||
(off(*tp, ISSHADOW) || on(player, CANSEE)) &&
|
||||
(off(*tp, CANSURPRISE) || ISWEARING(R_ALERT)))
|
||||
msg("%s grunts with frustration",prname(monster_name(tp),TRUE));
|
||||
|
||||
when A_MOVE:
|
||||
/* Let's try to move */
|
||||
do_chase(tp);
|
||||
|
||||
/* If t_no_move > 0, we found that we have to fight! */
|
||||
if (tp->t_no_move > 0) return;
|
||||
|
||||
when A_BREATHE:
|
||||
/* Breathe on the critter */
|
||||
m_breathe(tp);
|
||||
|
||||
when A_SLOW:
|
||||
/* make him move slower */
|
||||
add_slow();
|
||||
turn_off(*tp, CANSLOW);
|
||||
|
||||
when A_MISSILE:
|
||||
/* Start up a magic missile spell */
|
||||
m_spell(tp);
|
||||
|
||||
when A_SONIC:
|
||||
/* Let out a sonic blast! */
|
||||
m_sonic(tp);
|
||||
|
||||
when A_THROW:
|
||||
/* We're throwing something (like an arrow) */
|
||||
missile(tp->t_newpos.y, tp->t_newpos.x, tp->t_using, tp);
|
||||
|
||||
when A_SUMMON:
|
||||
/* We're summoning help */
|
||||
m_summon(tp);
|
||||
|
||||
when A_USERELIC:
|
||||
/* Use our relic */
|
||||
m_use_relic(tp);
|
||||
|
||||
when A_USEWAND:
|
||||
/* use the wand we have */
|
||||
m_use_wand(tp);
|
||||
}
|
||||
|
||||
/* No action now */
|
||||
tp->t_action = A_NIL;
|
||||
tp->t_using = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* m_breathe:
|
||||
* Breathe in the chosen direction.
|
||||
*/
|
||||
|
||||
m_breathe(tp)
|
||||
register struct thing *tp;
|
||||
{
|
||||
register int damage;
|
||||
register char *breath;
|
||||
|
||||
damage = tp->t_stats.s_hpt;
|
||||
turn_off(*tp, CANSURPRISE);
|
||||
|
||||
/* Will it breathe at random */
|
||||
if (on(*tp, CANBRANDOM)) {
|
||||
/* Turn off random breath */
|
||||
turn_off(*tp, CANBRANDOM);
|
||||
|
||||
/* Select type of breath */
|
||||
switch (rnd(10)) {
|
||||
case 0: breath = "acid";
|
||||
turn_on(*tp, NOACID);
|
||||
when 1: breath = "flame";
|
||||
turn_on(*tp, NOFIRE);
|
||||
when 2: breath = "lightning bolt";
|
||||
turn_on(*tp, NOBOLT);
|
||||
when 3: breath = "chlorine gas";
|
||||
turn_on(*tp, NOGAS);
|
||||
when 4: breath = "ice";
|
||||
turn_on(*tp, NOCOLD);
|
||||
when 5: breath = "nerve gas";
|
||||
turn_on(*tp, NOPARALYZE);
|
||||
when 6: breath = "sleeping gas";
|
||||
turn_on(*tp, NOSLEEP);
|
||||
when 7: breath = "slow gas";
|
||||
turn_on(*tp, NOSLOW);
|
||||
when 8: breath = "confusion gas";
|
||||
turn_on(*tp, ISCLEAR);
|
||||
when 9: breath = "fear gas";
|
||||
turn_on(*tp, NOFEAR);
|
||||
}
|
||||
}
|
||||
|
||||
/* Or can it breathe acid? */
|
||||
else if (on(*tp, CANBACID)) {
|
||||
turn_off(*tp, CANBACID);
|
||||
breath = "acid";
|
||||
}
|
||||
|
||||
/* Or can it breathe fire */
|
||||
else if (on(*tp, CANBFIRE)) {
|
||||
turn_off(*tp, CANBFIRE);
|
||||
breath = "flame";
|
||||
}
|
||||
|
||||
/* Or can it breathe electricity? */
|
||||
else if (on(*tp, CANBBOLT)) {
|
||||
turn_off(*tp, CANBBOLT);
|
||||
breath = "lightning bolt";
|
||||
}
|
||||
|
||||
/* Or can it breathe gas? */
|
||||
else if (on(*tp, CANBGAS)) {
|
||||
turn_off(*tp, CANBGAS);
|
||||
breath = "chlorine gas";
|
||||
}
|
||||
|
||||
/* Or can it breathe ice? */
|
||||
else if (on(*tp, CANBICE)) {
|
||||
turn_off(*tp, CANBICE);
|
||||
breath = "ice";
|
||||
}
|
||||
|
||||
else if (on(*tp, CANBPGAS)) {
|
||||
turn_off(*tp, CANBPGAS);
|
||||
breath = "nerve gas";
|
||||
}
|
||||
|
||||
/* can it breathe sleeping gas */
|
||||
else if (on(*tp, CANBSGAS)) {
|
||||
turn_off(*tp, CANBSGAS);
|
||||
breath = "sleeping gas";
|
||||
}
|
||||
|
||||
/* can it breathe slow gas */
|
||||
else if (on(*tp, CANBSLGAS)) {
|
||||
turn_off(*tp, CANBSLGAS);
|
||||
breath = "slow gas";
|
||||
}
|
||||
|
||||
/* can it breathe confusion gas */
|
||||
else if (on(*tp, CANBCGAS)) {
|
||||
turn_off(*tp, CANBCGAS);
|
||||
breath = "confusion gas";
|
||||
}
|
||||
|
||||
/* can it breathe fear gas */
|
||||
else {
|
||||
turn_off(*tp, CANBFGAS);
|
||||
breath = "fear gas";
|
||||
}
|
||||
|
||||
/* Now breathe -- sets "monst_dead" if it kills someone */
|
||||
shoot_bolt(tp, tp->t_pos, tp->t_newpos, FALSE,
|
||||
tp->t_index, breath, damage);
|
||||
|
||||
running = FALSE;
|
||||
if (fight_flush) md_flushinp();
|
||||
}
|
||||
|
||||
/*
|
||||
* m_select:
|
||||
* Select an action for the monster.
|
||||
*/
|
||||
|
||||
m_select(th, flee)
|
||||
register struct thing *th;
|
||||
register bool flee; /* True if running away or player is inaccessible in wall */
|
||||
{
|
||||
register struct room *rer, *ree; /* room of chaser, room of chasee */
|
||||
int dist = MININT;
|
||||
int mindist = MAXINT, maxdist = MININT;
|
||||
bool rundoor; /* TRUE means run to a door */
|
||||
char sch;
|
||||
coord *last_door=0, /* Door we just came from */
|
||||
this; /* Temporary destination for chaser */
|
||||
|
||||
rer = roomin(&th->t_pos); /* Find room of chaser */
|
||||
ree = roomin(th->t_dest); /* Find room of chasee */
|
||||
|
||||
/* First see if we want to use an ability or weapon */
|
||||
if (m_use_it(th, flee, rer, ree)) return;
|
||||
|
||||
/*
|
||||
* We don't count monsters on doors as inside rooms here because when
|
||||
* a monster is in a room and the player is not in that room, the
|
||||
* monster looks for the best door out. If we counted doors as part
|
||||
* of the room, the monster would already be on the best door out;
|
||||
* so he would never move.
|
||||
*/
|
||||
if ((sch = CCHAR( mvwinch(stdscr, th->t_pos.y, th->t_pos.x) )) == DOOR ||
|
||||
sch == SECRETDOOR || sch == PASSAGE) {
|
||||
rer = NULL;
|
||||
}
|
||||
this = *th->t_dest;
|
||||
|
||||
/*
|
||||
* If we are in a room heading for the player and the player is not
|
||||
* in the room with us, we run to the "best" door.
|
||||
* If we are in a room fleeing from the player, then we run to the
|
||||
* "best" door if he IS in the same room.
|
||||
*
|
||||
* Note: We don't bother with doors in mazes or if we can walk
|
||||
* through walls.
|
||||
*/
|
||||
if (rer != NULL && levtype != MAZELEV && off(*th, CANINWALL)) {
|
||||
if (flee) rundoor = (rer == ree);
|
||||
else rundoor = (rer != ree);
|
||||
}
|
||||
else rundoor = FALSE;
|
||||
|
||||
if (rundoor) {
|
||||
register struct linked_list *exitptr; /* For looping through exits */
|
||||
coord *exit, /* A particular door */
|
||||
*entrance; /* Place just inside doorway */
|
||||
int exity, exitx; /* Door's coordinates */
|
||||
char dch='\0'; /* Door character */
|
||||
|
||||
if (th->t_doorgoal)
|
||||
dch = CCHAR( mvwinch(stdscr, th->t_doorgoal->y, th->t_doorgoal->x) );
|
||||
|
||||
/* Do we have a valid goal? */
|
||||
if ((dch == PASSAGE || dch == DOOR) && /* A real door */
|
||||
(!flee || !ce(*th->t_doorgoal, *th->t_dest))) { /* Prey should not
|
||||
* be at door if
|
||||
* we are running
|
||||
* away
|
||||
*/
|
||||
/* Make sure the player is not in the doorway, either */
|
||||
entrance = doorway(rer, th->t_doorgoal);
|
||||
if (!flee || entrance == NULL || !ce(*entrance, *th->t_dest)) {
|
||||
this = *th->t_doorgoal;
|
||||
dist = 0; /* Indicate that we have our door */
|
||||
}
|
||||
}
|
||||
|
||||
/* Go through all the doors */
|
||||
else for (exitptr = rer->r_exit; exitptr; exitptr = next(exitptr)) {
|
||||
exit = DOORPTR(exitptr);
|
||||
exity = exit->y;
|
||||
exitx = exit->x;
|
||||
|
||||
/* Make sure it is a real door */
|
||||
dch = CCHAR( mvwinch(stdscr, exity, exitx) );
|
||||
if (dch == PASSAGE || dch == DOOR) {
|
||||
/* Don't count a door if we are fleeing from someone and
|
||||
* he is standing on it. Also, don't count it if he is
|
||||
* standing in the doorway.
|
||||
*/
|
||||
if (flee) {
|
||||
if (ce(*exit, *th->t_dest)) continue;
|
||||
|
||||
entrance = doorway(rer, exit);
|
||||
if (entrance != NULL && ce(*entrance, *th->t_dest))
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Were we just on this door? */
|
||||
if (ce(*exit, th->t_oldpos)) last_door = exit;
|
||||
|
||||
else {
|
||||
dist = DISTANCE(th->t_dest->y, th->t_dest->x, exity, exitx);
|
||||
|
||||
/* If fleeing, we want to maximize distance from door to
|
||||
* what we flee, and minimize distance from door to us.
|
||||
*/
|
||||
if (flee)
|
||||
dist -= DISTANCE(th->t_pos.y, th->t_pos.x, exity, exitx);
|
||||
|
||||
/* Maximize distance if fleeing, otherwise minimize it */
|
||||
if ((flee && (dist > maxdist)) ||
|
||||
(!flee && (dist < mindist))) {
|
||||
th->t_doorgoal = exit; /* Use this door */
|
||||
this = *exit;
|
||||
mindist = maxdist = dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Could we not find a door? */
|
||||
if (dist == MININT) {
|
||||
/* If we were on a door, go ahead and use it */
|
||||
if (last_door) {
|
||||
th->t_doorgoal = last_door;
|
||||
this = th->t_oldpos;
|
||||
dist = 0; /* Indicate that we found a door */
|
||||
}
|
||||
else th->t_doorgoal = NULL; /* No more door goal */
|
||||
}
|
||||
|
||||
/* Indicate that we do not want to flee from the door */
|
||||
if (dist != MININT) flee = FALSE;
|
||||
}
|
||||
else th->t_doorgoal = 0; /* Not going to any door */
|
||||
|
||||
/* Now select someplace to go and start the action */
|
||||
chase(th, &this, rer, ree, flee);
|
||||
}
|
||||
|
||||
/*
|
||||
* m_sonic:
|
||||
* The monster is sounding a sonic blast.
|
||||
*/
|
||||
|
||||
m_sonic(tp)
|
||||
register struct thing *tp;
|
||||
{
|
||||
register int damage;
|
||||
static struct object blast =
|
||||
{
|
||||
MISSILE, {0, 0}, "", 0, "", "150" , NULL, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
turn_off(*tp, CANSONIC);
|
||||
turn_off(*tp, CANSURPRISE);
|
||||
do_motion(&blast, tp->t_newpos.y, tp->t_newpos.x, tp);
|
||||
damage = 150;
|
||||
if (save(VS_BREATH, &player, -3))
|
||||
damage /= 2;
|
||||
msg ("%s's sonic blast hits you", prname(monster_name(tp), TRUE));
|
||||
if ((pstats.s_hpt -= damage) <= 0)
|
||||
death(tp->t_index);
|
||||
|
||||
running = FALSE;
|
||||
if (fight_flush) md_flushinp();
|
||||
dsrpt_player();
|
||||
}
|
||||
|
||||
/*
|
||||
* m_spell:
|
||||
* The monster casts a spell. Currently this is limited to
|
||||
* magic missile.
|
||||
*/
|
||||
m_spell(tp)
|
||||
register struct thing *tp;
|
||||
{
|
||||
static struct object missile =
|
||||
{
|
||||
MISSILE, {0, 0}, "", 0, "", "0d4 " , NULL, 0, WS_MISSILE, 100, 1
|
||||
};
|
||||
|
||||
sprintf(missile.o_hurldmg, "%dd4", tp->t_stats.s_lvl);
|
||||
do_motion(&missile, tp->t_newpos.y, tp->t_newpos.x, tp);
|
||||
hit_monster(unc(missile.o_pos), &missile, tp);
|
||||
turn_off(*tp, CANMISSILE);
|
||||
turn_off(*tp, CANSURPRISE);
|
||||
|
||||
running = FALSE;
|
||||
if (fight_flush) md_flushinp();
|
||||
}
|
||||
|
||||
/*
|
||||
* m_summon:
|
||||
* Summon aid.
|
||||
*/
|
||||
|
||||
m_summon(tp)
|
||||
register struct thing *tp;
|
||||
{
|
||||
register char *helpname, *mname;
|
||||
int fail, numsum;
|
||||
register int which, i;
|
||||
|
||||
/* Let's make sure our prey is still here */
|
||||
if (!cansee(unc(tp->t_pos)) || fallpos(&hero, FALSE, 2) == NULL) return;
|
||||
|
||||
/*
|
||||
* Non-uniques can only summon once. Uniques get fewer
|
||||
* creatures with each successive summoning. Also, the
|
||||
* probability of summoning goes down
|
||||
*/
|
||||
if (off(*tp, ISUNIQUE))
|
||||
turn_off(*tp, CANSUMMON);
|
||||
|
||||
turn_off(*tp, CANSURPRISE);
|
||||
mname = monster_name(tp);
|
||||
helpname = monsters[tp->t_index].m_typesum;
|
||||
which = findmindex(helpname);
|
||||
|
||||
if ((off(*tp, ISINVIS) || on(player, CANSEE)) &&
|
||||
(off(*tp, ISSHADOW) || on(player, CANSEE)) &&
|
||||
(off(*tp, CANSURPRISE) || ISWEARING(R_ALERT))) {
|
||||
if (monsters[which].m_normal == FALSE) { /* genocided? */
|
||||
msg("%s appears dismayed", prname(mname, TRUE));
|
||||
monsters[tp->t_index].m_numsum = 0;
|
||||
}
|
||||
else {
|
||||
msg("%s summons %ss for help", prname(mname, TRUE), helpname);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (monsters[which].m_normal == FALSE) /* genocided? */
|
||||
monsters[tp->t_index].m_numsum = 0;
|
||||
else {
|
||||
msg("%ss seem to appear from nowhere!", helpname);
|
||||
}
|
||||
}
|
||||
numsum = monsters[tp->t_index].m_numsum;
|
||||
if (numsum && on(*tp, ISUNIQUE)) { /* UNIQUEs summon less each time */
|
||||
monsters[tp->t_index].m_numsum--;
|
||||
tp->t_summon *= 2; /* cut probability in half */
|
||||
}
|
||||
|
||||
/*
|
||||
* try to make all the creatures around player but remember
|
||||
* if unsuccessful
|
||||
*/
|
||||
for (i=0, fail=0; i<numsum; i++) {
|
||||
if (!creat_mons(&player, which, FALSE))
|
||||
fail++; /* remember the failures */
|
||||
}
|
||||
|
||||
/*
|
||||
* try once again to make the buggers
|
||||
*/
|
||||
for (i=0; i<fail; i++)
|
||||
creat_mons(tp, which, FALSE);
|
||||
|
||||
/* Now let the poor fellow see all the trouble */
|
||||
light(&hero);
|
||||
turn_on(*tp, HASSUMMONED);
|
||||
}
|
||||
|
||||
/*
|
||||
* m_use_it:
|
||||
* See if the monster (tp) has anything useful it can do
|
||||
* (ie. an ability or a weapon) other than just move.
|
||||
*/
|
||||
|
||||
bool
|
||||
m_use_it(tp, flee, rer, ree)
|
||||
register struct thing *tp;
|
||||
bool flee;
|
||||
register struct room *rer, *ree;
|
||||
{
|
||||
int dist;
|
||||
register coord *ee = tp->t_dest, *er = &tp->t_pos;
|
||||
coord *shoot_dir;
|
||||
struct linked_list *weapon;
|
||||
struct thing *prey;
|
||||
bool dest_player; /* Are we after the player? */
|
||||
|
||||
/*
|
||||
* If we are fleeing, there's a chance, depending on our
|
||||
* intelligence, that we'll just run in terror.
|
||||
*/
|
||||
if (flee && rnd(25) >= tp->t_stats.s_intel) return(FALSE);
|
||||
|
||||
/*
|
||||
* Make sure that we have a living destination, and record whether
|
||||
* it is the player.
|
||||
*/
|
||||
if (ee != NULL) {
|
||||
if (ce(*ee, hero)) {
|
||||
dest_player = TRUE;
|
||||
prey = &player;
|
||||
}
|
||||
else {
|
||||
struct linked_list *item;
|
||||
|
||||
dest_player = FALSE;
|
||||
|
||||
/* What is the monster we're chasing? */
|
||||
item = find_mons(ee->y, ee->x);
|
||||
if (item != NULL) prey = THINGPTR(item);
|
||||
else return(FALSE);
|
||||
}
|
||||
}
|
||||
else return(FALSE);
|
||||
|
||||
/*
|
||||
* If we are friendly to the hero, we don't do anything.
|
||||
*/
|
||||
if (on(*tp, ISFRIENDLY) && dest_player) return(FALSE);
|
||||
|
||||
/*
|
||||
* Also, for now, if our prey is in a wall, we won't do
|
||||
* anything. The prey must be in the same room as we are OR
|
||||
* we must have a straight shot at him. Note that
|
||||
* shoot_dir must get set before rer is checked so
|
||||
* that we get a valid value.
|
||||
*/
|
||||
if (on(*prey, ISINWALL) ||
|
||||
((shoot_dir = can_shoot(er, ee)) == NULL &&
|
||||
(rer == NULL || rer != ree)))
|
||||
return(FALSE);
|
||||
|
||||
/*
|
||||
* If we can't see the prey then forget it
|
||||
*/
|
||||
if (on(*prey, ISINVIS) && off(*tp, CANSEE))
|
||||
return(FALSE);
|
||||
|
||||
/* How far are we from our prey? */
|
||||
dist = DISTANCE(er->y, er->x, ee->y, ee->x);
|
||||
|
||||
/*
|
||||
* Shall we summon aid so we don't have to get our hands dirty?
|
||||
* For now, we will only summon aid against the player.
|
||||
* We'll wait until he's within 2 dots of a missile length.
|
||||
*/
|
||||
if (on(*tp, CANSUMMON) && dest_player &&
|
||||
dist < (BOLT_LENGTH+2)*(BOLT_LENGTH+2) &&
|
||||
rnd(tp->t_summon) < tp->t_stats.s_lvl &&
|
||||
monsters[tp->t_index].m_numsum > 0 &&
|
||||
fallpos(&hero, FALSE, 2) != NULL) {
|
||||
tp->t_action = A_SUMMON; /* We're going to summon help */
|
||||
tp->t_no_move = movement(tp); /* It takes time! */
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the creature can cast a slow spell and if the prey is within
|
||||
* 2 dots of a missile fire, then see whether we will cast it.
|
||||
* if next to player, lessen chance because we don't like being
|
||||
* disrupted
|
||||
*/
|
||||
if (on(*tp, CANSLOW) && dest_player &&
|
||||
dist < (BOLT_LENGTH+5)*(BOLT_LENGTH+5) &&
|
||||
rnd(100) < (dist > 3 ? tp->t_cast : tp->t_cast/2)) {
|
||||
tp->t_action = A_SLOW; /* We're going to slow him */
|
||||
tp->t_no_move = 3 * movement(tp); /* Takes time! */
|
||||
debug("casting slow spell!");
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have a special magic item, we might use it. We will restrict
|
||||
* this options to uniques with relics and creatures with wands for now.
|
||||
* Also check for the quartermaster. Don't want him shooting wands....
|
||||
*/
|
||||
if ((on(*tp, ISUNIQUE) || on(*tp, CARRYSTICK)) &&
|
||||
off(*tp, CANSELL) && dest_player &&
|
||||
m_use_pack(tp, er, ee, dist, shoot_dir)) {
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/* From now on, we must have a direct shot at the prey */
|
||||
if (shoot_dir == NULL) return(FALSE);
|
||||
|
||||
/* We may use a sonic blast if we can, only on the player */
|
||||
if (on(*tp, CANSONIC) &&
|
||||
dest_player &&
|
||||
(dist < BOLT_LENGTH*2) &&
|
||||
(rnd(100) < tp->t_breathe)) {
|
||||
tp->t_newpos = *shoot_dir; /* Save the direction */
|
||||
tp->t_action = A_SONIC; /* We're going to sonic blast */
|
||||
tp->t_no_move = 2 * movement(tp); /* Takes 2 movement periods */
|
||||
}
|
||||
|
||||
/* If we can breathe, we may do so */
|
||||
else if (on(*tp, CANBREATHE) &&
|
||||
(dist < BOLT_LENGTH*BOLT_LENGTH) &&
|
||||
(rnd(100) < tp->t_breathe)) {
|
||||
tp->t_newpos = *shoot_dir; /* Save the direction */
|
||||
tp->t_action = A_BREATHE; /* We're going to breathe */
|
||||
tp->t_no_move = movement(tp); /* It takes 1 movement period */
|
||||
}
|
||||
|
||||
/*
|
||||
* We may shoot missiles if we can
|
||||
* if next to player, lessen chance so we don't get disrupted as often
|
||||
*/
|
||||
else if (on(*tp,CANMISSILE) &&
|
||||
rnd(100) < (dist > 3 ? tp->t_cast : tp->t_cast/2)){
|
||||
tp->t_newpos = *shoot_dir; /* Save the direction */
|
||||
tp->t_action = A_MISSILE; /* We're going to shoot MM's */
|
||||
tp->t_no_move = 3 * movement(tp); /* Takes time! */
|
||||
}
|
||||
|
||||
/*
|
||||
* If we can shoot or throw something, we might do so.
|
||||
* If next to player, then forget it
|
||||
*/
|
||||
else if ((on(*tp,CANSHOOT) || on(*tp,CARRYWEAPON) ||
|
||||
on(*tp,CARRYDAGGER) || on(*tp, CARRYAXE)) &&
|
||||
dist > 3 &&
|
||||
off(*tp, CANSELL) &&
|
||||
(weapon = get_hurl(tp))) {
|
||||
tp->t_newpos = *shoot_dir; /* Save the direction */
|
||||
tp->t_action = A_THROW; /* We're going to throw something */
|
||||
tp->t_using = weapon; /* Save our weapon */
|
||||
tp->t_no_move = 2 * movement(tp); /* Takes 2 movement periods */
|
||||
}
|
||||
|
||||
/* We couldn't find anything to do */
|
||||
else return(FALSE);
|
||||
|
||||
return(TRUE);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* runners:
|
||||
* Make all the awake monsters try to do something.
|
||||
*/
|
||||
|
||||
runners(segments)
|
||||
int segments; /* Number of segments since last called */
|
||||
{
|
||||
register struct linked_list *item;
|
||||
register struct thing *tp;
|
||||
register min_time = 20; /* Minimum time until a monster can act */
|
||||
|
||||
/*
|
||||
* loop thru the list of running (wandering) monsters and see what
|
||||
* each one will do this time.
|
||||
*
|
||||
* Note: the special case that one of this buggers kills another.
|
||||
* if this happens than we have to see if the monster killed
|
||||
* himself or someone else. In case its himself we have to get next
|
||||
* one immediately. If it wasn't we have to get next one at very
|
||||
* end in case he killed the next one.
|
||||
*/
|
||||
|
||||
for (item = mlist; item != NULL; item = next(item)) {
|
||||
tp = THINGPTR(item);
|
||||
turn_on(*tp, ISREADY);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
|
||||
for (item = mlist; item != NULL; item = next(item)) {
|
||||
tp = THINGPTR(item);
|
||||
|
||||
if (on(*tp, ISREADY))
|
||||
break;
|
||||
}
|
||||
|
||||
if (item == NULL)
|
||||
break;
|
||||
|
||||
turn_off(*tp, ISREADY);
|
||||
|
||||
/* If we are not awake, just skip us */
|
||||
if (off(*tp, ISRUN) && off(*tp, ISHELD)) continue;
|
||||
|
||||
/* See if it's our turn */
|
||||
tp->t_no_move -= segments;
|
||||
if (tp->t_no_move > 0) {
|
||||
if (tp->t_no_move < min_time) min_time = tp->t_no_move;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If we were frozen, we're moving now */
|
||||
if (tp->t_action == A_FREEZE) tp->t_action = A_NIL;
|
||||
|
||||
if (on(*tp, ISHELD)) {
|
||||
/* Make sure the action and using are nil */
|
||||
tp->t_action = A_NIL;
|
||||
tp->t_using = NULL;
|
||||
|
||||
/* Can we break free? */
|
||||
if (rnd(tp->t_stats.s_lvl) > 11) {
|
||||
turn_off(*tp, ISHELD);
|
||||
runto(tp, &hero);
|
||||
if (cansee(tp->t_pos.y, tp->t_pos.x))
|
||||
msg("%s breaks free from the hold spell",
|
||||
prname(monster_name(tp), TRUE));
|
||||
}
|
||||
|
||||
/* Too bad -- try again later */
|
||||
else tp->t_no_move = movement(tp);
|
||||
}
|
||||
|
||||
/* Heal the creature if it's not in the middle of some action */
|
||||
if (tp->t_action == A_NIL) doctor(tp);
|
||||
|
||||
while (off(*tp,ISELSEWHERE) &&
|
||||
off(*tp,ISDEAD) &&
|
||||
tp->t_no_move <= 0 && off(*tp, ISHELD) && on(*tp, ISRUN)) {
|
||||
/* Let's act (or choose an action if t_action = A_NIL) */
|
||||
m_act(tp);
|
||||
}
|
||||
|
||||
if (off(*tp,ISELSEWHERE) && off(*tp,ISDEAD)) {
|
||||
if (tp->t_no_move < min_time) min_time = tp->t_no_move;
|
||||
if (tp->t_quiet < 0) tp->t_quiet = 0;
|
||||
}
|
||||
}
|
||||
return(min_time);
|
||||
}
|
||||
|
||||
/*
|
||||
* See if a monster has some magic it can use. Return TRUE if so.
|
||||
* Only care about relics and wands for now.
|
||||
*/
|
||||
bool
|
||||
m_use_pack(monster, monst_pos, defend_pos, dist, shoot_dir)
|
||||
register struct thing *monster;
|
||||
register coord *monst_pos, *defend_pos;
|
||||
register int dist;
|
||||
register coord *shoot_dir;
|
||||
{
|
||||
register struct object *obj;
|
||||
register struct linked_list *pitem, *relic, *stick;
|
||||
register int units = -1;
|
||||
|
||||
relic = stick = NULL;
|
||||
|
||||
for (pitem=monster->t_pack; pitem; pitem=next(pitem)) {
|
||||
obj = OBJPTR(pitem);
|
||||
if (obj->o_flags & ISCURSED) continue;
|
||||
if (obj->o_type == RELIC) {
|
||||
switch (obj->o_which) {
|
||||
case MING_STAFF:
|
||||
if (shoot_dir != NULL) {
|
||||
units = 2; /* Use 2 time units */
|
||||
relic = pitem;
|
||||
}
|
||||
|
||||
when EMORI_CLOAK:
|
||||
if (obj->o_charges != 0 &&
|
||||
shoot_dir != NULL) {
|
||||
units = 2; /* Use 2 time units */
|
||||
relic = pitem;
|
||||
}
|
||||
|
||||
when ASMO_ROD:
|
||||
/* The bolt must be able to reach the defendant */
|
||||
if (shoot_dir != NULL &&
|
||||
dist < BOLT_LENGTH * BOLT_LENGTH) {
|
||||
units = 2; /* Use 2 time units */
|
||||
relic = pitem;
|
||||
}
|
||||
|
||||
when BRIAN_MANDOLIN:
|
||||
/* The defendant must be the player and within 4 spaces */
|
||||
if (ce(*defend_pos, hero) &&
|
||||
dist < 25 &&
|
||||
player.t_action != A_FREEZE) {
|
||||
units = 4;
|
||||
relic = pitem;
|
||||
}
|
||||
|
||||
when GERYON_HORN:
|
||||
/* The defendant must be the player and within 5 spaces */
|
||||
if (ce(*defend_pos, hero) &&
|
||||
dist < 25 &&
|
||||
(off(player,ISFLEE)|| player.t_dest!=&monster->t_pos)) {
|
||||
units = 3;
|
||||
relic = pitem;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (obj->o_type == STICK) {
|
||||
if (obj->o_charges < 1) continue;
|
||||
switch(obj->o_which) {
|
||||
case WS_ELECT:
|
||||
case WS_FIRE:
|
||||
case WS_COLD:
|
||||
/* The bolt must be able to reach the defendant */
|
||||
if (shoot_dir != NULL &&
|
||||
dist < BOLT_LENGTH * BOLT_LENGTH) {
|
||||
units = 3;
|
||||
stick = pitem;
|
||||
}
|
||||
|
||||
when WS_MISSILE:
|
||||
case WS_SLOW_M:
|
||||
case WS_CONFMON:
|
||||
case WS_PARALYZE:
|
||||
case WS_MDEG:
|
||||
case WS_FEAR:
|
||||
if (shoot_dir != NULL) {
|
||||
units = 3;
|
||||
stick = pitem;
|
||||
}
|
||||
|
||||
otherwise:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* use relics in preference to all others */
|
||||
if (relic) debug("chance to use relic = %d%%", monster->t_artifact);
|
||||
if (stick) debug("chance to use stick = %d%%", monster->t_wand);
|
||||
if (relic && rnd(100) < monster->t_artifact) {
|
||||
monster->t_action = A_USERELIC;
|
||||
pitem = relic;
|
||||
}
|
||||
else if (stick && rnd(100) < monster->t_wand) {
|
||||
/*
|
||||
* see if the monster will use the wand
|
||||
*/
|
||||
pitem = stick;
|
||||
monster->t_action = A_USEWAND;
|
||||
}
|
||||
else {
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
monster->t_no_move = units * movement(monster);
|
||||
monster->t_using = pitem;
|
||||
monster->t_newpos = *shoot_dir;
|
||||
return(TRUE);
|
||||
}
|
||||
799
arogue7/aguide.mm
Normal file
799
arogue7/aguide.mm
Normal file
|
|
@ -0,0 +1,799 @@
|
|||
.\"
|
||||
.\" aguide.mm
|
||||
.\"
|
||||
.\" Advanced Rogue
|
||||
.\" Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
.\" 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.
|
||||
.\"
|
||||
.tr ~
|
||||
.nr Pt 1
|
||||
.ds HF 3 2 2 2 2 2 2
|
||||
.TL
|
||||
The Dungeons of Doom
|
||||
.AF Toolchest
|
||||
.AU " "
|
||||
.AS 1
|
||||
.P
|
||||
Rogue was introduced at the University of California at Berkeley as a
|
||||
screen-oriented fantasy game.
|
||||
The game had 26 types of monsters that the player could meet while
|
||||
exploring a dungeon generated by the computer.
|
||||
Scrolls, potions, rings, wands, staves, armor, and weapons helped the
|
||||
player to battle these monsters and to gain gold, the basis for scoring.
|
||||
.P
|
||||
The version of Rogue described in this guide has been expanded to include
|
||||
over 110 monsters with many new capabilities.
|
||||
Many of the monsters are intelligent, and they, like the player, must avoid
|
||||
traps and decide when it is better to fight or to run.
|
||||
The player chooses a character class at the beginning of the game which
|
||||
defines the player's abilities.
|
||||
Experience, rather than gold, decides the player's score.
|
||||
.AE
|
||||
.MT 4
|
||||
.H 1 INTRODUCTION
|
||||
Rogue is a screen-oriented fantasy game set in the ever-changing
|
||||
\fIDungeons of Doom\fR.
|
||||
The game comes complete with monsters, spells, weapons, armor, potions,
|
||||
and other magical items.
|
||||
The dungeon's geography changes with every game, and although many magical
|
||||
items have certain identifiable properties, such as turning the player
|
||||
invisible, the physical manifestation of the magic changes each game.
|
||||
A red potion, for example, will cause the same reaction throughout
|
||||
a given game, but it may be a completely different potion in a new game.
|
||||
.P
|
||||
Entering the dungeon with only a little food, armor, and a weapon, the player
|
||||
must develop a good strategy of when
|
||||
to fight, when to run, and how to best use any magical items found
|
||||
in the dungeon.
|
||||
To make things interesting, the player has a quest to return one of
|
||||
several unique artifacts, rumored to lie deep in the dungeon's bowels.
|
||||
Returning with this artifact brings great glory and the title of
|
||||
\fIComplete Winner\fR.
|
||||
But even after finding the artifact, the player may wish to continue
|
||||
further to match wits with an \fIarch-devil\fR, \fIdemon prince\fR, or even a
|
||||
\fIdeity\fR found far down in the dungeon.
|
||||
Defeating such a creature will gain the player many experience points,
|
||||
the basis for scoring in Rogue.
|
||||
.P
|
||||
It is very difficult to return from the \fIDungeons of Doom\fR.
|
||||
Few people ever make it out alive.
|
||||
Should this unlikely event occur, the player would be proclaimed a
|
||||
complete winner and handsomely rewarded for any booty removed from the
|
||||
dungeon.
|
||||
.H 1 "CHARACTER CLASSES"
|
||||
Before placing the player in the dungeon, the game requests the player
|
||||
to select what type of character they would like to be:~ a fighter, a magic user, a cleric,
|
||||
a druid, a thief, a paladin, a ranger, a monk, or an assassin.
|
||||
.H 2 "The Fighter"
|
||||
A fighter is very strong and will have a high strength rating.
|
||||
This great strength gives a fighter the best odds of
|
||||
winning a battle with a monster.
|
||||
At high experience levels the \fIfighter\fR also gets to attack
|
||||
multiple times in a single turn.
|
||||
This obviously further increases his chances at winning battles.
|
||||
Intrinsic to the fighter class is a robustness which results in
|
||||
1 to 12 extra hit points for every new experience
|
||||
level.
|
||||
.H 2 "The Magician"
|
||||
A Magician is able to "cast" spells.
|
||||
The number and variety of spells increases as
|
||||
the magician gains experience and intelligence.
|
||||
Magic users are not as hearty as fighters;
|
||||
they receive 1 to 6 extra hit
|
||||
points for every new experience level.
|
||||
.H 2 "The Cleric"
|
||||
A cleric is able to "pray" to his god for help.
|
||||
The number and variety of prayers which the gods are willing to grant to
|
||||
a cleric increase as the cleric gains experience and wisdom.
|
||||
.P
|
||||
Because of their religious nature, clerics can also affect the "undead"
|
||||
beings, like \fIzombies\fR and \fIghouls\fR, which became monsters after they
|
||||
died.
|
||||
If an "undead" creature is next to a cleric, the cleric may try
|
||||
to turn it and cause it to flee.
|
||||
If the cleric is sufficiently powerful relative to the monster,
|
||||
the cleric will destroy it.
|
||||
This ability increases as the character gains experience levels.
|
||||
.P
|
||||
Clerics can gain from 1 to 8 extra hit points on
|
||||
reaching a new experience level.
|
||||
.H 2 "The Druid"
|
||||
The druid is a cleric of sorts but worships nature rather than a god.
|
||||
The druid is able to "chant" and thereby recieve certain types
|
||||
of spells. Most of the chants are targeted more towards the
|
||||
elements and nature.
|
||||
.P
|
||||
Druids gain from 1 to 8 hit points when they gain an experience level.
|
||||
.H 2 "The Thief"
|
||||
A thief is exceptionally dextrous and has a good chance to
|
||||
set a trap or rob a monster.
|
||||
.P
|
||||
By their nature, thieves can automatically detect all the gold on the
|
||||
current level of the dungeon.
|
||||
They are also good at detecting hidden traps.
|
||||
Because thieves slink along, they are not as likely as other characters
|
||||
to wake sleeping monsters.
|
||||
If a \fIthief\fR manages to sneak up on a creature without waking it, he
|
||||
will get a chance to \fIbackstab\fR the monster. When this is done,
|
||||
the damage done by the \fIthief\fR greatly increases based on his experience
|
||||
level.
|
||||
.P
|
||||
Thieves gain from 1 to 6 extra hit points from a new experience level.
|
||||
.H 2 "The Paladin"
|
||||
The paladin is a type of holy warrior. Somewhat of a cross between a
|
||||
fighter and a cleric. He is able to pray and turn undead as a cleric,
|
||||
(but to a lesser degree) but fights as a fighter. He is on the side of
|
||||
all that is good and righteous. Therefore he would never attack a
|
||||
creature that would not attack him first. If he does kill a non-violent
|
||||
creature inadvertantly he will feel "uneasy" and his god may retaliate
|
||||
by making him a mere fighter.
|
||||
.P
|
||||
Paladins gain 1 to 10 hit points per experience level.
|
||||
.H 2 "The Ranger"
|
||||
The ranger is somewhat of a cross between a druid and a fighter. He
|
||||
too is on the side of righteousness and good. Therefore, the same
|
||||
same restrictions apply to his as they do to a paladin. The ranger
|
||||
can "chant" and "cast" but to a lesser degree than the druid and
|
||||
magician.
|
||||
.P
|
||||
Rangers gain 1 to 8 hit points per experience level.
|
||||
.H 2 "The Monk"
|
||||
The Monk is a martial arts expert. He wears no armor but has
|
||||
an effective armor class based on his ability to dodge attacks.
|
||||
He does not need a weapon in combat for his hands and feet are
|
||||
a formidable weapon. His ability to dodge and use his hands
|
||||
as weapons increases as he gains in level.
|
||||
.P
|
||||
Monks gain 1 to 6 hit points per experience level.
|
||||
.H 2 "The Assassin"
|
||||
The assassin is a person trained in the art of killing people
|
||||
by surprise. He has most of the abilities of the thief except
|
||||
the "backstab". Instead, the assassin has the chance to kill
|
||||
an opponent outright with one strike. He is also a ruthless
|
||||
character and trained in the use of poison. He can recognize
|
||||
poison on sight and can coat his weapon with it thereby making
|
||||
his next attack an exceptionally lethal one.
|
||||
.P
|
||||
Assassins gain 1 to 6 hit points per experience level.
|
||||
.H 1 "ATTRIBUTES"
|
||||
.H 2 "Intelligence"
|
||||
Intelligence is the primary attribute associated with casting
|
||||
spells. With higher intelligence comes the knowledge of more
|
||||
spells, the ability to cast more spells, and faster recovery
|
||||
of spells that have been cast.
|
||||
.H 2 "Strength"
|
||||
This is, of course, the measure of a character's physical strength.
|
||||
With higher strength a character can carry more, cause more damage
|
||||
when striking, have a better chance to strike an opponent, and
|
||||
move about more quickly when carrying a load.
|
||||
.H 2 "Wisdom"
|
||||
Wisdom is the primary attribute associated with Praying
|
||||
to a god. With higher wisdom comes the knowledge of more
|
||||
prayers, the ability to pray more often, and faster recovery
|
||||
of prayer ability.
|
||||
.H 2 "Dexterity"
|
||||
Dexterity is a measure of a character's agility. With higher dexterity
|
||||
a character is harder to hit, can hit a opponent more easily, and
|
||||
can move about more quickly when carrying a load.
|
||||
.H 2 Constitution
|
||||
Every character has a constitution rating.
|
||||
A character with an exceptionally good constitution will gain more than
|
||||
the normal amount of hit points associated with the character's class
|
||||
when the character reaches a new experience level. Exceptional constitution
|
||||
also provides better protection versus poison-based attacks and diseases.
|
||||
.H 2 "Charisma"
|
||||
Charisma is a measure of a characters looks and general likeableness.
|
||||
It effects transactions when trying to purchase things.
|
||||
.H 2 "Experience Levels"
|
||||
Characters gain experience for killing monsters, stealing from monsters,
|
||||
and turning monsters.
|
||||
Each character class has a set of thresholds associated with it.
|
||||
When a character reaches a threshold, the character attains the next
|
||||
experience level.
|
||||
This new level brings extra hit points and a greater chance of success
|
||||
in performing the abilities associated with the character's class.
|
||||
For example, magicians receive new spells, and clerics receive new prayers.
|
||||
.P
|
||||
.H 2 "Allocating Attributes"
|
||||
The player starts with 72 "attribute points" to create a character and
|
||||
can distribute them in any manner among the six attributes described
|
||||
above.
|
||||
When prompting the player for each attribute, the game displays the
|
||||
minimum and maximum allowable values for that attribute.
|
||||
The player can type a backspace (control-H) to go back and change
|
||||
a value; typing an escape (ESC) sets the remaining attributes to
|
||||
the maximum value possible given the remaining attribute points.
|
||||
.H 1 "THE SCREEN"
|
||||
During the normal course of play, the screen consists of three separate
|
||||
sections:~ the top line of the terminal, the bottom two lines of the
|
||||
terminal, and the remaining middle lines.
|
||||
The top line reports actions which occur during the game, the middle
|
||||
section depicts the dungeon, and the bottom lines describe the player's
|
||||
current condition.
|
||||
.H 2 "The Top Line"
|
||||
Whenever anything happens to the player, such as finding a scroll or
|
||||
hitting or being hit by a monster, a short report of the occurrence
|
||||
appears on the top line of the screen.
|
||||
When such reports occur quickly, one right after another,
|
||||
the game displays the notice followed by the prompt '\(emMore\(em.'~
|
||||
After reading this notice, the player can press a space to display
|
||||
the next message.
|
||||
At such a point, the game ignores all commands until the player presses
|
||||
a space.
|
||||
.H 2 "The Dungeon Section"
|
||||
The large middle section of the screen displays the player's surroundings using
|
||||
the following symbols:
|
||||
.tr ~~
|
||||
.VL 10
|
||||
.LI |
|
||||
A wall of a room.
|
||||
.LI -
|
||||
A wall of a room.
|
||||
.LI *
|
||||
A pile of gold.
|
||||
.LI %
|
||||
A way to the next level.
|
||||
.LI +
|
||||
A doorway.
|
||||
.LI .
|
||||
The floor in a room.
|
||||
.LI @
|
||||
The player.
|
||||
.LI _
|
||||
The player, when invisible.
|
||||
.LI #
|
||||
The floor in a passageway.
|
||||
.LI !
|
||||
A flask containing a potion.
|
||||
.LI ?
|
||||
A sealed scroll.
|
||||
.LI :
|
||||
Some food.
|
||||
.LI )
|
||||
A weapon.
|
||||
.LI \
|
||||
Solid rock (denoted by a space).
|
||||
.LI ]
|
||||
Some armor.
|
||||
.LI ;
|
||||
A miscellaneous magic item
|
||||
.LI ,
|
||||
An artifact
|
||||
.LI =
|
||||
A ring.
|
||||
.LI /
|
||||
A wand or a staff.
|
||||
.LI ^
|
||||
The entrance to a trading post
|
||||
.LI >
|
||||
A trapdoor leading to the next level
|
||||
.LI {
|
||||
An arrow trap
|
||||
.LI $
|
||||
A sleeping gas trap
|
||||
.LI }
|
||||
A beartrap
|
||||
.LI ~
|
||||
A trap that teleports you somewhere else
|
||||
.LI \`
|
||||
A poison dart trap
|
||||
.LI \fR"\fR
|
||||
A shimmering magic pool
|
||||
.LI \'
|
||||
An entrance to a maze
|
||||
.LI $
|
||||
Any magical item. (During magic detection)
|
||||
.LI >
|
||||
A blessed magical item. (During magic detection)
|
||||
.LI <
|
||||
A cursed magical item. (During magic detection)
|
||||
.LI A\ letter
|
||||
A monster.
|
||||
Note that a given letter may signify multiple monsters,
|
||||
depending on the level of the dungeon.
|
||||
The player can always identify a current monster by using
|
||||
the identify command ('\fB/\fR').
|
||||
.LE
|
||||
.tr ~
|
||||
.H 2 "The Status Section"
|
||||
The bottom two lines of the screen describe the player's current status.
|
||||
The first line gives the player's characteristics:
|
||||
.BL
|
||||
.LI
|
||||
Intelligence (\fBInt\fR)
|
||||
.LI
|
||||
Strength (\fBStr\fR)
|
||||
.LI
|
||||
Wisdom (\fBWis\fR)
|
||||
.LI
|
||||
Dexterity (\fBDxt\fR)
|
||||
.LI
|
||||
Constitution (\fBConst\fR)
|
||||
.LI
|
||||
Charisma (\fBChar\fR)
|
||||
.LI
|
||||
Encumberance (\fBCarry\fR)
|
||||
.LE
|
||||
.P
|
||||
Intelligence, strength, wisdom, dexterity, charisma, and constitution have a
|
||||
normal maximum of 25, but can be higher when augmented by a ring.
|
||||
Encumberance is a measurement of how much the player can carry versus
|
||||
how much he is currently carrying. The more you carry relative to your
|
||||
maximum causes you to use more food.
|
||||
.P
|
||||
The second status line provides the following information:
|
||||
.BL
|
||||
.LI
|
||||
The current level (\fBLvl\fR) in the dungeon. This number increases as the
|
||||
player goes further down.
|
||||
.LI
|
||||
The player's current number of hit points (\fBHp\fR), followed in parentheses
|
||||
by the player's current maximum number of hit points.
|
||||
Hit points express the player's health.
|
||||
As a player heals by resting, the player's current hit points gradually
|
||||
increase until reaching the current maximum.
|
||||
This maximum increases each time a player attains a new experience level.
|
||||
If the player's current hit points reach 0, the player dies.
|
||||
.LI
|
||||
The player's armor class (\fBAc\fR).
|
||||
This number describes the amount of protection provided by the armor, cloaks,
|
||||
and/or rings currently worn by the player.
|
||||
It is also affected by high or low dexterity.
|
||||
Wearing no armor is equivalent to an armor class of 10.
|
||||
The protection level increases as the armor class decreases.
|
||||
.LI
|
||||
The player's current experience level (\fBExp\fR) followed by the player's
|
||||
experience points.
|
||||
The player can gain experience points by killing monsters, successfully
|
||||
stealing from monsters, and turning monsters.
|
||||
When a player gains enough experience points to surpass a threshold that
|
||||
depends on the player's character type, the player reaches a new
|
||||
experience level.
|
||||
A new experience level brings extra hit points and possibly added
|
||||
abilities, such as a new spell for a magician or a new prayer for
|
||||
a cleric.
|
||||
.LI
|
||||
A description of the player's character.
|
||||
This description depends on the player's character type and experience
|
||||
level.
|
||||
.LE
|
||||
.H 1 COMMANDS
|
||||
A player can invoke most Rogue commands by typing a single character.
|
||||
Some commands, however, require a direction, in which case the player
|
||||
types the command character followed by a directional command.
|
||||
Many commands can be prefaced by a number, indicating how many times
|
||||
the command should be executed.
|
||||
.P
|
||||
When the player invokes a command referring to an item in the player's
|
||||
pack (such as reading a scroll), the game prompts for the item.
|
||||
The player should then type the letter associated with the item, as
|
||||
displayed by the \fBinventory\fR command.
|
||||
Typing a '*' at this point produces a list of the eligible items.
|
||||
.P
|
||||
Rogue understands the following commands:~
|
||||
.VL 4
|
||||
.LI ?
|
||||
Preceding a command by a '\fB?\fR' produces a brief explanation of the command.
|
||||
The command '\fB?*\fR' gives an explanation of all the commands.
|
||||
.LI /
|
||||
Preceding a symbol by a '\fB/\fR' identifies the symbol.
|
||||
.LI =
|
||||
Clarify.
|
||||
After typing an '\fB=\fR' sign, the player can use the movement keys to
|
||||
position the cursor anywhere on the current level.
|
||||
As long as the player can normally see the selected position, Rogue will
|
||||
identify whatever is at that space.
|
||||
Examples include a \fIsleeping giant rat\fR, a \fIblue potion\fR, and a \fIfood
|
||||
ration\fR.
|
||||
.LI h
|
||||
Move one position to the left.
|
||||
.LI j
|
||||
Move one position down.
|
||||
.LI k
|
||||
Move one position up.
|
||||
.LI l
|
||||
Move one position to the right.
|
||||
.LI y
|
||||
Move one position to the top left.
|
||||
.LI u
|
||||
Move one position to the top right.
|
||||
.LI b
|
||||
Move one position to the bottom left.
|
||||
.LI n
|
||||
Move one position to the bottom right.
|
||||
.LI H
|
||||
Run to the left until reaching something interesting.
|
||||
.LI J
|
||||
Run down until reaching something interesting.
|
||||
.LI K
|
||||
Run up until reaching something interesting.
|
||||
.LI L
|
||||
Run to the right until reaching something interesting.
|
||||
.LI Y
|
||||
Run to the top left until reaching something interesting.
|
||||
.LI U
|
||||
Run to the top right until reaching something interesting.
|
||||
.LI B
|
||||
Run to the bottom left until reaching something interesting.
|
||||
.LI N
|
||||
Run to the bottom right until reaching something interesting.
|
||||
.LI t
|
||||
This command prompts for an object from the players pack.
|
||||
The player then \fBt\fRhrows the object in the specified direction.
|
||||
.LI f
|
||||
When this command precedes a directional command, the player moves
|
||||
in the specified direction until passing something interesting.
|
||||
.LI z
|
||||
This command prompts for a wand or staff from the player's pack and
|
||||
\fBz\fRaps it in the specified direction.
|
||||
.LI >
|
||||
Go down to the next level.
|
||||
.LI <
|
||||
Go up to the next level.
|
||||
.LI s
|
||||
\fBS\fRearch for a secret door or a trap in the circle surrounding the player.
|
||||
.LI .
|
||||
This command (a dot) causes the player to rest a turn.
|
||||
.LI i
|
||||
Display an \fBi\fRnventory of the player's pack.
|
||||
.LI I
|
||||
This command prompts for an item from the player's pack and displays
|
||||
the \fBi\fRnventory information for that item.
|
||||
.LI q
|
||||
\fBQ\fRuaff a potion from the player's pack.
|
||||
.LI r
|
||||
\fBR\fRead a scroll from the player's pack.
|
||||
.LI e
|
||||
\fBE\fRat some food from the player's pack.
|
||||
.LI w
|
||||
\fBW\fRield a weapon from the player's pack.
|
||||
.LI W
|
||||
\fBW\fRear some armor, ring, or miscellaneous magic item from the player's pack.
|
||||
The player can wear a maximum of eight rings.
|
||||
.LI T
|
||||
\fBT\fRake off whatever the player is wearing.
|
||||
.LI ^U
|
||||
\fBU\fRse a magic item in the player's pack.
|
||||
.LI d
|
||||
\fBD\fRrop an item from the player's pack.
|
||||
.LI P
|
||||
\fBP\fRick up the items currently under the player.
|
||||
.LI ^N
|
||||
When the player types this command, Rogue prompts for a monster or an item
|
||||
from the player's pack and a one-line \fBn\fRame.
|
||||
For monsters, the player can use the movement keys to position the cursor
|
||||
over the desired monster, and Rogue will use the given \fBn\fRame to refer
|
||||
to that monster.
|
||||
For items, Rogue gives all similar items (such as all the blue potions)
|
||||
the specified \fBn\fRame.
|
||||
.LI m
|
||||
When the player types this command, Rogue prompts for an item from the
|
||||
player's pack and a one-line name.
|
||||
Rogue then \fBm\fRarks the specified item with the given name.
|
||||
.LI o
|
||||
Typing this command causes Rogue to display all the settable \fBo\fRptions.
|
||||
The player can then merely examine the options or change any or all of them.
|
||||
.LI C
|
||||
This command, restricted to magicians and rangers
|
||||
produces a listing of the current supply of spells.
|
||||
The player can select one of the displayed spells and, if the player's
|
||||
energy level is sufficiently high, \fBC\fRast it.
|
||||
The more complicated the spell, the more energy it takes.
|
||||
.LI c
|
||||
This command, restricted to druids and rangers
|
||||
produces a listing of the current supply of chants.
|
||||
The player can select one of the displayed chants and, if the player's
|
||||
energy level is sufficiently high, \fBc\fRhant it.
|
||||
The more complicated the spell, the more energy it takes.
|
||||
.LI p
|
||||
This command, restricted to clerics and paladins,
|
||||
produces a listing of the character's known \fBp\fRrayers.
|
||||
The player can then offer one of these prayers to the character's deity.
|
||||
Deities are not known for favoring characters which continually pray
|
||||
to them, and they are most likely to answer the least "ambitious" prayers.
|
||||
.LI a
|
||||
This command is restricted to clerics and paladins
|
||||
must be followed by a directional command.
|
||||
If there is an "undead" monster standing next to the player in the
|
||||
specified direction, there is a chance the player will \fBa\fRffect the
|
||||
monster by causing it to flee or possibly even destroying it.
|
||||
.LI *
|
||||
Count the gold in the player's pack.
|
||||
.LI ^
|
||||
This command sets a trap and is limited to thieves and assassins.
|
||||
If the character is successful, Rogue prompts the player for a type of trap
|
||||
and sets it where the player is standing.
|
||||
.LI G
|
||||
This command is restricted to thieves and assassins.
|
||||
It causes Rogue to display all the gold on the current level.
|
||||
.LI D
|
||||
\fBD\fRip something into a magic pool.
|
||||
.LI ^T
|
||||
This command is restricted to thieves and assassins.
|
||||
It must be followed by a directional command.
|
||||
If there is a monster standing next to the player in the specified direction,
|
||||
the player tries to \fBs\fRteal an item from the monster's pack.
|
||||
If the player is successful, the monster does not notice anything, but if
|
||||
the player is unsuccessful, there is a chance the monster will wake up.
|
||||
.LI ^L
|
||||
Redraw the screen.
|
||||
.LI ^R
|
||||
\fBR\fRepeat the last message that was displayed on the top line of the screen.
|
||||
.LI ^[
|
||||
Typing an escape will usually cause Rogue to cancel the current command.
|
||||
.LI v
|
||||
Print the current Rogue \fBv\fRersion number.
|
||||
.LI !
|
||||
Escape to the shell.
|
||||
.LI S
|
||||
Quit and \fBs\fRave the game for resumption at a later time.
|
||||
.LI Q
|
||||
\fBQ\fRuit without saving the game.
|
||||
.LE
|
||||
.H 1 "IMPLICIT COMMANDS"
|
||||
There is no "attack" command.
|
||||
If a player wishes to attack a monster, the player simply tries to
|
||||
move onto the spot where the monster is standing.
|
||||
The game then assumes that the player wishes to attack the monster
|
||||
with whatever weapon the player is wielding.
|
||||
.P
|
||||
When the player moves onto an item, the game automatically places the
|
||||
object into the player's pack.
|
||||
If there is no room left in the pack, the game announces that fact and
|
||||
leaves the item on the floor.
|
||||
.H 1 TIME
|
||||
All actions except for purely bookkeeping commands, such as taking an
|
||||
inventory, take time.
|
||||
The amount of time varies with the command.
|
||||
Swinging a weapon, for example, takes more time than simply moving;
|
||||
so a monster could move several spaces in the time it takes the player
|
||||
to make one attack.
|
||||
The time it takes to swing a weapon also varies based on the bulk of the
|
||||
weapon, and the time it takes to simply move a space varies with the type
|
||||
of armor worn.
|
||||
Movement is always faster when flying.
|
||||
.P
|
||||
Since actions take time, some of them can be disrupted.
|
||||
If the player is casting a spell, for example, and gets hit before finishing
|
||||
it, the spell is lost.
|
||||
Similarly, the player might choke if hit while trying to eat.
|
||||
Of course, the same rule applies when the player hits a monster.
|
||||
.P
|
||||
Magical hasting (or slowing) will decrease (or increase) the time it takes
|
||||
to perform an action.
|
||||
.H 1 LIGHT
|
||||
Some rooms in the dungeon possess a natural light source.
|
||||
In other rooms and in corridors the player can see only those things
|
||||
within a one space radius from the player.
|
||||
These dark rooms can be lit with magical light or by a \fIfire beetle\fR.
|
||||
.H 1 "WEAPONS AND ARMOR"
|
||||
The player can wield exactly one weapon at a time.
|
||||
When the player attacks a monster, the amount of damage depends on the
|
||||
particular weapon the player is wielding.
|
||||
To fire a projectile weapon, such as a crossbow or a short bow, the player
|
||||
should wield the bow and "throw" the bolt or arrow at the monster.
|
||||
.P
|
||||
A weapon may be cursed or blessed, affecting the likelihood of hitting a
|
||||
monster with the weapon and the damage the weapon will inflict on the monster.
|
||||
If the player has identified a weapon, the "to hit" and "to damage" bonuses
|
||||
appear in that order before the weapon's name in an inventory listing.
|
||||
A positive bonus indicates a blessed weapon, and a negative bonus usually
|
||||
indicates a cursed weapon.
|
||||
The player cannot release a cursed weapon.
|
||||
.P
|
||||
Without any armor the player has an armor class of 10.
|
||||
The lower the player's armor class, the harder it is for a monster to hit
|
||||
the player, so
|
||||
wearing armor can improve the player's armor class.
|
||||
A cursed suit of armor, however, offers poor protection and may sometimes be
|
||||
worse than no armor at all.
|
||||
.P
|
||||
After the player has identified a suit of armor, the protection bonus appears
|
||||
before the armor's name in an inventory listing.
|
||||
If the bonus is positive the armor is blessed, and if it is negative, the
|
||||
armor is usually cursed.
|
||||
The player cannot remove a cursed suit of armor.
|
||||
.P
|
||||
Some monsters can corrode armor when they hit it.
|
||||
If such a monster hits the player when the player is wearing metal armor,
|
||||
the armor loses some of its protection value, but the corrosion does not
|
||||
curse the armor.
|
||||
This corrosive property can also apply to weapons when the player hits
|
||||
such a monster.
|
||||
.H 1 "POTIONS AND SCROLLS"
|
||||
The player can frequently find potions and scrolls in the dungeon.
|
||||
In any given dungeon, the player can distinguish among the different types
|
||||
of potions by a potion's color and among the different types of scrolls
|
||||
by a scroll's name.
|
||||
Quaffing a potion or reading a scroll usually causes some magical occurrence.
|
||||
Most potions and scrolls may be cursed or blessed.
|
||||
.H 1 RINGS
|
||||
The player can wear a maximum of eight rings, and
|
||||
they have a magical effect on the player as long as they are worn.
|
||||
Some rings also speed up the player's metabolism, making the player require
|
||||
food more often.
|
||||
Many rings can be cursed or blessed, and the player cannot remove a
|
||||
cursed ring.
|
||||
The player can distinguish among different types of rings by a ring's jewel.
|
||||
.H 1 "WANDS AND STAVES"
|
||||
Wands and staves affect the player's environment.
|
||||
The player can zap a wand or staff at something and perhaps shoot a bolt
|
||||
of lightning at it or teleport it away.
|
||||
All wands or staves of the same type are constructed with the same type of wood.
|
||||
Some wands and staves may be cursed or blessed.
|
||||
.H 1 FOOD
|
||||
The player must be careful not to run out of food since moving through the
|
||||
dungeon fighting monsters consumes a lot of energy.
|
||||
Starving results in the player's fainting for increasingly longer periods
|
||||
of time, during which any nearby monster can attack the player freely.
|
||||
.P
|
||||
Food comes in the form of standard rations and as a variety of berries.
|
||||
Some berries have side effects in addition to satisfying one's hunger.
|
||||
.H 1 GOLD
|
||||
Gold has one use in a dungeon:~ buying things.
|
||||
One can buy things in two ways, either in a \fItrading post\fR or from a
|
||||
\fIquartermaster\fR.
|
||||
A trading post is a place that sometimes occurs "between levels" of the
|
||||
dungeon and can be entered by stepping on the entrance.
|
||||
A quartermaster is a person who will sometimes appear and
|
||||
will try to sell the player some of his wares.
|
||||
These wares are never cursed and frequently blessed, though blessed goods
|
||||
cost more than normal goods.
|
||||
If the player chooses to buy one of the quartermaster's items, the
|
||||
quartermaster trades the item for the specified amount of gold and
|
||||
disappears.
|
||||
Attacking a quartermaster causes him to vanish without offering
|
||||
a trade.
|
||||
.P
|
||||
The player starts the game in a trading post with a class-dependent allotment
|
||||
of gold.
|
||||
Although there are restrictions on the use of some items (eg. only fighters,
|
||||
paladins, and rangers can wield two-handed swords), the market will happily
|
||||
sell the player anything that he can afford.
|
||||
|
||||
.H 1 "MISCELLANEOUS MAGIC ITEMS"
|
||||
Miscellaneous items such as a pair of boots or a book may be found within the
|
||||
dungeon.
|
||||
These items can usually be used to the player's advantage (assuming they are
|
||||
not cursed).
|
||||
Some of these items can be worn, such as a cloak, while others are to be used,
|
||||
such as a book.
|
||||
.H 1 "ARTIFACTS"
|
||||
Some monsters down in the depths of the dungeon carry unique artifacts.
|
||||
The game begins as a quest to retrieve one of these items.
|
||||
Each artifact appears only on its owner's person.
|
||||
These items also can usually be used to the player's advantage. However,
|
||||
care must be taken when handling them for they are intelligent and will
|
||||
reject mishandling or abuse. These items consume food and merely carrying
|
||||
them will result in increased food use.
|
||||
.H 1 TRAPS
|
||||
A variety of traps, including trap doors, bear traps, and sleeping traps, are
|
||||
hidden in the dungeon.
|
||||
They remain hidden until sprung by a monster or the player.
|
||||
A sprung trap continues to function, but since it is visible, an intelligent
|
||||
monster is not likely to tread on it.
|
||||
.H 1 "THE MONSTERS"
|
||||
Each monster except for the merchant \fIquartermaster\fR appears in
|
||||
a limited range of dungeon levels.
|
||||
All monsters of the same type share the same abilities;
|
||||
all \fIgiant rats\fR, for example, can give the player a disease, and
|
||||
all \fIjackalweres\fR can put the player to sleep.
|
||||
Monsters of the same type can vary, however, such that one \fIkobold\fR
|
||||
may be much more difficult to kill than another one.
|
||||
In general, the more difficult it is to kill a monster, the more
|
||||
experience points the monster is worth.
|
||||
.P
|
||||
Most monsters attack by biting and clawing, but some monsters carry
|
||||
weapons, including such projectile weapons as short bows and crossbows,
|
||||
and some monsters have breath weapons.
|
||||
Some monsters even use magical items, such as wands.
|
||||
Monsters with distance weapons or magic can attack the player from across a room
|
||||
or down a corridor.
|
||||
.P
|
||||
Some monsters are more intelligent than others, and the more intelligent
|
||||
a monster, the more likely that the monster will run away if it is about
|
||||
to die.
|
||||
A fleeing monster will not attack the player unless cornered.
|
||||
.P
|
||||
It is sometimes possible to enlist a monster's aid.
|
||||
Reading a \fIcharm monster\fR scroll, for example, or singing a \fIcharm
|
||||
monster\fR chant can make a monster believe the player is its friend.
|
||||
A charmed monster will fight hostile monsters for the player as long as they are
|
||||
not of its race.
|
||||
.P
|
||||
As the player moves down in the dungeon, the monsters get more powerful.
|
||||
Deep down in the dungeon there exist some one-of-a-kind monsters.
|
||||
These monsters are greatly feared.
|
||||
However, once a "unique monster" is killed, the player will not find
|
||||
another in the current dungeon.
|
||||
.H 1 OPTIONS
|
||||
Rogue has several options which may be set by the player:~
|
||||
.VL 7
|
||||
.LI \fBterse\fR
|
||||
Setting this Boolean option results in shorter messages appearing on
|
||||
the top line of the screen.
|
||||
.LI \fBjump\fR
|
||||
Setting this Boolean option results in waiting until the player has
|
||||
finished running to draw the player's path.
|
||||
Otherwise the game always displays the path one step at a time.
|
||||
.LI \fBstep\fR
|
||||
Setting this Boolean option results in most listings, such as an inventory,
|
||||
appearing one item at a time on the top line of the screen.
|
||||
When this option is not set, the game clears the screen, displays the
|
||||
list, and then redraws the dungeon.
|
||||
.LI \fBflush\fR
|
||||
Setting this Boolean option results in flushing all typeahead (pending) commands
|
||||
when the player encounters a monster.
|
||||
.LI \fBaskme\fR
|
||||
Setting this Boolean option results in the game prompting the player for a
|
||||
name upon encountering a new type of scroll, potion, ring, staff, or wand.
|
||||
.LI \fBpickup\fR
|
||||
This option specifys whether items should be picked up automatically as the
|
||||
rogue steps over them.
|
||||
In the non-automatic mode, the player may still pick up items via the
|
||||
pickup (P) command.
|
||||
The option defaults to true.
|
||||
.LI \fBname\fR
|
||||
This string is the player's name and defaults to the player's account name.
|
||||
.LI \fBfile\fR
|
||||
This string, which defaults to rogue.save, specifies the file to use for
|
||||
saving the game.
|
||||
.LI \fBscore\fR
|
||||
This string identifies the top-twenty score file to use for the game.
|
||||
.LI \fBclass\fR
|
||||
This option specifies the character class of the rogue.
|
||||
It can be set only in the ROGUEOPTS environment variable.
|
||||
.LI \fBquested~item\fR
|
||||
.br
|
||||
This option is set by the game at the start and cannot be reset by the player.
|
||||
It is merely listed to remind the player of his quest.
|
||||
.LE
|
||||
.P
|
||||
The player can set options at the beginning of a game via the ROGUEOPTS
|
||||
environment variable.
|
||||
Naming a Boolean option sets it, and preceding the Boolean option name by
|
||||
"no" clears it.
|
||||
The syntax "stringoption=name" sets a string option to "name."~
|
||||
So setting ROGUEOPTS to
|
||||
"terse, jump, nostep, flush, askme, name=Ivan~the~Terrible"
|
||||
would set the \fIterse, jump, flush\fR, and \fIaskme\fR Boolean options,
|
||||
clear the \fIstep\fR Boolean option, set the player's
|
||||
\fIname\fR to "Ivan the Terrible," and use the defaults for
|
||||
the \fIsave file\fR and the \fIscore file\fR.
|
||||
.P
|
||||
The player may change an option at any time during the game
|
||||
via the \fBoption\fR command, which results in a listing of
|
||||
the current options.
|
||||
Typing a new value changes the option, a RETURN moves to the
|
||||
next option, a '-' moves to the previous option, and an ESCAPE
|
||||
returns the player to the dungeon.
|
||||
.H 1 SCORING
|
||||
The player receives experience points for stealing items from
|
||||
monsters, turning monsters (a clerical ability), and killing
|
||||
monsters.
|
||||
When the player gets killed, the player's score equals the player's
|
||||
experience points.
|
||||
A player who quits gets a score equal to the player's experience
|
||||
points and gold.
|
||||
If the player makes it back up out of the dungeon, the player's
|
||||
score equals the player's experience points plus the gold the
|
||||
player carried and the gold received from selling the player's
|
||||
possessions.
|
||||
.P
|
||||
Rogue maintains a list of the top twenty scores to date, together
|
||||
with the name of the player obtaining the score, the level where
|
||||
the player finished, and the manner in which the player ended the
|
||||
game.
|
||||
As an installation option, the game may record only one entry per
|
||||
character type and login;
|
||||
this restriction encourages a greater number of different players
|
||||
in the scorechart.
|
||||
.H 1 ACKNOWLEDGEMENTS
|
||||
This version of Rogue is based on a version developed at the
|
||||
University of California.
|
||||
1122
arogue7/arogue77.doc
Normal file
1122
arogue7/arogue77.doc
Normal file
File diff suppressed because it is too large
Load diff
1328
arogue7/arogue77.html
Normal file
1328
arogue7/arogue77.html
Normal file
File diff suppressed because it is too large
Load diff
21
arogue7/arogue77.sln
Normal file
21
arogue7/arogue77.sln
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
Microsoft Visual Studio Solution File, Format Version 7.00
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "arogue77", "arogue77.vcproj", "{D95CFDAC-E66E-47D3-87B7-F76149F6A51D}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
ConfigName.0 = Debug
|
||||
ConfigName.1 = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectDependencies) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{D95CFDAC-E66E-47D3-87B7-F76149F6A51D}.Debug.ActiveCfg = Debug|Win32
|
||||
{D95CFDAC-E66E-47D3-87B7-F76149F6A51D}.Debug.Build.0 = Debug|Win32
|
||||
{D95CFDAC-E66E-47D3-87B7-F76149F6A51D}.Release.ActiveCfg = Release|Win32
|
||||
{D95CFDAC-E66E-47D3-87B7-F76149F6A51D}.Release.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
270
arogue7/arogue77.vcproj
Normal file
270
arogue7/arogue77.vcproj
Normal file
|
|
@ -0,0 +1,270 @@
|
|||
<?xml version="1.0" encoding = "Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.00"
|
||||
Name="arogue77"
|
||||
ProjectGUID="{D95CFDAC-E66E-47D3-87B7-F76149F6A51D}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../pdcurses"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;DUMP"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="5"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
DisableSpecificWarnings="4013;4033;4716"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="shfolder.lib pdcurses.lib"
|
||||
OutputFile="$(OutDir)/arogue77.exe"
|
||||
LinkIncremental="2"
|
||||
AdditionalLibraryDirectories="../pdcurses"
|
||||
IgnoreAllDefaultLibraries="FALSE"
|
||||
IgnoreDefaultLibraryNames="LIBC.LIB"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/arogue77.pdb"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
InlineFunctionExpansion="1"
|
||||
OmitFramePointers="TRUE"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="4"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/arogue77.exe"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
|
||||
<File
|
||||
RelativePath="actions.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="chase.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="command.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="daemon.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="daemons.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="eat.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="effects.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="encumb.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="fight.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="init.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="io.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="list.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="main.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="maze.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="mdport.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="misc.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="monsters.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="move.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="new_level.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="options.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="outside.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="pack.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="passages.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="player.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="potions.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rings.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rip.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rogue.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rooms.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="save.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="scrolls.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="state.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="sticks.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="things.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="trader.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="util.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="vers.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="weapons.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="wear.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="mach_dep.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="network.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="LICENSE.TXT">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="Makefile">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="aguide.mm">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="arogue77.doc">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="arogue77.html">
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
928
arogue7/chase.c
Normal file
928
arogue7/chase.c
Normal file
|
|
@ -0,0 +1,928 @@
|
|||
/*
|
||||
* chase.c - Code for one object to chase another
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Code for one object to chase another
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include "curses.h"
|
||||
#include "rogue.h"
|
||||
#define MAXINT INT_MAX
|
||||
#define MININT INT_MIN
|
||||
|
||||
|
||||
/*
|
||||
* Canblink checks if the monster can teleport (blink). If so, it will
|
||||
* try to blink the monster next to the player.
|
||||
*/
|
||||
|
||||
bool
|
||||
can_blink(tp)
|
||||
register struct thing *tp;
|
||||
{
|
||||
register int y, x, index=9;
|
||||
coord tryp; /* To hold the coordinates for use in diag_ok */
|
||||
bool spots[9], found_one=FALSE;
|
||||
|
||||
/*
|
||||
* First, can the monster even blink? And if so, there is only a 50%
|
||||
* chance that it will do so. And it won't blink if it is running or
|
||||
* held.
|
||||
*/
|
||||
if (off(*tp, CANBLINK) || (on(*tp, ISHELD)) ||
|
||||
on(*tp, ISFLEE) ||
|
||||
tp->t_action == A_FREEZE ||
|
||||
(rnd(12) < 6)) return(FALSE);
|
||||
|
||||
|
||||
/* Initialize the spots as illegal */
|
||||
do {
|
||||
spots[--index] = FALSE;
|
||||
} while (index > 0);
|
||||
|
||||
/* Find a suitable spot next to the player */
|
||||
for (y=hero.y-1; y<hero.y+2; y++)
|
||||
for (x=hero.x-1; x<hero.x+2; x++, index++) {
|
||||
/* Make sure x coordinate is in range and that we are
|
||||
* not at the player's position
|
||||
*/
|
||||
if (x<0 || x >= cols || index == 4) continue;
|
||||
|
||||
/* Is it OK to move there? */
|
||||
if (step_ok(y, x, NOMONST, tp) &&
|
||||
(!isatrap(mvwinch(cw, y, x)) ||
|
||||
rnd(10) >= tp->t_stats.s_intel ||
|
||||
on(*tp, ISFLY))) {
|
||||
/* OK, we can go here. But don't go there if
|
||||
* monster can't get at player from there
|
||||
*/
|
||||
tryp.y = y;
|
||||
tryp.x = x;
|
||||
if (diag_ok(&tryp, &hero, tp)) {
|
||||
spots[index] = TRUE;
|
||||
found_one = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we found one, go to it */
|
||||
if (found_one) {
|
||||
char rch; /* What's really where the creatures moves to */
|
||||
|
||||
/* Find a legal spot */
|
||||
while (spots[index=rnd(9)] == FALSE) continue;
|
||||
|
||||
/* Get the coordinates */
|
||||
y = hero.y + (index/3) - 1;
|
||||
x = hero.x + (index % 3) - 1;
|
||||
|
||||
/* Move the monster from the old space */
|
||||
mvwaddch(cw, tp->t_pos.y, tp->t_pos.x, tp->t_oldch);
|
||||
|
||||
/* Move it to the new space */
|
||||
tp->t_oldch = CCHAR( mvwinch(cw, y, x) );
|
||||
|
||||
/* Display the creature if our hero can see it */
|
||||
if (cansee(y, x) &&
|
||||
off(*tp, ISINWALL) &&
|
||||
!invisible(tp))
|
||||
mvwaddch(cw, y, x, tp->t_type);
|
||||
|
||||
/* Fix the monster window */
|
||||
mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, ' '); /* Clear old position */
|
||||
mvwaddch(mw, y, x, tp->t_type);
|
||||
|
||||
/* Record the new position */
|
||||
tp->t_pos.y = y;
|
||||
tp->t_pos.x = x;
|
||||
|
||||
/* If the monster is on a trap, trap it */
|
||||
rch = CCHAR( mvinch(y, x) );
|
||||
if (isatrap(rch)) {
|
||||
if (cansee(y, x)) tp->t_oldch = rch;
|
||||
be_trapped(tp, &(tp->t_pos));
|
||||
}
|
||||
}
|
||||
|
||||
return(found_one);
|
||||
}
|
||||
|
||||
/*
|
||||
* Can_shoot determines if the monster (er) has a direct line of shot
|
||||
* at the prey (ee). If so, it returns the direction in which to shoot.
|
||||
*/
|
||||
|
||||
coord *
|
||||
can_shoot(er, ee)
|
||||
register coord *er, *ee;
|
||||
{
|
||||
static coord shoot_dir;
|
||||
|
||||
/*
|
||||
* They must be in the same room or very close (at door)
|
||||
*/
|
||||
if (roomin(er) != roomin(ee) && DISTANCE(er->y,er->x,ee->y,ee->x) > 1)
|
||||
return(NULL);
|
||||
|
||||
/* Do we have a straight shot? */
|
||||
if (!straight_shot(er->y, er->x, ee->y, ee->x, &shoot_dir)) return(NULL);
|
||||
else return(&shoot_dir);
|
||||
}
|
||||
|
||||
/*
|
||||
* chase:
|
||||
* Find the spot for the chaser(er) to move closer to the
|
||||
* chasee(ee). Rer is the room of the chaser, and ree is the
|
||||
* room of the creature being chased (chasee).
|
||||
*/
|
||||
|
||||
chase(tp, ee, rer, ree, flee)
|
||||
register struct thing *tp;
|
||||
register coord *ee;
|
||||
register struct room *rer, *ree;
|
||||
bool flee; /* True if destination (ee) is player and monster is running away
|
||||
* or the player is in a wall and the monster can't get to it
|
||||
*/
|
||||
{
|
||||
int dist, thisdist, monst_dist = MAXINT;
|
||||
register coord *er = &tp->t_pos;
|
||||
struct thing *prey; /* What we are chasing */
|
||||
coord ch_ret; /* Where chasing takes you */
|
||||
char ch, mch;
|
||||
bool next_player = FALSE;
|
||||
|
||||
/*
|
||||
* set the distance from the chas(er) to the chas(ee) here and then
|
||||
* we won't have to reset it unless the chas(er) moves (instead of shoots)
|
||||
*/
|
||||
dist = DISTANCE(er->y, er->x, ee->y, ee->x);
|
||||
|
||||
/*
|
||||
* See if our destination is a monster or player. If so, make "prey" point
|
||||
* to it.
|
||||
*/
|
||||
if (ce(hero, *ee)) prey = &player; /* Is it the player? */
|
||||
else if (tp->t_dest && ce(*(tp->t_dest), *ee)) { /* Is it a monster? */
|
||||
struct linked_list *item;
|
||||
|
||||
/* What is the monster we're chasing? */
|
||||
item = find_mons(ee->y, ee->x);
|
||||
if (item != NULL) prey = THINGPTR(item);
|
||||
else prey = NULL;
|
||||
}
|
||||
else prey = NULL;
|
||||
|
||||
/* We will use at least one movement period */
|
||||
tp->t_no_move = movement(tp);
|
||||
if (on(*tp, ISFLY)) /* If the creature is flying, speed it up */
|
||||
tp->t_no_move /= 2;
|
||||
|
||||
/*
|
||||
* If the thing is confused or it can't see the player,
|
||||
* let it move randomly.
|
||||
*/
|
||||
if ((on(*tp, ISHUH) && rnd(10) < 8) ||
|
||||
(prey && on(*prey, ISINVIS) && off(*tp, CANSEE))) { /* invisible prey */
|
||||
/*
|
||||
* get a valid random move
|
||||
*/
|
||||
tp->t_newpos = *rndmove(tp);
|
||||
dist = DISTANCE(tp->t_newpos.y, tp->t_newpos.x, ee->y, ee->x);
|
||||
}
|
||||
|
||||
/*
|
||||
* Otherwise, find the empty spot next to the chaser that is
|
||||
* closest to the chasee.
|
||||
*/
|
||||
else {
|
||||
register int ey, ex, x, y;
|
||||
int dist_to_old = MININT; /* Dist from goal to old position */
|
||||
|
||||
/*
|
||||
* This will eventually hold where we move to get closer
|
||||
* If we can't find an empty spot, we stay where we are.
|
||||
*/
|
||||
dist = flee ? 0 : MAXINT;
|
||||
ch_ret = *er;
|
||||
|
||||
/* Are we at our goal already? */
|
||||
if (!flee && ce(ch_ret, *ee)) {
|
||||
turn_off(*tp, ISRUN); /* So stop running! */
|
||||
return;
|
||||
}
|
||||
|
||||
ey = er->y + 1;
|
||||
ex = er->x + 1;
|
||||
|
||||
/* Check all possible moves */
|
||||
for (x = er->x - 1; x <= ex; x++) {
|
||||
if (x < 0 || x >= cols) /* Don't try off the board */
|
||||
continue;
|
||||
for (y = er->y - 1; y <= ey; y++) {
|
||||
coord tryp;
|
||||
|
||||
if ((y < 1) || (y >= lines - 2)) /* Don't try off the board */
|
||||
continue;
|
||||
|
||||
/* Don't try the player if not going after the player */
|
||||
if ((flee || !ce(hero, *ee) || on(*tp, ISFRIENDLY)) &&
|
||||
x == hero.x && y == hero.y) {
|
||||
next_player = TRUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
tryp.x = x;
|
||||
tryp.y = y;
|
||||
|
||||
/* Is there a monster on this spot closer to our goal?
|
||||
* Don't look in our spot or where we were.
|
||||
*/
|
||||
if (!ce(tryp, *er) && !ce(tryp, tp->t_oldpos) &&
|
||||
isalpha(mch = CCHAR( mvwinch(mw, y, x) ) )) {
|
||||
int test_dist;
|
||||
|
||||
test_dist = DISTANCE(y, x, ee->y, ee->x);
|
||||
if (test_dist <= 25 && /* Let's be fairly close */
|
||||
test_dist < monst_dist) {
|
||||
/* Could we really move there? */
|
||||
mvwaddch(mw, y, x, ' '); /* Temporarily blank monst */
|
||||
if (diag_ok(er, &tryp, tp)) monst_dist = test_dist;
|
||||
mvwaddch(mw, y, x, mch); /* Restore monster */
|
||||
}
|
||||
}
|
||||
|
||||
/* Can we move onto the spot? */
|
||||
if (!diag_ok(er, &tryp, tp)) continue;
|
||||
|
||||
ch = CCHAR( mvwinch(cw, y, x) ); /* Screen character */
|
||||
|
||||
/*
|
||||
* Stepping on player is NOT okay if we are fleeing.
|
||||
* If we are friendly to the player and there is a monster
|
||||
* in the way that is not of our race, it is okay to move
|
||||
* there.
|
||||
*/
|
||||
if (step_ok(y, x, FIGHTOK, tp) &&
|
||||
(off(*tp, ISFLEE) || ch != PLAYER))
|
||||
{
|
||||
/*
|
||||
* If it is a trap, an intelligent monster may not
|
||||
* step on it (unless our hero is on top!)
|
||||
*/
|
||||
if ((isatrap(ch)) &&
|
||||
(rnd(10) < tp->t_stats.s_intel) &&
|
||||
(!on(*tp, ISFLY)) &&
|
||||
(y != hero.y || x != hero.x))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* OK -- this place counts
|
||||
*/
|
||||
thisdist = DISTANCE(y, x, ee->y, ee->x);
|
||||
|
||||
/* Adjust distance if we are being shot at */
|
||||
if (tp->t_wasshot && tp->t_stats.s_intel > 5 &&
|
||||
prey != NULL) {
|
||||
/* Move out of line of sight */
|
||||
if (straight_shot(tryp.y, tryp.x, ee->y, ee->x, NULL)) {
|
||||
if (flee) thisdist -= SHOTPENALTY;
|
||||
else thisdist += SHOTPENALTY;
|
||||
}
|
||||
|
||||
/* But do we want to leave the room? */
|
||||
else if (rer && rer == ree && ch == DOOR)
|
||||
thisdist += DOORPENALTY;
|
||||
}
|
||||
|
||||
/* Don't move to the last position if we can help it
|
||||
* (unless out prey just moved there)
|
||||
*/
|
||||
if (ce(tryp, tp->t_oldpos) && (flee || !ce(tryp, hero)))
|
||||
dist_to_old = thisdist;
|
||||
|
||||
else if ((flee && (thisdist > dist)) ||
|
||||
(!flee && (thisdist < dist)))
|
||||
{
|
||||
ch_ret = tryp;
|
||||
dist = thisdist;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we aren't trying to get the player, but he is in our way,
|
||||
* hit him (unless we have been turned or are friendly). next_player
|
||||
* being TRUE -> we are next to the player but don't want to hit him.
|
||||
*
|
||||
* If we are friendly to the player, following him, and standing next
|
||||
* to him, we will try to help him out in battle.
|
||||
*/
|
||||
if (next_player && off(*tp, WASTURNED)) {
|
||||
if (off(*tp, ISFRIENDLY) &&
|
||||
((flee && ce(ch_ret, *er)) ||
|
||||
(!flee && DISTANCE(er->y, er->x, ee->y, ee->x) < dist)) &&
|
||||
step_ok(tp->t_dest->y, tp->t_dest->x, NOMONST, tp)) {
|
||||
/* Okay to hit player */
|
||||
debug("Switching to hero.");
|
||||
tp->t_newpos = hero;
|
||||
tp->t_action = A_MOVE;
|
||||
return;
|
||||
}
|
||||
else if (on(*tp, ISFRIENDLY) && !flee && ce(*ee, hero)) {
|
||||
/*
|
||||
* Look all around the player. If there is a fightable
|
||||
* creature next to both of us, hit it. Otherwise, if
|
||||
* there is a fightable creature next to the player, try
|
||||
* to move next to it.
|
||||
*/
|
||||
dist = MAXINT;
|
||||
for (x = hero.x - 1; x <= hero.x + 1; x++) {
|
||||
if (x < 0 || x >= cols) /* Don't try off the board */
|
||||
continue;
|
||||
for (y = hero.y - 1; y <= hero.y + 1; y++) {
|
||||
if ((y < 1) || (y >= lines - 2)) /* Stay on the board */
|
||||
continue;
|
||||
|
||||
/* Is there a fightable monster here? */
|
||||
if (isalpha(mvwinch(mw, y, x)) &&
|
||||
step_ok(y, x, FIGHTOK, tp) &&
|
||||
off(*tp, ISSTONE)) {
|
||||
thisdist = DISTANCE(er->y, er->x, y, x);
|
||||
if (thisdist < dist) {
|
||||
dist = thisdist;
|
||||
ch_ret.y = y;
|
||||
ch_ret.x = x;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Are we next to a bad guy? */
|
||||
if (dist <= 2) { /* Get him! */
|
||||
tp->t_newpos = ch_ret;
|
||||
tp->t_action = A_MOVE;
|
||||
}
|
||||
|
||||
/* Try to move to the bad guy */
|
||||
else if (dist < MAXINT)
|
||||
chase(tp, &ch_ret,
|
||||
roomin(&tp->t_pos), roomin(&ch_ret), FALSE);
|
||||
|
||||
else tp->t_action = A_NIL;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If we have decided that we can move onto a monster (we are
|
||||
* friendly to the player, go to it.
|
||||
*/
|
||||
if (!ce(ch_ret, *er) && isalpha(mvwinch(mw, ch_ret.y, ch_ret.x))) {
|
||||
debug("Attack monster");
|
||||
tp->t_newpos = ch_ret;
|
||||
tp->t_action = A_MOVE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we can't get closer to the player (if that's our goal)
|
||||
* because other monsters are in the way, just stay put
|
||||
*/
|
||||
if (!flee && ce(hero, *ee) && monst_dist < MAXINT &&
|
||||
DISTANCE(er->y, er->x, hero.y, hero.x) < dist) {
|
||||
tp->t_action = A_NIL; /* do nothing for awhile */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Do we want to go back to the last position? */
|
||||
else if (dist_to_old != MININT && /* It is possible to move back */
|
||||
((flee && dist == 0) || /* No other possible moves */
|
||||
(!flee && dist == MAXINT))) {
|
||||
/* Do we move back or just stay put (default)? */
|
||||
dist = DISTANCE(er->y, er->x, ee->y, ee->x); /* Current distance */
|
||||
if (!flee || (flee && (dist_to_old > dist))) ch_ret = tp->t_oldpos;
|
||||
}
|
||||
|
||||
/* Record the new destination */
|
||||
tp->t_newpos = ch_ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do we want to fight or move? If our selected destination (ch_ret)
|
||||
* is our hero, then we want to fight. Otherwise, we want to move.
|
||||
*/
|
||||
if (ce(tp->t_newpos, hero)) {
|
||||
/* Fight! (or sell) */
|
||||
if (on(*tp, CANSELL)) {
|
||||
tp->t_action = A_SELL;
|
||||
tp->t_no_move += movement(tp); /* takes a little time to sell */
|
||||
}
|
||||
else {
|
||||
tp->t_action = A_ATTACK;
|
||||
|
||||
/*
|
||||
* Try to find a weapon to wield. Wield_weap will return a
|
||||
* projector if weapon is a projectile (eg. bow for arrow).
|
||||
* If weapon is NULL (the case here), it will try to find
|
||||
* a suitable weapon.
|
||||
*
|
||||
* Add in rest of time. Fight is
|
||||
* movement() + weap_move() + FIGHTBASE
|
||||
*/
|
||||
tp->t_using = wield_weap(NULL, tp);
|
||||
if (tp->t_using == NULL)
|
||||
tp->t_no_move += weap_move(tp, NULL);
|
||||
else
|
||||
tp->t_no_move += weap_move(tp, OBJPTR(tp->t_using));
|
||||
|
||||
if (on(*tp, ISHASTE))
|
||||
tp->t_no_move += FIGHTBASE/2;
|
||||
else if (on(*tp, ISSLOW))
|
||||
tp->t_no_move += FIGHTBASE*2;
|
||||
else
|
||||
tp->t_no_move += FIGHTBASE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Move */
|
||||
tp->t_action = A_MOVE;
|
||||
|
||||
/*
|
||||
* Check if the creature is not next to the player. If it
|
||||
* is not and has held or suffocated the player, then stop it!
|
||||
* Note that this code should more appropriately appear in
|
||||
* the area that actually moves the monster, but for now it
|
||||
* is okay here because the player can't move while held or
|
||||
* suffocating.
|
||||
*/
|
||||
if (dist > 2) {
|
||||
if (on(*tp, DIDHOLD)) {
|
||||
turn_off(*tp, DIDHOLD);
|
||||
turn_on(*tp, CANHOLD);
|
||||
if (--hold_count == 0)
|
||||
turn_off(player, ISHELD);
|
||||
}
|
||||
|
||||
/* If monster was suffocating, stop it */
|
||||
if (on(*tp, DIDSUFFOCATE)) {
|
||||
turn_off(*tp, DIDSUFFOCATE);
|
||||
turn_on(*tp, CANSUFFOCATE);
|
||||
extinguish(suffocate);
|
||||
msg("You can breathe again.....Whew!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* do_chase:
|
||||
* Make one thing chase another.
|
||||
*/
|
||||
|
||||
do_chase(th)
|
||||
register struct thing *th;
|
||||
{
|
||||
register struct room *orig_rer, /* Original room of chaser */
|
||||
*new_room; /* new room of monster */
|
||||
char floor, rch, sch;
|
||||
coord old_pos, /* Old position of monster */
|
||||
ch_ret; /* Where we want to go */
|
||||
|
||||
if (on(*th, NOMOVE)) return;
|
||||
|
||||
ch_ret = th->t_newpos; /* Record our desired new position */
|
||||
|
||||
/*
|
||||
* Make sure we have an open spot (no other monster's gotten in our way,
|
||||
* someone didn't just drop a scare monster there, our prey didn't just
|
||||
* get there, etc.)
|
||||
*/
|
||||
if (!step_ok(th->t_newpos.y, th->t_newpos.x, FIGHTOK, th)) {
|
||||
/*
|
||||
* Most monsters get upset now. Guardians are all friends,
|
||||
* and we don't want to see 50 messages in a row!
|
||||
*/
|
||||
if (th->t_stats.s_intel > 4 &&
|
||||
off(*th, ISUNDEAD) &&
|
||||
off(*th, ISGUARDIAN) &&
|
||||
off(*th, AREMANY) &&
|
||||
off(*th, ISHUH) &&
|
||||
off(player, ISBLIND) &&
|
||||
cansee(unc(th->t_pos)) &&
|
||||
!invisible(th))
|
||||
msg("%s motions angrily.", prname(monster_name(th), TRUE));
|
||||
return;
|
||||
}
|
||||
else if (ce(th->t_newpos, hero) || /* Player just got in our way */
|
||||
isalpha(mvwinch(mw, th->t_newpos.y, th->t_newpos.x))) {
|
||||
bool fightplayer = ce(th->t_newpos, hero);
|
||||
|
||||
/* If we were turned or are friendly, we just have to sit here! */
|
||||
if (fightplayer && (on(*th, WASTURNED) || on(*th, ISFRIENDLY))) return;
|
||||
|
||||
/* Do we want to sell something? */
|
||||
if (fightplayer && on(*th, CANSELL)) {
|
||||
th->t_action = A_SELL;
|
||||
th->t_no_move += movement(th); /* takes a little time to sell */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Let's hit him */
|
||||
th->t_action = A_ATTACK;
|
||||
|
||||
/*
|
||||
* Try to find a weapon to wield. Wield_weap will return a
|
||||
* projector if weapon is a projectile (eg. bow for arrow).
|
||||
* If weapon is NULL (the case here), it will try to find
|
||||
* a suitable weapon.
|
||||
*/
|
||||
th->t_using = wield_weap(NULL, th);
|
||||
/*
|
||||
* add in rest of time
|
||||
*/
|
||||
if (th->t_using == NULL)
|
||||
th->t_no_move += weap_move(th, NULL);
|
||||
else
|
||||
th->t_no_move += weap_move(th, OBJPTR(th->t_using));
|
||||
if (on(*th, ISHASTE))
|
||||
th->t_no_move += FIGHTBASE/2;
|
||||
else if (on(*th, ISSLOW))
|
||||
th->t_no_move += FIGHTBASE*2;
|
||||
else
|
||||
th->t_no_move += FIGHTBASE;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Blank out the old position and record the new position --
|
||||
* the blanking must be done first in case the positions are the same.
|
||||
*/
|
||||
mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
|
||||
mvwaddch(mw, ch_ret.y, ch_ret.x, th->t_type);
|
||||
|
||||
/* Get new and old rooms of monster */
|
||||
new_room = roomin(&ch_ret);
|
||||
orig_rer = roomin(&th->t_pos);
|
||||
|
||||
/* Store the critter's old position and update the current one */
|
||||
old_pos = th->t_pos;
|
||||
th->t_pos = ch_ret;
|
||||
floor = (roomin(&ch_ret) == NULL) ? PASSAGE : FLOOR;
|
||||
|
||||
/* If we have a scavenger, it can pick something up */
|
||||
if (off(*th, ISGUARDIAN)) {
|
||||
register struct linked_list *n_item, *o_item;
|
||||
register int item_count = 0;
|
||||
bool want_something = FALSE;
|
||||
|
||||
while ((n_item = find_obj(ch_ret.y, ch_ret.x)) != NULL) {
|
||||
register struct object *n_obj, *o_obj;
|
||||
bool wants_it;
|
||||
|
||||
/* Does this monster want anything? */
|
||||
if (want_something == FALSE) {
|
||||
if (on(*th, ISSCAVENGE) || on(*th, CARRYFOOD) ||
|
||||
on(*th, CARRYGOLD) || on(*th, CARRYSCROLL) ||
|
||||
on(*th, CARRYPOTION) || on(*th, CARRYRING) ||
|
||||
on(*th, CARRYSTICK) || on(*th, CARRYMISC) ||
|
||||
on(*th, CARRYWEAPON) || on(*th, CARRYARMOR) ||
|
||||
on(*th, CARRYDAGGER)) {
|
||||
want_something = TRUE;
|
||||
|
||||
/*
|
||||
* Blank the area. We have to do it only before the
|
||||
* first item in case an item gets dropped in same
|
||||
* place. We don't want to blank it out after it get
|
||||
* dropped.
|
||||
*/
|
||||
mvaddch(ch_ret.y, ch_ret.x, floor);
|
||||
|
||||
/* Were we specifically after something here? */
|
||||
if (ce(*th->t_dest, ch_ret)) {
|
||||
/* If we're mean, we go after the hero */
|
||||
if (on(*th, ISMEAN)) runto(th, &hero);
|
||||
|
||||
/* Otherwise just go back to sleep */
|
||||
else {
|
||||
turn_off(*th, ISRUN);
|
||||
th->t_dest = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
item_count++; /* Count the number of items */
|
||||
|
||||
/*
|
||||
* see if he's got one of this group already
|
||||
*/
|
||||
o_item = NULL;
|
||||
n_obj = OBJPTR(n_item);
|
||||
detach(lvl_obj, n_item);
|
||||
|
||||
/* See if he wants it */
|
||||
if (n_obj->o_type == SCROLL && n_obj->o_which == S_SCARE &&
|
||||
th->t_stats.s_intel < 16)
|
||||
wants_it = FALSE; /* Most monsters don't want a scare monster */
|
||||
else if (on(*th, ISSCAVENGE)) wants_it = TRUE;
|
||||
else {
|
||||
wants_it = FALSE; /* Default case */
|
||||
switch (n_obj->o_type) {
|
||||
case FOOD: if(on(*th, CARRYFOOD)) wants_it = TRUE;
|
||||
when GOLD: if(on(*th, CARRYGOLD)) wants_it = TRUE;
|
||||
when SCROLL:if(on(*th, CARRYSCROLL)) wants_it = TRUE;
|
||||
when POTION:if(on(*th, CARRYPOTION)) wants_it = TRUE;
|
||||
when RING: if(on(*th, CARRYRING)) wants_it = TRUE;
|
||||
when STICK: if(on(*th, CARRYSTICK)) wants_it = TRUE;
|
||||
when MM: if(on(*th, CARRYMISC)) wants_it = TRUE;
|
||||
when ARMOR: if(on(*th, CARRYARMOR)) wants_it = TRUE;
|
||||
when WEAPON:if(on(*th, CARRYWEAPON) ||
|
||||
(on(*th,CARRYDAGGER)&&n_obj->o_which==DAGGER))
|
||||
wants_it = TRUE;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* The quartermaster doesn't sell cursed stuff so he won't
|
||||
* pick it up
|
||||
*/
|
||||
if (on(*th, CANSELL) && (n_obj->o_flags & ISCURSED))
|
||||
wants_it = FALSE;
|
||||
|
||||
/* If he doesn't want it, throw it away */
|
||||
if (wants_it == FALSE) {
|
||||
fall(n_item, FALSE);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Otherwise, let's pick it up */
|
||||
if (n_obj->o_group) {
|
||||
for(o_item = th->t_pack; o_item != NULL; o_item = next(o_item)){
|
||||
o_obj = OBJPTR(o_item);
|
||||
if (o_obj->o_group == n_obj->o_group) {
|
||||
o_obj->o_count += n_obj->o_count;
|
||||
o_discard(n_item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (o_item == NULL) { /* didn't find it */
|
||||
attach(th->t_pack, n_item);
|
||||
}
|
||||
}
|
||||
|
||||
/* If there was anything here, we may have to update the screen */
|
||||
if (item_count) {
|
||||
if (cansee(ch_ret.y, ch_ret.x))
|
||||
mvwaddch(cw, ch_ret.y, ch_ret.x, mvinch(ch_ret.y, ch_ret.x));
|
||||
updpack(TRUE, th); /* Update the monster's encumberance, too */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
rch = CCHAR( mvwinch(stdscr, old_pos.y, old_pos.x) );
|
||||
if (th->t_oldch == floor && rch != floor && !isatrap(rch))
|
||||
mvwaddch(cw, old_pos.y, old_pos.x, rch);
|
||||
else
|
||||
mvwaddch(cw, old_pos.y, old_pos.x, th->t_oldch);
|
||||
sch = CCHAR( mvwinch(cw, ch_ret.y, ch_ret.x) ); /* What player sees */
|
||||
rch = CCHAR( mvwinch(stdscr, ch_ret.y, ch_ret.x) ); /* What's really there */
|
||||
|
||||
/* If we have a tunneling monster, it may be making a tunnel */
|
||||
if (on(*th, CANTUNNEL) &&
|
||||
(rch == SECRETDOOR || rch == WALL || rch == '|' || rch == '-')) {
|
||||
char nch; /* The new look to the tunnel */
|
||||
|
||||
if (rch == WALL) nch = PASSAGE;
|
||||
else if (levtype == MAZELEV) nch = FLOOR;
|
||||
else nch = DOOR;
|
||||
addch(nch);
|
||||
|
||||
if (cansee(ch_ret.y, ch_ret.x)) sch = nch; /* Can player see this? */
|
||||
|
||||
/* Does this make a new exit? */
|
||||
if (rch == '|' || rch == '-') {
|
||||
struct linked_list *newroom;
|
||||
coord *exit;
|
||||
|
||||
newroom = new_item(sizeof(coord));
|
||||
exit = DOORPTR(newroom);
|
||||
*exit = ch_ret;
|
||||
attach(new_room->r_exit, newroom);
|
||||
}
|
||||
}
|
||||
|
||||
/* Mark if the monster is inside a wall */
|
||||
if (isrock(mvinch(ch_ret.y, ch_ret.x))) turn_on(*th, ISINWALL);
|
||||
else turn_off(*th, ISINWALL);
|
||||
|
||||
/* If the monster can illuminate rooms, check for a change */
|
||||
if (on(*th, HASFIRE)) {
|
||||
register struct linked_list *fire_item;
|
||||
|
||||
/* Is monster entering a room? */
|
||||
if (orig_rer != new_room && new_room != NULL) {
|
||||
fire_item = creat_item(); /* Get an item-only structure */
|
||||
ldata(fire_item) = (char *) th;
|
||||
|
||||
attach(new_room->r_fires, fire_item);
|
||||
new_room->r_flags |= HASFIRE;
|
||||
|
||||
if (cansee(ch_ret.y, ch_ret.x) && next(new_room->r_fires) == NULL)
|
||||
light(&hero);
|
||||
}
|
||||
|
||||
/* Is monster leaving a room? */
|
||||
if (orig_rer != new_room && orig_rer != NULL) {
|
||||
/* Find the bugger in the list and delete him */
|
||||
for (fire_item = orig_rer->r_fires; fire_item != NULL;
|
||||
fire_item = next(fire_item)) {
|
||||
if (THINGPTR(fire_item) == th) { /* Found him! */
|
||||
detach(orig_rer->r_fires, fire_item);
|
||||
destroy_item(fire_item);
|
||||
if (orig_rer->r_fires == NULL) {
|
||||
orig_rer->r_flags &= ~HASFIRE;
|
||||
if (cansee(old_pos.y, old_pos.x))
|
||||
light(&old_pos);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If monster is entering player's room and player can see it,
|
||||
* stop the player's running.
|
||||
*/
|
||||
if (new_room != orig_rer && new_room != NULL &&
|
||||
new_room == roomin(th->t_dest) && cansee(unc(ch_ret)) &&
|
||||
(off(*th, ISINVIS) || on(player, CANSEE)) &&
|
||||
(off(*th, ISSHADOW) || on(player, CANSEE)) &&
|
||||
(off(*th, CANSURPRISE) || ISWEARING(R_ALERT))) {
|
||||
running = FALSE;
|
||||
if (fight_flush) md_flushinp();
|
||||
}
|
||||
|
||||
th->t_oldch = sch;
|
||||
|
||||
/* Let's display those creatures that we can see. */
|
||||
if (cansee(unc(ch_ret)) &&
|
||||
off(*th, ISINWALL) &&
|
||||
!invisible(th))
|
||||
mvwaddch(cw, ch_ret.y, ch_ret.x, th->t_type);
|
||||
|
||||
/* Record monster's last position (if new one is different) */
|
||||
if (!ce(ch_ret, old_pos)) th->t_oldpos = old_pos;
|
||||
|
||||
/* If the monster is on a trap, trap it */
|
||||
sch = CCHAR( mvinch(ch_ret.y, ch_ret.x) );
|
||||
if (isatrap(sch)) {
|
||||
if (cansee(ch_ret.y, ch_ret.x)) th->t_oldch = sch;
|
||||
be_trapped(th, &ch_ret);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get_hurl returns the weapon that the monster will "throw" if he has one
|
||||
*/
|
||||
|
||||
struct linked_list *
|
||||
get_hurl(tp)
|
||||
register struct thing *tp;
|
||||
{
|
||||
struct linked_list *arrow=NULL, *bolt=NULL, *rock=NULL,
|
||||
*spear = NULL, *dagger=NULL, *dart=NULL, *aklad=NULL;
|
||||
register struct linked_list *pitem;
|
||||
register struct object *obj;
|
||||
bool bow=FALSE, crossbow=FALSE, sling=FALSE;
|
||||
|
||||
for (pitem=tp->t_pack; pitem; pitem=next(pitem)) {
|
||||
obj = OBJPTR(pitem);
|
||||
if (obj->o_type == WEAPON)
|
||||
switch (obj->o_which) {
|
||||
case BOW: bow = TRUE;
|
||||
when CROSSBOW: crossbow = TRUE;
|
||||
when SLING: sling = TRUE;
|
||||
when ROCK: rock = pitem;
|
||||
when ARROW: arrow = pitem;
|
||||
when BOLT: bolt = pitem;
|
||||
when SPEAR: spear = pitem;
|
||||
when DAGGER:
|
||||
/* Don't throw the dagger if it's our last one */
|
||||
if (obj->o_count > 1) dagger = pitem;
|
||||
when DART: dart = pitem;
|
||||
}
|
||||
else if (obj->o_type == RELIC &&
|
||||
obj->o_which == AXE_AKLAD)
|
||||
aklad = pitem;
|
||||
}
|
||||
|
||||
/* Do we have that all-powerful Aklad Axe? */
|
||||
if (aklad) return(aklad);
|
||||
|
||||
/* Use crossbow bolt if possible */
|
||||
if (crossbow && bolt) return(bolt);
|
||||
if (bow && arrow) return(arrow);
|
||||
if (spear) return(spear);
|
||||
if (dagger) return(dagger);
|
||||
if (sling && rock) return(rock);
|
||||
if (dart) return(dart);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* runto:
|
||||
* Set a monster running after something
|
||||
*/
|
||||
|
||||
runto(runner, spot)
|
||||
register struct thing *runner;
|
||||
coord *spot;
|
||||
{
|
||||
if (on(*runner, ISSTONE))
|
||||
return;
|
||||
|
||||
/* If we are chasing a new creature, forget about thrown weapons */
|
||||
if (runner->t_dest && !ce(*runner->t_dest, *spot)) runner->t_wasshot=FALSE;
|
||||
|
||||
/*
|
||||
* Start the beastie running
|
||||
*/
|
||||
runner->t_dest = spot;
|
||||
turn_on(*runner, ISRUN);
|
||||
turn_off(*runner, ISDISGUISE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* straight_shot:
|
||||
* See if there is a straight line of sight between the two
|
||||
* given coordinates. If shooting is not NULL, it is a pointer
|
||||
* to a structure which should be filled with the direction
|
||||
* to shoot (if there is a line of sight). If shooting, monsters
|
||||
* get in the way. Otherwise, they do not.
|
||||
*/
|
||||
|
||||
bool
|
||||
straight_shot(ery, erx, eey, eex, shooting)
|
||||
register int ery, erx, eey, eex;
|
||||
register coord *shooting;
|
||||
{
|
||||
register int dy, dx; /* Deltas */
|
||||
char ch;
|
||||
|
||||
/* Does the monster have a straight shot at prey */
|
||||
if ((ery != eey) && (erx != eex) &&
|
||||
(abs(ery - eey) != abs(erx - eex))) return(FALSE);
|
||||
|
||||
/* Get the direction to shoot */
|
||||
if (eey > ery) dy = 1;
|
||||
else if (eey == ery) dy = 0;
|
||||
else dy = -1;
|
||||
|
||||
if (eex > erx) dx = 1;
|
||||
else if (eex == erx) dx = 0;
|
||||
else dx = -1;
|
||||
|
||||
/* Make sure we have free area all the way to the player */
|
||||
ery += dy;
|
||||
erx += dx;
|
||||
while ((ery != eey) || (erx != eex)) {
|
||||
switch (ch = CCHAR( winat(ery, erx) )) {
|
||||
case '|':
|
||||
case '-':
|
||||
case WALL:
|
||||
case DOOR:
|
||||
case SECRETDOOR:
|
||||
case FOREST:
|
||||
return(FALSE);
|
||||
default:
|
||||
if (shooting && isalpha(ch)) return(FALSE);
|
||||
}
|
||||
ery += dy;
|
||||
erx += dx;
|
||||
}
|
||||
|
||||
if (shooting) { /* If we are shooting -- put in the directions */
|
||||
shooting->y = dy;
|
||||
shooting->x = dx;
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
1220
arogue7/command.c
Normal file
1220
arogue7/command.c
Normal file
File diff suppressed because it is too large
Load diff
252
arogue7/daemon.c
Normal file
252
arogue7/daemon.c
Normal file
|
|
@ -0,0 +1,252 @@
|
|||
/*
|
||||
* daemon.c - functions for dealing with things that happen in the future.
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Contains functions for dealing with things that happen in the
|
||||
* future.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "curses.h"
|
||||
#include "rogue.h"
|
||||
|
||||
#define EMPTY 0
|
||||
#define DAEMON -1
|
||||
#define MAXDAEMONS 10
|
||||
#define MAXFUSES 20
|
||||
|
||||
#define _X_ { EMPTY }
|
||||
|
||||
struct delayed_action d_list[MAXDAEMONS] = {
|
||||
_X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_
|
||||
};
|
||||
struct delayed_action f_list[MAXFUSES] = {
|
||||
_X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_,
|
||||
_X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_
|
||||
};
|
||||
int demoncnt = 0; /* number of active daemons */
|
||||
int fusecnt = 0;
|
||||
|
||||
|
||||
/*
|
||||
* d_slot:
|
||||
* Find an empty slot in the daemon list
|
||||
*/
|
||||
struct delayed_action *
|
||||
d_slot()
|
||||
{
|
||||
reg int i;
|
||||
reg struct delayed_action *dev;
|
||||
|
||||
for (i = 0, dev = d_list; i < MAXDAEMONS; i++, dev++)
|
||||
if (dev->d_type == EMPTY)
|
||||
return dev;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* f_slot:
|
||||
* Find an empty slot in the fuses list
|
||||
*/
|
||||
struct delayed_action *
|
||||
f_slot()
|
||||
{
|
||||
reg int i;
|
||||
reg struct delayed_action *dev;
|
||||
|
||||
for (i = 0, dev = f_list; i < MAXFUSES; 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(func)
|
||||
reg int (*func)();
|
||||
{
|
||||
reg int i;
|
||||
reg struct delayed_action *dev;
|
||||
|
||||
for (i = 0, dev = f_list; i < MAXFUSES; i++, dev++)
|
||||
if (dev->d_type != EMPTY && func == dev->d_func)
|
||||
return dev;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* daemon:
|
||||
* Start a daemon, takes a function.
|
||||
*/
|
||||
daemon(func, arg, type)
|
||||
reg int arg, type, (*func)();
|
||||
{
|
||||
reg struct delayed_action *dev;
|
||||
|
||||
dev = d_slot();
|
||||
if (dev != NULL) {
|
||||
dev->d_type = type;
|
||||
dev->d_func = func;
|
||||
dev->d_.arg = arg;
|
||||
dev->d_time = DAEMON;
|
||||
demoncnt += 1; /* update count */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* kill_daemon:
|
||||
* Remove a daemon from the list
|
||||
*/
|
||||
kill_daemon(func)
|
||||
reg int (*func)();
|
||||
{
|
||||
reg struct delayed_action *dev;
|
||||
reg int i;
|
||||
|
||||
for (i = 0, dev = d_list; i < MAXDAEMONS; i++, dev++) {
|
||||
if (dev->d_type != EMPTY && func == dev->d_func)
|
||||
break;
|
||||
}
|
||||
if (i >= MAXDAEMONS) return; /* if not found, forget it */
|
||||
/*
|
||||
* Take it out of the list
|
||||
*/
|
||||
dev->d_type = EMPTY;
|
||||
dev->d_.arg = 0;
|
||||
dev->d_func = NULL;
|
||||
dev->d_time = 0;
|
||||
demoncnt -= 1; /* update count */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* do_daemons:
|
||||
* Run all the daemons that are active with the current flag,
|
||||
* passing the argument to the function.
|
||||
*/
|
||||
do_daemons(flag)
|
||||
reg int flag;
|
||||
{
|
||||
reg struct delayed_action *dev;
|
||||
|
||||
/*
|
||||
* Loop through the devil list
|
||||
*/
|
||||
for (dev = d_list; dev <= &d_list[MAXDAEMONS-1]; dev++)
|
||||
/*
|
||||
* Executing each one, giving it the proper arguments
|
||||
*/
|
||||
if (dev->d_type == flag && dev->d_time == DAEMON)
|
||||
(*dev->d_func)(dev->d_.arg);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fuse:
|
||||
* Start a fuse to go off in a certain number of turns
|
||||
*/
|
||||
fuse(func, arg, time, type)
|
||||
reg int (*func)(), arg, time, type;
|
||||
{
|
||||
reg struct delayed_action *wire;
|
||||
|
||||
wire = f_slot();
|
||||
if (wire != NULL) {
|
||||
wire->d_type = type;
|
||||
wire->d_func = func;
|
||||
wire->d_.arg = arg;
|
||||
wire->d_time = time;
|
||||
fusecnt += 1; /* update count */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* lengthen:
|
||||
* Increase the time until a fuse goes off
|
||||
*/
|
||||
lengthen(func, xtime)
|
||||
reg int (*func)(), xtime;
|
||||
{
|
||||
reg struct delayed_action *wire;
|
||||
|
||||
if ((wire = find_slot(func)) == NULL)
|
||||
return;
|
||||
wire->d_time += xtime;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* extinguish:
|
||||
* Put out a fuse
|
||||
*/
|
||||
extinguish(func)
|
||||
reg int (*func)();
|
||||
{
|
||||
reg struct delayed_action *wire;
|
||||
|
||||
if ((wire = find_slot(func)) == NULL)
|
||||
return;
|
||||
wire->d_type = EMPTY;
|
||||
wire->d_func = NULL;
|
||||
wire->d_.arg = 0;
|
||||
wire->d_time = 0;
|
||||
fusecnt -= 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* do_fuses:
|
||||
* Decrement counters and start needed fuses
|
||||
*/
|
||||
do_fuses(flag)
|
||||
reg int flag;
|
||||
{
|
||||
reg struct delayed_action *wire;
|
||||
|
||||
/*
|
||||
* Step though the list
|
||||
*/
|
||||
for (wire = f_list; wire <= &f_list[MAXFUSES-1]; wire++) {
|
||||
/*
|
||||
* Decrementing counters and starting things we want. We also need
|
||||
* to remove the fuse from the list once it has gone off.
|
||||
*/
|
||||
if(flag == wire->d_type && wire->d_time > 0 &&
|
||||
--wire->d_time == 0) {
|
||||
wire->d_type = EMPTY;
|
||||
if (wire->d_func != NULL)
|
||||
(*wire->d_func)(wire->d_.arg);
|
||||
fusecnt -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* activity:
|
||||
* Show wizard number of demaons and memory blocks used
|
||||
*/
|
||||
activity()
|
||||
{
|
||||
msg("Daemons = %d : Fuses = %d : Memory Items = %d : Memory Used = %d",
|
||||
demoncnt,fusecnt,total,md_memused(0));
|
||||
}
|
||||
663
arogue7/daemons.c
Normal file
663
arogue7/daemons.c
Normal file
|
|
@ -0,0 +1,663 @@
|
|||
/*
|
||||
* daemon.c - All the daemon and fuse functions are in here
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* All the daemon and fuse functions are in here
|
||||
*
|
||||
*/
|
||||
|
||||
#include "curses.h"
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* doctor:
|
||||
* A healing daemon that restors hit points after rest
|
||||
*/
|
||||
|
||||
doctor(tp)
|
||||
register struct thing *tp;
|
||||
{
|
||||
register int ohp;
|
||||
register int limit, new_points;
|
||||
register struct stats *curp; /* current stats pointer */
|
||||
register struct stats *maxp; /* max stats pointer */
|
||||
|
||||
curp = &(tp->t_stats);
|
||||
maxp = &(tp->maxstats);
|
||||
if (curp->s_hpt == maxp->s_hpt) {
|
||||
tp->t_quiet = 0;
|
||||
return;
|
||||
}
|
||||
tp->t_quiet++;
|
||||
switch (tp->t_ctype) {
|
||||
case C_MAGICIAN:
|
||||
limit = 8 - curp->s_lvl;
|
||||
new_points = curp->s_lvl - 3;
|
||||
when C_THIEF:
|
||||
case C_ASSASIN:
|
||||
case C_MONK:
|
||||
limit = 8 - curp->s_lvl;
|
||||
new_points = curp->s_lvl - 2;
|
||||
when C_CLERIC:
|
||||
case C_DRUID:
|
||||
limit = 8 - curp->s_lvl;
|
||||
new_points = curp->s_lvl - 3;
|
||||
when C_FIGHTER:
|
||||
case C_RANGER:
|
||||
case C_PALADIN:
|
||||
limit = 16 - curp->s_lvl*2;
|
||||
new_points = curp->s_lvl - 5;
|
||||
when C_MONSTER:
|
||||
limit = 16 - curp->s_lvl;
|
||||
new_points = curp->s_lvl - 6;
|
||||
otherwise:
|
||||
debug("what a strange character you are!");
|
||||
return;
|
||||
}
|
||||
ohp = curp->s_hpt;
|
||||
if (off(*tp, HASDISEASE) && off(*tp, DOROT)) {
|
||||
if (curp->s_lvl < 8) {
|
||||
if (tp->t_quiet > limit) {
|
||||
curp->s_hpt++;
|
||||
tp->t_quiet = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (tp->t_quiet >= 3) {
|
||||
curp->s_hpt += rnd(new_points)+1;
|
||||
tp->t_quiet = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tp == &player) {
|
||||
if (ISRING(LEFT_1, R_REGEN)) curp->s_hpt++;
|
||||
if (ISRING(LEFT_2, R_REGEN)) curp->s_hpt++;
|
||||
if (ISRING(LEFT_3, R_REGEN)) curp->s_hpt++;
|
||||
if (ISRING(LEFT_4, R_REGEN)) curp->s_hpt++;
|
||||
if (ISRING(RIGHT_1, R_REGEN)) curp->s_hpt++;
|
||||
if (ISRING(RIGHT_2, R_REGEN)) curp->s_hpt++;
|
||||
if (ISRING(RIGHT_3, R_REGEN)) curp->s_hpt++;
|
||||
if (ISRING(RIGHT_4, R_REGEN)) curp->s_hpt++;
|
||||
}
|
||||
if (on(*tp, ISREGEN))
|
||||
curp->s_hpt += curp->s_lvl/10 + 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 */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Swander:
|
||||
* Called when it is time to start rolling for wandering monsters
|
||||
*/
|
||||
|
||||
swander()
|
||||
{
|
||||
daemon(rollwand, 0, BEFORE);
|
||||
}
|
||||
|
||||
/*
|
||||
* rollwand:
|
||||
* Called to roll to see if a wandering monster starts up
|
||||
*/
|
||||
|
||||
int between = 0;
|
||||
|
||||
rollwand()
|
||||
{
|
||||
|
||||
if (++between >= 4)
|
||||
{
|
||||
/* Theives may not awaken a monster */
|
||||
if ((roll(1, 6) == 4) &&
|
||||
((player.t_ctype != C_THIEF && player.t_ctype != C_ASSASIN) ||
|
||||
(rnd(30) >= dex_compute()))) {
|
||||
if (levtype != POSTLEV)
|
||||
wanderer();
|
||||
kill_daemon(rollwand);
|
||||
fuse(swander, 0, WANDERTIME, BEFORE);
|
||||
}
|
||||
between = 0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* this function is a daemon called each turn when the character is a thief
|
||||
*/
|
||||
trap_look()
|
||||
{
|
||||
if (rnd(100) < (2*dex_compute() + 5*pstats.s_lvl))
|
||||
search(TRUE, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* unconfuse:
|
||||
* Release the poor player from his confusion
|
||||
*/
|
||||
|
||||
unconfuse()
|
||||
{
|
||||
turn_off(player, ISHUH);
|
||||
msg("You feel less confused now");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* unsee:
|
||||
* He lost his see invisible power
|
||||
*/
|
||||
unsee()
|
||||
{
|
||||
if (!ISWEARING(R_SEEINVIS)) {
|
||||
turn_off(player, CANSEE);
|
||||
msg("The tingling feeling leaves your eyes");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* unstink:
|
||||
* Remove to-hit handicap from player
|
||||
*/
|
||||
|
||||
unstink()
|
||||
{
|
||||
turn_off(player, HASSTINK);
|
||||
}
|
||||
|
||||
/*
|
||||
* unclrhead:
|
||||
* Player is no longer immune to confusion
|
||||
*/
|
||||
|
||||
unclrhead()
|
||||
{
|
||||
turn_off(player, ISCLEAR);
|
||||
msg("The blue aura about your head fades away.");
|
||||
}
|
||||
|
||||
/*
|
||||
* unphase:
|
||||
* Player can no longer walk through walls
|
||||
*/
|
||||
|
||||
unphase()
|
||||
{
|
||||
turn_off(player, CANINWALL);
|
||||
msg("Your dizzy feeling leaves you.");
|
||||
if (!step_ok(hero.y, hero.x, NOMONST, &player)) death(D_PETRIFY);
|
||||
}
|
||||
|
||||
/*
|
||||
* land:
|
||||
* Player can no longer fly
|
||||
*/
|
||||
|
||||
land()
|
||||
{
|
||||
turn_off(player, ISFLY);
|
||||
msg("You regain your normal weight");
|
||||
running = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* sight:
|
||||
* He gets his sight back
|
||||
*/
|
||||
|
||||
sight()
|
||||
{
|
||||
if (on(player, ISBLIND))
|
||||
{
|
||||
extinguish(sight);
|
||||
turn_off(player, ISBLIND);
|
||||
light(&hero);
|
||||
msg("The veil of darkness lifts");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* res_strength:
|
||||
* Restore player's strength
|
||||
*/
|
||||
|
||||
void
|
||||
res_strength(howmuch)
|
||||
int howmuch;
|
||||
{
|
||||
|
||||
/* If lost_str is non-zero, restore that amount of strength,
|
||||
* else all of it
|
||||
*/
|
||||
if (lost_str) {
|
||||
chg_str(lost_str);
|
||||
lost_str = 0;
|
||||
}
|
||||
|
||||
/* Now, add in the restoral, but no greater than maximum strength */
|
||||
if (howmuch > 0)
|
||||
pstats.s_str =
|
||||
min(pstats.s_str + howmuch, max_stats.s_str + ring_value(R_ADDSTR));
|
||||
|
||||
updpack(TRUE, &player);
|
||||
}
|
||||
|
||||
/*
|
||||
* nohaste:
|
||||
* End the hasting
|
||||
*/
|
||||
|
||||
nohaste()
|
||||
{
|
||||
turn_off(player, ISHASTE);
|
||||
msg("You feel yourself slowing down.");
|
||||
}
|
||||
|
||||
/*
|
||||
* noslow:
|
||||
* End the slowing
|
||||
*/
|
||||
|
||||
noslow()
|
||||
{
|
||||
turn_off(player, ISSLOW);
|
||||
msg("You feel yourself speeding up.");
|
||||
}
|
||||
|
||||
/*
|
||||
* suffocate:
|
||||
* If this gets called, the player has suffocated
|
||||
*/
|
||||
|
||||
suffocate()
|
||||
{
|
||||
death(D_SUFFOCATION);
|
||||
}
|
||||
|
||||
/*
|
||||
* digest the hero's food
|
||||
*/
|
||||
stomach()
|
||||
{
|
||||
register int oldfood, old_hunger, food_use, i;
|
||||
|
||||
/*
|
||||
* avoid problems of fainting while eating by just not saying it
|
||||
* takes food to eat food
|
||||
*/
|
||||
if (player.t_action == C_EAT)
|
||||
return;
|
||||
|
||||
old_hunger = hungry_state;
|
||||
if (food_left <= 0)
|
||||
{
|
||||
/*
|
||||
* the hero is fainting
|
||||
*/
|
||||
if (player.t_action == A_FREEZE)
|
||||
return;
|
||||
if (rnd(100) > 20)
|
||||
return;
|
||||
if (hungry_state == F_FAINT && rnd(20) == 7) /*must have fainted once*/
|
||||
death(D_STARVATION);
|
||||
player.t_action = A_FREEZE;
|
||||
player.t_no_move = movement(&player) * (rnd(8) + 4);
|
||||
if (!terse)
|
||||
addmsg("You feel too weak from lack of food. ");
|
||||
msg("You faint");
|
||||
running = FALSE;
|
||||
if (fight_flush) md_flushinp();
|
||||
count = 0;
|
||||
hungry_state = F_FAINT;
|
||||
}
|
||||
else
|
||||
{
|
||||
oldfood = food_left;
|
||||
food_use = 0;
|
||||
for (i=0; i<MAXRELIC; i++) { /* each relic eats an additional food */
|
||||
if (cur_relic[i])
|
||||
food_use++;
|
||||
}
|
||||
food_use += (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 (food_use < 1)
|
||||
food_use = 1;
|
||||
food_left -= food_use;
|
||||
if (food_left < MORETIME && oldfood >= MORETIME) {
|
||||
msg("You are starting to feel weak");
|
||||
running = FALSE;
|
||||
if (fight_flush) md_flushinp();
|
||||
count = 0;
|
||||
hungry_state = F_WEAK;
|
||||
}
|
||||
else if (food_left < 2 * MORETIME && oldfood >= 2 * MORETIME)
|
||||
{
|
||||
msg(terse ? "Getting hungry" : "You are starting to get hungry");
|
||||
running = FALSE;
|
||||
hungry_state = F_HUNGRY;
|
||||
}
|
||||
else if(food_left<STOMACHSIZE-MORETIME && oldfood>=STOMACHSIZE-MORETIME)
|
||||
{
|
||||
hungry_state = F_OKAY;
|
||||
}
|
||||
}
|
||||
if (old_hunger != hungry_state) {
|
||||
updpack(TRUE, &player);
|
||||
status(TRUE);
|
||||
}
|
||||
wghtchk();
|
||||
}
|
||||
/*
|
||||
* daemon for curing the diseased
|
||||
*/
|
||||
cure_disease()
|
||||
{
|
||||
turn_off(player, HASDISEASE);
|
||||
if (off (player, HASINFEST))
|
||||
msg(terse ? "You feel yourself improving"
|
||||
: "You begin to feel yourself improving again");
|
||||
}
|
||||
|
||||
/*
|
||||
* appear:
|
||||
* Become visible again
|
||||
*/
|
||||
appear()
|
||||
{
|
||||
turn_off(player, ISINVIS);
|
||||
PLAYER = VPLAYER;
|
||||
msg("The tingling feeling leaves your body");
|
||||
light(&hero);
|
||||
}
|
||||
/*
|
||||
* dust_appear:
|
||||
* dust of disappearance wears off
|
||||
*/
|
||||
dust_appear()
|
||||
{
|
||||
turn_off(player, ISINVIS);
|
||||
PLAYER = VPLAYER;
|
||||
msg("You become visible again");
|
||||
light(&hero);
|
||||
}
|
||||
/*
|
||||
* unchoke:
|
||||
* the effects of "dust of choking and sneezing" wear off
|
||||
*/
|
||||
unchoke()
|
||||
{
|
||||
if (!find_slot(unconfuse))
|
||||
turn_off(player, ISHUH);
|
||||
if (!find_slot(sight))
|
||||
turn_off(player, ISBLIND);
|
||||
light(&hero);
|
||||
msg("Your throat and eyes return to normal");
|
||||
}
|
||||
/*
|
||||
* make some potion for the guy in the Alchemy jug
|
||||
*/
|
||||
alchemy(obj)
|
||||
register struct object *obj;
|
||||
{
|
||||
register struct object *tobj;
|
||||
register struct linked_list *item;
|
||||
|
||||
/*
|
||||
* verify that the object pointer we have still points to an alchemy
|
||||
* jug (hopefully the right one!) because the hero could have thrown
|
||||
* it away
|
||||
*/
|
||||
for (item = pack; item != NULL; item = next(item)) {
|
||||
tobj = OBJPTR(item);
|
||||
if (tobj == obj &&
|
||||
tobj->o_type == MM &&
|
||||
tobj->o_which== MM_JUG &&
|
||||
tobj->o_ac == JUG_EMPTY )
|
||||
break;
|
||||
}
|
||||
if (item == NULL) { /* not in the pack, check the level */
|
||||
for (item = lvl_obj; item != NULL; item = next(item)) {
|
||||
tobj = OBJPTR(item);
|
||||
if (tobj == obj &&
|
||||
tobj->o_type == MM &&
|
||||
tobj->o_which== MM_JUG &&
|
||||
tobj->o_ac == JUG_EMPTY )
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (item == NULL) /* can't find it.....too bad */
|
||||
return;
|
||||
|
||||
switch(rnd(11)) {
|
||||
case 0: tobj->o_ac = P_PHASE;
|
||||
when 1: tobj->o_ac = P_CLEAR;
|
||||
when 2: tobj->o_ac = P_SEEINVIS;
|
||||
when 3: tobj->o_ac = P_HEALING;
|
||||
when 4: tobj->o_ac = P_MFIND;
|
||||
when 5: tobj->o_ac = P_TFIND;
|
||||
when 6: tobj->o_ac = P_HASTE;
|
||||
when 7: tobj->o_ac = P_RESTORE;
|
||||
when 8: tobj->o_ac = P_FLY;
|
||||
when 9: tobj->o_ac = P_SKILL;
|
||||
when 10:tobj->o_ac = P_FFIND;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* otto's irresistable dance wears off
|
||||
*/
|
||||
|
||||
undance()
|
||||
{
|
||||
turn_off(player, ISDANCE);
|
||||
msg ("Your feet take a break.....whew!");
|
||||
}
|
||||
|
||||
/*
|
||||
* if he has our favorite necklace of strangulation then take damage every turn
|
||||
*/
|
||||
strangle()
|
||||
{
|
||||
if ((pstats.s_hpt -= 6) <= 0) death(D_STRANGLE);
|
||||
}
|
||||
/*
|
||||
* if he has on the gauntlets of fumbling he might drop his weapon each turn
|
||||
*/
|
||||
fumble()
|
||||
{
|
||||
register struct linked_list *item;
|
||||
|
||||
if (cur_weapon!=NULL &&
|
||||
!(cur_weapon->o_flags & ISCURSED) &&
|
||||
cur_weapon->o_type != RELIC &&
|
||||
rnd(100)<3) {
|
||||
for (item = pack; item != NULL; item = next(item)) {
|
||||
if (OBJPTR(item) == cur_weapon)
|
||||
break;
|
||||
}
|
||||
if (item != NULL) {
|
||||
switch(mvwinch(stdscr, hero.y, hero.x)) {
|
||||
case PASSAGE:
|
||||
case SCROLL:
|
||||
case POTION:
|
||||
case WEAPON:
|
||||
case FLOOR:
|
||||
case STICK:
|
||||
case ARMOR:
|
||||
case POOL:
|
||||
case RELIC:
|
||||
case GOLD:
|
||||
case FOOD:
|
||||
case RING:
|
||||
case MM:
|
||||
drop(item);
|
||||
running = FALSE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* this is called each turn the hero has the ring of searching on
|
||||
*/
|
||||
ring_search()
|
||||
{
|
||||
search(FALSE, FALSE);
|
||||
}
|
||||
/*
|
||||
* this is called each turn the hero has the ring of teleportation on
|
||||
*/
|
||||
ring_teleport()
|
||||
{
|
||||
if (rnd(100) < 2) teleport();
|
||||
}
|
||||
/*
|
||||
* this is called to charge up the quill of Nagrom
|
||||
*/
|
||||
quill_charge()
|
||||
{
|
||||
register struct object *tobj;
|
||||
register struct linked_list *item;
|
||||
|
||||
/*
|
||||
* find the Quill of Nagrom in the hero's pack. It should still be there
|
||||
* because it can't be dropped. If its not then don't do anything.
|
||||
*/
|
||||
for (item = pack; item != NULL; item = next(item)) {
|
||||
tobj = OBJPTR(item);
|
||||
if (tobj->o_type == RELIC && tobj->o_which == QUILL_NAGROM)
|
||||
break;
|
||||
}
|
||||
if (item == NULL)
|
||||
return;
|
||||
if (tobj->o_charges < QUILLCHARGES)
|
||||
tobj->o_charges++;
|
||||
fuse (quill_charge, 0, player.t_ctype == C_MAGICIAN ? 4 : 8, AFTER);
|
||||
}
|
||||
/*
|
||||
* take the skills away gained (or lost) by the potion of skills
|
||||
*/
|
||||
unskill()
|
||||
{
|
||||
if (pstats.s_lvladj != 0) {
|
||||
pstats.s_lvl -= pstats.s_lvladj;
|
||||
pstats.s_lvladj = 0;
|
||||
msg("You feel your normal skill level return.");
|
||||
status(TRUE);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* charge up the cloak of Emori
|
||||
*/
|
||||
|
||||
cloak_charge(obj)
|
||||
register struct object *obj;
|
||||
{
|
||||
if (obj->o_charges < 1)
|
||||
obj->o_charges = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* nofire:
|
||||
* He lost his fire resistance
|
||||
*/
|
||||
nofire()
|
||||
{
|
||||
if (!ISWEARING(R_FIRE)) {
|
||||
turn_off(player, NOFIRE);
|
||||
msg("Your feeling of fire resistance leaves you");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* nocold:
|
||||
* He lost his cold resistance
|
||||
*/
|
||||
nocold()
|
||||
{
|
||||
if (!ISWEARING(R_WARMTH)) {
|
||||
turn_off(player, NOCOLD);
|
||||
msg("Your feeling of warmth leaves you");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* nobolt:
|
||||
* He lost his protection from lightning
|
||||
*/
|
||||
nobolt()
|
||||
{
|
||||
turn_off(player, NOBOLT);
|
||||
msg("Your skin looses its bluish tint");
|
||||
}
|
||||
/*
|
||||
* eat_gold:
|
||||
* an artifact eats gold
|
||||
*/
|
||||
eat_gold(obj)
|
||||
register struct object *obj;
|
||||
{
|
||||
if (purse == 1)
|
||||
msg("%s demand you find more gold", inv_name(obj, FALSE));
|
||||
if (purse == 0) {
|
||||
if (--pstats.s_hpt <= 0)
|
||||
death(D_RELIC);
|
||||
}
|
||||
else
|
||||
purse--;
|
||||
}
|
||||
/*
|
||||
* give the hero back some spell points
|
||||
*/
|
||||
spell_recovery()
|
||||
{
|
||||
int time;
|
||||
|
||||
time = SPELLTIME - max(17-pstats.s_intel, 0);
|
||||
time = max(time, 5);
|
||||
if (spell_power > 0) spell_power--;
|
||||
fuse(spell_recovery, NULL, time, AFTER);
|
||||
}
|
||||
/*
|
||||
* give the hero back some prayer points
|
||||
*/
|
||||
prayer_recovery()
|
||||
{
|
||||
int time;
|
||||
|
||||
time = SPELLTIME - max(17-pstats.s_wisdom, 0);
|
||||
time = max(time, 5);
|
||||
if (pray_time > 0) pray_time--;
|
||||
fuse(prayer_recovery, NULL, time, AFTER);
|
||||
}
|
||||
/*
|
||||
* give the hero back some chant points
|
||||
*/
|
||||
chant_recovery()
|
||||
{
|
||||
int time;
|
||||
|
||||
time = SPELLTIME - max(17-pstats.s_wisdom, 0);
|
||||
time = max(time, 5);
|
||||
if (chant_time > 0) chant_time--;
|
||||
fuse(chant_recovery, NULL, time, AFTER);
|
||||
}
|
||||
130
arogue7/eat.c
Normal file
130
arogue7/eat.c
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* eat.c - Functions for dealing with digestion
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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 "curses.h"
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* eat:
|
||||
* He wants to eat something, so let him try
|
||||
*/
|
||||
|
||||
eat()
|
||||
{
|
||||
register struct linked_list *item;
|
||||
int which;
|
||||
unsigned long temp;
|
||||
|
||||
if (player.t_action != C_EAT) {
|
||||
if ((item = get_item(pack, "eat", FOOD, FALSE, FALSE)) == NULL)
|
||||
return;
|
||||
|
||||
player.t_using = item; /* Remember what it is */
|
||||
player.t_action = C_EAT; /* We are eating */
|
||||
which = (OBJPTR(item))->o_which;
|
||||
player.t_no_move = max(foods[which].mi_food/100, 1) * movement(&player);
|
||||
return;
|
||||
}
|
||||
|
||||
/* We have waited our time, let's eat the food */
|
||||
item = player.t_using;
|
||||
player.t_using = NULL;
|
||||
player.t_action = A_NIL;
|
||||
|
||||
which = (OBJPTR(item))->o_which;
|
||||
if ((food_left += foods[which].mi_food) > STOMACHSIZE)
|
||||
food_left = STOMACHSIZE;
|
||||
del_pack(item);
|
||||
if (hungry_state == F_SATIATED && food_left == STOMACHSIZE && rnd(4) == 1) {
|
||||
pstats.s_hpt = 0;
|
||||
msg ("You choke on all that food and die! -- More --");
|
||||
wait_for(' ');
|
||||
death(D_FOOD_CHOKE);
|
||||
}
|
||||
if (food_left >= STOMACHSIZE-MORETIME) {
|
||||
hungry_state = F_SATIATED;
|
||||
msg ("You have trouble getting all that food down.");
|
||||
msg ("Your stomach feels like its about to burst!");
|
||||
}
|
||||
else {
|
||||
hungry_state = F_OKAY;
|
||||
switch (rnd(3)) {
|
||||
case 0: msg("My, that was a yummy %s", foods[which].mi_name);
|
||||
when 1: msg("Mmmm, that was a tasty %s", foods[which].mi_name);
|
||||
when 2: msg("Wow, that was a scrumptious %s", foods[which].mi_name);
|
||||
}
|
||||
}
|
||||
updpack(TRUE, &player);
|
||||
switch(which) {
|
||||
case E_WHORTLEBERRY:
|
||||
add_abil[A_INTELLIGENCE](1);
|
||||
|
||||
when E_SWEETSOP:
|
||||
add_abil[A_DEXTERITY](1);
|
||||
|
||||
when E_SOURSOP:
|
||||
add_abil[A_STRENGTH](1);
|
||||
|
||||
when E_SAPODILLA:
|
||||
add_abil[A_WISDOM](1);
|
||||
|
||||
when E_RAMBUTAN:
|
||||
add_abil[A_CONSTITUTION](1);
|
||||
|
||||
when E_PEACH:
|
||||
add_abil[A_CHARISMA](1);
|
||||
|
||||
when E_STRAWBERRY:
|
||||
temp = pstats.s_exp/100;
|
||||
pstats.s_exp += temp;
|
||||
if (temp > 0)
|
||||
msg("You feel slightly more experienced now");
|
||||
check_level();
|
||||
|
||||
when E_PITANGA:
|
||||
max_stats.s_hpt++;
|
||||
pstats.s_hpt++;
|
||||
if (terse)
|
||||
msg("You feel a bit tougher now");
|
||||
else
|
||||
msg("You feel a bit tougher now. Go get 'em!");
|
||||
|
||||
when E_HAGBERRY:
|
||||
pstats.s_arm--;
|
||||
msg("Your skin feels more resilient now");
|
||||
|
||||
when E_DEWBERRY:
|
||||
if (chant_time > 0) {
|
||||
chant_time -= 50;
|
||||
if (chant_time < 0)
|
||||
chant_time = 0;
|
||||
msg("You feel you have more chant ability");
|
||||
}
|
||||
if (pray_time > 0) {
|
||||
pray_time -= 50;
|
||||
if (pray_time < 0)
|
||||
pray_time = 0;
|
||||
msg("You feel you have more prayer ability");
|
||||
}
|
||||
if (spell_power > 0) {
|
||||
spell_power -= 50;
|
||||
if (spell_power < 0)
|
||||
spell_power = 0;
|
||||
msg("You feel you have more spell casting ability");
|
||||
}
|
||||
|
||||
otherwise: /* all the foods don't have to do something */
|
||||
break;
|
||||
}
|
||||
}
|
||||
699
arogue7/effects.c
Normal file
699
arogue7/effects.c
Normal file
|
|
@ -0,0 +1,699 @@
|
|||
/*
|
||||
* effects.c - functions for dealing with appllying effects to monsters
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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 "curses.h"
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* effect:
|
||||
* Check for effects of one thing hitting another thing. Return
|
||||
* the reason code if the defender is killed. Otherwise return 0.
|
||||
*/
|
||||
effect(att, def, weap, thrown, see_att, see_def)
|
||||
register struct thing *att, *def;
|
||||
struct object *weap;
|
||||
bool thrown;
|
||||
register bool see_att, see_def;
|
||||
{
|
||||
register bool att_player, def_player;
|
||||
char attname[LINELEN+1], defname[LINELEN+1];
|
||||
|
||||
/* See if the attacker or defender is the player */
|
||||
att_player = (att == &player);
|
||||
def_player = (def == &player);
|
||||
|
||||
/*
|
||||
* If the player could see the attacker or defender, they can't
|
||||
* surprise anymore (don't bother checking if they could).
|
||||
*/
|
||||
if (see_att) turn_off(*att, CANSURPRISE);
|
||||
if (see_def) turn_off(*def, CANSURPRISE);
|
||||
|
||||
/* What are the attacker and defender names? */
|
||||
if (att_player) strcpy(attname, "you");
|
||||
else {
|
||||
if (see_att) strcpy(attname, monster_name(att));
|
||||
else strcpy(attname, "something");
|
||||
}
|
||||
|
||||
if (def_player) strcpy(defname, "you");
|
||||
else {
|
||||
if (see_def) strcpy(defname, monster_name(def));
|
||||
else strcpy(defname, "something");
|
||||
}
|
||||
|
||||
/*
|
||||
* See what happens to the attacker first. We can skip this
|
||||
* whole section, however, if the defender is the player.
|
||||
* Nothing happens (yet) to anyone just for hitting the player.
|
||||
*/
|
||||
if (!def_player) {
|
||||
if (!thrown) { /* Some things require a direct hit. */
|
||||
/*
|
||||
* If the attacker hits a rusting monster, The weapon
|
||||
* may be damaged
|
||||
*/
|
||||
if (on(*def, CANRUST) && weap &&
|
||||
weap->o_type != RELIC && (weap->o_flags & ISMETAL) &&
|
||||
!(weap->o_flags & ISPROT)) {
|
||||
if ((weap->o_hplus < 1 && weap->o_dplus < 1) ||
|
||||
roll(1,20) < weap->o_hplus+weap->o_dplus+10) {
|
||||
if (rnd(100) < 50) weap->o_hplus--;
|
||||
else weap->o_dplus--;
|
||||
if (att_player)
|
||||
msg(terse ? "Your %s weakens!"
|
||||
: "Your %s appears to be weaker now!",
|
||||
weaps[weap->o_which].w_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If the attacker hit something that shrieks, wake the dungeon */
|
||||
if (on(*def, CANSHRIEK)) {
|
||||
turn_off(*def, CANSHRIEK);
|
||||
if (see_def)
|
||||
msg("%s emits a piercing shriek.", prname(defname, TRUE));
|
||||
else msg("You hear a piercing shriek.");
|
||||
aggravate(TRUE, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* does the creature explode when hit?
|
||||
*/
|
||||
if (on(*def, CANEXPLODE)) {
|
||||
if (see_def) msg("%s explodes!", prname(defname, TRUE));
|
||||
else msg("You hear a tremendous explosion!");
|
||||
explode(def);
|
||||
if (pstats.s_hpt <= 0)
|
||||
death(def->t_index);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now let's see what happens to the defender. Start out with
|
||||
* the things that everyone can do. Then exit if the attacker
|
||||
* is the player.
|
||||
*/
|
||||
if (!thrown) {
|
||||
/*
|
||||
* Can the player confuse?
|
||||
*/
|
||||
if (on(*att, CANHUH) && att_player) {
|
||||
msg("Your hands stop glowing red.");
|
||||
if (off(*def, ISCLEAR) &&
|
||||
(off(*def, ISUNIQUE) || !save(VS_MAGIC, def, 0))) {
|
||||
if (see_def) msg("%s appears confused.", prname(defname, TRUE));
|
||||
turn_on(*def, ISHUH);
|
||||
}
|
||||
turn_off(*att, CANHUH);
|
||||
}
|
||||
|
||||
/* Return now if the attacker is the player. */
|
||||
if (att_player) return(0);
|
||||
|
||||
/*
|
||||
* Some monsters may take half your hit points
|
||||
*/
|
||||
if (on(*att, CANSUCK) && !save(VS_MAGIC, def, 0)) {
|
||||
if (def->t_stats.s_hpt == 1) return(att->t_index); /* Killed! */
|
||||
else {
|
||||
def->t_stats.s_hpt /= 2;
|
||||
if (def_player)
|
||||
msg("You feel your life force being drawn from you.");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If a hugging monster hits, it may SQUEEEEEEEZE.
|
||||
*/
|
||||
if (on(*att, CANHUG)) {
|
||||
if (roll(1,20) >= 18 || roll(1,20) >= 18) {
|
||||
if (def_player)
|
||||
msg("%s squeezes you against itself.",
|
||||
prname(attname, TRUE));
|
||||
else if (see_att)
|
||||
msg("%s squeezes hard.", prname(attname, TRUE));
|
||||
|
||||
if ((def->t_stats.s_hpt -= roll(2,8)) <= 0)
|
||||
return(att->t_index);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Some monsters have poisonous bites.
|
||||
*/
|
||||
if (on(*att, CANPOISON) && !save(VS_POISON, def, 0)) {
|
||||
if (def_player) {
|
||||
if (ISWEARING(R_SUSABILITY))
|
||||
msg(terse ? "Sting has no effect"
|
||||
: "A sting momentarily weakens you");
|
||||
else {
|
||||
chg_str(-1);
|
||||
msg(terse ? "A sting has weakened you" :
|
||||
"You feel a sting in your arm and now feel weaker");
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Subtract a strength point and see if it kills it */
|
||||
if (--def->t_stats.s_str <= 0) return(D_STRENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Turning to stone:
|
||||
*/
|
||||
if (on(*att, TOUCHSTONE)) {
|
||||
if (def_player) turn_off(*att, TOUCHSTONE);
|
||||
if (on(*def, CANINWALL)) {
|
||||
if (def_player)
|
||||
msg("%s's touch has no effect.", prname(attname, TRUE));
|
||||
}
|
||||
else {
|
||||
if (!save(VS_PETRIFICATION, def, 0) && rnd(100) < 10) {
|
||||
if (def_player) {
|
||||
msg("Your body begins to solidify.");
|
||||
msg("You are turned to stone !!! --More--");
|
||||
wait_for(' ');
|
||||
return(D_PETRIFY);
|
||||
}
|
||||
else {
|
||||
/* The monster got stoned! */
|
||||
turn_on(*def, ISSTONE);
|
||||
turn_off(*def, ISRUN);
|
||||
turn_off(*def, ISINVIS);
|
||||
turn_off(*def, ISDISGUISE);
|
||||
if (see_def)
|
||||
msg("%s turns to stone.", prname(defname, TRUE));
|
||||
else if (cansee(unc(def->t_pos)))
|
||||
msg("A new statue appears!");
|
||||
}
|
||||
}
|
||||
else if (def->t_action != A_FREEZE) {
|
||||
if (def_player)
|
||||
msg("%s's touch stiffens your limbs.",
|
||||
prname(attname, TRUE));
|
||||
else if (see_def)
|
||||
msg("%s appears to freeze.", prname(defname, TRUE));
|
||||
|
||||
def->t_no_move += movement(def) * STONETIME;
|
||||
def->t_action = A_FREEZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Wraiths might drain energy levels
|
||||
*/
|
||||
if ((on(*att, CANDRAIN) || on(*att, DOUBLEDRAIN)) &&
|
||||
!save(VS_POISON, def, 3-(att->t_stats.s_lvl/5))) {
|
||||
if (def_player) {
|
||||
lower_level(att->t_index);
|
||||
if (on(*att, DOUBLEDRAIN)) lower_level(att->t_index);
|
||||
turn_on(*att, DIDDRAIN);
|
||||
}
|
||||
else {
|
||||
def->t_stats.s_hpt -= roll(1, 8);
|
||||
def->t_stats.s_lvl--;
|
||||
if (on(*att, DOUBLEDRAIN)) {
|
||||
def->t_stats.s_hpt -= roll(1, 8);
|
||||
def->t_stats.s_lvl--;
|
||||
}
|
||||
if (see_def)
|
||||
msg("%s appears less skillfull.", prname(defname, TRUE));
|
||||
|
||||
/* Did it kill it? */
|
||||
if (def->t_stats.s_hpt <= 0 ||
|
||||
def->t_stats.s_lvl <= 0)
|
||||
return(att->t_index);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Paralyzation:
|
||||
*/
|
||||
if (on(*att, CANPARALYZE) && def->t_action != A_FREEZE) {
|
||||
if (def_player) turn_off(*att, CANPARALYZE);
|
||||
if (!save(VS_PARALYZATION, def, 0)) {
|
||||
if (on(*def, CANINWALL)) {
|
||||
if (def_player)
|
||||
msg("%s's touch has no effect.", prname(attname, TRUE));
|
||||
}
|
||||
else {
|
||||
if (def_player)
|
||||
msg("%s's touch paralyzes you.", prname(attname, TRUE));
|
||||
else if (see_def)
|
||||
msg("%s appears to freeze.", prname(defname, TRUE));
|
||||
|
||||
def->t_no_move += movement(def) * FREEZETIME;
|
||||
def->t_action = A_FREEZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Painful wounds make the defendant faint
|
||||
*/
|
||||
if (on(*att, CANPAIN) && def->t_action != A_FREEZE) {
|
||||
if (def_player) turn_off(*att, CANPAIN);
|
||||
if (!ISWEARING(R_ALERT) && !save(VS_POISON, def, 0)) {
|
||||
if (def_player)
|
||||
msg("You faint from the painful wound");
|
||||
else if (see_def)
|
||||
msg("%s appears to faint.", prname(defname, TRUE));
|
||||
|
||||
def->t_no_move += movement(def) * PAINTIME;
|
||||
def->t_action = A_FREEZE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Some things currently affect only the player. Let's make
|
||||
* a check here so we don't have to check for each thing.
|
||||
*/
|
||||
if (def_player) {
|
||||
/*
|
||||
* Stinking monsters make the defender weaker (to hit). For now
|
||||
* this will only affect the player. We may later add the HASSTINK
|
||||
* effect to monsters, too.
|
||||
*/
|
||||
if (on(*att, CANSTINK)) {
|
||||
turn_off(*att, CANSTINK);
|
||||
if (!save(VS_POISON, def, 0)) {
|
||||
msg("The stench of %s sickens you.",
|
||||
prname(attname, FALSE));
|
||||
if (on(player, HASSTINK)) lengthen(unstink, STINKTIME);
|
||||
else {
|
||||
turn_on(player, HASSTINK);
|
||||
fuse(unstink, 0, STINKTIME, AFTER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Chilling monster reduces strength each time. This only
|
||||
* affects the player for now because of its temporary nature.
|
||||
*/
|
||||
if (on(*att, CANCHILL)) {
|
||||
if (!ISWEARING(R_SUSABILITY) && !save(VS_POISON, def, 0)) {
|
||||
msg("You cringe at %s's chilling touch.",
|
||||
prname(attname, FALSE));
|
||||
chg_str(-1);
|
||||
if (lost_str++ == 0)
|
||||
fuse(res_strength, 0, CHILLTIME, AFTER);
|
||||
else lengthen(res_strength, CHILLTIME);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Itching monsters reduce dexterity (temporarily). This only
|
||||
* affects the player for now because of its temporary nature.
|
||||
*/
|
||||
if (on(*att, CANITCH) && !save(VS_POISON, def, 0)) {
|
||||
msg("The claws of %s scratch you.", prname(attname, FALSE));
|
||||
if (ISWEARING(R_SUSABILITY)) {
|
||||
msg("The scratch has no effect");
|
||||
}
|
||||
else {
|
||||
add_abil[A_DEXTERITY](-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If a disease-carrying monster hits, there is a chance the
|
||||
* defender will catch the disease. This only applies to the
|
||||
* player for now because of the temporary nature.
|
||||
*/
|
||||
if (on(*att, CANDISEASE) &&
|
||||
(rnd(def->t_stats.s_const) < att->t_stats.s_lvl) &&
|
||||
off(*def, HASDISEASE)) {
|
||||
if (ISWEARING(R_HEALTH) ||
|
||||
player.t_ctype == C_PALADIN ||
|
||||
player.t_ctype == C_MONK) {
|
||||
msg("The wound heals quickly.");
|
||||
}
|
||||
else {
|
||||
turn_on(*def, HASDISEASE);
|
||||
fuse(cure_disease, 0, roll(HEALTIME,SICKTIME), AFTER);
|
||||
msg(terse ? "You have been diseased."
|
||||
: "You have contracted a disease!");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If a rusting monster hits, you lose armor. This only applies to
|
||||
* the player because monsters don't wear armor (for now).
|
||||
*/
|
||||
if (on(*att, CANRUST)) {
|
||||
if (cur_armor != NULL &&
|
||||
cur_armor->o_which != LEATHER &&
|
||||
cur_armor->o_which != STUDDED_LEATHER &&
|
||||
cur_armor->o_which != PADDED_ARMOR &&
|
||||
!(cur_armor->o_flags & ISPROT) &&
|
||||
cur_armor->o_ac < def->t_stats.s_arm+1) {
|
||||
msg(terse ? "Your armor weakens"
|
||||
: "Your armor appears to be weaker now. Oh my!");
|
||||
cur_armor->o_ac++;
|
||||
}
|
||||
if (cur_misc[WEAR_BRACERS] != NULL &&
|
||||
cur_misc[WEAR_BRACERS]->o_ac > 0 &&
|
||||
!(cur_misc[WEAR_BRACERS]->o_flags & ISPROT)) {
|
||||
cur_misc[WEAR_BRACERS]->o_ac--;
|
||||
if (cur_misc[WEAR_BRACERS]->o_ac == 0) {
|
||||
register struct linked_list *item;
|
||||
|
||||
for (item=pack; item!=NULL; item=next(item)) {
|
||||
if (OBJPTR(item) == cur_misc[WEAR_BRACERS]) {
|
||||
detach(pack, item);
|
||||
o_discard(item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
msg ("Your bracers crumble and fall off!");
|
||||
cur_misc[WEAR_BRACERS] = NULL;
|
||||
inpack--;
|
||||
}
|
||||
else {
|
||||
msg("Your bracers weaken!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If can dissolve and hero has leather type armor. This
|
||||
* also only applies to the player for now because of the
|
||||
* armor.
|
||||
*/
|
||||
if (on(*att, CANDISSOLVE) && cur_armor != NULL &&
|
||||
(cur_armor->o_which == LEATHER ||
|
||||
cur_armor->o_which == STUDDED_LEATHER ||
|
||||
cur_armor->o_which == PADDED_ARMOR) &&
|
||||
!(cur_armor->o_flags & ISPROT) &&
|
||||
cur_armor->o_ac < def->t_stats.s_arm+1) {
|
||||
msg(terse ? "Your armor dissolves"
|
||||
: "Your armor appears to dissolve. Oh my!");
|
||||
cur_armor->o_ac++;
|
||||
}
|
||||
|
||||
/*
|
||||
* If an infesting monster hits you, you get a parasite or rot.
|
||||
* This will only affect the player until we figure out how to
|
||||
* make it affect monsters.
|
||||
*/
|
||||
if (on(*att, CANINFEST) &&
|
||||
rnd(def->t_stats.s_const) < att->t_stats.s_lvl) {
|
||||
if (ISWEARING(R_HEALTH) ||
|
||||
player.t_ctype == C_PALADIN ||
|
||||
player.t_ctype == C_MONK) {
|
||||
msg("The wound heals quickly.");
|
||||
}
|
||||
else {
|
||||
turn_off(*att, CANINFEST);
|
||||
msg(terse ? "You have been infested."
|
||||
: "You have contracted a parasitic infestation!");
|
||||
infest_dam++;
|
||||
turn_on(*def, HASINFEST);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Does it take wisdom away? This currently affects only
|
||||
* the player because of its temporary nature.
|
||||
*/
|
||||
if (on(*att, TAKEWISDOM) &&
|
||||
!save(VS_MAGIC, def, 0) &&
|
||||
!ISWEARING(R_SUSABILITY)) {
|
||||
add_abil[A_WISDOM](-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Does it take intelligence away? This currently affects
|
||||
* only the player because of its temporary nature.
|
||||
*/
|
||||
if (on(*att, TAKEINTEL) &&
|
||||
!save(VS_MAGIC, &player, 0) &&
|
||||
!ISWEARING(R_SUSABILITY)) {
|
||||
add_abil[A_INTELLIGENCE](-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Cause fear by touching. This currently affects only
|
||||
* the player until we figure out how we want it to
|
||||
* affect monsters.
|
||||
*/
|
||||
if (on(*att, TOUCHFEAR)) {
|
||||
turn_off(*att, TOUCHFEAR);
|
||||
if (!ISWEARING(R_HEROISM) &&
|
||||
!save(VS_WAND, def, 0) &&
|
||||
!(on(*def, ISFLEE) && (def->t_dest == &att->t_pos))) {
|
||||
turn_on(*def, ISFLEE);
|
||||
def->t_dest = &att->t_pos;
|
||||
msg("%s's touch terrifies you.", prname(attname, TRUE));
|
||||
|
||||
/* It is okay to turn tail */
|
||||
if (!def_player) def->t_oldpos = def->t_pos;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Make the hero dance (as in otto's irresistable dance)
|
||||
* This should be fairly easy to do to monsters, but
|
||||
* we'll restrict it to players until we decide what to
|
||||
* do about the temporary nature.
|
||||
*/
|
||||
if (on(*att, CANDANCE) &&
|
||||
!on(*def, ISDANCE) &&
|
||||
def->t_action != A_FREEZE &&
|
||||
!save(VS_MAGIC, def, -4)) {
|
||||
turn_off(*att, CANDANCE);
|
||||
turn_on(*def, ISDANCE);
|
||||
msg("You begin to dance uncontrollably!");
|
||||
fuse(undance, 0, roll(2,4), AFTER);
|
||||
}
|
||||
|
||||
/*
|
||||
* Suffocating our hero. Monsters don't get suffocated.
|
||||
* That's too hard for now.
|
||||
*/
|
||||
if (on(*att, CANSUFFOCATE) &&
|
||||
!ISWEARING(R_FREEDOM) &&
|
||||
rnd(100) < 25 &&
|
||||
(find_slot(suffocate) == 0)) {
|
||||
turn_on(*att, DIDSUFFOCATE);
|
||||
msg("%s is beginning to suffocate you.", prname(attname, TRUE));
|
||||
fuse(suffocate, 0, roll(9,3), AFTER);
|
||||
}
|
||||
|
||||
/*
|
||||
* some creatures stops the poor guy from moving.
|
||||
* How can we do this to a monster?
|
||||
*/
|
||||
if (on(*att,CANHOLD) && off(*att,DIDHOLD) && !ISWEARING(R_FREEDOM)){
|
||||
turn_on(*def, ISHELD);
|
||||
turn_on(*att, DIDHOLD);
|
||||
hold_count++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sucker will suck blood and run. This
|
||||
* should be easy to have happen to a monster,
|
||||
* but we have to decide how to handle the fleeing.
|
||||
*/
|
||||
if (on(*att, CANDRAW)) {
|
||||
turn_off(*att, CANDRAW);
|
||||
turn_on(*att, ISFLEE);
|
||||
msg("%s sates itself with your blood.", prname(attname, TRUE));
|
||||
if ((def->t_stats.s_hpt -= 12) <= 0) return(att->t_index);
|
||||
|
||||
/* It is okay to turn tail */
|
||||
att->t_oldpos = att->t_pos;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bad smell will force a reduction in strength.
|
||||
* This will happen only to the player because of
|
||||
* the temporary nature.
|
||||
*/
|
||||
if (on(*att, CANSMELL)) {
|
||||
turn_off(*att, CANSMELL);
|
||||
if (save(VS_MAGIC, def, 0) || ISWEARING(R_SUSABILITY))
|
||||
msg("You smell an unpleasant odor.");
|
||||
else {
|
||||
int odor_str = -(rnd(6)+1);
|
||||
|
||||
msg("You are overcome by a foul odor.");
|
||||
if (lost_str == 0) {
|
||||
chg_str(odor_str);
|
||||
fuse(res_strength, 0, SMELLTIME, AFTER);
|
||||
lost_str -= odor_str;
|
||||
}
|
||||
else lengthen(res_strength, SMELLTIME);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The monsters touch slows the defendant down.
|
||||
*/
|
||||
if (on(*att, TOUCHSLOW)) {
|
||||
turn_off(*att, TOUCHSLOW);
|
||||
if (!save(VS_PARALYZATION, def, 0))
|
||||
add_slow();
|
||||
}
|
||||
|
||||
/*
|
||||
* Rotting only affects the player.
|
||||
*/
|
||||
if (on(*att, CANROT)) {
|
||||
if (!ISWEARING(R_HEALTH) &&
|
||||
player.t_ctype != C_PALADIN &&
|
||||
player.t_ctype != C_MONK &&
|
||||
!save(VS_POISON, def, 0) &&
|
||||
off(*def, DOROT)) {
|
||||
turn_on(*def, DOROT);
|
||||
msg("You feel your skin starting to rot away!");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Monsters should be able to steal gold from anyone,
|
||||
* but until this is rewritten, they will only steal
|
||||
* from the player (tough break).
|
||||
*/
|
||||
if (on(*att, STEALGOLD)) {
|
||||
/*
|
||||
* steal some gold
|
||||
*/
|
||||
register long lastpurse;
|
||||
register struct linked_list *item;
|
||||
register struct object *obj;
|
||||
|
||||
lastpurse = purse;
|
||||
purse -= GOLDCALC + GOLDCALC;
|
||||
if (!save(VS_MAGIC, def, att->t_stats.s_lvl/10)) {
|
||||
if (on(*att, ISUNIQUE))
|
||||
purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC;
|
||||
purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC;
|
||||
}
|
||||
if (purse < 0)
|
||||
purse = 0;
|
||||
if (purse != lastpurse) {
|
||||
msg("Your purse feels lighter");
|
||||
|
||||
/* Give the gold to the thief */
|
||||
for (item=att->t_pack; item != NULL; item=next(item)) {
|
||||
obj = OBJPTR(item);
|
||||
if (obj->o_type == GOLD) {
|
||||
obj->o_count += lastpurse - purse;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Did we do it? */
|
||||
if (item == NULL) { /* Then make some */
|
||||
item = new_item(sizeof *obj);
|
||||
obj = OBJPTR(item);
|
||||
obj->o_type = GOLD;
|
||||
obj->o_count = lastpurse - purse;
|
||||
obj->o_hplus = obj->o_dplus = 0;
|
||||
strncpy(obj->o_damage, "0d0", sizeof(obj->o_damage));
|
||||
strncpy(obj->o_hurldmg, "0d0", sizeof(obj->o_hurldmg));
|
||||
obj->o_ac = 11;
|
||||
obj->contents = NULL;
|
||||
obj->o_group = 0;
|
||||
obj->o_flags = 0;
|
||||
obj->o_mark[0] = '\0';
|
||||
obj->o_pos = att->t_pos;
|
||||
|
||||
attach(att->t_pack, item);
|
||||
}
|
||||
}
|
||||
|
||||
turn_on(*att, ISFLEE);
|
||||
turn_on(*att, ISINVIS);
|
||||
|
||||
/* It is okay to turn tail */
|
||||
att->t_oldpos = att->t_pos;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Stealing happens last since the monster disappears
|
||||
* after the act.
|
||||
*/
|
||||
if (on(*att, STEALMAGIC)) {
|
||||
register struct linked_list *list, *steal;
|
||||
register struct object *obj;
|
||||
register int nobj;
|
||||
|
||||
/*
|
||||
* steal a magic item, look through the pack
|
||||
* and pick out one we like.
|
||||
*/
|
||||
steal = NULL;
|
||||
for (nobj = 0, list = def->t_pack; list != NULL; list = next(list))
|
||||
{
|
||||
obj = OBJPTR(list);
|
||||
if (!is_current(obj) &&
|
||||
list != def->t_using &&
|
||||
obj->o_type != RELIC &&
|
||||
is_magic(obj) &&
|
||||
rnd(++nobj) == 0)
|
||||
steal = list;
|
||||
}
|
||||
if (steal != NULL)
|
||||
{
|
||||
register struct object *obj;
|
||||
struct linked_list *item;
|
||||
|
||||
obj = OBJPTR(steal);
|
||||
if (on(*att, ISUNIQUE))
|
||||
monsters[att->t_index].m_normal = TRUE;
|
||||
item = find_mons(att->t_pos.y, att->t_pos.x);
|
||||
|
||||
killed(item, FALSE, FALSE, FALSE); /* Remove the attacker */
|
||||
|
||||
if (obj->o_count > 1 && obj->o_group == 0) {
|
||||
register int oc;
|
||||
|
||||
oc = --(obj->o_count);
|
||||
obj->o_count = 1;
|
||||
if (def_player)
|
||||
msg("%s stole %s!", prname(attname, TRUE),
|
||||
inv_name(obj, TRUE));
|
||||
obj->o_count = oc;
|
||||
}
|
||||
else {
|
||||
if (def_player) {
|
||||
msg("%s stole %s!", prname(attname, TRUE),
|
||||
inv_name(obj, TRUE));
|
||||
|
||||
/* If this is a relic, clear its holding field */
|
||||
if (obj->o_type == RELIC)
|
||||
cur_relic[obj->o_which] = 0;
|
||||
|
||||
inpack--;
|
||||
}
|
||||
|
||||
detach(def->t_pack, steal);
|
||||
o_discard(steal);
|
||||
}
|
||||
|
||||
updpack(FALSE, def);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Didn't kill the defender */
|
||||
return(0);
|
||||
}
|
||||
207
arogue7/encumb.c
Normal file
207
arogue7/encumb.c
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
* encumb.c - Stuff to do with encumberence
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Stuff to do with encumberence
|
||||
*
|
||||
*/
|
||||
|
||||
#include "curses.h"
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* updpack:
|
||||
* Update his pack weight and adjust fooduse accordingly
|
||||
*/
|
||||
updpack(getmax, tp)
|
||||
int getmax;
|
||||
struct thing *tp;
|
||||
{
|
||||
|
||||
reg int topcarry, curcarry;
|
||||
|
||||
if (getmax)
|
||||
tp->t_stats.s_carry = totalenc(tp); /* get total encumb */
|
||||
curcarry = packweight(tp); /* get pack weight */
|
||||
|
||||
/* Only update food use for the player (for now) */
|
||||
if (tp == &player) {
|
||||
topcarry = tp->t_stats.s_carry / 5; /* 20% of total carry */
|
||||
if(curcarry > 4 * topcarry) {
|
||||
if(rnd(100) < 80)
|
||||
foodlev = 3; /* > 80% of pack */
|
||||
} else if(curcarry > 3 * topcarry) {
|
||||
if(rnd(100) < 60)
|
||||
foodlev = 2; /* > 60% of pack */
|
||||
} else
|
||||
foodlev = 1; /* <= 60% of pack */
|
||||
}
|
||||
tp->t_stats.s_pack = curcarry; /* update pack weight */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* packweight:
|
||||
* Get the total weight of the hero's pack
|
||||
*/
|
||||
packweight(tp)
|
||||
register struct thing *tp;
|
||||
{
|
||||
reg struct object *obj;
|
||||
reg struct linked_list *pc;
|
||||
reg int weight;
|
||||
|
||||
weight = 0;
|
||||
for (pc = tp->t_pack ; pc != NULL ; pc = next(pc)) {
|
||||
obj = OBJPTR(pc);
|
||||
weight += itemweight(obj);
|
||||
}
|
||||
if (weight < 0) /* in case of amulet */
|
||||
weight = 0;
|
||||
|
||||
/* If this is the player, is he wearing a ring of carrying? */
|
||||
if (tp == &player && ISWEARING(R_CARRY)) {
|
||||
register int temp, i;
|
||||
|
||||
temp = 0;
|
||||
for (i=0; i<NUM_FINGERS; i++) {
|
||||
if (cur_ring[i]->o_which == R_CARRY) {
|
||||
if (cur_ring[i]->o_flags & ISCURSED) temp--;
|
||||
else temp++;
|
||||
}
|
||||
}
|
||||
weight -= (temp * weight) / 4;
|
||||
}
|
||||
|
||||
return(weight);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* itemweight:
|
||||
* Get the weight of an object
|
||||
*/
|
||||
itemweight(wh)
|
||||
reg struct object *wh;
|
||||
{
|
||||
reg int weight;
|
||||
reg int ac;
|
||||
|
||||
weight = wh->o_weight; /* get base weight */
|
||||
switch(wh->o_type) {
|
||||
case ARMOR:
|
||||
/*
|
||||
* subtract 10% for each enchantment
|
||||
* this will add weight for negative items
|
||||
*/
|
||||
ac = armors[wh->o_which].a_class - wh->o_ac;
|
||||
weight = ((weight*10) - (weight*ac)) / 10;
|
||||
if (weight < 0) weight = 0;
|
||||
when WEAPON:
|
||||
if ((wh->o_hplus + wh->o_dplus) > 0)
|
||||
weight /= 2;
|
||||
}
|
||||
if(wh->o_flags & ISCURSED)
|
||||
weight += weight / 5; /* 20% more for cursed */
|
||||
weight *= wh->o_count;
|
||||
return(weight);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* playenc:
|
||||
* Get hero's carrying ability above norm
|
||||
*/
|
||||
playenc(tp)
|
||||
register struct thing *tp;
|
||||
{
|
||||
register int strength;
|
||||
|
||||
if (tp == &player) strength = str_compute();
|
||||
else strength = tp->t_stats.s_str;
|
||||
|
||||
return ((strength-8)*50);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* totalenc:
|
||||
* Get total weight that the hero can carry
|
||||
*/
|
||||
totalenc(tp)
|
||||
register struct thing *tp;
|
||||
{
|
||||
reg int wtotal;
|
||||
|
||||
wtotal = NORMENCB + playenc(tp);
|
||||
if (tp == &player) switch(hungry_state) {
|
||||
case F_SATIATED:
|
||||
case F_OKAY:
|
||||
case F_HUNGRY: ; /* no change */
|
||||
when F_WEAK: wtotal -= wtotal / 10; /* 10% off weak */
|
||||
when F_FAINT: wtotal /= 2; /* 50% off faint */
|
||||
}
|
||||
return(wtotal);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* whgtchk:
|
||||
* See if the hero can carry his pack
|
||||
*/
|
||||
|
||||
wghtchk()
|
||||
{
|
||||
reg int dropchk, err = TRUE;
|
||||
reg char ch;
|
||||
int wghtchk();
|
||||
|
||||
inwhgt = TRUE;
|
||||
if (pstats.s_pack > pstats.s_carry) {
|
||||
ch = CCHAR( mvwinch(stdscr, hero.y, hero.x) );
|
||||
if((ch != FLOOR && ch != PASSAGE)) {
|
||||
extinguish(wghtchk);
|
||||
fuse(wghtchk,TRUE,1,AFTER);
|
||||
inwhgt = FALSE;
|
||||
return;
|
||||
}
|
||||
extinguish(wghtchk);
|
||||
msg("Your pack is too heavy for you");
|
||||
do {
|
||||
dropchk = drop(NULL);
|
||||
if(dropchk == 0) {
|
||||
mpos = 0;
|
||||
msg("You must drop something");
|
||||
}
|
||||
if(dropchk == TRUE)
|
||||
err = FALSE;
|
||||
} while(err);
|
||||
}
|
||||
inwhgt = FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* hitweight:
|
||||
* Gets the fighting ability according to current weight
|
||||
* This returns a +1 hit for light pack weight
|
||||
* 0 hit for medium pack weight
|
||||
* -1 hit for heavy pack weight
|
||||
*/
|
||||
|
||||
hitweight()
|
||||
{
|
||||
return(2 - foodlev);
|
||||
}
|
||||
1495
arogue7/fight.c
Normal file
1495
arogue7/fight.c
Normal file
File diff suppressed because it is too large
Load diff
624
arogue7/init.c
Normal file
624
arogue7/init.c
Normal file
|
|
@ -0,0 +1,624 @@
|
|||
/*
|
||||
* init.c - global variable initializaton
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* global variable initializaton
|
||||
*
|
||||
*/
|
||||
|
||||
#include "curses.h"
|
||||
#include <ctype.h>
|
||||
#include "rogue.h"
|
||||
#include "mach_dep.h"
|
||||
|
||||
|
||||
/*
|
||||
* If there is any news, put it in a character string and assign it to
|
||||
* rogue_news. Otherwise, assign NULL to rogue_news.
|
||||
*/
|
||||
static char *rogue_news = "You no longer fall into trading posts. They are \
|
||||
now entered like going down the stairs.";
|
||||
|
||||
char *rainbow[] = {
|
||||
|
||||
"amber", "aquamarine", "beige",
|
||||
"black", "blue", "brown",
|
||||
"clear", "crimson", "ecru",
|
||||
"gold", "green", "grey",
|
||||
"indigo", "khaki", "lavender",
|
||||
"magenta", "orange", "pink",
|
||||
"plaid", "purple", "red",
|
||||
"silver", "saffron", "scarlet",
|
||||
"tan", "tangerine", "topaz",
|
||||
"turquoise", "vermilion", "violet",
|
||||
"white", "yellow",
|
||||
};
|
||||
#define NCOLORS (sizeof rainbow / sizeof(char *))
|
||||
int cNCOLORS = NCOLORS;
|
||||
|
||||
static char *sylls[] = {
|
||||
"a", "ab", "ag", "aks", "ala", "an", "ankh", "app", "arg", "arze",
|
||||
"ash", "ban", "bar", "bat", "bek", "bie", "bin", "bit", "bjor",
|
||||
"blu", "bot", "bu", "byt", "comp", "con", "cos", "cre", "dalf",
|
||||
"dan", "den", "do", "e", "eep", "el", "eng", "er", "ere", "erk",
|
||||
"esh", "evs", "fa", "fid", "for", "fri", "fu", "gan", "gar",
|
||||
"glen", "gop", "gre", "ha", "he", "hyd", "i", "ing", "ion", "ip",
|
||||
"ish", "it", "ite", "iv", "jo", "kho", "kli", "klis", "la", "lech",
|
||||
"man", "mar", "me", "mi", "mic", "mik", "mon", "mung", "mur",
|
||||
"nej", "nelg", "nep", "ner", "nes", "net", "nih", "nin", "o", "od",
|
||||
"ood", "org", "orn", "ox", "oxy", "pay", "pet", "ple", "plu", "po",
|
||||
"pot", "prok", "re", "rea", "rhov", "ri", "ro", "rog", "rok", "rol",
|
||||
"sa", "san", "sat", "see", "sef", "seh", "shu", "ski", "sna",
|
||||
"sne", "snik", "sno", "so", "sol", "sri", "sta", "sun", "ta",
|
||||
"tab", "tem", "ther", "ti", "tox", "trol", "tue", "turs", "u",
|
||||
"ulk", "um", "un", "uni", "ur", "val", "viv", "vly", "vom", "wah",
|
||||
"wed", "werg", "wex", "whon", "wun", "xo", "y", "yot", "yu",
|
||||
"zant", "zap", "zeb", "zim", "zok", "zon", "zum",
|
||||
};
|
||||
|
||||
char *stones[] = {
|
||||
"agate", "alexandrite", "amethyst",
|
||||
"azurite", "bloodstone", "cairngorm",
|
||||
"carnelian", "chalcedony", "chrysoberyl",
|
||||
"chrysolite", "chrysoprase", "citrine",
|
||||
"coral", "diamond", "emerald",
|
||||
"garnet", "heliotrope", "hematite",
|
||||
"hyacinth", "jacinth", "jade",
|
||||
"jargoon", "jasper", "kryptonite",
|
||||
"lapus lazuli", "malachite", "mocca stone",
|
||||
"moonstone", "obsidian", "olivine",
|
||||
"onyx", "opal", "pearl",
|
||||
"peridot", "quartz", "rhodochrosite",
|
||||
"rhodolite", "ruby", "sapphire",
|
||||
"sardonyx", "serpintine", "spinel",
|
||||
"tiger eye", "topaz", "tourmaline",
|
||||
"turquoise", "zircon",
|
||||
};
|
||||
#define NSTONES (sizeof stones / sizeof(char *))
|
||||
int cNSTONES = NSTONES;
|
||||
|
||||
char *wood[] = {
|
||||
"avocado wood", "balsa", "banyan", "birch",
|
||||
"cedar", "cherry", "cinnibar", "dogwood",
|
||||
"driftwood", "ebony", "eucalyptus", "hemlock",
|
||||
"ironwood", "mahogany", "manzanita", "maple",
|
||||
"oak", "pine", "redwood", "rosewood",
|
||||
"teak", "walnut", "zebra wood", "persimmon wood",
|
||||
};
|
||||
#define NWOOD (sizeof wood / sizeof(char *))
|
||||
int cNWOOD = NWOOD;
|
||||
|
||||
char *metal[] = {
|
||||
"aluminium", "bone", "brass", "bronze",
|
||||
"copper", "chromium", "iron", "lead",
|
||||
"magnesium", "pewter", "platinum", "silver",
|
||||
"steel", "tin", "titanium", "zinc",
|
||||
};
|
||||
#define NMETAL (sizeof metal / sizeof(char *))
|
||||
int cNMETAL = NMETAL;
|
||||
#define MAX3(a,b,c) (a > b ? (a > c ? a : c) : (b > c ? b : c))
|
||||
|
||||
static bool used[MAX3(NCOLORS, NSTONES, NWOOD)];
|
||||
|
||||
|
||||
/*
|
||||
* make sure all the percentages specified in the tables add up to the
|
||||
* right amounts
|
||||
*/
|
||||
badcheck(name, magic, bound)
|
||||
char *name;
|
||||
register struct magic_item *magic;
|
||||
register int bound;
|
||||
{
|
||||
register struct magic_item *end;
|
||||
|
||||
if (magic[bound - 1].mi_prob == 1000)
|
||||
return;
|
||||
printf("\nBad percentages for %s:\n", name);
|
||||
for (end = &magic[bound] ; magic < end ; magic++)
|
||||
printf("%4d%% %s\n", magic->mi_prob, magic->mi_name);
|
||||
printf(retstr);
|
||||
fflush(stdout);
|
||||
while (getchar() != '\n')
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* init_colors:
|
||||
* Initialize the potion color scheme for this time
|
||||
*/
|
||||
|
||||
init_colors()
|
||||
{
|
||||
register int i, j;
|
||||
|
||||
for (i = 0; i < NCOLORS; i++)
|
||||
used[i] = FALSE;
|
||||
|
||||
for (i = 0 ; i < MAXPOTIONS ; i++)
|
||||
{
|
||||
do
|
||||
j = rnd(NCOLORS);
|
||||
until (!used[j]);
|
||||
used[j] = TRUE;
|
||||
p_colors[i] = rainbow[j];
|
||||
p_know[i] = FALSE;
|
||||
p_guess[i] = NULL;
|
||||
if (i > 0)
|
||||
p_magic[i].mi_prob += p_magic[i-1].mi_prob;
|
||||
}
|
||||
badcheck("potions", p_magic, MAXPOTIONS);
|
||||
}
|
||||
|
||||
/*
|
||||
* do any initialization for food
|
||||
*/
|
||||
|
||||
init_foods()
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i=0; i < MAXFOODS; i++) {
|
||||
if (i > 0)
|
||||
foods[i].mi_prob += foods[i-1].mi_prob;
|
||||
}
|
||||
badcheck("foods", foods, MAXFOODS);
|
||||
}
|
||||
|
||||
/*
|
||||
* init_materials:
|
||||
* Initialize the construction materials for wands and staffs
|
||||
*/
|
||||
|
||||
init_materials()
|
||||
{
|
||||
register int i, j;
|
||||
register char *str;
|
||||
static bool metused[NMETAL];
|
||||
|
||||
for (i = 0; i < NWOOD; i++)
|
||||
used[i] = FALSE;
|
||||
for (i = 0; i < NMETAL; i++)
|
||||
metused[i] = FALSE;
|
||||
|
||||
for (i = 0 ; i < MAXSTICKS ; i++)
|
||||
{
|
||||
for (;;)
|
||||
if (rnd(100) > 50)
|
||||
{
|
||||
j = rnd(NMETAL);
|
||||
if (!metused[j])
|
||||
{
|
||||
ws_type[i] = "wand";
|
||||
str = metal[j];
|
||||
metused[j] = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
j = rnd(NWOOD);
|
||||
if (!used[j])
|
||||
{
|
||||
ws_type[i] = "staff";
|
||||
str = wood[j];
|
||||
used[j] = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ws_made[i] = str;
|
||||
ws_know[i] = FALSE;
|
||||
ws_guess[i] = NULL;
|
||||
if (i > 0)
|
||||
ws_magic[i].mi_prob += ws_magic[i-1].mi_prob;
|
||||
}
|
||||
badcheck("sticks", ws_magic, MAXSTICKS);
|
||||
}
|
||||
|
||||
/*
|
||||
* do any initialization for miscellaneous magic
|
||||
*/
|
||||
|
||||
init_misc()
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i=0; i < MAXMM; i++) {
|
||||
m_know[i] = FALSE;
|
||||
m_guess[i] = NULL;
|
||||
if (i > 0)
|
||||
m_magic[i].mi_prob += m_magic[i-1].mi_prob;
|
||||
}
|
||||
badcheck("miscellaneous magic", m_magic, MAXMM);
|
||||
}
|
||||
|
||||
/*
|
||||
* init_names:
|
||||
* Generate the names of the various scrolls
|
||||
*/
|
||||
|
||||
init_names()
|
||||
{
|
||||
register int nsyl;
|
||||
register char *cp, *sp;
|
||||
register int i, nwords;
|
||||
|
||||
for (i = 0 ; i < MAXSCROLLS ; i++)
|
||||
{
|
||||
cp = prbuf;
|
||||
nwords = rnd(cols/20) + 1 + (cols > 40 ? 1 : 0);
|
||||
while(nwords--)
|
||||
{
|
||||
nsyl = rnd(3)+1;
|
||||
while(nsyl--)
|
||||
{
|
||||
sp = sylls[rnd((sizeof sylls) / (sizeof (char *)))];
|
||||
while(*sp)
|
||||
*cp++ = *sp++;
|
||||
}
|
||||
*cp++ = ' ';
|
||||
}
|
||||
*--cp = '\0';
|
||||
s_names[i] = (char *) new(strlen(prbuf)+1);
|
||||
s_know[i] = FALSE;
|
||||
s_guess[i] = NULL;
|
||||
strcpy(s_names[i], prbuf);
|
||||
if (i > 0)
|
||||
s_magic[i].mi_prob += s_magic[i-1].mi_prob;
|
||||
}
|
||||
badcheck("scrolls", s_magic, MAXSCROLLS);
|
||||
}
|
||||
|
||||
/*
|
||||
* init_player:
|
||||
* roll up the rogue
|
||||
*/
|
||||
|
||||
init_player()
|
||||
{
|
||||
int stat_total, round, minimum, maximum, ch, i, j;
|
||||
short do_escape, *our_stats[NUMABILITIES-1];
|
||||
struct linked_list *weap_item, *armor_item;
|
||||
struct object *obj;
|
||||
|
||||
weap_item = armor_item = NULL;
|
||||
|
||||
if (char_type == -1) {
|
||||
/* See what type character will be */
|
||||
wclear(hw);
|
||||
touchwin(hw);
|
||||
wmove(hw,2,0);
|
||||
for(i=1; i<=NUM_CHARTYPES-1; i++) {
|
||||
wprintw(hw,"[%d] %s\n",i,char_class[i-1].name);
|
||||
}
|
||||
mvwaddstr(hw, 0, 0, "What character class do you desire? ");
|
||||
draw(hw);
|
||||
char_type = (wgetch(hw) - '0');
|
||||
while (char_type < 1 || char_type > NUM_CHARTYPES-1) {
|
||||
wmove(hw,0,0);
|
||||
wprintw(hw,"Please enter a character type between 1 and %d: ",
|
||||
NUM_CHARTYPES-1);
|
||||
draw(hw);
|
||||
char_type = (wgetch(hw) - '0');
|
||||
}
|
||||
char_type--;
|
||||
}
|
||||
player.t_ctype = char_type;
|
||||
player.t_quiet = 0;
|
||||
pack = NULL;
|
||||
|
||||
/* Select the gold */
|
||||
purse = 2700;
|
||||
switch (player.t_ctype) {
|
||||
case C_FIGHTER:
|
||||
purse += 1800;
|
||||
when C_THIEF:
|
||||
case C_ASSASIN:
|
||||
purse += 600;
|
||||
}
|
||||
#ifdef WIZARD
|
||||
/*
|
||||
* allow me to describe a super character
|
||||
*/
|
||||
if (wizard && strcmp(getenv("SUPER"),"YES") == 0) {
|
||||
pstats.s_str = 25;
|
||||
pstats.s_intel = 25;
|
||||
pstats.s_wisdom = 25;
|
||||
pstats.s_dext = 25;
|
||||
pstats.s_const = 25;
|
||||
pstats.s_charisma = 25;
|
||||
pstats.s_exp = 10000000L;
|
||||
pstats.s_lvladj = 0;
|
||||
pstats.s_lvl = 1;
|
||||
pstats.s_hpt = 500;
|
||||
pstats.s_carry = totalenc(&player);
|
||||
strncpy(pstats.s_dmg, "3d4", sizeof(pstats.s_dmg));
|
||||
check_level();
|
||||
mpos = 0;
|
||||
if (player.t_ctype == C_FIGHTER ||
|
||||
player.t_ctype == C_RANGER ||
|
||||
player.t_ctype == C_PALADIN)
|
||||
weap_item = spec_item(WEAPON, TWOSWORD, 5, 5);
|
||||
else
|
||||
weap_item = spec_item(WEAPON, SWORD, 5, 5);
|
||||
obj = OBJPTR(weap_item);
|
||||
obj->o_flags |= ISKNOW;
|
||||
add_pack(weap_item, TRUE, NULL);
|
||||
cur_weapon = obj;
|
||||
if (player.t_ctype != C_MONK) {
|
||||
j = PLATE_ARMOR;
|
||||
if (player.t_ctype == C_THIEF || player.t_ctype == C_ASSASIN)
|
||||
j = STUDDED_LEATHER;
|
||||
armor_item = spec_item(ARMOR, j, 10, 0);
|
||||
obj = OBJPTR(armor_item);
|
||||
obj->o_flags |= (ISKNOW | ISPROT);
|
||||
obj->o_weight = armors[j].a_wght;
|
||||
add_pack(armor_item, TRUE, NULL);
|
||||
cur_armor = obj;
|
||||
}
|
||||
purse += 10000;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
{
|
||||
switch(player.t_ctype) {
|
||||
case C_MAGICIAN:round = A_INTELLIGENCE;
|
||||
when C_FIGHTER: round = A_STRENGTH;
|
||||
when C_RANGER: round = A_STRENGTH;
|
||||
when C_PALADIN: round = A_STRENGTH;
|
||||
when C_CLERIC: round = A_WISDOM;
|
||||
when C_DRUID: round = A_WISDOM;
|
||||
when C_THIEF: round = A_DEXTERITY;
|
||||
when C_ASSASIN: round = A_DEXTERITY;
|
||||
when C_MONK: round = A_DEXTERITY;
|
||||
}
|
||||
|
||||
do {
|
||||
wclear(hw);
|
||||
|
||||
/* If there is any news, display it */
|
||||
if (rogue_news) {
|
||||
register int i;
|
||||
|
||||
/* Print a separator line */
|
||||
wmove(hw, 12, 0);
|
||||
for (i=0; i<cols; i++) waddch(hw, '-');
|
||||
|
||||
/* Print the news */
|
||||
mvwaddstr(hw, 14, 0, rogue_news);
|
||||
}
|
||||
|
||||
stat_total = MAXSTATS;
|
||||
do_escape = FALSE; /* No escape seen yet */
|
||||
|
||||
/* Initialize abilities */
|
||||
pstats.s_intel = 0;
|
||||
pstats.s_str = 0;
|
||||
pstats.s_wisdom = 0;
|
||||
pstats.s_dext = 0;
|
||||
pstats.s_const = 0;
|
||||
pstats.s_charisma = 0;
|
||||
|
||||
/* Initialize pointer into abilities */
|
||||
our_stats[A_INTELLIGENCE] = &pstats.s_intel;
|
||||
our_stats[A_STRENGTH] = &pstats.s_str;
|
||||
our_stats[A_WISDOM] = &pstats.s_wisdom;
|
||||
our_stats[A_DEXTERITY] = &pstats.s_dext;
|
||||
our_stats[A_CONSTITUTION] = &pstats.s_const;
|
||||
|
||||
/* Let player distribute attributes */
|
||||
for (i=0; i<NUMABILITIES-1; i++) {
|
||||
wmove(hw, 2, 0);
|
||||
wprintw(hw, "You are creating a %s with %2d attribute points.",
|
||||
char_class[player.t_ctype].name, stat_total);
|
||||
|
||||
/*
|
||||
* Player must have a minimum of 7 in any attribute and 11 in
|
||||
* the player's primary attribute.
|
||||
*/
|
||||
minimum = (round == i ? 11 : 7);
|
||||
|
||||
/* Subtract out remaining minimums */
|
||||
maximum = stat_total - (7 * (NUMABILITIES-1 - i));
|
||||
|
||||
/* Subtract out remainder of profession minimum (11 - 7) */
|
||||
if (round > i) maximum -= 4;
|
||||
|
||||
/* Maximum can't be greater than 18 */
|
||||
if (maximum > 18) maximum = 18;
|
||||
|
||||
wmove(hw, 4, 0);
|
||||
wprintw(hw,
|
||||
"Minimum: %2d; Maximum: %2d (%s corrects previous entry)",
|
||||
minimum, maximum, unctrl('\b'));
|
||||
|
||||
wmove(hw, 6, 0);
|
||||
wprintw(hw, " Int: %-2d", pstats.s_intel);
|
||||
wprintw(hw, " Str: %-2d", pstats.s_str);
|
||||
wprintw(hw, " Wis: %-2d", pstats.s_wisdom);
|
||||
wprintw(hw, " Dex: %-2d", pstats.s_dext);
|
||||
wprintw(hw, " Con: %-2d", pstats.s_const);
|
||||
wprintw(hw, " Cha: %-2d", pstats.s_charisma);
|
||||
wclrtoeol(hw);
|
||||
wmove(hw, 6, 11*i + 9);
|
||||
if (do_escape == FALSE) draw(hw);
|
||||
|
||||
/* Get player's input */
|
||||
if (do_escape || maximum == minimum) {
|
||||
*our_stats[i] = maximum;
|
||||
stat_total -= maximum;
|
||||
}
|
||||
else for (;;) {
|
||||
ch = wgetch(hw);
|
||||
if (ch == '\b') { /* Backspace */
|
||||
if (i == 0) continue; /* Can't move back */
|
||||
else {
|
||||
stat_total += *our_stats[i-1];
|
||||
*our_stats[i] = 0;
|
||||
*our_stats[i-1] = 0;
|
||||
i -= 2; /* Back out */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ch == '\033') { /* Escape */
|
||||
/*
|
||||
* Escape will result in using all maximums for
|
||||
* remaining abilities.
|
||||
*/
|
||||
do_escape = TRUE;
|
||||
*our_stats[i] = maximum;
|
||||
stat_total -= maximum;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Do we have a legal digit? */
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
ch -= '0'; /* Convert it to a number */
|
||||
*our_stats[i] = 10 * *our_stats[i] + ch;
|
||||
|
||||
/* Is the number in range? */
|
||||
if (*our_stats[i] >= minimum &&
|
||||
*our_stats[i] <= maximum) {
|
||||
stat_total -= *our_stats[i];
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If it's too small, get more - 1x is the only
|
||||
* allowable case.
|
||||
*/
|
||||
if (*our_stats[i] < minimum && *our_stats[i] == 1) {
|
||||
/* Print the player's one */
|
||||
waddch(hw, '1');
|
||||
draw(hw);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Error condition */
|
||||
putchar('\007');
|
||||
*our_stats[i] = 0;
|
||||
i--; /* Rewind */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Discard extra points over 18 */
|
||||
if (stat_total > 18) stat_total = 18;
|
||||
|
||||
/* Charisma gets what's left */
|
||||
pstats.s_charisma = stat_total;
|
||||
|
||||
/* Intialize constants */
|
||||
pstats.s_lvl = 1;
|
||||
pstats.s_lvladj = 0;
|
||||
pstats.s_exp = 0L;
|
||||
strncpy(pstats.s_dmg, "1d4", sizeof(pstats.s_dmg));
|
||||
pstats.s_carry = totalenc(&player);
|
||||
|
||||
/* Get the hit points. */
|
||||
pstats.s_hpt = 12 + const_bonus(); /* Base plus bonus */
|
||||
|
||||
/* Add in the component that varies according to class */
|
||||
pstats.s_hpt += char_class[player.t_ctype].hit_pts;
|
||||
|
||||
/* Display the character */
|
||||
wmove(hw, 2, 0);
|
||||
wprintw(hw,"You are creating a %s.",
|
||||
char_class[player.t_ctype].name);
|
||||
wclrtoeol(hw);
|
||||
|
||||
/* Get rid of max/min line */
|
||||
wmove(hw, 4, 0);
|
||||
wclrtoeol(hw);
|
||||
|
||||
wmove(hw, 6, 0);
|
||||
wprintw(hw, " Int: %2d", pstats.s_intel);
|
||||
wprintw(hw, " Str: %2d", pstats.s_str);
|
||||
wprintw(hw, " Wis: %2d", pstats.s_wisdom);
|
||||
wprintw(hw, " Dex: %2d", pstats.s_dext);
|
||||
wprintw(hw, " Con: %2d", pstats.s_const);
|
||||
wprintw(hw, " Cha: %2d", pstats.s_charisma);
|
||||
wclrtoeol(hw);
|
||||
|
||||
wmove(hw, 8, 0);
|
||||
wprintw(hw, " Hp: %2d", pstats.s_hpt);
|
||||
wclrtoeol(hw);
|
||||
|
||||
wmove(hw, 10, 0);
|
||||
wprintw(hw, " Gold: %d", purse);
|
||||
|
||||
mvwaddstr(hw, 0, 0, "Is this character okay? ");
|
||||
draw(hw);
|
||||
} while(wgetch(hw) != 'y');
|
||||
}
|
||||
|
||||
pstats.s_arm = 10;
|
||||
max_stats = pstats;
|
||||
|
||||
/* Set up the initial movement rate */
|
||||
player.t_action = A_NIL;
|
||||
player.t_movement = 6;
|
||||
player.t_no_move = 0;
|
||||
player.t_using = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* init_stones:
|
||||
* Initialize the ring stone setting scheme for this time
|
||||
*/
|
||||
|
||||
init_stones()
|
||||
{
|
||||
register int i, j;
|
||||
|
||||
for (i = 0; i < NSTONES; i++)
|
||||
used[i] = FALSE;
|
||||
|
||||
for (i = 0 ; i < MAXRINGS ; i++)
|
||||
{
|
||||
do
|
||||
j = rnd(NSTONES);
|
||||
until (!used[j]);
|
||||
used[j] = TRUE;
|
||||
r_stones[i] = stones[j];
|
||||
r_know[i] = FALSE;
|
||||
r_guess[i] = NULL;
|
||||
if (i > 0)
|
||||
r_magic[i].mi_prob += r_magic[i-1].mi_prob;
|
||||
}
|
||||
badcheck("rings", r_magic, MAXRINGS);
|
||||
}
|
||||
|
||||
/*
|
||||
* init_things
|
||||
* Initialize the probabilities for types of things
|
||||
*/
|
||||
init_things()
|
||||
{
|
||||
register struct magic_item *mp;
|
||||
|
||||
for (mp = &things[1] ; mp < &things[NUMTHINGS] ; mp++)
|
||||
mp->mi_prob += (mp-1)->mi_prob;
|
||||
badcheck("things", things, NUMTHINGS);
|
||||
}
|
||||
|
||||
|
||||
539
arogue7/io.c
Normal file
539
arogue7/io.c
Normal file
|
|
@ -0,0 +1,539 @@
|
|||
/*
|
||||
* io.c - Various input/output functions
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Various input/output functions
|
||||
*/
|
||||
|
||||
#include "curses.h"
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* msg:
|
||||
* Display a message at the top of the screen.
|
||||
*/
|
||||
|
||||
static char msgbuf[BUFSIZ];
|
||||
static int newpos = 0;
|
||||
|
||||
/*VARARGS1*/
|
||||
msg(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
/*
|
||||
* if the string is "", just clear the line
|
||||
*/
|
||||
if (*fmt == '\0')
|
||||
{
|
||||
overwrite(cw,msgw);
|
||||
wmove(msgw, 0, 0);
|
||||
clearok(msgw, FALSE);
|
||||
draw(msgw);
|
||||
mpos = 0;
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* otherwise add to the message and flush it out
|
||||
*/
|
||||
va_start(ap,fmt);
|
||||
doadd(fmt, ap);
|
||||
va_end(ap);
|
||||
endmsg();
|
||||
}
|
||||
|
||||
/*
|
||||
* add things to the current message
|
||||
*/
|
||||
addmsg(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
doadd(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Display a new msg (giving him a chance to see the previous one if it
|
||||
* is up there with the --More--)
|
||||
*/
|
||||
endmsg()
|
||||
{
|
||||
/* Needed to track where we are for 5.0 (PC) curses */
|
||||
register int x, y;
|
||||
|
||||
strcpy(huh, msgbuf);
|
||||
if (mpos) {
|
||||
/*
|
||||
* If this message will fit on the line (plus space for --More--
|
||||
* then just add it (only during combat).
|
||||
*/
|
||||
if (player.t_quiet < 0 && mpos + newpos + strlen(morestr) + 2 < cols) {
|
||||
wmove(msgw, 0, mpos + 2);
|
||||
newpos += mpos + 2;
|
||||
}
|
||||
else {
|
||||
wmove(msgw, 0, mpos);
|
||||
waddstr(msgw, morestr);
|
||||
draw(cw);
|
||||
draw(msgw);
|
||||
wait_for(' ');
|
||||
overwrite(cw,msgw);
|
||||
wmove(msgw, 0, 0);
|
||||
touchwin(cw);
|
||||
}
|
||||
}
|
||||
else {
|
||||
overwrite(cw,msgw);
|
||||
wmove(msgw, 0, 0);
|
||||
}
|
||||
waddstr(msgw, msgbuf);
|
||||
getyx(msgw, y, x);
|
||||
mpos = newpos;
|
||||
newpos = 0;
|
||||
wmove(msgw, y, x);
|
||||
draw(cw);
|
||||
clearok(msgw, FALSE);
|
||||
draw(msgw);
|
||||
}
|
||||
|
||||
doadd(char *fmt, va_list ap)
|
||||
{
|
||||
|
||||
/*
|
||||
* Do the printf into buf
|
||||
*/
|
||||
vsprintf(&msgbuf[newpos], fmt, ap);
|
||||
newpos = strlen(msgbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* step_ok:
|
||||
* returns true if it is ok for type to step on ch
|
||||
* flgptr will be NULL if we don't know what the monster is yet!
|
||||
*/
|
||||
|
||||
step_ok(y, x, can_on_monst, flgptr)
|
||||
register int y, x, can_on_monst;
|
||||
register struct thing *flgptr;
|
||||
{
|
||||
/* can_on_monst = MONSTOK if all we care about are physical obstacles */
|
||||
register struct linked_list *item;
|
||||
register struct thing *tp;
|
||||
char ch;
|
||||
|
||||
/* What is here? Don't check monster window if MONSTOK is set */
|
||||
if (can_on_monst == MONSTOK) ch = CCHAR( mvinch(y, x) );
|
||||
else ch = CCHAR( winat(y, x) );
|
||||
|
||||
if (can_on_monst == FIGHTOK && isalpha(ch) &&
|
||||
(item = find_mons(y, x)) != NULL) {
|
||||
tp = THINGPTR(item); /* What monster is here? */
|
||||
|
||||
/* We can hit it if we're after it */
|
||||
if (flgptr->t_dest == &tp->t_pos) return TRUE;
|
||||
|
||||
/*
|
||||
* Otherwise, if we're friendly we'll hit it unless it is also
|
||||
* friendly or is our race.
|
||||
*/
|
||||
if (off(*flgptr, ISFRIENDLY) ||
|
||||
on(*tp, ISFRIENDLY) ||
|
||||
flgptr->t_index == tp->t_index) return FALSE;
|
||||
else return TRUE;
|
||||
}
|
||||
else switch (ch)
|
||||
{
|
||||
case ' ':
|
||||
case '|':
|
||||
case '-':
|
||||
case SECRETDOOR:
|
||||
if (flgptr && on(*flgptr, CANINWALL)) return(TRUE);
|
||||
return FALSE;
|
||||
when SCROLL:
|
||||
if (can_on_monst == MONSTOK) return(TRUE); /* Not a real obstacle */
|
||||
/*
|
||||
* If it is a scroll, it might be a scare monster scroll
|
||||
* so we need to look it up to see what type it is.
|
||||
*/
|
||||
if (flgptr && flgptr->t_ctype == C_MONSTER) {
|
||||
item = find_obj(y, x);
|
||||
if (item != NULL &&
|
||||
(OBJPTR(item))->o_which==S_SCARE &&
|
||||
(flgptr == NULL || flgptr->t_stats.s_intel < 16))
|
||||
return(FALSE); /* All but smart ones are scared */
|
||||
}
|
||||
return(TRUE);
|
||||
otherwise:
|
||||
return (!isalpha(ch));
|
||||
}
|
||||
return(FALSE);
|
||||
}
|
||||
/*
|
||||
* shoot_ok:
|
||||
* returns true if it is ok for type to shoot over ch
|
||||
*/
|
||||
|
||||
shoot_ok(ch)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case ' ':
|
||||
case '|':
|
||||
case '-':
|
||||
case SECRETDOOR:
|
||||
case FOREST:
|
||||
return FALSE;
|
||||
default:
|
||||
return (!isalpha(ch));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* readchar:
|
||||
* flushes stdout so that screen is up to date and then returns
|
||||
* getchar.
|
||||
*/
|
||||
|
||||
readchar()
|
||||
{
|
||||
int ch;
|
||||
|
||||
ch = md_readchar(cw);
|
||||
|
||||
if ((ch == 3) || (ch == 0))
|
||||
{
|
||||
quit(0);
|
||||
return(27);
|
||||
}
|
||||
|
||||
return(ch);
|
||||
}
|
||||
|
||||
/*
|
||||
* status:
|
||||
* Display the important stats line. Keep the cursor where it was.
|
||||
*/
|
||||
|
||||
status(display)
|
||||
bool display; /* is TRUE, display unconditionally */
|
||||
{
|
||||
register struct stats *stat_ptr, *max_ptr;
|
||||
register int oy, ox, temp;
|
||||
register char *pb;
|
||||
static char buf[LINELEN];
|
||||
static int hpwidth = 0, s_hungry = -1;
|
||||
static int s_lvl = -1, s_hp = -1, s_str, maxs_str,
|
||||
s_ac = 0;
|
||||
static short s_intel, s_dext, s_wisdom, s_const, s_charisma;
|
||||
static short maxs_intel, maxs_dext, maxs_wisdom, maxs_const, maxs_charisma;
|
||||
static unsigned long s_exp = 0;
|
||||
static int s_carry, s_pack;
|
||||
bool first_line=FALSE;
|
||||
|
||||
stat_ptr = &pstats;
|
||||
max_ptr = &max_stats;
|
||||
|
||||
/*
|
||||
* If nothing has changed in the first line, then skip it
|
||||
*/
|
||||
if (!display &&
|
||||
s_lvl == level &&
|
||||
s_intel == stat_ptr->s_intel &&
|
||||
s_wisdom == stat_ptr->s_wisdom &&
|
||||
s_dext == dex_compute() &&
|
||||
s_const == stat_ptr->s_const &&
|
||||
s_charisma == stat_ptr->s_charisma &&
|
||||
s_str == str_compute() &&
|
||||
s_hungry == hungry_state &&
|
||||
maxs_intel == max_ptr->s_intel &&
|
||||
maxs_wisdom == max_ptr->s_wisdom &&
|
||||
maxs_dext == max_ptr->s_dext &&
|
||||
maxs_const == max_ptr->s_const &&
|
||||
maxs_charisma == max_ptr->s_charisma &&
|
||||
maxs_str == max_ptr->s_str ) goto line_two;
|
||||
|
||||
/* Display the first line */
|
||||
first_line = TRUE;
|
||||
getyx(cw, oy, ox);
|
||||
sprintf(buf, "Int:%d(%d) Str:%d", stat_ptr->s_intel,
|
||||
max_ptr->s_intel, str_compute());
|
||||
|
||||
/* Maximum strength */
|
||||
pb = &buf[strlen(buf)];
|
||||
sprintf(pb, "(%d)", max_ptr->s_str);
|
||||
|
||||
pb = &buf[strlen(buf)];
|
||||
sprintf(pb, " Wis:%d(%d) Dxt:%d(%d) Con:%d(%d) Cha:%d(%d)",
|
||||
stat_ptr->s_wisdom,max_ptr->s_wisdom,dex_compute(),max_ptr->s_dext,
|
||||
stat_ptr->s_const,max_ptr->s_const,stat_ptr->s_charisma,
|
||||
max_ptr->s_charisma);
|
||||
|
||||
/* Update first line status */
|
||||
s_intel = stat_ptr->s_intel;
|
||||
s_wisdom = stat_ptr->s_wisdom;
|
||||
s_dext = dex_compute();
|
||||
s_const = stat_ptr->s_const;
|
||||
s_charisma = stat_ptr->s_charisma;
|
||||
s_str = str_compute();
|
||||
maxs_intel = max_ptr->s_intel;
|
||||
maxs_wisdom = max_ptr->s_wisdom;
|
||||
maxs_dext = max_ptr->s_dext;
|
||||
maxs_const = max_ptr->s_const;
|
||||
maxs_charisma = max_ptr->s_charisma;
|
||||
maxs_str = max_ptr->s_str;
|
||||
|
||||
/* Print the line */
|
||||
mvwaddstr(cw, lines - 2, 0, buf);
|
||||
switch (hungry_state)
|
||||
{
|
||||
case F_SATIATED:
|
||||
waddstr(cw, " Satiated");
|
||||
when F_OKAY: ;
|
||||
when F_HUNGRY:
|
||||
waddstr(cw, " Hungry");
|
||||
when F_WEAK:
|
||||
waddstr(cw, " Weak");
|
||||
when F_FAINT:
|
||||
waddstr(cw, " Fainting");
|
||||
}
|
||||
wclrtoeol(cw);
|
||||
s_hungry = hungry_state;
|
||||
|
||||
/*
|
||||
* If nothing has changed since the last status, don't
|
||||
* bother.
|
||||
*/
|
||||
line_two:
|
||||
if (!display &&
|
||||
s_lvl == level &&
|
||||
s_hp == stat_ptr->s_hpt &&
|
||||
s_ac == ac_compute(FALSE) - dext_prot(s_dext) &&
|
||||
s_pack == stat_ptr->s_pack &&
|
||||
s_carry == stat_ptr->s_carry &&
|
||||
s_exp == stat_ptr->s_exp ) return;
|
||||
|
||||
if (!first_line) getyx(cw, oy, ox);
|
||||
if (s_hp != max_ptr->s_hpt)
|
||||
{
|
||||
temp = s_hp = max_ptr->s_hpt;
|
||||
for (hpwidth = 0; temp; hpwidth++)
|
||||
temp /= 10;
|
||||
}
|
||||
sprintf(buf, "Lvl:%d Hp:%*d(%*d) Ac:%d Carry:%d(%d) Exp:%d/%lu %s",
|
||||
level, hpwidth, stat_ptr->s_hpt, hpwidth, max_ptr->s_hpt,
|
||||
ac_compute(FALSE) - dext_prot(s_dext),stat_ptr->s_pack/10,
|
||||
stat_ptr->s_carry/10, stat_ptr->s_lvl, stat_ptr->s_exp,
|
||||
cnames[player.t_ctype][min(stat_ptr->s_lvl-1, NUM_CNAMES-1)]);
|
||||
|
||||
/*
|
||||
* Save old status
|
||||
*/
|
||||
s_lvl = level;
|
||||
s_hp = stat_ptr->s_hpt;
|
||||
s_ac = ac_compute(FALSE) - dext_prot(s_dext);
|
||||
s_pack = stat_ptr->s_pack;
|
||||
s_carry = stat_ptr->s_carry;
|
||||
s_exp = stat_ptr->s_exp;
|
||||
mvwaddstr(cw, lines - 1, 0, buf);
|
||||
wclrtoeol(cw);
|
||||
wmove(cw, oy, ox);
|
||||
}
|
||||
|
||||
/*
|
||||
* wait_for
|
||||
* Sit around until the guy types the right key
|
||||
*/
|
||||
wait_for(ch)
|
||||
register char ch;
|
||||
{
|
||||
register char c;
|
||||
|
||||
if (ch == '\n')
|
||||
while ((c = wgetch(msgw)) != '\n' && c != '\r')
|
||||
continue;
|
||||
else
|
||||
while (wgetch(msgw) != ch)
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* over_win:
|
||||
* Given a current window, a new window, and the max y and x of the
|
||||
* new window, paint the new window on top of the old window without
|
||||
* destroying any of the old window. Current window and new window
|
||||
* are assumed to have lines lines and cols columns (max y and max x
|
||||
* pertain only the the useful information to be displayed.
|
||||
* If redraw is non-zero, we wait for the character "redraw" to be
|
||||
* typed and then redraw the starting screen.
|
||||
*/
|
||||
|
||||
over_win(oldwin, newin, maxy, maxx, cursory, cursorx, redraw)
|
||||
WINDOW *oldwin, *newin;
|
||||
int maxy, maxx, cursory, cursorx;
|
||||
char redraw;
|
||||
{
|
||||
static char blanks[LINELEN+1];
|
||||
register int line, i;
|
||||
WINDOW *ow; /* Overlay window */
|
||||
|
||||
/* Create a blanking line */
|
||||
for (i=0; i<maxx && i<cols && i<LINELEN; i++) blanks[i] = ' ';
|
||||
blanks[i] = '\0';
|
||||
|
||||
/* Create the window we will display */
|
||||
ow = newwin(lines, cols, 0, 0);
|
||||
|
||||
/* Blank out the area we want to use */
|
||||
if (oldwin == cw) {
|
||||
msg("");
|
||||
line = 1;
|
||||
}
|
||||
else line = 0;
|
||||
|
||||
overwrite(oldwin, ow); /* Get a copy of the old window */
|
||||
|
||||
/* Do the remaining blanking */
|
||||
for (; line < maxy; line++) mvwaddstr(ow, line, 0, blanks);
|
||||
|
||||
overlay(newin, ow); /* Overlay our new window */
|
||||
|
||||
/* Move the cursor to the specified location */
|
||||
wmove(ow, cursory, cursorx);
|
||||
|
||||
clearok(ow, FALSE); /* Draw inventory without clearing */
|
||||
draw(ow);
|
||||
|
||||
if (redraw) {
|
||||
wait_for(redraw);
|
||||
|
||||
clearok(oldwin, FALSE); /* Setup to redraw current screen */
|
||||
touchwin(oldwin); /* clearing first */
|
||||
draw(oldwin);
|
||||
}
|
||||
|
||||
delwin(ow);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* show_win:
|
||||
* function used to display a window and wait before returning
|
||||
*/
|
||||
|
||||
show_win(scr, message)
|
||||
register WINDOW *scr;
|
||||
char *message;
|
||||
{
|
||||
mvwaddstr(scr, 0, 0, message);
|
||||
touchwin(scr);
|
||||
wmove(scr, hero.y, hero.x);
|
||||
draw(scr);
|
||||
wait_for(' ');
|
||||
clearok(cw, TRUE);
|
||||
touchwin(cw);
|
||||
}
|
||||
|
||||
/*
|
||||
* dbotline:
|
||||
* Displays message on bottom line and waits for a space to return
|
||||
*/
|
||||
dbotline(scr,message)
|
||||
WINDOW *scr;
|
||||
char *message;
|
||||
{
|
||||
mvwaddstr(scr,lines-1,0,message);
|
||||
draw(scr);
|
||||
wait_for(' ');
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* restscr:
|
||||
* Restores the screen to the terminal
|
||||
*/
|
||||
restscr(scr)
|
||||
WINDOW *scr;
|
||||
{
|
||||
clearok(scr,TRUE);
|
||||
touchwin(scr);
|
||||
}
|
||||
|
||||
/*
|
||||
* netread:
|
||||
* Read a byte, short, or long machine independently
|
||||
* Always returns the value as an unsigned long.
|
||||
*/
|
||||
|
||||
unsigned long
|
||||
netread(error, size, stream)
|
||||
int *error;
|
||||
int size;
|
||||
FILE *stream;
|
||||
{
|
||||
unsigned long result = 0L, /* What we read in */
|
||||
partial; /* Partial value */
|
||||
int nextc, /* The next byte */
|
||||
i; /* To index through the result a byte at a time */
|
||||
|
||||
/* Be sure we have a right sized chunk */
|
||||
if (size < 1 || size > 4) {
|
||||
*error = 1;
|
||||
return(0L);
|
||||
}
|
||||
|
||||
for (i=0; i<size; i++) {
|
||||
nextc = getc(stream);
|
||||
if (nextc == EOF) {
|
||||
*error = 1;
|
||||
return(0L);
|
||||
}
|
||||
else {
|
||||
partial = (unsigned long) (nextc & 0xff);
|
||||
partial <<= 8*i;
|
||||
result |= partial;
|
||||
}
|
||||
}
|
||||
|
||||
*error = 0;
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* netwrite:
|
||||
* Write out a byte, short, or long machine independently.
|
||||
*/
|
||||
|
||||
netwrite(value, size, stream)
|
||||
unsigned long value; /* What to write */
|
||||
int size; /* How much to write out */
|
||||
FILE *stream; /* Where to write it */
|
||||
{
|
||||
int i; /* Goes through value one byte at a time */
|
||||
char outc; /* The next character to be written */
|
||||
|
||||
/* Be sure we have a right sized chunk */
|
||||
if (size < 1 || size > 4) return(0);
|
||||
|
||||
for (i=0; i<size; i++) {
|
||||
outc = (char) ((value >> (8 * i)) & 0xff);
|
||||
putc(outc, stream);
|
||||
}
|
||||
return(size);
|
||||
}
|
||||
226
arogue7/list.c
Normal file
226
arogue7/list.c
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
* list.c - Functions for dealing with linked lists of goodies
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Functions for dealing with linked lists of goodies
|
||||
*
|
||||
*/
|
||||
|
||||
#include "curses.h"
|
||||
#include <stdlib.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* detach:
|
||||
* Takes an item out of whatever linked list it might be in
|
||||
*/
|
||||
|
||||
_detach(list, item)
|
||||
register struct linked_list **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
|
||||
*/
|
||||
|
||||
_attach(list, item)
|
||||
register struct linked_list **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;
|
||||
}
|
||||
|
||||
/*
|
||||
* o_free_list:
|
||||
* Throw the whole object list away
|
||||
*/
|
||||
|
||||
_o_free_list(ptr)
|
||||
register struct linked_list **ptr;
|
||||
{
|
||||
register struct linked_list *item;
|
||||
|
||||
while (*ptr != NULL)
|
||||
{
|
||||
item = *ptr;
|
||||
*ptr = next(item);
|
||||
o_discard(item);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* o_discard:
|
||||
* free up an item and its object(and maybe contents)
|
||||
*/
|
||||
|
||||
o_discard(item)
|
||||
register struct linked_list *item;
|
||||
{
|
||||
register struct object *obj;
|
||||
|
||||
obj = OBJPTR(item);
|
||||
if (obj->contents != NULL)
|
||||
o_free_list(obj->contents);
|
||||
total -= 2;
|
||||
FREE(obj);
|
||||
FREE(item);
|
||||
}
|
||||
|
||||
/*
|
||||
* r_free_list:
|
||||
* Throw the whole list of room exits away
|
||||
*/
|
||||
|
||||
_r_free_list(ptr)
|
||||
register struct linked_list **ptr;
|
||||
{
|
||||
register struct linked_list *item;
|
||||
|
||||
while (*ptr != NULL)
|
||||
{
|
||||
item = *ptr;
|
||||
*ptr = next(item);
|
||||
r_discard(item);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* r_discard:
|
||||
* free up an item and its room
|
||||
*/
|
||||
|
||||
r_discard(item)
|
||||
register struct linked_list *item;
|
||||
{
|
||||
total -= 2;
|
||||
FREE(DOORPTR(item));
|
||||
FREE(item);
|
||||
}
|
||||
|
||||
/*
|
||||
* t_free_list:
|
||||
* Throw the whole thing list away
|
||||
*/
|
||||
|
||||
_t_free_list(ptr)
|
||||
register struct linked_list **ptr;
|
||||
{
|
||||
register struct linked_list *item;
|
||||
|
||||
while (*ptr != NULL)
|
||||
{
|
||||
item = *ptr;
|
||||
*ptr = next(item);
|
||||
t_discard(item);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* t_discard:
|
||||
* free up an item and its thing
|
||||
*/
|
||||
|
||||
t_discard(item)
|
||||
register struct linked_list *item;
|
||||
{
|
||||
register struct thing *tp;
|
||||
|
||||
total -= 2;
|
||||
tp = THINGPTR(item);
|
||||
if (tp->t_name != NULL) FREE(tp->t_name);
|
||||
FREE(tp);
|
||||
FREE(item);
|
||||
}
|
||||
|
||||
/*
|
||||
* destroy_item:
|
||||
* get rid of an item structure -- don't worry about contents
|
||||
*/
|
||||
|
||||
destroy_item(item)
|
||||
register struct linked_list *item;
|
||||
{
|
||||
total--;
|
||||
FREE(item);
|
||||
}
|
||||
|
||||
/*
|
||||
* new_item
|
||||
* get a new item with a specified size
|
||||
*/
|
||||
|
||||
struct linked_list *
|
||||
new_item(size)
|
||||
int size;
|
||||
{
|
||||
register struct linked_list *item;
|
||||
|
||||
if ((item = (struct linked_list *) new(sizeof *item)) == NULL)
|
||||
msg("Ran out of memory for header after %d items", total);
|
||||
if ((item->l_data = new(size)) == NULL)
|
||||
msg("Ran out of memory for data after %d items", total);
|
||||
item->l_next = item->l_prev = NULL;
|
||||
return item;
|
||||
}
|
||||
|
||||
/*
|
||||
* creat_item:
|
||||
* Create just an item structure -- don't make any contents
|
||||
*/
|
||||
|
||||
struct linked_list *
|
||||
creat_item()
|
||||
{
|
||||
register struct linked_list *item;
|
||||
|
||||
if ((item = (struct linked_list *) new(sizeof *item)) == NULL)
|
||||
msg("Ran out of memory for header after %d items", total);
|
||||
item->l_next = item->l_prev = NULL;
|
||||
return item;
|
||||
}
|
||||
|
||||
char *
|
||||
new(size)
|
||||
int size;
|
||||
{
|
||||
register char *space = ALLOC(size);
|
||||
static char errbuf[LINELEN];
|
||||
|
||||
if (space == NULL) {
|
||||
sprintf(errbuf,"Rogue ran out of memory (used = %d, wanted = %d).",
|
||||
md_memused(), size);
|
||||
fatal(errbuf);
|
||||
}
|
||||
total++;
|
||||
return space;
|
||||
}
|
||||
84
arogue7/mach_dep.h
Normal file
84
arogue7/mach_dep.h
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* mach_dep.h - machine dependicies
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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 that the wizard commands exist
|
||||
*/
|
||||
#define WIZARD 0
|
||||
|
||||
/*
|
||||
* define if you want to limit scores to one per class per userid
|
||||
*/
|
||||
#undef LIMITSCORE /* 1 */
|
||||
|
||||
/*
|
||||
* define that rogue should "nice()" itself
|
||||
*/
|
||||
#undef NICE /* 1 */
|
||||
|
||||
#ifdef NICE
|
||||
#define FUDGE_TIME 70 /* fudge factor allowed in time for saved game*/
|
||||
#else
|
||||
#define FUDGE_TIME 50 /* fudge factor allowed in time for saved game*/
|
||||
#endif
|
||||
|
||||
#undef DUMP /* 1 */ /* dump core rather than catch the signal */
|
||||
#undef NOCHECKACCESS /* 1 */ /* If set, then don't check time on save file */
|
||||
|
||||
|
||||
/*
|
||||
* where scorefile should live
|
||||
*/
|
||||
#ifndef SCOREFILE
|
||||
#define SCOREFILE "/usr/games/lib/rogue_roll"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Variables for checking to make sure the system isn't too loaded
|
||||
* for people to play
|
||||
*/
|
||||
|
||||
#if u370
|
||||
# define MAXUSERS 40 /* max number of users for this game */
|
||||
# define MAXPROCESSES 140 /* number processes including system */
|
||||
/* processes but not including gettys*/
|
||||
#endif
|
||||
#if uts
|
||||
# define MAXUSERS 45 /* max number of users for this game */
|
||||
# define MAXPROCESSES 150 /* number processes including system */
|
||||
/* processes but not including gettys*/
|
||||
#endif
|
||||
#if vax
|
||||
# define MAXUSERS 17 /* max number of users for this game */
|
||||
# define MAXPROCESSES 85 /* number processes including system */
|
||||
/* processes but not including gettys*/
|
||||
#endif
|
||||
#if u3b
|
||||
# define MAXUSERS 14 /* max number of users for this game */
|
||||
# define MAXPROCESSES 75 /* number processes including system */
|
||||
/* processes but not including gettys*/
|
||||
#endif
|
||||
|
||||
#undef MAXUSERS
|
||||
#undef MAXPROCESSES
|
||||
|
||||
#undef CHECKTIME /* 15 *//* number of minutes between load checks */
|
||||
/* if not defined checks are only on startup */
|
||||
#define UTMP "/etc/utmp" /* where utmp file lives */
|
||||
/*
|
||||
* define the current author user id of the program for "special handling"
|
||||
*/
|
||||
#ifndef AUTHOR
|
||||
#define AUTHOR 0
|
||||
#endif
|
||||
725
arogue7/main.c
Normal file
725
arogue7/main.c
Normal file
|
|
@ -0,0 +1,725 @@
|
|||
/*
|
||||
* main.c - setup code
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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 "curses.h"
|
||||
#include <signal.h>
|
||||
#ifdef BSD
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif
|
||||
#include "mach_dep.h"
|
||||
#include "network.h"
|
||||
#include "rogue.h"
|
||||
#ifdef PC7300
|
||||
#include "sys/window.h"
|
||||
#include <ctype.h>
|
||||
extern struct uwdata wdata, oldwin;
|
||||
extern char oldtext[WTXTNUM][WTXTLEN];
|
||||
#endif
|
||||
|
||||
main(argc, argv, envp)
|
||||
char **argv;
|
||||
char **envp;
|
||||
{
|
||||
register char *env;
|
||||
int lowtime;
|
||||
time_t now;
|
||||
#ifdef PC7300
|
||||
int hardwindow; /* Do we have a hardware window? */
|
||||
#endif
|
||||
|
||||
md_init();
|
||||
|
||||
/*
|
||||
* get home and options from environment
|
||||
*/
|
||||
|
||||
strncpy(home, md_gethomedir(), LINELEN);
|
||||
|
||||
/* Get default save file */
|
||||
strcpy(file_name, home);
|
||||
strcat(file_name, "arogue77.sav");
|
||||
|
||||
/* Get default score file */
|
||||
strcpy(score_file, md_getroguedir());
|
||||
|
||||
if (*score_file)
|
||||
strcat(score_file,"/");
|
||||
|
||||
strcat(score_file,"arogue77.scr");
|
||||
|
||||
if ((env = getenv("ROGUEOPTS")) != NULL)
|
||||
parse_opts(env);
|
||||
|
||||
if (whoami[0] == '\0')
|
||||
strucpy(whoami, md_getusername(), strlen(md_getusername()));
|
||||
|
||||
/*
|
||||
* check for print-score option
|
||||
*/
|
||||
if (argc == 2 && strcmp(argv[1], "-s") == 0)
|
||||
{
|
||||
waswizard = TRUE;
|
||||
score(0, SCOREIT, 0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#ifdef NUMNET
|
||||
/*
|
||||
* Check for a network update
|
||||
*/
|
||||
if (argc == 2 && strcmp(argv[1], "-u") == 0) {
|
||||
unsigned long netread();
|
||||
int errcheck, errors = 0;
|
||||
unsigned long amount;
|
||||
short monster;
|
||||
|
||||
/* Read in the amount and monster values to pass to score */
|
||||
amount = netread(&errcheck, sizeof(unsigned long), stdin);
|
||||
if (errcheck) errors++;
|
||||
|
||||
monster = (short) netread(&errcheck, sizeof(short), stdin);
|
||||
if (errcheck) errors++;
|
||||
|
||||
/* Now do the update if there were no errors */
|
||||
if (errors) exit(1);
|
||||
else {
|
||||
score(amount, UPDATE, monster);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WIZARD
|
||||
/*
|
||||
* Check to see if he is a wizard
|
||||
*/
|
||||
if (argc >= 2 && argv[1][0] == '\0')
|
||||
if (strcmp(PASSWD, md_crypt(md_getpass("Wizard's password: "), "mT")) == 0)
|
||||
{
|
||||
wizard = TRUE;
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!wizard && !author() && !holiday()) {
|
||||
printf("Sorry, %s, but you can't play during working hours.\n", whoami);
|
||||
printf("Try again later.\n");
|
||||
exit(1);
|
||||
}
|
||||
if (!wizard && !author() && too_much()) {
|
||||
printf("Sorry, %s, but the system is too loaded now.\n", whoami);
|
||||
printf("Try again later.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#if NICE
|
||||
if (!wizard)
|
||||
nice(19); /* nice the max amount */
|
||||
#endif
|
||||
|
||||
if (argc == 2)
|
||||
if (!restore(argv[1], envp)) /* Note: restore will never return */
|
||||
exit(1);
|
||||
lowtime = (int) time(&now);
|
||||
dnum = (wizard && getenv("SEED") != NULL ?
|
||||
atoi(getenv("SEED")) :
|
||||
lowtime + getpid());
|
||||
if (wizard)
|
||||
printf("Hello %s, welcome to dungeon #%d", whoami, dnum);
|
||||
else
|
||||
printf("Hello %s, just a moment while I dig the dungeon...", whoami);
|
||||
fflush(stdout);
|
||||
seed = dnum;
|
||||
md_srand(seed);
|
||||
|
||||
#ifdef PC7300
|
||||
/* Store static window parameters */
|
||||
hardwindow = ioctl(0, WIOCGETD, &wdata);
|
||||
if (hardwindow >= 0) { /* We have a hardware window */
|
||||
extern char **environ;
|
||||
|
||||
/* Make sure our window is the right size */
|
||||
oldwin = wdata;
|
||||
if ((wdata.uw_height / wdata.uw_vs) < 23 ||
|
||||
(wdata.uw_width / wdata.uw_hs) < 75) {
|
||||
wdata.uw_width = 80 * wdata.uw_hs;
|
||||
wdata.uw_height = 24 * wdata.uw_vs;
|
||||
wdata.uw_x = 0;
|
||||
wdata.uw_y = wdata.uw_vs;
|
||||
wdata.uw_uflags = NBORDER;
|
||||
|
||||
/* Make the change */
|
||||
if (ioctl(1, WIOCSETD, &wdata) >= 0 && environ) {
|
||||
char **eptr, *tptr, *nptr, *newenv, *lptr = 0, *cptr = 0;
|
||||
int i, nlines = -1, ncols = -1, nlindig = 0, ncoldig = 0;
|
||||
struct utdata labelbuf;
|
||||
|
||||
/* Save and change window-associated text */
|
||||
for (i=0; i<WTXTNUM; i++) {
|
||||
labelbuf.ut_num = i;
|
||||
ioctl(1, WIOCGETTEXT, &labelbuf);
|
||||
strncpy(oldtext[i], labelbuf.ut_text, WTXTLEN - 1);
|
||||
if (*labelbuf.ut_text) {
|
||||
*labelbuf.ut_text = '\0';
|
||||
ioctl(1, WIOCSETTEXT, &labelbuf);
|
||||
}
|
||||
}
|
||||
|
||||
labelbuf.ut_num = WTXTLABEL;
|
||||
strcpy(labelbuf.ut_text, "Advanced Rogue");
|
||||
ioctl(1, WIOCSETTEXT, &labelbuf);
|
||||
|
||||
/* We have to change the TERMCAP entry */
|
||||
eptr = environ;
|
||||
while (*eptr) {
|
||||
if (strncmp(*eptr, "TERMCAP=", 8) == 0) break;
|
||||
else eptr++;
|
||||
}
|
||||
|
||||
/* We found a TERMCAP entry */
|
||||
if (*eptr) {
|
||||
/* Search for li# and co# */
|
||||
tptr = *eptr;
|
||||
while (*tptr) {
|
||||
switch (*tptr) {
|
||||
case 'l':
|
||||
if (nlines == -1 &&
|
||||
strncmp(tptr, "li#", 3) == 0) {
|
||||
tptr += 3;
|
||||
lptr = tptr;
|
||||
lines = atoi(tptr);
|
||||
while (isdigit(*tptr)) {
|
||||
nlindig++;;
|
||||
tptr++;
|
||||
}
|
||||
}
|
||||
else tptr++;
|
||||
break;
|
||||
case 'c':
|
||||
if (ncols == -1 &&
|
||||
strncmp(tptr, "co#", 3) == 0) {
|
||||
tptr += 3;
|
||||
cptr = tptr;
|
||||
cols = atoi(tptr);
|
||||
while (isdigit(*tptr)) {
|
||||
ncoldig++;
|
||||
tptr++;
|
||||
}
|
||||
}
|
||||
else tptr++;
|
||||
break;
|
||||
default:
|
||||
tptr++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Change the entry */
|
||||
if (ncoldig != 2 || nlindig != 2) {
|
||||
int length;
|
||||
|
||||
/* Add in difference in num lengths plus NULL */
|
||||
length = strlen(*eptr) - ncoldig - nlindig + 5;
|
||||
|
||||
if (ncoldig == 0) length += 4; /* For :co# */
|
||||
if (nlindig == 0) length += 4; /* For :li# */
|
||||
|
||||
newenv = malloc(length);
|
||||
tptr = *eptr;
|
||||
nptr = newenv;
|
||||
|
||||
if (nlindig == 0 || ncoldig == 0) {
|
||||
/* Copy up to the first : */
|
||||
while (*tptr && *tptr != ':') *nptr++ = *tptr++;
|
||||
|
||||
/* Do we have to add a field? */
|
||||
if (nlindig == 0) {
|
||||
strcpy(nptr, ":li#24");
|
||||
nptr += 6;
|
||||
}
|
||||
if (ncoldig == 0) {
|
||||
strcpy(nptr, ":co#80");
|
||||
nptr += 6;
|
||||
}
|
||||
}
|
||||
while (*tptr) {
|
||||
if (tptr == lptr) {
|
||||
strcpy(nptr, "24");
|
||||
nptr += 2;
|
||||
tptr += nlindig;
|
||||
}
|
||||
else if (tptr == cptr) {
|
||||
strcpy(nptr, "80");
|
||||
nptr += 2;
|
||||
tptr += ncoldig;
|
||||
}
|
||||
else *nptr++ = *tptr++;
|
||||
}
|
||||
|
||||
*nptr = '\0';
|
||||
|
||||
/* Replace the old one */
|
||||
free(*eptr);
|
||||
*eptr = newenv;
|
||||
}
|
||||
else {
|
||||
/* Just overwrite the old numbers */
|
||||
*lptr++ = '2';
|
||||
*lptr = '4';
|
||||
*cptr++ = '8';
|
||||
*cptr = '0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
init_things(); /* Set up probabilities of things */
|
||||
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 */
|
||||
init_names(); /* Set up names of scrolls */
|
||||
init_misc(); /* Set up miscellaneous magic */
|
||||
init_foods(); /* set up the food table */
|
||||
|
||||
cols = COLS;
|
||||
lines = LINES;
|
||||
if (cols > 85) cols = 85;
|
||||
if (lines > 24) lines = 24;
|
||||
if (lines < 23 || cols < 75) { /* give player a break if larger font used */
|
||||
printf("\nERROR: screen size too small for rogue\n");
|
||||
byebye(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now that we have cols and lines, we can update our window
|
||||
* structure for non-hardware windows.
|
||||
*/
|
||||
#ifdef PC7300
|
||||
if (hardwindow < 0) {
|
||||
wdata.uw_x = 0;
|
||||
wdata.uw_y = 0;
|
||||
wdata.uw_width = COLS;
|
||||
wdata.uw_height = LINES;
|
||||
wdata.uw_uflags = 0;
|
||||
wdata.uw_hs = 1;
|
||||
wdata.uw_vs = 1;
|
||||
wdata.uw_baseline = 0;
|
||||
}
|
||||
#endif
|
||||
setup();
|
||||
/*
|
||||
* Set up windows
|
||||
*/
|
||||
cw = newwin(lines, cols, 0, 0);
|
||||
mw = newwin(lines, cols, 0, 0);
|
||||
hw = newwin(lines, cols, 0, 0);
|
||||
msgw = newwin(4, cols, 0, 0);
|
||||
keypad(cw,TRUE);
|
||||
keypad(msgw,TRUE);
|
||||
|
||||
init_player(); /* Roll up the rogue */
|
||||
waswizard = wizard;
|
||||
|
||||
#ifdef WIZARD
|
||||
/* A super wizard doesn't have to get equipped */
|
||||
if (wizard && strcmp(getenv("SUPER"),"YES") == 0) {
|
||||
level = 1;
|
||||
new_level(NORMLEV);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
new_level(STARTLEV); /* Draw current level */
|
||||
/*
|
||||
* Start up daemons and fuses
|
||||
*/
|
||||
daemon(doctor, &player, AFTER);
|
||||
fuse(swander, 0, WANDERTIME, AFTER);
|
||||
if (player.t_ctype == C_MAGICIAN || player.t_ctype == C_RANGER)
|
||||
fuse(spell_recovery, 0, SPELLTIME, AFTER);
|
||||
if (player.t_ctype == C_DRUID || player.t_ctype == C_RANGER)
|
||||
fuse(chant_recovery, 0, SPELLTIME, AFTER);
|
||||
if (player.t_ctype == C_CLERIC || player.t_ctype == C_PALADIN)
|
||||
fuse(prayer_recovery, 0, SPELLTIME, AFTER);
|
||||
daemon(stomach, 0, AFTER);
|
||||
if (player.t_ctype == C_THIEF ||
|
||||
player.t_ctype == C_ASSASIN ||
|
||||
player.t_ctype == C_MONK)
|
||||
daemon(trap_look, 0, AFTER);
|
||||
|
||||
/* Does this character have any special knowledge? */
|
||||
switch (player.t_ctype) {
|
||||
case C_ASSASIN:
|
||||
/* Assassins automatically recognize poison */
|
||||
p_know[P_POISON] = TRUE;
|
||||
}
|
||||
|
||||
/* Choose a quest item */
|
||||
quest_item = rnd(MAXRELIC);
|
||||
draw(cw);
|
||||
msg("You have been quested to retrieve the %s....",
|
||||
rel_magic[quest_item].mi_name);
|
||||
mpos = 0;
|
||||
playit();
|
||||
}
|
||||
|
||||
/*
|
||||
* endit:
|
||||
* Exit the program abnormally.
|
||||
*/
|
||||
|
||||
void
|
||||
endit(sig)
|
||||
int sig;
|
||||
{
|
||||
fatal("Ok, if you want to exit that badly, I'll have to allow it\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* fatal:
|
||||
* Exit the program, printing a message.
|
||||
*/
|
||||
|
||||
fatal(s)
|
||||
char *s;
|
||||
{
|
||||
clear();
|
||||
move(lines-2, 0);
|
||||
printw("%s", s);
|
||||
draw(stdscr);
|
||||
endwin();
|
||||
#ifdef PC7300
|
||||
endhardwin();
|
||||
#endif
|
||||
printf("\n"); /* So the curser doesn't stop at the end of the line */
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* rnd:
|
||||
* Pick a very random number.
|
||||
*/
|
||||
rnd(range)
|
||||
register int range;
|
||||
{
|
||||
return(range <= 0 ? 0 : md_rand() % range);
|
||||
}
|
||||
|
||||
/*
|
||||
* roll:
|
||||
* roll a number of dice
|
||||
*/
|
||||
|
||||
roll(number, sides)
|
||||
register int number, sides;
|
||||
{
|
||||
register int dtotal = 0;
|
||||
|
||||
while(number--)
|
||||
dtotal += rnd(sides)+1;
|
||||
return dtotal;
|
||||
}
|
||||
# ifdef SIGTSTP
|
||||
/*
|
||||
* handle stop and start signals
|
||||
*/
|
||||
void
|
||||
tstp(sig)
|
||||
int sig;
|
||||
{
|
||||
mvcur(0, cols - 1, lines - 1, 0);
|
||||
endwin();
|
||||
fflush(stdout);
|
||||
kill(0, SIGTSTP);
|
||||
signal(SIGTSTP, tstp);
|
||||
raw();
|
||||
noecho();
|
||||
keypad(cw,1);
|
||||
keypad(msgw,1);
|
||||
clearok(curscr, TRUE);
|
||||
touchwin(cw);
|
||||
draw(cw);
|
||||
md_flushinp();
|
||||
}
|
||||
# endif
|
||||
|
||||
setup()
|
||||
{
|
||||
#ifdef CHECKTIME
|
||||
int checkout();
|
||||
|
||||
if (!author()) {
|
||||
signal(SIGALRM, checkout);
|
||||
alarm(CHECKTIME * 60);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
#ifndef DUMP
|
||||
signal(SIGILL, bugkill);
|
||||
#ifdef SIGTRAP
|
||||
signal(SIGTRAP, bugkill);
|
||||
#endif
|
||||
#ifdef SIGIOT
|
||||
signal(SIGIOT, bugkill);
|
||||
#endif
|
||||
#ifdef SIGEMT
|
||||
signal(SIGEMT, bugkill);
|
||||
#endif
|
||||
signal(SIGFPE, bugkill);
|
||||
#ifdef SIGBUS
|
||||
signal(SIGBUS, bugkill);
|
||||
#endif
|
||||
signal(SIGSEGV, bugkill);
|
||||
#ifdef SIGSYS
|
||||
signal(SIGSYS, bugkill);
|
||||
#endif
|
||||
#ifdef SIGPIPE
|
||||
signal(SIGPIPE, bugkill);
|
||||
#endif
|
||||
#endif
|
||||
*/
|
||||
#ifdef SIGTSTP
|
||||
signal(SIGTSTP, tstp);
|
||||
#endif
|
||||
|
||||
#ifdef SIGHUP
|
||||
signal(SIGHUP, auto_save);
|
||||
#endif
|
||||
signal(SIGTERM, auto_save);
|
||||
signal(SIGINT, quit);
|
||||
#ifdef SIGQUIT
|
||||
signal(SIGQUIT, endit);
|
||||
#endif
|
||||
raw(); /* Cbreak mode */
|
||||
noecho(); /* Echo off */
|
||||
}
|
||||
|
||||
/*
|
||||
* playit:
|
||||
* The main loop of the program. Loop until the game is over,
|
||||
* refreshing things and looking at the proper times.
|
||||
*/
|
||||
|
||||
playit()
|
||||
{
|
||||
register char *opts;
|
||||
|
||||
|
||||
/*
|
||||
* parse environment declaration of options
|
||||
*/
|
||||
if ((opts = getenv("ROGUEOPTS")) != NULL)
|
||||
parse_opts(opts);
|
||||
|
||||
|
||||
player.t_oldpos = hero;
|
||||
oldrp = roomin(&hero);
|
||||
after = TRUE;
|
||||
command(); /* Command execution */
|
||||
endit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* see if the system is being used too much for this game
|
||||
*/
|
||||
too_much()
|
||||
{
|
||||
#if MAXPROCESSES
|
||||
if (loadav() > MAXPROCESSES)
|
||||
return(TRUE);
|
||||
#endif
|
||||
#if MAXUSERS
|
||||
if (ucount() > MAXUSERS)
|
||||
return(TRUE);
|
||||
#endif
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* author:
|
||||
* See if a user is an author of the program
|
||||
*/
|
||||
author()
|
||||
{
|
||||
switch (md_getuid()) {
|
||||
#if AUTHOR
|
||||
case AUTHOR:
|
||||
#endif
|
||||
case 0: /* always OK for root to play */
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if CHECKTIME
|
||||
static int num_checks = 0; /* times we've gone over in checkout() */
|
||||
|
||||
checkout()
|
||||
{
|
||||
static char *msgs[] = {
|
||||
"The system is too loaded for games. Please leave in %d minutes",
|
||||
"Please save your game. You have %d minutes",
|
||||
"This is your last chance. You had better leave in %d minutes",
|
||||
};
|
||||
int checktime;
|
||||
|
||||
signal(SIGALRM, checkout);
|
||||
if (!holiday() && !author()) {
|
||||
msg("Game time is over. Your game is being saved.\n\n");
|
||||
auto_save(); /* NO RETURN */
|
||||
}
|
||||
if (too_much()) {
|
||||
if (num_checks >= 3)
|
||||
fatal("You didn't listen, so now you are DEAD !!\n");
|
||||
checktime = CHECKTIME / (num_checks + 1);
|
||||
chmsg(msgs[num_checks++], checktime);
|
||||
alarm(checktime * 60);
|
||||
}
|
||||
else {
|
||||
if (num_checks) {
|
||||
chmsg("The load has dropped. You have a reprieve.");
|
||||
num_checks = 0;
|
||||
}
|
||||
alarm(CHECKTIME * 60);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* checkout()'s version of msg. If we are in the middle of a shell, do a
|
||||
* printf instead of a msg to avoid the refresh.
|
||||
*/
|
||||
chmsg(fmt, arg)
|
||||
char *fmt;
|
||||
int arg;
|
||||
{
|
||||
if (in_shell) {
|
||||
printf(fmt, arg);
|
||||
putchar('\n');
|
||||
fflush(stdout);
|
||||
}
|
||||
else
|
||||
msg(fmt, arg);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MAXPROCESSES
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
loadav()
|
||||
{
|
||||
char *sarcmd = "sar -v | cut -c17-20 | tail -2";
|
||||
char *gettycmd = "grep getty /etc/inittab | wc -l";
|
||||
char sysbuffer[BUFSIZ];
|
||||
char tempfile[50];
|
||||
char inbuf[BUFSIZ];
|
||||
int fd, nprocess, ngetty;
|
||||
|
||||
sprintf(tempfile, "/tmp/rg%d", getpid());
|
||||
sprintf(sysbuffer, "%s > %s", sarcmd, tempfile);
|
||||
if (system(sysbuffer) != 0) {
|
||||
debug ("system() call failed");
|
||||
return (MAXPROCESSES - 1);
|
||||
}
|
||||
if ((fd = open(tempfile, O_RDONLY)) == -1) {
|
||||
debug ("open() call failed");
|
||||
return (MAXPROCESSES - 1);
|
||||
}
|
||||
if (read(fd, inbuf, BUFSIZ) == -1) {
|
||||
debug ("read() call failed");
|
||||
return (MAXPROCESSES - 1);
|
||||
}
|
||||
close(fd);
|
||||
sscanf(inbuf, "%d", &nprocess);
|
||||
sprintf(sysbuffer, "%s > %s", gettycmd, tempfile);
|
||||
if (system(sysbuffer) != 0) {
|
||||
debug ("system() call failed");
|
||||
return (MAXPROCESSES - 1);
|
||||
}
|
||||
if ((fd = open(tempfile, O_RDONLY)) == -1) {
|
||||
debug ("open() call failed");
|
||||
return (MAXPROCESSES - 1);
|
||||
}
|
||||
if (read(fd, inbuf, BUFSIZ) == -1) {
|
||||
debug ("read() call failed");
|
||||
return (MAXPROCESSES - 1);
|
||||
}
|
||||
close(fd);
|
||||
sscanf(inbuf, "%d", &ngetty);
|
||||
unlink(tempfile);
|
||||
return(nprocess - ngetty);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MAXUSERS
|
||||
/*
|
||||
* ucount:
|
||||
* Count the number of people on the system
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <utmp.h>
|
||||
struct utmp buf;
|
||||
ucount()
|
||||
{
|
||||
reg struct utmp *up;
|
||||
reg FILE *utmp;
|
||||
reg int count;
|
||||
|
||||
if ((utmp = fopen(UTMP, "r")) == NULL)
|
||||
return 0;
|
||||
|
||||
up = &buf;
|
||||
count = 0;
|
||||
while (fread(up, 1, sizeof (*up), utmp) > 0)
|
||||
#ifdef BSD
|
||||
if (buf.ut_line[0] == 't') /* On a tty */
|
||||
#else
|
||||
if (buf.ut_type == USER_PROCESS)
|
||||
#endif
|
||||
count++;
|
||||
fclose(utmp);
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* holiday:
|
||||
* Returns TRUE when it is a good time to play rogue
|
||||
*/
|
||||
holiday()
|
||||
{
|
||||
#ifdef CHECKTIME
|
||||
long now;
|
||||
struct tm *localtime();
|
||||
reg struct tm *ntime;
|
||||
|
||||
|
||||
time(&now); /* get the current time */
|
||||
ntime = localtime(&now);
|
||||
if(ntime->tm_wday == 0 || ntime->tm_wday == 6)
|
||||
return TRUE; /* OK on Sat & Sun */
|
||||
if(ntime->tm_hour < 8 || ntime->tm_hour >= 18)
|
||||
return TRUE; /* OK before 8AM & after 6PM */
|
||||
if(ntime->tm_yday <= 7 || ntime->tm_yday >= 350)
|
||||
return TRUE; /* OK during Christmas */
|
||||
return FALSE; /* All other times are bad */
|
||||
#else
|
||||
return TRUE;
|
||||
#endif
|
||||
}
|
||||
368
arogue7/maze.c
Normal file
368
arogue7/maze.c
Normal file
|
|
@ -0,0 +1,368 @@
|
|||
/*
|
||||
* maze.c - functions for dealing with mazes
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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 "curses.h"
|
||||
#include <stdlib.h>
|
||||
#include "rogue.h"
|
||||
|
||||
struct cell {
|
||||
char y_pos;
|
||||
char x_pos;
|
||||
};
|
||||
struct bordercells {
|
||||
char num_pos; /* number of frontier cells next to you */
|
||||
struct cell conn[4]; /* the y,x position of above cell */
|
||||
} border_cells;
|
||||
|
||||
|
||||
static char *frontier,
|
||||
*bits;
|
||||
static int maze_lines,
|
||||
maze_cols;
|
||||
char *moffset(),
|
||||
*foffset();
|
||||
|
||||
|
||||
/*
|
||||
* crankout:
|
||||
* Does actual drawing of maze to window
|
||||
*/
|
||||
crankout()
|
||||
{
|
||||
reg 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* domaze:
|
||||
* Draw the maze on this level.
|
||||
*/
|
||||
do_maze()
|
||||
{
|
||||
reg int least;
|
||||
reg struct room *rp;
|
||||
reg struct linked_list *item;
|
||||
reg struct object *obj;
|
||||
int cnt;
|
||||
bool treas;
|
||||
coord tp;
|
||||
|
||||
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) {
|
||||
rp->r_flags = ISGONE; /* kill all rooms */
|
||||
rp->r_fires = NULL; /* 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, NULL, NULL, NULL);
|
||||
obj = OBJPTR(item);
|
||||
obj->o_count *= (rnd(5) + 5); /* add in one large hunk */
|
||||
attach(lvl_obj, item);
|
||||
cnt = 0;
|
||||
do {
|
||||
rnd_pos(rp, &tp);
|
||||
} until (mvinch(tp.y, tp.x) == FLOOR || cnt++ > 5000);
|
||||
mvaddch(tp.y, tp.x, GOLD);
|
||||
obj->o_pos = tp;
|
||||
/*
|
||||
* add in some food to make sure he has enough
|
||||
*/
|
||||
item = spec_item(FOOD, NULL, NULL, NULL);
|
||||
obj = OBJPTR(item);
|
||||
attach(lvl_obj, item);
|
||||
do {
|
||||
rnd_pos(rp, &tp);
|
||||
} until (mvinch(tp.y, tp.x) == FLOOR || cnt++ > 5000);
|
||||
mvaddch(tp.y, tp.x, FOOD);
|
||||
obj->o_pos = tp;
|
||||
if (rnd(100) < 40) { /* treasure type maze */
|
||||
treas = TRUE;
|
||||
least = 10;
|
||||
debug("treasure maze");
|
||||
}
|
||||
else { /* normal maze level */
|
||||
least = 5;
|
||||
treas = FALSE;
|
||||
}
|
||||
genmonsters(least, treas);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* draw_maze:
|
||||
* Generate and draw the maze on the screen
|
||||
*/
|
||||
draw_maze()
|
||||
{
|
||||
reg int i, j, more;
|
||||
reg char *ptr;
|
||||
|
||||
maze_lines = (lines - 3) / 2;
|
||||
maze_cols = (cols - 1) / 2;
|
||||
bits = ALLOC((lines - 3) * (cols - 1));
|
||||
frontier = ALLOC(maze_lines * maze_cols);
|
||||
ptr = frontier;
|
||||
while (ptr < (frontier + (maze_lines * maze_cols)))
|
||||
*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 < maze_lines; i++) {
|
||||
for (j = 0; j < maze_cols; j++) {
|
||||
do
|
||||
more = findcells(i,j);
|
||||
while(more != 0);
|
||||
}
|
||||
}
|
||||
crankout();
|
||||
FREE(frontier);
|
||||
FREE(bits);
|
||||
}
|
||||
|
||||
/*
|
||||
* findcells:
|
||||
* Figure out cells to open up
|
||||
*/
|
||||
findcells(y,x)
|
||||
reg int x, y;
|
||||
{
|
||||
reg int rtpos, i;
|
||||
|
||||
*foffset(y, x) = FALSE;
|
||||
border_cells.num_pos = 0;
|
||||
if (y < maze_lines - 1) { /* look below */
|
||||
if (*foffset(y + 1, x)) {
|
||||
border_cells.conn[border_cells.num_pos].y_pos = y + 1;
|
||||
border_cells.conn[border_cells.num_pos].x_pos = x;
|
||||
border_cells.num_pos += 1;
|
||||
}
|
||||
}
|
||||
if (y > 0) { /* look above */
|
||||
if (*foffset(y - 1, x)) {
|
||||
border_cells.conn[border_cells.num_pos].y_pos = y - 1;
|
||||
border_cells.conn[border_cells.num_pos].x_pos = x;
|
||||
border_cells.num_pos += 1;
|
||||
|
||||
}
|
||||
}
|
||||
if (x < maze_cols - 1) { /* look right */
|
||||
if (*foffset(y, x + 1)) {
|
||||
border_cells.conn[border_cells.num_pos].y_pos = y;
|
||||
border_cells.conn[border_cells.num_pos].x_pos = x + 1;
|
||||
border_cells.num_pos += 1;
|
||||
}
|
||||
}
|
||||
if (x > 0) { /* look left */
|
||||
if (*foffset(y, x - 1)) {
|
||||
border_cells.conn[border_cells.num_pos].y_pos = y;
|
||||
border_cells.conn[border_cells.num_pos].x_pos = x - 1;
|
||||
border_cells.num_pos += 1;
|
||||
|
||||
}
|
||||
}
|
||||
if (border_cells.num_pos == 0) /* no neighbors available */
|
||||
return 0;
|
||||
else {
|
||||
i = rnd(border_cells.num_pos);
|
||||
rtpos = border_cells.num_pos - 1;
|
||||
rmwall(border_cells.conn[i].y_pos, border_cells.conn[i].x_pos, y, x);
|
||||
return rtpos;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* foffset:
|
||||
* Calculate memory address for frontier
|
||||
*/
|
||||
char *
|
||||
foffset(y, x)
|
||||
int y, x;
|
||||
{
|
||||
|
||||
return (frontier + (y * maze_cols) + x);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Maze_view:
|
||||
* Returns true if the player can see the specified location within
|
||||
* the confines of a maze (within one column or row)
|
||||
*/
|
||||
|
||||
bool
|
||||
maze_view(y, x)
|
||||
int y, x;
|
||||
{
|
||||
register int start, goal, delta, ycheck, xcheck, absy, absx, see_radius;
|
||||
register bool row;
|
||||
|
||||
/* Get the absolute value of y and x differences */
|
||||
absy = hero.y - y;
|
||||
absx = hero.x - x;
|
||||
if (absy < 0) absy = -absy;
|
||||
if (absx < 0) absx = -absx;
|
||||
|
||||
/* If we are standing in a wall, we can see a bit more */
|
||||
switch (winat(hero.y, hero.x)) {
|
||||
case '|':
|
||||
case '-':
|
||||
case WALL:
|
||||
case SECRETDOOR:
|
||||
case DOOR:
|
||||
see_radius = 2;
|
||||
otherwise:
|
||||
see_radius = 1;
|
||||
}
|
||||
|
||||
/* Must be within one or two rows or columns */
|
||||
if (absy > see_radius && absx > see_radius) return(FALSE);
|
||||
|
||||
if (absx > see_radius) { /* Go along row */
|
||||
start = hero.x;
|
||||
goal = x;
|
||||
ycheck = hero.y;
|
||||
row = TRUE;
|
||||
}
|
||||
else { /* Go along column */
|
||||
start = hero.y;
|
||||
goal = y;
|
||||
xcheck = hero.x;
|
||||
row = FALSE;
|
||||
}
|
||||
|
||||
if (start <= goal) delta = 1;
|
||||
else delta = -1;
|
||||
|
||||
/* Start one past where we are standing */
|
||||
if (start != goal) start += delta;
|
||||
|
||||
/* If we are in a wall, we want to look in the area outside the wall */
|
||||
if (see_radius > 1) {
|
||||
if (row) {
|
||||
/* See if above us it okay first */
|
||||
switch (winat(ycheck, start)) {
|
||||
case '|':
|
||||
case '-':
|
||||
case WALL:
|
||||
case DOOR:
|
||||
case SECRETDOOR:
|
||||
/* No good, try one up */
|
||||
if (y > hero.y) ycheck++;
|
||||
else ycheck--;
|
||||
otherwise:
|
||||
see_radius = 1; /* Just look straight over the row */
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* See if above us it okay first */
|
||||
switch (winat(start, xcheck)) {
|
||||
case '|':
|
||||
case '-':
|
||||
case WALL:
|
||||
case DOOR:
|
||||
case SECRETDOOR:
|
||||
/* No good, try one over */
|
||||
if (x > hero.x) xcheck++;
|
||||
else xcheck--;
|
||||
otherwise:
|
||||
see_radius = 1; /* Just look straight up the column */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check boundary again */
|
||||
if (absy > see_radius && absx > see_radius) return(FALSE);
|
||||
|
||||
while (start != goal) {
|
||||
if (row) xcheck = start;
|
||||
else ycheck = start;
|
||||
switch (winat(ycheck, xcheck)) {
|
||||
case '|':
|
||||
case '-':
|
||||
case WALL:
|
||||
case DOOR:
|
||||
case SECRETDOOR:
|
||||
return(FALSE);
|
||||
}
|
||||
start += delta;
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* moffset:
|
||||
* Calculate memory address for bits
|
||||
*/
|
||||
char *
|
||||
moffset(y, x)
|
||||
int y, x;
|
||||
{
|
||||
|
||||
return (bits + (y * (cols - 1)) + x);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* rmwall:
|
||||
* Removes appropriate walls from the maze
|
||||
*/
|
||||
rmwall(newy, newx, oldy, oldx)
|
||||
int newy, newx, oldy, oldx;
|
||||
{
|
||||
reg int xdif,ydif;
|
||||
|
||||
xdif = newx - oldx;
|
||||
ydif = newy - oldy;
|
||||
|
||||
*moffset((oldy * 2) + ydif + 1, (oldx * 2) + xdif + 1) = FALSE;
|
||||
findcells(newy, newx);
|
||||
}
|
||||
1195
arogue7/mdport.c
Normal file
1195
arogue7/mdport.c
Normal file
File diff suppressed because it is too large
Load diff
1202
arogue7/misc.c
Normal file
1202
arogue7/misc.c
Normal file
File diff suppressed because it is too large
Load diff
827
arogue7/monsters.c
Normal file
827
arogue7/monsters.c
Normal file
|
|
@ -0,0 +1,827 @@
|
|||
/*
|
||||
* monsters.c - File with various monster functions in it
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* File with various monster functions in it
|
||||
*
|
||||
*/
|
||||
|
||||
#include "curses.h"
|
||||
#include "rogue.h"
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
/*
|
||||
* Check_residue takes care of any effect of the monster
|
||||
*/
|
||||
check_residue(tp)
|
||||
register struct thing *tp;
|
||||
{
|
||||
/*
|
||||
* Take care of special abilities
|
||||
*/
|
||||
if (on(*tp, DIDHOLD) && (--hold_count == 0)) {
|
||||
turn_off(player, ISHELD);
|
||||
turn_off(*tp, DIDHOLD);
|
||||
}
|
||||
|
||||
/* If frightened of this monster, stop */
|
||||
if (on(player, ISFLEE) &&
|
||||
player.t_dest == &tp->t_pos) turn_off(player, ISFLEE);
|
||||
|
||||
/* If monster was suffocating player, stop it */
|
||||
if (on(*tp, DIDSUFFOCATE)) {
|
||||
extinguish(suffocate);
|
||||
turn_off(*tp, DIDSUFFOCATE);
|
||||
}
|
||||
|
||||
/* If something with fire, may darken */
|
||||
if (on(*tp, HASFIRE)) {
|
||||
register struct room *rp=roomin(&tp->t_pos);
|
||||
register struct linked_list *fire_item;
|
||||
|
||||
if (rp) {
|
||||
for (fire_item = rp->r_fires; fire_item != NULL;
|
||||
fire_item = next(fire_item)) {
|
||||
if (THINGPTR(fire_item) == tp) {
|
||||
detach(rp->r_fires, fire_item);
|
||||
destroy_item(fire_item);
|
||||
if (rp->r_fires == NULL) {
|
||||
rp->r_flags &= ~HASFIRE;
|
||||
if (cansee(tp->t_pos.y, tp->t_pos.x)) light(&hero);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Creat_mons creates the specified monster -- any if 0
|
||||
*/
|
||||
|
||||
bool
|
||||
creat_mons(person, monster, report)
|
||||
struct thing *person; /* Where to create next to */
|
||||
short monster;
|
||||
bool report;
|
||||
{
|
||||
struct linked_list *nitem;
|
||||
register struct thing *tp;
|
||||
struct room *rp;
|
||||
coord *mp;
|
||||
|
||||
if (levtype == POSTLEV)
|
||||
return(FALSE);
|
||||
if ((mp = fallpos(&(person->t_pos), FALSE, 2)) != NULL) {
|
||||
nitem = new_item(sizeof (struct thing));
|
||||
new_monster(nitem,
|
||||
monster == 0 ? randmonster(FALSE, FALSE)
|
||||
: monster,
|
||||
mp,
|
||||
TRUE);
|
||||
tp = THINGPTR(nitem);
|
||||
runto(tp, &hero);
|
||||
carry_obj(tp, monsters[tp->t_index].m_carry/2); /* only half chance */
|
||||
|
||||
/* since it just got here, it is disoriented */
|
||||
tp->t_no_move = 2 * movement(tp);
|
||||
|
||||
if (on(*tp, HASFIRE)) {
|
||||
rp = roomin(&tp->t_pos);
|
||||
if (rp) {
|
||||
register struct linked_list *fire_item;
|
||||
|
||||
/* Put the new fellow in the room list */
|
||||
fire_item = creat_item();
|
||||
ldata(fire_item) = (char *) tp;
|
||||
attach(rp->r_fires, fire_item);
|
||||
|
||||
rp->r_flags |= HASFIRE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we can see this monster, set oldch to ' ' to make light()
|
||||
* think the creature used to be invisible (ie. not seen here)
|
||||
*/
|
||||
if (cansee(tp->t_pos.y, tp->t_pos.x)) tp->t_oldch = ' ';
|
||||
return(TRUE);
|
||||
}
|
||||
if (report) msg("You hear a faint cry of anguish in the distance.");
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Genmonsters:
|
||||
* Generate at least 'least' monsters for this single room level.
|
||||
* 'Treas' indicates whether this is a "treasure" level.
|
||||
*/
|
||||
|
||||
void
|
||||
genmonsters(least, treas)
|
||||
register int least;
|
||||
bool treas;
|
||||
{
|
||||
reg int i;
|
||||
reg struct room *rp = &rooms[0];
|
||||
reg struct linked_list *item;
|
||||
reg struct thing *mp;
|
||||
coord tp;
|
||||
|
||||
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);
|
||||
} until(mvwinch(stdscr, tp.y, tp.x) == FLOOR);
|
||||
|
||||
new_monster(item, randmonster(FALSE, FALSE), &tp, FALSE);
|
||||
/*
|
||||
* See if we want to give it a treasure to carry around.
|
||||
*/
|
||||
carry_obj(mp, monsters[mp->t_index].m_carry);
|
||||
|
||||
/* Calculate a movement rate */
|
||||
mp->t_no_move = movement(mp);
|
||||
|
||||
/* Is it going to give us some light? */
|
||||
if (on(*mp, HASFIRE)) {
|
||||
register struct linked_list *fire_item;
|
||||
|
||||
fire_item = creat_item();
|
||||
ldata(fire_item) = (char *) mp;
|
||||
attach(rp->r_fires, fire_item);
|
||||
rp->r_flags |= HASFIRE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* id_monst returns the index of the monster given its letter
|
||||
*/
|
||||
|
||||
short
|
||||
id_monst(monster)
|
||||
register char monster;
|
||||
{
|
||||
register short result;
|
||||
|
||||
result = NLEVMONS*vlevel;
|
||||
if (result > NUMMONST) result = NUMMONST;
|
||||
|
||||
for(; result>0; result--)
|
||||
if (monsters[result].m_appear == monster) return(result);
|
||||
for (result=(NLEVMONS*vlevel)+1; result <= NUMMONST; result++)
|
||||
if (monsters[result].m_appear == monster) return(result);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* new_monster:
|
||||
* Pick a new monster and add it to the list
|
||||
*/
|
||||
|
||||
new_monster(item, type, cp, max_monster)
|
||||
struct linked_list *item;
|
||||
short type;
|
||||
coord *cp;
|
||||
bool max_monster;
|
||||
{
|
||||
register struct thing *tp;
|
||||
register struct monster *mp;
|
||||
register char *ip, *hitp;
|
||||
register int i, min_intel, max_intel;
|
||||
register int num_dice, num_sides=8, num_extra=0;
|
||||
char *strchr();
|
||||
|
||||
attach(mlist, item);
|
||||
tp = THINGPTR(item);
|
||||
tp->t_pack = NULL;
|
||||
tp->t_index = type;
|
||||
tp->t_wasshot = FALSE;
|
||||
tp->t_type = monsters[type].m_appear;
|
||||
tp->t_ctype = C_MONSTER;
|
||||
tp->t_action = A_NIL;
|
||||
tp->t_doorgoal = 0;
|
||||
tp->t_quiet = 0;
|
||||
tp->t_dest = NULL;
|
||||
tp->t_name = NULL;
|
||||
tp->t_pos = tp->t_oldpos = *cp;
|
||||
tp->t_oldch = CCHAR( mvwinch(cw, cp->y, cp->x) );
|
||||
mvwaddch(mw, cp->y, cp->x, tp->t_type);
|
||||
mp = &monsters[tp->t_index];
|
||||
|
||||
/* Figure out monster's hit points */
|
||||
hitp = mp->m_stats.s_hpt;
|
||||
num_dice = atoi(hitp);
|
||||
if ((hitp = strchr(hitp, 'd')) != NULL) {
|
||||
num_sides = atoi(++hitp);
|
||||
if ((hitp = strchr(hitp, '+')) != NULL)
|
||||
num_extra = atoi(++hitp);
|
||||
}
|
||||
|
||||
tp->t_stats.s_lvladj = 0;
|
||||
tp->t_stats.s_lvl = mp->m_stats.s_lvl;
|
||||
tp->t_stats.s_arm = mp->m_stats.s_arm;
|
||||
strncpy(tp->t_stats.s_dmg, mp->m_stats.s_dmg, sizeof(tp->t_stats.s_dmg));
|
||||
tp->t_stats.s_str = mp->m_stats.s_str;
|
||||
tp->t_stats.s_dext = mp->m_stats.s_dex;
|
||||
tp->t_movement = mp->m_stats.s_move;
|
||||
if (vlevel > HARDER) { /* the deeper, the meaner we get */
|
||||
tp->t_stats.s_lvl += (vlevel - HARDER);
|
||||
num_dice += (vlevel - HARDER)/2;
|
||||
tp->t_stats.s_arm -= (vlevel - HARDER) / 4;
|
||||
}
|
||||
if (max_monster)
|
||||
tp->t_stats.s_hpt = num_dice * num_sides + num_extra;
|
||||
else
|
||||
tp->t_stats.s_hpt = roll(num_dice, num_sides) + num_extra;
|
||||
tp->t_stats.s_exp = mp->m_stats.s_exp + mp->m_add_exp*tp->t_stats.s_hpt;
|
||||
|
||||
/*
|
||||
* just initailize others values to something reasonable for now
|
||||
* maybe someday will *really* put these in monster table
|
||||
*/
|
||||
tp->t_stats.s_wisdom = 8 + rnd(4);
|
||||
tp->t_stats.s_const = 8 + rnd(4);
|
||||
tp->t_stats.s_charisma = 8 + rnd(4);
|
||||
|
||||
/* Set the initial flags */
|
||||
for (i=0; i<16; i++) tp->t_flags[i] = 0;
|
||||
for (i=0; i<MAXFLAGS; i++)
|
||||
turn_on(*tp, mp->m_flags[i]);
|
||||
|
||||
/*
|
||||
* these are the base chances that a creatures will do something
|
||||
* assuming it can. These are(or can be) modified at runtime
|
||||
* based on what the creature experiences
|
||||
*/
|
||||
tp->t_breathe = 75; /* base chance of breathing */
|
||||
tp->t_artifact = 90; /* base chance of using artifact */
|
||||
tp->t_summon = 40; /* base chance of summoning */
|
||||
tp->t_cast = 75; /* base chance of casting a spell */
|
||||
tp->t_wand = on(*tp, ISUNIQUE) ? 35 : 50; /* base chance of using wands */
|
||||
|
||||
/* suprising monsters don't always surprise you */
|
||||
if (!max_monster && on(*tp, CANSURPRISE) &&
|
||||
off(*tp, ISUNIQUE) && rnd(100) < 20)
|
||||
turn_off(*tp, CANSURPRISE);
|
||||
|
||||
/* If this monster is unique, gen it */
|
||||
if (on(*tp, ISUNIQUE)) mp->m_normal = FALSE;
|
||||
|
||||
/*
|
||||
* If it is the quartermaster, then compute his level and exp pts
|
||||
* based on the level. This will make it fair when thieves try to
|
||||
* steal and give them reasonable experience if they succeed.
|
||||
* Then fill his pack with his wares.
|
||||
*/
|
||||
if (on(*tp, CANSELL)) {
|
||||
tp->t_stats.s_exp = vlevel * 100;
|
||||
tp->t_stats.s_lvl = vlevel/2 + 1;
|
||||
make_sell_pack(tp);
|
||||
}
|
||||
|
||||
/* Normally scared monsters have a chance to not be scared */
|
||||
if (on(*tp, ISFLEE) && (rnd(4) == 0)) turn_off(*tp, ISFLEE);
|
||||
|
||||
/* Figure intelligence */
|
||||
min_intel = atoi(mp->m_intel);
|
||||
if ((ip = (char *) strchr(mp->m_intel, '-')) == NULL)
|
||||
tp->t_stats.s_intel = min_intel;
|
||||
else {
|
||||
max_intel = atoi(++ip);
|
||||
if (max_monster)
|
||||
tp->t_stats.s_intel = max_intel;
|
||||
else
|
||||
tp->t_stats.s_intel = min_intel + rnd(max_intel - min_intel);
|
||||
}
|
||||
if (vlevel > HARDER)
|
||||
tp->t_stats.s_intel += ((vlevel - HARDER)/2);
|
||||
tp->maxstats = tp->t_stats;
|
||||
|
||||
/* If the monster can shoot, it may have a weapon */
|
||||
if (on(*tp, CANSHOOT) && ((rnd(100) < (22 + vlevel)) || max_monster)) {
|
||||
struct linked_list *item1;
|
||||
register struct object *cur, *cur1;
|
||||
|
||||
item = new_item(sizeof *cur);
|
||||
item1 = new_item(sizeof *cur1);
|
||||
cur = OBJPTR(item);
|
||||
cur1 = OBJPTR(item1);
|
||||
cur->o_hplus = (rnd(4) < 3) ? 0
|
||||
: (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
|
||||
cur->o_dplus = (rnd(4) < 3) ? 0
|
||||
: (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
|
||||
cur1->o_hplus = (rnd(4) < 3) ? 0
|
||||
: (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
|
||||
cur1->o_dplus = (rnd(4) < 3) ? 0
|
||||
: (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
|
||||
|
||||
strncpy(cur->o_damage, "0d0", sizeof(cur->o_damage));
|
||||
strncpy(cur->o_hurldmg, "0d0", sizeof(cur->o_hurldmg));
|
||||
strncpy(cur1->o_damage, "0d0", sizeof(cur1->o_damage));
|
||||
strncpy(cur1->o_hurldmg, "0d0", sizeof(cur1->o_hurldmg));
|
||||
|
||||
cur->o_ac = cur1->o_ac = 11;
|
||||
cur->o_count = cur1->o_count = 1;
|
||||
cur->o_group = cur1->o_group = 0;
|
||||
cur->contents = cur1->contents = NULL;
|
||||
if ((cur->o_hplus <= 0) && (cur->o_dplus <= 0)) cur->o_flags = ISCURSED;
|
||||
if ((cur1->o_hplus <= 0) && (cur1->o_dplus <= 0))
|
||||
cur1->o_flags = ISCURSED;
|
||||
cur->o_flags = cur1->o_flags = 0;
|
||||
cur->o_type = cur1->o_type = WEAPON;
|
||||
cur->o_mark[0] = cur1->o_mark[0] = '\0';
|
||||
|
||||
/* The monster may use a crossbow, sling, or an arrow */
|
||||
i = rnd(100);
|
||||
if (i < 10) {
|
||||
cur->o_which = CROSSBOW;
|
||||
cur1->o_which = BOLT;
|
||||
init_weapon(cur, CROSSBOW);
|
||||
init_weapon(cur1, BOLT);
|
||||
}
|
||||
else if (i < 70) {
|
||||
cur->o_which = BOW;
|
||||
cur1->o_which = ARROW;
|
||||
init_weapon(cur, BOW);
|
||||
init_weapon(cur1, ARROW);
|
||||
}
|
||||
else {
|
||||
cur->o_which = SLING;
|
||||
cur1->o_which = ROCK;
|
||||
init_weapon(cur, SLING);
|
||||
init_weapon(cur1, ROCK);
|
||||
}
|
||||
|
||||
attach(tp->t_pack, item);
|
||||
attach(tp->t_pack, item1);
|
||||
}
|
||||
|
||||
|
||||
/* Calculate the initial movement rate */
|
||||
updpack(TRUE, tp);
|
||||
tp->t_no_move = movement(tp);
|
||||
|
||||
if (ISWEARING(R_AGGR))
|
||||
runto(tp, &hero);
|
||||
if (on(*tp, ISDISGUISE))
|
||||
{
|
||||
char mch;
|
||||
|
||||
if (tp->t_pack != NULL)
|
||||
mch = (OBJPTR(tp->t_pack))->o_type;
|
||||
else
|
||||
switch (rnd(10)) {
|
||||
case 0: mch = GOLD;
|
||||
when 1: mch = POTION;
|
||||
when 2: mch = SCROLL;
|
||||
when 3: mch = FOOD;
|
||||
when 4: mch = WEAPON;
|
||||
when 5: mch = ARMOR;
|
||||
when 6: mch = RING;
|
||||
when 7: mch = STICK;
|
||||
when 8: mch = monsters[randmonster(FALSE, FALSE)].m_appear;
|
||||
when 9: mch = MM;
|
||||
}
|
||||
tp->t_disguise = mch;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* randmonster:
|
||||
* Pick a monster to show up. The lower the level,
|
||||
* the meaner the monster.
|
||||
*/
|
||||
|
||||
short
|
||||
randmonster(wander, no_unique)
|
||||
register bool wander, no_unique;
|
||||
{
|
||||
register int d, cur_level, range, i;
|
||||
|
||||
/*
|
||||
* Do we want a merchant? Merchant is always in place 'NUMMONST'
|
||||
*/
|
||||
if (wander && monsters[NUMMONST].m_wander && rnd(100) < pstats.s_charisma/4)
|
||||
return NUMMONST;
|
||||
|
||||
cur_level = vlevel;
|
||||
range = 4*NLEVMONS;
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
if (i++ > range*10) { /* just in case all have be genocided */
|
||||
i = 0;
|
||||
if (--cur_level <= 0)
|
||||
fatal("Rogue could not find a monster to make");
|
||||
}
|
||||
d = NLEVMONS*(cur_level - 1) + (rnd(range) - (range - 1 - NLEVMONS));
|
||||
if (d < 1)
|
||||
d = rnd(NLEVMONS) + 1;
|
||||
if (d > NUMMONST - NUMUNIQUE - 1) {
|
||||
if (no_unique)
|
||||
d = rnd(range) + (NUMMONST - NUMUNIQUE - 1) - (range - 1);
|
||||
else if (d > NUMMONST - 1)
|
||||
d = rnd(range+NUMUNIQUE) + (NUMMONST-1) - (range+NUMUNIQUE-1);
|
||||
}
|
||||
}
|
||||
while (wander ? !monsters[d].m_wander || !monsters[d].m_normal
|
||||
: !monsters[d].m_normal);
|
||||
return d;
|
||||
}
|
||||
|
||||
/* Sell displays a menu of goods from which the player may choose
|
||||
* to purchase something.
|
||||
*/
|
||||
|
||||
sell(tp)
|
||||
register struct thing *tp;
|
||||
{
|
||||
register struct linked_list *item, *seller;
|
||||
register struct linked_list *sellpack;
|
||||
register struct object *obj;
|
||||
register int worth, min_worth;
|
||||
char buffer[LINELEN];
|
||||
|
||||
|
||||
/*
|
||||
* Get a linked_list pointer to the seller. We need this in case
|
||||
* he disappears so we can set monst_dead.
|
||||
*/
|
||||
seller = find_mons(tp->t_pos.y, tp->t_pos.x);
|
||||
|
||||
sellpack = tp->t_pack;
|
||||
if (sellpack == NULL) {
|
||||
msg("%s looks puzzled and departs.", prname(monster_name(tp), TRUE));
|
||||
|
||||
/* Get rid of the monster */
|
||||
killed(seller, FALSE, FALSE, FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* See how much the minimum pack item is worth */
|
||||
min_worth = 100000;
|
||||
for (item = sellpack; item != NULL; item = next(item)) {
|
||||
obj = OBJPTR(item);
|
||||
obj->o_flags |= ISPOST; /* Force a long description of the item */
|
||||
worth = get_worth(obj);
|
||||
if (worth < min_worth) min_worth = worth;
|
||||
}
|
||||
|
||||
/* See if player can afford an item */
|
||||
if (min_worth > purse) {
|
||||
msg("%s eyes your small purse and departs.",
|
||||
prname(monster_name(tp), TRUE));
|
||||
|
||||
/* Get rid of the monster */
|
||||
killed(seller, FALSE, FALSE, FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Announce our intentions */
|
||||
msg("%s opens his pack.--More--", prname(monster_name(tp), TRUE));
|
||||
wait_for(' ');
|
||||
|
||||
/* Try to sell something */
|
||||
sprintf(buffer, "You got %d gold pieces. Buy", purse);
|
||||
item = get_item(sellpack, buffer, ALL, TRUE, TRUE);
|
||||
|
||||
/* Get rid of the monster */
|
||||
if (item != NULL) detach(tp->t_pack, item); /* Take it out of the pack */
|
||||
killed(seller, FALSE, FALSE, FALSE);
|
||||
|
||||
if (item == NULL) return;
|
||||
|
||||
/* Can he afford the selected item? */
|
||||
obj = OBJPTR(item);
|
||||
|
||||
worth = get_worth(obj);
|
||||
if (worth > purse) {
|
||||
msg("You cannot afford it.");
|
||||
o_discard(item);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Charge him through the nose */
|
||||
purse -= worth;
|
||||
|
||||
/* If a stick or ring, let player know the type */
|
||||
switch (obj->o_type) {
|
||||
case RING: r_know[obj->o_which] = TRUE;
|
||||
when POTION:p_know[obj->o_which] = TRUE;
|
||||
when SCROLL:s_know[obj->o_which] = TRUE;
|
||||
when STICK: ws_know[obj->o_which] = TRUE;
|
||||
when MM: m_know[obj->o_which] = TRUE;
|
||||
|
||||
}
|
||||
|
||||
/* Remove the POST flag that we used for get_item() */
|
||||
obj->o_flags &= ~ISPOST;
|
||||
|
||||
if (add_pack(item, FALSE, NULL) == FALSE) {
|
||||
obj->o_pos = hero;
|
||||
fall(item, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* what to do when the hero steps next to a monster
|
||||
*/
|
||||
struct linked_list *
|
||||
wake_monster(y, x)
|
||||
int y, x;
|
||||
{
|
||||
register struct thing *tp;
|
||||
register struct linked_list *it;
|
||||
register struct room *trp;
|
||||
register char *mname;
|
||||
bool nasty; /* Will the monster "attack"? */
|
||||
|
||||
if ((it = find_mons(y, x)) == NULL) {
|
||||
msg("Wake: can't find monster in show (%d, %d)", y, x);
|
||||
return (NULL);
|
||||
}
|
||||
tp = THINGPTR(it);
|
||||
if (on(*tp, ISSTONE)) /* if stoned, don't do anything */
|
||||
return it;
|
||||
|
||||
/*
|
||||
* For now, if we are a friendly monster, we won't do any of
|
||||
* our special effects.
|
||||
*/
|
||||
if (on(*tp, ISFRIENDLY)) return it;
|
||||
|
||||
trp = roomin(&tp->t_pos); /* Current room for monster */
|
||||
|
||||
/*
|
||||
* Let greedy ones in a room guard gold
|
||||
* (except in a maze where lots of creatures would all go for the
|
||||
* same piece of gold)
|
||||
*/
|
||||
if (on(*tp, ISGREED) && off(*tp, ISRUN) &&
|
||||
levtype != MAZELEV && trp != NULL &&
|
||||
lvl_obj != NULL) {
|
||||
register struct linked_list *item;
|
||||
register struct object *cur;
|
||||
|
||||
for (item = lvl_obj; item != NULL; item = next(item)) {
|
||||
cur = OBJPTR(item);
|
||||
if ((cur->o_type == GOLD) && (roomin(&cur->o_pos) == trp)) {
|
||||
/* Run to the gold */
|
||||
runto(tp, &cur->o_pos);
|
||||
|
||||
/* Make it worth protecting */
|
||||
cur->o_count += GOLDCALC + GOLDCALC;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Every time he sees mean monster, it might start chasing him
|
||||
*/
|
||||
if (on(*tp, ISMEAN) &&
|
||||
off(*tp, ISHELD) &&
|
||||
off(*tp, ISRUN) &&
|
||||
rnd(100) > 33 &&
|
||||
(!is_stealth(&player) || (on(*tp, ISUNIQUE) && rnd(100) > 50)) &&
|
||||
(off(player, ISINVIS) || on(*tp, CANSEE)) ||
|
||||
(trp != NULL && (trp->r_flags & ISTREAS))) {
|
||||
runto(tp, &hero);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the name; we don't want to do it until here because we need to
|
||||
* know whether the monster is still sleeping or not.
|
||||
*/
|
||||
mname = monster_name(tp);
|
||||
|
||||
/* See if the monster will bother the player */
|
||||
nasty = (on(*tp, ISRUN) && cansee(tp->t_pos.y, tp->t_pos.x));
|
||||
|
||||
/*
|
||||
* if the creature is awake and can see the player and the
|
||||
* player has the dreaded "eye of vecna" then see if the
|
||||
* creature is turned to stone
|
||||
*/
|
||||
if (cur_relic[EYE_VECNA] && nasty && off(*tp, NOSTONE) &&
|
||||
(off(player, ISINVIS) || on(*tp, CANSEE))) {
|
||||
turn_on(*tp, NOSTONE); /* only have to save once */
|
||||
if (!save(VS_PETRIFICATION, tp, -2)) {
|
||||
turn_on(*tp, ISSTONE);
|
||||
turn_off(*tp, ISRUN);
|
||||
turn_off(*tp, ISINVIS);
|
||||
turn_off(*tp, CANSURPRISE);
|
||||
turn_off(*tp, ISDISGUISE);
|
||||
msg("%s is turned to stone!", prname(mname, TRUE));
|
||||
return it;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle monsters that can gaze and do things while running
|
||||
* Player must be able to see the monster and the monster must
|
||||
* not be asleep
|
||||
*/
|
||||
if (nasty && !invisible(tp)) {
|
||||
/*
|
||||
* Confusion
|
||||
*/
|
||||
if (on(*tp, CANHUH) &&
|
||||
(off(*tp, ISINVIS) || on(player, CANSEE)) &&
|
||||
(off(*tp, CANSURPRISE) || ISWEARING(R_ALERT))) {
|
||||
if (!save(VS_MAGIC, &player, 0)) {
|
||||
if (off(player, ISCLEAR)) {
|
||||
if (find_slot(unconfuse))
|
||||
lengthen(unconfuse, HUHDURATION);
|
||||
else {
|
||||
fuse(unconfuse, 0, HUHDURATION, AFTER);
|
||||
msg("%s's gaze has confused you.",prname(mname, TRUE));
|
||||
turn_on(player, ISHUH);
|
||||
}
|
||||
}
|
||||
else msg("You feel dizzy for a moment, but it quickly passes.");
|
||||
}
|
||||
else if (rnd(100) < 67)
|
||||
turn_off(*tp, CANHUH); /* Once you save, maybe that's it */
|
||||
}
|
||||
|
||||
/* Sleep */
|
||||
if(on(*tp, CANSNORE) &&
|
||||
player.t_action != A_FREEZE &&
|
||||
!save(VS_PARALYZATION, &player, 0)) {
|
||||
if (ISWEARING(R_ALERT))
|
||||
msg("You feel slightly drowsy for a moment.");
|
||||
else {
|
||||
msg("%s's gaze puts you to sleep.", prname(mname, TRUE));
|
||||
player.t_no_move += movement(&player) * SLEEPTIME;
|
||||
player.t_action = A_FREEZE;
|
||||
if (rnd(100) < 50) turn_off(*tp, CANSNORE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fear */
|
||||
if (on(*tp, CANFRIGHTEN) && !on(player, ISFLEE)) {
|
||||
turn_off(*tp, CANFRIGHTEN);
|
||||
if (!ISWEARING(R_HEROISM) &&
|
||||
!save(VS_WAND, &player, -(tp->t_stats.s_lvl/10))) {
|
||||
turn_on(player, ISFLEE);
|
||||
player.t_dest = &tp->t_pos;
|
||||
msg("The sight of %s terrifies you.", prname(mname, FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* blinding creatures */
|
||||
if(on(*tp, CANBLIND) && !find_slot(sight)) {
|
||||
turn_off(*tp, CANBLIND);
|
||||
if (!save(VS_WAND, &player, 0)) {
|
||||
msg("The gaze of %s blinds you", prname(mname, FALSE));
|
||||
turn_on(player, ISBLIND);
|
||||
fuse(sight, 0, rnd(30)+20, AFTER);
|
||||
light(&hero);
|
||||
}
|
||||
}
|
||||
|
||||
/* the sight of the ghost can age you! */
|
||||
if (on(*tp, CANAGE)) {
|
||||
turn_off (*tp, CANAGE);
|
||||
if (!save(VS_MAGIC, &player, 0)) {
|
||||
msg ("The sight of %s ages you!", prname(mname, FALSE));
|
||||
pstats.s_const--;
|
||||
max_stats.s_const--;
|
||||
if (pstats.s_const < 0)
|
||||
death (D_CONSTITUTION);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Turning to stone */
|
||||
if (on(*tp, LOOKSTONE)) {
|
||||
turn_off(*tp, LOOKSTONE);
|
||||
|
||||
if (on(player, CANINWALL))
|
||||
msg("The gaze of %s has no effect.", prname(mname, FALSE));
|
||||
else {
|
||||
if (!save(VS_PETRIFICATION, &player, 0) && rnd(100) < 5) {
|
||||
pstats.s_hpt = -1;
|
||||
msg("The gaze of %s petrifies you.", prname(mname, FALSE));
|
||||
msg("You are turned to stone !!! --More--");
|
||||
wait_for(' ');
|
||||
death(D_PETRIFY);
|
||||
}
|
||||
else {
|
||||
msg("The gaze of %s stiffens your limbs.",
|
||||
prname(mname, FALSE));
|
||||
player.t_no_move += movement(&player) * STONETIME;
|
||||
player.t_action = A_FREEZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return it;
|
||||
}
|
||||
/*
|
||||
* wanderer:
|
||||
* A wandering monster has awakened and is headed for the player
|
||||
*/
|
||||
|
||||
wanderer()
|
||||
{
|
||||
register int i;
|
||||
register struct room *hr = roomin(&hero);
|
||||
register struct linked_list *item;
|
||||
register struct thing *tp;
|
||||
register long *attr; /* Points to monsters' attributes */
|
||||
int carry; /* Chance of wanderer carrying anything */
|
||||
short rmonst; /* Our random wanderer */
|
||||
bool canteleport = FALSE, /* Can the monster teleport? */
|
||||
seehim; /* Is monster within sight? */
|
||||
coord cp;
|
||||
|
||||
rmonst = randmonster(TRUE, FALSE); /* Choose a random wanderer */
|
||||
attr = &monsters[rmonst].m_flags[0]; /* Start of attributes */
|
||||
for (i=0; i<MAXFLAGS; i++)
|
||||
if (*attr++ == CANTELEPORT) {
|
||||
canteleport = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Find a place for it -- avoid the player's room if can't teleport */
|
||||
do {
|
||||
do {
|
||||
i = rnd_room();
|
||||
} until (canteleport || hr != &rooms[i] || levtype == MAZELEV ||
|
||||
levtype == OUTSIDE || levtype == POSTLEV);
|
||||
|
||||
/* Make sure the monster does not teleport on top of the player */
|
||||
do {
|
||||
rnd_pos(&rooms[i], &cp);
|
||||
} while (hr == &rooms[i] && ce(cp, hero));
|
||||
} until (step_ok(cp.y, cp.x, NOMONST, NULL));
|
||||
|
||||
/* Create a new wandering monster */
|
||||
item = new_item(sizeof *tp);
|
||||
new_monster(item, rmonst, &cp, FALSE);
|
||||
tp = THINGPTR(item);
|
||||
runto(tp, &hero);
|
||||
tp->t_pos = cp; /* Assign the position to the monster */
|
||||
seehim = cansee(tp->t_pos.y, tp->t_pos.x);
|
||||
if (on(*tp, HASFIRE)) {
|
||||
register struct room *rp;
|
||||
|
||||
rp = roomin(&tp->t_pos);
|
||||
if (rp) {
|
||||
register struct linked_list *fire_item;
|
||||
|
||||
fire_item = creat_item();
|
||||
ldata(fire_item) = (char *) tp;
|
||||
attach(rp->r_fires, fire_item);
|
||||
|
||||
rp->r_flags |= HASFIRE;
|
||||
if (seehim && next(rp->r_fires) == NULL)
|
||||
light(&hero);
|
||||
}
|
||||
}
|
||||
|
||||
/* See if we give the monster anything */
|
||||
carry = monsters[tp->t_index].m_carry;
|
||||
if (off(*tp, ISUNIQUE)) carry /= 2; /* Non-unique has only a half chance */
|
||||
carry_obj(tp, carry);
|
||||
|
||||
/* Calculate its movement rate */
|
||||
tp->t_no_move = movement(tp);
|
||||
|
||||
/* Alert the player if a monster just teleported in */
|
||||
if (hr == &rooms[i] && canteleport && seehim && !invisible(tp)) {
|
||||
msg("A %s just teleported in", monster_name(tp));
|
||||
light(&hero);
|
||||
running = FALSE;
|
||||
}
|
||||
|
||||
if (wizard)
|
||||
msg("Started a wandering %s", monster_name(tp));
|
||||
}
|
||||
1874
arogue7/move.c
Normal file
1874
arogue7/move.c
Normal file
File diff suppressed because it is too large
Load diff
36
arogue7/network.h
Normal file
36
arogue7/network.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* network.h - networking setup
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Note that networking is set up for machines that can communicate
|
||||
* via some system such as uucp. The mechanism listed here uses
|
||||
* uux and assumes that the target machine allows access to the
|
||||
* game via the uux command. NETCOMMAND must be defined if networking
|
||||
* is desired.
|
||||
*/
|
||||
|
||||
/* #define NETCOMMAND "uux - -n '%s!%s -u' >/dev/null 2>&1" */
|
||||
|
||||
/* Networking information -- should not vary among networking machines */
|
||||
#define SYSLEN 9
|
||||
#define LOGLEN 8
|
||||
#undef NUMNET /* 1 */
|
||||
struct network {
|
||||
char *system;
|
||||
char *rogue;
|
||||
};
|
||||
extern struct network Network[];
|
||||
|
||||
/* This system's name -- should not be defined if uname() is available */
|
||||
#undef SYSTEM /* "ihesa" */
|
||||
628
arogue7/new_level.c
Normal file
628
arogue7/new_level.c
Normal file
|
|
@ -0,0 +1,628 @@
|
|||
/*
|
||||
* new_level.c - Dig and draw a new level
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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 "curses.h"
|
||||
#include "rogue.h"
|
||||
#define TERRASAVE 3
|
||||
|
||||
/*
|
||||
* new_level:
|
||||
* Dig and draw a new level
|
||||
*
|
||||
*/
|
||||
|
||||
new_level(ltype)
|
||||
LEVTYPE ltype; /* designates type of level to create */
|
||||
{
|
||||
register int rm, i, cnt;
|
||||
register char ch;
|
||||
register struct linked_list *item;
|
||||
register struct thing *tp;
|
||||
register struct object *obj;
|
||||
int waslit = 0; /* Was the previous outside level lit? */
|
||||
int starty, startx, deltay, deltax;
|
||||
bool fresh=TRUE, vert, top;
|
||||
struct room *rp;
|
||||
struct linked_list *nitem, *savmonst=NULL, *savitems=NULL;
|
||||
coord stairs;
|
||||
|
||||
if (wizard) {
|
||||
msg("Turns: %d", turns); /* Number of turns for last level */
|
||||
mpos = 0;
|
||||
}
|
||||
|
||||
/* Start player off right */
|
||||
turn_off(player, ISHELD);
|
||||
turn_off(player, ISFLEE);
|
||||
extinguish(suffocate);
|
||||
hold_count = 0;
|
||||
trap_tries = 0;
|
||||
|
||||
/* Are we just entering a dungeon? If so, how big is it? */
|
||||
if (ltype != OUTSIDE && nfloors < 0) nfloors = HARDER+10 + rnd(11);
|
||||
|
||||
if (level > max_level)
|
||||
max_level = level;
|
||||
|
||||
/* Are we starting a new outside level? */
|
||||
if (ltype == OUTSIDE) {
|
||||
register int i, j;
|
||||
|
||||
/* Save some information prior to clearing the screen */
|
||||
if (level == -1 || mvinch(hero.y, hero.x) == '-') vert = TRUE;
|
||||
else vert = FALSE;
|
||||
|
||||
if (level == -1) {
|
||||
fresh = TRUE;
|
||||
starty = 2;
|
||||
startx = 1;
|
||||
deltay = deltax = 1;
|
||||
level = 0; /* Restore the level */
|
||||
}
|
||||
else { /* Copy several lines of the terrain to the other end */
|
||||
char cch; /* Copy character */
|
||||
|
||||
/* Was the area dark (not magically lit)? */
|
||||
if (!(rooms[0].r_flags & ISDARK)) waslit = 1;
|
||||
|
||||
fresh = FALSE;
|
||||
if ((vert && hero.y == 1) || (!vert && hero.x == 0)) top = TRUE;
|
||||
else top = FALSE;
|
||||
for (i=0; i<TERRASAVE; i++) {
|
||||
if (vert)
|
||||
for (j=1; j<cols-1; j++) {
|
||||
if (top) {
|
||||
cch = CCHAR( mvinch(i+2, j) );
|
||||
mvaddch(lines-6+i, j, cch);
|
||||
}
|
||||
else {
|
||||
cch = CCHAR( mvinch(lines-4-i, j) );
|
||||
mvaddch(4-i, j, cch);
|
||||
}
|
||||
}
|
||||
else
|
||||
for (j=2; j<lines-3; j++) {
|
||||
if (top) {
|
||||
cch = CCHAR( mvinch(j, i+1) );
|
||||
mvaddch(j, cols-4+i, cch);
|
||||
}
|
||||
else {
|
||||
cch = CCHAR( mvinch(j, cols-2-i) );
|
||||
mvaddch(j, 3-i, cch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vert) {
|
||||
startx = deltax = 1;
|
||||
if (top) {
|
||||
starty = lines-4-TERRASAVE;
|
||||
deltay = -1;
|
||||
}
|
||||
else {
|
||||
starty = TERRASAVE + 2;
|
||||
deltay = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
starty = 2;
|
||||
deltay = 1;
|
||||
if (top) {
|
||||
startx = cols-2-TERRASAVE;
|
||||
deltax = -1;
|
||||
}
|
||||
else {
|
||||
deltax = 1;
|
||||
startx = TERRASAVE + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if any monsters should be saved */
|
||||
for (item = mlist; item != NULL; item = nitem) {
|
||||
nitem = next(item);
|
||||
tp = THINGPTR(item);
|
||||
if (vert) {
|
||||
if (top) {
|
||||
if (tp->t_pos.y < TERRASAVE + 2)
|
||||
tp->t_pos.y += lines - 5 - TERRASAVE;
|
||||
else continue;
|
||||
}
|
||||
else {
|
||||
if (tp->t_pos.y > lines - 4 - TERRASAVE)
|
||||
tp->t_pos.y += 5 + TERRASAVE - lines;
|
||||
else continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (top) {
|
||||
if (tp->t_pos.x < TERRASAVE + 1)
|
||||
tp->t_pos.x += cols - 2 - TERRASAVE;
|
||||
else continue;
|
||||
}
|
||||
else {
|
||||
if (tp->t_pos.x > cols - 2 - TERRASAVE)
|
||||
tp->t_pos.x += 2 + TERRASAVE - cols;
|
||||
else continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the monster is busy chasing another monster, don't save
|
||||
* it
|
||||
*/
|
||||
if (tp->t_dest && tp->t_dest != &hero) continue;
|
||||
|
||||
detach(mlist, item);
|
||||
attach(savmonst, item);
|
||||
}
|
||||
|
||||
/* Check if any treasure should be saved */
|
||||
for (item = lvl_obj; item != NULL; item = nitem) {
|
||||
nitem = next(item);
|
||||
obj = OBJPTR(item);
|
||||
if (vert) {
|
||||
if (top) {
|
||||
if (obj->o_pos.y < TERRASAVE + 2)
|
||||
obj->o_pos.y += lines - 5 - TERRASAVE;
|
||||
else continue;
|
||||
}
|
||||
else {
|
||||
if (obj->o_pos.y > lines - 4 - TERRASAVE)
|
||||
obj->o_pos.y += 5 + TERRASAVE - lines;
|
||||
else continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (top) {
|
||||
if (obj->o_pos.x < TERRASAVE + 1)
|
||||
obj->o_pos.x += cols - 2 - TERRASAVE;
|
||||
else continue;
|
||||
}
|
||||
else {
|
||||
if (obj->o_pos.x > cols - 2 - TERRASAVE)
|
||||
obj->o_pos.x += 2 + TERRASAVE - cols;
|
||||
else continue;
|
||||
}
|
||||
}
|
||||
detach(lvl_obj, item);
|
||||
attach(savitems, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
wclear(cw);
|
||||
wclear(mw);
|
||||
if (fresh) clear();
|
||||
/*
|
||||
* check to see if he missed a UNIQUE, If he did then put it back
|
||||
* in the monster table for next time
|
||||
*/
|
||||
for (item = mlist; item != NULL; item = next(item)) {
|
||||
tp = THINGPTR(item);
|
||||
if (on(*tp, ISUNIQUE))
|
||||
monsters[tp->t_index].m_normal = TRUE;
|
||||
}
|
||||
/*
|
||||
* Free up the monsters on the last level
|
||||
*/
|
||||
t_free_list(monst_dead);
|
||||
t_free_list(mlist);
|
||||
o_free_list(lvl_obj); /* Free up previous objects (if any) */
|
||||
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
|
||||
r_free_list(rp->r_exit); /* Free up the exit lists */
|
||||
|
||||
levtype = ltype;
|
||||
foods_this_level = 0; /* food for hero this level */
|
||||
if (ltype == POSTLEV || ltype == STARTLEV) {
|
||||
if (ltype == POSTLEV) do_post(FALSE); /* Trading post */
|
||||
else do_post(TRUE); /* Equippage */
|
||||
levtype = ltype = POSTLEV;
|
||||
}
|
||||
else if (ltype == MAZELEV) {
|
||||
do_maze();
|
||||
no_food++;
|
||||
put_things(ltype); /* Place objects (if any) */
|
||||
}
|
||||
else if (ltype == OUTSIDE) {
|
||||
init_terrain();
|
||||
do_terrain(starty, startx, deltay, deltax, (bool) (fresh || !vert));
|
||||
no_food++;
|
||||
put_things(ltype);
|
||||
|
||||
/* Should we magically light this area? */
|
||||
if (waslit) rooms[0].r_flags &= ~ISDARK;
|
||||
}
|
||||
else {
|
||||
do_rooms(); /* Draw rooms */
|
||||
do_passages(); /* Draw passages */
|
||||
no_food++;
|
||||
put_things(ltype); /* Place objects (if any) */
|
||||
}
|
||||
/*
|
||||
* Place the staircase down. Only a small chance for an outside stairway.
|
||||
*/
|
||||
if (ltype != OUTSIDE || roll(1, 4) == 4) {
|
||||
cnt = 0;
|
||||
do {
|
||||
rm = rnd_room();
|
||||
rnd_pos(&rooms[rm], &stairs);
|
||||
} until (mvinch(stairs.y, stairs.x) == FLOOR || cnt++ > 5000);
|
||||
addch(STAIRS);
|
||||
}
|
||||
/*
|
||||
* maybe add a trading post
|
||||
*/
|
||||
if (level > 5 && rnd(11) == 7 && ltype == NORMLEV) {
|
||||
cnt = 0;
|
||||
do {
|
||||
rm = rnd_room();
|
||||
if (rooms[rm].r_flags & ISTREAS)
|
||||
continue;
|
||||
rnd_pos(&rooms[rm], &stairs);
|
||||
} until (winat(stairs.y, stairs.x) == FLOOR || cnt++ > 5000);
|
||||
addch(POST);
|
||||
}
|
||||
if (ltype != POSTLEV) { /* Add monsters that fell through */
|
||||
nitem = tlist;
|
||||
while (nitem != NULL) {
|
||||
item = nitem;
|
||||
nitem = next(item); /* because detach and attach mess up ptrs */
|
||||
tp = THINGPTR(item);
|
||||
cnt = 0;
|
||||
do {
|
||||
rm = rnd_room();
|
||||
rnd_pos(&rooms[rm], &tp->t_pos);
|
||||
} until (cnt++ > 5000 || winat(tp->t_pos.y, tp->t_pos.x) == FLOOR);
|
||||
mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, tp->t_type);
|
||||
tp->t_oldch = CCHAR( mvwinch(cw, tp->t_pos.y, tp->t_pos.x) );
|
||||
|
||||
/*
|
||||
* If it has a fire, mark it
|
||||
*/
|
||||
if (on(*tp, HASFIRE)) {
|
||||
register struct linked_list *fire_item;
|
||||
|
||||
fire_item = creat_item();
|
||||
ldata(fire_item) = (char *) tp;
|
||||
attach(rooms[rm].r_fires, fire_item);
|
||||
rooms[rm].r_flags |= HASFIRE;
|
||||
}
|
||||
turn_off(*tp,ISELSEWHERE);
|
||||
detach(tlist, item);
|
||||
attach(mlist, item);
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore any saved monsters */
|
||||
for (item = savmonst; item != NULL; item = nitem) {
|
||||
nitem = next(item);
|
||||
tp = THINGPTR(item);
|
||||
mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, tp->t_type);
|
||||
tp->t_oldch = CCHAR( mvwinch(cw, tp->t_pos.y, tp->t_pos.x) );
|
||||
|
||||
/*
|
||||
* If it has a fire, mark it
|
||||
*/
|
||||
if (on(*tp, HASFIRE)) {
|
||||
register struct linked_list *fire_item;
|
||||
|
||||
fire_item = creat_item();
|
||||
ldata(fire_item) = (char *) tp;
|
||||
attach(rooms[rm].r_fires, fire_item);
|
||||
rooms[rm].r_flags |= HASFIRE;
|
||||
}
|
||||
|
||||
detach(savmonst, item);
|
||||
attach(mlist, item);
|
||||
}
|
||||
|
||||
/* Restore any saved objects */
|
||||
for(item = savitems; item != NULL; item = nitem) {
|
||||
nitem = next(item);
|
||||
obj = OBJPTR(item);
|
||||
mvaddch(obj->o_pos.y, obj->o_pos.x, obj->o_type);
|
||||
detach(savitems, item);
|
||||
attach(lvl_obj, item);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Place the traps (except for trading post)
|
||||
*/
|
||||
ntraps = 0; /* No traps yet */
|
||||
if (levtype == NORMLEV) {
|
||||
if (rnd(10) < vlevel) {
|
||||
ntraps = rnd(vlevel/4)+1;
|
||||
if (ntraps > MAXTRAPS)
|
||||
ntraps = MAXTRAPS;
|
||||
i = ntraps;
|
||||
while (i--)
|
||||
{
|
||||
cnt = 0;
|
||||
do {
|
||||
rm = rnd_room();
|
||||
if (rooms[rm].r_flags & ISTREAS)
|
||||
continue;
|
||||
rnd_pos(&rooms[rm], &stairs);
|
||||
} until (winat(stairs.y, stairs.x) == FLOOR || cnt++ > 5000);
|
||||
|
||||
traps[i].tr_flags = 0;
|
||||
|
||||
/* If we are at the bottom, we can't set a trap door */
|
||||
if (level >= nfloors) ch = (char) rnd(7) + 1;
|
||||
else ch = (char) rnd(8);
|
||||
|
||||
switch((int) ch) {
|
||||
case 0: ch = TRAPDOOR;
|
||||
when 1: ch = BEARTRAP;
|
||||
when 2: ch = SLEEPTRAP;
|
||||
when 3: ch = ARROWTRAP;
|
||||
when 4: ch = TELTRAP;
|
||||
when 5: ch = DARTTRAP;
|
||||
when 6: ch = POOL;
|
||||
traps[i].tr_flags = ISFOUND;
|
||||
when 7: ch = MAZETRAP;
|
||||
}
|
||||
addch(ch);
|
||||
traps[i].tr_type = ch;
|
||||
traps[i].tr_show = FLOOR;
|
||||
traps[i].tr_pos = stairs;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fresh) { /* A whole new picture */
|
||||
/*
|
||||
* try to find a room for the hero. The objective here is to:
|
||||
*
|
||||
* --> don't put him in a treasure room
|
||||
* --> don't put him on an object
|
||||
* --> try not to put him next to the stairs
|
||||
*/
|
||||
cnt = 5000;
|
||||
do {
|
||||
rm = rnd_room();
|
||||
if (rooms[rm].r_flags & ISTREAS)
|
||||
continue;
|
||||
rnd_pos(&rooms[rm], &hero);
|
||||
} until( cnt-- == 0 ||
|
||||
(winat(hero.y, hero.x) == FLOOR &&
|
||||
DISTANCE(hero.y, hero.x, stairs.y, stairs.x) > cnt/10));
|
||||
}
|
||||
else { /* We're extending into an adjacent outside plane */
|
||||
rm = 0;
|
||||
if (vert) {
|
||||
if (hero.y == 1) hero.y = lines - 3 - TERRASAVE; /* Top to bottom */
|
||||
else hero.y = TERRASAVE + 1; /* Bottom to top */
|
||||
}
|
||||
else {
|
||||
if (hero.x == 0) hero.x = cols - 1 - TERRASAVE; /* Right to left */
|
||||
else hero.x = TERRASAVE; /* Left to right */
|
||||
}
|
||||
}
|
||||
oldrp = &rooms[rm]; /* Set the current room */
|
||||
player.t_oldpos = player.t_pos; /* Set the current position */
|
||||
if (ISWEARING(R_AGGR) ||
|
||||
(cur_misc[WEAR_JEWEL] != NULL &&
|
||||
cur_misc[WEAR_JEWEL]->o_which == MM_JEWEL))
|
||||
aggravate(TRUE, TRUE);
|
||||
|
||||
/*
|
||||
* If player is moving up or above his deepest point, wake up any
|
||||
* non-uniques
|
||||
*/
|
||||
else if (level < cur_max) aggravate(FALSE, FALSE);
|
||||
|
||||
light(&hero);
|
||||
wmove(cw, hero.y, hero.x);
|
||||
waddch(cw, PLAYER);
|
||||
|
||||
if (level > cur_max)
|
||||
cur_max = level;
|
||||
|
||||
status(TRUE);
|
||||
|
||||
/* Do we sense any food on this level? */
|
||||
if (cur_relic[SURTUR_RING]) quaff(P_FFIND, NULL, NULL, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pick a room that is really there
|
||||
*/
|
||||
|
||||
rnd_room()
|
||||
{
|
||||
register int rm;
|
||||
|
||||
if (levtype != NORMLEV)
|
||||
rm = 0;
|
||||
else do
|
||||
{
|
||||
rm = rnd(MAXROOMS);
|
||||
} while (rooms[rm].r_flags & ISGONE);
|
||||
return rm;
|
||||
}
|
||||
|
||||
/*
|
||||
* put_things:
|
||||
* put potions and scrolls on this level
|
||||
*/
|
||||
|
||||
put_things(ltype)
|
||||
LEVTYPE ltype; /* designates type of level to create */
|
||||
{
|
||||
register int i, rm, cnt;
|
||||
register struct object *cur;
|
||||
register struct linked_list *item, *nextitem, *exitptr;
|
||||
int length, width;
|
||||
coord tp, *exit;
|
||||
|
||||
/*
|
||||
* The only way to get new stuff is to go down into the dungeon.
|
||||
*/
|
||||
if (level <= cur_max)
|
||||
return;
|
||||
|
||||
/*
|
||||
* There is a chance that there is a treasure room on this level
|
||||
*/
|
||||
if (ltype != MAZELEV && rnd(HARDER) < level - 10) {
|
||||
register j;
|
||||
register struct room *rp;
|
||||
|
||||
/* Count the number of free spaces */
|
||||
i = 0; /* 0 tries */
|
||||
do {
|
||||
rp = &rooms[rnd_room()];
|
||||
width = rp->r_max.y - 2;
|
||||
length = rp->r_max.x - 2;
|
||||
} until ((width*length >= MAXTREAS) || (i++ > MAXROOMS*4));
|
||||
|
||||
/* Mark the room as a treasure room */
|
||||
rp->r_flags |= ISTREAS;
|
||||
|
||||
/* Make all the doors secret doors */
|
||||
for (exitptr = rp->r_exit; exitptr; exitptr = next(exitptr)) {
|
||||
exit = DOORPTR(exitptr);
|
||||
move(exit->y, exit->x);
|
||||
addch(SECRETDOOR);
|
||||
}
|
||||
|
||||
/*
|
||||
* check to see if there are any monsters in room already
|
||||
*/
|
||||
for (item = mlist; item != NULL; item = nextitem) {
|
||||
register struct thing *tp;
|
||||
|
||||
tp = THINGPTR(item);
|
||||
nextitem = next(item);
|
||||
if (rp == roomin(&tp->t_pos)) {
|
||||
/*
|
||||
* Don't let nice creatures be generated in a treasure
|
||||
* room.
|
||||
*/
|
||||
if ((player.t_ctype==C_PALADIN || player.t_ctype==C_RANGER) &&
|
||||
off(*tp, ISMEAN)) {
|
||||
int index;
|
||||
|
||||
if (on(*tp, ISUNIQUE)) index = tp->t_index;
|
||||
else index = -1;
|
||||
|
||||
/* Get rid of the monster */
|
||||
killed(item, FALSE, FALSE, FALSE);
|
||||
|
||||
/* Restore uniques back in the table */
|
||||
if (index != -1) monsters[index].m_normal = TRUE;
|
||||
|
||||
continue;
|
||||
}
|
||||
turn_on(*tp, ISMEAN);
|
||||
turn_on(*tp, ISGUARDIAN);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Put in the monsters and treasures */
|
||||
for (j=1; j<rp->r_max.y-1; j++)
|
||||
for (i=1; i<rp->r_max.x-1; i++) {
|
||||
coord trp;
|
||||
|
||||
trp.y = rp->r_pos.y+j;
|
||||
trp.x = rp->r_pos.x+i;
|
||||
|
||||
/* Monsters */
|
||||
if ((rnd(100) < (MAXTREAS*100)/(width*length)) &&
|
||||
(mvwinch(mw, rp->r_pos.y+j, rp->r_pos.x+i) == ' ')) {
|
||||
register struct thing *tp;
|
||||
|
||||
/*
|
||||
* Put it there and leave it asleep. Wake the monsters
|
||||
* when the player enters the room. Hopefully, all bases
|
||||
* are covered as far as the ways to get in. This way
|
||||
* cpu time is not wasted on the awake monsters that
|
||||
* can't get to the player anyway.
|
||||
* try not to put any UNIQUEs in a treasure room.
|
||||
* note that they may have put put in already by the
|
||||
* non-treasure room code.
|
||||
* also, try not to put ISMEAN monsters in a treasure
|
||||
* room as these are supposed to be non-hostile until
|
||||
* attacked. It also makes life simpler for the ranger
|
||||
* and paladin.
|
||||
*/
|
||||
while (TRUE) {
|
||||
item = new_item(sizeof *tp); /* Make a monster */
|
||||
tp = THINGPTR(item);
|
||||
new_monster(item,randmonster(FALSE, TRUE),&trp,TRUE);
|
||||
if (on(*tp, HASFIRE)) {
|
||||
register struct linked_list *fire_item;
|
||||
|
||||
fire_item = creat_item();
|
||||
ldata(fire_item) = (char *) tp;
|
||||
attach(rp->r_fires, fire_item);
|
||||
rp->r_flags |= HASFIRE;
|
||||
}
|
||||
/*
|
||||
* only picky for these classes
|
||||
*/
|
||||
if (player.t_ctype!=C_RANGER&&player.t_ctype!=C_PALADIN)
|
||||
break;
|
||||
if (on(*tp, ISMEAN))
|
||||
break;
|
||||
killed (item, FALSE, FALSE, FALSE);
|
||||
}
|
||||
if (on(*tp, ISUNIQUE)) { /* just in case */
|
||||
carry_obj(tp, monsters[tp->t_index].m_carry);
|
||||
tp->t_no_move = movement(tp);
|
||||
}
|
||||
turn_on(*tp, ISGUARDIAN);
|
||||
|
||||
}
|
||||
|
||||
/* Treasures */
|
||||
if ((rnd(100) < (MAXTREAS*100)/(width*length)) &&
|
||||
(mvinch(rp->r_pos.y+j, rp->r_pos.x+i) == FLOOR)) {
|
||||
item = new_thing(ALL, TRUE);
|
||||
attach(lvl_obj, item);
|
||||
cur = OBJPTR(item);
|
||||
|
||||
mvaddch(trp.y, trp.x, cur->o_type);
|
||||
cur->o_pos = trp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Do MAXOBJ attempts to put things on a level
|
||||
* put more things in a maze to entice player to navigate them
|
||||
*/
|
||||
for (i = 0; i < MAXOBJ; i++)
|
||||
if (ltype == MAZELEV || rnd(100) < 45) {
|
||||
/*
|
||||
* Pick a new object and link it in the list
|
||||
*/
|
||||
item = new_thing(ALL, TRUE);
|
||||
attach(lvl_obj, item);
|
||||
cur = OBJPTR(item);
|
||||
/*
|
||||
* Put it somewhere
|
||||
*/
|
||||
cnt = 0;
|
||||
do {
|
||||
rm = rnd_room();
|
||||
rnd_pos(&rooms[rm], &tp);
|
||||
} until (winat(tp.y, tp.x) == FLOOR || cnt++ > 500);
|
||||
mvaddch(tp.y, tp.x, cur->o_type);
|
||||
cur->o_pos = tp;
|
||||
}
|
||||
}
|
||||
464
arogue7/options.c
Normal file
464
arogue7/options.c
Normal file
|
|
@ -0,0 +1,464 @@
|
|||
/*
|
||||
* options.c - This file has all the code for the option command
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file has all the code for the option command.
|
||||
* I would rather this command were not necessary, but
|
||||
* it is the only way to keep the wolves off of my back.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "curses.h"
|
||||
#include <ctype.h>
|
||||
#include "rogue.h"
|
||||
|
||||
#define NUM_OPTS (sizeof optlist / sizeof (OPTION))
|
||||
|
||||
|
||||
/*
|
||||
* description of an option and what to do with it
|
||||
*/
|
||||
struct optstruct {
|
||||
char *o_name; /* option name */
|
||||
char *o_prompt; /* prompt for interactive entry */
|
||||
int *o_opt; /* pointer to thing to set */
|
||||
int (*o_putfunc)(); /* function to print value */
|
||||
int (*o_getfunc)(); /* function to get value interactively */
|
||||
};
|
||||
|
||||
typedef struct optstruct OPTION;
|
||||
|
||||
int put_bool(),
|
||||
get_bool(),
|
||||
put_str(),
|
||||
get_str(),
|
||||
put_abil(),
|
||||
get_abil(),
|
||||
get_quest(),
|
||||
put_quest();
|
||||
|
||||
OPTION optlist[] = {
|
||||
{"terse", "Terse output: ",
|
||||
(int *) &terse, put_bool, get_bool },
|
||||
{"flush", "Flush typeahead during battle: ",
|
||||
(int *) &fight_flush, put_bool, get_bool },
|
||||
{"jump", "Show position only at end of run: ",
|
||||
(int *) &jump, put_bool, get_bool },
|
||||
{"step", "Do inventories one line at a time: ",
|
||||
(int *) &slow_invent, put_bool, get_bool },
|
||||
{"askme", "Ask me about unidentified things: ",
|
||||
(int *) &askme, put_bool, get_bool },
|
||||
{"pickup", "Pick things up automatically: ",
|
||||
(int *) &auto_pickup, put_bool, get_bool },
|
||||
{"overlay", "Overlay menu: ",
|
||||
(int *) &menu_overlay, put_bool, get_bool },
|
||||
{"name", "Name: ",
|
||||
(int *) whoami, put_str, get_str },
|
||||
{"file", "Save file: ",
|
||||
(int *) file_name, put_str, get_str },
|
||||
{"score", "Score file: ",
|
||||
(int *) score_file, put_str, get_str },
|
||||
{"class", "Character class: ",
|
||||
(int *)&char_type, put_abil, get_abil },
|
||||
{"quest", "Quest item: ",
|
||||
(int *) &quest_item, put_quest, get_quest }
|
||||
};
|
||||
|
||||
/*
|
||||
* The ability field is read-only
|
||||
*/
|
||||
get_abil(abil, win)
|
||||
int *abil;
|
||||
WINDOW *win;
|
||||
{
|
||||
register int oy, ox;
|
||||
|
||||
getyx(win, oy, ox);
|
||||
put_abil(abil, win);
|
||||
get_ro(win, oy, ox);
|
||||
}
|
||||
|
||||
/*
|
||||
* The quest field is read-only
|
||||
*/
|
||||
get_quest(quest, win)
|
||||
int *quest;
|
||||
WINDOW *win;
|
||||
{
|
||||
register int oy, ox;
|
||||
|
||||
getyx(win, oy, ox);
|
||||
waddstr(win, rel_magic[*quest].mi_name);
|
||||
get_ro(win, oy, ox);
|
||||
}
|
||||
|
||||
/*
|
||||
* get_ro:
|
||||
* "Get" a read-only value.
|
||||
*/
|
||||
|
||||
get_ro(win, oy, ox)
|
||||
WINDOW *win;
|
||||
register int oy, ox;
|
||||
{
|
||||
register int ny, nx;
|
||||
register bool op_bad;
|
||||
|
||||
op_bad = TRUE;
|
||||
getyx(win, ny, nx);
|
||||
while(op_bad)
|
||||
{
|
||||
wmove(win, oy, ox);
|
||||
draw(win);
|
||||
switch (wgetch(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;
|
||||
}
|
||||
|
||||
/*
|
||||
* allow changing a boolean option and print it out
|
||||
*/
|
||||
|
||||
get_bool(bp, win)
|
||||
bool *bp;
|
||||
WINDOW *win;
|
||||
{
|
||||
register int oy, ox;
|
||||
register bool op_bad;
|
||||
|
||||
op_bad = TRUE;
|
||||
getyx(win, oy, ox);
|
||||
waddstr(win, *bp ? "True" : "False");
|
||||
while(op_bad)
|
||||
{
|
||||
wmove(win, oy, ox);
|
||||
draw(win);
|
||||
switch (wgetch(win))
|
||||
{
|
||||
case 't':
|
||||
case 'T':
|
||||
*bp = TRUE;
|
||||
op_bad = FALSE;
|
||||
break;
|
||||
case 'f':
|
||||
case 'F':
|
||||
*bp = 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, *bp ? "True" : "False");
|
||||
waddch(win, '\n');
|
||||
return NORM;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* set a string option
|
||||
*/
|
||||
get_str(opt, win)
|
||||
register char *opt;
|
||||
WINDOW *win;
|
||||
{
|
||||
register char *sp;
|
||||
register int c, oy, ox;
|
||||
char buf[LINELEN];
|
||||
|
||||
draw(win);
|
||||
getyx(win, oy, ox);
|
||||
/*
|
||||
* loop reading in the string, and put it in a temporary buffer
|
||||
*/
|
||||
for (sp = buf;
|
||||
(c = wgetch(win)) != '\n' &&
|
||||
c != '\r' &&
|
||||
c != '\033' &&
|
||||
c != '\007' &&
|
||||
sp < &buf[LINELEN-1];
|
||||
wclrtoeol(win), draw(win))
|
||||
{
|
||||
if (c == -1)
|
||||
continue;
|
||||
else if (c == md_erasechar()) /* process erase character */
|
||||
{
|
||||
if (sp > buf)
|
||||
{
|
||||
register int i;
|
||||
|
||||
sp--;
|
||||
for (i = strlen(unctrl(*sp)); i; i--)
|
||||
waddch(win, '\b');
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (c == md_killchar()) /* process kill character */
|
||||
{
|
||||
sp = buf;
|
||||
wmove(win, oy, ox);
|
||||
continue;
|
||||
}
|
||||
else if (sp == buf)
|
||||
if (c == '-' && win == hw) /* To move back a line in hw */
|
||||
break;
|
||||
else if (c == '~')
|
||||
{
|
||||
strcpy(buf, home);
|
||||
waddstr(win, home);
|
||||
sp += strlen(home);
|
||||
continue;
|
||||
}
|
||||
*sp++ = c;
|
||||
waddstr(win, unctrl(c));
|
||||
}
|
||||
*sp = '\0';
|
||||
if (sp > buf) /* only change option if something has been typed */
|
||||
strucpy(opt, buf, strlen(buf));
|
||||
wmove(win, oy, ox);
|
||||
waddstr(win, opt);
|
||||
waddch(win, '\n');
|
||||
draw(win);
|
||||
if (win == msgw)
|
||||
mpos += (int)(sp - buf);
|
||||
if (c == '-')
|
||||
return MINUS;
|
||||
else if (c == '\033' || c == '\007')
|
||||
return QUIT;
|
||||
else
|
||||
return NORM;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* print and then set options from the terminal
|
||||
*/
|
||||
option()
|
||||
{
|
||||
register OPTION *op;
|
||||
register int retval;
|
||||
|
||||
wclear(hw);
|
||||
touchwin(hw);
|
||||
/*
|
||||
* Display current values of options
|
||||
*/
|
||||
for (op = optlist; op <= &optlist[NUM_OPTS-1]; 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-1]; op++)
|
||||
{
|
||||
waddstr(hw, op->o_prompt);
|
||||
if ((retval = (*op->o_getfunc)(op->o_opt, hw)))
|
||||
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);
|
||||
draw(hw);
|
||||
wait_for(' ');
|
||||
clearok(cw, TRUE);
|
||||
touchwin(cw);
|
||||
after = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
parse_opts(str)
|
||||
register char *str;
|
||||
{
|
||||
register char *sp;
|
||||
register OPTION *op;
|
||||
register int len;
|
||||
|
||||
while (*str)
|
||||
{
|
||||
/*
|
||||
* Get option name
|
||||
*/
|
||||
for (sp = str; isalpha(*sp); sp++)
|
||||
continue;
|
||||
len = (int)(sp - str);
|
||||
/*
|
||||
* Look it up and deal with it
|
||||
*/
|
||||
for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++)
|
||||
if (EQSTR(str, op->o_name, len))
|
||||
{
|
||||
if (op->o_putfunc == put_bool) /* if option is a boolean */
|
||||
*(bool *)op->o_opt = TRUE;
|
||||
else /* string option */
|
||||
{
|
||||
register char *start;
|
||||
char value[LINELEN];
|
||||
|
||||
/*
|
||||
* Skip to start of string value
|
||||
*/
|
||||
for (str = sp + 1; *str == '='; str++)
|
||||
continue;
|
||||
if (*str == '~')
|
||||
{
|
||||
strcpy((char *) value, home);
|
||||
start = (char *) value + strlen(home);
|
||||
while (*++str == '/')
|
||||
continue;
|
||||
}
|
||||
else
|
||||
start = (char *) value;
|
||||
/*
|
||||
* Skip to end of string value
|
||||
*/
|
||||
for (sp = str + 1; *sp && *sp != ','; sp++)
|
||||
continue;
|
||||
strucpy(start, str, sp - str);
|
||||
|
||||
/* Put the value into the option field */
|
||||
if (op->o_putfunc != put_abil)
|
||||
strcpy((char *)op->o_opt, (char *)value);
|
||||
|
||||
else if (*op->o_opt == -1) { /* Only init ability once */
|
||||
register int len = strlen(value);
|
||||
register int i;
|
||||
|
||||
if (isupper(value[0])) value[0] = tolower(value[0]);
|
||||
for (i=0; i<NUM_CHARTYPES-1; i++) {
|
||||
if (EQSTR(value, char_class[i].name, len)) {
|
||||
*op->o_opt = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* check for "noname" for booleans
|
||||
*/
|
||||
else if (op->o_putfunc == put_bool
|
||||
&& EQSTR(str, "no", 2) && EQSTR(str + 2, op->o_name, len - 2))
|
||||
{
|
||||
*(bool *)op->o_opt = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* skip to start of next option name
|
||||
*/
|
||||
while (*sp && !isalpha(*sp))
|
||||
sp++;
|
||||
str = sp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* print the character type
|
||||
*/
|
||||
put_abil(ability, win)
|
||||
int *ability;
|
||||
WINDOW *win;
|
||||
{
|
||||
waddstr(win, char_class[*ability].name);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* print out the quest
|
||||
*/
|
||||
|
||||
put_quest(quest, win)
|
||||
int *quest;
|
||||
WINDOW *win;
|
||||
{
|
||||
waddstr(win, rel_magic[*quest].mi_name);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* put out a boolean
|
||||
*/
|
||||
put_bool(b, win)
|
||||
bool *b;
|
||||
WINDOW *win;
|
||||
{
|
||||
waddstr(win, *b ? "True" : "False");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* put out a string
|
||||
*/
|
||||
put_str(str, win)
|
||||
char *str;
|
||||
WINDOW *win;
|
||||
{
|
||||
waddstr(win, str);
|
||||
}
|
||||
213
arogue7/outside.c
Normal file
213
arogue7/outside.c
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* outside.c - functions for dealing with the "outside" level
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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 "curses.h"
|
||||
#include "rogue.h"
|
||||
|
||||
extern char rnd_terrain(), get_terrain();
|
||||
|
||||
/*
|
||||
* init_terrain:
|
||||
* Get the single "outside room" set up correctly
|
||||
*/
|
||||
|
||||
void
|
||||
init_terrain()
|
||||
{
|
||||
register struct room *rp;
|
||||
|
||||
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) {
|
||||
rp->r_flags = ISGONE; /* kill all rooms */
|
||||
rp->r_fires = NULL; /* no fires */
|
||||
}
|
||||
rp = &rooms[0]; /* point to only room */
|
||||
rp->r_flags = ISDARK; /* outside is always dark */
|
||||
rp->r_pos.x = 0; /* room fills whole screen */
|
||||
rp->r_pos.y = 1;
|
||||
rp->r_max.x = cols;
|
||||
rp->r_max.y = lines - 3;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
do_terrain(basey, basex, deltay, deltax, fresh)
|
||||
int basey, basex, deltay, deltax;
|
||||
bool fresh;
|
||||
{
|
||||
register cury, curx; /* Current y and x positions */
|
||||
|
||||
/* Lay out the boundary */
|
||||
for (cury=1; cury<lines-2; cury++) { /* Vertical "walls" */
|
||||
mvaddch(cury, 0, '|');
|
||||
mvaddch(cury, cols-1, '|');
|
||||
}
|
||||
for (curx=0; curx<cols; curx++) { /* Horizontal "walls" */
|
||||
mvaddch(1, curx, '-');
|
||||
mvaddch(lines-3, curx, '-');
|
||||
}
|
||||
|
||||
/* If we are not continuing, let's start out with a line of terrain */
|
||||
if (fresh) {
|
||||
char ch; /* Next char to add */
|
||||
|
||||
/* Move to the starting point (should be (1, 0)) */
|
||||
move(basey, basex);
|
||||
curx = basex;
|
||||
|
||||
/* Start with some random terrain */
|
||||
if (basex == 0) {
|
||||
ch = rnd_terrain();
|
||||
addch(ch);
|
||||
}
|
||||
else ch = CCHAR( mvinch(basey, basex) );
|
||||
|
||||
curx += deltax;
|
||||
|
||||
/* Fill in the rest of the line */
|
||||
while (curx > 0 && curx < cols-1) {
|
||||
/* Put in the next piece */
|
||||
ch = get_terrain(ch, '\0', '\0', '\0');
|
||||
mvaddch(basey, curx, ch);
|
||||
curx += deltax;
|
||||
}
|
||||
|
||||
basey++; /* Advance to next line */
|
||||
}
|
||||
|
||||
/* Fill in the rest of the lines */
|
||||
cury = basey;
|
||||
while (cury > 1 && cury < lines - 3) {
|
||||
curx = basex;
|
||||
while (curx > 0 && curx < cols-1) {
|
||||
register char left, top_left, top, top_right;
|
||||
register int left_pos, top_pos;
|
||||
|
||||
/* Get the surrounding terrain */
|
||||
left_pos = curx - deltax;
|
||||
top_pos = cury - deltay;
|
||||
|
||||
left = CCHAR( mvinch(cury, left_pos) );
|
||||
top_left = CCHAR( mvinch(top_pos, left_pos) );
|
||||
top = CCHAR( mvinch(top_pos, curx) );
|
||||
top_right = CCHAR( mvinch(top_pos, curx + deltax) );
|
||||
|
||||
/* Put the piece of terrain on the map */
|
||||
mvaddch(cury, curx, get_terrain(left, top_left, top, top_right));
|
||||
|
||||
/* Get the next x coordinate */
|
||||
curx += deltax;
|
||||
}
|
||||
|
||||
/* Get the next y coordinate */
|
||||
cury += deltay;
|
||||
}
|
||||
genmonsters(5, (bool) 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* do_paths:
|
||||
* draw at least a single path-way through the terrain
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* rnd_terrain:
|
||||
* return a weighted, random type of outside terrain
|
||||
*/
|
||||
|
||||
char
|
||||
rnd_terrain()
|
||||
{
|
||||
int chance = rnd(100);
|
||||
|
||||
/* Forest is most likely */
|
||||
if (chance < 60) return(FOREST);
|
||||
|
||||
/* Next comes meadow */
|
||||
if (chance < 90) return(FLOOR);
|
||||
|
||||
/* Then comes lakes */
|
||||
if (chance < 97) return(POOL);
|
||||
|
||||
/* Finally, mountains */
|
||||
return(WALL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* get_terrain:
|
||||
* return a terrain weighted by what is surrounding
|
||||
*/
|
||||
|
||||
char
|
||||
get_terrain(one, two, three, four)
|
||||
char one, two, three, four;
|
||||
{
|
||||
register int i;
|
||||
int forest = 0, mountain = 0, lake = 0, meadow = 0, total = 0;
|
||||
char surrounding[4];
|
||||
|
||||
surrounding[0] = one;
|
||||
surrounding[1] = two;
|
||||
surrounding[2] = three;
|
||||
surrounding[3] = four;
|
||||
|
||||
for (i=0; i<4; i++)
|
||||
switch (surrounding[i]) {
|
||||
case FOREST:
|
||||
forest++;
|
||||
total++;
|
||||
|
||||
when WALL:
|
||||
mountain++;
|
||||
total++;
|
||||
|
||||
when POOL:
|
||||
lake++;
|
||||
total++;
|
||||
|
||||
when FLOOR:
|
||||
meadow++;
|
||||
total++;
|
||||
}
|
||||
|
||||
/* Should we continue mountain? */
|
||||
if (rnd(total+1) < mountain) return(WALL);
|
||||
|
||||
/* Should we continue lakes? */
|
||||
if (rnd(total+1) < lake) return(POOL);
|
||||
|
||||
/* Should we continue meadow? */
|
||||
if (rnd(total+1) < meadow) return(FLOOR);
|
||||
|
||||
/* Should we continue forest? */
|
||||
if (rnd(total+2) < forest) return(FOREST);
|
||||
|
||||
/* Return something random */
|
||||
return(rnd_terrain());
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* lake_check:
|
||||
* Determine if the player would drown
|
||||
*/
|
||||
|
||||
void
|
||||
lake_check(place)
|
||||
coord *place;
|
||||
{
|
||||
}
|
||||
1548
arogue7/pack.c
Normal file
1548
arogue7/pack.c
Normal file
File diff suppressed because it is too large
Load diff
366
arogue7/passages.c
Normal file
366
arogue7/passages.c
Normal file
|
|
@ -0,0 +1,366 @@
|
|||
/*
|
||||
* passages.c - Draw the connecting passages
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Draw the connecting passages
|
||||
*
|
||||
* @(#)passages.c 3.4 (Berkeley) 6/15/81
|
||||
*/
|
||||
|
||||
#include "curses.h"
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* do_passages:
|
||||
* Draw all the passages on a level.
|
||||
*/
|
||||
|
||||
do_passages()
|
||||
{
|
||||
register struct rdes *r1, *r2;
|
||||
register int i, j;
|
||||
register int roomcount;
|
||||
static struct rdes
|
||||
{
|
||||
bool conn[MAXROOMS]; /* possible to connect to room i? */
|
||||
bool isconn[MAXROOMS]; /* connection been made to room i? */
|
||||
bool ingraph; /* this room in graph already? */
|
||||
} 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-1]; 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
|
||||
{
|
||||
/*
|
||||
* find a room to connect with
|
||||
*/
|
||||
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)];
|
||||
until (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.
|
||||
*/
|
||||
|
||||
conn(r1, r2)
|
||||
int r1, r2;
|
||||
{
|
||||
register struct room *rpf, *rpt;
|
||||
register char rmt;
|
||||
register int distance, max_diag, offset, i;
|
||||
register int rm;
|
||||
int turns[3], turn_dist[3];
|
||||
register char direc;
|
||||
coord delta, curr, turn_delta, spos, epos;
|
||||
|
||||
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 */
|
||||
delta.x = 0; /* direction of move */
|
||||
delta.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);
|
||||
offset = abs(spos.x - epos.x); /* how far to turn */
|
||||
}
|
||||
else if (direc == 'r') /* setup for moving right */
|
||||
{
|
||||
rmt = rm + 1;
|
||||
rpt = &rooms[rmt];
|
||||
delta.x = 1;
|
||||
delta.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;
|
||||
offset = abs(spos.y - epos.y);
|
||||
}
|
||||
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('#');
|
||||
}
|
||||
|
||||
/* How far can we move diagonally? */
|
||||
max_diag = min(distance, offset);
|
||||
|
||||
/*
|
||||
* Decide how many turns we will have.
|
||||
*/
|
||||
for (i=0; i<3; i++) turn_dist[i] = 0; /* Init distances */
|
||||
if (max_diag > 0) {
|
||||
int nturns;
|
||||
|
||||
for (i=0, nturns=0; i<3; i++) {
|
||||
if (rnd(3 - i + nturns) == 0) {
|
||||
nturns++;
|
||||
turns[i] = 0;
|
||||
}
|
||||
else turns[i] = -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Just use a straight line (middle turn) */
|
||||
turns[0] = turns[2] = -1;
|
||||
turns[1] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now decide how long each turn will be (for those selected above).
|
||||
*/
|
||||
while (max_diag > 0) {
|
||||
for (i=0; i<3; i++) {
|
||||
if (turns[i] >= 0 && max_diag > 0 && rnd(2) == 0) {
|
||||
turn_dist[i]++;
|
||||
max_diag--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have extra offset space, add it to the straight turn.
|
||||
*/
|
||||
if (offset > distance) turn_dist[1] += offset - distance;
|
||||
|
||||
/*
|
||||
* Decide where we want to make our turns.
|
||||
* First calculate the offsets, then use those offsets to calculate
|
||||
* the exact position relative to "distance."
|
||||
*/
|
||||
turns[0] = rnd(distance - turn_dist[0] - turn_dist[2]);
|
||||
turns[2] = rnd(distance - turn_dist[0] - turn_dist[2] - turns[0]);
|
||||
turns[1] = rnd(distance - turn_dist[0] - turn_dist[2] -
|
||||
turns[0] - turns[2]);
|
||||
|
||||
turns[0] = distance - turns[0];
|
||||
turns[1] = turns[0] - turn_dist[0] - turns[1];
|
||||
turns[2] = turns[1] - turns[2];
|
||||
|
||||
/*
|
||||
* Get ready to move...
|
||||
*/
|
||||
curr.x = spos.x;
|
||||
curr.y = spos.y;
|
||||
while (distance > 0) {
|
||||
/*
|
||||
* Move to next row/column
|
||||
*/
|
||||
curr.x += delta.x;
|
||||
curr.y += delta.y;
|
||||
|
||||
/*
|
||||
* Check if we are at a turn place; if so make a turn
|
||||
*/
|
||||
for (i=0; i<3; i++) {
|
||||
if (distance == turns[i] && turn_dist[i] > 0) {
|
||||
/*
|
||||
* If this is the start of a straight path,
|
||||
* we might put in a right-angle turn (33% chance).
|
||||
*/
|
||||
if (i == 1 && rnd(3) == 0) {
|
||||
cmov(curr);
|
||||
addch(PASSAGE);
|
||||
}
|
||||
|
||||
/* Now dig the turn */
|
||||
while (turn_dist[i]--) {
|
||||
curr.x += turn_delta.x;
|
||||
curr.y += turn_delta.y;
|
||||
cmov(curr);
|
||||
addch(PASSAGE);
|
||||
if (i != 1) { /* A diagonal */
|
||||
if (--distance > 0) {
|
||||
curr.x += delta.x;
|
||||
curr.y += delta.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (distance > 0) {
|
||||
/*
|
||||
* Dig the passage.
|
||||
*/
|
||||
cmov(curr);
|
||||
addch(PASSAGE);
|
||||
distance--;
|
||||
}
|
||||
}
|
||||
curr.x += delta.x;
|
||||
curr.y += delta.y;
|
||||
if (!ce(curr, epos))
|
||||
msg("Warning, connectivity problem (%d, %d) to (%d, %d).",
|
||||
curr.y, curr.x, epos.y, epos.x);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a door or possibly a secret door
|
||||
* also enters the door in the exits array of the room.
|
||||
*/
|
||||
|
||||
door(rm, cp)
|
||||
register struct room *rm;
|
||||
register coord *cp;
|
||||
{
|
||||
struct linked_list *newroom;
|
||||
coord *exit;
|
||||
|
||||
cmov(*cp);
|
||||
addch((rnd(10) < level - 1 && rnd(100) < 20) ? SECRETDOOR : DOOR);
|
||||
|
||||
/* Insert the new room into the linked list of rooms */
|
||||
newroom = new_item(sizeof(coord));
|
||||
exit = DOORPTR(newroom);
|
||||
*exit = *cp;
|
||||
attach(rm->r_exit, newroom);
|
||||
}
|
||||
812
arogue7/player.c
Normal file
812
arogue7/player.c
Normal file
|
|
@ -0,0 +1,812 @@
|
|||
/*
|
||||
* player.c - This file contains functions for dealing with special player
|
||||
* abilities
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains functions for dealing with special player abilities
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include "curses.h"
|
||||
#include "rogue.h"
|
||||
#ifdef PC7300
|
||||
#include "menu.h"
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* affect:
|
||||
* cleric affecting undead
|
||||
*/
|
||||
|
||||
affect()
|
||||
{
|
||||
register struct linked_list *item;
|
||||
register struct thing *tp;
|
||||
register char *mname;
|
||||
bool see;
|
||||
coord new_pos;
|
||||
int lvl;
|
||||
|
||||
if (!(player.t_ctype == C_CLERIC ||
|
||||
(player.t_ctype == C_PALADIN && pstats.s_lvl > 4) ||
|
||||
cur_relic[HEIL_ANKH] != 0)) {
|
||||
msg("You cannot affect undead.");
|
||||
return;
|
||||
}
|
||||
|
||||
new_pos.y = hero.y + player.t_newpos.y;
|
||||
new_pos.x = hero.x + player.t_newpos.x;
|
||||
|
||||
if (cansee(new_pos.y, new_pos.x)) see = TRUE;
|
||||
else see = FALSE;
|
||||
|
||||
/* 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 = monster_name(tp);
|
||||
|
||||
if (on(player, ISINVIS) && off(*tp, CANSEE)) {
|
||||
msg("%s%s cannot see you", see ? "The " : "It",
|
||||
see ? mname : "");
|
||||
return;
|
||||
}
|
||||
|
||||
if (off(*tp, TURNABLE) || on(*tp, WASTURNED))
|
||||
goto annoy;
|
||||
turn_off(*tp, TURNABLE);
|
||||
|
||||
lvl = pstats.s_lvl;
|
||||
if (player.t_ctype == C_PALADIN && cur_relic[HEIL_ANKH] == 0) {
|
||||
lvl -= 4;
|
||||
}
|
||||
/* Can cleric kill it? */
|
||||
if (lvl >= 3 * tp->t_stats.s_lvl) {
|
||||
unsigned long test; /* For overflow check */
|
||||
|
||||
msg("You have destroyed %s%s.", see ? "the " : "it", see ? mname : "");
|
||||
test = pstats.s_exp + tp->t_stats.s_exp;
|
||||
|
||||
/* Be sure there is no overflow before increasing experience */
|
||||
if (test > pstats.s_exp) pstats.s_exp = test;
|
||||
killed(item, FALSE, TRUE, TRUE);
|
||||
check_level();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Can cleric turn it? */
|
||||
if (rnd(100) + 1 >
|
||||
(100 * ((2 * tp->t_stats.s_lvl) - lvl)) / lvl) {
|
||||
unsigned long test; /* Overflow test */
|
||||
|
||||
/* Make the monster flee */
|
||||
turn_on(*tp, WASTURNED); /* No more fleeing after this */
|
||||
turn_on(*tp, ISFLEE);
|
||||
runto(tp, &hero);
|
||||
|
||||
/* Disrupt it */
|
||||
dsrpt_monster(tp, TRUE, TRUE);
|
||||
|
||||
/* Let player know */
|
||||
msg("You have turned %s%s.", see ? "the " : "it", see ? mname : "");
|
||||
|
||||
/* get points for turning monster -- but check overflow first */
|
||||
test = pstats.s_exp + tp->t_stats.s_exp/2;
|
||||
if (test > pstats.s_exp) pstats.s_exp = test;
|
||||
check_level();
|
||||
|
||||
/* If monster was suffocating, stop it */
|
||||
if (on(*tp, DIDSUFFOCATE)) {
|
||||
turn_off(*tp, DIDSUFFOCATE);
|
||||
extinguish(suffocate);
|
||||
}
|
||||
|
||||
/* If monster held us, stop it */
|
||||
if (on(*tp, DIDHOLD) && (--hold_count == 0))
|
||||
turn_off(player, ISHELD);
|
||||
turn_off(*tp, DIDHOLD);
|
||||
|
||||
/* It is okay to turn tail */
|
||||
tp->t_oldpos = tp->t_pos;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Otherwise -- no go */
|
||||
annoy:
|
||||
if (see && tp->t_stats.s_intel > 16)
|
||||
msg("%s laughs at you...", prname(mname, TRUE));
|
||||
else
|
||||
msg("You do not affect %s%s.", see ? "the " : "it", see ? mname : "");
|
||||
|
||||
/* Annoy monster */
|
||||
if (off(*tp, ISFLEE)) runto(tp, &hero);
|
||||
}
|
||||
|
||||
/*
|
||||
* the magic user is going to try and cast a spell
|
||||
*/
|
||||
cast()
|
||||
{
|
||||
int spell_ability,
|
||||
which_spell,
|
||||
num_spells;
|
||||
|
||||
if (player.t_ctype != C_MAGICIAN && player.t_ctype != C_RANGER) {
|
||||
msg("You are not permitted to cast spells.");
|
||||
return;
|
||||
}
|
||||
spell_ability = pstats.s_lvl * pstats.s_intel;
|
||||
if (player.t_ctype != C_MAGICIAN)
|
||||
spell_ability /= 3;
|
||||
|
||||
if (player.t_action != C_CAST) {
|
||||
/*
|
||||
* Get the number of avilable spells
|
||||
*/
|
||||
num_spells = 0;
|
||||
if (pstats.s_intel >= 16)
|
||||
num_spells += pstats.s_intel - 15;
|
||||
num_spells += pstats.s_lvl;
|
||||
if (player.t_ctype != C_MAGICIAN)
|
||||
num_spells /= 3;
|
||||
if (num_spells > MAXSPELLS)
|
||||
num_spells = MAXSPELLS;
|
||||
if (num_spells < 1) {
|
||||
msg("You are not allowed to cast spells yet.");
|
||||
return;
|
||||
}
|
||||
if (pick_spell( magic_spells,
|
||||
spell_ability,
|
||||
num_spells,
|
||||
spell_power,
|
||||
"cast",
|
||||
"spell"))
|
||||
player.t_action = C_CAST;
|
||||
return;
|
||||
}
|
||||
|
||||
/* We've waited our required casting time. */
|
||||
which_spell = player.t_selection;
|
||||
player.t_selection = 0;
|
||||
player.t_using = NULL;
|
||||
player.t_action = A_NIL;
|
||||
|
||||
if ((spell_power + magic_spells[which_spell].s_cost) > spell_ability) {
|
||||
msg("Your attempt fails.");
|
||||
return;
|
||||
}
|
||||
|
||||
msg("Your spell is successful.");
|
||||
|
||||
if (magic_spells[which_spell].s_type == TYP_POTION)
|
||||
quaff( magic_spells[which_spell].s_which,
|
||||
NULL,
|
||||
magic_spells[which_spell].s_flag,
|
||||
FALSE);
|
||||
else if (magic_spells[which_spell].s_type == TYP_SCROLL)
|
||||
read_scroll( magic_spells[which_spell].s_which,
|
||||
magic_spells[which_spell].s_flag,
|
||||
FALSE);
|
||||
else if (magic_spells[which_spell].s_type == TYP_STICK) {
|
||||
if (!player_zap(magic_spells[which_spell].s_which,
|
||||
magic_spells[which_spell].s_flag)) {
|
||||
after = FALSE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
spell_power += magic_spells[which_spell].s_cost;
|
||||
}
|
||||
|
||||
/*
|
||||
* the druid asks his deity for a spell
|
||||
*/
|
||||
chant()
|
||||
{
|
||||
register int num_chants,
|
||||
chant_ability,
|
||||
which_chant;
|
||||
|
||||
which_chant = num_chants = chant_ability = 0;
|
||||
|
||||
if (player.t_ctype != C_DRUID && player.t_ctype != C_RANGER) {
|
||||
msg("You are not permitted to chant.");
|
||||
return;
|
||||
}
|
||||
if (cur_misc[WEAR_CLOAK] != NULL &&
|
||||
cur_misc[WEAR_CLOAK]->o_which == MM_R_POWERLESS) {
|
||||
msg("You can't seem to chant!");
|
||||
return;
|
||||
}
|
||||
chant_ability = pstats.s_lvl * pstats.s_wisdom;
|
||||
if (player.t_ctype != C_DRUID)
|
||||
chant_ability /= 3;
|
||||
|
||||
if (player.t_action != C_CHANT) {
|
||||
num_chants = 0;
|
||||
|
||||
/* Get the number of avilable chants */
|
||||
if (pstats.s_wisdom > 16)
|
||||
num_chants = (pstats.s_wisdom - 15) / 2;
|
||||
|
||||
num_chants += pstats.s_lvl;
|
||||
|
||||
if (player.t_ctype != C_DRUID)
|
||||
num_chants /= 3;
|
||||
|
||||
if (num_chants > MAXCHANTS)
|
||||
num_chants = MAXCHANTS;
|
||||
|
||||
if (num_chants < 1) {
|
||||
msg("You are not permitted to chant yet.");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Prompt for chant */
|
||||
if (pick_spell( druid_spells,
|
||||
chant_ability,
|
||||
num_chants,
|
||||
chant_time,
|
||||
"sing",
|
||||
"chant"))
|
||||
player.t_action = C_CHANT;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* We've waited our required chanting time. */
|
||||
which_chant = player.t_selection;
|
||||
player.t_selection = 0;
|
||||
player.t_using = NULL;
|
||||
player.t_action = A_NIL;
|
||||
|
||||
if (druid_spells[which_chant].s_cost + chant_time > chant_ability) {
|
||||
msg("Your chant fails.");
|
||||
return;
|
||||
}
|
||||
|
||||
msg("Your chant has been granted.");
|
||||
|
||||
if (druid_spells[which_chant].s_type == TYP_POTION)
|
||||
quaff( druid_spells[which_chant].s_which,
|
||||
NULL,
|
||||
druid_spells[which_chant].s_flag,
|
||||
FALSE);
|
||||
else if (druid_spells[which_chant].s_type == TYP_SCROLL)
|
||||
read_scroll( druid_spells[which_chant].s_which,
|
||||
druid_spells[which_chant].s_flag,
|
||||
FALSE);
|
||||
else if (druid_spells[which_chant].s_type == TYP_STICK) {
|
||||
if (!player_zap(druid_spells[which_chant].s_which,
|
||||
druid_spells[which_chant].s_flag)) {
|
||||
after = FALSE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
chant_time += druid_spells[which_chant].s_cost;
|
||||
}
|
||||
|
||||
/* Constitution bonus */
|
||||
|
||||
const_bonus() /* Hit point adjustment for changing levels */
|
||||
{
|
||||
register int bonus;
|
||||
if (pstats.s_const > 6 && pstats.s_const <= 14)
|
||||
bonus = 0;
|
||||
else if (pstats.s_const > 14)
|
||||
bonus = pstats.s_const-14;
|
||||
else if (pstats.s_const > 3)
|
||||
bonus = -1;
|
||||
else
|
||||
bonus = -2;
|
||||
switch(player.t_ctype) {
|
||||
case C_FIGHTER: bonus = min(bonus, 11);
|
||||
when C_MAGICIAN: bonus = min(bonus, 4);
|
||||
when C_CLERIC: bonus = min(bonus, 4);
|
||||
when C_THIEF: bonus = min(bonus, 4);
|
||||
when C_RANGER: bonus = min(bonus, 6);
|
||||
when C_PALADIN: bonus = min(bonus, 8);
|
||||
when C_ASSASIN: bonus = min(bonus, 4);
|
||||
when C_MONK: bonus = min(bonus, 6);
|
||||
when C_DRUID: bonus = min(bonus, 4);
|
||||
otherwise: bonus = min(bonus, 4);
|
||||
}
|
||||
return(bonus);
|
||||
}
|
||||
|
||||
|
||||
/* Routines for thieves */
|
||||
|
||||
/*
|
||||
* gsense:
|
||||
* Sense gold
|
||||
*/
|
||||
|
||||
gsense()
|
||||
{
|
||||
/* Only thieves can do this */
|
||||
if (player.t_ctype != C_THIEF && player.t_ctype != C_ASSASIN) {
|
||||
msg("You seem to have no gold sense.");
|
||||
return;
|
||||
}
|
||||
|
||||
read_scroll(S_GFIND, NULL, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* the cleric asks his deity for a spell
|
||||
*/
|
||||
pray()
|
||||
{
|
||||
register int num_prayers,
|
||||
prayer_ability,
|
||||
which_prayer;
|
||||
|
||||
which_prayer = num_prayers = prayer_ability = 0;
|
||||
|
||||
if (player.t_ctype != C_CLERIC &&
|
||||
player.t_ctype != C_PALADIN &&
|
||||
cur_relic[HEIL_ANKH] == 0) {
|
||||
msg("You are not permitted to pray.");
|
||||
return;
|
||||
}
|
||||
if (cur_misc[WEAR_CLOAK] != NULL &&
|
||||
cur_misc[WEAR_CLOAK]->o_which == MM_R_POWERLESS) {
|
||||
msg("You can't seem to pray!");
|
||||
return;
|
||||
}
|
||||
|
||||
prayer_ability = pstats.s_lvl * pstats.s_wisdom;
|
||||
if (player.t_ctype != C_CLERIC)
|
||||
prayer_ability /= 3;
|
||||
|
||||
if (cur_relic[HEIL_ANKH]) prayer_ability *= 2;
|
||||
|
||||
if (player.t_action != C_PRAY) {
|
||||
num_prayers = 0;
|
||||
|
||||
/* Get the number of avilable prayers */
|
||||
if (pstats.s_wisdom > 16)
|
||||
num_prayers += (pstats.s_wisdom - 15) / 2;
|
||||
|
||||
num_prayers += pstats.s_lvl;
|
||||
if (cur_relic[HEIL_ANKH]) num_prayers += 3;
|
||||
|
||||
if (player.t_ctype != C_CLERIC)
|
||||
num_prayers /= 3;
|
||||
|
||||
if (num_prayers > MAXPRAYERS)
|
||||
num_prayers = MAXPRAYERS;
|
||||
if (num_prayers < 1) {
|
||||
msg("You are not permitted to pray yet.");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Prompt for prayer */
|
||||
if (pick_spell( cleric_spells,
|
||||
prayer_ability,
|
||||
num_prayers,
|
||||
pray_time,
|
||||
"offer",
|
||||
"prayer"))
|
||||
player.t_action = C_PRAY;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* We've waited our required praying time. */
|
||||
which_prayer = player.t_selection;
|
||||
player.t_selection = 0;
|
||||
player.t_using = NULL;
|
||||
player.t_action = A_NIL;
|
||||
|
||||
if (cleric_spells[which_prayer].s_cost + pray_time > prayer_ability) {
|
||||
msg("Your prayer fails.");
|
||||
return;
|
||||
}
|
||||
|
||||
msg("Your prayer has been granted.");
|
||||
|
||||
if (cleric_spells[which_prayer].s_type == TYP_POTION)
|
||||
quaff( cleric_spells[which_prayer].s_which,
|
||||
NULL,
|
||||
cleric_spells[which_prayer].s_flag,
|
||||
FALSE);
|
||||
else if (cleric_spells[which_prayer].s_type == TYP_SCROLL)
|
||||
read_scroll( cleric_spells[which_prayer].s_which,
|
||||
cleric_spells[which_prayer].s_flag,
|
||||
FALSE);
|
||||
else if (cleric_spells[which_prayer].s_type == TYP_STICK) {
|
||||
if (!player_zap(cleric_spells[which_prayer].s_which,
|
||||
cleric_spells[which_prayer].s_flag)) {
|
||||
after = FALSE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
pray_time += cleric_spells[which_prayer].s_cost;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* steal:
|
||||
* Steal in direction given in delta
|
||||
*/
|
||||
|
||||
steal()
|
||||
{
|
||||
register struct linked_list *item;
|
||||
register struct thing *tp;
|
||||
register char *mname;
|
||||
coord new_pos;
|
||||
int thief_bonus = -50;
|
||||
bool isinvisible = FALSE;
|
||||
|
||||
if (player.t_ctype != C_THIEF && player.t_ctype != C_ASSASIN) {
|
||||
msg("Only thieves and assassins can steal.");
|
||||
return;
|
||||
}
|
||||
if (on(player, ISBLIND)) {
|
||||
msg("You can't see anything.");
|
||||
return;
|
||||
}
|
||||
|
||||
new_pos.y = hero.y + player.t_newpos.y;
|
||||
new_pos.x = hero.x + player.t_newpos.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 steal from.");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((item = find_mons(new_pos.y, new_pos.x)) == NULL)
|
||||
debug("Steal from what @ %d,%d?", new_pos.y, new_pos.x);
|
||||
tp = THINGPTR(item);
|
||||
if (on(*tp, ISSTONE)) {
|
||||
msg ("You can't steal from stone!");
|
||||
return;
|
||||
}
|
||||
if (isinvisible = invisible(tp)) mname = "creature";
|
||||
else mname = monster_name(tp);
|
||||
|
||||
/* Can player steal something unnoticed? */
|
||||
if (player.t_ctype == C_THIEF) thief_bonus = 10;
|
||||
if (player.t_ctype == C_ASSASIN) thief_bonus = 0;
|
||||
if (on(*tp, ISUNIQUE)) thief_bonus -= 15;
|
||||
if (isinvisible) thief_bonus -= 20;
|
||||
if (on(*tp, ISINWALL) && off(player, CANINWALL)) thief_bonus -= 50;
|
||||
|
||||
if (on(*tp, ISHELD) || tp->t_action == A_FREEZE ||
|
||||
rnd(100) <
|
||||
(thief_bonus + 2*dex_compute() + 5*pstats.s_lvl -
|
||||
5*(tp->t_stats.s_lvl - 3))) {
|
||||
register struct linked_list *s_item, *pack_ptr;
|
||||
int count = 0;
|
||||
unsigned long test; /* Overflow check */
|
||||
|
||||
s_item = NULL; /* Start stolen goods out as nothing */
|
||||
|
||||
/* Find a good item to take */
|
||||
for (pack_ptr=tp->t_pack; pack_ptr != NULL; pack_ptr=next(pack_ptr))
|
||||
if ((OBJPTR(pack_ptr))->o_type != RELIC &&
|
||||
pack_ptr != tp->t_using && /* Monster can't be using it */
|
||||
rnd(++count) == 0)
|
||||
s_item = pack_ptr;
|
||||
|
||||
/*
|
||||
* Find anything?
|
||||
*/
|
||||
if (s_item == NULL) {
|
||||
msg("%s apparently has nothing to steal.", prname(mname, TRUE));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Take it from monster */
|
||||
if (tp->t_pack) detach(tp->t_pack, s_item);
|
||||
|
||||
/* Recalculate the monster's encumberance */
|
||||
updpack(TRUE, tp);
|
||||
|
||||
/* Give it to player */
|
||||
if (add_pack(s_item, FALSE, NULL) == FALSE) {
|
||||
(OBJPTR(s_item))->o_pos = hero;
|
||||
fall(s_item, TRUE);
|
||||
}
|
||||
|
||||
/* Get points for stealing -- but first check for overflow */
|
||||
test = pstats.s_exp + tp->t_stats.s_exp/2;
|
||||
if (test > pstats.s_exp) pstats.s_exp = test;
|
||||
|
||||
/*
|
||||
* Do adjustments if player went up a level
|
||||
*/
|
||||
check_level();
|
||||
}
|
||||
|
||||
else {
|
||||
msg("Your attempt fails.");
|
||||
|
||||
/* Annoy monster (maybe) */
|
||||
if (rnd(35) >= dex_compute() + thief_bonus) {
|
||||
/*
|
||||
* If this is a charmed creature, there is a chance it
|
||||
* will become uncharmed.
|
||||
*/
|
||||
if (on(*tp, ISCHARMED) && save(VS_MAGIC, tp, 0)) {
|
||||
msg("The eyes of %s turn clear.", prname(mname, FALSE));
|
||||
turn_off(*tp, ISCHARMED);
|
||||
}
|
||||
if (on(*tp, CANSELL)) {
|
||||
turn_off(*tp, CANSELL);
|
||||
tp->t_action = A_NIL;
|
||||
tp->t_movement = 0;
|
||||
if (rnd(100) < 50) /* make him steal something */
|
||||
turn_on(*tp, STEALMAGIC);
|
||||
else
|
||||
turn_on(*tp, STEALGOLD);
|
||||
if (!isinvisible)
|
||||
msg("%s looks insulted.", prname(mname, TRUE));
|
||||
}
|
||||
runto(tp, &hero);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PC7300
|
||||
/* Use MAXSPELLS or whatever is the biggest number of spells/prayers/etc */
|
||||
static menu_t Display; /* The menu structure */
|
||||
static mitem_t Dispitems[MAXSPELLS+1]; /* Info for each line */
|
||||
static char Displines[MAXSPELLS+1][LINELEN+1]; /* The lines themselves */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* this routine lets the player pick the spell that they
|
||||
* want to cast regardless of character class
|
||||
*/
|
||||
pick_spell(spells, ability, num_spells, power, prompt, type)
|
||||
struct spells spells[]; /* spell list */
|
||||
int ability; /* spell ability */
|
||||
int num_spells; /* number of spells that can be cast */
|
||||
int power; /* spell power */
|
||||
char *prompt; /* prompt for spell list */
|
||||
char *type; /* type of thing--> spell, prayer, chant */
|
||||
{
|
||||
bool nohw = FALSE;
|
||||
register int i;
|
||||
int curlen,
|
||||
maxlen,
|
||||
dummy,
|
||||
which_spell,
|
||||
spell_left;
|
||||
#ifdef PC7300
|
||||
char label[LINELEN], /* For menu label */
|
||||
title[LINELEN]; /* For menu title */
|
||||
#endif
|
||||
|
||||
if (cur_misc[WEAR_CLOAK] != NULL &&
|
||||
cur_misc[WEAR_CLOAK]->o_which == MM_R_POWERLESS) {
|
||||
msg("You can't seem to start a %s!", type);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/* Prompt for spells */
|
||||
msg("Which %s are you %sing? (* for list): ", type, prompt);
|
||||
|
||||
which_spell = (int) (readchar() - 'a');
|
||||
msg(""); /* Get rid of the prompt */
|
||||
if (which_spell == (int) ESCAPE - (int) 'a') {
|
||||
after = FALSE;
|
||||
return(FALSE);
|
||||
}
|
||||
if (which_spell >= 0 && which_spell < num_spells) nohw = TRUE;
|
||||
|
||||
else if (slow_invent) {
|
||||
register char c;
|
||||
|
||||
nohw = TRUE;
|
||||
do {
|
||||
for (i=0; i<num_spells; i++) {
|
||||
msg("");
|
||||
mvwaddch(msgw, 0, 0, '[');
|
||||
waddch(msgw, (char) ((int) 'a' + i));
|
||||
wprintw(msgw, "] A %s of ", type);
|
||||
if (spells[i].s_type == TYP_POTION)
|
||||
waddstr(msgw, p_magic[spells[i].s_which].mi_name);
|
||||
else if (spells[i].s_type == TYP_SCROLL)
|
||||
waddstr(msgw, s_magic[spells[i].s_which].mi_name);
|
||||
else if (spells[i].s_type == TYP_STICK)
|
||||
waddstr(msgw, ws_magic[spells[i].s_which].mi_name);
|
||||
waddstr(msgw, morestr);
|
||||
wclrtobot(msgw);
|
||||
clearok(msgw, FALSE);
|
||||
draw(msgw);
|
||||
do {
|
||||
c = readchar();
|
||||
} while (c != ' ' && c != ESCAPE);
|
||||
if (c == ESCAPE)
|
||||
break;
|
||||
}
|
||||
msg("");
|
||||
wmove(msgw, 0, 0);
|
||||
wprintw(msgw, "Which %s are you %sing? ", type, prompt);
|
||||
clearok(msgw, FALSE);
|
||||
draw(msgw);
|
||||
|
||||
which_spell = (int) (readchar() - 'a');
|
||||
} while (which_spell != (int) (ESCAPE - 'a') &&
|
||||
(which_spell < 0 || which_spell >= num_spells));
|
||||
|
||||
if (which_spell == (int) (ESCAPE - 'a')) {
|
||||
mpos = 0;
|
||||
msg("");
|
||||
after = FALSE;
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Now display the possible spells */
|
||||
wclear(hw);
|
||||
touchwin(hw);
|
||||
wmove(hw, 2, 0);
|
||||
*type = toupper(*type);
|
||||
wprintw(hw, " Cost %s", type);
|
||||
*type = tolower(*type);
|
||||
mvwaddstr(hw, 3, 0,
|
||||
"-----------------------------------------------");
|
||||
maxlen = 47; /* Maximum width of header */
|
||||
|
||||
for (i=0; i<num_spells; i++) {
|
||||
sprintf(prbuf, "[%c] %3d A %s of ",
|
||||
(char) ((int) 'a' + i), spells[i].s_cost, type);
|
||||
if (spells[i].s_type == TYP_POTION)
|
||||
strcat(prbuf, p_magic[spells[i].s_which].mi_name);
|
||||
else if (spells[i].s_type == TYP_SCROLL)
|
||||
strcat(prbuf, s_magic[spells[i].s_which].mi_name);
|
||||
else if (spells[i].s_type == TYP_STICK)
|
||||
strcat(prbuf, ws_magic[spells[i].s_which].mi_name);
|
||||
mvwaddstr(hw, i+4, 0, prbuf);
|
||||
|
||||
/* Get the length of the line */
|
||||
getyx(hw, dummy, curlen);
|
||||
if (maxlen < curlen) maxlen = curlen;
|
||||
|
||||
#ifdef PC7300
|
||||
/* Put it into the PC menu display */
|
||||
strcpy(Displines[i], prbuf);
|
||||
Dispitems[i].mi_name = Displines[i];
|
||||
Dispitems[i].mi_flags = 0;
|
||||
Dispitems[i].mi_val = i;
|
||||
#endif
|
||||
}
|
||||
|
||||
spell_left = ability - power;
|
||||
if (spell_left < 0) {
|
||||
spell_left = 0;
|
||||
if (spell_left < -20) power = ability + 20;
|
||||
}
|
||||
sprintf(prbuf, "[Current %s power = %d]", type, spell_left);
|
||||
|
||||
mvwaddstr(hw, 0, 0, prbuf);
|
||||
wprintw(hw, " Which %s are you %sing? ", type, prompt);
|
||||
getyx(hw, dummy, curlen);
|
||||
if (maxlen < curlen) maxlen = curlen;
|
||||
|
||||
#ifdef PC7300
|
||||
/* Place an end marker for the items */
|
||||
Dispitems[num_spells].mi_name = 0;
|
||||
|
||||
/* Design prompts */
|
||||
sprintf(label, "Current %s power is %d", type, spell_left);
|
||||
*type = toupper(*type);
|
||||
sprintf(title, " Cost %s", type);
|
||||
*type = tolower(*type);
|
||||
sprintf(prbuf, "Select a %s or press Cancl to continue.", type);
|
||||
|
||||
/* Set up the main menu structure */
|
||||
Display.m_label = label;
|
||||
Display.m_title = title;
|
||||
Display.m_prompt = prbuf;
|
||||
Display.m_curptr = '\0';
|
||||
Display.m_markptr = '\0';
|
||||
Display.m_flags = M_ASISTITLE;
|
||||
Display.m_selcnt = 1;
|
||||
Display.m_items = Dispitems;
|
||||
Display.m_curi = 0;
|
||||
|
||||
/*
|
||||
* Try to display the menu. If we don't have a local terminal,
|
||||
* the call will fail and we will just continue with the
|
||||
* normal mode.
|
||||
*/
|
||||
if (menu(&Display) >= 0) {
|
||||
if (Display.m_selcnt == 0) {
|
||||
/* Menu was cancelled */
|
||||
after = FALSE;
|
||||
return FALSE; /* all done if abort */
|
||||
}
|
||||
else which_spell = (int) Display.m_curi->mi_val;
|
||||
goto got_spell;
|
||||
}
|
||||
#endif
|
||||
/* Should we overlay? */
|
||||
if (menu_overlay && num_spells + 3 < lines / 2) {
|
||||
over_win(cw, hw, num_spells + 5, maxlen + 3, 0, curlen, NULL);
|
||||
}
|
||||
else draw(hw);
|
||||
}
|
||||
|
||||
if (!nohw) {
|
||||
which_spell = (int) (readchar() - 'a');
|
||||
while (which_spell < 0 || which_spell >= num_spells) {
|
||||
if (which_spell == (int) ESCAPE - (int) 'a') {
|
||||
after = FALSE;
|
||||
|
||||
/* Restore the screen */
|
||||
touchwin(cw);
|
||||
if (num_spells + 3 < lines / 2) clearok(cw, FALSE);
|
||||
else clearok(cw, TRUE);
|
||||
return(FALSE);
|
||||
}
|
||||
wmove(hw, 0, 0);
|
||||
wclrtoeol(hw);
|
||||
wprintw(hw, "Please enter one of the listed %ss. ", type);
|
||||
getyx(hw, dummy, curlen);
|
||||
if (maxlen < curlen) maxlen = curlen;
|
||||
|
||||
/* Should we overlay? */
|
||||
if (menu_overlay && num_spells + 3 < lines / 2) {
|
||||
over_win(cw, hw, num_spells + 5, maxlen + 3,
|
||||
0, curlen, NULL);
|
||||
}
|
||||
else draw(hw);
|
||||
|
||||
which_spell = (int) (readchar() - 'a');
|
||||
}
|
||||
}
|
||||
|
||||
/* Now restore the screen if we have to */
|
||||
if (!nohw) {
|
||||
touchwin(cw);
|
||||
if (num_spells + 3 < lines / 2) clearok(cw, FALSE);
|
||||
else clearok(cw, TRUE);
|
||||
}
|
||||
|
||||
#ifdef PC7300
|
||||
got_spell:
|
||||
#endif
|
||||
if (spells[which_spell].s_type == TYP_STICK &&
|
||||
need_dir(STICK, spells[which_spell].s_which)) {
|
||||
if (!get_dir(&player.t_newpos)) {
|
||||
after = FALSE;
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
player.t_selection = which_spell;
|
||||
player.t_using = NULL;
|
||||
player.t_no_move = (which_spell/3 + 1) * movement(&player);
|
||||
return(TRUE);
|
||||
}
|
||||
980
arogue7/potions.c
Normal file
980
arogue7/potions.c
Normal file
|
|
@ -0,0 +1,980 @@
|
|||
/*
|
||||
* potions.c - Function(s) for dealing with potions
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Function(s) for dealing with potions
|
||||
*/
|
||||
|
||||
#include "curses.h"
|
||||
#include "rogue.h"
|
||||
|
||||
|
||||
/*
|
||||
* add_abil is an array of functions used to change attributes. It must be
|
||||
* ordered according to the attribute definitions in rogue.h.
|
||||
*/
|
||||
|
||||
void (*add_abil[NUMABILITIES])() = {
|
||||
add_intelligence, add_strength, add_wisdom, add_dexterity,
|
||||
add_constitution, add_charisma
|
||||
};
|
||||
|
||||
/*
|
||||
* res_abil is an array of functions used to change attributes. It must be
|
||||
* ordered according to the attribute definitions in rogue.h.
|
||||
*/
|
||||
|
||||
void (*res_abil[NUMABILITIES])() = {
|
||||
res_intelligence, res_strength, res_wisdom, res_dexterity,
|
||||
res_constitution, res_charisma
|
||||
};
|
||||
|
||||
/*
|
||||
* Increase player's constitution
|
||||
*/
|
||||
|
||||
void
|
||||
add_constitution(change)
|
||||
int change;
|
||||
{
|
||||
/* Do the potion */
|
||||
if (change < 0) {
|
||||
msg("You feel less healthy now.");
|
||||
pstats.s_const += change;
|
||||
if (pstats.s_const <= 0)
|
||||
death(D_CONSTITUTION);
|
||||
}
|
||||
else {
|
||||
msg("You feel healthier now.");
|
||||
pstats.s_const = min(pstats.s_const + change, 25);
|
||||
}
|
||||
|
||||
/* Adjust the maximum */
|
||||
if (max_stats.s_const < pstats.s_const)
|
||||
max_stats.s_const = pstats.s_const;
|
||||
}
|
||||
|
||||
/*
|
||||
* Increase player's charisma
|
||||
*/
|
||||
|
||||
void
|
||||
add_charisma(change)
|
||||
int change;
|
||||
{
|
||||
/* Do the potion */
|
||||
if (change < 0) msg("You feel less attractive now.");
|
||||
else msg("You feel more attractive now.");
|
||||
|
||||
pstats.s_charisma += change;
|
||||
if (pstats.s_charisma > 25) pstats.s_charisma = 25;
|
||||
else if (pstats.s_charisma < 3) pstats.s_charisma = 3;
|
||||
|
||||
/* Adjust the maximum */
|
||||
if (max_stats.s_charisma < pstats.s_charisma)
|
||||
max_stats.s_charisma = pstats.s_charisma;
|
||||
}
|
||||
|
||||
/*
|
||||
* Increase player's dexterity
|
||||
*/
|
||||
|
||||
void
|
||||
add_dexterity(change)
|
||||
int change;
|
||||
{
|
||||
int ring_str; /* Value of ring strengths */
|
||||
|
||||
/* Undo any ring changes */
|
||||
ring_str = ring_value(R_ADDHIT);
|
||||
pstats.s_dext -= ring_str;
|
||||
|
||||
/* Now do the potion */
|
||||
if (change < 0) msg("You feel less dextrous now.");
|
||||
else msg("You feel more dextrous now. Watch those hands!");
|
||||
|
||||
pstats.s_dext += change;
|
||||
if (pstats.s_dext > 25) pstats.s_dext = 25;
|
||||
else if (pstats.s_dext < 3) pstats.s_dext = 3;
|
||||
|
||||
/* Adjust the maximum */
|
||||
if (max_stats.s_dext < pstats.s_dext)
|
||||
max_stats.s_dext = pstats.s_dext;
|
||||
|
||||
/* Now put back the ring changes */
|
||||
if (ring_str)
|
||||
pstats.s_dext += ring_str;
|
||||
}
|
||||
|
||||
/*
|
||||
* add_haste:
|
||||
* add a haste to the player
|
||||
*/
|
||||
|
||||
add_haste(blessed)
|
||||
bool blessed;
|
||||
{
|
||||
int hasttime;
|
||||
|
||||
if (player.t_ctype == C_MONK) { /* monks cannot be slowed or hasted */
|
||||
msg(nothing);
|
||||
return;
|
||||
}
|
||||
|
||||
if (blessed) hasttime = HASTETIME*2;
|
||||
else hasttime = HASTETIME;
|
||||
|
||||
if (on(player, ISSLOW)) { /* Is person slow? */
|
||||
extinguish(noslow);
|
||||
noslow();
|
||||
|
||||
if (blessed) hasttime = HASTETIME/2;
|
||||
else return;
|
||||
}
|
||||
|
||||
if (on(player, ISHASTE)) {
|
||||
msg("You faint from exhaustion.");
|
||||
player.t_no_move += movement(&player) * rnd(hasttime);
|
||||
player.t_action = A_FREEZE;
|
||||
lengthen(nohaste, roll(hasttime,hasttime));
|
||||
}
|
||||
else {
|
||||
msg("You feel yourself moving %sfaster.", blessed ? "much " : "");
|
||||
turn_on(player, ISHASTE);
|
||||
fuse(nohaste, 0, roll(hasttime, hasttime), AFTER);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Increase player's intelligence
|
||||
*/
|
||||
void
|
||||
add_intelligence(change)
|
||||
int change;
|
||||
{
|
||||
int ring_str; /* Value of ring strengths */
|
||||
|
||||
/* Undo any ring changes */
|
||||
ring_str = ring_value(R_ADDINTEL);
|
||||
pstats.s_intel -= ring_str;
|
||||
|
||||
/* Now do the potion */
|
||||
if (change < 0) msg("You feel slightly less intelligent now.");
|
||||
else msg("You feel more intelligent now. What a mind!");
|
||||
|
||||
pstats.s_intel += change;
|
||||
if (pstats.s_intel > 25) pstats.s_intel = 25;
|
||||
else if (pstats.s_intel < 3) pstats.s_intel = 3;
|
||||
|
||||
/* Adjust the maximum */
|
||||
if (max_stats.s_intel < pstats.s_intel)
|
||||
max_stats.s_intel = pstats.s_intel;
|
||||
|
||||
/* Now put back the ring changes */
|
||||
if (ring_str)
|
||||
pstats.s_intel += ring_str;
|
||||
}
|
||||
|
||||
/*
|
||||
* this routine makes the hero move slower
|
||||
*/
|
||||
add_slow()
|
||||
{
|
||||
/* monks cannot be slowed or hasted */
|
||||
if (player.t_ctype == C_MONK || ISWEARING(R_FREEDOM)) {
|
||||
msg(nothing);
|
||||
return;
|
||||
}
|
||||
|
||||
if (on(player, ISHASTE)) { /* Already sped up */
|
||||
extinguish(nohaste);
|
||||
nohaste();
|
||||
}
|
||||
else {
|
||||
msg("You feel yourself moving %sslower.",
|
||||
on(player, ISSLOW) ? "even " : "");
|
||||
if (on(player, ISSLOW))
|
||||
lengthen(noslow, roll(HASTETIME,HASTETIME));
|
||||
else {
|
||||
turn_on(player, ISSLOW);
|
||||
fuse(noslow, 0, roll(HASTETIME,HASTETIME), AFTER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Increase player's strength
|
||||
*/
|
||||
|
||||
void
|
||||
add_strength(change)
|
||||
int change;
|
||||
{
|
||||
|
||||
if (change < 0) {
|
||||
msg("You feel slightly weaker now.");
|
||||
chg_str(change);
|
||||
}
|
||||
else {
|
||||
msg("You feel stronger now. What bulging muscles!");
|
||||
chg_str(change);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Increase player's wisdom
|
||||
*/
|
||||
|
||||
void
|
||||
add_wisdom(change)
|
||||
int change;
|
||||
{
|
||||
int ring_str; /* Value of ring strengths */
|
||||
|
||||
/* Undo any ring changes */
|
||||
ring_str = ring_value(R_ADDWISDOM);
|
||||
pstats.s_wisdom -= ring_str;
|
||||
|
||||
/* Now do the potion */
|
||||
if (change < 0) msg("You feel slightly less wise now.");
|
||||
else msg("You feel wiser now. What a sage!");
|
||||
|
||||
pstats.s_wisdom += change;
|
||||
if (pstats.s_wisdom > 25) pstats.s_wisdom = 25;
|
||||
else if (pstats.s_wisdom < 3) pstats.s_wisdom = 3;
|
||||
|
||||
/* Adjust the maximum */
|
||||
if (max_stats.s_wisdom < pstats.s_wisdom)
|
||||
max_stats.s_wisdom = pstats.s_wisdom;
|
||||
|
||||
/* Now put back the ring changes */
|
||||
if (ring_str)
|
||||
pstats.s_wisdom += ring_str;
|
||||
}
|
||||
|
||||
quaff(which, kind, flags, is_potion)
|
||||
int which;
|
||||
int kind;
|
||||
int flags;
|
||||
bool is_potion;
|
||||
{
|
||||
register struct object *obj;
|
||||
register struct linked_list *item, *titem;
|
||||
register struct thing *th;
|
||||
bool cursed, blessed;
|
||||
|
||||
blessed = FALSE;
|
||||
cursed = FALSE;
|
||||
item = NULL;
|
||||
|
||||
if (which < 0) { /* figure out which ourselves */
|
||||
/* This is a potion. */
|
||||
if (player.t_action != C_QUAFF) {
|
||||
int units;
|
||||
|
||||
item = get_item(pack, "quaff", QUAFFABLE, FALSE, FALSE);
|
||||
|
||||
/*
|
||||
* Make certain that it is somethings that we want to drink
|
||||
*/
|
||||
if (item == NULL)
|
||||
return;
|
||||
|
||||
/* How long does it take to quaff? */
|
||||
units = usage_time(item);
|
||||
if (units < 0) return;
|
||||
|
||||
player.t_using = item; /* Remember what it is */
|
||||
player.t_no_move = units * movement(&player);
|
||||
if ((OBJPTR(item))->o_type == POTION) player.t_action = C_QUAFF;
|
||||
else player.t_action = C_USE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* We have waited our time, let's quaff the potion */
|
||||
item = player.t_using;
|
||||
player.t_using = NULL;
|
||||
player.t_action = A_NIL;
|
||||
|
||||
obj = OBJPTR(item);
|
||||
/* remove it from the pack */
|
||||
inpack--;
|
||||
detach(pack, item);
|
||||
|
||||
flags = obj->o_flags;
|
||||
which = obj->o_which;
|
||||
kind = obj->o_kind;
|
||||
}
|
||||
cursed = flags & ISCURSED;
|
||||
blessed = flags & ISBLESSED;
|
||||
|
||||
switch(which) {
|
||||
case P_CLEAR:
|
||||
if (cursed) {
|
||||
confus_player();
|
||||
}
|
||||
else {
|
||||
if (blessed) { /* Make player immune for the whole game */
|
||||
extinguish(unclrhead); /* If we have a fuse, put it out */
|
||||
msg("A strong blue aura surrounds your head.");
|
||||
}
|
||||
else { /* Just light a fuse for how long player is safe */
|
||||
if (off(player, ISCLEAR)) {
|
||||
fuse(unclrhead, 0, CLRDURATION, AFTER);
|
||||
msg("A faint blue aura surrounds your head.");
|
||||
}
|
||||
else { /* If we have a fuse lengthen it, else we
|
||||
* are permanently clear.
|
||||
*/
|
||||
if (find_slot(unclrhead) == 0)
|
||||
msg("Your blue aura continues to glow strongly.");
|
||||
else {
|
||||
lengthen(unclrhead, CLRDURATION);
|
||||
msg("Your blue aura brightens for a moment.");
|
||||
}
|
||||
}
|
||||
}
|
||||
turn_on(player, ISCLEAR);
|
||||
/* If player is confused, unconfuse him */
|
||||
if (on(player, ISHUH)) {
|
||||
extinguish(unconfuse);
|
||||
unconfuse();
|
||||
}
|
||||
}
|
||||
when P_HEALING:
|
||||
if (cursed) {
|
||||
msg("You feel worse now.");
|
||||
pstats.s_hpt -= roll(pstats.s_lvl, char_class[player.t_ctype].hit_pts);
|
||||
if (pstats.s_hpt <= 0)
|
||||
death(D_POISON);
|
||||
}
|
||||
else {
|
||||
if (blessed) {
|
||||
pstats.s_hpt += roll(pstats.s_lvl+1, char_class[player.t_ctype].hit_pts);
|
||||
if (pstats.s_hpt > max_stats.s_hpt)
|
||||
pstats.s_hpt = ++max_stats.s_hpt;
|
||||
if (on(player, ISHUH)) {
|
||||
extinguish(unconfuse);
|
||||
unconfuse();
|
||||
}
|
||||
}
|
||||
else {
|
||||
pstats.s_hpt += roll(pstats.s_lvl+1, char_class[player.t_ctype].hit_pts/2);
|
||||
if (pstats.s_hpt > max_stats.s_hpt)
|
||||
pstats.s_hpt = ++max_stats.s_hpt;
|
||||
}
|
||||
msg("You begin to feel %sbetter.",
|
||||
blessed ? "much " : "");
|
||||
sight();
|
||||
if (is_potion) p_know[P_HEALING] = TRUE;
|
||||
}
|
||||
when P_ABIL:
|
||||
/* If it is cursed, we take a point away */
|
||||
if (cursed) {
|
||||
if (ISWEARING(R_SUSABILITY)) {
|
||||
msg(nothing);
|
||||
break;
|
||||
}
|
||||
else add_abil[kind](-1);
|
||||
}
|
||||
|
||||
/* Otherwise we add points */
|
||||
else add_abil[kind](blessed ? 3 : 1);
|
||||
|
||||
if (is_potion) p_know[P_ABIL] = TRUE;
|
||||
when P_MFIND:
|
||||
/*
|
||||
* Potion of monster detection, if there are monters, detect them
|
||||
*/
|
||||
if (mlist != NULL)
|
||||
{
|
||||
register struct thing *tp;
|
||||
register struct linked_list *item;
|
||||
|
||||
msg("You begin to sense the presence of monsters.");
|
||||
wclear(hw);
|
||||
for (item=mlist; item!=NULL; item=next(item)) {
|
||||
tp = THINGPTR(item);
|
||||
if (on(*tp, NODETECT))
|
||||
continue;
|
||||
if (off(*tp, ISRUN))/* turn off only on sleeping ones */
|
||||
turn_off(*tp, CANSURPRISE);
|
||||
mvwaddch(hw, tp->t_pos.y, tp->t_pos.x,
|
||||
monsters[tp->t_index].m_appear);
|
||||
}
|
||||
waddstr(msgw, morestr);
|
||||
clearok(msgw, FALSE);
|
||||
draw(msgw);
|
||||
overlay(hw, cw);
|
||||
draw(cw);
|
||||
wait_for(' ');
|
||||
msg("");
|
||||
if (is_potion) p_know[P_MFIND] = TRUE;
|
||||
}
|
||||
else
|
||||
msg("You have a strange feeling for a moment, then it passes.");
|
||||
when P_TFIND:
|
||||
/*
|
||||
* Potion of magic detection. Show the potions and scrolls
|
||||
*/
|
||||
{
|
||||
register struct linked_list *mobj;
|
||||
register struct object *tp;
|
||||
bool show;
|
||||
|
||||
show = FALSE;
|
||||
wclear(hw);
|
||||
for (mobj = lvl_obj; mobj != NULL; mobj = next(mobj)) {
|
||||
tp = OBJPTR(mobj);
|
||||
if (is_magic(tp)) {
|
||||
char mag_type=MAGIC;
|
||||
|
||||
/* Mark cursed items or bad weapons */
|
||||
if ((tp->o_flags & ISCURSED) ||
|
||||
(tp->o_type == WEAPON &&
|
||||
(tp->o_hplus < 0 || tp->o_dplus < 0)))
|
||||
mag_type = CMAGIC;
|
||||
else if ((tp->o_flags & ISBLESSED) ||
|
||||
(tp->o_type == WEAPON &&
|
||||
(tp->o_hplus > 0 || tp->o_dplus > 0)))
|
||||
mag_type = BMAGIC;
|
||||
show = TRUE;
|
||||
mvwaddch(hw, tp->o_pos.y, tp->o_pos.x, mag_type);
|
||||
}
|
||||
}
|
||||
for (titem = mlist; titem != NULL; titem = next(titem)) {
|
||||
register struct linked_list *pitem;
|
||||
|
||||
th = THINGPTR(titem);
|
||||
if (on(*th, NODETECT)) continue;
|
||||
for(pitem = th->t_pack; pitem != NULL; pitem = next(pitem)){
|
||||
tp = OBJPTR(pitem);
|
||||
if (is_magic(tp)) {
|
||||
char mag_type=MAGIC;
|
||||
|
||||
/* Mark cursed items or bad weapons */
|
||||
if ((tp->o_flags & ISCURSED) ||
|
||||
(tp->o_type == WEAPON &&
|
||||
(tp->o_hplus < 0 || tp->o_dplus < 0)))
|
||||
mag_type = CMAGIC;
|
||||
else if ((tp->o_flags & ISBLESSED) ||
|
||||
(tp->o_type == WEAPON &&
|
||||
(tp->o_hplus > 0 || tp->o_dplus > 0)))
|
||||
mag_type = BMAGIC;
|
||||
show = TRUE;
|
||||
mvwaddch(hw, th->t_pos.y, th->t_pos.x, mag_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (show) {
|
||||
if (is_potion) p_know[P_TFIND] = TRUE;
|
||||
msg("You sense the presence of magic on this level.");
|
||||
waddstr(msgw, morestr);
|
||||
clearok(msgw, FALSE);
|
||||
draw(msgw);
|
||||
overlay(hw,cw);
|
||||
draw(cw);
|
||||
wait_for(' ');
|
||||
msg("");
|
||||
break;
|
||||
}
|
||||
else
|
||||
msg("You have a strange feeling for a moment, then it passes.");
|
||||
}
|
||||
when P_SEEINVIS:
|
||||
if (cursed) {
|
||||
if (!find_slot(sight))
|
||||
{
|
||||
msg("A cloak of darkness falls around you.");
|
||||
turn_on(player, ISBLIND);
|
||||
fuse(sight, 0, SEEDURATION, AFTER);
|
||||
light(&hero);
|
||||
}
|
||||
else
|
||||
lengthen(sight, SEEDURATION);
|
||||
}
|
||||
else {
|
||||
if (off(player, CANSEE)) {
|
||||
turn_on(player, CANSEE);
|
||||
msg("Your eyes begin to tingle.");
|
||||
fuse(unsee, 0, blessed ? SEEDURATION*3 :SEEDURATION, AFTER);
|
||||
light(&hero);
|
||||
}
|
||||
else if (find_slot(unsee) != 0)
|
||||
lengthen(unsee, blessed ? SEEDURATION*3 : SEEDURATION);
|
||||
sight();
|
||||
}
|
||||
when P_PHASE:
|
||||
if (cursed) {
|
||||
msg("You can't move.");
|
||||
player.t_no_move = movement(&player) * FREEZETIME;
|
||||
player.t_action = A_FREEZE;
|
||||
}
|
||||
else {
|
||||
int duration;
|
||||
|
||||
if (blessed) duration = 3;
|
||||
else duration = 1;
|
||||
|
||||
if (on(player, CANINWALL))
|
||||
lengthen(unphase, duration*PHASEDURATION);
|
||||
else {
|
||||
fuse(unphase, 0, duration*PHASEDURATION, AFTER);
|
||||
turn_on(player, CANINWALL);
|
||||
}
|
||||
msg("You feel %slight-headed!",
|
||||
blessed ? "very " : "");
|
||||
}
|
||||
when P_FLY: {
|
||||
int duration;
|
||||
bool say_message;
|
||||
|
||||
say_message = TRUE;
|
||||
|
||||
if (blessed) duration = 3;
|
||||
else duration = 1;
|
||||
|
||||
if (on(player, ISFLY)) {
|
||||
if (find_slot(land))
|
||||
lengthen(land, duration*FLYTIME);
|
||||
else {
|
||||
msg("Nothing happens."); /* Flying by cloak */
|
||||
say_message = FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
fuse(land, 0, duration*FLYTIME, AFTER);
|
||||
turn_on(player, ISFLY);
|
||||
}
|
||||
if (say_message) {
|
||||
if (is_potion) p_know[P_FLY] = TRUE;
|
||||
msg("You feel %slighter than air!", blessed ? "much " : "");
|
||||
}
|
||||
}
|
||||
when P_RAISE:
|
||||
if (cursed) lower_level(D_POTION);
|
||||
else {
|
||||
msg("You suddenly feel %smore skillful",
|
||||
blessed ? "much " : "");
|
||||
p_know[P_RAISE] = TRUE;
|
||||
raise_level();
|
||||
if (blessed) raise_level();
|
||||
}
|
||||
when P_HASTE:
|
||||
if (cursed) { /* Slow player down */
|
||||
add_slow();
|
||||
}
|
||||
else {
|
||||
add_haste(blessed);
|
||||
if (is_potion) p_know[P_HASTE] = TRUE;
|
||||
}
|
||||
when P_RESTORE: {
|
||||
register int i, howmuch, strength_tally;
|
||||
|
||||
msg("Hey, this tastes great. It make you feel %swarm all over.",
|
||||
blessed ? "really " : "");
|
||||
howmuch = blessed ? 2 : 1;
|
||||
|
||||
for (i=0; i<NUMABILITIES; i++) {
|
||||
if (i == A_STRENGTH) {
|
||||
if (lost_str) {
|
||||
if (lost_str > howmuch) {
|
||||
lost_str -= howmuch;
|
||||
|
||||
/*
|
||||
* Save the lost strength. We have to set
|
||||
* temporarilty set it to 0 so that res_strength
|
||||
* will not restore it.
|
||||
*/
|
||||
strength_tally = lost_str;
|
||||
lost_str = 0;
|
||||
res_strength(howmuch);
|
||||
lost_str = strength_tally;
|
||||
}
|
||||
else {
|
||||
lost_str = 0;
|
||||
extinguish(res_strength);
|
||||
res_strength(howmuch);
|
||||
}
|
||||
}
|
||||
else res_strength(howmuch);
|
||||
}
|
||||
else res_abil[i](howmuch);
|
||||
}
|
||||
}
|
||||
when P_INVIS:
|
||||
if (off(player, ISINVIS)) {
|
||||
turn_on(player, ISINVIS);
|
||||
msg("You have a tingling feeling all over your body");
|
||||
fuse(appear, 0, blessed ? GONETIME*3 : GONETIME, AFTER);
|
||||
PLAYER = IPLAYER;
|
||||
light(&hero);
|
||||
}
|
||||
else {
|
||||
if (find_slot(appear)) {
|
||||
msg("Your tingling feeling surges.");
|
||||
lengthen(appear, blessed ? GONETIME*3 : GONETIME);
|
||||
}
|
||||
else msg("Nothing happens."); /* Using cloak */
|
||||
}
|
||||
|
||||
when P_FFIND:
|
||||
{
|
||||
register struct linked_list *nitem;
|
||||
register struct object *nobj;
|
||||
bool show;
|
||||
|
||||
show = FALSE;
|
||||
wclear(hw);
|
||||
for (nitem = lvl_obj; nitem != NULL; nitem = next(nitem)) {
|
||||
nobj = OBJPTR(nitem);
|
||||
if (nobj->o_type == FOOD) {
|
||||
show = TRUE;
|
||||
mvwaddch(hw, nobj->o_pos.y, nobj->o_pos.x, FOOD);
|
||||
}
|
||||
}
|
||||
for (nitem = mlist; nitem != NULL; nitem = next(nitem)) {
|
||||
register struct linked_list *pitem;
|
||||
register struct thing *th;
|
||||
|
||||
th = THINGPTR(nitem);
|
||||
if (on(*th, NODETECT)) continue;
|
||||
for(pitem = th->t_pack; pitem != NULL; pitem = next(pitem)){
|
||||
nobj = OBJPTR(pitem);
|
||||
if (nobj->o_type == FOOD) {
|
||||
show = TRUE;
|
||||
mvwaddch(hw, th->t_pos.y, th->t_pos.x, FOOD);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (show) {
|
||||
if (is_potion) p_know[P_FFIND] = TRUE;
|
||||
msg("Your nose tingles.");
|
||||
msg("You sense the presence of food on this level.");
|
||||
waddstr(msgw, morestr);
|
||||
clearok(msgw, FALSE);
|
||||
draw(msgw);
|
||||
overlay(hw,cw);
|
||||
draw(cw);
|
||||
wait_for(' ');
|
||||
msg("");
|
||||
}
|
||||
else
|
||||
msg("You have a strange feeling for a moment, then it passes.");
|
||||
}
|
||||
|
||||
when P_SKILL:
|
||||
if (cursed) {
|
||||
msg("You feel less skillful.");
|
||||
|
||||
/* Does he currently have an artifical skill? */
|
||||
if (!find_slot(unskill)) { /* No skill */
|
||||
pstats.s_lvladj = -2;
|
||||
pstats.s_lvl += pstats.s_lvladj;
|
||||
fuse(unskill, 0, SKILLDURATION, AFTER);
|
||||
}
|
||||
else { /* Has an artifical skill */
|
||||
/* Is the skill beneficial? */
|
||||
if (pstats.s_lvladj > 0) {
|
||||
/* Decrease the previous skill advantage */
|
||||
pstats.s_lvl -= 2;
|
||||
pstats.s_lvladj -= 2;
|
||||
|
||||
/* If there is now a negative skill, lengthen time */
|
||||
if (pstats.s_lvladj < 0)
|
||||
lengthen(unskill, SKILLDURATION);
|
||||
|
||||
/* If there is no skill advantage, unfuse us */
|
||||
else if (pstats.s_lvladj == 0) extinguish(unskill);
|
||||
}
|
||||
else { /* Already bad */
|
||||
/* Make it a little worse, and lengthen it */
|
||||
pstats.s_lvl--;
|
||||
pstats.s_lvladj--;
|
||||
lengthen(unskill, SKILLDURATION);
|
||||
}
|
||||
}
|
||||
|
||||
/* Is our level too low now? */
|
||||
if (pstats.s_lvl < 1) death(D_POTION);
|
||||
}
|
||||
else {
|
||||
int adjust;
|
||||
|
||||
msg("You feel more skillful.");
|
||||
|
||||
/* Get the adjustment */
|
||||
adjust = blessed ? 3 : 2;
|
||||
|
||||
/* Does he currently have an artifical skill? */
|
||||
if (!find_slot(unskill)) {
|
||||
pstats.s_lvladj = adjust;
|
||||
pstats.s_lvl += pstats.s_lvladj;
|
||||
fuse(unskill, 0,
|
||||
blessed ? SKILLDURATION*2 : SKILLDURATION, AFTER);
|
||||
}
|
||||
else { /* Has an artifical skill */
|
||||
/* Is the skill detrimental? */
|
||||
if (pstats.s_lvladj < 0) {
|
||||
/* Decrease the previous skill advantage */
|
||||
pstats.s_lvl += adjust;
|
||||
pstats.s_lvladj += adjust;
|
||||
|
||||
/* If there is now a positive skill, lengthen time */
|
||||
if (pstats.s_lvladj < 0)
|
||||
lengthen(unskill, SKILLDURATION);
|
||||
|
||||
/* If there is no skill advantage, unfuse us */
|
||||
else if (pstats.s_lvladj == 0) extinguish(unskill);
|
||||
}
|
||||
else { /* Already good */
|
||||
/*
|
||||
* Make the skill the maximum of the current good
|
||||
* skill and what the adjust would give him.
|
||||
*/
|
||||
pstats.s_lvl -= pstats.s_lvladj;
|
||||
pstats.s_lvladj = max(pstats.s_lvladj, adjust);
|
||||
pstats.s_lvl += pstats.s_lvladj;
|
||||
lengthen(unskill,
|
||||
blessed ? SKILLDURATION*2 : SKILLDURATION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when P_FIRE: {
|
||||
int duration;
|
||||
bool say_message;
|
||||
|
||||
say_message = TRUE;
|
||||
|
||||
if (blessed) duration = 3;
|
||||
else duration = 1;
|
||||
|
||||
if (on(player, NOFIRE)) {
|
||||
if (find_slot(nofire))
|
||||
lengthen(nofire, duration*FIRETIME);
|
||||
else {
|
||||
msg("Nothing happens."); /* has on a ring */
|
||||
say_message = FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
fuse(nofire, 0, duration*FIRETIME, AFTER);
|
||||
turn_on(player, NOFIRE);
|
||||
}
|
||||
if (say_message) {
|
||||
if (is_potion) p_know[P_FIRE] = TRUE;
|
||||
msg("You feel %sfire resistant", blessed ? "very " : "");
|
||||
}
|
||||
}
|
||||
when P_COLD: {
|
||||
int duration;
|
||||
bool say_message;
|
||||
|
||||
say_message = TRUE;
|
||||
|
||||
if (blessed) duration = 3;
|
||||
else duration = 1;
|
||||
|
||||
if (on(player, NOCOLD)) {
|
||||
if (find_slot(nocold))
|
||||
lengthen(nocold, duration*COLDTIME);
|
||||
else {
|
||||
msg("Nothing happens."); /* has on a ring */
|
||||
say_message = FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
fuse(nocold, 0, duration*COLDTIME, AFTER);
|
||||
turn_on(player, NOCOLD);
|
||||
}
|
||||
if (say_message) {
|
||||
if (is_potion) p_know[P_COLD] = TRUE;
|
||||
msg("You feel %scold resistant", blessed ? "very " : "");
|
||||
}
|
||||
}
|
||||
when P_LIGHTNING: {
|
||||
int duration;
|
||||
bool say_message;
|
||||
|
||||
say_message = TRUE;
|
||||
|
||||
if (blessed) duration = 3;
|
||||
else duration = 1;
|
||||
|
||||
if (on(player, NOBOLT)) {
|
||||
if (find_slot(nobolt))
|
||||
lengthen(nobolt, duration*BOLTTIME);
|
||||
}
|
||||
else {
|
||||
fuse(nobolt, 0, duration*BOLTTIME, AFTER);
|
||||
turn_on(player, NOBOLT);
|
||||
}
|
||||
if (say_message)
|
||||
msg("Your skin turns %sblue!", blessed ? "very " : "");
|
||||
}
|
||||
when P_POISON:
|
||||
if (!save(VS_POISON, &player, -2)) {
|
||||
msg("You feel very sick now.");
|
||||
pstats.s_hpt /= 2;
|
||||
if (!ISWEARING(R_SUSABILITY))
|
||||
pstats.s_const--;
|
||||
}
|
||||
else {
|
||||
msg("You feel sick now.");
|
||||
pstats.s_hpt -= (pstats.s_hpt / 4);
|
||||
}
|
||||
if (pstats.s_const <= 0 || pstats.s_hpt <= 0)
|
||||
death(D_POISON);
|
||||
otherwise:
|
||||
msg("What an odd tasting potion!");
|
||||
return;
|
||||
}
|
||||
status(FALSE);
|
||||
if (is_potion && item && p_know[which] && p_guess[which])
|
||||
{
|
||||
free(p_guess[which]);
|
||||
p_guess[which] = NULL;
|
||||
}
|
||||
else if (is_potion &&
|
||||
!p_know[which] &&
|
||||
item &&
|
||||
askme &&
|
||||
(flags & ISKNOW) == 0 &&
|
||||
(flags & ISPOST) == 0 &&
|
||||
p_guess[which] == NULL) {
|
||||
nameitem(item, FALSE);
|
||||
}
|
||||
if (item != NULL) o_discard(item);
|
||||
updpack(TRUE, &player);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* res_dexterity:
|
||||
* Restore player's dexterity
|
||||
* if called with zero the restore fully
|
||||
*/
|
||||
|
||||
void
|
||||
res_dexterity(howmuch)
|
||||
int howmuch;
|
||||
{
|
||||
short save_max;
|
||||
int ring_str;
|
||||
|
||||
if (howmuch < 0) return;
|
||||
|
||||
/* Discount the ring value */
|
||||
ring_str = ring_value(R_ADDHIT);
|
||||
pstats.s_dext -= ring_str;
|
||||
|
||||
if (pstats.s_dext < max_stats.s_dext ) {
|
||||
if (howmuch == 0)
|
||||
pstats.s_dext = max_stats.s_dext;
|
||||
else
|
||||
pstats.s_dext = min(pstats.s_dext+howmuch, max_stats.s_dext);
|
||||
}
|
||||
|
||||
/* Redo the rings */
|
||||
if (ring_str) {
|
||||
save_max = max_stats.s_dext;
|
||||
pstats.s_dext += ring_str;
|
||||
max_stats.s_dext = save_max;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* res_intelligence:
|
||||
* Restore player's intelligence
|
||||
*/
|
||||
|
||||
void
|
||||
res_intelligence(howmuch)
|
||||
int howmuch;
|
||||
{
|
||||
short save_max;
|
||||
int ring_str;
|
||||
|
||||
if (howmuch <= 0) return;
|
||||
|
||||
/* Discount the ring value */
|
||||
ring_str = ring_value(R_ADDINTEL);
|
||||
pstats.s_intel -= ring_str;
|
||||
|
||||
pstats.s_intel = min(pstats.s_intel + howmuch, max_stats.s_intel);
|
||||
|
||||
/* Redo the rings */
|
||||
if (ring_str) {
|
||||
save_max = max_stats.s_intel;
|
||||
pstats.s_intel += ring_str;
|
||||
max_stats.s_intel = save_max;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* res_wisdom:
|
||||
* Restore player's wisdom
|
||||
*/
|
||||
|
||||
void
|
||||
res_wisdom(howmuch)
|
||||
int howmuch;
|
||||
{
|
||||
short save_max;
|
||||
int ring_str;
|
||||
|
||||
if (howmuch <= 0) return;
|
||||
|
||||
/* Discount the ring value */
|
||||
ring_str = ring_value(R_ADDWISDOM);
|
||||
pstats.s_wisdom -= ring_str;
|
||||
|
||||
pstats.s_wisdom = min(pstats.s_wisdom + howmuch, max_stats.s_wisdom);
|
||||
|
||||
/* Redo the rings */
|
||||
if (ring_str) {
|
||||
save_max = max_stats.s_wisdom;
|
||||
pstats.s_wisdom += ring_str;
|
||||
max_stats.s_wisdom = save_max;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* res_constitution:
|
||||
* Restore the players constitution.
|
||||
*/
|
||||
|
||||
void
|
||||
res_constitution(howmuch)
|
||||
int howmuch;
|
||||
{
|
||||
if (howmuch > 0)
|
||||
pstats.s_const = min(pstats.s_const + howmuch, max_stats.s_const);
|
||||
}
|
||||
|
||||
/*
|
||||
* res_charisma:
|
||||
* Restore the players charisma.
|
||||
*/
|
||||
|
||||
void
|
||||
res_charisma(howmuch)
|
||||
int howmuch;
|
||||
{
|
||||
if (howmuch > 0)
|
||||
pstats.s_charisma =
|
||||
min(pstats.s_charisma + howmuch, max_stats.s_charisma);
|
||||
}
|
||||
161
arogue7/rings.c
Normal file
161
arogue7/rings.c
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* rings.c - routines dealing specifically with rings
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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 "curses.h"
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* routines dealing specifically with rings
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* how much food does this ring use up?
|
||||
*/
|
||||
ring_eat(hand)
|
||||
register int hand;
|
||||
{
|
||||
if (cur_ring[hand] == NULL)
|
||||
return 0;
|
||||
switch (cur_ring[hand]->o_which) {
|
||||
case R_VAMPREGEN:
|
||||
return 3;
|
||||
case R_REGEN:
|
||||
return 2;
|
||||
case R_HEALTH:
|
||||
case R_SUSABILITY:
|
||||
return 1;
|
||||
case R_SEARCH:
|
||||
case R_SEEINVIS:
|
||||
return (rnd(100) < 33);
|
||||
case R_DIGEST:
|
||||
if (cur_ring[hand]->o_ac >= 0)
|
||||
return (-(cur_ring[hand]->o_ac)-1);
|
||||
else
|
||||
return (-(cur_ring[hand]->o_ac));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ring_on(item)
|
||||
register struct linked_list *item;
|
||||
{
|
||||
register struct object *obj;
|
||||
register int save_max;
|
||||
|
||||
obj = OBJPTR(item);
|
||||
|
||||
/*
|
||||
* Calculate the effect it has on the poor guy.
|
||||
*/
|
||||
switch (obj->o_which)
|
||||
{
|
||||
case R_ADDSTR:
|
||||
save_max = max_stats.s_str;
|
||||
chg_str(obj->o_ac);
|
||||
max_stats.s_str = save_max;
|
||||
when R_ADDHIT:
|
||||
pstats.s_dext += obj->o_ac;
|
||||
when R_ADDINTEL:
|
||||
pstats.s_intel += obj->o_ac;
|
||||
when R_ADDWISDOM:
|
||||
pstats.s_wisdom += obj->o_ac;
|
||||
when R_SEEINVIS:
|
||||
turn_on(player, CANSEE);
|
||||
msg("Your eyes begin to tingle");
|
||||
light(&hero);
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
when R_AGGR:
|
||||
aggravate(TRUE, TRUE);
|
||||
when R_WARMTH:
|
||||
turn_on(player, NOCOLD);
|
||||
when R_FIRE:
|
||||
turn_on(player, NOFIRE);
|
||||
when R_LIGHT: {
|
||||
if(roomin(&hero) != NULL) {
|
||||
light(&hero);
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
}
|
||||
}
|
||||
when R_SEARCH:
|
||||
daemon(ring_search, 0, AFTER);
|
||||
when R_TELEPORT:
|
||||
daemon(ring_teleport, 0, AFTER);
|
||||
}
|
||||
status(FALSE);
|
||||
if (r_know[obj->o_which] && r_guess[obj->o_which])
|
||||
{
|
||||
free(r_guess[obj->o_which]);
|
||||
r_guess[obj->o_which] = NULL;
|
||||
}
|
||||
else if (!r_know[obj->o_which] &&
|
||||
askme &&
|
||||
(obj->o_flags & ISKNOW) == 0 &&
|
||||
r_guess[obj->o_which] == NULL) {
|
||||
nameitem(item, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* print ring bonuses
|
||||
*/
|
||||
char *
|
||||
ring_num(obj)
|
||||
register struct object *obj;
|
||||
{
|
||||
static char buf[5];
|
||||
|
||||
if (!(obj->o_flags & ISKNOW))
|
||||
return "";
|
||||
switch (obj->o_which)
|
||||
{
|
||||
case R_PROTECT:
|
||||
case R_ADDSTR:
|
||||
case R_ADDDAM:
|
||||
case R_ADDHIT:
|
||||
case R_ADDINTEL:
|
||||
case R_ADDWISDOM:
|
||||
case R_DIGEST:
|
||||
buf[0] = ' ';
|
||||
strcpy(&buf[1], num(obj->o_ac, 0));
|
||||
when R_AGGR:
|
||||
case R_LIGHT:
|
||||
case R_CARRY:
|
||||
case R_TELEPORT:
|
||||
if (obj->o_flags & ISCURSED)
|
||||
return " cursed";
|
||||
else
|
||||
return "";
|
||||
otherwise:
|
||||
return "";
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the effect of the specified ring
|
||||
*/
|
||||
ring_value(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(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;
|
||||
return(result);
|
||||
}
|
||||
889
arogue7/rip.c
Normal file
889
arogue7/rip.c
Normal file
|
|
@ -0,0 +1,889 @@
|
|||
/*
|
||||
* rip.c - File for the fun ends Death or a total win
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Print flags for scoring */
|
||||
#define REALLIFE 1 /* Print out machine and logname */
|
||||
#define EDITSCORE 2 /* Edit the current score file */
|
||||
#define ADDSCORE 3 /* Add a new score */
|
||||
|
||||
#define NAMELEN 80
|
||||
|
||||
/*
|
||||
* File for the fun ends
|
||||
* Death or a total win
|
||||
*
|
||||
*/
|
||||
|
||||
#include "curses.h"
|
||||
#ifdef BSD
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include "mach_dep.h"
|
||||
#include "network.h"
|
||||
#include "rogue.h"
|
||||
#ifdef PC7300
|
||||
#include "sys/window.h"
|
||||
extern struct uwdata wdata, oldwin;
|
||||
extern char oldtext[WTXTNUM][WTXTLEN];
|
||||
#endif
|
||||
|
||||
#ifdef NUMNET
|
||||
/* Network machines (for mutual score keeping) */
|
||||
static struct network Network[NUMNET] = {
|
||||
{ "ihwpt", "/t1/michael/bin/rg" },
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If you change this structure, change the compatibility routines
|
||||
* scoreout() and scorein() to reflect the change. Also update SCORELEN.
|
||||
*/
|
||||
struct sc_ent {
|
||||
unsigned long sc_score;
|
||||
char sc_name[NAMELEN];
|
||||
char sc_system[SYSLEN];
|
||||
char sc_login[LOGLEN];
|
||||
short sc_flags;
|
||||
short sc_level;
|
||||
short sc_ctype;
|
||||
short sc_monster;
|
||||
short sc_quest;
|
||||
};
|
||||
#define SCORELEN \
|
||||
(sizeof(unsigned long) + NAMELEN + SYSLEN + LOGLEN + 5*sizeof(short))
|
||||
|
||||
static char *rip[] = {
|
||||
" __________",
|
||||
" / \\",
|
||||
" / REST \\",
|
||||
" / IN \\",
|
||||
" / PEACE \\",
|
||||
" / \\",
|
||||
" | |",
|
||||
" | |",
|
||||
" | killed by |",
|
||||
" | |",
|
||||
" | 1984 |",
|
||||
" *| * * * | *",
|
||||
" ________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______",
|
||||
0
|
||||
};
|
||||
|
||||
char *killname();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
byebye(sig)
|
||||
int sig;
|
||||
{
|
||||
if (!isendwin()) {
|
||||
clear();
|
||||
endwin();
|
||||
}
|
||||
#ifdef PC7300
|
||||
endhardwin();
|
||||
#endif
|
||||
printf("\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* death:
|
||||
* Do something really fun when he dies
|
||||
*/
|
||||
|
||||
death(monst)
|
||||
register short monst;
|
||||
{
|
||||
register char **dp = rip, *killer;
|
||||
register struct tm *lt;
|
||||
time_t date;
|
||||
char buf[LINELEN];
|
||||
struct tm *localtime();
|
||||
|
||||
time(&date);
|
||||
lt = localtime(&date);
|
||||
clear();
|
||||
move(8, 0);
|
||||
while (*dp)
|
||||
printw("%s\n", *dp++);
|
||||
mvaddstr(14, 28-((strlen(whoami)+1)/2), whoami);
|
||||
sprintf(buf, "%lu Points", pstats.s_exp );
|
||||
mvaddstr(15, 28-((strlen(buf)+1)/2), buf);
|
||||
killer = killname(monst);
|
||||
mvaddstr(17, 28-((strlen(killer)+1)/2), killer);
|
||||
mvaddstr(18, 26, (sprintf(prbuf, "%4d", 1900+lt->tm_year), prbuf));
|
||||
move(lines-1, 0);
|
||||
refresh();
|
||||
score(pstats.s_exp, KILLED, monst);
|
||||
endwin();
|
||||
#ifdef PC7300
|
||||
endhardwin();
|
||||
#endif
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#ifdef PC7300
|
||||
/*
|
||||
* Restore window characteristics on a hard window terminal (PC7300).
|
||||
*/
|
||||
endhardwin()
|
||||
{
|
||||
register int i;
|
||||
struct utdata labelbuf;
|
||||
|
||||
/* Restore the old window size */
|
||||
if (oldwin.uw_width) ioctl(1, WIOCSETD, &oldwin);
|
||||
|
||||
/* Restore the old window text */
|
||||
for (i=0; i<WTXTNUM; i++) {
|
||||
labelbuf.ut_num = i;
|
||||
strcpy(labelbuf.ut_text, oldtext[i]);
|
||||
ioctl(1, WIOCSETTEXT, &labelbuf);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
char *
|
||||
killname(monst)
|
||||
register short monst;
|
||||
{
|
||||
static char mons_name[LINELEN];
|
||||
int i;
|
||||
|
||||
if (monst > NUMMONST) return("a strange monster");
|
||||
|
||||
if (monst >= 0) {
|
||||
switch (monsters[monst].m_name[0]) {
|
||||
case 'a':
|
||||
case 'e':
|
||||
case 'i':
|
||||
case 'o':
|
||||
case 'u':
|
||||
sprintf(mons_name, "an %s", monsters[monst].m_name);
|
||||
break;
|
||||
default:
|
||||
sprintf(mons_name, "a %s", monsters[monst].m_name);
|
||||
}
|
||||
return(mons_name);
|
||||
}
|
||||
for (i = 0; i< DEATHNUM; i++) {
|
||||
if (deaths[i].reason == monst)
|
||||
break;
|
||||
}
|
||||
if (i >= DEATHNUM)
|
||||
return ("strange death");
|
||||
return (deaths[i].name);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* score -- figure score and post it.
|
||||
*/
|
||||
|
||||
/* VARARGS2 */
|
||||
score(amount, flags, monst)
|
||||
unsigned long amount;
|
||||
short monst;
|
||||
{
|
||||
static struct sc_ent top_ten[NUMSCORE];
|
||||
register struct sc_ent *scp;
|
||||
register int i;
|
||||
register struct sc_ent *sc2;
|
||||
register int outfd;
|
||||
register char *killer;
|
||||
register int prflags = 0;
|
||||
register int fd;
|
||||
short upquest, wintype, uplevel, uptype; /* For network updating */
|
||||
char upsystem[SYSLEN], uplogin[LOGLEN];
|
||||
char *thissys; /* Holds the name of this system */
|
||||
char *compatstr=NULL; /* Holds scores for writing compatible score files */
|
||||
char scoreline[100];
|
||||
#define REASONLEN 3
|
||||
static char *reason[] = {
|
||||
"killed",
|
||||
"quit",
|
||||
"A total winner",
|
||||
"somehow left",
|
||||
};
|
||||
char *packend;
|
||||
|
||||
signal(SIGINT, byebye);
|
||||
if (flags != WINNER && flags != SCOREIT && flags != UPDATE) {
|
||||
if (flags == CHICKEN)
|
||||
packend = "when you quit";
|
||||
else
|
||||
{
|
||||
packend = "at your untimely demise";
|
||||
mvaddstr(lines - 1, 0, retstr);
|
||||
refresh();
|
||||
getstr(prbuf);
|
||||
}
|
||||
showpack(packend);
|
||||
}
|
||||
purse = 0; /* Steal all the gold */
|
||||
|
||||
/*
|
||||
* Open file and read list
|
||||
*/
|
||||
|
||||
if ((fd = open(score_file, O_RDWR | O_CREAT, 0666)) < 0) return;
|
||||
outfd = fd;
|
||||
|
||||
#ifndef SYSTEM
|
||||
thissys = md_gethostname();
|
||||
#else
|
||||
thissys = SYSTEM;
|
||||
#endif
|
||||
|
||||
for (scp = top_ten; scp <= &top_ten[NUMSCORE-1]; scp++)
|
||||
{
|
||||
scp->sc_score = 0L;
|
||||
for (i = 0; i < NAMELEN; i++)
|
||||
scp->sc_name[i] = rnd(255);
|
||||
scp->sc_quest= RN;
|
||||
scp->sc_flags = RN;
|
||||
scp->sc_level = RN;
|
||||
scp->sc_monster = RN;
|
||||
scp->sc_ctype = 0;
|
||||
strncpy(scp->sc_system, thissys, SYSLEN);
|
||||
scp->sc_login[0] = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is a SCOREIT optin (rogue -s), don't call byebye. The
|
||||
* endwin() call in byebye() will result in a core dump.
|
||||
*/
|
||||
if (flags == SCOREIT) signal(SIGINT, SIG_DFL);
|
||||
else signal(SIGINT, byebye);
|
||||
|
||||
if (flags != SCOREIT && flags != UPDATE)
|
||||
{
|
||||
mvaddstr(lines - 1, 0, retstr);
|
||||
refresh();
|
||||
fflush(stdout);
|
||||
getstr(prbuf);
|
||||
}
|
||||
|
||||
/* Check for special options */
|
||||
if (strcmp(prbuf, "names") == 0)
|
||||
prflags = REALLIFE;
|
||||
#ifdef WIZARD
|
||||
else if (wizard) {
|
||||
if (strcmp(prbuf, "edit") == 0) prflags = EDITSCORE;
|
||||
else if (strcmp(prbuf, "add") == 0) {
|
||||
prflags = ADDSCORE;
|
||||
waswizard = FALSE; /* We want the new score recorded */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Read the score and convert it to a compatible format */
|
||||
for(i = 0; i < NUMSCORE; i++)
|
||||
{
|
||||
encread(top_ten[i].sc_name, NAMELEN, fd);
|
||||
encread(top_ten[i].sc_system, SYSLEN, fd);
|
||||
encread(top_ten[i].sc_login, LOGLEN, fd);
|
||||
encread(scoreline, 100, fd);
|
||||
sscanf(scoreline, " %lu %hd %hd %hd %hd %hd \n",
|
||||
&top_ten[i].sc_score, &top_ten[i].sc_flags,
|
||||
&top_ten[i].sc_level, &top_ten[i].sc_ctype,
|
||||
&top_ten[i].sc_monster, &top_ten[i].sc_quest
|
||||
);
|
||||
}
|
||||
|
||||
/* Get some values if this is an update */
|
||||
if (flags == UPDATE) {
|
||||
unsigned long netread();
|
||||
int errcheck, errors = 0;
|
||||
|
||||
upquest = (short) netread(&errcheck, sizeof(short), stdin);
|
||||
if (errcheck) errors++;
|
||||
|
||||
if (fread(whoami, 1, NAMELEN, stdin) != NAMELEN) errors++;
|
||||
|
||||
wintype = (short) netread(&errcheck, sizeof(short), stdin);
|
||||
if (errcheck) errors++;
|
||||
|
||||
uplevel = (short) netread(&errcheck, sizeof(short), stdin);
|
||||
if (errcheck) errors++;
|
||||
|
||||
uptype = (short) netread(&errcheck, sizeof(short), stdin);
|
||||
if (errcheck) errors++;
|
||||
|
||||
if (fread(upsystem, 1, SYSLEN, stdin) != SYSLEN)
|
||||
errors++;
|
||||
if (fread(uplogin, 1, LOGLEN, stdin) != LOGLEN)
|
||||
errors++;
|
||||
|
||||
if (errors) {
|
||||
close(outfd);
|
||||
free(compatstr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert player in list if need be
|
||||
*/
|
||||
if (!waswizard) {
|
||||
char *login;
|
||||
|
||||
if (flags != UPDATE) {
|
||||
login = md_getusername();
|
||||
}
|
||||
|
||||
if (flags == UPDATE)
|
||||
(void) update(top_ten, amount, upquest, whoami, wintype,
|
||||
uplevel, monst, uptype, upsystem, uplogin);
|
||||
else {
|
||||
#ifdef WIZARD
|
||||
if (prflags == ADDSCORE) { /* Overlay characteristic by new ones */
|
||||
char buffer[LINELEN];
|
||||
|
||||
clear();
|
||||
mvaddstr(1, 0, "Score: ");
|
||||
mvaddstr(2, 0, "Quest (number): ");
|
||||
mvaddstr(3, 0, "Name: ");
|
||||
mvaddstr(4, 0, "System: ");
|
||||
mvaddstr(5, 0, "Login: ");
|
||||
mvaddstr(6, 0, "Level: ");
|
||||
mvaddstr(7, 0, "Char type: ");
|
||||
mvaddstr(8, 0, "Result: ");
|
||||
|
||||
/* Get the score */
|
||||
move(1, 7);
|
||||
get_str(buffer, stdscr);
|
||||
amount = atol(buffer);
|
||||
|
||||
/* Get the character's quest -- must be a number */
|
||||
move(2, 16);
|
||||
get_str(buffer, stdscr);
|
||||
quest_item = atoi(buffer);
|
||||
|
||||
/* Get the character's name */
|
||||
move(3, 6);
|
||||
get_str(buffer, stdscr);
|
||||
strncpy(whoami, buffer, NAMELEN);
|
||||
|
||||
/* Get the system */
|
||||
move(4, 8);
|
||||
get_str(buffer, stdscr);
|
||||
strncpy(thissys, buffer, SYSLEN);
|
||||
|
||||
/* Get the login */
|
||||
move(5, 7);
|
||||
get_str(buffer, stdscr);
|
||||
strncpy(login, buffer, LOGLEN);
|
||||
|
||||
/* Get the level */
|
||||
move(6, 7);
|
||||
get_str(buffer, stdscr);
|
||||
level = max_level = (short) atoi(buffer);
|
||||
|
||||
/* Get the character type */
|
||||
move(7, 11);
|
||||
get_str(buffer, stdscr);
|
||||
for (i=0; i<NUM_CHARTYPES; i++) {
|
||||
if (EQSTR(buffer, char_class[i].name, strlen(buffer)))
|
||||
break;
|
||||
}
|
||||
player.t_ctype = i;
|
||||
|
||||
/* Get the win type */
|
||||
move(8, 8);
|
||||
get_str(buffer, stdscr);
|
||||
switch (buffer[0]) {
|
||||
case 'W':
|
||||
case 'w':
|
||||
case 'T':
|
||||
case 't':
|
||||
flags = WINNER;
|
||||
break;
|
||||
|
||||
case 'Q':
|
||||
case 'q':
|
||||
flags = CHICKEN;
|
||||
break;
|
||||
|
||||
case 'k':
|
||||
case 'K':
|
||||
default:
|
||||
flags = KILLED;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get the monster if player was killed */
|
||||
if (flags == KILLED) {
|
||||
mvaddstr(9, 0, "Death type: ");
|
||||
get_str(buffer, stdscr);
|
||||
if (buffer[0] == 'M' || buffer[0] == 'm')
|
||||
do {
|
||||
monst = makemonster(TRUE, "Editing", "choose");
|
||||
} while (monst < 0); /* Force a choice */
|
||||
else monst = getdeath();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (update(top_ten, amount, (short) quest_item, whoami, flags,
|
||||
(flags == WINNER) ? (short) max_level : (short) level,
|
||||
monst, player.t_ctype, thissys, login)
|
||||
#ifdef NUMNET
|
||||
&& fork() == 0 /* Spin off network process */
|
||||
#endif
|
||||
) {
|
||||
#ifdef NUMNET
|
||||
/* Send this update to the other systems in the network */
|
||||
int i, j;
|
||||
char cmd[256]; /* Command for remote execution */
|
||||
FILE *rmf, *popen(); /* For input to remote command */
|
||||
|
||||
for (i=0; i<NUMNET; i++)
|
||||
if (Network[i].system[0] != '!' &&
|
||||
strcmp(Network[i].system, thissys)) {
|
||||
sprintf(cmd, NETCOMMAND,
|
||||
Network[i].system, Network[i].rogue);
|
||||
|
||||
/* Execute the command */
|
||||
if ((rmf=popen(cmd, "w")) != NULL) {
|
||||
unsigned long temp; /* Temporary value */
|
||||
|
||||
/* Write out the parameters */
|
||||
(void) netwrite((unsigned long) amount,
|
||||
sizeof(unsigned long), rmf);
|
||||
|
||||
(void) netwrite((unsigned long) monst,
|
||||
sizeof(short), rmf);
|
||||
|
||||
(void) netwrite((unsigned long) quest_item,
|
||||
sizeof(short), rmf);
|
||||
|
||||
(void) fwrite(whoami, 1, strlen(whoami), rmf);
|
||||
for (j=strlen(whoami); j<NAMELEN; j++)
|
||||
putc('\0', rmf);
|
||||
|
||||
(void) netwrite((unsigned long) flags,
|
||||
sizeof(short), rmf);
|
||||
|
||||
temp = (unsigned long)
|
||||
(flags==WINNER ? max_level : level);
|
||||
(void) netwrite(temp, sizeof(short), rmf);
|
||||
|
||||
(void) netwrite((unsigned long) player.t_ctype,
|
||||
sizeof(short), rmf);
|
||||
|
||||
(void) fwrite(thissys, 1,
|
||||
strlen(thissys), rmf);
|
||||
for (j=strlen(thissys); j<SYSLEN; j++)
|
||||
putc('\0', rmf);
|
||||
|
||||
(void) fwrite(login, 1, strlen(login), rmf);
|
||||
for (j=strlen(login); j<LOGLEN; j++)
|
||||
putc('\0', rmf);
|
||||
|
||||
/* Close off the command */
|
||||
(void) pclose(rmf);
|
||||
}
|
||||
}
|
||||
_exit(0); /* Exit network process */
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* SCOREIT -- rogue -s option. Never started curses if this option.
|
||||
* UPDATE -- network scoring update. Never started curses if this option.
|
||||
* EDITSCORE -- want to delete or change a score.
|
||||
*/
|
||||
/* if (flags != SCOREIT && flags != UPDATE && prflags != EDITSCORE)
|
||||
endwin(); */
|
||||
|
||||
if (flags != UPDATE) {
|
||||
if (flags != SCOREIT) {
|
||||
clear();
|
||||
refresh();
|
||||
endwin();
|
||||
}
|
||||
/*
|
||||
* Print the list
|
||||
*/
|
||||
printf("\nTop %d Adventurers:\nRank Score\tName\n",
|
||||
NUMSCORE);
|
||||
for (scp = top_ten; scp <= &top_ten[NUMSCORE-1]; scp++) {
|
||||
const char *class;
|
||||
|
||||
if (scp->sc_score != 0) {
|
||||
class = char_class[scp->sc_ctype].name;
|
||||
|
||||
/* Make sure we have an in-bound reason */
|
||||
if (scp->sc_flags > REASONLEN) scp->sc_flags = REASONLEN;
|
||||
|
||||
printf("%3d %10lu\t%s (%s)", scp - top_ten + 1,
|
||||
scp->sc_score, scp->sc_name, class);
|
||||
|
||||
if (prflags == REALLIFE) printf(" [in real life %.*s!%.*s]",
|
||||
SYSLEN, scp->sc_system, LOGLEN, scp->sc_login);
|
||||
printf(":\n\t\t%s on level %d", reason[scp->sc_flags],
|
||||
scp->sc_level);
|
||||
|
||||
switch (scp->sc_flags) {
|
||||
case KILLED:
|
||||
printf(" by");
|
||||
killer = killname(scp->sc_monster);
|
||||
printf(" %s", killer);
|
||||
break;
|
||||
|
||||
case WINNER:
|
||||
printf(" with the %s",
|
||||
rel_magic[scp->sc_quest].mi_name);
|
||||
break;
|
||||
}
|
||||
|
||||
if (prflags == EDITSCORE)
|
||||
{
|
||||
fflush(stdout);
|
||||
getstr(prbuf);
|
||||
printf("\n");
|
||||
if (prbuf[0] == 'd') {
|
||||
for (sc2 = scp; sc2 < &top_ten[NUMSCORE-1]; sc2++)
|
||||
*sc2 = *(sc2 + 1);
|
||||
top_ten[NUMSCORE-1].sc_score = 0;
|
||||
for (i = 0; i < NAMELEN; i++)
|
||||
top_ten[NUMSCORE-1].sc_name[i] = rnd(255);
|
||||
top_ten[NUMSCORE-1].sc_flags = RN;
|
||||
top_ten[NUMSCORE-1].sc_level = RN;
|
||||
top_ten[NUMSCORE-1].sc_monster = RN;
|
||||
scp--;
|
||||
}
|
||||
else if (prbuf[0] == 'e') {
|
||||
printf("Death type: ");
|
||||
getstr(prbuf);
|
||||
if (prbuf[0] == 'M' || prbuf[0] == 'm')
|
||||
do {
|
||||
scp->sc_monster =
|
||||
makemonster(TRUE, "Editing", "choose");
|
||||
} while (scp->sc_monster < 0); /* Force a choice */
|
||||
else scp->sc_monster = getdeath();
|
||||
clear();
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
else printf("\n");
|
||||
}
|
||||
}
|
||||
if ((flags != SCOREIT) && (flags != UPDATE)) {
|
||||
printf("\n[Press return to exit]");
|
||||
fflush(stdout);
|
||||
fgets(prbuf,80,stdin);
|
||||
}
|
||||
/* if (prflags == EDITSCORE) endwin();*/ /* End editing windowing */
|
||||
}
|
||||
lseek(outfd, 0L, 0);
|
||||
/*
|
||||
* Update the list file
|
||||
*/
|
||||
|
||||
for(i = 0; i < NUMSCORE; i++)
|
||||
{
|
||||
memset(scoreline,0,100);
|
||||
encwrite(top_ten[i].sc_name, NAMELEN, outfd);
|
||||
encwrite(top_ten[i].sc_system, SYSLEN, outfd);
|
||||
encwrite(top_ten[i].sc_login, LOGLEN, outfd);
|
||||
sprintf(scoreline, " %lu %hd %hd %hd %hd %hd \n",
|
||||
top_ten[i].sc_score, top_ten[i].sc_flags,
|
||||
top_ten[i].sc_level, top_ten[i].sc_ctype,
|
||||
top_ten[i].sc_monster, top_ten[i].sc_quest);
|
||||
encwrite(scoreline,100,outfd);
|
||||
}
|
||||
|
||||
close(outfd);
|
||||
}
|
||||
|
||||
/*
|
||||
* scorein:
|
||||
* Convert a character string that has been translated from a
|
||||
* score file by scoreout() back to a score file structure.
|
||||
*/
|
||||
scorein(input, scores, num_bytes)
|
||||
unsigned char *input;
|
||||
struct sc_ent scores[];
|
||||
int num_bytes; /* Number of bytes of input that we want to convert */
|
||||
{
|
||||
register int i, j;
|
||||
unsigned long *lptr;
|
||||
unsigned short *sptr;
|
||||
unsigned char *cptr;
|
||||
|
||||
/* Convert a maximum of NUMSCORE entries */
|
||||
for (i=0; num_bytes > 0 && i < NUMSCORE; num_bytes -= SCORELEN, i++) {
|
||||
/* The long fields are first -- ordered low to high byte in input */
|
||||
lptr = &scores[i].sc_score;
|
||||
*lptr = ((unsigned long) *input++) & 0x000000ffL;
|
||||
*lptr |= (((unsigned long) *input++) << 8) & 0x0000ff00L;
|
||||
*lptr |= (((unsigned long) *input++) << 16) & 0x00ff0000L;
|
||||
*lptr |= (((unsigned long) *input++) << 24) & 0xff000000L;
|
||||
|
||||
/* The short fields are next -- ordered low to high byte in input */
|
||||
sptr = (unsigned short *) &scores[i].sc_flags;
|
||||
*sptr = ((unsigned short) *input++) & 0xff;
|
||||
*sptr |= (((unsigned short) *input++) << 8) & 0xff00;
|
||||
|
||||
sptr = (unsigned short *) &scores[i].sc_level;
|
||||
*sptr = ((unsigned short) *input++) & 0xff;
|
||||
*sptr |= (((unsigned short) *input++) << 8) & 0xff00;
|
||||
|
||||
sptr = (unsigned short *) &scores[i].sc_ctype;
|
||||
*sptr = ((unsigned short) *input++) & 0xff;
|
||||
*sptr |= (((unsigned short) *input++) << 8) & 0xff00;
|
||||
|
||||
sptr = (unsigned short *) &scores[i].sc_monster;
|
||||
*sptr = ((unsigned short) *input++) & 0xff;
|
||||
*sptr |= (((unsigned short) *input++) << 8) & 0xff00;
|
||||
|
||||
sptr = (unsigned short *) &scores[i].sc_quest;
|
||||
*sptr = ((unsigned short) *input++) & 0xff;
|
||||
*sptr |= (((unsigned short) *input++) << 8) & 0xff00;
|
||||
|
||||
/* Finally comes the char fields -- they're easy */
|
||||
cptr = (unsigned char *) scores[i].sc_name;
|
||||
for (j = 0; j < NAMELEN; j++) *cptr++ = *input++;
|
||||
|
||||
cptr = (unsigned char *) scores[i].sc_system;
|
||||
for (j = 0; j < SYSLEN; j++) *cptr++ = *input++;
|
||||
|
||||
cptr = (unsigned char *) scores[i].sc_login;
|
||||
for (j = 0; j < LOGLEN; j++) *cptr++ = *input++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* scoreout:
|
||||
* Convert a score file structure to a character string. We do
|
||||
* this for compatibility sake since some machines write out fields in
|
||||
* different orders.
|
||||
*/
|
||||
scoreout(scores, output)
|
||||
struct sc_ent scores[];
|
||||
unsigned char *output;
|
||||
{
|
||||
register int i, j;
|
||||
unsigned long *lptr;
|
||||
unsigned short *sptr;
|
||||
unsigned char *cptr;
|
||||
|
||||
for (i=0; i<NUMSCORE; i++) {
|
||||
/* The long fields are first -- ordered low to high byte in input */
|
||||
lptr = &scores[i].sc_score;
|
||||
for (j = 0; j < sizeof(unsigned long); j++)
|
||||
*output++ = (unsigned char) ((*lptr >> 8*j) & 0xff);
|
||||
|
||||
/* The short fields are next -- ordered low to high byte in input */
|
||||
sptr = (unsigned short *) &scores[i].sc_flags;
|
||||
*output++ = (unsigned char) (*sptr & 0xff);
|
||||
*output++ = (unsigned char) ((*sptr >> 8) & 0xff);
|
||||
|
||||
sptr = (unsigned short *) &scores[i].sc_level;
|
||||
*output++ = (unsigned char) (*sptr & 0xff);
|
||||
*output++ = (unsigned char) ((*sptr >> 8) & 0xff);
|
||||
|
||||
sptr = (unsigned short *) &scores[i].sc_ctype;
|
||||
*output++ = (unsigned char) (*sptr & 0xff);
|
||||
*output++ = (unsigned char) ((*sptr >> 8) & 0xff);
|
||||
|
||||
sptr = (unsigned short *) &scores[i].sc_monster;
|
||||
*output++ = (unsigned char) (*sptr & 0xff);
|
||||
*output++ = (unsigned char) ((*sptr >> 8) & 0xff);
|
||||
|
||||
sptr = (unsigned short *) &scores[i].sc_quest;
|
||||
*output++ = (unsigned char) (*sptr & 0xff);
|
||||
*output++ = (unsigned char) ((*sptr >> 8) & 0xff);
|
||||
|
||||
/* Finally comes the char fields -- they're easy */
|
||||
cptr = (unsigned char *) scores[i].sc_name;
|
||||
for (j = 0; j < NAMELEN; j++) *output++ = *cptr++;
|
||||
|
||||
cptr = (unsigned char *) scores[i].sc_system;
|
||||
for (j = 0; j < SYSLEN; j++) *output++ = *cptr++;
|
||||
|
||||
cptr = (unsigned char *) scores[i].sc_login;
|
||||
for (j = 0; j < LOGLEN; j++) *output++ = *cptr++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* showpack:
|
||||
* Display the contents of the hero's pack
|
||||
*/
|
||||
showpack(howso)
|
||||
char *howso;
|
||||
{
|
||||
reg char *iname;
|
||||
reg int cnt, packnum;
|
||||
reg struct linked_list *item;
|
||||
reg struct object *obj;
|
||||
|
||||
idenpack();
|
||||
cnt = 1;
|
||||
clear();
|
||||
mvprintw(0, 0, "Contents of your pack %s:\n",howso);
|
||||
packnum = 'a';
|
||||
for (item = pack; item != NULL; item = next(item)) {
|
||||
obj = OBJPTR(item);
|
||||
iname = inv_name(obj, FALSE);
|
||||
mvprintw(cnt, 0, "%c) %s\n",packnum++,iname);
|
||||
if (++cnt >= lines - 2 &&
|
||||
next(item) != NULL) {
|
||||
cnt = 1;
|
||||
mvaddstr(lines - 1, 0, morestr);
|
||||
refresh();
|
||||
wait_for(' ');
|
||||
clear();
|
||||
}
|
||||
}
|
||||
mvprintw(cnt + 1,0,"--- %d Gold Pieces ---",purse);
|
||||
refresh();
|
||||
}
|
||||
|
||||
total_winner()
|
||||
{
|
||||
register struct linked_list *item;
|
||||
register struct object *obj;
|
||||
register int worth;
|
||||
register char c;
|
||||
register int oldpurse;
|
||||
|
||||
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 escaped the\n");
|
||||
addstr("Dungeons of Doom alive. You journey home and sell all your loot at\n");
|
||||
addstr("a great profit and are appointed leader of a ");
|
||||
switch (player.t_ctype) {
|
||||
case C_MAGICIAN:addstr("magic user's guild.\n");
|
||||
when C_FIGHTER: addstr("fighter's guild.\n");
|
||||
when C_RANGER: addstr("ranger's guild.\n");
|
||||
when C_CLERIC: addstr("monastery.\n");
|
||||
when C_PALADIN: addstr("monastery.\n");
|
||||
when C_MONK: addstr("monastery.\n");
|
||||
when C_DRUID: addstr("monastery.\n");
|
||||
when C_THIEF: addstr("thief's guild.\n");
|
||||
when C_ASSASIN: addstr("assassin's guild.\n");
|
||||
otherwise: addstr("tavern.\n");
|
||||
}
|
||||
mvaddstr(lines - 1, 0, spacemsg);
|
||||
refresh();
|
||||
wait_for(' ');
|
||||
clear();
|
||||
mvaddstr(0, 0, " Worth Item");
|
||||
oldpurse = purse;
|
||||
for (c = 'a', item = pack; item != NULL; c++, item = next(item))
|
||||
{
|
||||
obj = OBJPTR(item);
|
||||
worth = get_worth(obj);
|
||||
if (obj->o_group == 0)
|
||||
worth *= obj->o_count;
|
||||
whatis(item);
|
||||
mvprintw(c - 'a' + 1, 0, "%c) %6d %s", c, worth, inv_name(obj, FALSE));
|
||||
purse += worth;
|
||||
}
|
||||
mvprintw(c - 'a' + 1, 0," %5d Gold Pieces ", oldpurse);
|
||||
refresh();
|
||||
score(pstats.s_exp + (long) purse, WINNER, '\0');
|
||||
endwin();
|
||||
#ifdef PC7300
|
||||
endhardwin();
|
||||
#endif
|
||||
exit(0);
|
||||
}
|
||||
|
||||
update(top_ten, amount, quest, whoami, flags, level, monst, ctype, system, login)
|
||||
struct sc_ent top_ten[];
|
||||
unsigned long amount;
|
||||
short quest, flags, level, monst, ctype;
|
||||
char *whoami, *system, *login;
|
||||
{
|
||||
register struct sc_ent *scp, *sc2;
|
||||
int retval=0; /* 1 if a change, 0 otherwise */
|
||||
|
||||
for (scp = top_ten; scp < &top_ten[NUMSCORE]; scp++) {
|
||||
if (amount >= scp->sc_score)
|
||||
break;
|
||||
|
||||
#ifdef LIMITSCORE /* Limits player to one entry per class per uid */
|
||||
/* If this good score is the same class and uid, then forget it */
|
||||
if (strncmp(scp->sc_login, login, LOGLEN) == 0 &&
|
||||
scp->sc_ctype == ctype &&
|
||||
strncmp(scp->sc_system, system, SYSLEN) == 0) return(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (scp < &top_ten[NUMSCORE])
|
||||
{
|
||||
retval = 1;
|
||||
|
||||
#ifdef LIMITSCORE /* Limits player to one entry per class per uid */
|
||||
/* If a lower scores exists for the same login and class, delete it */
|
||||
for (sc2 = scp ;sc2 < &top_ten[NUMSCORE]; sc2++) {
|
||||
if (sc2->sc_score == 0L) break; /* End of useful scores */
|
||||
|
||||
if (strncmp(sc2->sc_login, login, LOGLEN) == 0 &&
|
||||
sc2->sc_ctype == ctype &&
|
||||
strncmp(sc2->sc_system, system, SYSLEN) == 0) {
|
||||
/* We want to delete this entry */
|
||||
while (sc2 < &top_ten[NUMSCORE-1]) {
|
||||
*sc2 = *(sc2+1);
|
||||
sc2++;
|
||||
}
|
||||
sc2->sc_score = 0L;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for (sc2 = &top_ten[NUMSCORE-1]; sc2 > scp; sc2--)
|
||||
*sc2 = *(sc2-1);
|
||||
scp->sc_score = amount;
|
||||
scp->sc_quest = quest;
|
||||
strncpy(scp->sc_name, whoami, NAMELEN);
|
||||
scp->sc_flags = flags;
|
||||
scp->sc_level = level;
|
||||
scp->sc_monster = monst;
|
||||
scp->sc_ctype = ctype;
|
||||
strncpy(scp->sc_system, system, SYSLEN);
|
||||
strncpy(scp->sc_login, login, LOGLEN);
|
||||
}
|
||||
|
||||
return(retval);
|
||||
}
|
||||
1689
arogue7/rogue.c
Normal file
1689
arogue7/rogue.c
Normal file
File diff suppressed because it is too large
Load diff
1297
arogue7/rogue.h
Normal file
1297
arogue7/rogue.h
Normal file
File diff suppressed because it is too large
Load diff
295
arogue7/rooms.c
Normal file
295
arogue7/rooms.c
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
/*
|
||||
* rooms.c - Draw the nine rooms on the screen
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Draw the nine rooms on the screen
|
||||
*
|
||||
*/
|
||||
|
||||
#include "curses.h"
|
||||
#include "rogue.h"
|
||||
|
||||
do_rooms()
|
||||
{
|
||||
register int i;
|
||||
register struct room *rp;
|
||||
register struct linked_list *item;
|
||||
register struct thing *tp;
|
||||
int left_out;
|
||||
int num_monsters;
|
||||
int which_monster;
|
||||
int j;
|
||||
coord top;
|
||||
coord bsze;
|
||||
coord mp;
|
||||
coord *np;
|
||||
|
||||
/*
|
||||
* 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_flags = 0;
|
||||
rp->r_fires = NULL;
|
||||
}
|
||||
/*
|
||||
* Put the gone rooms, if any, on the level
|
||||
*/
|
||||
left_out = rnd(4);
|
||||
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++)
|
||||
{
|
||||
bool 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;
|
||||
} until(rp->r_pos.y > 0 && rp->r_pos.y < lines-2);
|
||||
continue;
|
||||
}
|
||||
if (rnd(10) < level-1)
|
||||
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);
|
||||
} until (rp->r_pos.y != 0);
|
||||
|
||||
/* Draw the room */
|
||||
draw_room(rp);
|
||||
|
||||
/*
|
||||
* Put the gold in
|
||||
*/
|
||||
if (rnd(100) < 50 && level >= cur_max)
|
||||
{
|
||||
register struct linked_list *item;
|
||||
register struct object *cur;
|
||||
coord tp;
|
||||
|
||||
has_gold = TRUE; /* This room has gold in it */
|
||||
|
||||
item = spec_item(GOLD, NULL, NULL, NULL);
|
||||
cur = OBJPTR(item);
|
||||
|
||||
/* Put the gold into the level list of items */
|
||||
attach(lvl_obj, item);
|
||||
|
||||
/* Put it somewhere */
|
||||
rnd_pos(rp, &tp);
|
||||
mvaddch(tp.y, tp.x, GOLD);
|
||||
cur->o_pos = tp;
|
||||
if (roomin(&tp) != rp) {
|
||||
endwin();
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Put the monster in
|
||||
*/
|
||||
if (rnd(100) < (has_gold ? 80 : 25) + vlevel/2)
|
||||
{
|
||||
do
|
||||
{
|
||||
rnd_pos(rp, &mp);
|
||||
} until(mvwinch(stdscr, mp.y, mp.x) == FLOOR);
|
||||
which_monster = randmonster(FALSE, FALSE);
|
||||
num_monsters = 1;
|
||||
/*
|
||||
* see if we should make a whole bunch
|
||||
*/
|
||||
for (j=0; j<MAXFLAGS; j++) {
|
||||
if (monsters[which_monster].m_flags[j] == AREMANY)
|
||||
num_monsters = roll(3,3);
|
||||
}
|
||||
for (j=0; j<num_monsters; j++) {
|
||||
if ((np = fallpos(&mp, FALSE, 2)) != NULL &&
|
||||
mvwinch(stdscr, np->y, np->x) == FLOOR) {
|
||||
item = new_item(sizeof *tp);
|
||||
tp = THINGPTR(item);
|
||||
new_monster(item, which_monster, np, FALSE);
|
||||
/*
|
||||
* See if we want to give it a treasure to
|
||||
* carry around.
|
||||
*/
|
||||
carry_obj(tp, monsters[tp->t_index].m_carry);
|
||||
tp->t_no_move = movement(tp);
|
||||
|
||||
/*
|
||||
* If it has a fire, mark it
|
||||
*/
|
||||
if (on(*tp, HASFIRE)) {
|
||||
register struct linked_list *fire_item;
|
||||
|
||||
fire_item = creat_item();
|
||||
ldata(fire_item) = (char *) tp;
|
||||
attach(rp->r_fires, fire_item);
|
||||
rp->r_flags |= HASFIRE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a room pointer and a pointer to a door, supposedly in that room,
|
||||
* return the coordinates of the entrance to the doorway.
|
||||
*/
|
||||
|
||||
coord *
|
||||
doorway(rp, door)
|
||||
register struct room *rp;
|
||||
register coord *door;
|
||||
{
|
||||
register int misses = 0;
|
||||
static coord answer;
|
||||
|
||||
/* Do we have decent parameters? */
|
||||
if (rp == NULL || door == NULL) return(NULL);
|
||||
|
||||
/* Initialize the answer to be the door, then calculate the offset */
|
||||
answer = *door;
|
||||
|
||||
/* Calculate the x-offset */
|
||||
if (door->x == rp->r_pos.x) answer.x++;
|
||||
else if (door->x == rp->r_pos.x + rp->r_max.x - 1) answer.x--;
|
||||
else misses++;
|
||||
|
||||
/* Calculate the y-offset */
|
||||
if (door->y == rp->r_pos.y) answer.y++;
|
||||
else if (door->y == rp->r_pos.y + rp->r_max.y - 1) answer.y--;
|
||||
else misses++;
|
||||
|
||||
if (misses <= 1) return(&answer);
|
||||
else return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Draw a box around a room
|
||||
*/
|
||||
|
||||
draw_room(rp)
|
||||
register struct room *rp;
|
||||
{
|
||||
register 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
|
||||
*/
|
||||
|
||||
horiz(cnt)
|
||||
register int cnt;
|
||||
{
|
||||
while (cnt--)
|
||||
addch('-');
|
||||
}
|
||||
|
||||
/*
|
||||
* rnd_pos:
|
||||
* pick a random spot in a room
|
||||
*/
|
||||
|
||||
rnd_pos(rp, cp)
|
||||
register struct room *rp;
|
||||
register 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* roomin:
|
||||
* Find what room some coordinates are in. NULL means they aren't
|
||||
* in any room.
|
||||
*/
|
||||
|
||||
struct room *
|
||||
roomin(cp)
|
||||
register coord *cp;
|
||||
{
|
||||
register struct room *rp;
|
||||
|
||||
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
|
||||
if (inroom(rp, cp))
|
||||
return rp;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* vert:
|
||||
* draw a vertical line
|
||||
*/
|
||||
|
||||
vert(cnt)
|
||||
register int cnt;
|
||||
{
|
||||
register int x, y;
|
||||
|
||||
getyx(stdscr, y, x);
|
||||
x--;
|
||||
while (cnt--) {
|
||||
move(++y, x);
|
||||
addch('|');
|
||||
}
|
||||
}
|
||||
302
arogue7/save.c
Normal file
302
arogue7/save.c
Normal file
|
|
@ -0,0 +1,302 @@
|
|||
/*
|
||||
* save.c - save and restore routines
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* save and restore routines
|
||||
*
|
||||
*/
|
||||
|
||||
#include "curses.h"
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <signal.h>
|
||||
#include "rogue.h"
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include "mach_dep.h"
|
||||
#ifdef PC7300
|
||||
#include "sys/window.h"
|
||||
extern struct uwdata wdata;
|
||||
#endif
|
||||
|
||||
#if u370 || uts
|
||||
#define ENCREAD(b,n,fd) read(fd,b,n)
|
||||
#define ENCWRITE(b,n,fd) write(fd,b,n)
|
||||
#endif
|
||||
#ifndef ENCREAD
|
||||
#define ENCREAD encread
|
||||
#define ENCWRITE encwrite
|
||||
#endif
|
||||
|
||||
typedef struct stat STAT;
|
||||
|
||||
extern char version[], encstr[];
|
||||
/* extern bool _endwin; */
|
||||
extern int errno;
|
||||
|
||||
STAT sbuf;
|
||||
|
||||
bool
|
||||
save_game()
|
||||
{
|
||||
register int savefd;
|
||||
register int c;
|
||||
char buf[LINELEN];
|
||||
|
||||
/*
|
||||
* get file name
|
||||
*/
|
||||
mpos = 0;
|
||||
if (file_name[0] != '\0')
|
||||
{
|
||||
msg("Save file (%s)? ", file_name);
|
||||
do
|
||||
{
|
||||
c = readchar();
|
||||
if (c == ESCAPE) return(0);
|
||||
} while (c != 'n' && c != 'N' && c != 'y' && c != 'Y');
|
||||
mpos = 0;
|
||||
if (c == 'y' || c == 'Y')
|
||||
{
|
||||
msg("File name: %s", file_name);
|
||||
goto gotfile;
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
msg("File name: ");
|
||||
mpos = 0;
|
||||
buf[0] = '\0';
|
||||
if (get_str(buf, msgw) == QUIT)
|
||||
{
|
||||
msg("");
|
||||
return FALSE;
|
||||
}
|
||||
strcpy(file_name, buf);
|
||||
gotfile:
|
||||
if ((savefd = open(file_name, O_WRONLY|O_CREAT|O_TRUNC,0666)) < 0)
|
||||
msg(strerror(errno)); /* fake perror() */
|
||||
} while (savefd < 0);
|
||||
|
||||
/*
|
||||
* write out encrpyted file (after a stat)
|
||||
*/
|
||||
if (save_file(savefd) == FALSE) {
|
||||
msg("Cannot create save file.");
|
||||
unlink(file_name);
|
||||
return(FALSE);
|
||||
}
|
||||
else return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* automatically save a file. This is used if a HUP signal is
|
||||
* recieved
|
||||
*/
|
||||
void
|
||||
auto_save(sig)
|
||||
int sig;
|
||||
{
|
||||
register int savefd;
|
||||
register int i;
|
||||
|
||||
for (i = 0; i < NSIG; i++)
|
||||
signal(i, SIG_IGN);
|
||||
if (file_name[0] != '\0' &&
|
||||
pstats.s_hpt > 0 &&
|
||||
(savefd = open(file_name, O_WRONLY|O_CREAT|O_TRUNC, 0600)) >= 0)
|
||||
save_file(savefd);
|
||||
endwin();
|
||||
#ifdef PC7300
|
||||
endhardwin();
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* write the saved game on the file
|
||||
*/
|
||||
bool
|
||||
save_file(savefd)
|
||||
register int savefd;
|
||||
{
|
||||
register unsigned num_to_write, num_written;
|
||||
FILE *savef;
|
||||
int ret;
|
||||
|
||||
wmove(cw, lines-1, 0);
|
||||
draw(cw);
|
||||
lseek(savefd, 0L, 0);
|
||||
fstat(savefd, &sbuf);
|
||||
num_to_write = strlen(version) + 1;
|
||||
num_written = ENCWRITE(version, num_to_write, savefd);
|
||||
sprintf(prbuf,"%d x %d\n", LINES, COLS);
|
||||
ENCWRITE(prbuf,80,savefd);
|
||||
savef = (FILE *) fdopen(savefd,"wb");
|
||||
ret = rs_save_file(savef);
|
||||
fclose(savef);
|
||||
if (num_to_write == num_written && ret == 0) return(TRUE);
|
||||
else return(FALSE);
|
||||
}
|
||||
|
||||
restore(file, envp)
|
||||
register char *file;
|
||||
char **envp;
|
||||
{
|
||||
register int inf;
|
||||
extern char **environ;
|
||||
char buf[LINELEN];
|
||||
STAT sbuf2;
|
||||
int oldcol, oldline; /* Old number of columns and lines */
|
||||
|
||||
if (strcmp(file, "-r") == 0)
|
||||
file = file_name;
|
||||
if ((inf = open(file, 0)) < 0)
|
||||
{
|
||||
perror(file);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
ENCREAD(buf, strlen(version) + 1, inf);
|
||||
if (strcmp(buf, version) != 0)
|
||||
{
|
||||
printf("Sorry, saved game is out of date.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the lines and columns from the previous game
|
||||
*/
|
||||
|
||||
ENCREAD(buf, 80, inf);
|
||||
sscanf(buf, "%d x %d\n", &oldline, &oldcol);
|
||||
fstat(inf, &sbuf2);
|
||||
fflush(stdout);
|
||||
|
||||
initscr();
|
||||
|
||||
if (COLS < oldcol || LINES < oldline) {
|
||||
endwin();
|
||||
printf("Cannot restart the game on a smaller screen.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
setup();
|
||||
/*
|
||||
* Set up windows
|
||||
*/
|
||||
cw = newwin(lines, cols, 0, 0);
|
||||
mw = newwin(lines, cols, 0, 0);
|
||||
hw = newwin(lines, cols, 0, 0);
|
||||
msgw = newwin(4, cols, 0, 0);
|
||||
|
||||
keypad(cw,1);
|
||||
keypad(msgw,1);
|
||||
|
||||
if (rs_restore_file(inf) != 0)
|
||||
{
|
||||
printf("Cannot restore file\n");
|
||||
close(inf);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
cols = COLS;
|
||||
lines = LINES;
|
||||
if (cols > 85) cols = 85;
|
||||
if (lines > 24) lines = 24;
|
||||
|
||||
mpos = 0;
|
||||
mvwprintw(msgw, 0, 0, "%s: %s", file, ctime(&sbuf2.st_mtime));
|
||||
|
||||
/*
|
||||
* defeat multiple restarting from the same place
|
||||
*/
|
||||
if (!wizard && md_unlink_open_file(file, inf) < 0) {
|
||||
printf("Cannot unlink file\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
environ = envp;
|
||||
strcpy(file_name, file);
|
||||
setup();
|
||||
clearok(curscr, TRUE);
|
||||
touchwin(cw);
|
||||
srand(getpid());
|
||||
playit();
|
||||
/*NOTREACHED*/
|
||||
return(0);
|
||||
}
|
||||
|
||||
#define ENCWBSIZ 1024
|
||||
/*
|
||||
* perform an encrypted write
|
||||
*/
|
||||
encwrite(start, size, outf)
|
||||
register char *start;
|
||||
register unsigned size;
|
||||
register int outf;
|
||||
{
|
||||
register char *ep;
|
||||
register int i = 0;
|
||||
int num_written = 0;
|
||||
auto char buf[ENCWBSIZ];
|
||||
|
||||
ep = encstr;
|
||||
|
||||
while (size--)
|
||||
{
|
||||
buf[i++] = *start++ ^ *ep++ ;
|
||||
if (*ep == '\0')
|
||||
ep = encstr;
|
||||
|
||||
if (i == ENCWBSIZ || size == 0) {
|
||||
if (write(outf, buf, (unsigned)i) < i)
|
||||
return(num_written);
|
||||
else {
|
||||
num_written += i;
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(num_written);
|
||||
}
|
||||
|
||||
/*
|
||||
* perform an encrypted read
|
||||
*/
|
||||
encread(start, size, inf)
|
||||
register char *start;
|
||||
register unsigned size;
|
||||
register int inf;
|
||||
{
|
||||
register char *ep;
|
||||
register int read_size;
|
||||
|
||||
if ((read_size = read(inf, start, size)) == -1 || read_size == 0)
|
||||
return read_size;
|
||||
|
||||
ep = encstr;
|
||||
|
||||
size = read_size;
|
||||
while (size--)
|
||||
{
|
||||
*start++ ^= *ep++;
|
||||
if (*ep == '\0')
|
||||
ep = encstr;
|
||||
}
|
||||
return read_size;
|
||||
}
|
||||
841
arogue7/scrolls.c
Normal file
841
arogue7/scrolls.c
Normal file
|
|
@ -0,0 +1,841 @@
|
|||
/*
|
||||
* scrolls.c - Functions for dealing with scrolls
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Read a scroll and let it happen
|
||||
*
|
||||
*/
|
||||
|
||||
#include "curses.h"
|
||||
#include <ctype.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* let the hero get rid of some type of monster (but not a UNIQUE!)
|
||||
*/
|
||||
genocide()
|
||||
{
|
||||
register struct linked_list *ip;
|
||||
register struct thing *mp;
|
||||
register struct linked_list *nip;
|
||||
register int num_monst = NUMMONST-NUMUNIQUE-1, /* cannot genocide uniques */
|
||||
pres_monst=1,
|
||||
num_lines=2*(lines-3);
|
||||
register int which_monst;
|
||||
|
||||
which_monst = makemonster(FALSE, "Genocide", "wipe out");
|
||||
if (which_monst <= 0) {
|
||||
msg("");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Remove this monster from the present level */
|
||||
for (ip = mlist; ip; ip = nip) {
|
||||
mp = THINGPTR(ip);
|
||||
nip = next(ip);
|
||||
if (mp->t_index == which_monst) {
|
||||
killed(ip, FALSE, FALSE, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove from available monsters */
|
||||
monsters[which_monst].m_normal = FALSE;
|
||||
monsters[which_monst].m_wander = FALSE;
|
||||
mpos = 0;
|
||||
msg("You have wiped out the %s.", monsters[which_monst].m_name);
|
||||
}
|
||||
|
||||
read_scroll(which, flag, is_scroll)
|
||||
register int which;
|
||||
int flag;
|
||||
bool is_scroll;
|
||||
{
|
||||
register struct object *obj, *nobj;
|
||||
register struct linked_list *item, *nitem;
|
||||
register int i,j;
|
||||
register char ch, nch;
|
||||
bool cursed, blessed;
|
||||
|
||||
blessed = FALSE;
|
||||
cursed = FALSE;
|
||||
item = NULL;
|
||||
|
||||
if (which < 0) {
|
||||
if (on(player, ISBLIND)) {
|
||||
msg("You can't see to read anything");
|
||||
return;
|
||||
}
|
||||
if (on(player, ISINWALL)) {
|
||||
msg("You can't see the scroll while inside rock!");
|
||||
return;
|
||||
}
|
||||
|
||||
/* This is a scroll or book. */
|
||||
if (player.t_action != C_READ) {
|
||||
int units;
|
||||
|
||||
item = get_item(pack, "read", READABLE, FALSE, FALSE);
|
||||
|
||||
/*
|
||||
* Make certain that it is somethings that we want to read
|
||||
*/
|
||||
if (item == NULL)
|
||||
return;
|
||||
|
||||
/* How long does it take to read? */
|
||||
units = usage_time(item);
|
||||
if (units < 0) return;
|
||||
|
||||
player.t_using = item; /* Remember what it is */
|
||||
player.t_no_move = units * movement(&player);
|
||||
if ((OBJPTR(item))->o_type == SCROLL) player.t_action = C_READ;
|
||||
else player.t_action = C_USE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* We have waited our time, let's quaff the potion */
|
||||
item = player.t_using;
|
||||
player.t_using = NULL;
|
||||
player.t_action = A_NIL;
|
||||
|
||||
obj = OBJPTR(item);
|
||||
/* remove it from the pack */
|
||||
inpack--;
|
||||
detach(pack, item);
|
||||
|
||||
msg("As you read the scroll, it vanishes.");
|
||||
cursed = (obj->o_flags & ISCURSED) != 0;
|
||||
blessed = (obj->o_flags & ISBLESSED) != 0;
|
||||
|
||||
which = obj->o_which;
|
||||
}
|
||||
else {
|
||||
cursed = flag & ISCURSED;
|
||||
blessed = flag & ISBLESSED;
|
||||
}
|
||||
|
||||
|
||||
switch (which) {
|
||||
case S_CONFUSE:
|
||||
/*
|
||||
* Scroll of monster confusion. Give him that power.
|
||||
*/
|
||||
msg("Your hands begin to glow red");
|
||||
turn_on(player, CANHUH);
|
||||
when S_CURING:
|
||||
/*
|
||||
* A cure disease spell
|
||||
*/
|
||||
if (on(player, HASINFEST) ||
|
||||
on(player, HASDISEASE)||
|
||||
on(player, DOROT)) {
|
||||
if (on(player, HASDISEASE)) {
|
||||
extinguish(cure_disease);
|
||||
cure_disease();
|
||||
}
|
||||
if (on(player, HASINFEST)) {
|
||||
msg(terse ? "You feel yourself improving."
|
||||
: "You begin to feel yourself improving again.");
|
||||
turn_off(player, HASINFEST);
|
||||
infest_dam = 0;
|
||||
}
|
||||
if (on(player, DOROT)) {
|
||||
msg("You feel your skin returning to normal.");
|
||||
turn_off(player, DOROT);
|
||||
}
|
||||
}
|
||||
else {
|
||||
msg(nothing);
|
||||
break;
|
||||
}
|
||||
if (is_scroll) s_know[S_CURING] = TRUE;
|
||||
when S_LIGHT:
|
||||
if (blue_light(blessed, cursed) && is_scroll)
|
||||
s_know[S_LIGHT] = TRUE;
|
||||
when S_HOLD:
|
||||
if (cursed) {
|
||||
/*
|
||||
* This scroll aggravates all the monsters on the current
|
||||
* level and sets them running towards the hero
|
||||
*/
|
||||
aggravate(TRUE, TRUE);
|
||||
msg("You hear a high pitched humming noise.");
|
||||
}
|
||||
else if (blessed) { /* Hold all monsters on level */
|
||||
if (mlist == NULL) msg(nothing);
|
||||
else {
|
||||
register struct linked_list *mon;
|
||||
register struct thing *th;
|
||||
|
||||
for (mon = mlist; mon != NULL; mon = next(mon)) {
|
||||
th = THINGPTR(mon);
|
||||
turn_off(*th, ISRUN);
|
||||
turn_on(*th, ISHELD);
|
||||
}
|
||||
msg("A sudden peace comes over the dungeon.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Hold monster scroll. Stop all monsters within two spaces
|
||||
* from chasing after the hero.
|
||||
*/
|
||||
register int x,y;
|
||||
register struct linked_list *mon;
|
||||
bool gotone=FALSE;
|
||||
|
||||
for (x = hero.x-2; x <= hero.x+2; x++) {
|
||||
for (y = hero.y-2; y <= hero.y+2; y++) {
|
||||
if (y < 1 || x < 0 || y > lines - 3 || x > cols - 1)
|
||||
continue;
|
||||
if (isalpha(mvwinch(mw, y, x))) {
|
||||
if ((mon = find_mons(y, x)) != NULL) {
|
||||
register struct thing *th;
|
||||
|
||||
gotone = TRUE;
|
||||
th = THINGPTR(mon);
|
||||
turn_off(*th, ISRUN);
|
||||
turn_on(*th, ISHELD);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (gotone) msg("A sudden peace surrounds you.");
|
||||
else msg(nothing);
|
||||
}
|
||||
when S_SLEEP:
|
||||
/*
|
||||
* if cursed, you fall asleep
|
||||
*/
|
||||
if (is_scroll) s_know[S_SLEEP] = TRUE;
|
||||
if (cursed) {
|
||||
if (ISWEARING(R_ALERT))
|
||||
msg("You feel drowsy for a moment.");
|
||||
else {
|
||||
msg("You fall asleep.");
|
||||
player.t_no_move += movement(&player)*(4 + rnd(SLEEPTIME));
|
||||
player.t_action = A_FREEZE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* sleep monster scroll.
|
||||
* puts all monsters within 2 spaces asleep
|
||||
*/
|
||||
register int x,y;
|
||||
register struct linked_list *mon;
|
||||
bool gotone=FALSE;
|
||||
|
||||
for (x = hero.x-2; x <= hero.x+2; x++) {
|
||||
for (y = hero.y-2; y <= hero.y+2; y++) {
|
||||
if (y < 1 || x < 0 || y > lines - 3 || x > cols - 1)
|
||||
continue;
|
||||
if (isalpha(mvwinch(mw, y, x))) {
|
||||
if ((mon = find_mons(y, x)) != NULL) {
|
||||
register struct thing *th;
|
||||
|
||||
th = THINGPTR(mon);
|
||||
if (on(*th, ISUNDEAD))
|
||||
continue;
|
||||
th->t_no_move += movement(th)*(SLEEPTIME+4);
|
||||
th->t_action = A_FREEZE;
|
||||
gotone = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (gotone)
|
||||
msg("The monster(s) around you seem to have fallen asleep");
|
||||
else
|
||||
msg(nothing);
|
||||
}
|
||||
when S_CREATE:
|
||||
/*
|
||||
* Create a monster
|
||||
* First look in a circle around him, next try his room
|
||||
* otherwise give up
|
||||
*/
|
||||
creat_mons(&player, (short) 0, TRUE);
|
||||
light(&hero);
|
||||
when S_IDENT:
|
||||
/*
|
||||
* if its blessed then identify everything in the pack
|
||||
*/
|
||||
if (blessed) {
|
||||
msg("You feel more Knowledgeable!");
|
||||
idenpack();
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Identify, let the rogue figure something out
|
||||
*/
|
||||
if (is_scroll && s_know[S_IDENT] != TRUE) {
|
||||
msg("This scroll is an identify scroll");
|
||||
}
|
||||
whatis(NULL);
|
||||
}
|
||||
if (is_scroll) s_know[S_IDENT] = TRUE;
|
||||
when S_MAP:
|
||||
/*
|
||||
* Scroll of magic mapping.
|
||||
*/
|
||||
if (is_scroll && s_know[S_MAP] != TRUE) {
|
||||
msg("Oh, now this scroll has a map on it.");
|
||||
s_know[S_MAP] = TRUE;
|
||||
}
|
||||
overwrite(stdscr, hw);
|
||||
/*
|
||||
* Take all the things we want to keep hidden out of the window
|
||||
*/
|
||||
for (i = 1; i < lines-2; i++)
|
||||
for (j = 0; j < cols; j++)
|
||||
{
|
||||
switch (nch = ch = CCHAR( mvwinch(hw, i, j) ))
|
||||
{
|
||||
case SECRETDOOR:
|
||||
nch = secretdoor (i, j);
|
||||
break;
|
||||
case '-':
|
||||
case '|':
|
||||
case DOOR:
|
||||
case PASSAGE:
|
||||
case ' ':
|
||||
case STAIRS:
|
||||
if (mvwinch(mw, i, j) != ' ')
|
||||
{
|
||||
register struct thing *it;
|
||||
|
||||
it = THINGPTR(find_mons(i, j));
|
||||
if (it && it->t_oldch == ' ')
|
||||
it->t_oldch = nch;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
nch = ' ';
|
||||
}
|
||||
if (nch != ch)
|
||||
waddch(hw, nch);
|
||||
}
|
||||
/*
|
||||
* Copy in what he has discovered
|
||||
*/
|
||||
overlay(cw, hw);
|
||||
/*
|
||||
* And set up for display
|
||||
*/
|
||||
overwrite(hw, cw);
|
||||
when S_GFIND:
|
||||
/*
|
||||
* Scroll of gold detection
|
||||
*/
|
||||
{
|
||||
int gtotal = 0;
|
||||
|
||||
wclear(hw);
|
||||
for (nitem = lvl_obj; nitem != NULL; nitem = next(nitem)) {
|
||||
nobj = OBJPTR(nitem);
|
||||
if (nobj->o_type == GOLD) {
|
||||
gtotal += nobj->o_count;
|
||||
mvwaddch(hw, nobj->o_pos.y, nobj->o_pos.x, GOLD);
|
||||
}
|
||||
}
|
||||
for (nitem = mlist; nitem != NULL; nitem = next(nitem)) {
|
||||
register struct linked_list *gitem;
|
||||
register struct thing *th;
|
||||
|
||||
th = THINGPTR(nitem);
|
||||
if (on(*th, NODETECT)) continue;
|
||||
for(gitem = th->t_pack; gitem != NULL; gitem = next(gitem)){
|
||||
nobj = OBJPTR(gitem);
|
||||
if (nobj->o_type == GOLD) {
|
||||
gtotal += nobj->o_count;
|
||||
mvwaddch(hw, th->t_pos.y, th->t_pos.x, GOLD);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (gtotal) {
|
||||
if (is_scroll) s_know[S_GFIND] = TRUE;
|
||||
msg("You begin to feel greedy and you sense gold.");
|
||||
waddstr(msgw, morestr);
|
||||
clearok(msgw, FALSE);
|
||||
draw(msgw);
|
||||
overlay(hw, cw);
|
||||
draw(cw);
|
||||
wait_for(' ');
|
||||
msg("");
|
||||
break;
|
||||
}
|
||||
}
|
||||
msg("You begin to feel a pull downward");
|
||||
when S_TELEP:
|
||||
/*
|
||||
* Scroll of teleportation:
|
||||
* Make him disappear and reappear
|
||||
*/
|
||||
if (cursed) {
|
||||
int old_max = cur_max;
|
||||
|
||||
turns = (vlevel * 3) * LEVEL;
|
||||
level = nfloors;
|
||||
new_level(NORMLEV);
|
||||
status(TRUE);
|
||||
mpos = 0;
|
||||
msg("You are banished to the lower regions.");
|
||||
if (old_max == cur_max) /* if he's been here, make it harder */
|
||||
aggravate(TRUE, TRUE);
|
||||
}
|
||||
else if (blessed) {
|
||||
int old_level,
|
||||
much = rnd(4) - 4;
|
||||
|
||||
old_level = level;
|
||||
if (much != 0) {
|
||||
level += much;
|
||||
if (level < 1)
|
||||
level = 1;
|
||||
mpos = 0;
|
||||
cur_max = level;
|
||||
turns += much*LEVEL;
|
||||
if (turns < 0)
|
||||
turns = 0;
|
||||
new_level(NORMLEV); /* change levels */
|
||||
if (level == old_level)
|
||||
status(TRUE);
|
||||
msg("You are whisked away to another region.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
teleport();
|
||||
}
|
||||
if (is_scroll) s_know[S_TELEP] = TRUE;
|
||||
when S_SCARE:
|
||||
/*
|
||||
* A monster will refuse to step on a scare monster scroll
|
||||
* if it is dropped. Thus reading it is a mistake and produces
|
||||
* laughter at the poor rogue's boo boo.
|
||||
*/
|
||||
msg("You hear maniacal laughter in the distance.");
|
||||
when S_REMOVE:
|
||||
if (cursed) { /* curse all player's possessions */
|
||||
for (nitem = pack; nitem != NULL; nitem = next(nitem)) {
|
||||
nobj = OBJPTR(nitem);
|
||||
if (nobj->o_flags & ISBLESSED)
|
||||
nobj->o_flags &= ~ISBLESSED;
|
||||
else
|
||||
nobj->o_flags |= ISCURSED;
|
||||
}
|
||||
msg("The smell of fire and brimstone fills the air.");
|
||||
}
|
||||
else if (blessed) {
|
||||
for (nitem = pack; nitem != NULL; nitem = next(nitem)) {
|
||||
nobj = OBJPTR(nitem);
|
||||
nobj->o_flags &= ~ISCURSED;
|
||||
}
|
||||
msg("Your pack glistens brightly");
|
||||
}
|
||||
else {
|
||||
nitem = get_item(pack, "remove the curse on",ALL,FALSE,FALSE);
|
||||
if (nitem != NULL) {
|
||||
nobj = OBJPTR(nitem);
|
||||
nobj->o_flags &= ~ISCURSED;
|
||||
msg("Removed the curse from %s",inv_name(nobj,TRUE));
|
||||
}
|
||||
}
|
||||
if (is_scroll) s_know[S_REMOVE] = TRUE;
|
||||
when S_PETRIFY:
|
||||
switch (mvinch(hero.y, hero.x)) {
|
||||
case TRAPDOOR:
|
||||
case DARTTRAP:
|
||||
case TELTRAP:
|
||||
case ARROWTRAP:
|
||||
case SLEEPTRAP:
|
||||
case BEARTRAP:
|
||||
{
|
||||
register int i;
|
||||
|
||||
/* Find the right trap */
|
||||
for (i=0; i<ntraps && !ce(traps[i].tr_pos, hero); i++);
|
||||
ntraps--;
|
||||
|
||||
if (!ce(traps[i].tr_pos, hero))
|
||||
msg("What a strange trap!");
|
||||
else {
|
||||
while (i < ntraps) {
|
||||
traps[i] = traps[i + 1];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
goto pet_message;
|
||||
case DOOR:
|
||||
case SECRETDOOR:
|
||||
case FLOOR:
|
||||
case PASSAGE:
|
||||
pet_message: msg("The dungeon begins to rumble and shake!");
|
||||
addch(WALL);
|
||||
|
||||
/* If the player is phased, unphase him */
|
||||
if (on(player, CANINWALL)) {
|
||||
extinguish(unphase);
|
||||
turn_off(player, CANINWALL);
|
||||
msg("Your dizzy feeling leaves you.");
|
||||
}
|
||||
|
||||
/* Mark the player as in a wall */
|
||||
turn_on(player, ISINWALL);
|
||||
break;
|
||||
default:
|
||||
msg(nothing);
|
||||
}
|
||||
when S_GENOCIDE:
|
||||
msg("You have been granted the boon of genocide!--More--");
|
||||
wait_for(' ');
|
||||
msg("");
|
||||
genocide();
|
||||
if (is_scroll) s_know[S_GENOCIDE] = TRUE;
|
||||
when S_PROTECT: {
|
||||
struct linked_list *ll;
|
||||
struct object *lb;
|
||||
bool did_it = FALSE;
|
||||
msg("You are granted the power of protection.");
|
||||
if ((ll=get_item(pack,"protect",PROTECTABLE,FALSE,FALSE)) != NULL) {
|
||||
lb = OBJPTR(ll);
|
||||
mpos = 0;
|
||||
if (cursed) {
|
||||
switch(lb->o_type) { /* ruin it completely */
|
||||
case RING: if (lb->o_ac > 0) {
|
||||
if (is_current(lb)) {
|
||||
switch (lb->o_which) {
|
||||
case R_ADDWISDOM:
|
||||
pstats.s_wisdom -= lb->o_ac;
|
||||
when R_ADDINTEL:
|
||||
pstats.s_intel -= lb->o_ac;
|
||||
when R_ADDSTR:
|
||||
pstats.s_str -= lb->o_ac;
|
||||
when R_ADDHIT:
|
||||
pstats.s_dext -= lb->o_ac;
|
||||
}
|
||||
}
|
||||
did_it = TRUE;
|
||||
lb->o_ac = 0;
|
||||
}
|
||||
when ARMOR: if (lb->o_ac > 10) {
|
||||
did_it = TRUE;
|
||||
lb->o_ac = 10;
|
||||
}
|
||||
when STICK: if (lb->o_charges > 0) {
|
||||
did_it = TRUE;
|
||||
lb->o_charges = 0;
|
||||
}
|
||||
when WEAPON:if (lb->o_hplus > 0) {
|
||||
did_it = TRUE;
|
||||
lb->o_hplus = 0;
|
||||
}
|
||||
if (lb->o_dplus > 0) {
|
||||
did_it = TRUE;
|
||||
lb->o_dplus = 0;
|
||||
}
|
||||
}
|
||||
if (lb->o_flags & ISPROT) {
|
||||
did_it = TRUE;
|
||||
lb->o_flags &= ~ISPROT;
|
||||
}
|
||||
if (lb->o_flags & ISBLESSED) {
|
||||
did_it = TRUE;
|
||||
lb->o_flags &= ~ISBLESSED;
|
||||
}
|
||||
if (did_it)
|
||||
msg("Your %s glows red for a moment",inv_name(lb,TRUE));
|
||||
else {
|
||||
msg(nothing);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
lb->o_flags |= ISPROT;
|
||||
msg("Protected %s.",inv_name(lb,TRUE));
|
||||
}
|
||||
}
|
||||
if (is_scroll) s_know[S_PROTECT] = TRUE;
|
||||
}
|
||||
when S_MAKEIT:
|
||||
msg("You have been endowed with the power of creation.");
|
||||
if (is_scroll) s_know[S_MAKEIT] = TRUE;
|
||||
create_obj(TRUE, 0, 0);
|
||||
when S_ALLENCH: {
|
||||
struct linked_list *ll;
|
||||
struct object *lb;
|
||||
int howmuch, flags;
|
||||
if (is_scroll && s_know[S_ALLENCH] == FALSE) {
|
||||
msg("You are granted the power of enchantment.");
|
||||
msg("You may enchant anything(weapon,ring,armor,scroll,potion)");
|
||||
}
|
||||
if ((ll = get_item(pack, "enchant", ALL, FALSE, FALSE)) != NULL) {
|
||||
lb = OBJPTR(ll);
|
||||
lb->o_flags &= ~ISCURSED;
|
||||
if (blessed) {
|
||||
howmuch = 2;
|
||||
flags = ISBLESSED;
|
||||
}
|
||||
else if (cursed) {
|
||||
howmuch = -1;
|
||||
flags = ISCURSED;
|
||||
}
|
||||
else {
|
||||
howmuch = 1;
|
||||
flags = ISBLESSED;
|
||||
}
|
||||
switch(lb->o_type) {
|
||||
case RING:
|
||||
if (lb->o_ac + howmuch > MAXENCHANT) {
|
||||
msg("The enchantment doesn't seem to work!");
|
||||
break;
|
||||
}
|
||||
lb->o_ac += howmuch;
|
||||
if (lb==cur_ring[LEFT_1] || lb==cur_ring[LEFT_2] ||
|
||||
lb==cur_ring[LEFT_3] || lb==cur_ring[LEFT_4] ||
|
||||
lb==cur_ring[RIGHT_1] || lb==cur_ring[RIGHT_2] ||
|
||||
lb==cur_ring[RIGHT_3] || lb==cur_ring[RIGHT_4]) {
|
||||
switch (lb->o_which) {
|
||||
case R_ADDWISDOM: pstats.s_wisdom += howmuch;
|
||||
when R_ADDINTEL: pstats.s_intel += howmuch;
|
||||
when R_ADDSTR: pstats.s_str += howmuch;
|
||||
when R_ADDHIT: pstats.s_dext += howmuch;
|
||||
}
|
||||
}
|
||||
msg("Enchanted %s.",inv_name(lb,TRUE));
|
||||
when ARMOR:
|
||||
if ((armors[lb->o_which].a_class - lb->o_ac) +
|
||||
howmuch > MAXENCHANT) {
|
||||
msg("The enchantment doesn't seem to work!");
|
||||
break;
|
||||
}
|
||||
else
|
||||
lb->o_ac -= howmuch;
|
||||
msg("Enchanted %s.",inv_name(lb,TRUE));
|
||||
when STICK:
|
||||
lb->o_charges += (howmuch * 10) + rnd(5);
|
||||
if (lb->o_charges < 0)
|
||||
lb->o_charges = 0;
|
||||
if (EQUAL(ws_type[lb->o_which], "staff")) {
|
||||
if (lb->o_charges > 100)
|
||||
lb->o_charges = 100;
|
||||
}
|
||||
else {
|
||||
if (lb->o_charges > 50)
|
||||
lb->o_charges = 50;
|
||||
}
|
||||
msg("Enchanted %s.",inv_name(lb,TRUE));
|
||||
when WEAPON:
|
||||
if(lb->o_hplus+lb->o_dplus+howmuch > MAXENCHANT * 2){
|
||||
msg("The enchantment doesn't seem to work!");
|
||||
break;
|
||||
}
|
||||
if (rnd(100) < 50)
|
||||
lb->o_hplus += howmuch;
|
||||
else
|
||||
lb->o_dplus += howmuch;
|
||||
msg("Enchanted %s.",inv_name(lb,TRUE));
|
||||
when MM:
|
||||
switch (lb->o_which) {
|
||||
case MM_BRACERS:
|
||||
if (lb->o_ac + howmuch > MAXENCHANT) {
|
||||
msg("The enchantment doesn't seem to work!");
|
||||
break;
|
||||
}
|
||||
else lb->o_ac += howmuch;
|
||||
msg("Enchanted %s.",inv_name(lb,TRUE));
|
||||
when MM_PROTECT:
|
||||
if (lb->o_ac + howmuch > MAXENCHANT/2) {
|
||||
msg("The enchantment doesn't seem to work!");
|
||||
break;
|
||||
}
|
||||
else lb->o_ac += howmuch;
|
||||
msg("Enchanted %s.",inv_name(lb,TRUE));
|
||||
}
|
||||
lb->o_flags |= flags;
|
||||
when POTION:
|
||||
case SCROLL:
|
||||
default:
|
||||
lb->o_flags |= flags;
|
||||
msg("Enchanted %s.",inv_name(lb,TRUE));
|
||||
}
|
||||
}
|
||||
if (is_scroll) s_know[S_ALLENCH] = TRUE;
|
||||
if (!is_scroll) {
|
||||
pstats.s_const--;
|
||||
max_stats.s_const--;
|
||||
if (pstats.s_const <= 0)
|
||||
death(D_CONSTITUTION);
|
||||
msg("You feel less healthy now");
|
||||
}
|
||||
}
|
||||
when S_FINDTRAPS:
|
||||
for (i=0; i<ntraps; i++) {
|
||||
if (!(traps[i].tr_flags & ISFOUND)) {
|
||||
traps[i].tr_flags |= ISFOUND;
|
||||
if (cansee(traps[i].tr_pos.y, traps[i].tr_pos.x))
|
||||
mvwaddch(cw,traps[i].tr_pos.y,traps[i].tr_pos.x,
|
||||
traps[i].tr_type);
|
||||
}
|
||||
}
|
||||
if (ntraps > 0) {
|
||||
msg("You sense the presence of traps");
|
||||
if (is_scroll) s_know[S_FINDTRAPS] = TRUE;
|
||||
}
|
||||
else
|
||||
msg(nothing);
|
||||
|
||||
when S_RUNES:
|
||||
{
|
||||
register struct linked_list *sitem;
|
||||
|
||||
msg("The scroll explodes in a ball of fire!");
|
||||
if (on(player, NOFIRE)) {
|
||||
msg("The fire does not seem to affect you");
|
||||
break;
|
||||
}
|
||||
explode(&player);
|
||||
if (pstats.s_hpt <= 0)
|
||||
death(D_SCROLL);
|
||||
for (sitem = pack; sitem != NULL; sitem = nitem) {
|
||||
nitem = next(sitem); /* in case we delete it */
|
||||
nobj = OBJPTR(sitem);
|
||||
/*
|
||||
* check for loss of all scrolls and give them
|
||||
* a save versus fire
|
||||
*/
|
||||
if (nobj->o_type == SCROLL && roll(1,20) < 19) {
|
||||
msg("%s burns up!", inv_name(nobj, TRUE));
|
||||
inpack--;
|
||||
detach(pack, sitem);
|
||||
o_discard(sitem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when S_CHARM:
|
||||
{
|
||||
bool spots[9];
|
||||
int x, y, spot, count, numcharmed, something, bonus;
|
||||
struct linked_list *item;
|
||||
register struct thing *tp;
|
||||
|
||||
/* Initialize the places where we look around us */
|
||||
for (i=0; i<9; i++) spots[i] = FALSE;
|
||||
count = 0; /* No spots tried yet */
|
||||
numcharmed = 0; /* Nobody charmed yet */
|
||||
something = 0; /* Nothing has been seen yet */
|
||||
bonus = 0; /* no bonus yet */
|
||||
|
||||
/* Now look around us randomly for a charmee */
|
||||
while (count < 9) {
|
||||
do {
|
||||
spot = rnd(9);
|
||||
} while (spots[spot] == TRUE);
|
||||
|
||||
/* We found a place */
|
||||
count++;
|
||||
spots[spot] = TRUE;
|
||||
y = hero.y - 1 + (spot / 3);
|
||||
x = hero.x - 1 + (spot % 3);
|
||||
|
||||
/* Be sure to stay on the board! */
|
||||
if (x < 0 || x >= cols || (y < 1) || (y >= lines - 2))
|
||||
continue;
|
||||
|
||||
/* Is there a monster here? */
|
||||
if (!isalpha(mvwinch(mw, y, x))) continue;
|
||||
|
||||
/* What kind is it? */
|
||||
item = find_mons(y, x);
|
||||
if (item == NULL) continue;
|
||||
|
||||
tp = THINGPTR(item);
|
||||
if (on(*tp,ISCHARMED) || on(*tp,ISUNIQUE) || on(*tp,ISUNDEAD))
|
||||
continue;
|
||||
|
||||
/* Will the monster be charmed? */
|
||||
if (blessed) bonus -= 3;
|
||||
bonus -= (pstats.s_charisma - 13) / 3;
|
||||
if ((player.t_ctype==C_PALADIN || player.t_ctype==C_RANGER) &&
|
||||
off(*tp, ISMEAN))
|
||||
bonus -= 3;
|
||||
if (save(VS_MAGIC, tp, bonus)) continue;
|
||||
|
||||
/* We got him! */
|
||||
numcharmed++;
|
||||
|
||||
/* Let the player know (maybe) */
|
||||
if ((off(*tp, ISINVIS) || on(player, CANSEE)) &&
|
||||
(off(*tp, ISSHADOW) || on(player, CANSEE)) &&
|
||||
cansee(y, x)) {
|
||||
if (on(*tp, CANSURPRISE)) {
|
||||
turn_off(*tp, CANSURPRISE);
|
||||
msg("Woah!");
|
||||
}
|
||||
msg("The eyes of %s glaze over!",
|
||||
prname(monster_name(tp), FALSE));
|
||||
something++;
|
||||
}
|
||||
|
||||
/* Charm him and turn off any side effects */
|
||||
turn_on(*tp, ISCHARMED);
|
||||
runto(tp, &hero);
|
||||
tp->t_action = A_NIL;
|
||||
|
||||
/* If monster was suffocating us, stop it */
|
||||
if (on(*tp, DIDSUFFOCATE)) {
|
||||
turn_off(*tp, DIDSUFFOCATE);
|
||||
extinguish(suffocate);
|
||||
}
|
||||
|
||||
/* If monster held us, stop it */
|
||||
if (on(*tp, DIDHOLD) && (--hold_count == 0))
|
||||
turn_off(player, ISHELD);
|
||||
turn_off(*tp, DIDHOLD);
|
||||
|
||||
/* If frightened of this monster, stop */
|
||||
if (on(player, ISFLEE) &&
|
||||
player.t_dest == &tp->t_pos) turn_off(player, ISFLEE);
|
||||
|
||||
if ((blessed && numcharmed >= 2) || numcharmed > 0) break;
|
||||
}
|
||||
|
||||
if (something == 0) msg(nothing);
|
||||
}
|
||||
|
||||
otherwise:
|
||||
msg("What a puzzling scroll!");
|
||||
return;
|
||||
}
|
||||
look(TRUE, FALSE); /* put the result of the scroll on the screen */
|
||||
status(FALSE);
|
||||
if (is_scroll && item && s_know[which] && s_guess[which])
|
||||
{
|
||||
free(s_guess[which]);
|
||||
s_guess[which] = NULL;
|
||||
}
|
||||
else if (is_scroll &&
|
||||
!s_know[which] &&
|
||||
item &&
|
||||
askme &&
|
||||
(obj->o_flags & ISKNOW) == 0 &&
|
||||
(obj->o_flags & ISPOST) == 0 &&
|
||||
s_guess[which] == NULL) {
|
||||
nameitem(item, FALSE);
|
||||
}
|
||||
if (item != NULL) o_discard(item);
|
||||
updpack(TRUE, &player);
|
||||
}
|
||||
2674
arogue7/state.c
Normal file
2674
arogue7/state.c
Normal file
File diff suppressed because it is too large
Load diff
1247
arogue7/sticks.c
Normal file
1247
arogue7/sticks.c
Normal file
File diff suppressed because it is too large
Load diff
930
arogue7/things.c
Normal file
930
arogue7/things.c
Normal file
|
|
@ -0,0 +1,930 @@
|
|||
/*
|
||||
* things.c - functions for dealing with things like potions and scrolls
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Contains functions for dealing with things like
|
||||
* potions and scrolls
|
||||
*
|
||||
*/
|
||||
|
||||
#include "curses.h"
|
||||
#include <ctype.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* print out the number of charges on a stick
|
||||
*/
|
||||
char *
|
||||
charge_str(obj)
|
||||
register struct object *obj;
|
||||
{
|
||||
static char buf[20];
|
||||
|
||||
if (!(obj->o_flags & ISKNOW))
|
||||
buf[0] = '\0';
|
||||
else if (terse)
|
||||
sprintf(buf, " [%d]", obj->o_charges);
|
||||
else
|
||||
sprintf(buf, " [%d charges]", obj->o_charges);
|
||||
return buf;
|
||||
}
|
||||
/*
|
||||
* inv_name:
|
||||
* return the name of something as it would appear in an
|
||||
* inventory.
|
||||
*/
|
||||
char *
|
||||
inv_name(obj, drop)
|
||||
register struct object *obj;
|
||||
bool drop;
|
||||
{
|
||||
register char *pb;
|
||||
|
||||
pb = prbuf;
|
||||
pb[0] = '\0';
|
||||
switch(obj->o_type) {
|
||||
case SCROLL:
|
||||
if (obj->o_count == 1)
|
||||
sprintf(pb, "A %sscroll ", blesscurse(obj->o_flags));
|
||||
else
|
||||
sprintf(pb, "%d %sscrolls ",
|
||||
obj->o_count, blesscurse(obj->o_flags));
|
||||
pb = &pb[strlen(pb)];
|
||||
if (s_know[obj->o_which] || (obj->o_flags & ISPOST))
|
||||
sprintf(pb, "of %s", s_magic[obj->o_which].mi_name);
|
||||
else if (s_guess[obj->o_which])
|
||||
sprintf(pb, "named %s", s_guess[obj->o_which]);
|
||||
else
|
||||
sprintf(pb, "titled '%s'", s_names[obj->o_which]);
|
||||
when POTION:
|
||||
if (obj->o_count == 1)
|
||||
sprintf(pb, "A %spotion ", blesscurse(obj->o_flags));
|
||||
else
|
||||
sprintf(pb, "%d %spotions ",
|
||||
obj->o_count, blesscurse(obj->o_flags));
|
||||
pb = &pb[strlen(pb)];
|
||||
if (p_know[obj->o_which])
|
||||
sprintf(pb, "of %s (%s)", p_magic[obj->o_which].mi_name,
|
||||
p_kind(obj));
|
||||
else if (obj->o_flags & ISPOST)
|
||||
sprintf(pb, "of %s", p_magic[obj->o_which].mi_name);
|
||||
else if (p_guess[obj->o_which])
|
||||
sprintf(pb, "named %s (%s)", p_guess[obj->o_which],
|
||||
p_colors[obj->o_which]);
|
||||
else {
|
||||
pb = prbuf;
|
||||
if (obj->o_count == 1)
|
||||
sprintf(pb, "A%s %s potion",
|
||||
vowelstr(p_colors[obj->o_which]),
|
||||
p_colors[obj->o_which]);
|
||||
else
|
||||
sprintf(pb, "%d %s potions",
|
||||
obj->o_count, p_colors[obj->o_which]);
|
||||
}
|
||||
when FOOD:
|
||||
if (obj->o_count == 1)
|
||||
sprintf(pb, "A%s %s", vowelstr(foods[obj->o_which].mi_name),
|
||||
foods[obj->o_which].mi_name);
|
||||
else
|
||||
sprintf(pb, "%d %ss", obj->o_count,foods[obj->o_which].mi_name);
|
||||
when WEAPON:
|
||||
if (obj->o_count > 1)
|
||||
sprintf(pb, "%d ", obj->o_count);
|
||||
else
|
||||
strcpy(pb, "A ");
|
||||
pb = &pb[strlen(pb)];
|
||||
if (obj->o_flags & ISKNOW) {
|
||||
strcat(pb, num(obj->o_hplus, obj->o_dplus));
|
||||
strcat (pb, " ");
|
||||
}
|
||||
strcat(pb, weaps[obj->o_which].w_name);
|
||||
if (obj->o_count > 1)
|
||||
strcat(pb, "s");
|
||||
if (obj == cur_weapon)
|
||||
strcat(pb, " (weapon in hand)");
|
||||
if (obj->o_flags & ISPOISON)
|
||||
strcat(pb, " {Poisoned}");
|
||||
when ARMOR:
|
||||
if (obj->o_flags & ISKNOW) {
|
||||
strcat(pb, num(armors[obj->o_which].a_class - obj->o_ac, 0));
|
||||
strcat(pb, " ");
|
||||
}
|
||||
strcat(pb, armors[obj->o_which].a_name);
|
||||
if (obj == cur_armor)
|
||||
strcat(pb, " (being worn)");
|
||||
when STICK:
|
||||
sprintf(pb, "A %s%s ",
|
||||
blesscurse(obj->o_flags), ws_type[obj->o_which]);
|
||||
pb = &pb[strlen(pb)];
|
||||
if (ws_know[obj->o_which] || obj->o_flags & ISKNOW)
|
||||
sprintf(pb, "of %s%s (%s)", ws_magic[obj->o_which].mi_name,
|
||||
charge_str(obj), ws_made[obj->o_which]);
|
||||
else if (obj->o_flags & ISPOST)
|
||||
sprintf(pb, "of %s", ws_magic[obj->o_which].mi_name);
|
||||
else if (ws_guess[obj->o_which])
|
||||
sprintf(pb, "named %s (%s)", ws_guess[obj->o_which],
|
||||
ws_made[obj->o_which]);
|
||||
else {
|
||||
pb = prbuf;
|
||||
sprintf(pb, "A %s %s", ws_made[obj->o_which],
|
||||
ws_type[obj->o_which]);
|
||||
}
|
||||
if (obj == cur_weapon)
|
||||
strcat(prbuf, " (weapon in hand)");
|
||||
when RING:
|
||||
if (r_know[obj->o_which] || obj->o_flags & ISKNOW)
|
||||
sprintf(pb, "A%s ring of %s (%s)", ring_num(obj),
|
||||
r_magic[obj->o_which].mi_name, r_stones[obj->o_which]);
|
||||
else if (obj->o_flags & ISPOST)
|
||||
sprintf(pb, "A ring of %s", r_magic[obj->o_which].mi_name);
|
||||
else if (r_guess[obj->o_which])
|
||||
sprintf(pb, "A ring named %s (%s)",
|
||||
r_guess[obj->o_which], r_stones[obj->o_which]);
|
||||
else
|
||||
sprintf(pb, "A%s %s ring", vowelstr(r_stones[obj->o_which]),
|
||||
r_stones[obj->o_which]);
|
||||
if (obj == cur_ring[LEFT_1] || obj == cur_ring[LEFT_2] ||
|
||||
obj == cur_ring[LEFT_3] || obj == cur_ring[LEFT_4])
|
||||
strcat(pb, " (on left hand)");
|
||||
if (obj == cur_ring[RIGHT_1] || obj == cur_ring[RIGHT_2] ||
|
||||
obj == cur_ring[RIGHT_3] || obj == cur_ring[RIGHT_4])
|
||||
strcat(pb, " (on right hand)");
|
||||
when RELIC:
|
||||
if (obj->o_flags & ISKNOW)
|
||||
switch(obj->o_which) {
|
||||
case QUILL_NAGROM:
|
||||
sprintf(pb, "%s%s", rel_magic[obj->o_which].mi_name,
|
||||
charge_str(obj));
|
||||
otherwise:
|
||||
strcpy(pb, rel_magic[obj->o_which].mi_name);
|
||||
}
|
||||
else switch(obj->o_which) {
|
||||
case MUSTY_DAGGER:
|
||||
strcpy(pb, "Two very fine daggers marked MDDE");
|
||||
when EMORI_CLOAK:
|
||||
strcpy(pb, "A silk cloak");
|
||||
when HEIL_ANKH:
|
||||
strcpy(pb, "A golden ankh");
|
||||
when MING_STAFF:
|
||||
strcpy(pb, "A finely carved staff");
|
||||
when ORCUS_WAND:
|
||||
strcpy(pb, "A sparkling ivory wand");
|
||||
when ASMO_ROD:
|
||||
strcpy(pb, "A glistening ebony rod");
|
||||
when YENDOR_AMULET:
|
||||
strcpy(pb, "A silver amulet");
|
||||
when STONEBONES_AMULET:
|
||||
strcpy(pb, "A stone amulet");
|
||||
when BRIAN_MANDOLIN:
|
||||
strcpy(pb, "A gleaming mandolin");
|
||||
when HRUGGEK_MSTAR:
|
||||
strcpy(pb, "A huge morning star");
|
||||
when AXE_AKLAD:
|
||||
strcpy(pb, "A jewel encrusted axe");
|
||||
when QUILL_NAGROM:
|
||||
strcpy(pb, "A bright white feather");
|
||||
when GERYON_HORN:
|
||||
strcpy(pb, "A jet black horn");
|
||||
when YEENOGHU_FLAIL:
|
||||
strcpy(pb, "A shimmering flail");
|
||||
when SURTUR_RING:
|
||||
strcpy(pb, "A fiery red ring");
|
||||
otherwise:
|
||||
strcpy(pb, "A magical item");
|
||||
}
|
||||
|
||||
/* Take care of wielding and wearing */
|
||||
switch (obj->o_which) {
|
||||
case EMORI_CLOAK:
|
||||
if (cur_armor == NULL && cur_misc[WEAR_CLOAK] == NULL)
|
||||
strcat(pb, " (being worn)");
|
||||
if (obj->o_charges)
|
||||
strcat(pb, " [charged]");
|
||||
else
|
||||
strcat(pb, " [discharged]");
|
||||
when HEIL_ANKH:
|
||||
if (cur_relic[HEIL_ANKH]) strcat(pb, " (in hand)");
|
||||
when EYE_VECNA:
|
||||
if (cur_relic[EYE_VECNA]) strcat(pb, " (in eye socket)");
|
||||
when STONEBONES_AMULET:
|
||||
if (cur_relic[STONEBONES_AMULET])
|
||||
strcat(pb, " (in chest)");
|
||||
when YENDOR_AMULET:
|
||||
if (cur_relic[YENDOR_AMULET])
|
||||
strcat(pb, " (in chest)");
|
||||
when MUSTY_DAGGER:
|
||||
case HRUGGEK_MSTAR:
|
||||
case AXE_AKLAD:
|
||||
case YEENOGHU_FLAIL:
|
||||
case MING_STAFF:
|
||||
case ASMO_ROD:
|
||||
case ORCUS_WAND:
|
||||
if (cur_weapon == obj) strcat(pb, " (weapon in hand)");
|
||||
when SURTUR_RING:
|
||||
if (cur_relic[SURTUR_RING])
|
||||
strcat(pb, " (in nose)");
|
||||
}
|
||||
when MM:
|
||||
if (m_know[obj->o_which])
|
||||
strcpy(pb, misc_name(obj));
|
||||
else {
|
||||
switch (obj->o_which) {
|
||||
case MM_JUG:
|
||||
case MM_BEAKER:
|
||||
strcpy(pb, "A bottle");
|
||||
when MM_KEOGHTOM:
|
||||
strcpy(pb, "A jar");
|
||||
when MM_JEWEL:
|
||||
strcpy(pb, "An amulet");
|
||||
when MM_BOOK:
|
||||
case MM_SKILLS:
|
||||
strcpy(pb, "A book");
|
||||
when MM_ELF_BOOTS:
|
||||
case MM_DANCE:
|
||||
strcpy(pb, "A pair of boots");
|
||||
when MM_BRACERS:
|
||||
strcpy(pb, "A pair of bracers");
|
||||
when MM_OPEN:
|
||||
case MM_HUNGER:
|
||||
strcpy(pb, "A chime");
|
||||
when MM_DISP:
|
||||
case MM_R_POWERLESS:
|
||||
case MM_PROTECT:
|
||||
strcpy(pb, "A cloak");
|
||||
when MM_DRUMS:
|
||||
strcpy(pb, "A set of drums");
|
||||
when MM_DISAPPEAR:
|
||||
case MM_CHOKE:
|
||||
strcpy(pb, "A pouch of dust");
|
||||
when MM_G_DEXTERITY:
|
||||
case MM_G_OGRE:
|
||||
case MM_FUMBLE:
|
||||
strcpy(pb, "A pair of gauntlets");
|
||||
when MM_ADAPTION:
|
||||
case MM_STRANGLE:
|
||||
strcpy(pb, "A necklace");
|
||||
otherwise:
|
||||
strcpy(pb, "A magical item");
|
||||
}
|
||||
if (m_guess[obj->o_which]) {
|
||||
strcat(pb, " named: ");
|
||||
strcat(pb, m_guess[obj->o_which]);
|
||||
}
|
||||
}
|
||||
if (obj == cur_misc[WEAR_BOOTS] ||
|
||||
obj == cur_misc[WEAR_BRACERS] ||
|
||||
obj == cur_misc[WEAR_CLOAK] ||
|
||||
obj == cur_misc[WEAR_GAUNTLET] ||
|
||||
obj == cur_misc[WEAR_NECKLACE] ||
|
||||
obj == cur_misc[WEAR_JEWEL])
|
||||
strcat(pb, " (being worn)");
|
||||
when GOLD:
|
||||
sprintf(pb, "%d Pieces of Gold", obj->o_count);
|
||||
otherwise:
|
||||
debug("Picked up something funny");
|
||||
sprintf(pb, "Something bizarre %s", unctrl(obj->o_type));
|
||||
}
|
||||
|
||||
/* Is it marked? */
|
||||
if (obj->o_mark[0]) {
|
||||
pb = &pb[strlen(pb)];
|
||||
sprintf(pb, " <%s>", obj->o_mark);
|
||||
}
|
||||
|
||||
if (obj->o_flags & ISPROT)
|
||||
strcat(pb, " [protected]");
|
||||
if (drop && isupper(prbuf[0]))
|
||||
prbuf[0] = tolower(prbuf[0]);
|
||||
else if (!drop && islower(*prbuf))
|
||||
*prbuf = toupper(*prbuf);
|
||||
if (!drop)
|
||||
strcat(pb, ".");
|
||||
/*
|
||||
* Truncate if long. Use cols-4 to offset the "pack letter" of a normal
|
||||
* inventory listing.
|
||||
*/
|
||||
prbuf[cols-4] = '\0';
|
||||
return prbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* weap_name:
|
||||
* Return the name of a weapon.
|
||||
*/
|
||||
char *
|
||||
weap_name(obj)
|
||||
register struct object *obj;
|
||||
{
|
||||
switch (obj->o_type) {
|
||||
case WEAPON:
|
||||
return(weaps[obj->o_which].w_name);
|
||||
when MISSILE:
|
||||
return(ws_magic[obj->o_which].mi_name);
|
||||
when RELIC:
|
||||
switch (obj->o_which) {
|
||||
case MUSTY_DAGGER:
|
||||
return("daggers");
|
||||
when YEENOGHU_FLAIL:
|
||||
return("flail");
|
||||
when AXE_AKLAD:
|
||||
return("axe");
|
||||
when HRUGGEK_MSTAR:
|
||||
return("morning star");
|
||||
when MING_STAFF:
|
||||
return("staff");
|
||||
when ORCUS_WAND:
|
||||
return("wand");
|
||||
when ASMO_ROD:
|
||||
return("rod");
|
||||
}
|
||||
}
|
||||
return("weapon");
|
||||
}
|
||||
|
||||
/*
|
||||
* drop:
|
||||
* put something down
|
||||
*/
|
||||
drop(item)
|
||||
struct linked_list *item;
|
||||
{
|
||||
register char ch;
|
||||
register struct linked_list *obj, *nobj;
|
||||
register struct object *op;
|
||||
|
||||
if (item == NULL) {
|
||||
/* We charge 2 movement times to drop something */
|
||||
if (player.t_action == C_DROP && player.t_using != NULL) {
|
||||
obj = player.t_using;
|
||||
player.t_using = NULL;
|
||||
player.t_action = A_NIL;
|
||||
}
|
||||
|
||||
/* t_action == C_DROP always when called from command() */
|
||||
else {
|
||||
if ((obj = get_item(pack, "drop", ALL, FALSE, FALSE)) == NULL) {
|
||||
player.t_action = A_NIL;
|
||||
player.t_using = NULL;
|
||||
return(FALSE);
|
||||
}
|
||||
if (player.t_action == C_DROP) {
|
||||
player.t_using = obj;
|
||||
player.t_no_move = 2 * movement(&player);
|
||||
return(FALSE); /* We'll come back after we've waited */
|
||||
}
|
||||
}
|
||||
|
||||
switch(ch = CCHAR(mvwinch(stdscr, hero.y, hero.x))) {
|
||||
case PASSAGE:
|
||||
case SCROLL:
|
||||
case POTION:
|
||||
case WEAPON:
|
||||
case FLOOR:
|
||||
case STICK:
|
||||
case ARMOR:
|
||||
case POOL:
|
||||
case RELIC:
|
||||
case GOLD:
|
||||
case FOOD:
|
||||
case RING:
|
||||
case MM:
|
||||
break;
|
||||
default:
|
||||
msg("Can't leave it here");
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
else {
|
||||
obj = item;
|
||||
}
|
||||
op = OBJPTR(obj);
|
||||
if (!dropcheck(op))
|
||||
return(FALSE);
|
||||
|
||||
/*
|
||||
* If it is a scare monster scroll, curse it
|
||||
*/
|
||||
if (op->o_type == SCROLL && op->o_which == S_SCARE) {
|
||||
if (op->o_flags & ISBLESSED)
|
||||
op->o_flags &= ~ISBLESSED;
|
||||
else op->o_flags |= ISCURSED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Take it out of the pack
|
||||
*/
|
||||
if (op->o_count >= 2 && op->o_group == 0)
|
||||
{
|
||||
nobj = new_item(sizeof *op);
|
||||
op->o_count--;
|
||||
op = OBJPTR(nobj);
|
||||
*op = *(OBJPTR(obj));
|
||||
op->o_count = 1;
|
||||
obj = nobj;
|
||||
}
|
||||
else {
|
||||
detach(pack, obj);
|
||||
inpack--;
|
||||
}
|
||||
if(ch == POOL) {
|
||||
msg("Your %s sinks out of sight.",inv_name(op,TRUE));
|
||||
o_discard(obj);
|
||||
}
|
||||
else if (levtype == POSTLEV) {
|
||||
op->o_pos = hero; /* same place as hero */
|
||||
fall(obj,FALSE);
|
||||
if (item == NULL) /* if item wasn't sold */
|
||||
msg("Thanks for your donation to the fiend's flea market.");
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Link it into the level object list
|
||||
*/
|
||||
attach(lvl_obj, obj);
|
||||
mvaddch(hero.y, hero.x, op->o_type);
|
||||
op->o_pos = hero;
|
||||
msg("Dropped %s", inv_name(op, TRUE));
|
||||
}
|
||||
updpack(FALSE, &player);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* do special checks for dropping or unweilding|unwearing|unringing
|
||||
*/
|
||||
dropcheck(op)
|
||||
register struct object *op;
|
||||
{
|
||||
int save_max;
|
||||
|
||||
if (op == NULL)
|
||||
return TRUE;
|
||||
if (levtype == POSTLEV) {
|
||||
if ((op->o_flags & ISCURSED) && (op->o_flags & ISKNOW)) {
|
||||
msg("The trader does not accept your shoddy merchandise");
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Player will not drop a relic */
|
||||
if (op->o_type == RELIC) {
|
||||
/*
|
||||
* There is a 1% cumulative chance per relic that trying to get
|
||||
* rid of it will cause the relic to turn on the player.
|
||||
*/
|
||||
if (rnd(100) < cur_relic[op->o_which]++) {
|
||||
msg("The artifact turns on you.");
|
||||
msg("It crushes your mind!!! -- More --");
|
||||
pstats.s_hpt = -1;
|
||||
wait_for (' ');
|
||||
death(D_RELIC);
|
||||
}
|
||||
else {
|
||||
if (terse) msg("Can't release it.");
|
||||
else msg("You cannot bring yourself to release it.");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we aren't wearing it, we can drop it */
|
||||
if (!is_current(op)) return TRUE;
|
||||
|
||||
/* At this point, we know we are wearing the item */
|
||||
if (op->o_flags & ISCURSED) {
|
||||
msg("You can't. It appears to be cursed.");
|
||||
return FALSE;
|
||||
}
|
||||
if (op->o_type == RING && cur_misc[WEAR_GAUNTLET] != NULL) {
|
||||
msg ("You have to remove your gauntlets first!");
|
||||
return FALSE;
|
||||
}
|
||||
cur_null(op); /* set current to NULL */
|
||||
if (op->o_type == RING) {
|
||||
switch (op->o_which) {
|
||||
case R_ADDSTR: save_max = max_stats.s_str;
|
||||
chg_str(-op->o_ac);
|
||||
max_stats.s_str = save_max;
|
||||
when R_ADDHIT: pstats.s_dext -= op->o_ac;
|
||||
when R_ADDINTEL: pstats.s_intel -= op->o_ac;
|
||||
when R_ADDWISDOM: pstats.s_wisdom -= op->o_ac;
|
||||
when R_SEEINVIS: if (!ISWEARING(R_SEEINVIS) &&
|
||||
find_slot(unsee) == 0) {
|
||||
turn_off(player, CANSEE);
|
||||
msg("The tingling feeling leaves your eyes");
|
||||
}
|
||||
light(&hero);
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
when R_WARMTH: if (!ISWEARING(R_WARMTH) && !find_slot(nocold))
|
||||
turn_off(player, NOCOLD);
|
||||
when R_FIRE: if (!ISWEARING(R_FIRE) &&
|
||||
!cur_relic[SURTUR_RING] &&
|
||||
!find_slot(nofire))
|
||||
turn_off(player, NOFIRE);
|
||||
when R_LIGHT: {
|
||||
if(roomin(&hero) != NULL) {
|
||||
light(&hero);
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
}
|
||||
}
|
||||
when R_SEARCH: kill_daemon(ring_search);
|
||||
when R_TELEPORT: kill_daemon(ring_teleport);
|
||||
}
|
||||
}
|
||||
else if (op->o_type == MM) {
|
||||
switch (op->o_which) {
|
||||
case MM_ADAPTION:
|
||||
turn_off(player, NOGAS);
|
||||
|
||||
when MM_STRANGLE:
|
||||
msg("You can breathe again.....whew!");
|
||||
kill_daemon(strangle);
|
||||
|
||||
when MM_DANCE:
|
||||
turn_off(player, ISDANCE);
|
||||
msg ("Your feet take a break.....whew!");
|
||||
|
||||
when MM_FUMBLE:
|
||||
kill_daemon(fumble);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* return a new thing
|
||||
*/
|
||||
struct linked_list *
|
||||
new_thing(thing_type, allow_curse)
|
||||
int thing_type;
|
||||
bool allow_curse;
|
||||
{
|
||||
register struct linked_list *item;
|
||||
register struct object *cur;
|
||||
register int j;
|
||||
register int blesschance, cursechance;
|
||||
|
||||
item = new_item(sizeof *cur);
|
||||
cur = OBJPTR(item);
|
||||
cur->o_hplus = cur->o_dplus = 0;
|
||||
strncpy(cur->o_damage, "0d0", sizeof(cur->o_damage));
|
||||
strncpy(cur->o_hurldmg, "0d0", sizeof(cur->o_hurldmg));
|
||||
cur->o_ac = 0;
|
||||
cur->o_count = 1;
|
||||
cur->o_group = 0;
|
||||
cur->contents = NULL;
|
||||
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.
|
||||
*/
|
||||
blesschance = rnd(100);
|
||||
if (allow_curse) cursechance = rnd(100);
|
||||
else cursechance = 100; /* No chance of curse */
|
||||
|
||||
/* Get the type of item (pick one if 'any' is specified) */
|
||||
if (thing_type == ALL) j = pick_one(things, NUMTHINGS);
|
||||
else j = thing_type;
|
||||
|
||||
/*
|
||||
* make sure he gets his vitamins
|
||||
*/
|
||||
if (thing_type == ALL && no_food > 3)
|
||||
j = 2;
|
||||
/*
|
||||
* limit the number of foods on a level because it sometimes
|
||||
* gets out of hand in the "deep" levels where there is a
|
||||
* treasure room on most every level with lots of food in it
|
||||
*/
|
||||
while (thing_type == ALL && levtype != POSTLEV && foods_this_level > 2 &&
|
||||
j == 2)
|
||||
j = pick_one(things, NUMTHINGS); /* not too many.... */
|
||||
switch (j)
|
||||
{
|
||||
case TYP_POTION:
|
||||
cur->o_type = POTION;
|
||||
do {
|
||||
cur->o_which = pick_one(p_magic, MAXPOTIONS);
|
||||
} while (!allow_curse && p_magic[cur->o_which].mi_curse == 100);
|
||||
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;
|
||||
|
||||
/* If we made a gain ability potion, see what kind it is */
|
||||
if (cur->o_which == P_ABIL) cur->o_kind = rnd(NUMABILITIES);
|
||||
|
||||
when TYP_SCROLL:
|
||||
cur->o_type = SCROLL;
|
||||
do {
|
||||
cur->o_which = pick_one(s_magic, MAXSCROLLS);
|
||||
} while (!allow_curse && s_magic[cur->o_which].mi_curse == 100);
|
||||
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;
|
||||
when TYP_FOOD:
|
||||
no_food = 0;
|
||||
cur->o_type = FOOD;
|
||||
cur->o_weight = things[TYP_FOOD].mi_wght;
|
||||
cur->o_count += extras();
|
||||
foods_this_level += cur->o_count;
|
||||
cur->o_which = pick_one(foods, MAXFOODS);
|
||||
when TYP_WEAPON:
|
||||
cur->o_type = WEAPON;
|
||||
cur->o_which = rnd(MAXWEAPONS);
|
||||
init_weapon(cur, cur->o_which);
|
||||
if (cursechance < 20)
|
||||
{
|
||||
|
||||
cur->o_flags |= ISCURSED;
|
||||
cur->o_hplus -= rnd(2) + 1;
|
||||
cur->o_dplus -= rnd(2) + 1;
|
||||
}
|
||||
else if (blesschance < 50) {
|
||||
|
||||
cur->o_hplus += rnd(5) + 1;
|
||||
cur->o_dplus += rnd(5) + 1;
|
||||
}
|
||||
when 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;
|
||||
cur->o_weight = armors[j].a_wght;
|
||||
if (cursechance < 20)
|
||||
{
|
||||
cur->o_flags |= ISCURSED;
|
||||
cur->o_ac += rnd(3)+1;
|
||||
}
|
||||
else if (blesschance < 35)
|
||||
cur->o_ac -= rnd(3)+1;
|
||||
when TYP_RING:
|
||||
cur->o_type = RING;
|
||||
do {
|
||||
cur->o_which = pick_one(r_magic, MAXRINGS);
|
||||
} while (!allow_curse && r_magic[cur->o_which].mi_curse == 100);
|
||||
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:
|
||||
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++;
|
||||
when 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;
|
||||
}
|
||||
when TYP_STICK:
|
||||
cur->o_type = STICK;
|
||||
do {
|
||||
cur->o_which = pick_one(ws_magic, MAXSTICKS);
|
||||
} while (!allow_curse && ws_magic[cur->o_which].mi_curse == 100);
|
||||
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;
|
||||
when TYP_MM:
|
||||
cur->o_type = MM;
|
||||
do {
|
||||
cur->o_which = pick_one(m_magic, MAXMM);
|
||||
} while (!allow_curse && m_magic[cur->o_which].mi_curse == 100);
|
||||
cur->o_weight = things[TYP_MM].mi_wght;
|
||||
if (cursechance < m_magic[cur->o_which].mi_curse)
|
||||
cur->o_flags |= ISCURSED;
|
||||
else if (blesschance < m_magic[cur->o_which].mi_bless)
|
||||
cur->o_flags |= ISBLESSED;
|
||||
switch (cur->o_which) {
|
||||
case MM_JUG:
|
||||
switch(rnd(11)) {
|
||||
case 0: cur->o_ac = P_PHASE;
|
||||
when 1: cur->o_ac = P_CLEAR;
|
||||
when 2: cur->o_ac = P_SEEINVIS;
|
||||
when 3: cur->o_ac = P_HEALING;
|
||||
when 4: cur->o_ac = P_MFIND;
|
||||
when 5: cur->o_ac = P_TFIND;
|
||||
when 6: cur->o_ac = P_HASTE;
|
||||
when 7: cur->o_ac = P_RESTORE;
|
||||
when 8: cur->o_ac = P_FLY;
|
||||
when 9: cur->o_ac = P_SKILL;
|
||||
when 10:cur->o_ac = P_FFIND;
|
||||
}
|
||||
when MM_OPEN:
|
||||
cur->o_ac = (4 + rnd(5)) * 5;
|
||||
when MM_HUNGER:
|
||||
case MM_DRUMS:
|
||||
case MM_DISAPPEAR:
|
||||
case MM_CHOKE:
|
||||
case MM_KEOGHTOM:
|
||||
cur->o_ac = 3 + (rnd(3)+1) * 3;
|
||||
when MM_BRACERS:
|
||||
if (cur->o_flags & ISCURSED)
|
||||
cur->o_ac = -(rnd(3)+1);
|
||||
else
|
||||
cur->o_ac = rnd(8)+1;
|
||||
when MM_PROTECT:
|
||||
if (cur->o_flags & ISCURSED)
|
||||
cur->o_ac = -(rnd(3)+1);
|
||||
else
|
||||
cur->o_ac = rnd(5)+1;
|
||||
when MM_DISP:
|
||||
cur->o_ac = 2;
|
||||
when MM_SKILLS: /* set it to a character class */
|
||||
cur->o_ac = rnd(NUM_CHARTYPES-1);
|
||||
otherwise:
|
||||
cur->o_ac = 0;
|
||||
}
|
||||
otherwise:
|
||||
debug("Picked a bad kind of object");
|
||||
wait_for(' ');
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
/*
|
||||
* provide a new item tailored to specification
|
||||
*/
|
||||
struct linked_list *
|
||||
spec_item(type, which, hit, damage)
|
||||
int type, which, hit, damage;
|
||||
{
|
||||
register struct linked_list *item;
|
||||
register struct object *obj;
|
||||
|
||||
item = new_item(sizeof *obj);
|
||||
obj = OBJPTR(item);
|
||||
obj->o_count = 1;
|
||||
obj->o_group = 0;
|
||||
obj->contents = NULL;
|
||||
obj->o_type = type;
|
||||
obj->o_which = which;
|
||||
strncpy(obj->o_damage, "0d0", sizeof(obj->o_damage));
|
||||
strncpy(obj->o_hurldmg, "0d0", sizeof(obj->o_hurldmg));
|
||||
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;
|
||||
|
||||
/* Handle special characteristics */
|
||||
switch (type) {
|
||||
case WEAPON:
|
||||
init_weapon(obj, which);
|
||||
obj->o_hplus = hit;
|
||||
obj->o_dplus = damage;
|
||||
obj->o_ac = 10;
|
||||
|
||||
if (hit > 0 || damage > 0) obj->o_flags |= ISBLESSED;
|
||||
else if (hit < 0 || damage < 0) obj->o_flags |= ISCURSED;
|
||||
|
||||
when ARMOR:
|
||||
obj->o_ac = armors[which].a_class - hit;
|
||||
if (hit > 0) obj->o_flags |= ISBLESSED;
|
||||
else if (hit < 0) obj->o_flags |= ISCURSED;
|
||||
|
||||
when RING:
|
||||
obj->o_ac = hit;
|
||||
switch (obj->o_which) {
|
||||
case R_ADDSTR:
|
||||
case R_ADDWISDOM:
|
||||
case R_ADDINTEL:
|
||||
case R_PROTECT:
|
||||
case R_ADDHIT:
|
||||
case R_ADDDAM:
|
||||
case R_DIGEST:
|
||||
if (hit > 1) obj->o_flags |= ISBLESSED;
|
||||
else if (hit < 0) obj->o_flags |= ISCURSED;
|
||||
}
|
||||
|
||||
when STICK:
|
||||
fix_stick(obj);
|
||||
obj->o_charges = hit;
|
||||
|
||||
when GOLD:
|
||||
obj->o_type = GOLD;
|
||||
obj->o_count = GOLDCALC;
|
||||
obj->o_ac = 11;
|
||||
|
||||
when MM:
|
||||
obj->o_type = MM;
|
||||
obj->o_ac = hit;
|
||||
|
||||
when RELIC:
|
||||
/* Handle weight here since these are all created uniquely */
|
||||
obj->o_weight = things[TYP_RELIC].mi_wght;
|
||||
if (obj->o_which == EMORI_CLOAK)
|
||||
obj->o_charges = 1;
|
||||
|
||||
}
|
||||
return(item);
|
||||
}
|
||||
|
||||
/*
|
||||
* pick an item out of a list of nitems possible magic items
|
||||
*/
|
||||
pick_one(magic, nitems)
|
||||
register struct magic_item *magic;
|
||||
int nitems;
|
||||
{
|
||||
register struct magic_item *end;
|
||||
register int i;
|
||||
register struct magic_item *start;
|
||||
|
||||
start = magic;
|
||||
for (end = &magic[nitems], i = rnd(1000); magic < end; magic++)
|
||||
if (i < magic->mi_prob)
|
||||
break;
|
||||
if (magic == end)
|
||||
{
|
||||
if (wizard)
|
||||
{
|
||||
msg("bad pick_one: %d from %d items", i, nitems);
|
||||
for (magic = start; magic < end; magic++)
|
||||
msg("%s: %d%%", magic->mi_name, magic->mi_prob);
|
||||
}
|
||||
magic = start;
|
||||
}
|
||||
return (int) (magic - start);
|
||||
}
|
||||
|
||||
|
||||
/* blesscurse returns whether, according to the flag, the object is
|
||||
* blessed, cursed, or neither
|
||||
*/
|
||||
|
||||
char *
|
||||
blesscurse(flags)
|
||||
int flags;
|
||||
{
|
||||
if (flags & ISKNOW) {
|
||||
if (flags & ISCURSED) return("cursed ");
|
||||
if (flags & ISBLESSED) return("blessed ");
|
||||
return("normal ");
|
||||
}
|
||||
return("");
|
||||
}
|
||||
|
||||
/*
|
||||
* p_kind returns the type of potion for some types of identified potions;
|
||||
* otherwise, it returns the color.
|
||||
*/
|
||||
|
||||
char *
|
||||
p_kind(obj)
|
||||
struct object *obj; /* We assume that obj points to a potion */
|
||||
{
|
||||
if (obj->o_which == P_ABIL) return(abilities[obj->o_kind]);
|
||||
else return(p_colors[obj->o_which]);
|
||||
}
|
||||
|
||||
/*
|
||||
* extras:
|
||||
* Return the number of extra items to be created
|
||||
*/
|
||||
extras()
|
||||
{
|
||||
reg int i;
|
||||
|
||||
i = rnd(100);
|
||||
if (i < 4) /* 4% for 2 more */
|
||||
return (2);
|
||||
else if (i < 11) /* 7% for 1 more */
|
||||
return (1);
|
||||
else /* otherwise no more */
|
||||
return (0);
|
||||
}
|
||||
539
arogue7/trader.c
Normal file
539
arogue7/trader.c
Normal file
|
|
@ -0,0 +1,539 @@
|
|||
/*
|
||||
* trader.c - Anything to do with trading posts
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Anything to do with trading posts
|
||||
*/
|
||||
|
||||
#include "curses.h"
|
||||
#include "rogue.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* buy_it:
|
||||
* Buy the item on which the hero stands
|
||||
*/
|
||||
buy_it()
|
||||
{
|
||||
reg int wh;
|
||||
struct linked_list *item;
|
||||
|
||||
if (purse <= 0) {
|
||||
msg("You have no money.");
|
||||
return;
|
||||
}
|
||||
if (curprice < 0) { /* if not yet priced */
|
||||
wh = price_it();
|
||||
if (!wh) /* nothing to price */
|
||||
return;
|
||||
msg("Do you want to buy it? ");
|
||||
do {
|
||||
wh = tolower(readchar());
|
||||
if (wh == ESCAPE || wh == 'n') {
|
||||
msg("");
|
||||
return;
|
||||
}
|
||||
} until(wh == 'y');
|
||||
}
|
||||
mpos = 0;
|
||||
if (curprice > purse) {
|
||||
msg("You can't afford to buy that %s !",curpurch);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* See if the hero has done all his transacting
|
||||
*/
|
||||
if (!open_market())
|
||||
return;
|
||||
/*
|
||||
* The hero bought the item here
|
||||
*/
|
||||
item = find_obj(hero.y, hero.x);
|
||||
mpos = 0;
|
||||
if (add_pack(NULL, TRUE, &item)) { /* try to put it in his pack */
|
||||
purse -= curprice; /* take his money */
|
||||
++trader; /* another transaction */
|
||||
trans_line(); /* show remaining deals */
|
||||
curprice = -1; /* reset stuff */
|
||||
curpurch[0] = 0;
|
||||
whatis (item); /* identify it after purchase */
|
||||
(OBJPTR(item))->o_flags &= ~ISPOST; /* turn off ISPOST */
|
||||
msg("%s", inv_name(OBJPTR(item), TRUE));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* do_post:
|
||||
* Put a trading post room and stuff on the screen
|
||||
*/
|
||||
do_post(startup)
|
||||
bool startup; /* True if equipping the player at the beginning of the game */
|
||||
{
|
||||
coord tp;
|
||||
reg int i, j, k;
|
||||
reg struct room *rp;
|
||||
reg struct object *op;
|
||||
reg struct linked_list *ll;
|
||||
|
||||
o_free_list(lvl_obj); /* throw old items away */
|
||||
|
||||
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
|
||||
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 = 1; /* 2nd line */
|
||||
draw_room(rp); /* draw the only room */
|
||||
|
||||
/* Are we equipping the player? */
|
||||
if (startup) {
|
||||
int wpt;
|
||||
|
||||
/*
|
||||
* Give the rogue some weaponry.
|
||||
*/
|
||||
for (wpt=0; wpt<MAXWEAPONS; wpt++) {
|
||||
ll = spec_item(WEAPON, wpt, rnd(2), rnd(2)+1);
|
||||
attach(lvl_obj, ll);
|
||||
op = OBJPTR(ll);
|
||||
op->o_flags |= (ISPOST | ISKNOW);
|
||||
do {
|
||||
rnd_pos(rp,&tp);
|
||||
} until (mvinch(tp.y, tp.x) == FLOOR);
|
||||
op->o_pos = tp;
|
||||
mvaddch(tp.y,tp.x,op->o_type);
|
||||
}
|
||||
|
||||
/*
|
||||
* And his suit of armor.......
|
||||
* Thieves can only wear leather armor,
|
||||
* so make sure some is available for them.
|
||||
*/
|
||||
for (i=0; i<MAXARMORS; i++) {
|
||||
ll = spec_item(ARMOR, i, 0, 0);
|
||||
attach(lvl_obj, ll);
|
||||
op = OBJPTR(ll);
|
||||
op->o_flags |= (ISPOST | ISKNOW);
|
||||
op->o_weight = armors[i].a_wght;
|
||||
do {
|
||||
rnd_pos(rp,&tp);
|
||||
} until (mvinch(tp.y, tp.x) == FLOOR);
|
||||
op->o_pos = tp;
|
||||
mvaddch(tp.y,tp.x,op->o_type);
|
||||
}
|
||||
|
||||
/* Now create some wands */
|
||||
for (i=rnd(4)+2; i>0; i--) {
|
||||
switch (rnd(8)) {
|
||||
case 0: j = WS_SLOW_M;
|
||||
when 1: j = WS_TELMON;
|
||||
when 2: j = WS_CONFMON;
|
||||
when 3: j = WS_PARALYZE;
|
||||
when 4: j = WS_MDEG;
|
||||
when 5: j = WS_WONDER;
|
||||
when 6: j = WS_FEAR;
|
||||
when 7: j = WS_LIGHT;
|
||||
}
|
||||
ll = spec_item(STICK, j, 0, 0);
|
||||
attach(lvl_obj, ll);
|
||||
op = OBJPTR(ll);
|
||||
|
||||
/* Let clerics and MU'S know what kind they are */
|
||||
switch (player.t_ctype) {
|
||||
case C_MAGICIAN:
|
||||
case C_CLERIC:
|
||||
case C_DRUID:
|
||||
op->o_flags |= (ISPOST | ISKNOW);
|
||||
otherwise:
|
||||
op->o_flags |= ISPOST;
|
||||
}
|
||||
fix_stick(op);
|
||||
do {
|
||||
rnd_pos(rp,&tp);
|
||||
} until (mvinch(tp.y, tp.x) == FLOOR);
|
||||
op->o_pos = tp;
|
||||
mvaddch(tp.y,tp.x,op->o_type);
|
||||
}
|
||||
|
||||
/* Now let's make some rings */
|
||||
for (i=rnd(4)+3; i>0; i--) {
|
||||
k = 0;
|
||||
switch (rnd(15)) {
|
||||
case 0: j = R_PROTECT; k = roll(1,2);
|
||||
when 1: j = R_ADDSTR; k = roll(1,3);
|
||||
when 2: j = R_ADDHIT; k = roll(1,3);
|
||||
when 3: j = R_ADDDAM; k = roll(1,3);
|
||||
when 4: j = R_DIGEST; k = 1;
|
||||
when 5: j = R_ADDINTEL; k = roll(1,3);
|
||||
when 6: j = R_ADDWISDOM;k = roll(1,3);
|
||||
when 7: j = R_SUSABILITY;
|
||||
when 8: j = R_SEEINVIS;
|
||||
when 9: j = R_ALERT;
|
||||
when 10:j = R_HEALTH;
|
||||
when 11:j = R_HEROISM;
|
||||
when 12:j = R_FIRE;
|
||||
when 13:j = R_WARMTH;
|
||||
when 14:j = R_FREEDOM;
|
||||
}
|
||||
ll = spec_item(RING, j, k, 0);
|
||||
attach(lvl_obj, ll);
|
||||
op = OBJPTR(ll);
|
||||
|
||||
/*
|
||||
* Let fighters, assassins, monks, and thieves know what kind
|
||||
* of rings these are.
|
||||
*/
|
||||
switch (player.t_ctype) {
|
||||
case C_FIGHTER:
|
||||
case C_THIEF:
|
||||
case C_ASSASIN:
|
||||
case C_MONK:
|
||||
op->o_flags |= (ISPOST | ISKNOW);
|
||||
otherwise:
|
||||
op->o_flags |= ISPOST;
|
||||
}
|
||||
do {
|
||||
rnd_pos(rp,&tp);
|
||||
} until (mvinch(tp.y, tp.x) == FLOOR);
|
||||
op->o_pos = tp;
|
||||
mvaddch(tp.y,tp.x,op->o_type);
|
||||
}
|
||||
|
||||
/* Let's offer some potions */
|
||||
for (i=rnd(3)+1; i>0; i--) {
|
||||
/* Choose the type of potion */
|
||||
if (i == 1 && player.t_ctype == C_ASSASIN) j = P_POISON;
|
||||
else switch (rnd(8)) {
|
||||
case 0: j = P_CLEAR;
|
||||
when 1: j = P_HEALING;
|
||||
when 2: j = P_MFIND;
|
||||
when 3: j = P_TFIND;
|
||||
when 4: j = P_HASTE;
|
||||
when 5: j = P_RESTORE;
|
||||
when 6: j = P_FLY;
|
||||
when 7: j = P_FFIND;
|
||||
}
|
||||
|
||||
/* Make the potion */
|
||||
ll = spec_item(POTION, j, 0, 0);
|
||||
attach(lvl_obj, ll);
|
||||
op = OBJPTR(ll);
|
||||
op->o_flags |= ISPOST;
|
||||
|
||||
/* Place the potion */
|
||||
do {
|
||||
rnd_pos(rp,&tp);
|
||||
} until (mvinch(tp.y, tp.x) == FLOOR);
|
||||
op->o_pos = tp;
|
||||
mvaddch(tp.y,tp.x,op->o_type);
|
||||
}
|
||||
|
||||
/* Let's offer some scrolls */
|
||||
for (i=rnd(3)+1; i>0; i--) {
|
||||
/* Choose the type of scrolls */
|
||||
switch (rnd(8)) {
|
||||
case 0: j = S_CONFUSE;
|
||||
when 1: j = S_MAP;
|
||||
when 2: j = S_LIGHT;
|
||||
when 3: j = S_SLEEP;
|
||||
when 4: j = S_IDENT;
|
||||
when 5: j = S_GFIND;
|
||||
when 6: j = S_REMOVE;
|
||||
when 7: j = S_CURING;
|
||||
}
|
||||
|
||||
/* Make the scroll */
|
||||
ll = spec_item(SCROLL, j, 0, 0);
|
||||
attach(lvl_obj, ll);
|
||||
op = OBJPTR(ll);
|
||||
op->o_flags |= ISPOST;
|
||||
|
||||
/* Place the scroll */
|
||||
do {
|
||||
rnd_pos(rp,&tp);
|
||||
} until (mvinch(tp.y, tp.x) == FLOOR);
|
||||
op->o_pos = tp;
|
||||
mvaddch(tp.y,tp.x,op->o_type);
|
||||
}
|
||||
|
||||
/* And finally, let's get some food */
|
||||
for (i=rnd(3)+1; i>0; i--) {
|
||||
ll = spec_item(FOOD, 0, 0, 0);
|
||||
attach(lvl_obj, ll);
|
||||
op = OBJPTR(ll);
|
||||
op->o_weight = things[TYP_FOOD].mi_wght;
|
||||
op->o_flags |= ISPOST;
|
||||
do {
|
||||
rnd_pos(rp,&tp);
|
||||
} until (mvinch(tp.y, tp.x) == FLOOR);
|
||||
op->o_pos = tp;
|
||||
mvaddch(tp.y,tp.x,op->o_type);
|
||||
}
|
||||
}
|
||||
else {
|
||||
i = roll(10, 4); /* 10 to 40 items */
|
||||
for (; i > 0 ; i--) { /* place all the items */
|
||||
ll = new_thing(ALL, TRUE); /* get something */
|
||||
attach(lvl_obj, ll);
|
||||
op = OBJPTR(ll);
|
||||
op->o_flags |= ISPOST; /* object in trading post */
|
||||
do {
|
||||
rnd_pos(rp,&tp);
|
||||
} until (mvinch(tp.y, tp.x) == FLOOR);
|
||||
op->o_pos = tp;
|
||||
mvaddch(tp.y,tp.x,op->o_type);
|
||||
}
|
||||
}
|
||||
wmove(cw,12,0);
|
||||
trader = 0;
|
||||
if (startup) {
|
||||
waddstr(cw,"Welcome to Friendly Fiend's Equipage\n\r");
|
||||
waddstr(cw,"====================================\n\r");
|
||||
}
|
||||
else {
|
||||
waddstr(cw,"Welcome to Friendly Fiend's Flea Market\n\r");
|
||||
waddstr(cw,"=======================================\n\r");
|
||||
}
|
||||
waddstr(cw,"$: Prices object that you stand upon.\n\r");
|
||||
waddstr(cw,"#: Buys the object that you stand upon.\n\r");
|
||||
waddstr(cw,"%: Trades in something in your pack for gold.\n\r");
|
||||
trans_line();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* get_worth:
|
||||
* Calculate an objects worth in gold
|
||||
*/
|
||||
get_worth(obj)
|
||||
reg struct object *obj;
|
||||
{
|
||||
reg int worth, wh;
|
||||
|
||||
worth = 0;
|
||||
wh = obj->o_which;
|
||||
switch (obj->o_type) {
|
||||
case FOOD:
|
||||
worth = 2;
|
||||
when WEAPON:
|
||||
if (wh < MAXWEAPONS) {
|
||||
worth = weaps[wh].w_worth;
|
||||
worth += s_magic[S_ALLENCH].mi_worth *
|
||||
(obj->o_hplus + obj->o_dplus);
|
||||
}
|
||||
when ARMOR:
|
||||
if (wh < MAXARMORS) {
|
||||
worth = armors[wh].a_worth;
|
||||
worth += s_magic[S_ALLENCH].mi_worth *
|
||||
(armors[wh].a_class - obj->o_ac);
|
||||
}
|
||||
when SCROLL:
|
||||
if (wh < MAXSCROLLS)
|
||||
worth = s_magic[wh].mi_worth;
|
||||
when POTION:
|
||||
if (wh < MAXPOTIONS)
|
||||
worth = p_magic[wh].mi_worth;
|
||||
when RING:
|
||||
if (wh < MAXRINGS) {
|
||||
worth = r_magic[wh].mi_worth;
|
||||
worth += obj->o_ac * 40;
|
||||
}
|
||||
when STICK:
|
||||
if (wh < MAXSTICKS) {
|
||||
worth = ws_magic[wh].mi_worth;
|
||||
worth += 20 * obj->o_charges;
|
||||
}
|
||||
when MM:
|
||||
if (wh < MAXMM) {
|
||||
worth = m_magic[wh].mi_worth;
|
||||
switch (wh) {
|
||||
case MM_BRACERS: worth += 40 * obj->o_ac;
|
||||
when MM_PROTECT: worth += 60 * obj->o_ac;
|
||||
when MM_DISP: /* ac already figured in price*/
|
||||
otherwise: worth += 20 * obj->o_ac;
|
||||
}
|
||||
}
|
||||
when RELIC:
|
||||
if (wh < MAXRELIC) {
|
||||
worth = rel_magic[wh].mi_worth;
|
||||
if (wh == quest_item) worth *= 10;
|
||||
}
|
||||
otherwise:
|
||||
worth = 0;
|
||||
}
|
||||
if (obj->o_flags & ISPROT) /* 300% more for protected */
|
||||
worth *= 3;
|
||||
if (obj->o_flags & ISBLESSED) /* 50% more for blessed */
|
||||
worth = worth * 3 / 2;
|
||||
if (obj->o_flags & ISCURSED) /* half for cursed */
|
||||
worth /= 2;
|
||||
if (worth < 0)
|
||||
worth = 0;
|
||||
return worth;
|
||||
}
|
||||
|
||||
/*
|
||||
* open_market:
|
||||
* Retruns TRUE when ok do to transacting
|
||||
*/
|
||||
open_market()
|
||||
{
|
||||
if (trader >= MAXPURCH && !wizard && level != 0) {
|
||||
msg("The market is closed. The stairs are that-a-way.");
|
||||
return FALSE;
|
||||
}
|
||||
else {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* price_it:
|
||||
* Price the object that the hero stands on
|
||||
*/
|
||||
price_it()
|
||||
{
|
||||
reg struct linked_list *item;
|
||||
reg struct object *obj;
|
||||
reg int worth;
|
||||
reg char *str;
|
||||
|
||||
if (!open_market()) /* after buying hours */
|
||||
return FALSE;
|
||||
if ((item = find_obj(hero.y,hero.x)) == NULL) {
|
||||
debug("Can't find the item");
|
||||
return FALSE;
|
||||
}
|
||||
obj = OBJPTR(item);
|
||||
worth = get_worth(obj);
|
||||
if (worth < 0) {
|
||||
msg("That's not for sale.");
|
||||
return FALSE;
|
||||
}
|
||||
if (worth < 25)
|
||||
worth = 25;
|
||||
|
||||
/* Our shopkeeper is affected by the person's charisma */
|
||||
worth = (int) ((float) worth * (17. / (float)pstats.s_charisma));
|
||||
str = inv_name(obj, TRUE);
|
||||
msg("%s for only %d pieces of gold", str, worth);
|
||||
curprice = worth; /* save price */
|
||||
strcpy(curpurch,str); /* save item */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* sell_it:
|
||||
* Sell an item to the trading post
|
||||
*/
|
||||
sell_it()
|
||||
{
|
||||
reg struct linked_list *item;
|
||||
reg struct object *obj;
|
||||
reg int wo, ch;
|
||||
|
||||
if (!open_market()) /* after selling hours */
|
||||
return;
|
||||
|
||||
if ((item = get_item(pack, "sell", ALL, FALSE, FALSE)) == NULL)
|
||||
return;
|
||||
obj = OBJPTR(item);
|
||||
wo = get_worth(obj);
|
||||
if (wo <= 0) {
|
||||
mpos = 0;
|
||||
msg("We don't buy those.");
|
||||
return;
|
||||
}
|
||||
if (wo < 25)
|
||||
wo = 25;
|
||||
msg("Your %s is worth %d pieces of gold.",typ_name(obj),wo);
|
||||
msg("Do you want to sell it? ");
|
||||
do {
|
||||
ch = tolower(readchar());
|
||||
if (ch == ESCAPE || ch == 'n') {
|
||||
msg("");
|
||||
return;
|
||||
}
|
||||
} until (ch == 'y');
|
||||
mpos = 0;
|
||||
if (drop(item) == TRUE) { /* drop this item */
|
||||
purse += wo; /* give him his money */
|
||||
++trader; /* another transaction */
|
||||
wo = obj->o_count;
|
||||
if (obj->o_group == 0) /* dropped one at a time */
|
||||
obj->o_count = 1;
|
||||
msg("Sold %s",inv_name(obj,TRUE));
|
||||
obj->o_count = wo;
|
||||
trans_line(); /* show remaining deals */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* trans_line:
|
||||
* Show how many transactions the hero has left
|
||||
*/
|
||||
trans_line()
|
||||
{
|
||||
if (level == 0)
|
||||
sprintf(prbuf, "You are welcome to spend whatever you have.");
|
||||
else if (!wizard)
|
||||
sprintf(prbuf,"You have %d transactions remaining.",
|
||||
MAXPURCH - trader);
|
||||
else
|
||||
sprintf(prbuf,
|
||||
"You have infinite transactions remaining oh great wizard.");
|
||||
mvwaddstr(cw,lines - 3,0,prbuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* typ_name:
|
||||
* Return the name for this type of object
|
||||
*/
|
||||
char *
|
||||
typ_name(obj)
|
||||
reg struct object *obj;
|
||||
{
|
||||
static char buff[20];
|
||||
reg int wh;
|
||||
|
||||
switch (obj->o_type) {
|
||||
case POTION: wh = TYP_POTION;
|
||||
when SCROLL: wh = TYP_SCROLL;
|
||||
when STICK: wh = TYP_STICK;
|
||||
when RING: wh = TYP_RING;
|
||||
when ARMOR: wh = TYP_ARMOR;
|
||||
when WEAPON: wh = TYP_WEAPON;
|
||||
when MM: wh = TYP_MM;
|
||||
when FOOD: wh = TYP_FOOD;
|
||||
when RELIC: wh = TYP_RELIC;
|
||||
otherwise: wh = -1;
|
||||
}
|
||||
if (wh < 0)
|
||||
strcpy(buff,"unknown");
|
||||
else
|
||||
strcpy(buff,things[wh].mi_name);
|
||||
return (buff);
|
||||
}
|
||||
|
||||
|
||||
1283
arogue7/util.c
Normal file
1283
arogue7/util.c
Normal file
File diff suppressed because it is too large
Load diff
24
arogue7/vers.c
Normal file
24
arogue7/vers.c
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* vers.c - version number
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* version number. Whenever a new version number is desired, use
|
||||
* sccs to get vers.c. Environ and encstr are declared here to
|
||||
* force them to be loaded before the version number, and therefore
|
||||
* not to be written in saved games.
|
||||
*/
|
||||
|
||||
char encstr[] = "\354\251\243\332A\201|\301\321p\210\251\327\"\257\365t\341%3\271^`~\203z{\341};\f\341\231\222e\234\351]\321\234";
|
||||
char version[] = "@(#)vers.c 7.7 (Bell Labs) 07/07/86";
|
||||
char *release = "7.7.1";
|
||||
402
arogue7/weapons.c
Normal file
402
arogue7/weapons.c
Normal file
|
|
@ -0,0 +1,402 @@
|
|||
/*
|
||||
* weapons.c - Functions for dealing with problems brought about by weapons
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Functions for dealing with problems brought about by weapons
|
||||
*
|
||||
*/
|
||||
|
||||
#include "curses.h"
|
||||
#include <ctype.h>
|
||||
#include "rogue.h"
|
||||
|
||||
boomerang(ydelta, xdelta, item, tp)
|
||||
int ydelta, xdelta;
|
||||
register struct linked_list *item;
|
||||
register struct thing *tp;
|
||||
{
|
||||
register struct object *obj;
|
||||
struct thing midpoint;
|
||||
coord oldpos;
|
||||
|
||||
obj = OBJPTR(item);
|
||||
oldpos = obj->o_pos;
|
||||
|
||||
/*
|
||||
* make it appear to fly at the target
|
||||
*/
|
||||
do_motion(obj, ydelta, xdelta, tp);
|
||||
hit_monster(unc(obj->o_pos), obj, tp);
|
||||
|
||||
/*
|
||||
* Now let's make it fly back to the wielder. We need to
|
||||
* use midpoint to fool do_motion into thinking the action
|
||||
* starts there. Do_motion only looks at the t_pos field.
|
||||
*/
|
||||
midpoint.t_pos = obj->o_pos; /* Simulate a new start position */
|
||||
do_motion(obj, -ydelta, -xdelta, &midpoint);
|
||||
|
||||
obj->o_pos = oldpos;
|
||||
}
|
||||
|
||||
/*
|
||||
* do the actual motion on the screen done by an object traveling
|
||||
* across the room. Note that we should not look at any field in
|
||||
* tp other than t_pos unless we change boomerang().
|
||||
*/
|
||||
do_motion(obj, ydelta, xdelta, tp)
|
||||
register struct object *obj;
|
||||
register int ydelta, xdelta;
|
||||
register struct thing *tp;
|
||||
{
|
||||
|
||||
/*
|
||||
* Come fly with us ...
|
||||
*/
|
||||
obj->o_pos = tp->t_pos;
|
||||
for (; ;) {
|
||||
register int ch;
|
||||
/*
|
||||
* Erase the old one
|
||||
*/
|
||||
if (!ce(obj->o_pos, tp->t_pos) &&
|
||||
cansee(unc(obj->o_pos)) &&
|
||||
mvwinch(cw, obj->o_pos.y, obj->o_pos.x) != ' ') {
|
||||
mvwaddch(cw, obj->o_pos.y, obj->o_pos.x, show(obj->o_pos.y, obj->o_pos.x));
|
||||
}
|
||||
/*
|
||||
* Get the new position
|
||||
*/
|
||||
obj->o_pos.y += ydelta;
|
||||
obj->o_pos.x += xdelta;
|
||||
if (shoot_ok(ch = winat(obj->o_pos.y, obj->o_pos.x)) && ch != DOOR && !ce(obj->o_pos, hero)) {
|
||||
/*
|
||||
* It hasn't hit anything yet, so display it
|
||||
* If it alright.
|
||||
*/
|
||||
if (cansee(unc(obj->o_pos)) &&
|
||||
mvwinch(cw, obj->o_pos.y, obj->o_pos.x) != ' ') {
|
||||
mvwaddch(cw, obj->o_pos.y, obj->o_pos.x, obj->o_type);
|
||||
draw(cw);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Did we stop because of a monster or the hero? If we did
|
||||
* not, we want to move our position back one because we could
|
||||
* not actually make it this far.
|
||||
*/
|
||||
if (!isalpha(ch) &&
|
||||
!(obj->o_pos.y == hero.y && obj->o_pos.x == hero.x)) {
|
||||
obj->o_pos.y -= ydelta;
|
||||
obj->o_pos.x -= xdelta;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fall:
|
||||
* Drop an item someplace around here.
|
||||
*/
|
||||
|
||||
fall(item, pr)
|
||||
register struct linked_list *item;
|
||||
bool pr;
|
||||
{
|
||||
register struct object *obj;
|
||||
register struct room *rp;
|
||||
register int i;
|
||||
struct object *tobj;
|
||||
struct linked_list *titem;
|
||||
coord *fpos;
|
||||
|
||||
obj = OBJPTR(item);
|
||||
/*
|
||||
* try to drop the item, look up to 3 squares away for now
|
||||
*/
|
||||
for (i=1; i<4; i++) {
|
||||
if ((fpos = fallpos(&obj->o_pos, FALSE, i)) != NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
if (fpos != NULL) {
|
||||
if (obj->o_group) { /* try to add groups together */
|
||||
for(titem=lvl_obj; titem!=NULL; titem=next(titem)) {
|
||||
tobj = OBJPTR(titem);
|
||||
if (tobj->o_group == obj->o_group &&
|
||||
tobj->o_pos.y == fpos->y &&
|
||||
tobj->o_pos.x == fpos->x) {
|
||||
tobj->o_count += obj->o_count;
|
||||
o_discard(item);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
mvaddch(fpos->y, fpos->x, obj->o_type);
|
||||
obj->o_pos = *fpos;
|
||||
if ((rp = roomin(&hero)) != NULL &&
|
||||
lit_room(rp)) {
|
||||
light(&hero);
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
}
|
||||
attach(lvl_obj, item);
|
||||
return;
|
||||
}
|
||||
if (pr) {
|
||||
msg("The %s vanishes as it hits the ground.",
|
||||
weaps[obj->o_which].w_name);
|
||||
}
|
||||
o_discard(item);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Does the missile hit the monster
|
||||
*/
|
||||
|
||||
hit_monster(y, x, obj, tp)
|
||||
register int y, x;
|
||||
struct object *obj;
|
||||
register struct thing *tp;
|
||||
{
|
||||
static coord mp;
|
||||
|
||||
mp.y = y;
|
||||
mp.x = x;
|
||||
if (tp == &player) {
|
||||
/* Make sure there is a monster where it landed */
|
||||
if (!isalpha(mvwinch(mw, y, x))) {
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/* Player hits monster */
|
||||
return(fight(&mp, obj, TRUE));
|
||||
} else {
|
||||
if (!ce(mp, hero)) {
|
||||
/* Monster hits monster */
|
||||
return(skirmish(tp, &mp, obj, TRUE));
|
||||
}
|
||||
|
||||
/* Monster hits player */
|
||||
return(attack(tp, obj, TRUE));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* init_weapon:
|
||||
* Set up the initial goodies for a weapon
|
||||
*/
|
||||
|
||||
init_weapon(weap, type)
|
||||
register struct object *weap;
|
||||
char type;
|
||||
{
|
||||
register struct init_weps *iwp;
|
||||
|
||||
iwp = &weaps[type];
|
||||
strncpy(weap->o_damage, iwp->w_dam, sizeof(weap->o_damage));
|
||||
strncpy(weap->o_hurldmg, iwp->w_hrl, sizeof(weap->o_hurldmg));
|
||||
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 = newgrp();
|
||||
} else {
|
||||
weap->o_count = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* missile:
|
||||
* Fire a missile in a given direction
|
||||
*/
|
||||
|
||||
missile(ydelta, xdelta, item, tp)
|
||||
int ydelta, xdelta;
|
||||
register struct linked_list *item;
|
||||
register struct thing *tp;
|
||||
{
|
||||
register struct object *obj;
|
||||
register struct linked_list *nitem;
|
||||
char ch;
|
||||
|
||||
/*
|
||||
* Get which thing we are hurling
|
||||
*/
|
||||
if (item == NULL) {
|
||||
return;
|
||||
}
|
||||
obj = OBJPTR(item);
|
||||
if (obj->o_type == RELIC && obj->o_which == AXE_AKLAD) {
|
||||
boomerang(ydelta, xdelta, item, tp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dropcheck(obj)) return; /* Can we get rid of it? */
|
||||
|
||||
if(!(obj->o_flags & ISMISL)) {
|
||||
while (TRUE) {
|
||||
msg(terse ? "Really throw? (y or n): "
|
||||
: "Do you really want to throw %s? (y or n): ",
|
||||
inv_name(obj, TRUE));
|
||||
mpos = 0;
|
||||
ch = readchar();
|
||||
if (ch == 'n' || ch == ESCAPE) {
|
||||
after = FALSE;
|
||||
return;
|
||||
}
|
||||
if (ch == 'y')
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 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) {
|
||||
detach(tp->t_pack, item);
|
||||
if (tp->t_pack == pack) {
|
||||
inpack--;
|
||||
}
|
||||
}
|
||||
else {
|
||||
obj->o_count--;
|
||||
nitem = (struct linked_list *) new_item(sizeof *obj);
|
||||
obj = OBJPTR(nitem);
|
||||
*obj = *(OBJPTR(item));
|
||||
obj->o_count = 1;
|
||||
item = nitem;
|
||||
}
|
||||
updpack(FALSE, tp);
|
||||
do_motion(obj, 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(unc(obj->o_pos), obj, tp)) {
|
||||
fall(item, TRUE);
|
||||
}
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
}
|
||||
|
||||
/*
|
||||
* num:
|
||||
* Figure out the plus number for armor/weapons
|
||||
*/
|
||||
|
||||
char *
|
||||
num(n1, n2)
|
||||
register int n1, n2;
|
||||
{
|
||||
static char numbuf[LINELEN];
|
||||
|
||||
if (n1 == 0 && n2 == 0) {
|
||||
return "+0";
|
||||
}
|
||||
if (n2 == 0) {
|
||||
sprintf(numbuf, "%s%d", n1 < 0 ? "" : "+", n1);
|
||||
} else {
|
||||
sprintf(numbuf, "%s%d, %s%d", n1 < 0 ? "" : "+", n1, n2 < 0 ? "" : "+", n2);
|
||||
}
|
||||
return(numbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* wield:
|
||||
* Pull out a certain weapon
|
||||
*/
|
||||
|
||||
wield()
|
||||
{
|
||||
register struct linked_list *item;
|
||||
register struct object *obj, *oweapon;
|
||||
|
||||
/*
|
||||
* It takes 2 movement periods to unwield a weapon and 2 movement
|
||||
* periods to wield a weapon.
|
||||
*/
|
||||
if (player.t_action != C_WIELD) {
|
||||
player.t_action = C_WIELD;
|
||||
player.t_using = NULL; /* Make sure this is NULL! */
|
||||
if (cur_weapon != NULL) {
|
||||
player.t_no_move = 2 * movement(&player);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((oweapon = cur_weapon) != NULL) {
|
||||
/* At this point we have waited at least 2 units */
|
||||
if (!dropcheck(cur_weapon)) {
|
||||
cur_weapon = oweapon;
|
||||
player.t_action = A_NIL;
|
||||
return;
|
||||
}
|
||||
if (terse)
|
||||
addmsg("Was ");
|
||||
else
|
||||
addmsg("You were ");
|
||||
msg("wielding %s", inv_name(oweapon, TRUE));
|
||||
}
|
||||
|
||||
/* We we have something picked out? */
|
||||
if (player.t_using == NULL) {
|
||||
/* Now, what does he want to wield? */
|
||||
if ((item = get_item(pack, "wield", WIELDABLE, FALSE, FALSE)) == NULL) {
|
||||
player.t_action = A_NIL;
|
||||
after = FALSE;
|
||||
return;
|
||||
}
|
||||
player.t_using = item;
|
||||
player.t_no_move = 2 * movement(&player);
|
||||
return;
|
||||
}
|
||||
|
||||
/* We have waited our time, let's wield the weapon */
|
||||
item = player.t_using;
|
||||
player.t_using = NULL;
|
||||
player.t_action = A_NIL;
|
||||
|
||||
obj = OBJPTR(item);
|
||||
|
||||
if (is_current(obj)) {
|
||||
msg("Item in use.");
|
||||
after = FALSE;
|
||||
return;
|
||||
}
|
||||
if (player.t_ctype != C_FIGHTER &&
|
||||
player.t_ctype != C_RANGER &&
|
||||
player.t_ctype != C_PALADIN &&
|
||||
obj->o_type == WEAPON &&
|
||||
(obj->o_which == TWOSWORD ||
|
||||
(obj->o_which == BASWORD &&
|
||||
player.t_ctype != C_ASSASIN))) {
|
||||
msg("Only fighter types can wield a %s",
|
||||
weaps[obj->o_which].w_name);
|
||||
return;
|
||||
}
|
||||
if (terse) {
|
||||
addmsg("W");
|
||||
} else {
|
||||
addmsg("You are now w");
|
||||
}
|
||||
msg("ielding %s", inv_name(obj, TRUE));
|
||||
cur_weapon = obj;
|
||||
}
|
||||
|
||||
431
arogue7/wear.c
Normal file
431
arogue7/wear.c
Normal file
|
|
@ -0,0 +1,431 @@
|
|||
/*
|
||||
* wear.c - functions for dealing with armor
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains misc functions for dealing with armor
|
||||
*/
|
||||
|
||||
#include "curses.h"
|
||||
#include "rogue.h"
|
||||
|
||||
|
||||
/*
|
||||
* take_off:
|
||||
* Get the armor off of the players back
|
||||
*/
|
||||
|
||||
take_off()
|
||||
{
|
||||
register struct object *obj;
|
||||
register struct linked_list *item;
|
||||
|
||||
/* It takes time to take things off */
|
||||
if (player.t_action != C_TAKEOFF) {
|
||||
/* What does player want to take off? */
|
||||
if ((item = get_item(pack, "take off", REMOVABLE, FALSE, FALSE))==NULL)
|
||||
return;
|
||||
|
||||
obj = OBJPTR(item);
|
||||
if (!is_current(obj)) {
|
||||
msg("Not wearing %c) %s", pack_char(pack, obj),inv_name(obj, TRUE));
|
||||
return;
|
||||
}
|
||||
|
||||
player.t_using = item; /* Remember what it is */
|
||||
player.t_action = C_TAKEOFF; /* We are taking something off */
|
||||
|
||||
/* Cursed items take almost no time */
|
||||
if (obj->o_flags & ISCURSED) player.t_no_move = movement(&player);
|
||||
else player.t_no_move = dress_units(item) * movement(&player);
|
||||
return;
|
||||
}
|
||||
|
||||
/* We have waited our time, let's take off our item */
|
||||
item = player.t_using;
|
||||
player.t_using = NULL;
|
||||
player.t_action = A_NIL;
|
||||
|
||||
obj = OBJPTR(item);
|
||||
if (!is_current(obj)) { /* Just to be on the safe side */
|
||||
msg("Not wearing %c) %s", pack_char(pack, obj),inv_name(obj, TRUE));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Can the player remove the item? */
|
||||
if (!dropcheck(obj)) return;
|
||||
updpack(TRUE, &player);
|
||||
|
||||
msg("Was wearing %c) %s", pack_char(pack, obj),inv_name(obj,TRUE));
|
||||
}
|
||||
|
||||
/*
|
||||
* wear:
|
||||
* The player wants to wear something, so let him/her put it on.
|
||||
*/
|
||||
|
||||
wear()
|
||||
{
|
||||
register struct linked_list *item;
|
||||
register struct object *obj;
|
||||
register int i;
|
||||
|
||||
/* It takes time to put things on */
|
||||
if (player.t_action != C_WEAR) {
|
||||
/* What does player want to wear? */
|
||||
if ((item = get_item(pack, "wear", WEARABLE, FALSE, FALSE)) == NULL)
|
||||
return;
|
||||
|
||||
obj = OBJPTR(item);
|
||||
|
||||
switch (obj->o_type) {
|
||||
case ARMOR:
|
||||
if (cur_armor != NULL) {
|
||||
addmsg("You are already wearing armor");
|
||||
if (!terse) addmsg(". You'll have to take it off first.");
|
||||
endmsg();
|
||||
after = FALSE;
|
||||
return;
|
||||
}
|
||||
if (player.t_ctype == C_MONK) {
|
||||
msg("Monks can't wear armor!");
|
||||
return;
|
||||
}
|
||||
if (cur_misc[WEAR_BRACERS] != NULL) {
|
||||
msg("You can't wear armor with bracers of defense.");
|
||||
return;
|
||||
}
|
||||
if (cur_misc[WEAR_CLOAK] != NULL || cur_relic[EMORI_CLOAK]) {
|
||||
msg("You can't wear armor with a cloak.");
|
||||
return;
|
||||
}
|
||||
if (player.t_ctype == C_THIEF &&
|
||||
(obj->o_which != LEATHER &&
|
||||
obj->o_which != STUDDED_LEATHER)) {
|
||||
if (terse) msg("Thieves can't wear that type of armor");
|
||||
else
|
||||
msg("Thieves can only wear leather or studded leather armor");
|
||||
return;
|
||||
}
|
||||
if (player.t_ctype == C_ASSASIN &&
|
||||
(obj->o_which != LEATHER &&
|
||||
obj->o_which != STUDDED_LEATHER)) {
|
||||
if (terse) msg("Assassins can't wear that type of armor");
|
||||
else
|
||||
msg("Assassins can only wear leather or studded leather armor");
|
||||
return;
|
||||
}
|
||||
|
||||
when MM:
|
||||
switch (obj->o_which) {
|
||||
/*
|
||||
* when wearing the boots of elvenkind the player will not
|
||||
* set off any traps
|
||||
*/
|
||||
case MM_ELF_BOOTS:
|
||||
if (cur_misc[WEAR_BOOTS] != NULL) {
|
||||
msg("Already wearing a pair of boots");
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* when wearing the boots of dancing the player will dance
|
||||
* uncontrollably
|
||||
*/
|
||||
when MM_DANCE:
|
||||
if (cur_misc[WEAR_BOOTS] != NULL) {
|
||||
msg("Already wearing a pair of boots");
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* bracers give the hero protection in he same way armor does.
|
||||
* they cannot be used with armor but can be used with cloaks
|
||||
*/
|
||||
when MM_BRACERS:
|
||||
if (cur_misc[WEAR_BRACERS] != NULL) {
|
||||
msg("Already wearing bracers");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (cur_armor != NULL) {
|
||||
msg("You can't wear bracers of defense with armor.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The robe (cloak) of powerlessness disallows any spell casting
|
||||
*/
|
||||
when MM_R_POWERLESS:
|
||||
/*
|
||||
* the cloak of displacement gives the hero an extra +2 on AC
|
||||
* and saving throws. Cloaks cannot be used with armor.
|
||||
*/
|
||||
case MM_DISP:
|
||||
/*
|
||||
* the cloak of protection gives the hero +n on AC and saving
|
||||
* throws with a max of +3 on saves
|
||||
*/
|
||||
case MM_PROTECT:
|
||||
if (cur_misc[WEAR_CLOAK] != NULL ||
|
||||
cur_relic[EMORI_CLOAK]) {
|
||||
msg("%slready wearing a cloak.", terse ? "A"
|
||||
: "You are a");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (cur_armor != NULL) {
|
||||
msg("You can't wear a cloak with armor.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* the gauntlets of dexterity give the hero a dexterity of 18
|
||||
* the gauntlets of ogre power give the hero a strength of 18
|
||||
* the gauntlets of fumbling cause the hero to drop his weapon
|
||||
*/
|
||||
when MM_G_DEXTERITY:
|
||||
case MM_G_OGRE:
|
||||
case MM_FUMBLE:
|
||||
if (cur_misc[WEAR_GAUNTLET] != NULL) {
|
||||
msg("Already wearing a pair of gauntlets.");
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* the jewel of attacks does an aggavate monster
|
||||
*/
|
||||
when MM_JEWEL:
|
||||
if (cur_misc[WEAR_JEWEL] != NULL ||
|
||||
cur_relic[YENDOR_AMULET] ||
|
||||
cur_relic[STONEBONES_AMULET]) {
|
||||
msg("Already wearing an amulet.");
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* the necklace of adaption makes the hero immune to
|
||||
* chlorine gas
|
||||
*/
|
||||
when MM_ADAPTION:
|
||||
if (cur_misc[WEAR_NECKLACE] != NULL) {
|
||||
msg("Already wearing a necklace");
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* the necklace of stragulation will try to strangle the
|
||||
* hero to death
|
||||
*/
|
||||
when MM_STRANGLE:
|
||||
if (cur_misc[WEAR_NECKLACE] != NULL) {
|
||||
msg("Already wearing a necklace");
|
||||
return;
|
||||
}
|
||||
otherwise:
|
||||
msg("what a strange item you have!");
|
||||
return;
|
||||
}
|
||||
|
||||
when RING:
|
||||
if (cur_misc[WEAR_GAUNTLET] != NULL) {
|
||||
msg ("You have to remove your gauntlets first!");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Is there room to put the ring on */
|
||||
for (i=0; i<NUM_FINGERS; i++)
|
||||
if (cur_ring[i] == NULL) {
|
||||
break;
|
||||
}
|
||||
if (i == NUM_FINGERS) { /* No room */
|
||||
if (terse) msg("Wearing enough rings");
|
||||
else msg("You already have on eight rings");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
player.t_using = item; /* Remember what it is */
|
||||
player.t_action = C_WEAR; /* We are taking something off */
|
||||
player.t_no_move = dress_units(item) * movement(&player);
|
||||
return;
|
||||
}
|
||||
|
||||
/* We have waited our time, let's put on our item */
|
||||
item = player.t_using;
|
||||
player.t_using = NULL;
|
||||
player.t_action = A_NIL;
|
||||
|
||||
obj = OBJPTR(item);
|
||||
|
||||
switch (obj->o_type) {
|
||||
case ARMOR:
|
||||
obj->o_flags |= ISKNOW;
|
||||
cur_armor = obj;
|
||||
addmsg(terse ? "W" : "You are now w");
|
||||
msg("earing %s.", armors[obj->o_which].a_name);
|
||||
|
||||
when MM:
|
||||
switch (obj->o_which) {
|
||||
/*
|
||||
* when wearing the boots of elvenkind the player will not
|
||||
* set off any traps
|
||||
*/
|
||||
case MM_ELF_BOOTS:
|
||||
msg("Wearing %s",inv_name(obj,TRUE));
|
||||
cur_misc[WEAR_BOOTS] = obj;
|
||||
/*
|
||||
* when wearing the boots of dancing the player will dance
|
||||
* uncontrollably
|
||||
*/
|
||||
when MM_DANCE:
|
||||
msg("Wearing %s",inv_name(obj,TRUE));
|
||||
cur_misc[WEAR_BOOTS] = obj;
|
||||
msg("You begin to dance uncontrollably!");
|
||||
turn_on(player, ISDANCE);
|
||||
/*
|
||||
* bracers give the hero protection in he same way armor does.
|
||||
* they cannot be used with armor but can be used with cloaks
|
||||
*/
|
||||
when MM_BRACERS:
|
||||
msg("wearing %s",inv_name(obj,TRUE));
|
||||
cur_misc[WEAR_BRACERS] = obj;
|
||||
|
||||
/*
|
||||
* The robe (cloak) of powerlessness disallows any spell casting
|
||||
*/
|
||||
when MM_R_POWERLESS:
|
||||
/*
|
||||
* the cloak of displacement gives the hero an extra +2 on AC
|
||||
* and saving throws. Cloaks cannot be used with armor.
|
||||
*/
|
||||
case MM_DISP:
|
||||
/*
|
||||
* the cloak of protection gives the hero +n on AC and saving
|
||||
* throws with a max of +3 on saves
|
||||
*/
|
||||
case MM_PROTECT:
|
||||
msg("wearing %s",inv_name(obj,TRUE));
|
||||
cur_misc[WEAR_CLOAK] = obj;
|
||||
/*
|
||||
* the gauntlets of dexterity give the hero a dexterity of 18
|
||||
* the gauntlets of ogre power give the hero a strength of 18
|
||||
* the gauntlets of fumbling cause the hero to drop his weapon
|
||||
*/
|
||||
when MM_G_DEXTERITY:
|
||||
case MM_G_OGRE:
|
||||
case MM_FUMBLE:
|
||||
msg("Wearing %s", inv_name(obj,TRUE));
|
||||
cur_misc[WEAR_GAUNTLET] = obj;
|
||||
if (obj->o_which == MM_FUMBLE)
|
||||
daemon(fumble, 0, AFTER);
|
||||
/*
|
||||
* the jewel of attacks does an aggavate monster
|
||||
*/
|
||||
when MM_JEWEL:
|
||||
msg("Wearing %s",inv_name(obj,TRUE));
|
||||
cur_misc[WEAR_JEWEL] = obj;
|
||||
aggravate(TRUE, TRUE);
|
||||
/*
|
||||
* the necklace of adaption makes the hero immune to
|
||||
* chlorine gas
|
||||
*/
|
||||
when MM_ADAPTION:
|
||||
msg("Wearing %s",inv_name(obj,TRUE));
|
||||
cur_misc[WEAR_NECKLACE] = obj;
|
||||
turn_on(player, NOGAS);
|
||||
/*
|
||||
* the necklace of stragulation will try to strangle the
|
||||
* hero to death
|
||||
*/
|
||||
when MM_STRANGLE:
|
||||
msg("Wearing %s",inv_name(obj,TRUE));
|
||||
cur_misc[WEAR_NECKLACE] = obj;
|
||||
msg("The necklace is beginning to strangle you!");
|
||||
daemon(strangle, 0, AFTER);
|
||||
otherwise:
|
||||
msg("What a strange item you have!");
|
||||
}
|
||||
status(FALSE);
|
||||
if (m_know[obj->o_which] && m_guess[obj->o_which]) {
|
||||
free(m_guess[obj->o_which]);
|
||||
m_guess[obj->o_which] = NULL;
|
||||
}
|
||||
else if (!m_know[obj->o_which] &&
|
||||
askme &&
|
||||
(obj->o_flags & ISKNOW) == 0 &&
|
||||
m_guess[obj->o_which] == NULL) {
|
||||
nameitem(item, FALSE);
|
||||
}
|
||||
|
||||
when RING:
|
||||
/* If there is room, put on the ring */
|
||||
for (i=0; i<NUM_FINGERS; i++)
|
||||
if (cur_ring[i] == NULL) {
|
||||
cur_ring[i] = obj;
|
||||
break;
|
||||
}
|
||||
if (i == NUM_FINGERS) { /* No room */
|
||||
if (terse) msg("Wearing enough rings");
|
||||
else msg("You already have on eight rings");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Calculate the effect of the ring */
|
||||
ring_on(item);
|
||||
}
|
||||
updpack(TRUE, &player);
|
||||
}
|
||||
|
||||
/*
|
||||
* dress_units:
|
||||
* How many movements periods does it take to put on or remove the
|
||||
* given item of "clothing"?
|
||||
*/
|
||||
dress_units(item)
|
||||
struct linked_list *item;
|
||||
{
|
||||
register struct object *obj;
|
||||
|
||||
obj = OBJPTR(item);
|
||||
|
||||
switch (obj->o_type) {
|
||||
case ARMOR:
|
||||
return(10-armors[obj->o_which].a_class);
|
||||
when RING:
|
||||
return(2);
|
||||
when MM:
|
||||
switch (obj->o_which) {
|
||||
case MM_ELF_BOOTS:
|
||||
case MM_DANCE:
|
||||
/* Boots */
|
||||
return(4);
|
||||
when MM_R_POWERLESS:
|
||||
case MM_DISP:
|
||||
case MM_PROTECT:
|
||||
/* Robes */
|
||||
return(4);
|
||||
when MM_BRACERS:
|
||||
case MM_G_DEXTERITY:
|
||||
case MM_G_OGRE:
|
||||
case MM_FUMBLE:
|
||||
/* Hand garments */
|
||||
return(3);
|
||||
when MM_JEWEL:
|
||||
case MM_ADAPTION:
|
||||
case MM_STRANGLE:
|
||||
/* Jewelry */
|
||||
return(2);
|
||||
otherwise:
|
||||
return(1); /* What is it? */
|
||||
}
|
||||
otherwise:
|
||||
return(1); /* What is it? */
|
||||
}
|
||||
}
|
||||
696
arogue7/wizard.c
Normal file
696
arogue7/wizard.c
Normal file
|
|
@ -0,0 +1,696 @@
|
|||
/*
|
||||
* wizard.c - Special wizard commands
|
||||
*
|
||||
* Advanced Rogue
|
||||
* Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Special wizard commands (some of which are also non-wizard commands
|
||||
* under strange circumstances)
|
||||
*/
|
||||
|
||||
#include "curses.h"
|
||||
#include <ctype.h>
|
||||
#include "rogue.h"
|
||||
#ifdef PC7300
|
||||
#include "menu.h"
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* create_obj:
|
||||
* Create any object for wizard, scroll, magician, or cleric
|
||||
*/
|
||||
create_obj(prompt, which_item, which_type)
|
||||
bool prompt;
|
||||
int which_item, which_type;
|
||||
{
|
||||
reg struct linked_list *item;
|
||||
reg struct object *obj;
|
||||
reg int wh;
|
||||
reg char ch, newitem, newtype, whc, msz, *pt;
|
||||
WINDOW *thiswin;
|
||||
|
||||
thiswin = cw;
|
||||
if (prompt) {
|
||||
bool nogood = TRUE;
|
||||
|
||||
thiswin = hw;
|
||||
wclear(hw);
|
||||
wprintw(hw,"Item\t\t\tKey\n\n");
|
||||
wprintw(hw,"%s\t\t\t%c\n%s\t\t\t%c\n",things[TYP_RING].mi_name,RING,
|
||||
things[TYP_STICK].mi_name,STICK);
|
||||
wprintw(hw,"%s\t\t\t%c\n%s\t\t\t%c\n",things[TYP_POTION].mi_name,POTION,
|
||||
things[TYP_SCROLL].mi_name,SCROLL);
|
||||
wprintw(hw,"%s\t\t\t%c\n%s\t\t\t%c\n",things[TYP_ARMOR].mi_name,ARMOR,
|
||||
things[TYP_WEAPON].mi_name,WEAPON);
|
||||
wprintw(hw,"%s\t%c\n",things[TYP_MM].mi_name,MM);
|
||||
wprintw(hw,"%s\t\t\t%c\n",things[TYP_FOOD].mi_name,FOOD);
|
||||
if (wizard) {
|
||||
wprintw(hw,"%s\t\t%c\n",things[TYP_RELIC].mi_name,RELIC);
|
||||
waddstr(hw,"monster\t\t\tm");
|
||||
}
|
||||
wprintw(hw,"\n\nWhat do you want to create? ");
|
||||
draw(hw);
|
||||
do {
|
||||
ch = wgetch(hw);
|
||||
if (ch == ESCAPE) {
|
||||
restscr(cw);
|
||||
return;
|
||||
}
|
||||
switch (ch) {
|
||||
case RING:
|
||||
case STICK:
|
||||
case POTION:
|
||||
case SCROLL:
|
||||
case ARMOR:
|
||||
case WEAPON:
|
||||
case FOOD:
|
||||
case MM:
|
||||
nogood = FALSE;
|
||||
break;
|
||||
case RELIC:
|
||||
case 'm':
|
||||
if (wizard)
|
||||
nogood = FALSE;
|
||||
break;
|
||||
default:
|
||||
nogood = TRUE;
|
||||
}
|
||||
} while (nogood);
|
||||
newitem = ch;
|
||||
}
|
||||
else
|
||||
newitem = which_item;
|
||||
|
||||
pt = "those";
|
||||
msz = 0;
|
||||
if(newitem == 'm') {
|
||||
/* make monster and be done with it */
|
||||
wh = makemonster(TRUE, "Creation", "create");
|
||||
if (wh > 0) {
|
||||
creat_mons (&player, wh, TRUE);
|
||||
light(&hero);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(newitem == GOLD)
|
||||
pt = "gold";
|
||||
/* else if(isatrap(newitem))
|
||||
pt = "traps";
|
||||
*/
|
||||
switch(newitem) {
|
||||
case POTION: whc = TYP_POTION; msz = MAXPOTIONS;
|
||||
when SCROLL: whc = TYP_SCROLL; msz = MAXSCROLLS;
|
||||
when WEAPON: whc = TYP_WEAPON; msz = MAXWEAPONS;
|
||||
when ARMOR: whc = TYP_ARMOR; msz = MAXARMORS;
|
||||
when RING: whc = TYP_RING; msz = MAXRINGS;
|
||||
when STICK: whc = TYP_STICK; msz = MAXSTICKS;
|
||||
when MM: whc = TYP_MM; msz = MAXMM;
|
||||
when RELIC: whc = TYP_RELIC; msz = MAXRELIC;
|
||||
when FOOD: whc = TYP_FOOD; msz = MAXFOODS;
|
||||
otherwise:
|
||||
if (thiswin == hw)
|
||||
restscr(cw);
|
||||
mpos = 0;
|
||||
msg("Even wizards can't create %s !!",pt);
|
||||
return;
|
||||
}
|
||||
if(msz == 1) { /* if only one type of item */
|
||||
ch = 'a';
|
||||
}
|
||||
else if (prompt) {
|
||||
register struct magic_item *wmi;
|
||||
char wmn;
|
||||
register int ii;
|
||||
int old_prob;
|
||||
|
||||
mpos = 0;
|
||||
wmi = NULL;
|
||||
wmn = 0;
|
||||
switch(newitem) {
|
||||
case POTION: wmi = &p_magic[0];
|
||||
when SCROLL: wmi = &s_magic[0];
|
||||
when RING: wmi = &r_magic[0];
|
||||
when STICK: wmi = &ws_magic[0];
|
||||
when MM: wmi = &m_magic[0];
|
||||
when RELIC: wmi = &rel_magic[0];
|
||||
when FOOD: wmi = &foods[0];
|
||||
when WEAPON: wmn = 1;
|
||||
when ARMOR: wmn = 2;
|
||||
}
|
||||
wclear(hw);
|
||||
thiswin = hw;
|
||||
if (wmi != NULL) {
|
||||
ii = old_prob = 0;
|
||||
while (ii < msz) {
|
||||
if(wmi->mi_prob == old_prob && wizard == FALSE) {
|
||||
msz--; /* can't make a unique item */
|
||||
}
|
||||
else {
|
||||
mvwaddch(hw,ii % 13,ii > 12 ? cols/2 : 0, ii + 'a');
|
||||
waddstr(hw,") ");
|
||||
waddstr(hw,wmi->mi_name);
|
||||
ii++;
|
||||
}
|
||||
old_prob = wmi->mi_prob;
|
||||
wmi++;
|
||||
}
|
||||
}
|
||||
else if (wmn != 0) {
|
||||
for(ii = 0 ; ii < msz ; ii++) {
|
||||
mvwaddch(hw,ii % 13,ii > 12 ? cols/2 : 0, ii + 'a');
|
||||
waddstr(hw,") ");
|
||||
if(wmn == 1)
|
||||
waddstr(hw,weaps[ii].w_name);
|
||||
else
|
||||
waddstr(hw,armors[ii].a_name);
|
||||
}
|
||||
}
|
||||
sprintf(prbuf,"Which %s? ",things[whc].mi_name);
|
||||
mvwaddstr(hw,lines - 1, 0, prbuf);
|
||||
draw(hw);
|
||||
do {
|
||||
ch = wgetch(hw);
|
||||
if (ch == ESCAPE) {
|
||||
restscr(cw);
|
||||
msg("");
|
||||
return;
|
||||
}
|
||||
} until (isalpha(ch));
|
||||
if (thiswin == hw) /* restore screen if need be */
|
||||
restscr(cw);
|
||||
newtype = tolower(ch) - 'a';
|
||||
if(newtype < 0 || newtype >= msz) { /* if an illegal value */
|
||||
mpos = 0;
|
||||
msg("There is no such %s",things[whc].mi_name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
newtype = which_type;
|
||||
item = new_item(sizeof *obj); /* get some memory */
|
||||
obj = OBJPTR(item);
|
||||
obj->o_type = newitem; /* store the new items */
|
||||
obj->o_mark[0] = '\0';
|
||||
obj->o_which = newtype;
|
||||
obj->o_group = 0;
|
||||
obj->contents = NULL;
|
||||
obj->o_count = 1;
|
||||
obj->o_flags = 0;
|
||||
obj->o_dplus = obj->o_hplus = 0;
|
||||
obj->o_weight = 0;
|
||||
wh = obj->o_which;
|
||||
mpos = 0;
|
||||
if (!wizard) /* users get 0 to +3 */
|
||||
whc = rnd(4);
|
||||
else /* wizard gets to choose */
|
||||
whc = getbless();
|
||||
if (whc < 0)
|
||||
obj->o_flags |= ISCURSED;
|
||||
switch (obj->o_type) {
|
||||
case WEAPON:
|
||||
case ARMOR:
|
||||
if (obj->o_type == WEAPON) {
|
||||
init_weapon(obj, wh);
|
||||
obj->o_hplus += whc;
|
||||
obj->o_dplus += whc;
|
||||
}
|
||||
else { /* armor here */
|
||||
obj->o_weight = armors[wh].a_wght;
|
||||
obj->o_ac = armors[wh].a_class - whc;
|
||||
}
|
||||
when RING:
|
||||
if (whc > 1 && r_magic[wh].mi_bless != 0)
|
||||
obj->o_flags |= ISBLESSED;
|
||||
r_know[wh] = TRUE;
|
||||
switch(wh) {
|
||||
case R_ADDSTR:
|
||||
case R_ADDWISDOM:
|
||||
case R_ADDINTEL:
|
||||
case R_PROTECT:
|
||||
case R_ADDHIT:
|
||||
case R_ADDDAM:
|
||||
case R_DIGEST:
|
||||
obj->o_ac = whc + 1;
|
||||
break;
|
||||
default:
|
||||
obj->o_ac = 0;
|
||||
}
|
||||
obj->o_weight = things[TYP_RING].mi_wght;
|
||||
when MM:
|
||||
if (whc > 1 && m_magic[wh].mi_bless != 0)
|
||||
obj->o_flags |= ISBLESSED;
|
||||
m_know[wh] = TRUE;
|
||||
switch(wh) {
|
||||
case MM_JUG:
|
||||
switch(rnd(11)) {
|
||||
case 0: obj->o_ac = P_PHASE;
|
||||
when 1: obj->o_ac = P_CLEAR;
|
||||
when 2: obj->o_ac = P_SEEINVIS;
|
||||
when 3: obj->o_ac = P_HEALING;
|
||||
when 4: obj->o_ac = P_MFIND;
|
||||
when 5: obj->o_ac = P_TFIND;
|
||||
when 6: obj->o_ac = P_HASTE;
|
||||
when 7: obj->o_ac = P_RESTORE;
|
||||
when 8: obj->o_ac = P_FLY;
|
||||
when 9: obj->o_ac = P_SKILL;
|
||||
when 10:obj->o_ac = P_FFIND;
|
||||
}
|
||||
when MM_OPEN:
|
||||
case MM_HUNGER:
|
||||
case MM_DRUMS:
|
||||
case MM_DISAPPEAR:
|
||||
case MM_CHOKE:
|
||||
case MM_KEOGHTOM:
|
||||
if (whc < 0)
|
||||
whc = -whc; /* these cannot be negative */
|
||||
obj->o_ac = (whc + 1) * 5;
|
||||
break;
|
||||
when MM_BRACERS:
|
||||
obj->o_ac = whc * 2 + 1;
|
||||
when MM_DISP:
|
||||
obj->o_ac = 2;
|
||||
when MM_PROTECT:
|
||||
obj->o_ac = whc;
|
||||
when MM_SKILLS:
|
||||
if (wizard && whc != 0)
|
||||
obj->o_ac = rnd(NUM_CHARTYPES-1);
|
||||
else
|
||||
obj->o_ac = player.t_ctype;
|
||||
otherwise:
|
||||
obj->o_ac = 0;
|
||||
}
|
||||
obj->o_weight = things[TYP_MM].mi_wght;
|
||||
when STICK:
|
||||
if (whc > 1 && ws_magic[wh].mi_bless != 0)
|
||||
obj->o_flags |= ISBLESSED;
|
||||
ws_know[wh] = TRUE;
|
||||
fix_stick(obj);
|
||||
when SCROLL:
|
||||
if (whc > 1 && s_magic[wh].mi_bless != 0)
|
||||
obj->o_flags |= ISBLESSED;
|
||||
obj->o_weight = things[TYP_SCROLL].mi_wght;
|
||||
s_know[wh] = TRUE;
|
||||
when POTION:
|
||||
if (whc > 1 && p_magic[wh].mi_bless != 0)
|
||||
obj->o_flags |= ISBLESSED;
|
||||
obj->o_weight = things[TYP_POTION].mi_wght;
|
||||
if (wh == P_ABIL) obj->o_kind = rnd(NUMABILITIES);
|
||||
p_know[wh] = TRUE;
|
||||
when RELIC:
|
||||
obj->o_weight = things[TYP_RELIC].mi_wght;
|
||||
switch (obj->o_which) {
|
||||
case QUILL_NAGROM: obj->o_charges = QUILLCHARGES;
|
||||
when EMORI_CLOAK: obj->o_charges = 1;
|
||||
otherwise: break;
|
||||
}
|
||||
when FOOD:
|
||||
obj->o_weight = things[TYP_FOOD].mi_wght;
|
||||
}
|
||||
mpos = 0;
|
||||
obj->o_flags |= ISKNOW;
|
||||
if (add_pack(item, FALSE, NULL) == FALSE) {
|
||||
obj->o_pos = hero;
|
||||
fall(item, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* getbless:
|
||||
* Get a blessing for a wizards object
|
||||
*/
|
||||
getbless()
|
||||
{
|
||||
reg char bless;
|
||||
|
||||
msg("Blessing? (+,-,n)");
|
||||
bless = wgetch(msgw);
|
||||
if (bless == '+')
|
||||
return (rnd(3) + 2);
|
||||
else if (bless == '-')
|
||||
return (-rnd(3) - 1);
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* get a non-monster death type
|
||||
*/
|
||||
getdeath()
|
||||
{
|
||||
register int i;
|
||||
int which_death;
|
||||
char label[80];
|
||||
|
||||
clear();
|
||||
for (i=0; i<DEATHNUM; i++) {
|
||||
sprintf(label, "[%d] %s", i+1, deaths[i].name);
|
||||
mvaddstr(i+2, 0, label);
|
||||
}
|
||||
mvaddstr(0, 0, "Which death? ");
|
||||
refresh();
|
||||
|
||||
/* Get the death */
|
||||
for (;;) {
|
||||
get_str(label, stdscr);
|
||||
which_death = atoi(label);
|
||||
if ((which_death < 1 || which_death > DEATHNUM)) {
|
||||
mvaddstr(0, 0, "Please enter a number in the displayed range -- ");
|
||||
refresh();
|
||||
}
|
||||
else break;
|
||||
}
|
||||
return(deaths[which_death-1].reason);
|
||||
}
|
||||
|
||||
#ifdef PC7300
|
||||
static menu_t Display; /* The menu structure */
|
||||
static mitem_t Dispitems[NUMMONST+1]; /* Info for each line */
|
||||
static char Displines[NUMMONST+1][LINELEN+1]; /* The lines themselves */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* make a monster for the wizard
|
||||
*/
|
||||
makemonster(showall, label, action)
|
||||
bool showall; /* showall -> show uniques and genocided creatures */
|
||||
char *label, *action;
|
||||
{
|
||||
#ifdef PC7300
|
||||
register int nextmonst;
|
||||
#endif
|
||||
register int i;
|
||||
register short which_monst;
|
||||
register int num_monst = NUMMONST, pres_monst=1, num_lines=2*(lines-3);
|
||||
int max_monster;
|
||||
char monst_name[40];
|
||||
|
||||
/* If we're not showing all, subtract out the UNIQUES and quartermaster */
|
||||
if (!showall) num_monst -= NUMUNIQUE + 1;
|
||||
max_monster = num_monst;
|
||||
|
||||
#ifdef PC7300
|
||||
nextmonst = 0;
|
||||
for (i=1; i<=num_monst; i++) {
|
||||
/* Only display existing monsters if we're not showing them all */
|
||||
if (showall || monsters[i].m_normal) {
|
||||
strcpy(Displines[nextmonst], monsters[i]);
|
||||
Dispitems[nextmonst].mi_name = Displines[nextmonst];
|
||||
Dispitems[nextmonst].mi_flags = 0;
|
||||
Dispitems[nextmonst++].mi_val = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* Place an end marker for the items */
|
||||
Dispitems[nextmonst].mi_name = 0;
|
||||
|
||||
/* Set up the main menu structure */
|
||||
Display.m_label = label;
|
||||
Display.m_title = "Monster Listing";
|
||||
Display.m_prompt = "Select a monster or press Cancl.";
|
||||
Display.m_curptr = '\0';
|
||||
Display.m_markptr = '\0';
|
||||
Display.m_flags = 0;
|
||||
Display.m_selcnt = 1;
|
||||
Display.m_items = Dispitems;
|
||||
Display.m_curi = 0;
|
||||
|
||||
/*
|
||||
* Try to display the menu. If we don't have a local terminal,
|
||||
* the call will fail and we will just continue with the
|
||||
* normal mode.
|
||||
*/
|
||||
if (menu(&Display) >= 0) {
|
||||
restscr(cw);
|
||||
touchwin(cw);
|
||||
return(Display.m_selcnt == 1 ? Display.m_curi->mi_val : -1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Print out the monsters */
|
||||
while (num_monst > 0) {
|
||||
register left_limit;
|
||||
|
||||
if (num_monst < num_lines) left_limit = (num_monst+1)/2;
|
||||
else left_limit = num_lines/2;
|
||||
|
||||
wclear(hw);
|
||||
touchwin(hw);
|
||||
|
||||
/* Print left column */
|
||||
wmove(hw, 2, 0);
|
||||
for (i=0; i<left_limit; i++) {
|
||||
sprintf(monst_name, "[%d] %c%s\n",
|
||||
pres_monst,
|
||||
(showall || monsters[pres_monst].m_normal)
|
||||
? ' '
|
||||
: '*',
|
||||
monsters[pres_monst].m_name);
|
||||
waddstr(hw, monst_name);
|
||||
pres_monst++;
|
||||
}
|
||||
|
||||
/* Print right column */
|
||||
for (i=0; i<left_limit && pres_monst<=max_monster; i++) {
|
||||
sprintf(monst_name, "[%d] %c%s",
|
||||
pres_monst,
|
||||
(showall || monsters[pres_monst].m_normal)
|
||||
? ' '
|
||||
: '*',
|
||||
monsters[pres_monst].m_name);
|
||||
wmove(hw, i+2, cols/2);
|
||||
waddstr(hw, monst_name);
|
||||
pres_monst++;
|
||||
}
|
||||
|
||||
if ((num_monst -= num_lines) > 0) {
|
||||
mvwaddstr(hw, lines-1, 0, morestr);
|
||||
draw(hw);
|
||||
wait_for(' ');
|
||||
}
|
||||
|
||||
else {
|
||||
mvwaddstr(hw, 0, 0, "Which monster");
|
||||
if (!terse) {
|
||||
waddstr(hw, " do you wish to ");
|
||||
waddstr(hw, action);
|
||||
}
|
||||
waddstr(hw, "? ");
|
||||
draw(hw);
|
||||
}
|
||||
}
|
||||
|
||||
get_monst:
|
||||
get_str(monst_name, hw);
|
||||
which_monst = atoi(monst_name);
|
||||
if ((which_monst < 1 || which_monst > max_monster)) {
|
||||
mvwaddstr(hw, 0, 0, "Please enter a number in the displayed range -- ");
|
||||
draw(hw);
|
||||
goto get_monst;
|
||||
}
|
||||
restscr(cw);
|
||||
touchwin(cw);
|
||||
return(which_monst);
|
||||
}
|
||||
|
||||
/*
|
||||
* passwd:
|
||||
* see if user knows password
|
||||
*/
|
||||
|
||||
passwd()
|
||||
{
|
||||
register char *sp, c;
|
||||
char buf[LINELEN], *crypt();
|
||||
|
||||
msg("Wizard's Password:");
|
||||
mpos = 0;
|
||||
sp = buf;
|
||||
while ((c = readchar()) != '\n' && c != '\r' && c != '\033')
|
||||
if (c == md_killchar())
|
||||
sp = buf;
|
||||
else if (c == md_erasechar() && sp > buf)
|
||||
sp--;
|
||||
else
|
||||
*sp++ = c;
|
||||
if (sp == buf)
|
||||
return FALSE;
|
||||
*sp = '\0';
|
||||
return (strcmp(PASSWD, md_crypt(buf, "mT")) == 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* teleport:
|
||||
* Bamf the hero someplace else
|
||||
*/
|
||||
|
||||
teleport()
|
||||
{
|
||||
register struct room *new_rp, *old_rp = roomin(&hero);
|
||||
register int rm, which;
|
||||
coord old;
|
||||
bool got_position = FALSE;
|
||||
|
||||
/* Disrupt whatever the hero was doing */
|
||||
dsrpt_player();
|
||||
|
||||
/*
|
||||
* If the hero wasn't doing something disruptable, NULL out his
|
||||
* action anyway and let him know about it. We don't want him
|
||||
* swinging or moving into his old place.
|
||||
*/
|
||||
if (player.t_action != A_NIL) {
|
||||
player.t_action = A_NIL;
|
||||
msg("You feel momentarily disoriented.");
|
||||
}
|
||||
|
||||
old = hero;
|
||||
mvwaddch(cw, hero.y, hero.x, mvwinch(stdscr, hero.y, hero.x));
|
||||
if (ISWEARING(R_TELCONTROL) || wizard) {
|
||||
got_position = move_hero(H_TELEPORT);
|
||||
if (!got_position)
|
||||
msg("Your attempt fails.");
|
||||
else {
|
||||
new_rp = roomin(&hero);
|
||||
msg("You teleport successfully.");
|
||||
}
|
||||
}
|
||||
if (!got_position) {
|
||||
do {
|
||||
rm = rnd_room();
|
||||
rnd_pos(&rooms[rm], &hero);
|
||||
} until(winat(hero.y, hero.x) == FLOOR);
|
||||
new_rp = &rooms[rm];
|
||||
}
|
||||
player.t_oldpos = old; /* Save last position */
|
||||
|
||||
/* If hero gets moved, darken old room */
|
||||
if (old_rp && old_rp != new_rp) {
|
||||
old_rp->r_flags |= FORCEDARK; /* Fake darkness */
|
||||
light(&old);
|
||||
old_rp->r_flags &= ~FORCEDARK; /* Restore light state */
|
||||
}
|
||||
|
||||
/* Darken where we just came from */
|
||||
else if (levtype == MAZELEV) light(&old);
|
||||
|
||||
light(&hero);
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
/* if entering a treasure room, wake everyone up......Surprise! */
|
||||
if (new_rp->r_flags & ISTREAS)
|
||||
wake_room(new_rp);
|
||||
|
||||
/* Reset current room and position */
|
||||
oldrp = new_rp; /* Used in look() */
|
||||
player.t_oldpos = hero;
|
||||
/*
|
||||
* make sure we set/unset the ISINWALL on a teleport
|
||||
*/
|
||||
which = winat(hero.y, hero.x);
|
||||
if (isrock(which)) turn_on(player, ISINWALL);
|
||||
else turn_off(player, ISINWALL);
|
||||
|
||||
/*
|
||||
* turn off ISHELD in case teleportation was done while fighting
|
||||
* something that holds you
|
||||
*/
|
||||
if (on(player, ISHELD)) {
|
||||
register struct linked_list *ip, *nip;
|
||||
register 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); /* Suffocation -- see below */
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure player does not suffocate */
|
||||
extinguish(suffocate);
|
||||
|
||||
count = 0;
|
||||
running = FALSE;
|
||||
md_flushinp();
|
||||
return rm;
|
||||
}
|
||||
|
||||
/*
|
||||
* whatis:
|
||||
* What a certin object is
|
||||
*/
|
||||
|
||||
whatis(what)
|
||||
struct linked_list *what;
|
||||
{
|
||||
register struct object *obj;
|
||||
register struct linked_list *item;
|
||||
|
||||
if (what == NULL) { /* do we need to ask which one? */
|
||||
if ((item = get_item(pack, "identify", IDENTABLE, FALSE, FALSE))==NULL)
|
||||
return;
|
||||
}
|
||||
else
|
||||
item = what;
|
||||
obj = OBJPTR(item);
|
||||
switch (obj->o_type) {
|
||||
case SCROLL:
|
||||
s_know[obj->o_which] = TRUE;
|
||||
if (s_guess[obj->o_which]) {
|
||||
free(s_guess[obj->o_which]);
|
||||
s_guess[obj->o_which] = NULL;
|
||||
}
|
||||
when POTION:
|
||||
p_know[obj->o_which] = TRUE;
|
||||
if (p_guess[obj->o_which]) {
|
||||
free(p_guess[obj->o_which]);
|
||||
p_guess[obj->o_which] = NULL;
|
||||
}
|
||||
when STICK:
|
||||
ws_know[obj->o_which] = TRUE;
|
||||
if (ws_guess[obj->o_which]) {
|
||||
free(ws_guess[obj->o_which]);
|
||||
ws_guess[obj->o_which] = NULL;
|
||||
}
|
||||
when RING:
|
||||
r_know[obj->o_which] = TRUE;
|
||||
if (r_guess[obj->o_which]) {
|
||||
free(r_guess[obj->o_which]);
|
||||
r_guess[obj->o_which] = NULL;
|
||||
}
|
||||
when MM:
|
||||
/* If it's an identified jug, identify its potion */
|
||||
if (obj->o_which == MM_JUG && (obj->o_flags & ISKNOW)) {
|
||||
if (obj->o_ac != JUG_EMPTY)
|
||||
p_know[obj->o_ac] = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
m_know[obj->o_which] = TRUE;
|
||||
if (m_guess[obj->o_which]) {
|
||||
free(m_guess[obj->o_which]);
|
||||
m_guess[obj->o_which] = NULL;
|
||||
}
|
||||
otherwise:
|
||||
break;
|
||||
}
|
||||
obj->o_flags |= ISKNOW;
|
||||
if (what == NULL)
|
||||
msg(inv_name(obj, FALSE));
|
||||
}
|
||||
|
||||
694
arogue7/xcrypt.c
Normal file
694
arogue7/xcrypt.c
Normal file
|
|
@ -0,0 +1,694 @@
|
|||
/*
|
||||
* 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>
|
||||
|
||||
#ifdef MASTER
|
||||
# include <stdio.h>
|
||||
#endif
|
||||
#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(ch)
|
||||
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 i, j, b, k, inbit, obit;
|
||||
unsigned int *p, *il, *ir, *fl, *fr;
|
||||
|
||||
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(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(key)
|
||||
const 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(l_in, r_in, l_out, r_out, count)
|
||||
unsigned int l_in, r_in, *l_out, *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(in, out, salt, count)
|
||||
const char *in;
|
||||
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(key, setting)
|
||||
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