# HG changeset patch
# User John "Elwin" Edwards
# Date 1431113080 14400
# Node ID adfa37e670842b857b49b6cc83565b7cbd5e4427
# Parent d10fc4a065ac7e84ca38edf2bd2b27cef07db59f
Import Advanced Rogue 7.7 from the Roguelike Restoration Project (r1490)
diff -r d10fc4a065ac -r adfa37e67084 arogue7/LICENSE.TXT
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/LICENSE.TXT Fri May 08 15:24:40 2015 -0400
@@ -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.
diff -r d10fc4a065ac -r adfa37e67084 arogue7/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/Makefile Fri May 08 15:24:40 2015 -0400
@@ -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
diff -r d10fc4a065ac -r adfa37e67084 arogue7/actions.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/actions.c Fri May 08 15:24:40 2015 -0400
@@ -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
+#include
+#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; it_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);
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/aguide.mm
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/aguide.mm Fri May 08 15:24:40 2015 -0400
@@ -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.
diff -r d10fc4a065ac -r adfa37e67084 arogue7/arogue77.doc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/arogue77.doc Fri May 08 15:24:40 2015 -0400
@@ -0,0 +1,1122 @@
+
+
+
+
+
+
+ The Dungeons of Doom
+
+ Toolchest
+
+
+
+
+
+
+ 1. INTRODUCTION
+
+ Rogue is a screen-oriented fantasy game set in the
+ ever-changing Dungeons of Doom. 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.
+
+ 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 Complete Winner. But even after finding the
+ artifact, the player may wish to continue further to match
+ wits with an arch-devil, demon prince, or even a deity found
+ far down in the dungeon. Defeating such a creature will
+ gain the player many experience points, the basis for
+ scoring in Rogue.
+
+ It is very difficult to return from the Dungeons of
+ Doom. 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.
+
+
+ 2. 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.
+
+ 2.1 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
+
+
+
+
+
+
+
+
+ - 2 -
+
+
+
+ levels the fighter 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.
+
+ 2.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.
+
+ 2.3 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.
+
+ Because of their religious nature, clerics can also
+ affect the "undead" beings, like zombies and ghouls, 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.
+
+ Clerics can gain from 1 to 8 extra hit points on
+ reaching a new experience level.
+
+ 2.4 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.
+
+ Druids gain from 1 to 8 hit points when they gain an
+ experience level.
+
+ 2.5 The Thief
+
+ A thief is exceptionally dextrous and has a good chance
+ to set a trap or rob a monster.
+
+ 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 thief manages to sneak up on a
+ creature without waking it, he will get a chance to backstab
+ the monster. When this is done, the damage done by the thief
+
+
+
+
+
+
+
+
+ - 3 -
+
+
+
+ greatly increases based on his experience level.
+
+ Thieves gain from 1 to 6 extra hit points from a new
+ experience level.
+
+ 2.6 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.
+
+ Paladins gain 1 to 10 hit points per experience level.
+
+ 2.7 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.
+
+ Rangers gain 1 to 8 hit points per experience level.
+
+ 2.8 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.
+
+ Monks gain 1 to 6 hit points per experience level.
+
+ 2.9 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.
+
+ Assassins gain 1 to 6 hit points per experience level.
+
+
+ 3. ATTRIBUTES
+
+
+
+
+
+
+
+
+
+ - 4 -
+
+
+
+ 3.1 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.
+
+ 3.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.
+
+ 3.3 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.
+
+ 3.4 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.
+
+ 3.5 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.
+
+ 3.6 Charisma
+
+ Charisma is a measure of a characters looks and general
+ likeableness. It effects transactions when trying to
+ purchase things.
+
+ 3.7 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
+
+
+
+
+
+
+
+
+ - 5 -
+
+
+
+ new prayers.
+
+ 3.8 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.
+
+
+ 4. 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.
+
+ 4.1 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 '--More--.' 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.
+
+ 4.2 The Dungeon Section
+
+ The large middle section of the screen displays the
+ player's surroundings using the following symbols:
+
+ | A wall of a room.
+
+ - A wall of a room.
+
+ * A pile of gold.
+
+ % A way to the next level.
+
+ + A doorway.
+
+ . The floor in a room.
+
+ @ The player.
+
+
+
+
+
+
+
+
+
+ - 6 -
+
+
+
+ _ The player, when invisible.
+
+ # The floor in a passageway.
+
+ ! A flask containing a potion.
+
+ ? A sealed scroll.
+
+ : Some food.
+
+ ) A weapon.
+
+ Solid rock (denoted by a space).
+
+ ] Some armor.
+
+ ; A miscellaneous magic item
+
+ , An artifact
+
+ = A ring.
+
+ / A wand or a staff.
+
+ ^ The entrance to a trading post
+
+ > A trapdoor leading to the next level
+
+ { An arrow trap
+
+ $ A sleeping gas trap
+
+ } A beartrap
+
+ ~ A trap that teleports you somewhere else
+
+ ` A poison dart trap
+
+ " A shimmering magic pool
+
+ ' An entrance to a maze
+
+ $ Any magical item. (During magic detection)
+
+ > A blessed magical item. (During magic detection)
+
+ < A cursed magical item. (During magic detection)
+
+ 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 ('/').
+
+
+
+
+
+
+
+
+
+
+ - 7 -
+
+
+
+ 4.3 The Status Section
+
+ The bottom two lines of the screen describe the
+ player's current status. The first line gives the player's
+ characteristics:
+
+ o Intelligence (Int)
+
+ o Strength (Str)
+
+ o Wisdom (Wis)
+
+ o Dexterity (Dxt)
+
+ o Constitution (Const)
+
+ o Charisma (Char)
+
+ o Encumberance (Carry)
+
+ 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.
+
+ The second status line provides the following
+ information:
+
+ o The current level (Lvl) in the dungeon. This number
+ increases as the player goes further down.
+
+ o The player's current number of hit points (Hp),
+ 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.
+
+ o The player's armor class (Ac). 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.
+
+ o The player's current experience level (Exp) 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
+
+
+
+
+
+
+
+
+ - 8 -
+
+
+
+ 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.
+
+ o A description of the player's character. This
+ description depends on the player's character type and
+ experience level.
+
+
+ 5. 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.
+
+ 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
+ inventory command. Typing a '*' at this point produces a
+ list of the eligible items.
+
+ Rogue understands the following commands:
+
+ ? Preceding a command by a '?' produces a brief
+ explanation of the command. The command '?*' gives an
+ explanation of all the commands.
+
+ / Preceding a symbol by a '/' identifies the symbol.
+
+ = Clarify. After typing an '=' 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 sleeping giant rat, a
+ blue potion, and a food ration.
+
+ h Move one position to the left.
+
+ j Move one position down.
+
+ k Move one position up.
+
+ l Move one position to the right.
+
+ y Move one position to the top left.
+
+ u Move one position to the top right.
+
+
+
+
+
+
+
+
+
+ - 9 -
+
+
+
+ b Move one position to the bottom left.
+
+ n Move one position to the bottom right.
+
+ H Run to the left until reaching something interesting.
+
+ J Run down until reaching something interesting.
+
+ K Run up until reaching something interesting.
+
+ L Run to the right until reaching something interesting.
+
+ Y Run to the top left until reaching something
+ interesting.
+
+ U Run to the top right until reaching something
+ interesting.
+
+ B Run to the bottom left until reaching something
+ interesting.
+
+ N Run to the bottom right until reaching something
+ interesting.
+
+ t This command prompts for an object from the players
+ pack. The player then throws the object in the
+ specified direction.
+
+ f When this command precedes a directional command, the
+ player moves in the specified direction until passing
+ something interesting.
+
+ z This command prompts for a wand or staff from the
+ player's pack and zaps it in the specified direction.
+
+ > Go down to the next level.
+
+ < Go up to the next level.
+
+ s Search for a secret door or a trap in the circle
+ surrounding the player.
+
+ . This command (a dot) causes the player to rest a turn.
+
+ i Display an inventory of the player's pack.
+
+ I This command prompts for an item from the player's pack
+ and displays the inventory information for that item.
+
+ q Quaff a potion from the player's pack.
+
+ r Read a scroll from the player's pack.
+
+
+
+
+
+
+
+
+
+
+ - 10 -
+
+
+
+ e Eat some food from the player's pack.
+
+ w Wield a weapon from the player's pack.
+
+ W Wear some armor, ring, or miscellaneous magic item from
+ the player's pack. The player can wear a maximum of
+ eight rings.
+
+ T Take off whatever the player is wearing.
+
+ ^U Use a magic item in the player's pack.
+
+ d Drop an item from the player's pack.
+
+ P Pick up the items currently under the player.
+
+ ^N When the player types this command, Rogue prompts for a
+ monster or an item from the player's pack and a one-line
+ name. For monsters, the player can use the movement
+ keys to position the cursor over the desired monster,
+ and Rogue will use the given name to refer to that
+ monster. For items, Rogue gives all similar items (such
+ as all the blue potions) the specified name.
+
+ m When the player types this command, Rogue prompts for an
+ item from the player's pack and a one-line name. Rogue
+ then marks the specified item with the given name.
+
+ o Typing this command causes Rogue to display all the
+ settable options. The player can then merely examine
+ the options or change any or all of them.
+
+ 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, Cast it.
+ The more complicated the spell, the more energy it
+ takes.
+
+ 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, chant it.
+ The more complicated the spell, the more energy it
+ takes.
+
+ p This command, restricted to clerics and paladins,
+ produces a listing of the character's known prayers.
+ 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.
+
+
+
+
+
+
+
+
+
+
+ - 11 -
+
+
+
+ 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
+ affect the monster by causing it to flee or possibly
+ even destroying it.
+
+ * Count the gold in the player's pack.
+
+ ^ 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.
+
+ G This command is restricted to thieves and assassins. It
+ causes Rogue to display all the gold on the current
+ level.
+
+ D Dip something into a magic pool.
+
+ ^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 steal 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.
+
+ ^L Redraw the screen.
+
+ ^R Repeat the last message that was displayed on the top
+ line of the screen.
+
+ ^[ Typing an escape will usually cause Rogue to cancel the
+ current command.
+
+ v Print the current Rogue version number.
+
+ ! Escape to the shell.
+
+ S Quit and save the game for resumption at a later time.
+
+ Q Quit without saving the game.
+
+
+ 6. 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.
+
+
+
+
+
+
+
+
+
+ - 12 -
+
+
+
+ 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.
+
+
+ 7. 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.
+
+ 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.
+
+ Magical hasting (or slowing) will decrease (or
+ increase) the time it takes to perform an action.
+
+
+ 8. 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 fire
+ beetle.
+
+
+ 9. 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.
+
+ 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.
+
+
+
+
+
+
+
+
+ - 13 -
+
+
+
+ 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.
+
+ 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.
+
+ 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.
+
+
+ 10. 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.
+
+
+ 11. 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.
+
+
+ 12. 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.
+
+
+
+
+
+
+
+
+
+
+
+ - 14 -
+
+
+
+ 13. 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.
+
+ 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.
+
+
+ 14. GOLD
+
+ Gold has one use in a dungeon: buying things. One can
+ buy things in two ways, either in a trading post or from a
+ quartermaster. 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.
+
+ 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.
+
+
+
+ 15. 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.
+
+
+ 16. 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
+
+
+
+
+
+
+
+
+ - 15 -
+
+
+
+ mishandling or abuse. These items consume food and merely
+ carrying them will result in increased food use.
+
+
+ 17. 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.
+
+
+ 18. THE MONSTERS
+
+ Each monster except for the merchant quartermaster
+ appears in a limited range of dungeon levels. All monsters
+ of the same type share the same abilities; all giant rats,
+ for example, can give the player a disease, and all
+ jackalweres can put the player to sleep. Monsters of the
+ same type can vary, however, such that one kobold 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.
+
+ 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.
+
+ 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.
+
+ It is sometimes possible to enlist a monster's aid.
+ Reading a charm monster scroll, for example, or singing a
+ charm monster 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.
+
+ 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.
+
+
+ 19. OPTIONS
+
+ Rogue has several options which may be set by the
+ player:
+
+
+
+
+
+
+
+
+ - 16 -
+
+
+
+ terse Setting this Boolean option results in shorter
+ messages appearing on the top line of the screen.
+
+ jump 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.
+
+ step 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.
+
+ flush Setting this Boolean option results in flushing all
+ typeahead (pending) commands when the player
+ encounters a monster.
+
+ askme 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.
+
+ pickup 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.
+
+ name This string is the player's name and defaults to the
+ player's account name.
+
+ file This string, which defaults to rogue.save, specifies
+ the file to use for saving the game.
+
+ score This string identifies the top-twenty score file to
+ use for the game.
+
+ class This option specifies the character class of the
+ rogue. It can be set only in the ROGUEOPTS
+ environment variable.
+
+ quested item
+ 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.
+
+ 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 terse, jump, flush, and askme Boolean options, clear
+ the step Boolean option, set the player's name to "Ivan the
+
+
+
+
+
+
+
+
+ - 17 -
+
+
+
+ Terrible," and use the defaults for the save file and the
+ score file.
+
+ The player may change an option at any time during the
+ game via the option 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.
+
+
+ 20. 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.
+
+ 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.
+
+
+ 21. ACKNOWLEDGEMENTS
+
+ This version of Rogue is based on a version developed
+ at the University of California.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -r d10fc4a065ac -r adfa37e67084 arogue7/arogue77.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/arogue77.html Fri May 08 15:24:40 2015 -0400
@@ -0,0 +1,1328 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Toolchest
+http://roguelike.sourceforge.net/arogue77
+
+
+
+
+ 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.
+
+1. Introduction
+
+
+ Rogue is a screen-oriented fantasy game set in the
+ ever-changing Dungeons of Doom. 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.
+
+
+
+ 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 Complete Winner. But even after finding the
+ artifact, the player may wish to continue further to match
+ wits with an arch-devil, demon prince, or even a deity found
+ far down in the dungeon. Defeating such a creature will
+ gain the player many experience points, the basis for
+ scoring in Rogue.
+
+
+
+ It is very difficult to return from the Dungeons of
+ Doom. 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.
+
+
+2. 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.
+
+
+2.1 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 fighter 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.
+
+
+2.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.
+
+2.3 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.
+
+
+
+ Because of their religious nature, clerics can also
+ affect the "undead" beings, like zombies and ghouls, 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.
+
+
+
+ Clerics can gain from 1 to 8 extra hit points on
+ reaching a new experience level.
+
+2.4 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.
+
+
+
+ Druids gain from 1 to 8 hit points when they gain an
+ experience level.
+
+
+2.5 The Thief
+
+
+ A thief is exceptionally dextrous and has a good chance
+ to set a trap or rob a monster.
+
+
+
+ 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 thief manages to sneak up on a
+ creature without waking it, he will get a chance to backstab
+ the monster. When this is done, the damage done by the thief
+ greatly increases based on his experience level.
+
+
+
+ Thieves gain from 1 to 6 extra hit points from a new
+ experience level.
+
+
+2.6 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.
+
+
+
+ Paladins gain 1 to 10 hit points per experience level.
+
+
+2.7 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.
+
+
+
+ Rangers gain 1 to 8 hit points per experience level.
+
+
+2.8 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.
+
+
+
+ Monks gain 1 to 6 hit points per experience level.
+
+
+2.9 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.
+
+
+
+ Assassins gain 1 to 6 hit points per experience level.
+
+
+3. ATTRIBUTES
+
+3.1 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.
+
+
+
+3.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.
+
+
+3.3 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.
+
+
+3.4 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.
+
+
+3.5 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.
+
+
+3.6 Charisma
+Charisma is a measure of a characters looks and general
+ likeableness. It effects transactions when trying to
+ purchase things.
+
+3.7 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.
+
+
+
+
+3.8 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.
+
+
+
+4.0
+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.
+
+
+4.1 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 '--More--.' 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.
+
+
+
+4.2 The Dungeon Section
+The large middle section of the screen displays the
+player's surroundings using the following symbols:
+
+
+
+
+
+ | |
+ |
+ A wall of a room. |
+
+
+ - |
+ |
+ A wall of a room. |
+
+
+ * |
+ |
+ A pile of gold. |
+
+
+ % |
+ |
+ A way to another level. |
+
+
+ + |
+ |
+ A doorway. |
+
+
+ . |
+ |
+ The floor in a room |
+
+
+ @ |
+ |
+ The player. |
+
+
+ _ |
+ |
+ The player, when invisible. |
+
+
+ # |
+ |
+ The floor in a passageway |
+
+
+ ! |
+ |
+ A flask containing a potion. |
+
+
+ ? |
+ |
+ A sealed scroll. |
+
+
+ : |
+ |
+ Some food. |
+
+
+ ) |
+ |
+ A weapon. |
+
+
+ |
+ |
+ Solid rock (denoted by a space) |
+
+
+ ] |
+ |
+ Some armor. |
+
+
+ ; |
+ |
+ A miscellaneous magic item. |
+
+
+ , |
+ |
+ An artifact. |
+
+
+ = |
+ |
+ A ring. |
+
+
+ / |
+ |
+ A wand or a staff. |
+
+
+ ^ |
+ |
+ The entrance to a trading post. |
+
+
+ > |
+ |
+ A trapdoor leading to the next level. |
+
+
+ { |
+ |
+ An arrow trap. |
+
+
+ $ |
+ |
+ A sleeping gas trap. |
+
+
+ } |
+ |
+ A beartrap. |
+
+
+ ~ |
+ |
+ A trap that teleports you somewhere else. |
+
+
+ ` |
+ |
+ A poison dart trap. |
+
+
+ " |
+ |
+ a shimmering magic pool. |
+
+
+ ' |
+ |
+ An entrance to a maze. |
+
+
+ $ |
+ |
+ Any magical item. (During magic detection) |
+
+
+ > |
+ |
+ A blessed magical item. (Duriing magic detection) |
+
+
+ < |
+ |
+ A cursed magical item. (During magic detection) |
+
+
+ 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 ('/'). |
+
+
+
+
+4.3 The Status Section
+
+
+The bottom two lines of the screen describe the
+player's current status. The first line gives the player's
+characteristics:
+
+
+
+-
+
Intelligence (Int)
+-
+
Strength (Str)
+-
+
Wisdom (Wis)
+-
+
Dexterity (Dxt)
+-
+
Constitution (Const)
+-
+
Charisma (Char)
+-
+
Encumberance (Carry)
+
+
+
+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.
+
+
+
+The second status line provides the following
+information:
+
+
+
+-
+
The current level (Lvl) in the dungeon. This number
+increases as the player goes further down.
+
+-
+
The player's current number of hit points (Hp),
+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.
+
+-
+
The player's armor class (Ac). 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.
+
+-
+
The player's current experience level (Exp) 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.
+
+-
+
A description of the player's character. This
+description depends on the player's character type and
+experience level.
+
+
+
+5.0 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.
+
+
+
+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
+inventory command. Typing a '*' at this point produces a
+list of the eligible items.
+
+
+Rogue understands the following commands:
+
+
+
+
+ ? |
+ |
+ Preceding a command by a '?' produces a brief explanation of the
+ command. The command '?*' gives an explanation of all the commands. |
+
+
+ / |
+ |
+ Preceding a symbol by a '/' identifies the symbol. |
+
+
+ = |
+ |
+ Clarify. After typing an '=' 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 sleeping giant rat, a blue
+ potion, and a food ration. |
+
+
+ h |
+ |
+ Move one position to the left. |
+
+
+ j |
+ |
+ Move one position down. |
+
+
+ k |
+ |
+ Move one position up. |
+
+
+ l |
+ |
+ Move one position to the right. |
+
+
+ y |
+ |
+ Move one position to the top left. |
+
+
+ u |
+ |
+ Move one position to the top right. |
+
+
+ b |
+ |
+ Move one position to the bottom left. |
+
+
+ n |
+ |
+ Move one position to the bottom right |
+
+
+ H |
+ |
+ Run to the left until reaching something interesting. |
+
+
+ J |
+ |
+ Run down until reaching something interesting. |
+
+
+ K |
+ |
+ Run up until reaching something interesting. |
+
+
+ L |
+ |
+ Run to the right until reaching something interesting. |
+
+
+ Y |
+ |
+ Run to the top left until reaching something interesting. |
+
+
+ U |
+ |
+ Run to the top right until reaching something interesting. |
+
+
+ B |
+ |
+ Run to the bottom left until reaching something interesting. |
+
+
+ N |
+ |
+ Run to the bottom right until reaching something interesting |
+
+
+ t |
+ |
+ This command prompts for an object from the players pack. The player
+then throws the object in the specified direction. |
+
+
+ f |
+ |
+ When this command is preceded with a directional command, the player
+ moves in the specified direction until passing something interesting. |
+
+
+ z |
+ |
+ This command prompts for a wand or staff from the player's pack and
+ zaps
+it in the specified direction. |
+
+
+ > |
+ |
+ Go down to the next level. |
+
+
+ < |
+ |
+ Go up to the next level. |
+
+
+ s |
+ |
+ Search for a secret door or a trap in the circle surrounding the
+ player. |
+
+
+ . |
+ |
+ This command (a dot) causes the player to rest a turn. |
+
+
+ i |
+ |
+ Display an inventory of the player's pack. |
+
+
+ I |
+ |
+ This command prompts for an item from the player's pack and displays
+the inventory information for that item. |
+
+
+ q |
+ |
+ Quaff a potion from the player's pack. |
+
+
+ r |
+ |
+ Read a scroll from the player's pack. |
+
+
+ e |
+ |
+ Eat some food from the player's pack. |
+
+
+ w |
+ |
+ Wield a weapon from the player's pack. |
+
+
+ W |
+ |
+ Wear some armor, ring, or a miscellaneous magic item from the
+ player's
+pack. The player can wear a maximum of 8 rings. |
+
+
+ T |
+ |
+ Take off whatever the player is wearing. |
+
+
+ ^U |
+ |
+ Use a magic item in the player's pack. |
+
+
+ d |
+ |
+ Drop an item from the player's pack. |
+
+
+ P |
+ |
+ Pick up the items currently under the player. |
+
+
+ ^N |
+ |
+ When the player types this command, Rogue prompts for a monster or
+ an item from the player's pack and a one-line name. For monsters, the
+ player can use the movement keys to position the cursor over the desired
+ monster, and Rogue will use the given name to refer to that
+ monster. For items, Rogue gives all similar items (such as all the blue
+ potions) the specified name. |
+
+
+ m |
+ |
+ When the player types this command, Rogue prompts for an item from
+ the player's pack and a one-line name. Rogue then marks the specified
+ item with the given name.. |
+
+
+ o |
+ |
+ Typing this command causes Rogue to display all the settable
+ options. The player can then merely examine the options or change any or
+ all of them. |
+
+
+ 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,
+ Cast it. The more complicated the spell, the more energy it takes. |
+
+
+ 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, chant it.
+ The more complicated the spell, the more energy it takes. |
+
+
+ p |
+ |
+ This command, restricted to clerics and paladins, produces a listing
+ of the character's known prayers. 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. |
+
+
+ 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 affect the monster by causing it to flee or possibly even
+ destroying it. |
+
+
+ * |
+ |
+ Count the gold in the player's pack. |
+
+
+ ^ |
+ |
+ 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. |
+
+
+ G |
+ |
+ This command is restricted to thieves and assassins. It causes Rogue
+ to display all the gold on the current level. |
+
+
+ D |
+ |
+ Dip something into a magic pool. |
+
+
+ ^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 steal 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. |
+
+
+ ^L |
+ |
+ Redraw the screen. |
+
+
+ ^R |
+ |
+ Repeat the last message that was displayed on the top line of the
+ screen. |
+
+
+ Escape (^[) |
+ |
+ Typing an escape will usually cause Rogue to cancel the current
+ command. |
+
+
+ v |
+ |
+ Print the current Rogue version number. |
+
+
+ ! |
+ |
+ Escape to the shell level. |
+
+
+ S |
+ |
+ Quit and save the game for resumption at a later time. |
+
+
+ Q |
+ |
+ Quit without saving the game. |
+
+
+
+
+6. 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.
+
+
+
+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.
+
+
+7. 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.
+
+
+
+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.
+
+
+
+Magical hasting (or slowing) will decrease (or
+increase) the time it takes to perform an action.
+
+
+8.0 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 fire
+beetle.
+
+
+9. 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.
+
+
+
+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.
+
+
+
+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.
+
+
+
+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.
+
+
+
+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.
+
+
+
+10. 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.
+
+
+11. 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.
+
+
+12. 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.
+
+
+13. 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.
+
+
+
+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.
+
+
+14. GOLD
+
+
+Gold has one use in a dungeon: buying things. One can
+buy things in two ways, either in a trading post or from a
+quartermaster. 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.
+
+
+
+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.
+
+
+15. 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.
+
+
+16. 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.
+
+
+17. 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.
+
+
+18. THE MONSTERS
+
+
+Each monster except for the merchant quartermaster
+appears in a limited range of dungeon levels. All monsters
+of the same type share the same abilities; all giant rats,
+for example, can give the player a disease, and all
+jackalweres can put the player to sleep. Monsters of the
+same type can vary, however, such that one kobold 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.
+
+
+
+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.
+
+
+
+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.
+
+
+
+It is sometimes possible to enlist a monster's aid.
+Reading a charm monster scroll, for example, or singing a
+charm monster 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.
+
+
+
+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.
+
+
+
+19. OPTIONS
+
+
+Rogue has several options which may be set by the player:
+
+
+
+
+
+ terse |
+ |
+ Setting this Boolean option results in shorter messages appearing on
+ the top line of the screen. |
+
+
+ jump |
+ |
+ 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. |
+
+
+ step |
+ |
+ 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. |
+
+
+ flush |
+ |
+ Setting this Boolean option results in flushing all typeahead
+ (pending) commands when the player encounters a monster. |
+
+
+ askme |
+ |
+ 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. |
+
+
+ pickup |
+ |
+ This option specifies 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. |
+
+
+ name |
+ |
+ This string is the player's name and defaults to the player's
+ account name. |
+
+
+ file |
+ |
+ This string, which defaults to arogue77.sav, specifies the file to
+ use for saving the game. |
+
+
+ score |
+ |
+ This string identifies the top-twenty score file to use for the
+ game. |
+
+
+ class |
+ |
+ This option specifies the character class of the rogue. It can be
+ set only in the ROGUEOPTS
+ environment variable. |
+
+
+ quested item |
+ |
+ 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. |
+
+
+
+
+
+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 terse, jump, flush, and askme
+Boolean options, clear the step Boolean option, set the player's name to "Ivan
+the Terrible," and use the defaults for the save file and the score file.
+
+
+
+The player may change an option at any time during the game via the option
+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.
+
+
+20. 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.
+
+
+
+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.
+
+
+21. ACKNOWLEDGEMENTS
+
+
+This version of Rogue is based on a version developed
+at the University of California.
+
diff -r d10fc4a065ac -r adfa37e67084 arogue7/arogue77.sln
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/arogue77.sln Fri May 08 15:24:40 2015 -0400
@@ -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
diff -r d10fc4a065ac -r adfa37e67084 arogue7/arogue77.vcproj
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/arogue77.vcproj Fri May 08 15:24:40 2015 -0400
@@ -0,0 +1,270 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -r d10fc4a065ac -r adfa37e67084 arogue7/chase.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/chase.c Fri May 08 15:24:40 2015 -0400
@@ -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
+#include
+#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= 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);
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/command.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/command.c Fri May 08 15:24:40 2015 -0400
@@ -0,0 +1,1220 @@
+/*
+ * command.c - Read and execute the user 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.
+ */
+
+/*
+ * Read and execute the user commands
+ *
+ */
+
+#include "curses.h"
+#include
+#include
+#include "mach_dep.h"
+#include "rogue.h"
+#ifdef PC7300
+#include "sys/window.h"
+extern struct uwdata wdata;
+#endif
+
+/*
+ * command:
+ * Process the user commands
+ */
+
+command()
+{
+ unsigned char ch;
+ struct linked_list *item;
+ unsigned char countch, direction, newcount = FALSE;
+ int segment = 1;
+ int monst_limit, monst_current;
+
+ monst_limit = monst_current = 1;
+ while (playing) {
+ /*
+ * Let the daemons start up, but only do them once a round
+ * (round = 10 segments).
+ */
+ if (segment >= 10) {
+ do_daemons(BEFORE);
+ do_fuses(BEFORE);
+ }
+
+ after = TRUE;
+ do {
+ /* One more tick of the clock. */
+ if (segment >= 10 && after && (++turns % DAYLENGTH) == 0) {
+ daytime ^= TRUE;
+ if (levtype == OUTSIDE) {
+ if (daytime) msg("The sun rises above the horizon");
+ else msg("The sun sinks below the horizon");
+ }
+ light(&hero);
+ }
+
+ /*
+ * Don't bother with these updates unless the player's going
+ * to do something.
+ */
+ if (player.t_action == A_NIL && player.t_no_move <= 1) {
+ look(after, FALSE);
+ lastscore = purse;
+ wmove(cw, hero.y, hero.x);
+ if (!((running || count) && jump)) {
+ status(FALSE);
+ }
+ }
+
+ /* Draw the screen */
+ if (!((running || count) && jump)) {
+ wmove(cw, hero.y, hero.x);
+ draw(cw);
+ }
+
+ after = TRUE;
+
+ /*
+ * Read command or continue run
+ */
+ if (--player.t_no_move <= 0) {
+ take = 0; /* Nothing here to start with */
+ player.t_no_move = 0; /* Be sure we don't go too negative */
+ if (!running) door_stop = FALSE;
+
+ /* Was the player being held? */
+ if (player.t_action == A_FREEZE) {
+ player.t_action = A_NIL;
+ msg("You can move again.");
+ }
+
+ if (player.t_action != A_NIL) ch = (char) player.t_action;
+ else if (running) {
+ char scratch;
+
+ /* If in a corridor or maze, if we are at a turn with
+ * only one way to go, turn that way.
+ */
+ scratch = CCHAR( winat(hero.y, hero.x) );
+ if ((scratch==PASSAGE||scratch==DOOR||levtype==MAZELEV) &&
+ off(player, ISHUH) &&
+ off(player, ISBLIND)) {
+ int y, x;
+ if (getdelta(runch, &y, &x) == TRUE) {
+ corr_move(y, x);
+ }
+ }
+ ch = runch;
+ }
+ else if (count) ch = countch;
+ else {
+ ch = readchar();
+ if (mpos != 0 && !running) /* Erase message if its there */
+ msg("");
+ }
+
+ /*
+ * check for prefixes
+ */
+ if (isdigit(ch))
+ {
+ count = 0;
+ newcount = TRUE;
+ while (isdigit(ch))
+ {
+ count = count * 10 + (ch - '0');
+ if (count > 255)
+ count = 255;
+ ch = readchar();
+ }
+ countch = ch;
+ /*
+ * turn off count for commands which don't make sense
+ * to repeat
+ */
+ switch (ch) {
+ case 'h': case 'j': case 'k': case 'l':
+ case 'y': case 'u': case 'b': case 'n':
+ case 'H': case 'J': case 'K': case 'L':
+ case 'Y': case 'U': case 'B': case 'N':
+ case C_SEARCH: case '.':
+ break;
+ default:
+ count = 0;
+ }
+ }
+
+ /* Save current direction */
+ if (!running) { /* If running, it is already saved */
+ switch (ch) {
+ case 'h': case 'j': case 'k': case 'l':
+ case 'y': case 'u': case 'b': case 'n':
+ case 'H': case 'J': case 'K': case 'L':
+ case 'Y': case 'U': case 'B': case 'N':
+ runch = tolower(ch);
+ }
+ }
+
+ /* Perform the action */
+ switch (ch) {
+ case 'f':
+ if (!on(player, ISBLIND))
+ {
+ door_stop = TRUE;
+ firstmove = TRUE;
+ }
+ if (count && !newcount)
+ ch = direction;
+ else
+ ch = readchar();
+ switch (ch)
+ {
+ case 'h': case 'j': case 'k': case 'l':
+ case 'y': case 'u': case 'b': case 'n':
+ ch = toupper(ch);
+ }
+ direction = ch;
+ }
+ newcount = FALSE;
+
+ /*
+ * execute a command
+ */
+ if (count && !running)
+ count--;
+ switch (ch) {
+ case '!' : shell();
+ when 'h' : do_move(0, -1);
+ when 'j' : do_move(1, 0);
+ when 'k' : do_move(-1, 0);
+ when 'l' : do_move(0, 1);
+ when 'y' : do_move(-1, -1);
+ when 'u' : do_move(-1, 1);
+ when 'b' : do_move(1, -1);
+ when 'n' : do_move(1, 1);
+ when 'H' : do_run('h');
+ when 'J' : do_run('j');
+ when 'K' : do_run('k');
+ when 'L' : do_run('l');
+ when 'Y' : do_run('y');
+ when 'U' : do_run('u');
+ when 'B' : do_run('b');
+ when 'N' : do_run('n');
+ when A_PICKUP:
+ player.t_action = A_NIL;
+ if (add_pack(NULL, FALSE, NULL)) {
+ char tch;
+
+ tch = CCHAR( mvwinch(stdscr, hero.y, hero.x) );
+ if (tch != FLOOR && tch != PASSAGE) {
+ player.t_action = A_PICKUP; /*get more */
+ player.t_no_move += 2 * movement(&player);
+ }
+ }
+ when A_ATTACK:
+ /* Is our attackee still there? */
+ if (isalpha(winat(player.t_newpos.y,
+ player.t_newpos.x))) {
+ /* Our friend is still here */
+ player.t_action = A_NIL;
+ fight(&player.t_newpos, cur_weapon, FALSE);
+ }
+ else { /* Our monster has moved */
+ player.t_action = A_NIL;
+ }
+ when A_THROW:
+ if (player.t_action == A_NIL) {
+ item = get_item(pack, "throw", ALL, FALSE, FALSE);
+ if (item != NULL && get_dir(&player.t_newpos)) {
+ player.t_action = A_THROW;
+ player.t_using = item;
+ player.t_no_move = 2 * movement(&player);
+ }
+ else
+ after = FALSE;
+ }
+ else {
+ missile(player.t_newpos.y, player.t_newpos.x,
+ player.t_using, &player);
+ player.t_action = A_NIL;
+ player.t_using = 0;
+ }
+ when 'Q' : after = FALSE; quit(0);
+ when 'i' : after = FALSE; inventory(pack, ALL);
+ when 'I' : after = FALSE; picky_inven();
+ when C_DROP : player.t_action = C_DROP; drop(NULL);
+ when 'P' :
+ if (levtype != POSTLEV) {
+ /* We charge 2 movement units per item */
+ player.t_no_move =
+ 2 * grab(hero.y, hero.x) * movement(&player);
+ }
+ else {
+ /* Let's quote the wise guy a price */
+ buy_it();
+ after = FALSE;
+ }
+ when C_COUNT : count_gold();
+ when C_QUAFF : quaff(-1, NULL, NULL, TRUE);
+ when C_READ : read_scroll(-1, NULL, TRUE);
+ when C_EAT : eat();
+ when C_WIELD : wield();
+ when C_WEAR : wear();
+ when C_TAKEOFF : take_off();
+ when 'o' : option();
+ when CTRL('N') : nameit();
+ when '=' : after = FALSE; display();
+ when 'm' : nameitem(NULL, TRUE);
+ when '>' : after = FALSE; d_level();
+ when '<' : after = FALSE; u_level();
+ when '?' : after = FALSE; help();
+ when '/' : after = FALSE; identify(NULL);
+ when C_USE : use_mm(-1);
+ when CTRL('T') :
+ if (player.t_action == A_NIL) {
+ if (get_dir(&player.t_newpos)) {
+ player.t_action = CTRL('T');
+ player.t_no_move = 2 * movement(&player);
+ }
+ else
+ after = FALSE;
+ }
+ else {
+ steal();
+ player.t_action = A_NIL;
+ }
+ when C_DIP : dip_it();
+ when 'G' :
+ if (player.t_action == A_NIL) {
+ player.t_action = 'G';
+ player.t_no_move = movement(&player);
+ }
+ else {
+ gsense();
+ player.t_action = A_NIL;
+ }
+ when C_SETTRAP : set_trap(&player, hero.y, hero.x);
+ when C_SEARCH :
+ if (player.t_action == A_NIL) {
+ player.t_action = C_SEARCH;
+ player.t_no_move = 5 * movement(&player);
+ }
+ else {
+ search(FALSE, FALSE);
+ player.t_action = A_NIL;
+ }
+ when C_ZAP : if (!player_zap(NULL, FALSE))
+ after=FALSE;
+ when C_PRAY : pray();
+ when C_CHANT : chant();
+ when C_CAST : cast();
+ when 'a' :
+ if (player.t_action == A_NIL) {
+ if (get_dir(&player.t_newpos)) {
+ player.t_action = 'a';
+ player.t_no_move = 2 * movement(&player);
+ }
+ else
+ after = FALSE;
+ }
+ else {
+ affect();
+ player.t_action = A_NIL;
+ }
+ when 'v' : after = FALSE;
+ msg("Advanced Rogue Version %s.",
+ release);
+ when CTRL('L') : after = FALSE; clearok(curscr, TRUE);
+ touchwin(cw); /* MMMMMMMMMM */
+ when CTRL('R') : after = FALSE; msg(huh);
+ when 'S' :
+ after = FALSE;
+ if (save_game())
+ {
+ wclear(cw);
+ draw(cw);
+ endwin();
+#ifdef PC7300
+ endhardwin();
+#endif
+ exit(0);
+ }
+ when '.' :
+ player.t_no_move = movement(&player); /* Rest */
+ player.t_action = A_NIL;
+ when ' ' : after = FALSE; /* Do Nothing */
+#ifdef WIZARD
+ when CTRL('P') :
+ after = FALSE;
+ if (wizard)
+ {
+ wizard = FALSE;
+ trader = 0;
+ msg("Not wizard any more");
+ }
+ else
+ {
+ if (waswizard || passwd())
+ {
+ msg("Welcome, oh mighty wizard.");
+ wizard = waswizard = TRUE;
+ }
+ else
+ msg("Sorry");
+ }
+#endif
+ when ESCAPE : /* Escape */
+ door_stop = FALSE;
+ count = 0;
+ after = FALSE;
+ when '#':
+ if (levtype == POSTLEV) /* buy something */
+ buy_it();
+ after = FALSE;
+ when '$':
+ if (levtype == POSTLEV) /* price something */
+ price_it();
+ after = FALSE;
+ when '%':
+ if (levtype == POSTLEV) /* sell something */
+ sell_it();
+ after = FALSE;
+ otherwise :
+ after = FALSE;
+#ifdef WIZARD
+ if (wizard) switch (ch)
+ {
+ case 'M' : create_obj(TRUE, 0, 0);
+ when CTRL('W') : wanderer();
+ when CTRL('I') : inventory(lvl_obj, ALL);
+ when CTRL('Z') : whatis(NULL);
+ when CTRL('D') : level++; new_level(NORMLEV);
+ when CTRL('F') : overlay(stdscr,cw);
+ when CTRL('X') : overlay(mw,cw);
+ when CTRL('J') : teleport();
+ when CTRL('E') : msg("food left: %d\tfood level: %d",
+ food_left, foodlev);
+ when CTRL('A') : activity();
+ when CTRL('C') :
+ {
+ int tlev;
+ prbuf[0] = 0;
+ msg("Which level? ");
+ if(get_str(prbuf,msgw) == NORM) {
+ tlev = atoi(prbuf);
+ if(tlev < 1) {
+ mpos = 0;
+ msg("Illegal level.");
+ }
+ else if (tlev > 199) {
+ levtype = MAZELEV;
+ level = tlev - 200 + 1;
+ }
+ else if (tlev > 99) {
+ levtype = POSTLEV;
+ level = tlev - 100 + 1;
+ }
+ else {
+ levtype = NORMLEV;
+ level = tlev;
+ }
+ new_level(levtype);
+ }
+ }
+ when CTRL('G') :
+ {
+ item=get_item(pack,"charge",STICK,FALSE,FALSE);
+ if (item != NULL) {
+ (OBJPTR(item))->o_charges=10000;
+ }
+ }
+ when CTRL('H') :
+ {
+ register int i;
+ register struct object *obj;
+
+ for (i = 0; i < 9; i++)
+ raise_level();
+ /*
+ * Give the rogue a sword
+ */
+ if (cur_weapon==NULL || cur_weapon->o_type !=
+ RELIC) {
+ item = spec_item(WEAPON, TWOSWORD, 5, 5);
+ add_pack(item, TRUE, NULL);
+ cur_weapon = OBJPTR(item);
+ (OBJPTR(item))->o_flags |= (ISKNOW|ISPROT);
+ }
+ /*
+ * And his suit of armor
+ */
+ if (player.t_ctype != C_MONK) {
+ item = spec_item(ARMOR, PLATE_ARMOR, 10, 0);
+ obj = OBJPTR(item);
+ if (player.t_ctype == C_THIEF)
+ obj->o_which = STUDDED_LEATHER;
+ obj->o_flags |= (ISKNOW | ISPROT);
+ obj->o_weight = armors[PLATE_ARMOR].a_wght;
+ cur_armor = obj;
+ add_pack(item, TRUE, NULL);
+ }
+ purse += 20000;
+ }
+ otherwise :
+ msg("Illegal command '%s'.", unctrl(ch));
+ count = 0;
+ }
+ else
+#endif
+ {
+ msg("Illegal command '%s'.", unctrl(ch));
+ count = 0;
+ after = FALSE;
+ }
+ }
+
+ /*
+ * If he ran into something to take, let him pick it up.
+ * unless it's a trading post
+ */
+ if (auto_pickup && take != 0 && levtype != POSTLEV) {
+ /* get ready to pick it up */
+ player.t_action = A_PICKUP;
+ player.t_no_move += 2 * movement(&player);
+ }
+ }
+
+ /* If he was fighting, let's stop (for now) */
+ if (player.t_quiet < 0) player.t_quiet = 0;
+
+ if (!running)
+ door_stop = FALSE;
+
+ if (after && segment >= 10) {
+ /*
+ * Kick off the rest if the daemons and fuses
+ */
+
+ /*
+ * If player is infested, take off a hit point
+ */
+ if (on(player, HASINFEST)) {
+ if ((pstats.s_hpt -= infest_dam) <= 0) death(D_INFESTATION);
+ }
+
+ /*
+ * The eye of Vecna is a constant drain on the player
+ */
+ if (cur_relic[EYE_VECNA]) {
+ if ((--pstats.s_hpt) <= 0) death(D_RELIC);
+ }
+
+ /*
+ * if player has body rot then take off five hits
+ */
+ if (on(player, DOROT)) {
+ if ((pstats.s_hpt -= 5) <= 0) death(D_ROT);
+ }
+ do_daemons(AFTER);
+ do_fuses(AFTER);
+ }
+ } while (after == FALSE);
+
+ /* Make the monsters go */
+ if (--monst_current <= 0)
+ monst_current = monst_limit = runners(monst_limit);
+
+#ifdef NEEDLOOK
+ /* Shall we take a look? */
+ if (player.t_no_move <= 1 &&
+ !((running || count) && jump))
+ look(FALSE, FALSE);
+#endif
+
+ if (++segment > 10) segment = 1;
+ t_free_list(monst_dead);
+ }
+}
+
+/*
+ * display
+ * tell the player what is at a certain coordinates assuming
+ * it can be seen.
+ */
+display()
+{
+ coord c;
+ struct linked_list *item;
+ struct thing *tp;
+ int what;
+
+ msg("What do you want to display (* for help)?");
+ c = get_coordinates();
+ mpos = 0;
+ if (!cansee(c.y, c.x)) {
+ msg("You can't see what is there.");
+ return;
+ }
+ what = mvwinch(cw, c.y, c.x);
+ if (isalpha(what)) {
+ item = find_mons(c.y, c.x);
+ tp = THINGPTR(item);
+ msg("%s", monster_name(tp));
+ return;
+ }
+ if ((item = find_obj(c.y, c.x)) != NULL) {
+ msg("%s", inv_name(OBJPTR(item), FALSE));
+ return;
+ }
+ identify(what);
+}
+
+/*
+ * quit:
+ * Have player make certain, then exit.
+ */
+
+void
+quit(sig)
+int sig;
+{
+ /*
+ * Reset the signal in case we got here via an interrupt
+ */
+ if (signal(SIGINT, quit) != quit)
+ mpos = 0;
+ msg("Really quit? ");
+ draw(cw);
+ prbuf[0] = '\0';
+ if ((get_str(prbuf, msgw) == NORM) && strcmp(prbuf, "yes") == 0) {
+ clear();
+ move(lines-1, 0);
+ draw(stdscr);
+ score(pstats.s_exp + (long) purse, CHICKEN, 0);
+#ifdef PC7300
+ endhardwin();
+#endif
+ exit(0);
+ }
+ else
+ {
+ signal(SIGINT, quit);
+ wmove(cw, 0, 0);
+ wclrtoeol(cw);
+ status(FALSE);
+ draw(cw);
+ mpos = 0;
+ count = 0;
+ running = FALSE;
+ }
+}
+
+/*
+ * bugkill:
+ * killed by a program bug instead of voluntarily.
+ */
+
+void
+bugkill(sig)
+int sig;
+{
+ signal(sig, quit); /* If we get it again, give up */
+ death(D_SIGNAL); /* Killed by a bug */
+}
+
+
+/*
+ * search:
+ * Player gropes about him to find hidden things.
+ */
+
+search(is_thief, door_chime)
+register bool is_thief, door_chime;
+{
+ register int x, y;
+ register char ch, /* The trap or door character */
+ sch, /* Trap or door character (as seen on screen) */
+ mch; /* Monster, if a monster is on the trap or door */
+ register struct linked_list *item;
+ register struct thing *mp; /* Status on surrounding monster */
+
+ /*
+ * Look all around the hero, if there is something hidden there,
+ * give him a chance to find it. If its found, display it.
+ */
+ if (on(player, ISBLIND))
+ return;
+ for (x = hero.x - 1; x <= hero.x + 1; x++)
+ for (y = hero.y - 1; y <= hero.y + 1; y++)
+ {
+ if (y==hero.y && x==hero.x)
+ continue;
+
+ /* Mch and ch will be the same unless there is a monster here */
+ mch = CCHAR( winat(y, x) );
+ ch = CCHAR( mvwinch(stdscr, y, x) );
+ sch = CCHAR( mvwinch(cw, y, x) ); /* What's on the screen */
+
+ if (door_chime == FALSE && isatrap(ch)) {
+ register struct trap *tp;
+
+ /* Is there a monster on the trap? */
+ if (mch != ch && (item = find_mons(y, x)) != NULL) {
+ mp = THINGPTR(item);
+ if (sch == mch) sch = mp->t_oldch;
+ }
+ else mp = NULL;
+
+ /*
+ * is this one found already?
+ */
+ if (isatrap(sch))
+ continue; /* give him chance for other traps */
+ tp = trap_at(y, x);
+ /*
+ * if the thief set it then don't display it.
+ * if its not a thief he has 50/50 shot
+ */
+ if((tp->tr_flags&ISTHIEFSET) || (!is_thief && rnd(100)>50))
+ continue; /* give him chance for other traps */
+ tp->tr_flags |= ISFOUND;
+
+ /* Let's update the screen */
+ if (mp != NULL && mvwinch(cw, y, x) == mch)
+ mp->t_oldch = ch; /* Will change when monst moves */
+ else mvwaddch(cw, y, x, ch);
+
+ count = 0;
+ running = FALSE;
+
+ /* Stop what we were doing */
+ player.t_no_move = movement(&player);
+ player.t_action = A_NIL;
+ player.t_using = NULL;
+
+ if (fight_flush) md_flushinp();
+ msg(tr_name(tp->tr_type));
+ }
+ else if (ch == SECRETDOOR) {
+ if (door_chime == TRUE || (!is_thief && rnd(100) < 20)) {
+ struct room *rp;
+ coord cp;
+
+ /* Is there a monster on the door? */
+ if (mch != ch && (item = find_mons(y, x)) != NULL) {
+ mp = THINGPTR(item);
+
+ /* Screen will change when monster moves */
+ if (sch == mch) mp->t_oldch = ch;
+ }
+ mvaddch(y, x, DOOR);
+ count = 0;
+ /*
+ * if its the entrance to a treasure room, wake it up
+ */
+ cp.y = y;
+ cp.x = x;
+ rp = roomin(&cp);
+ if (rp->r_flags & ISTREAS)
+ wake_room(rp);
+
+ /* Make sure we don't shoot into the room */
+ if (door_chime == FALSE) {
+ count = 0;
+ running = FALSE;
+
+ /* Stop what we were doing */
+ player.t_no_move = movement(&player);
+ player.t_action = A_NIL;
+ player.t_using = NULL;
+ }
+ }
+ }
+ }
+}
+
+
+/*
+ * help:
+ * Give single character help, or the whole mess if he wants it
+ */
+
+help()
+{
+ register struct h_list *strp = helpstr;
+#ifdef WIZARD
+ struct h_list *wizp = wiz_help;
+#endif
+ register char helpch;
+ register int cnt;
+
+ msg("Character you want help for (* for all): ");
+ helpch = readchar();
+ mpos = 0;
+ /*
+ * If its not a *, print the right help string
+ * or an error if he typed a funny character.
+ */
+ if (helpch != '*') {
+ wmove(msgw, 0, 0);
+ while (strp->h_ch) {
+ if (strp->h_ch == helpch) {
+ msg("%s%s", unctrl(strp->h_ch), strp->h_desc);
+ return;
+ }
+ strp++;
+ }
+#ifdef WIZARD
+ if (wizard) {
+ while (wizp->h_ch) {
+ if (wizp->h_ch == helpch) {
+ msg("%s%s", unctrl(wizp->h_ch), wizp->h_desc);
+ return;
+ }
+ wizp++;
+ }
+ }
+#endif
+
+ msg("Unknown character '%s'", unctrl(helpch));
+ return;
+ }
+ /*
+ * Here we print help for everything.
+ * Then wait before we return to command mode
+ */
+ wclear(hw);
+ cnt = 0;
+ while (strp->h_ch) {
+ mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrl(strp->h_ch));
+ waddstr(hw, strp->h_desc);
+ strp++;
+ if (++cnt >= 46 && strp->h_ch) {
+ wmove(hw, lines-1, 0);
+ wprintw(hw, morestr);
+ draw(hw);
+ wait_for(' ');
+ wclear(hw);
+ cnt = 0;
+ }
+ }
+#ifdef WIZARD
+ if (wizard) {
+ while (wizp->h_ch) {
+ mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrl(wizp->h_ch));
+ waddstr(hw, wizp->h_desc);
+ wizp++;
+ if (++cnt >= 46 && wizp->h_ch) {
+ wmove(hw, lines-1, 0);
+ wprintw(hw, morestr);
+ draw(hw);
+ wait_for(' ');
+ wclear(hw);
+ cnt = 0;
+ }
+ }
+ }
+#endif
+ wmove(hw, lines-1, 0);
+ wprintw(hw, spacemsg);
+ draw(hw);
+ wait_for(' ');
+ wclear(hw);
+ draw(hw);
+ wmove(cw, 0, 0);
+ wclrtoeol(cw);
+ status(FALSE);
+ touchwin(cw);
+}
+/*
+ * identify:
+ * Tell the player what a certain thing is.
+ */
+
+identify(ch)
+register char ch;
+{
+ register char *str;
+
+ if (ch == 0) {
+ msg("What do you want identified? ");
+ ch = readchar();
+ mpos = 0;
+ if (ch == ESCAPE)
+ {
+ msg("");
+ return;
+ }
+ }
+ if (isalpha(ch))
+ str = monsters[id_monst(ch)].m_name;
+ else switch(ch)
+ {
+ case '|':
+ case '-':
+ str = (levtype == OUTSIDE) ? "boundary of sector"
+ : "wall of a room";
+ when GOLD: str = "gold";
+ when STAIRS : str = (levtype == OUTSIDE) ? "entrance to a dungeon"
+ : "passage leading down";
+ when DOOR: str = "door";
+ when FLOOR: str = (levtype == OUTSIDE) ? "meadow" : "room floor";
+ when VPLAYER: str = "the hero of the game ---> you";
+ when IPLAYER: str = "you (but invisible)";
+ when PASSAGE: str = "passage";
+ when POST: str = "trading post";
+ when POOL: str = (levtype == OUTSIDE) ? "lake"
+ : "a shimmering pool";
+ when TRAPDOOR: str = "trapdoor";
+ when ARROWTRAP: str = "arrow trap";
+ when SLEEPTRAP: str = "sleeping gas trap";
+ when BEARTRAP: str = "bear trap";
+ when TELTRAP: str = "teleport trap";
+ when DARTTRAP: str = "dart trap";
+ when MAZETRAP: str = "entrance to a maze";
+ when FOREST: str = "forest";
+ when POTION: str = "potion";
+ when SCROLL: str = "scroll";
+ when FOOD: str = "food";
+ when WEAPON: str = "weapon";
+ when ' ' : str = "solid rock";
+ when ARMOR: str = "armor";
+ when MM: str = "miscellaneous magic";
+ when RING: str = "ring";
+ when STICK: str = "wand or staff";
+ when SECRETDOOR:str = "secret door";
+ when RELIC: str = "artifact";
+ otherwise: str = "unknown character";
+ }
+ msg("'%s' : %s", unctrl(ch), str);
+}
+
+/*
+ * d_level:
+ * He wants to go down a level
+ */
+
+d_level()
+{
+ bool no_phase=FALSE;
+ char position = CCHAR( winat(hero.y, hero.x) );
+
+
+ /* If we are on a trading post, go to a trading post level. */
+ if (position == POST) {
+ new_level(POSTLEV);
+ return;
+ }
+
+ /* If we are at a top-level trading post, we probably can't go down */
+ if (levtype == POSTLEV && level == 0 && position != STAIRS) {
+ msg("I see no way down.");
+ return;
+ }
+
+ if (winat(hero.y, hero.x) != STAIRS) {
+ if (off(player, CANINWALL) || /* Must use stairs if can't phase */
+ (levtype == OUTSIDE && rnd(100) < 90)) {
+ msg("I see no way down.");
+ return;
+ }
+
+ /* Is there any dungeon left below? */
+ if (level >= nfloors) {
+ msg("There is only solid rock below.");
+ return;
+ }
+
+ extinguish(unphase); /* Using phase to go down gets rid of it */
+ no_phase = TRUE;
+ }
+
+ /* Is this the bottom? */
+ if (level >= nfloors) {
+ msg("The stairway only goes up.");
+ return;
+ }
+
+ level++;
+ new_level(NORMLEV);
+ if (no_phase) unphase();
+}
+
+/*
+ * u_level:
+ * He wants to go up a level
+ */
+
+u_level()
+{
+ bool no_phase = FALSE;
+ register struct linked_list *item;
+ struct thing *tp;
+ struct object *obj;
+
+ if (winat(hero.y, hero.x) != STAIRS) {
+ if (off(player, CANINWALL)) { /* Must use stairs if can't phase */
+ msg("I see no way up.");
+ return;
+ }
+
+ extinguish(unphase);
+ no_phase = TRUE;
+ }
+
+ if (level == 0) {
+ msg("The stairway only goes down.");
+ return;
+ }
+
+ /*
+ * does he have the item he was quested to get?
+ */
+ if (level == 1) {
+ for (item = pack; item != NULL; item = next(item)) {
+ obj = OBJPTR(item);
+ if (obj->o_type == RELIC && obj->o_which == quest_item)
+ total_winner();
+ }
+ }
+ /*
+ * check to see if he trapped a UNIQUE, If he did then put it back
+ * in the monster table for next time
+ */
+ for (item = tlist; item != NULL; item = next(item)) {
+ tp = THINGPTR(item);
+ if (on(*tp, ISUNIQUE))
+ monsters[tp->t_index].m_normal = TRUE;
+ }
+ t_free_list(tlist); /* Monsters that fell below are long gone! */
+
+ if (levtype != POSTLEV) level--;
+ if (level > 0) new_level(NORMLEV);
+ else {
+ level = -1; /* Indicate that we are new to the outside */
+ msg("You emerge into the %s", daytime ? "light" : "night");
+ new_level(OUTSIDE); /* Leaving the dungeon */
+ }
+
+ if (no_phase) unphase();
+}
+
+/*
+ * Let him escape for a while
+ */
+
+shell()
+{
+ register char *sh;
+
+ /*
+ * Set the terminal back to original mode
+ */
+ sh = getenv("SHELL");
+ wclear(hw);
+ wmove(hw, lines-1, 0);
+ draw(hw);
+ endwin();
+ in_shell = TRUE;
+ fflush(stdout);
+ /*
+ * Fork and do a shell
+ */
+
+ md_shellescape();
+
+ printf(retstr);
+ noecho();
+ raw();
+ keypad(cw,1);
+ keypad(msgw,1);
+ in_shell = FALSE;
+ wait_for('\n');
+ clearok(cw, TRUE);
+ touchwin(cw);
+}
+
+/*
+ * see what we want to name -- an item or a monster.
+ */
+nameit()
+{
+ char answer;
+
+ msg("Name monster or item (m or i)? ");
+ answer = readchar();
+ mpos = 0;
+
+ while (answer != 'm' && answer != 'i' && answer != ESCAPE) {
+ mpos = 0;
+ msg("Please specify m or i, for monster or item - ");
+ answer = readchar();
+ }
+
+ switch (answer) {
+ case 'm': namemonst();
+ when 'i': nameitem(NULL, FALSE);
+ }
+}
+
+/*
+ * allow a user to call a potion, scroll, or ring something
+ */
+nameitem(item, mark)
+struct linked_list *item;
+bool mark;
+{
+ register struct object *obj;
+ register char **guess, *elsewise;
+ register bool *know;
+
+ if (item == NULL) {
+ if (mark) item = get_item(pack, "mark", ALL, FALSE, FALSE);
+ else item = get_item(pack, "name", CALLABLE, FALSE, FALSE);
+ if (item == NULL) return;
+ }
+ /*
+ * Make certain that it is somethings that we want to wear
+ */
+ obj = OBJPTR(item);
+ switch (obj->o_type)
+ {
+ case RING:
+ guess = r_guess;
+ know = r_know;
+ elsewise = (r_guess[obj->o_which] != NULL ?
+ r_guess[obj->o_which] : r_stones[obj->o_which]);
+ when POTION:
+ guess = p_guess;
+ know = p_know;
+ elsewise = (p_guess[obj->o_which] != NULL ?
+ p_guess[obj->o_which] : p_colors[obj->o_which]);
+ when SCROLL:
+ guess = s_guess;
+ know = s_know;
+ elsewise = (s_guess[obj->o_which] != NULL ?
+ s_guess[obj->o_which] : s_names[obj->o_which]);
+ when STICK:
+ guess = ws_guess;
+ know = ws_know;
+ elsewise = (ws_guess[obj->o_which] != NULL ?
+ ws_guess[obj->o_which] : ws_made[obj->o_which]);
+ when MM:
+ guess = m_guess;
+ know = m_know;
+ elsewise = (m_guess[obj->o_which] != NULL ?
+ m_guess[obj->o_which] : "nothing");
+ otherwise:
+ if (!mark) {
+ msg("You can't call that anything.");
+ return;
+ }
+ else know = (bool *) 0;
+ }
+ if ((obj->o_flags & ISPOST) || (know && know[obj->o_which]) && !mark) {
+ msg("That has already been identified.");
+ return;
+ }
+ if (mark) {
+ if (obj->o_mark[0]) {
+ addmsg(terse ? "M" : "Was m");
+ msg("arked \"%s\"", obj->o_mark);
+ }
+ msg(terse ? "Mark it: " : "What do you want to mark it? ");
+ prbuf[0] = '\0';
+ }
+ else {
+ if (elsewise) {
+ addmsg(terse ? "N" : "Was n");
+ msg("amed \"%s\"", elsewise);
+ strcpy(prbuf, elsewise);
+ }
+ else prbuf[0] = '\0';
+ msg(terse ? "Name it: " : "What do you want to name it? ");
+ }
+ if (get_str(prbuf, msgw) == NORM) {
+ if (mark) {
+ strncpy(obj->o_mark, prbuf, MARKLEN-1);
+ obj->o_mark[MARKLEN-1] = '\0';
+ }
+ else if (prbuf[0] != '\0') {
+ if (guess[obj->o_which] != NULL)
+ free(guess[obj->o_which]);
+ guess[obj->o_which] = new((unsigned int) strlen(prbuf) + 1);
+ strcpy(guess[obj->o_which], prbuf);
+ }
+ }
+}
+
+/* Name a monster */
+
+namemonst()
+{
+ register struct thing *tp;
+ struct linked_list *item;
+ coord c;
+
+ /* Find the monster */
+ msg("Choose the monster (* for help)");
+ c = get_coordinates();
+
+ /* Make sure we can see it and that it is a monster. */
+ mpos = 0;
+ if (!cansee(c.y, c.x)) {
+ msg("You can't see what is there.");
+ return;
+ }
+
+ if (isalpha(mvwinch(cw, c.y, c.x))) {
+ item = find_mons(c.y, c.x);
+ if (item != NULL) {
+ tp = THINGPTR(item);
+ if (tp->t_name == NULL)
+ strcpy(prbuf, monsters[tp->t_index].m_name);
+ else
+ strcpy(prbuf, tp->t_name);
+
+ addmsg(terse ? "N" : "Was n");
+ msg("amed \"%s\"", prbuf);
+ msg(terse ? "Name it: " : "What do you want to name it? ");
+
+ if (get_str(prbuf, msgw) == NORM) {
+ if (prbuf[0] != '\0') {
+ if (tp->t_name != NULL)
+ free(tp->t_name);
+ tp->t_name = new((unsigned int) strlen(prbuf) + 1);
+ strcpy(tp->t_name, prbuf);
+ }
+ }
+ return;
+ }
+ }
+
+ msg("There is no monster there to name.");
+}
+
+count_gold()
+{
+ if (player.t_action != C_COUNT) {
+ msg("You take a break to count your money...");
+ player.t_using = NULL;
+ player.t_action = C_COUNT; /* We are counting */
+ player.t_no_move = (purse/300 + 1) * movement(&player);
+ return;
+ }
+ if (purse > 100)
+ msg("You think you have about %d gold pieces.", purse);
+ else
+ msg("You have %d gold pieces.", purse);
+ player.t_action = A_NIL;
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/daemon.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/daemon.c Fri May 08 15:24:40 2015 -0400
@@ -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));
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/daemons.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/daemons.c Fri May 08 15:24:40 2015 -0400
@@ -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= 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)
+ {
+ 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);
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/eat.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/eat.c Fri May 08 15:24:40 2015 -0400
@@ -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;
+ }
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/effects.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/effects.c Fri May 08 15:24:40 2015 -0400
@@ -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);
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/encumb.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/encumb.c Fri May 08 15:24:40 2015 -0400
@@ -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; io_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);
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/fight.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/fight.c Fri May 08 15:24:40 2015 -0400
@@ -0,0 +1,1495 @@
+/*
+ * fight.c - All the fighting gets done 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 fighting gets done here
+ *
+ */
+
+#include "curses.h"
+#include
+#include "rogue.h"
+
+int hit(struct object *weapon, bool see_att, bool see_def, char *er, char *ee, bool back_stab, bool thrown, bool short_msg);
+#define CONF_DAMAGE -1
+#define PARAL_DAMAGE -2
+#define DEST_DAMAGE -3
+#define DRAIN_DAMAGE -4
+
+/*
+ * returns true if player has a any chance to hit the monster
+ */
+player_can_hit(tp, weap)
+register struct thing *tp;
+register struct object *weap;
+{
+ if (off(*tp, CMAGICHIT) && off(*tp, BMAGICHIT) && off(*tp, MAGICHIT))
+ return(TRUE);
+ if (weap && weap->o_type == RELIC)
+ return(TRUE);
+ if (on(*tp, CMAGICHIT) && weap && (weap->o_hplus>2 || weap->o_dplus>2))
+ return(TRUE);
+ if (on(*tp, BMAGICHIT) && weap && (weap->o_hplus>1 || weap->o_dplus>1))
+ return(TRUE);
+ if (on(*tp, MAGICHIT) && weap && (weap->o_hplus>0 || weap->o_dplus>0))
+ return(TRUE);
+ if (player.t_ctype == C_MONK) {
+ if (on(*tp, CMAGICHIT) && pstats.s_lvl > 15)
+ return(TRUE);
+ if (on(*tp, BMAGICHIT) && pstats.s_lvl > 10)
+ return(TRUE);
+ if (on(*tp, MAGICHIT) && pstats.s_lvl > 5)
+ return(TRUE);
+ }
+ return(FALSE);
+}
+
+/*
+ * fight:
+ * The player attacks the monster.
+ */
+
+fight(mp, weap, thrown)
+register coord *mp;
+struct object *weap;
+bool thrown;
+{
+ register struct thing *tp;
+ register struct linked_list *item;
+ register bool did_hit = TRUE;
+ bool see_def, back_stab = FALSE;
+ register char *mname;
+
+ /*
+ * Find the monster we want to fight
+ */
+ if ((item = find_mons(mp->y, mp->x)) == NULL) {
+ return(FALSE); /* must have killed him already */
+ }
+ tp = THINGPTR(item);
+
+ /*
+ * Since we are fighting, things are not quiet so no healing takes
+ * place. The -1 also tells us that we are in a fight.
+ */
+ player.t_quiet = -1;
+ tp->t_quiet = -1;
+
+ see_def = ((off(*tp, ISINVIS) || on(player, CANSEE)) &&
+ (off(*tp, ISSHADOW) || on(player, CANSEE)) &&
+ (!thrown || cansee(unc(tp->t_pos))));
+
+ mname = see_def ? monster_name(tp) : "something";
+
+ /*
+ * if its in the wall, we can't hit it
+ */
+ if (on(*tp, ISINWALL) && off(player, CANINWALL))
+ return(FALSE);
+
+ if (on(*tp, ISSTONE)) {
+ killed(item, FALSE, FALSE, FALSE);
+ if (see_def)
+ msg("%s shatters into a million pieces!", prname(mname, TRUE));
+ count = 0;
+ return (TRUE);
+ }
+ /*
+ * Let him know it was really a mimic (if it was one).
+ */
+ if (on(*tp, ISDISGUISE) && (tp->t_type != tp->t_disguise) &&
+ off(player, ISBLIND))
+ {
+ if (see_def) {
+ msg("Wait! That's a %s!", mname);
+ turn_off(*tp, ISDISGUISE);
+ }
+ did_hit = thrown;
+ }
+ if (on(*tp, CANSURPRISE) && off(player, ISBLIND) && !ISWEARING(R_ALERT)) {
+ if (see_def) {
+ msg("Wait! There's a %s!", mname);
+ turn_off(*tp, CANSURPRISE);
+ }
+ did_hit = thrown;
+ }
+
+ /*
+ * if he's a thief or assassin and the creature is asleep then he gets
+ * a chance for a backstab
+ */
+ if ((player.t_ctype == C_THIEF || player.t_ctype == C_ASSASIN) &&
+ !thrown &&
+ !on(*tp, NOSTAB) &&
+ !invisible(tp) &&
+ (!on(*tp, ISRUN) || on(*tp, ISHELD) || tp->t_action == A_FREEZE))
+ back_stab = TRUE;
+
+ /*
+ * assassins get an assassination chance, if it fails then its normal
+ * damage
+ */
+ if (back_stab && player.t_ctype == C_ASSASIN) {
+ int chance;
+
+ chance = 50 + (pstats.s_lvl - tp->t_stats.s_lvl) * 5;
+ if (cur_weapon && (cur_weapon->o_flags & ISPOISON))
+ chance += 20;
+ if (roll(1,100) > chance || on(*tp, ISUNIQUE))
+ back_stab = FALSE;
+ }
+
+ runto(tp, &hero);
+
+ /* Let the monster know that the player has missiles! */
+ if (thrown) tp->t_wasshot = TRUE;
+
+ if (did_hit)
+ {
+
+ did_hit = FALSE;
+ if (!can_blink(tp) &&
+ player_can_hit(tp, weap) &&
+ roll_em(&player, tp, weap, thrown, cur_weapon, back_stab))
+ {
+ did_hit = TRUE;
+
+ if (on(*tp, NOMETAL) && weap != NULL &&
+ weap->o_type != RELIC && weap->o_flags & ISMETAL) {
+ msg("Your %s passes right through %s!",
+ weaps[weap->o_which].w_name, prname(mname, FALSE));
+ }
+ else if (weap != NULL && weap->o_type == MISSILE && on(*tp, CARRYBAMULET)) {
+ msg("The magic missile has no affect on %s",
+ prname(mname, FALSE));
+ }
+ else {
+ hit(thrown ? NULL : weap,
+ TRUE, see_def,
+ thrown ? weap_name(weap) : NULL,
+ mname, back_stab, thrown, terse);
+
+ /* See if there are any special effects */
+ if (effect(&player, tp, weap, thrown, TRUE, see_def) != 0)
+ killed(item, FALSE, FALSE, TRUE);
+
+ /*
+ * Merchants just disappear if hit
+ */
+ else if (on(*tp, CANSELL)) {
+ if (see_def)
+ msg("%s disappears with his wares in a flash.",
+ prname(mname, FALSE));
+ killed(item, FALSE, FALSE, FALSE);
+ }
+
+ else if (tp->t_stats.s_hpt <= 0)
+ killed(item, TRUE, TRUE, TRUE);
+
+ else {
+ /* If the victim was charmed, it now gets a saving throw! */
+ if (on(*tp, ISCHARMED) && save(VS_MAGIC, tp, 0)) {
+ msg("The eyes of %s turn clear.", prname(mname, FALSE));
+ turn_off(*tp, ISCHARMED);
+ }
+
+ dsrpt_monster(tp, FALSE, see_def); /* Disrupt a spell? */
+ }
+ }
+ }
+ else {
+ miss(thrown ? NULL : weap,
+ TRUE, see_def,
+ thrown ? weap_name(weap) : NULL,
+ mname, thrown, terse);
+ }
+ }
+ count = 0;
+ return did_hit;
+}
+
+/*
+ * attack:
+ * The monster attacks the player
+ */
+
+attack(mp, weapon, thrown)
+register struct thing *mp;
+register struct object *weapon;
+bool thrown;
+{
+ register char *mname;
+ register bool see_att, did_hit = FALSE;
+ register struct object *wielded; /* The wielded weapon */
+ struct linked_list *get_wield; /* Linked list header for wielded */
+
+ /*
+ * Since this is an attack, stop running and any healing that was
+ * going on at the time. The -1 also tells us that we're fighting.
+ */
+ running = FALSE;
+ player.t_quiet = -1;
+ mp->t_quiet = -1;
+
+ if (on(*mp, ISDISGUISE) && off(player, ISBLIND))
+ turn_off(*mp, ISDISGUISE);
+
+ see_att = ((off(*mp, ISINVIS) || on(player, CANSEE)) &&
+ (off(*mp, ISSHADOW) || on(player, CANSEE)) &&
+ (!thrown || cansee(unc(mp->t_pos))));
+
+ mname = see_att ? monster_name(mp) : "something";
+
+ /*
+ * 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, it will try to find a suitable weapon.
+ */
+ get_wield = wield_weap(weapon, mp);
+ if (get_wield) wielded = OBJPTR(get_wield);
+ else wielded = NULL;
+
+ /* If we aren't wielding a weapon, wield what we found (could be NULL) */
+ if (weapon == NULL) weapon = wielded;
+
+ if (roll_em(mp, &player, weapon, thrown, wielded, FALSE)) {
+ int death_type; /* From one of the effects of getting hit */
+
+ did_hit = TRUE;
+
+ if (weapon != NULL && weapon->o_type == MISSILE && cur_relic[STONEBONES_AMULET]) {
+ hit(weapon, see_att, TRUE, mname, NULL, FALSE, thrown, terse);
+ msg("Your amulet seems to absorb the magic missile");
+ }
+ else {
+ hit(weapon, see_att, TRUE, mname, NULL, FALSE, thrown, terse);
+ dsrpt_player(); /* see if we disrupted some activity */
+ if (pstats.s_hpt <= 0)
+ death(mp->t_index); /* Bye bye life ... */
+ death_type = effect(mp, &player, weapon, thrown, see_att, TRUE);
+ if (death_type != 0) death(death_type);
+ }
+
+ }
+ else {
+ /* If the thing was trying to surprise, no good */
+ if (on(*mp, CANSURPRISE)) turn_off(*mp, CANSURPRISE);
+
+ /* If it couldn't surprise, let's tell the player. */
+ else miss(weapon, see_att, TRUE, mname, NULL, thrown, terse);
+ }
+ if (fight_flush) md_flushinp();
+ count = 0;
+ status(FALSE);
+ return(did_hit);
+}
+
+/*
+ * swing:
+ * returns true if the swing hits
+ */
+
+swing(class, at_lvl, op_arm, wplus)
+short class;
+int at_lvl, op_arm, wplus;
+{
+ register int res = rnd(20)+1;
+ register int need;
+
+ need = char_class[class].base -
+ char_class[class].factor *
+ ((min(at_lvl, char_class[class].max_lvl) -
+ char_class[class].offset)/char_class[class].range) +
+ (10 - op_arm);
+ if (need > 20 && need <= 25) need = 20;
+
+ return (res+wplus >= need);
+}
+
+/*
+ * roll_em:
+ * Roll several attacks
+ */
+
+roll_em(att_er, def_er, weap, hurl, cur_weapon, back_stab)
+struct thing *att_er, *def_er;
+struct object *weap;
+bool hurl;
+struct object *cur_weapon;
+bool back_stab;
+{
+ register struct stats *att, *def;
+ register char *cp;
+ register int ndice, nsides, nplus, def_arm;
+ bool did_hit = FALSE;
+ int prop_hplus, prop_dplus;
+ int vampiric_damage;
+ char *strchr();
+
+ /* Get statistics */
+ att = &att_er->t_stats;
+ def = &def_er->t_stats;
+
+ prop_hplus = prop_dplus = 0;
+ if (weap == NULL) {
+ static char dmgbuf[20];
+
+ /*
+ * monks damage grows with level
+ */
+ if (att == &pstats && player.t_ctype == C_MONK) {
+ sprintf(dmgbuf, "%dd4", att->s_lvl/3+1);
+ cp = dmgbuf;
+ }
+ else
+ cp = att->s_dmg;
+ }
+ else if (weap->o_type == RELIC) {
+ switch (weap->o_which) {
+ case MUSTY_DAGGER: cp = "1d4+1/1d4+1";
+ when YEENOGHU_FLAIL: cp = "3d6/paralyze/confuse";
+ when HRUGGEK_MSTAR: cp = "3d10";
+ when MING_STAFF: cp = "1d8";
+ when ASMO_ROD: cp = "2d8+1";
+ when ORCUS_WAND: cp = "destroy";
+ when AXE_AKLAD: if (hurl) cp = "1d6/drain";
+ else cp = "3d6/drain";
+ }
+ }
+ else if (hurl) {
+ if ((weap->o_flags&ISMISL) && cur_weapon != NULL &&
+ cur_weapon->o_which == weap->o_launch)
+ {
+ cp = weap->o_hurldmg;
+ prop_hplus = cur_weapon->o_hplus;
+ prop_dplus = cur_weapon->o_dplus;
+ }
+ else
+ cp = (weap->o_flags&ISMISL ? weap->o_damage : weap->o_hurldmg);
+ }
+ else {
+ cp = weap->o_damage;
+ /*
+ * Drain a staff of striking
+ */
+ if(weap->o_type==STICK && weap->o_which==WS_HIT && weap->o_charges==0)
+ {
+ strncpy(weap->o_damage, "1d6", sizeof(weap->o_damage));
+ weap->o_hplus = weap->o_dplus = 0;
+ }
+ }
+ /*
+ * If defender is wearing a cloak of displacement -- no damage
+ * the first time. (unless its a hurled magic missile or the
+ * attacker is very smart and can see thru the illusion)
+ */
+ if ((weap == NULL || weap->o_type != MISSILE) &&
+ def == &pstats &&
+ off(*att_er, MISSEDDISP) &&
+ att->s_intel < 22 &&
+ ((cur_misc[WEAR_CLOAK]!=NULL &&
+ cur_misc[WEAR_CLOAK]->o_which==MM_DISP) ||
+ cur_relic[EMORI_CLOAK])) {
+ turn_on(*att_er, MISSEDDISP);
+ if (cansee(att_er->t_pos.y, att_er->t_pos.x) && !invisible(att_er))
+ msg("%s looks amazed", prname(monster_name(att_er), TRUE));
+ return (FALSE);
+ }
+ if (on(*def_er, CARRYCLOAK) && def != &pstats &&
+ (weap == NULL || weap->o_type != MISSILE) && off(*att_er, MISSEDDISP) &&
+ pstats.s_intel < 22) {
+ turn_on(*att_er, MISSEDDISP);
+ msg("You feel amazed");
+ return(FALSE);
+ }
+ for (;;)
+ {
+ int damage;
+ int hplus = prop_hplus;
+ int dplus = prop_dplus;
+
+ if (weap != NULL && weap->o_type == RELIC) {
+ switch (weap->o_which) {
+ case MUSTY_DAGGER:
+ if (att != &pstats || /* Not player or good stats */
+ (str_compute() > 15 && dex_compute() > 15)) {
+
+ hplus += 6;
+ dplus += 6;
+
+ /* Give an additional strength and dex bonus */
+ if (att == &pstats) {
+ hplus += str_plus(str_compute()) +
+ dext_plus(dex_compute());
+ dplus += dext_plus(dex_compute()) +
+ add_dam(str_compute());
+ }
+ else {
+ hplus += str_plus(att->s_str) +
+ dext_plus(att->s_dext);
+ dplus += dext_plus(att->s_dext) +
+ add_dam(att->s_str);
+ }
+ }
+ else {
+ hplus -= 3;
+ dplus -= 3;
+ }
+ when YEENOGHU_FLAIL:
+ case HRUGGEK_MSTAR:
+ hplus += 3;
+ dplus += 3;
+ when MING_STAFF:
+ hplus += 2;
+ dplus += 2;
+ when AXE_AKLAD:
+ hplus += 5;
+ dplus += 5;
+ }
+ }
+ else if (weap != NULL) {
+ hplus += weap->o_hplus;
+ dplus += weap->o_dplus;
+ }
+
+ /* Is attacker weak? */
+ if (on(*att_er, HASSTINK)) hplus -= 2;
+
+ if (att == &pstats) /* Is the attacker the player? */
+ {
+ hplus += hitweight(); /* adjust for encumberence */
+ dplus += hung_dam(); /* adjust damage for hungry player */
+ dplus += ring_value(R_ADDDAM);
+ }
+ if (back_stab || (weap && att != &pstats && on(*att_er, CANBSTAB)))
+ hplus += 4; /* add in pluses for backstabbing */
+
+ /* Get the damage */
+ while (isspace(*cp)) cp++;
+ if (!isdigit(*cp)) {
+ if (strncmp(cp, "confuse", 7) == 0) ndice = CONF_DAMAGE;
+ else if (strncmp(cp, "paralyze", 8) == 0) ndice = PARAL_DAMAGE;
+ else if (strncmp(cp, "destroy", 7) == 0) ndice = DEST_DAMAGE;
+ else if (strncmp(cp, "drain", 5) == 0) ndice = DRAIN_DAMAGE;
+ else ndice = 0;
+ nsides = 0;
+ nplus = 0;
+ }
+ else {
+ char *oldcp;
+
+ /* Get the number of damage dice */
+ ndice = atoi(cp);
+ if ((cp = strchr(cp, 'd')) == NULL)
+ break;
+
+ /* Skip the 'd' and get the number of sides per die */
+ nsides = atoi(++cp);
+
+ /* Check for an addition -- save old place in case none is found */
+ oldcp = cp;
+ if ((cp = strchr(cp, '+')) != NULL) nplus = atoi(++cp);
+ else {
+ nplus = 0;
+ cp = oldcp;
+ }
+ }
+
+ if (def == &pstats) { /* Monster attacks player */
+ if (on(*att_er, NOMETAL))
+ def_arm = ac_compute(TRUE) - dext_prot(dex_compute());
+ else
+ def_arm = ac_compute(FALSE) - dext_prot(dex_compute());
+ hplus += str_plus(att->s_str)+dext_plus(att->s_dext);
+ }
+ else if (att == &pstats) { /* Player attacks monster */
+ def_arm = def->s_arm - dext_prot(def->s_dext);
+ if (player.t_ctype == C_MONK) /* no strength bonus for monk */
+ if (weap == NULL)
+ hplus += att->s_lvl/5; /* monks hplus varies with level */
+ else
+ hplus += str_plus(str_compute())+dext_plus(dex_compute());
+ }
+ else { /* Monster attacks monster */
+ def_arm = def->s_arm - dext_prot(def->s_dext);
+ hplus += str_plus(att->s_str)+dext_plus(att->s_dext);
+ }
+
+ if (swing(att_er->t_ctype, att->s_lvl, def_arm, hplus)) {
+ register int proll;
+
+ /* Take care of special effects */
+ switch (ndice) {
+ case CONF_DAMAGE:
+ if (def == &pstats) { /* Monster attacks player */
+ if (!save(VS_MAGIC, &player, 0) && off(player, ISCLEAR)) {
+ msg("You feel disoriented.");
+ if (find_slot(unconfuse))
+ lengthen(unconfuse, HUHDURATION);
+ else
+ fuse(unconfuse, 0, HUHDURATION, AFTER);
+ turn_on(player, ISHUH);
+ }
+ else msg("You feel dizzy, but it quickly passes.");
+ }
+ /* Player or monster hits monster */
+ else if (!save(VS_MAGIC, def_er, 0) && off(*def_er, ISCLEAR)) {
+ if (att == &pstats)
+ msg("The artifact warms with pleasure.");
+ turn_on(*def_er, ISHUH);
+ }
+ did_hit = TRUE;
+ when PARAL_DAMAGE:
+ if (def == &pstats) { /* Monster attacks player */
+ if (!save(VS_MAGIC, &player, 0) && off(player, CANINWALL)) {
+ msg("You stiffen up.");
+ player.t_no_move += movement(&player) * FREEZETIME;
+ player.t_action = A_FREEZE;
+ }
+ }
+ else if (!save(VS_MAGIC, def_er, 0)) { /* Player hits monster */
+ if (att == &pstats) msg("The artifact hums happily.");
+ turn_off(*def_er, ISRUN);
+ turn_on(*def_er, ISHELD);
+ }
+ did_hit = TRUE;
+ when DEST_DAMAGE:
+ if (def == &pstats) { /* Monster attacks player */
+ msg("You feel a tug at your life force.");
+ if (!save(VS_MAGIC, &player, -4)) {
+ msg("The wand devours your soul.");
+ def->s_hpt = 0;
+ }
+ }
+ /* Player hits monster */
+ else if (!save(VS_MAGIC, def_er, -4)) {
+ if (att == &pstats)
+ msg("The artifact draws energy.");
+
+ /* Give the attacker half the monster's hits */
+ att->s_hpt += def->s_hpt/2;
+ if (att->s_hpt > att_er->maxstats.s_hpt)
+ att->s_hpt = att_er->maxstats.s_hpt;
+
+ /* Kill the monster */
+ def->s_hpt = 0;
+ }
+ did_hit = TRUE;
+ when DRAIN_DAMAGE:
+ if (def == &pstats) { /* Monster attacks player */
+ if (!save(VS_MAGIC, &player, -4)) {
+ lower_level(att_er->t_index);
+ }
+ }
+ /* Player hits monster */
+ else if (!save(VS_MAGIC, def_er, -4)) {
+ def->s_hpt -= roll(1, 8);
+ def->s_lvl--;
+ if (def->s_lvl <= 0)
+ def->s_hpt = 0; /* he's dead */
+ if (att == &pstats)
+ msg("The artifact cackles with laughter");
+ }
+ did_hit = TRUE;
+ otherwise:
+ /* Heil's ankh always gives maximum damage */
+ if (att == &pstats && cur_relic[HEIL_ANKH])
+ proll = ndice * nsides;
+ else proll = roll(ndice, nsides);
+
+ if (ndice + nsides > 0 && proll < 1)
+ debug("Damage for %dd%d came out %d.",
+ ndice, nsides, proll);
+ damage = dplus + proll + nplus;
+ if (att == &pstats) {
+ /*
+ * Monks do not get strength bonus on damage. Instead,
+ * if they are wielding a weapon, they get at extra
+ * 1/2 point per level of damage.
+ */
+ if(player.t_ctype == C_MONK) {
+ /* Bonus does not apply for hands. */
+ if (weap != NULL) damage += att->s_lvl / 2;
+ }
+ else
+ damage += add_dam(str_compute());
+ }
+ else
+ damage += add_dam(att->s_str);
+
+ /* Check for half damage monsters */
+ if (on(*def_er, HALFDAMAGE)) damage /= 2;
+
+ /* add in multipliers for backstabbing */
+ if (back_stab ||
+ (weap && att != &pstats && on(*att_er, CANBSTAB))) {
+ int mult = 2 + (att->s_lvl-1)/4; /* Normal multiplier */
+
+ if (mult > 5)
+ mult = 5;
+ if (weap->o_type == RELIC && weap->o_which == MUSTY_DAGGER)
+ mult++;
+ damage *= mult;
+ }
+ if (att == &pstats) {
+ if (cur_weapon && (cur_weapon->o_flags & ISPOISON)) {
+ cur_weapon->o_flags &= ~ISPOISON;
+ if (save(VS_POISON, def_er, -2))
+ damage += def->s_hpt/4;
+ else
+ damage += def->s_hpt/2;
+ }
+ if (back_stab && player.t_ctype == C_ASSASIN)
+ damage = def->s_hpt + 1;
+ }
+ /* Check for no-damage and division */
+ if (on(*def_er, BLOWDIVIDE)) {
+ damage = 0;
+ creat_mons(def_er, def_er->t_index, FALSE);
+ if (cansee(unc(def_er->t_pos))) light(&hero);
+ }
+ /* check for immunity to metal -- RELICS are always bad */
+ if (on(*def_er, NOMETAL) && weap != NULL &&
+ weap->o_type != RELIC && weap->o_flags & ISMETAL) {
+ damage = 0;
+ }
+ if (weap != NULL && weap->o_type == MISSILE) {
+ if ((def == &pstats && cur_relic[STONEBONES_AMULET]) ||
+ (att == &pstats && on(*def_er, CARRYBAMULET))) {
+ damage = 0;
+ }
+ }
+
+
+ def->s_hpt -= max(0, damage); /* Do the damage */
+ did_hit = TRUE;
+ vampiric_damage = damage;
+ if (def->s_hpt < 0) /* only want REAL damage inflicted */
+ vampiric_damage += def->s_hpt;
+ if (vampiric_damage < 0)
+ vampiric_damage = 0;
+ if (att == &pstats && ISWEARING(R_VAMPREGEN) && !hurl) {
+ if ((pstats.s_hpt += vampiric_damage/2) > max_stats.s_hpt)
+ pstats.s_hpt = max_stats.s_hpt;
+ }
+ debug ("hplus=%d dmg=%d", hplus, damage);
+ }
+ }
+ if ((cp = strchr(cp, '/')) == NULL)
+ break;
+ cp++;
+ }
+ return did_hit;
+}
+
+/*
+ * prname:
+ * The print name of a combatant
+ */
+
+char *
+prname(who, upper)
+register char *who;
+bool upper;
+{
+ static char tbuf[LINELEN];
+
+ *tbuf = '\0';
+ if (who == 0)
+ strcpy(tbuf, "you");
+ else if (on(player, ISBLIND) || strcmp(who, "something") == 0)
+ strcpy(tbuf, "something");
+ else
+ {
+ /* If we have a name (starts with a capital), don't use a "the" */
+ if (islower(*who)) strcpy(tbuf, "the ");
+ strcat(tbuf, who);
+ }
+ if (upper)
+ *tbuf = toupper(*tbuf);
+ return tbuf;
+}
+
+/*
+ * hit:
+ * Print a message to indicate a succesful hit
+ */
+
+hit(weapon, see_att, see_def, er, ee, back_stab, thrown, short_msg)
+register struct object *weapon;
+bool see_att, see_def;
+register char *er, *ee;
+bool back_stab, thrown, short_msg;
+{
+ register char *s;
+ char att_name[LINELEN], /* Name of attacker */
+ def_name[LINELEN]; /* Name of defender */
+
+ /* If we can't see either the attacker or defender, don't say anything */
+ if (!see_att && !see_def) return;
+
+ /* What do we call the attacker? */
+ strcpy(att_name, see_att ? prname(er, TRUE) : "Something");
+ if (er) { /* A monster is attacking */
+
+ /* If the monster is using a weapon and we can see it, report it */
+ if (weapon != NULL && (see_att || thrown)) {
+ strcat(att_name, "'s ");
+ strcat(att_name, weap_name(weapon));
+ }
+ }
+
+ /* What do we call the defender? */
+ strcpy(def_name, see_def ? prname(ee, FALSE) : "something");
+
+ addmsg(att_name);
+ if (short_msg) {
+ if (back_stab) {
+ if (player.t_ctype == C_ASSASIN)
+ s = (er == 0 ? " assassinate!" : " assassinates!");
+ else
+ s = (er == 0 ? " backstab!" : " backstabs!");
+ }
+ else
+ s = " hit.";
+ }
+ else {
+ if (back_stab) {
+ if (player.t_ctype == C_ASSASIN)
+ s = (er == 0 ? " have assassinated " : " has assassinated ");
+ else
+ s = (er == 0 ? " have backstabbed " : " has backstabbed ");
+ }
+ else {
+ switch (rnd(thrown ? 2 : 3))
+ {
+ case 0: s = " hit ";
+ when 1: s = " injured ";
+ when 2: s = " smacked ";
+ }
+ }
+ }
+ if (short_msg) addmsg(s);
+ else addmsg("%s%s.", s, def_name);
+ endmsg();
+}
+
+/*
+ * miss:
+ * Print a message to indicate a poor swing
+ */
+
+miss(weapon, see_att, see_def, er, ee, thrown, short_msg)
+register struct object *weapon;
+bool see_att, see_def;
+register char *er, *ee;
+bool thrown, short_msg;
+{
+ register char *s;
+ char
+ att_name[LINELEN], /* Name of attacker */
+ def_name[LINELEN]; /* Name of defender */
+
+ /* If we can't see either the attacker or defender, don't say anything */
+ if (!see_att && !see_def) return;
+
+ /* What do we call the attacker? */
+ strcpy(att_name, see_att ? prname(er, TRUE) : "Something");
+ if (er) { /* A monster is attacking */
+
+ /* If the monster is using a weapon and we can see it, report it */
+ if (weapon != NULL && (see_att || thrown)) {
+ strcat(att_name, "'s ");
+ strcat(att_name, weap_name(weapon));
+ }
+ }
+
+ /* What do we call the defender? */
+ strcpy(def_name, see_def ? prname(ee, FALSE) : "something");
+
+ addmsg(att_name);
+ switch (short_msg ? 0 : rnd(thrown ? 3 : 2))
+ {
+ case 0: s = (er == 0 ? " miss" : " misses");
+ when 1: s = (er == 0 ? " don't hit" : " doesn't hit");
+ when 2: s = (" whizzes by");
+ }
+ if (short_msg) addmsg("%s.", s);
+ else addmsg("%s %s.", s, def_name);
+ endmsg();
+}
+
+/*
+ * dext_plus:
+ * compute to-hit bonus for dexterity
+ */
+
+dext_plus(dexterity)
+register int dexterity;
+{
+ return (dexterity > 10 ? (dexterity-13)/3 : (dexterity-10)/3);
+}
+
+
+/*
+ * dext_prot:
+ * compute armor class bonus for dexterity
+ */
+
+dext_prot(dexterity)
+register int dexterity;
+{
+ return ((dexterity-10)/2);
+}
+/*
+ * str_plus:
+ * compute bonus/penalties for strength on the "to hit" roll
+ */
+
+str_plus(str)
+register short str;
+{
+ return((str-10)/3);
+}
+
+/*
+ * add_dam:
+ * compute additional damage done for exceptionally high or low strength
+ */
+
+add_dam(str)
+register short str;
+{
+ return((str-9)/2);
+}
+
+/*
+ * hung_dam:
+ * Calculate damage depending on players hungry state
+ */
+hung_dam()
+{
+ reg int howmuch;
+
+ switch(hungry_state) {
+ case F_SATIATED:
+ case F_OKAY:
+ case F_HUNGRY: howmuch = 0;
+ when F_WEAK: howmuch = -1;
+ when F_FAINT: howmuch = -2;
+ }
+ return howmuch;
+}
+
+#ifdef THUNK
+/*
+ * thunk:
+ * A missile hits a monster
+ */
+
+thunk(weap, tp, mname)
+register struct object *weap;
+register struct thing *tp; /* Defender */
+register char *mname;
+{
+ char *def_name; /* Name of defender */
+
+ /* What do we call the defender? */
+ if (!cansee(tp->t_pos.y, tp->t_pos.x) || invisible(tp))
+ def_name = "something";
+ else def_name = prname(mname, FALSE);
+
+ if (weap->o_type == WEAPON)
+ msg("The %s hits %s.", weaps[weap->o_which].w_name, def_name);
+ else if (weap->o_type == MISSILE)
+ msg("The %s hits %s.",ws_magic[weap->o_which].mi_name, def_name);
+ else
+ msg("You hit %s.", def_name);
+}
+
+/*
+ * mthunk:
+ * A missile from a monster hits the player
+ */
+
+m_thunk(weap, tp, mname)
+register struct object *weap;
+register struct thing *tp;
+register char *mname;
+{
+ char *att_name; /* Name of attacker */
+
+ /* What do we call the attacker? */
+ if (!cansee(tp->t_pos.y, tp->t_pos.x) || invisible(tp))
+ att_name = "Something";
+ else att_name = prname(mname, TRUE);
+
+ if (weap->o_type == WEAPON)
+ msg("%s's %s hits you.", att_name, weaps[weap->o_which].w_name);
+ else if (weap->o_type == MISSILE)
+ msg("%s's %s hits you.", att_name, ws_magic[weap->o_which].mi_name);
+ else
+ msg("%s hits you.", att_name);
+}
+
+/*
+ * bounce:
+ * A missile misses a monster
+ */
+
+bounce(weap, tp, mname)
+register struct object *weap;
+register struct thing *tp; /* Defender */
+register char *mname;
+{
+ char *def_name; /* Name of defender */
+
+ /* What do we call the defender? */
+ if (!cansee(tp->t_pos.y, tp->t_pos.x) || invisible(tp))
+ def_name = "something";
+ else def_name = prname(mname, FALSE);
+
+ if (weap->o_type == WEAPON)
+ msg("The %s misses %s.",weaps[weap->o_which].w_name, def_name);
+ else if (weap->o_type == MISSILE)
+ msg("The %s misses %s.",ws_magic[weap->o_which].mi_name, def_name);
+ else
+ msg("You missed %s.", def_name);
+}
+
+/*
+ * m_bounce:
+ * A missle from a monster misses the player
+ */
+
+m_bounce(weap, tp, mname)
+register struct object *weap;
+register struct thing *tp;
+register char *mname;
+{
+ char *att_name; /* Name of attacker */
+
+ /* What do we call the attacker? */
+ if (!cansee(tp->t_pos.y, tp->t_pos.x) || invisible(tp))
+ att_name = "Something";
+ else att_name = prname(mname, TRUE);
+
+ if (weap->o_type == WEAPON)
+ msg("%s's %s misses you.", att_name, weaps[weap->o_which].w_name);
+ else if (weap->o_type == MISSILE)
+ msg("%s's %s misses you.", att_name, ws_magic[weap->o_which].mi_name);
+ else
+ msg("%s misses you.", att_name);
+}
+#endif
+
+
+/*
+ * is_magic:
+ * Returns true if an object radiates magic
+ */
+
+is_magic(obj)
+register struct object *obj;
+{
+ switch (obj->o_type)
+ {
+ case ARMOR:
+ return obj->o_ac != armors[obj->o_which].a_class;
+ when WEAPON:
+ return obj->o_hplus != 0 || obj->o_dplus != 0;
+ when POTION:
+ case SCROLL:
+ case STICK:
+ case RING:
+ case MM:
+ case RELIC:
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * killed:
+ * Called to put a monster to death
+ */
+
+int chance = 0;/* cumulative chance for goodies to loose it */
+
+killed(item, pr, points, treasure)
+register struct linked_list *item;
+bool pr, points, treasure;
+{
+ register struct thing *tp, *mp;
+ register struct linked_list *pitem, *nexti, *mitem;
+ char *monst;
+
+ tp = THINGPTR(item);
+
+ if (pr)
+ {
+ addmsg(terse ? "Defeated " : "You have defeated ");
+ if (on(player, ISBLIND))
+ msg("it.");
+ else
+ {
+ if (cansee(tp->t_pos.y, tp->t_pos.x) && !invisible(tp))
+ monst = monster_name(tp);
+ else {
+ if (terse) monst = "something";
+ else monst = "thing";
+ }
+ if (!terse)
+ addmsg("the ");
+ msg("%s.", monst);
+ }
+ }
+
+ /* Take care of any residual effects of the monster */
+ check_residue(tp);
+
+ /* Make sure that no one is still chasing us */
+ for (mitem = mlist; mitem != NULL; mitem = next(mitem)) {
+ mp = THINGPTR(mitem);
+ if (mp->t_dest == &tp->t_pos) {
+ mp->t_dest = &hero;
+ mp->t_wasshot = FALSE;
+ turn_off(*mp, ISFLEE); /* Be sure we aren't running away! */
+ }
+ }
+
+ if (points) {
+ if ((off(*tp, ISMEAN) || on(*tp, ISFRIENDLY)) &&
+ (player.t_ctype == C_RANGER || player.t_ctype == C_PALADIN)) {
+ if (tp->t_stats.s_exp > pstats.s_exp)
+ pstats.s_exp = 0;
+ else
+ pstats.s_exp -= tp->t_stats.s_exp;
+ if (roll(1,100) < chance++)
+ changeclass(C_FIGHTER);
+ else
+ msg("You feel uneasy for a moment");
+ }
+ else {
+ unsigned long test; /* For overflow check */
+ /*
+ * Do an overflow check before increasing experience
+ */
+ test = pstats.s_exp + tp->t_stats.s_exp;
+ if (test > pstats.s_exp)
+ pstats.s_exp = test;
+ }
+
+ /*
+ * Do adjustments if he went up a level
+ */
+ check_level();
+ }
+
+ /*
+ * Empty the monsters pack
+ */
+ pitem = tp->t_pack;
+
+ /*
+ * Get rid of the monster.
+ */
+ mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, ' ');
+ mvwaddch(cw, tp->t_pos.y, tp->t_pos.x, tp->t_oldch);
+ detach(mlist, item);
+ if (on(*tp, AREMANY) && levtype == NORMLEV) /* AREMANYs stick together */
+ wake_room(roomin(&tp->t_pos));
+ /*
+ * empty his pack
+ */
+ while (pitem != NULL)
+ {
+ nexti = next(tp->t_pack);
+ (OBJPTR(pitem))->o_pos = tp->t_pos;
+ detach(tp->t_pack, pitem);
+ if (treasure)
+ fall(pitem, FALSE);
+ else
+ o_discard(pitem);
+ pitem = nexti;
+ }
+ turn_on(*tp,ISDEAD);
+ attach(monst_dead,item);
+}
+
+
+/*
+ * Returns a pointer to the weapon the monster is wielding corresponding to
+ * the given thrown weapon. If no thrown item is given, try to find any
+ * decent weapon.
+ */
+
+struct linked_list *
+wield_weap(thrown, mp)
+struct object *thrown;
+struct thing *mp;
+{
+ int look_for, /* The projectile weapon we are looking for */
+ new_rate, /* The rating of a prospective weapon */
+ cand_rate = -1; /* Rating of current candidate -- higher is better */
+ register struct linked_list *pitem, *candidate = NULL;
+ register struct object *obj;
+
+ if (thrown != NULL) { /* Using a projectile weapon */
+ switch (thrown->o_which) {
+ case BOLT: look_for = CROSSBOW; /* Find the crossbow */
+ when ARROW: look_for = BOW; /* Find the bow */
+ when ROCK: look_for = SLING; /* find the sling */
+ otherwise: return(NULL);
+ }
+ }
+ else if (off(*mp, ISUNIQUE) && off(*mp, CARRYWEAPON)) return(NULL);
+
+ for (pitem=mp->t_pack; pitem; pitem=next(pitem)) {
+ obj = OBJPTR(pitem);
+
+ /*
+ * If we have a thrown weapon, just return the first match
+ * we come to.
+ */
+ if (thrown != NULL && obj->o_type == WEAPON && obj->o_which == look_for)
+ return(pitem);
+
+ /* If we have a usable RELIC, return it */
+ if (thrown == NULL && obj->o_type == RELIC) {
+ switch (obj->o_which) {
+ case MUSTY_DAGGER:
+ case YEENOGHU_FLAIL:
+ case HRUGGEK_MSTAR:
+ case AXE_AKLAD:
+ case MING_STAFF:
+ case ASMO_ROD:
+ case ORCUS_WAND:
+ return(pitem);
+ }
+ }
+
+ /* Otherwise if it's a usable weapon, it is a good candidate */
+ else if (thrown == NULL && obj->o_type == WEAPON) {
+ switch (obj->o_which) {
+ case DAGGER:
+ case SPEAR:
+ new_rate = 0;
+ when BATTLEAXE:
+ new_rate = 1;
+ when MACE:
+ new_rate = 2;
+ when SWORD:
+ new_rate = 3;
+ when PIKE:
+ new_rate = 4;
+ when HALBERD:
+ case SPETUM:
+ new_rate = 6;
+ when BARDICHE:
+ new_rate = 7;
+ when TRIDENT:
+ new_rate = 8;
+ when BASWORD:
+ new_rate = 9;
+ when TWOSWORD:
+ new_rate = 10;
+ otherwise:
+ new_rate = -1;
+ }
+
+ /* Only switch if this is better than the current candidate */
+ if (new_rate > cand_rate) {
+ cand_rate = new_rate;
+ candidate = pitem;
+ }
+ }
+ }
+
+ return(candidate);
+}
+explode(tp)
+register struct thing *tp;
+{
+
+ register int x,y, damage;
+ struct linked_list *item;
+ struct thing *th;
+
+ /*
+ * check to see if it got the hero
+ */
+ if (off(player, ISINWALL) &&
+ DISTANCE(hero.x, hero.y, tp->t_pos.x, tp->t_pos.y) <= 25) {
+ msg("The explosion hits you");
+ damage = roll(6,6);
+ if (save(VS_WAND, &player, 0))
+ damage /= 2;
+ pstats.s_hpt -= damage;
+ }
+
+ /*
+ * now check for monsters in vicinity
+ */
+ for (x = tp->t_pos.x-5; x<=tp->t_pos.x+5; x++) {
+ if (x < 0 || x > cols - 1)
+ continue;
+ for (y = tp->t_pos.y-5; y<=tp->t_pos.y+5; y++) {
+ if (y < 1 || y > lines - 3)
+ continue;
+ if (isalpha(mvwinch(mw, y, x))) {
+ if ((item = find_mons(y, x)) != NULL) {
+ th = THINGPTR(item);
+ if (th == tp || /* don't count gas spore */
+ on(*th, ISINWALL)) /* Don't count monsters in wall */
+ continue;
+ damage = roll(6, 6);
+ if (save(VS_WAND, th, 0))
+ damage /= 2;
+ runto(th, &hero);
+ if ((th->t_stats.s_hpt -= damage) <= 0) {
+ msg("The explosion kills %s",
+ prname(monster_name(th), FALSE));
+ killed(item, FALSE, FALSE, TRUE);
+ }
+ }
+ }
+ }
+ }
+}
+
+/*
+ * skirmish:
+ * Called when one monster attacks another monster.
+ */
+
+skirmish(attacker, mp, weap, thrown)
+register struct thing *attacker;
+register coord *mp;
+struct object *weap;
+bool thrown;
+{
+ register struct thing *defender;
+ register struct linked_list *item;
+ register bool did_hit = TRUE, see_att, see_def;
+ char attname[LINELEN+1], defname[LINELEN+1];
+ struct object *wielded; /* The wielded weapon */
+ struct linked_list *get_wield; /* Linked list header for wielded */
+
+ /*
+ * Find the monster we want to fight
+ */
+ if ((item = find_mons(mp->y, mp->x)) == NULL) {
+ return(FALSE); /* must have killed him already */
+ }
+ defender = THINGPTR(item);
+
+ /* Can the player see either of the fighters? */
+ see_att = (cansee(unc(attacker->t_pos)) &&
+ (off(*attacker, ISINVIS) || on(player, CANSEE)) &&
+ (off(*attacker, ISSHADOW) || on(player, CANSEE)));
+ see_def = (cansee(unc(defender->t_pos)) &&
+ (off(*defender, ISINVIS) || on(player, CANSEE)) &&
+ (off(*defender, ISSHADOW) || on(player, CANSEE)));
+
+ /*
+ * Since we are fighting, things are not quiet so no healing takes
+ * place. The -1 also tells us that we are in a fight.
+ */
+ attacker->t_quiet = -1;
+ defender->t_quiet = -1;
+
+ if (see_att) strcpy(attname, monster_name(attacker));
+ else strcpy(attname, "something");
+
+ if (see_def) strcpy(defname, monster_name(defender));
+ else strcpy(defname, "something");
+
+ /*
+ * if its in the wall, we can't hit it
+ */
+ if (on(*defender, ISINWALL) && off(*attacker, CANINWALL))
+ return(FALSE);
+
+ if (on(*defender, ISSTONE)) {
+ killed(item, FALSE, FALSE, FALSE);
+ if (see_def)
+ msg("%s shatters into a million pieces!", prname(defname, TRUE));
+ return (TRUE);
+ }
+
+ /*
+ * Let him know it was really a mimic (if it was one).
+ */
+ if (see_def && on(*defender, ISDISGUISE) &&
+ (defender->t_type != defender->t_disguise)) {
+ msg("Wait! There's a %s!", defname);
+ turn_off(*defender, ISDISGUISE);
+ did_hit = thrown;
+ }
+
+ if (see_def && on(*defender, CANSURPRISE) && !ISWEARING(R_ALERT)) {
+ msg("Wait! There's a %s!", defname);
+ turn_off(*defender, CANSURPRISE);
+ did_hit = thrown;
+ }
+
+ if (did_hit) {
+
+ did_hit = FALSE;
+
+ /*
+ * 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, it will try to find a suitable weapon.
+ */
+ get_wield = wield_weap(weap, attacker);
+ if (get_wield) wielded = OBJPTR(get_wield);
+ else wielded = NULL;
+
+#ifdef DOBLINK
+ /*
+ * For now Blink Dogs will not blink away from monsters. We
+ * have to fix can_blink so it isn't dependant on the player
+ * before we can add it.
+ */
+ if (!can_blink(defender) &&
+#endif
+ if (((weap && weap->o_type == RELIC) ||
+ ((off(*defender, MAGICHIT) ||
+ attacker->t_stats.s_lvl > 4 ||
+ (weap && (weap->o_hplus > 0 || weap->o_dplus > 0))) &&
+ (off(*defender, BMAGICHIT) ||
+ attacker->t_stats.s_lvl > 6 ||
+ (weap && (weap->o_hplus > 1 || weap->o_dplus > 1))) &&
+ (off(*defender, CMAGICHIT) ||
+ attacker->t_stats.s_lvl > 8 ||
+ (weap && (weap->o_hplus > 2 || weap->o_dplus > 2)))))
+ && roll_em(attacker, defender, weap, thrown, wielded, FALSE))
+ {
+ did_hit = TRUE;
+
+ /* Should we start to chase this creature? */
+ if (attacker->t_index != defender->t_index &&
+ (off(*defender, ISRUN) || rnd(100) < 50)) {
+ /*
+ * If we're intelligent enough to realize that this
+ * is a friendly monster, we will attack the hero instead.
+ */
+ if (on(*attacker, ISFRIENDLY) &&
+ roll(3,6) < defender->t_stats.s_intel) {
+ runto(defender, &hero);
+ debug("%s attacking %s's hero", defname, attname);
+ }
+
+ /* Otherwise, let's chase the monster */
+ else {
+ runto(defender, &attacker->t_pos);
+ debug("%s now attacking %s", defname, attname);
+ }
+ }
+ else if (off(*defender, ISRUN)) runto(defender, &hero);
+
+ /* Let the defender know that the attacker has missiles! */
+ if ((defender->t_dest == &attacker->t_pos) && thrown)
+ defender->t_wasshot = TRUE;
+
+ if (on(*defender, NOMETAL) && weap != NULL &&
+ weap->o_type != RELIC && weap->o_flags & ISMETAL) {
+ if (see_def && see_att)
+ msg("The %s passes right through %s!",
+ weaps[weap->o_which].w_name, prname(defname, FALSE));
+ }
+ else {
+ hit(weap, see_att, see_def,
+ attname, defname, FALSE, thrown, FALSE);
+ }
+
+ /* See if there are any special effects */
+ if (effect(attacker, defender,
+ weap, thrown, see_att, see_def) != 0) {
+ killed(item, FALSE, FALSE, TRUE);
+ if (see_def) msg("%s dies.", prname(defname, TRUE));
+ else msg("You hear a blood-curdling scream.");
+ }
+
+ /*
+ * Merchants just disappear if hit
+ */
+ else if (on(*defender, CANSELL)) {
+ if (see_def)
+ msg("%s disappears with his wares in a flash.",
+ prname(defname, TRUE));
+ killed(item, FALSE, FALSE, FALSE);
+ }
+
+ else if (defender->t_stats.s_hpt <= 0) {
+ killed(item, FALSE, FALSE, TRUE);
+ if (see_def) msg("%s dies.", prname(defname, TRUE));
+ else msg("You hear a blood-curdling scream.");
+ }
+
+ else {
+ /* Did we disrupt a spell? */
+ /* Don't turn on WASDISRUPTED since player didn't do it */
+ if (defender->t_action == A_SUMMON ||
+ defender->t_action == A_MISSILE) {
+ /* Just make the old fellow start over again */
+ defender->t_action = A_NIL;
+ defender->t_no_move = movement(defender);
+ defender->t_using = NULL;
+
+ if (see_def)
+ msg("%s was disrupted.", prname(defname, TRUE));
+ }
+
+#ifdef FLEEMONST
+ /*
+ * If the monster is fairly intelligent and about to die, it
+ * may turn tail and run. WE STILL NEED TO FIGURE OUT HOW
+ * WE WANT THIS TO WORK.
+ */
+ if ((tp->t_stats.s_hpt < max(10, tp->maxstats.s_hpt/10)) &&
+ (rnd(25) < tp->t_stats.s_intel)) {
+ turn_on(*tp, ISFLEE);
+
+ /* 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;
+ }
+#endif
+ }
+ }
+ else {
+ /* If the thing was trying to surprise, no good */
+ if (on(*attacker, CANSURPRISE)) {
+ /* If we can't see it, it keeps surprise (from us) */
+ if (see_att) turn_off(*attacker, CANSURPRISE);
+ }
+
+ miss(weap, see_att, see_def, attname, defname, thrown, FALSE);
+ }
+ }
+ return did_hit;
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/init.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/init.c Fri May 08 15:24:40 2015 -0400
@@ -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
+#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 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);
+}
+
+
diff -r d10fc4a065ac -r adfa37e67084 arogue7/io.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/io.c Fri May 08 15:24:40 2015 -0400
@@ -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
+#include
+#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 4) {
+ *error = 1;
+ return(0L);
+ }
+
+ for (i=0; i 4) return(0);
+
+ for (i=0; i> (8 * i)) & 0xff);
+ putc(outc, stream);
+ }
+ return(size);
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/list.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/list.c Fri May 08 15:24:40 2015 -0400
@@ -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
+#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;
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/mach_dep.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/mach_dep.h Fri May 08 15:24:40 2015 -0400
@@ -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
diff -r d10fc4a065ac -r adfa37e67084 arogue7/main.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/main.c Fri May 08 15:24:40 2015 -0400
@@ -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
+#ifdef BSD
+#include
+#else
+#include
+#endif
+#include "mach_dep.h"
+#include "network.h"
+#include "rogue.h"
+#ifdef PC7300
+#include "sys/window.h"
+#include
+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 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
+
+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
+#include
+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
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/maze.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/maze.c Fri May 08 15:24:40 2015 -0400
@@ -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
+#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);
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/mdport.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/mdport.c Fri May 08 15:24:40 2015 -0400
@@ -0,0 +1,1195 @@
+/*
+ mdport.c - Machine Dependent Code for Porting Unix/Curses games
+
+ 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.
+*/
+
+#if defined(_WIN32)
+#include
+#include
+#include
+#include
+#include
+#include
+#undef MOUSE_MOVED
+#elif defined(__DJGPP__)
+#include
+#else
+#include
+#include
+#include
+#endif
+
+#include
+
+#if defined(_WIN32) && !defined(__MINGW32__)
+#define PATH_MAX _PATH_MAX
+#endif
+
+#include
+
+#if defined(__INTERIX) || defined(__MSYS__)
+#include
+#else
+#ifdef NCURSES_VERSION
+#include
+#endif
+#endif
+
+#include
+#include
+#include
+#include
+#include
+
+#define MOD_MOVE(c) (toupper(c) )
+
+void
+md_init()
+{
+#ifdef __INTERIX
+ char *term;
+
+ term = getenv("TERM");
+
+ if (term == NULL)
+ setenv("TERM","interix");
+#endif
+#if defined(__DJGPP__) || defined(_WIN32)
+ _fmode = _O_BINARY;
+#endif
+#if defined(__CYGWIN__) || defined(__MSYS__)
+ ESCDELAY=250;
+#endif
+}
+
+int
+md_hasclreol()
+{
+#ifndef attron
+ return(!CE);
+#elif !defined(__PDCURSES__)
+ return(clr_eol != NULL);
+#else
+ return(TRUE);
+#endif
+}
+
+#ifdef attron
+# define _puts(s) tputs(s, 0, md_putchar);
+# define SO enter_standout_mode
+# define SE exit_standout_mode
+#endif
+
+int
+md_putchar(int c)
+{
+ putchar(c);
+}
+
+static int md_standout_mode = 0;
+
+int
+md_raw_standout()
+{
+#ifdef _WIN32
+ CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
+ HANDLE hStdout;
+ int fgattr,bgattr;
+
+ if (md_standout_mode == 0)
+ {
+ hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ GetConsoleScreenBufferInfo(hStdout, &csbiInfo);
+ fgattr = (csbiInfo.wAttributes & 0xF);
+ bgattr = (csbiInfo.wAttributes & 0xF0);
+ SetConsoleTextAttribute(hStdout,(fgattr << 4) | (bgattr >> 4));
+ md_standout_mode = 1;
+ }
+#elif !defined(__PDCURSES__)
+ _puts(SO);
+ fflush(stdout);
+#endif
+}
+
+int
+md_raw_standend()
+{
+#ifdef _WIN32
+ CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
+ HANDLE hStdout;
+ int fgattr,bgattr;
+
+ if (md_standout_mode == 1)
+ {
+ hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ GetConsoleScreenBufferInfo(hStdout, &csbiInfo);
+ fgattr = (csbiInfo.wAttributes & 0xF);
+ bgattr = (csbiInfo.wAttributes & 0xF0);
+ SetConsoleTextAttribute(hStdout,(fgattr << 4) | (bgattr >> 4));
+ md_standout_mode = 0;
+ }
+#elif !defined(__PDCURSES__)
+ _puts(SE);
+ fflush(stdout);
+#endif
+}
+
+int
+md_unlink_open_file(char *file, int inf)
+{
+#ifdef _WIN32
+ close(inf);
+ chmod(file, 0600);
+ return( _unlink(file) );
+#else
+ return(unlink(file));
+#endif
+}
+
+int
+md_unlink(char *file)
+{
+#ifdef _WIN32
+ chmod(file, 0600);
+ return( _unlink(file) );
+#else
+ return(unlink(file));
+#endif
+}
+
+int
+md_creat(char *file, int mode)
+{
+ int fd;
+#ifdef _WIN32
+ mode = _S_IREAD | _S_IWRITE;
+#endif
+ fd = open(file,O_CREAT | O_EXCL | O_WRONLY, mode);
+
+ return(fd);
+}
+
+
+int
+md_normaluser()
+{
+#ifndef _WIN32
+ setuid(getuid());
+ setgid(getgid());
+#endif
+}
+
+int
+md_getuid()
+{
+#ifndef _WIN32
+ return( getuid() );
+#else
+ return(42);
+#endif
+}
+
+char *
+md_getusername()
+{
+ static char login[80];
+ char *l = NULL;
+#ifdef _WIN32
+ LPSTR mybuffer;
+ DWORD size = UNLEN + 1;
+ TCHAR buffer[UNLEN + 1];
+
+ mybuffer = buffer;
+ GetUserName(mybuffer,&size);
+ l = mybuffer;
+#endif
+#if !defined(_WIN32) && !defined(DJGPP)
+ struct passwd *pw;
+
+ pw = getpwuid(getuid());
+
+ l = pw->pw_name;
+#endif
+
+ if ((l == NULL) || (*l == '\0'))
+ if ( (l = getenv("USERNAME")) == NULL )
+ if ( (l = getenv("LOGNAME")) == NULL )
+ if ( (l = getenv("USER")) == NULL )
+ l = "nobody";
+
+ strncpy(login,l,80);
+ login[79] = 0;
+
+ return(login);
+}
+
+char *
+md_gethomedir()
+{
+ static char homedir[PATH_MAX];
+ char *h = NULL;
+ size_t len;
+#if defined(_WIN32)
+ TCHAR szPath[PATH_MAX];
+#endif
+#if defined(_WIN32) || defined(DJGPP)
+ char slash = '\\';
+#else
+ char slash = '/';
+ struct passwd *pw;
+ pw = getpwuid(getuid());
+
+ h = pw->pw_dir;
+
+ if (strcmp(h,"/") == 0)
+ h = NULL;
+#endif
+ homedir[0] = 0;
+#ifdef _WIN32
+ if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, szPath)))
+ h = szPath;
+#endif
+
+ if ( (h == NULL) || (*h == '\0') )
+ if ( (h = getenv("HOME")) == NULL )
+ if ( (h = getenv("HOMEDRIVE")) == NULL)
+ h = "";
+ else
+ {
+ strncpy(homedir,h,PATH_MAX-1);
+ homedir[PATH_MAX-1] = 0;
+
+ if ( (h = getenv("HOMEPATH")) == NULL)
+ h = "";
+ }
+
+
+ len = strlen(homedir);
+ strncat(homedir,h,PATH_MAX-len-1);
+ len = strlen(homedir);
+
+ if ((len > 0) && (homedir[len-1] != slash)) {
+ homedir[len] = slash;
+ homedir[len+1] = 0;
+ }
+
+ return(homedir);
+}
+
+int
+md_sleep(int s)
+{
+#ifdef _WIN32
+ _sleep(s);
+#else
+ sleep(s);
+#endif
+}
+
+char *
+md_getshell()
+{
+ static char shell[PATH_MAX];
+ char *s = NULL;
+#ifdef _WIN32
+ char *def = "C:\\WINDOWS\\SYSTEM32\\CMD.EXE";
+#elif defined(__DJGPP__)
+ char *def = "C:\\COMMAND.COM";
+#else
+ char *def = "/bin/sh";
+ struct passwd *pw;
+ pw = getpwuid(getuid());
+ s = pw->pw_shell;
+#endif
+ if ((s == NULL) || (*s == '\0'))
+ if ( (s = getenv("COMSPEC")) == NULL)
+ if ( (s = getenv("SHELL")) == NULL)
+ if ( (s = getenv("SystemRoot")) == NULL)
+ s = def;
+
+ strncpy(shell,s,PATH_MAX);
+ shell[PATH_MAX-1] = 0;
+
+ return(shell);
+}
+
+int
+md_shellescape()
+{
+#if (!defined(_WIN32) && !defined(__DJGPP__))
+ int ret_status;
+ int pid;
+ void (*myquit)(int);
+ void (*myend)(int);
+#endif
+ char *sh;
+
+ sh = md_getshell();
+
+#if defined(_WIN32)
+ return((int)_spawnl(_P_WAIT,sh,"shell",NULL,0));
+#elif defined(__DJGPP__)
+ return ( spawnl(P_WAIT,sh,"shell",NULL,0) );
+#else
+ while((pid = fork()) < 0)
+ sleep(1);
+
+ if (pid == 0) /* Shell Process */
+ {
+ /*
+ * Set back to original user, just in case
+ */
+ setuid(getuid());
+ setgid(getgid());
+ execl(sh == NULL ? "/bin/sh" : sh, "shell", "-i", 0);
+ perror("No shelly");
+ _exit(-1);
+ }
+ else /* Application */
+ {
+ myend = signal(SIGINT, SIG_IGN);
+#ifdef SIGQUIT
+ myquit = signal(SIGQUIT, SIG_IGN);
+#endif
+ while (wait(&ret_status) != pid)
+ continue;
+
+ signal(SIGINT, myquit);
+#ifdef SIGQUIT
+ signal(SIGQUIT, myend);
+#endif
+ }
+
+ return(ret_status);
+#endif
+}
+
+int
+directory_exists(char *dirname)
+{
+ struct stat sb;
+
+ if (stat(dirname, &sb) == 0) /* path exists */
+ return (sb.st_mode & S_IFDIR);
+
+ return(0);
+}
+
+char *
+md_getroguedir()
+{
+ static char path[1024];
+ char *end,*home;
+
+ if ( (home = getenv("ROGUEHOME")) != NULL)
+ {
+ if (*home)
+ {
+ strncpy(path, home, PATH_MAX - 20);
+
+ end = &path[strlen(path)-1];
+
+ while( (end >= path) && ((*end == '/') || (*end == '\\')))
+ *end-- = '\0';
+
+ if (directory_exists(path))
+ return(path);
+ }
+ }
+
+ if (directory_exists("/var/games/roguelike"))
+ return("/var/games/roguelike");
+ if (directory_exists("/var/lib/roguelike"))
+ return("/var/lib/roguelike");
+ if (directory_exists("/var/roguelike"))
+ return("/var/roguelike");
+ if (directory_exists("/usr/games/lib"))
+ return("/usr/games/lib");
+ if (directory_exists("/games/roguelik"))
+ return("/games/roguelik");
+
+ return("");
+}
+
+char *
+md_getrealname(int uid)
+{
+ static char uidstr[20];
+#if !defined(_WIN32) && !defined(DJGPP)
+ struct passwd *pp;
+
+ if ((pp = getpwuid(uid)) == NULL)
+ {
+ sprintf(uidstr,"%d", uid);
+ return(uidstr);
+ }
+ else
+ return(pp->pw_name);
+#else
+ sprintf(uidstr,"%d", uid);
+ return(uidstr);
+#endif
+}
+
+extern char *xcrypt(char *key, char *salt);
+
+char *
+md_crypt(char *key, char *salt)
+{
+ return( xcrypt(key,salt) );
+}
+
+char *
+md_getpass(prompt)
+char *prompt;
+{
+#ifdef _WIN32
+ static char password_buffer[9];
+ char *p = password_buffer;
+ int c, count = 0;
+ int max_length = 9;
+
+ fflush(stdout);
+ /* If we can't prompt, abort */
+ if (fputs(prompt, stderr) < 0)
+ {
+ *p = '\0';
+ return NULL;
+ }
+
+ for(;;)
+ {
+ /* Get a character with no echo */
+ c = _getch();
+
+ /* Exit on interrupt (^c or ^break) */
+ if (c == '\003' || c == 0x100)
+ exit(1);
+
+ /* Terminate on end of line or file (^j, ^m, ^d, ^z) */
+ if (c == '\r' || c == '\n' || c == '\004' || c == '\032')
+ break;
+
+ /* Back up on backspace */
+ if (c == '\b')
+ {
+ if (count)
+ count--;
+ else if (p > password_buffer)
+ p--;
+ continue;
+ }
+
+ /* Ignore DOS extended characters */
+ if ((c & 0xff) != c)
+ continue;
+
+ /* Add to password if it isn't full */
+ if (p < password_buffer + max_length - 1)
+ *p++ = c;
+ else
+ count++;
+ }
+ *p = '\0';
+
+ fputc('\n', stderr);
+
+ return password_buffer;
+#else
+ return( (char *) getpass(prompt) );
+#endif
+}
+
+
+int md_endian = 0x01020304;
+
+unsigned long int
+md_ntohl(unsigned long int x)
+{
+#ifdef _WIN32
+ if ( *((char *)&md_endian) == 0x01 )
+ return(x);
+ else
+ return( ((x & 0x000000ffU) << 24) |
+ ((x & 0x0000ff00U) << 8) |
+ ((x & 0x00ff0000U) >> 8) |
+ ((x & 0xff000000U) >> 24) );
+#else
+ return( ntohl(x) );
+#endif
+}
+
+unsigned long int
+md_htonl(unsigned long int x)
+{
+#ifdef _WIN32
+ if ( *((char *)&md_endian) == 0x01 )
+ return(x);
+ else
+ return( ((x & 0x000000ffU) << 24) |
+ ((x & 0x0000ff00U) << 8) |
+ ((x & 0x00ff0000U) >> 8) |
+ ((x & 0xff000000U) >> 24) );
+#else
+ return( htonl(x) );
+#endif
+}
+
+int
+md_rand()
+{
+#ifdef _WIN32
+ return(rand());
+#else
+ return(random());
+#endif
+}
+
+int
+md_srand(seed)
+register int seed;
+{
+#ifdef _WIN32
+ srand(seed);
+#else
+ srandom(seed);
+#endif
+}
+
+long
+md_memused()
+{
+#ifdef _WIN32
+ MEMORYSTATUS stat;
+
+ GlobalMemoryStatus(&stat);
+
+ return((long)stat.dwTotalPageFile);
+#else
+ return( (long)sbrk(0) );
+#endif
+}
+
+char *
+md_gethostname()
+{
+ static char nodename[80];
+ char *n = NULL;
+#if !defined(_WIN32) && !defined(__DJGPP__)
+ struct utsname ourname;
+
+ if (uname(&ourname) == 0)
+ n = ourname.nodename;
+#endif
+ if ((n == NULL) || (*n == '\0'))
+ if ( (n = getenv("COMPUTERNAME")) == NULL)
+ if ( (n = getenv("HOSTNAME")) == NULL)
+ n = "localhost";
+
+ strncpy(nodename, n, 80);
+ nodename[79] = 0;
+
+ return(nodename);
+}
+
+int
+md_erasechar()
+{
+#ifdef BSD
+ return(_tty.sg_erase); /* process erase character */
+#elif defined(USG5_0)
+ return(_tty.c_cc[VERASE]); /* process erase character */
+#else /* USG5_2 .... curses */
+ return( erasechar() ); /* process erase character */
+#endif
+}
+
+int
+md_killchar()
+{
+#ifdef BSD
+ return(_tty.sg_kill);
+#elif defined(USG5_0)
+ return(_tty.c_cc[VKILL]);
+#else /* USG5_2 ..... curses */
+ return( killchar() );
+#endif
+}
+
+/*
+ * unctrl:
+ * Print a readable version of a certain character
+ */
+
+char *
+md_unctrl(ch)
+char ch;
+{
+#if USG5_0
+ extern char *_unctrl[]; /* Defined in curses library */
+
+ return _unctrl[ch&0177];
+#else
+ return( unctrl(ch) );
+#endif
+}
+
+void
+md_flushinp()
+{
+#ifdef BSD
+ ioctl(0, TIOCFLUSH);
+#elif defined(USG5_0)
+ ioctl(_tty_ch,TCFLSH,0)
+#else /* USG5_2.... curses */
+ flushinp();
+#endif
+}
+
+/*
+ Cursor/Keypad Support
+
+ Sadly Cursor/Keypad support is less straightforward than it should be.
+
+ The various terminal emulators/consoles choose to differentiate the
+ cursor and keypad keys (with modifiers) in different ways (if at all!).
+ Furthermore they use different code set sequences for each key only
+ a subset of which the various curses libraries recognize. Partly due
+ to incomplete termcap/terminfo entries and partly due to inherent
+ limitations of those terminal capability databases.
+
+ I give curses first crack at decoding the sequences. If it fails to decode
+ it we check for common ESC-prefixed sequences.
+
+ All cursor/keypad results are translated into standard rogue movement
+ commands.
+
+ Unmodified keys are translated to walk commands: hjklyubn
+ Modified (shift,control,alt) are translated to run commands: HJKLYUBN
+
+ Console and supported (differentiated) keys
+ Interix: Cursor Keys, Keypad, Ctl-Keypad
+ Cygwin: Cursor Keys, Keypad, Alt-Cursor Keys
+ MSYS: Cursor Keys, Keypad, Ctl-Cursor Keys, Ctl-Keypad
+ Win32: Cursor Keys, Keypad, Ctl/Shift/Alt-Cursor Keys, Ctl/Alt-Keypad
+ DJGPP: Cursor Keys, Keypad, Ctl/Shift/Alt-Cursor Keys, Ctl/Alt-Keypad
+
+ Interix Console (raw, ncurses)
+ ==============================
+ normal shift ctrl alt
+ ESC [D, ESC F^, ESC [D, ESC [D /# Left #/
+ ESC [C, ESC F$, ESC [C, ESC [C /# Right #/
+ ESC [A, ESC F-, local win, ESC [A /# Up #/
+ ESC [B, ESC F+, local win, ESC [B /# Down #/
+ ESC [H, ESC [H, ESC [H, ESC [H /# Home #/
+ ESC [S, local win, ESC [S, ESC [S /# Page Up #/
+ ESC [T, local win, ESC [T, ESC [T /# Page Down #/
+ ESC [U, ESC [U, ESC [U, ESC [U /# End #/
+ ESC [D, ESC F^, ESC [D, O /# Keypad Left #/
+ ESC [C, ESC F$, ESC [C, O /# Keypad Right #/
+ ESC [A, ESC [A, ESC [-1, O /# Keypad Up #/
+ ESC [B, ESC [B, ESC [-2, O /# Keypad Down #/
+ ESC [H, ESC [H, ESC [-263, O /# Keypad Home #/
+ ESC [S, ESC [S, ESC [-19, O /# Keypad PgUp #/
+ ESC [T, ESC [T, ESC [-20, O /# Keypad PgDn #/
+ ESC [U, ESC [U, ESC [-21, O /# Keypad End #/
+ nothing, nothing, nothing, O /# Kaypad 5 #/
+
+ Interix Console (term=interix, ncurses)
+ ==============================
+ KEY_LEFT, ESC F^, KEY_LEFT, KEY_LEFT /# Left #/
+ KEY_RIGHT, ESC F$, KEY_RIGHT, KEY_RIGHT /# Right #/
+ KEY_UP, 0x146, local win, KEY_UP /# Up #/
+ KEY_DOWN, 0x145, local win, KEY_DOWN /# Down #/
+ ESC [H, ESC [H, ESC [H, ESC [H /# Home #/
+ KEY_PPAGE, local win, KEY_PPAGE, KEY_PPAGE /# Page Up #/
+ KEY_NPAGE, local win, KEY_NPAGE, KEY_NPAGE /# Page Down #/
+ KEY_LL, KEY_LL, KEY_LL, KEY_LL /# End #/
+ KEY_LEFT, ESC F^, ESC [-4, O /# Keypad Left #/
+ KEY_RIGHT, ESC F$, ESC [-3, O /# Keypad Right #/
+ KEY_UP, KEY_UP, ESC [-1, O /# Keypad Up #/
+ KEY_DOWN, KEY_DOWN, ESC [-2, O /# Keypad Down #/
+ ESC [H, ESC [H, ESC [-263, O /# Keypad Home #/
+ KEY_PPAGE, KEY_PPAGE, ESC [-19, O /# Keypad PgUp #/
+ KEY_NPAGE, KEY_NPAGE, ESC [-20, O /# Keypad PgDn #/
+ KEY_LL, KEY_LL, ESC [-21, O /# Keypad End #/
+ nothing, nothing, nothing, O /# Keypad 5 #/
+
+ Cygwin Console (raw, ncurses)
+ ==============================
+ normal shift ctrl alt
+ ESC [D, ESC [D, ESC [D, ESC ESC [D /# Left #/
+ ESC [C, ESC [C, ESC [C, ESC ESC [C /# Rght #/
+ ESC [A, ESC [A, ESC [A, ESC ESC [A /# Up #/
+ ESC [B, ESC [B, ESC [B, ESC ESC [B /# Down #/
+ ESC [1~, ESC [1~, ESC [1~, ESC ESC [1~ /# Home #/
+ ESC [5~, ESC [5~, ESC [5~, ESC ESC [5~ /# Page Up #/
+ ESC [6~, ESC [6~, ESC [6~, ESC ESC [6~ /# Page Down #/
+ ESC [4~, ESC [4~, ESC [4~, ESC ESC [4~ /# End #/
+ ESC [D, ESC [D, ESC [D, ESC ESC [D,O /# Keypad Left #/
+ ESC [C, ESC [C, ESC [C, ESC ESC [C,O /# Keypad Right #/
+ ESC [A, ESC [A, ESC [A, ESC ESC [A,O /# Keypad Up #/
+ ESC [B, ESC [B, ESC [B, ESC ESC [B,O /# Keypad Down #/
+ ESC [1~, ESC [1~, ESC [1~, ESC ESC [1~,O /# Keypad Home #/
+ ESC [5~, ESC [5~, ESC [5~, ESC ESC [5~,O /# Keypad PgUp #/
+ ESC [6~, ESC [6~, ESC [6~, ESC ESC [6~,O /# Keypad PgDn #/
+ ESC [4~, ESC [4~, ESC [4~, ESC ESC [4~,O /# Keypad End #/
+ ESC [-71, nothing, nothing, O /# Keypad 5 #/
+
+ Cygwin Console (term=cygwin, ncurses)
+ ==============================
+ KEY_LEFT, KEY_LEFT, KEY_LEFT, ESC-260 /# Left #/
+ KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, ESC-261 /# Rght #/
+ KEY_UP, KEY_UP, KEY_UP, ESC-259 /# Up #/
+ KEY_DOWN, KEY_DOWN, KEY_DOWN, ESC-258 /# Down #/
+ KEY_HOME, KEY_HOME, KEY_HOME, ESC-262 /# Home #/
+ KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, ESC-339 /# Page Up #/
+ KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, ESC-338 /# Page Down #/
+ KEY_END, KEY_END, KEY_END, ESC-360 /# End #/
+ KEY_LEFT, KEY_LEFT, KEY_LEFT, ESC-260,O /# Keypad Left #/
+ KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, ESC-261,O /# Keypad Right #/
+ KEY_UP, KEY_UP, KEY_UP, ESC-259,O /# Keypad Up #/
+ KEY_DOWN, KEY_DOWN, KEY_DOWN, ESC-258,O /# Keypad Down #/
+ KEY_HOME, KEY_HOME, KEY_HOME, ESC-262,O /# Keypad Home #/
+ KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, ESC-339,O /# Keypad PgUp #/
+ KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, ESC-338,O /# Keypad PgDn #/
+ KEY_END, KEY_END, KEY_END, ESC-360,O /# Keypad End #/
+ ESC [G, nothing, nothing, O /# Keypad 5 #/
+
+ MSYS Console (raw, ncurses)
+ ==============================
+ normal shift ctrl alt
+ ESC OD, ESC [d, ESC Od nothing /# Left #/
+ ESC OE, ESC [e, ESC Oe, nothing /# Right #/
+ ESC OA, ESC [a, ESC Oa, nothing /# Up #/
+ ESC OB, ESC [b, ESC Ob, nothing /# Down #/
+ ESC [7~, ESC [7$, ESC [7^, nothing /# Home #/
+ ESC [5~, local window, ESC [5^, nothing /# Page Up #/
+ ESC [6~, local window, ESC [6^, nothing /# Page Down #/
+ ESC [8~, ESC [8$, ESC [8^, nothing /# End #/
+ ESC OD, ESC [d, ESC Od O /# Keypad Left #/
+ ESC OE, ESC [c, ESC Oc, O /# Keypad Right #/
+ ESC OA, ESC [a, ESC Oa, O /# Keypad Up #/
+ ESC OB, ESC [b, ESC Ob, O /# Keypad Down #/
+ ESC [7~, ESC [7$, ESC [7^, O /# Keypad Home #/
+ ESC [5~, local window, ESC [5^, O /# Keypad PgUp #/
+ ESC [6~, local window, ESC [6^, O /# Keypad PgDn #/
+ ESC [8~, ESC [8$, ESC [8^, O /# Keypad End #/
+ 11, 11, 11, O /# Keypad 5 #/
+
+ MSYS Console (term=rxvt, ncurses)
+ ==============================
+ normal shift ctrl alt
+ KEY_LEFT, KEY_SLEFT, 514 nothing /# Left #/
+ KEY_RIGHT, KEY_SRIGHT, 516, nothing /# Right #/
+ KEY_UP, 518, 519, nothing /# Up #/
+ KEY_DOWN, 511, 512, nothing /# Down #/
+ KEY_HOME, KEY_SHOME, ESC [7^, nothing /# Home #/
+ KEY_PPAGE, local window, ESC [5^, nothing /# Page Up #/
+ KEY_NPAGE, local window, ESC [6^, nothing /# Page Down #/
+ KEY_END, KEY_SEND, KEY_EOL, nothing /# End #/
+ KEY_LEFT, KEY_SLEFT, 514 O /# Keypad Left #/
+ KEY_RIGHT, KEY_SRIGHT, 516, O /# Keypad Right #/
+ KEY_UP, 518, 519, O /# Keypad Up #/
+ KEY_DOWN, 511, 512, O /# Keypad Down #/
+ KEY_HOME, KEY_SHOME, ESC [7^, O /# Keypad Home #/
+ KEY_PPAGE, local window, ESC [5^, O /# Keypad PgUp #/
+ KEY_NPAGE, local window, ESC [6^, O /# Keypad PgDn #/
+ KEY_END, KEY_SEND, KEY_EOL, O /# Keypad End #/
+ 11, 11, 11, O /# Keypad 5 #/
+
+ Win32 Console (raw, pdcurses)
+ DJGPP Console (raw, pdcurses)
+ ==============================
+ normal shift ctrl alt
+ 260, 391, 443, 493 /# Left #/
+ 261, 400, 444, 492 /# Right #/
+ 259, 547, 480, 490 /# Up #/
+ 258, 548, 481, 491 /# Down #/
+ 262, 388, 447, 524 /# Home #/
+ 339, 396, 445, 526 /# Page Up #/
+ 338, 394, 446, 520 /# Page Down #/
+ 358, 384, 448, 518 /# End #/
+ 452, 52('4'), 511, 521 /# Keypad Left #/
+ 454, 54('6'), 513, 523 /# Keypad Right #/
+ 450, 56('8'), 515, 525 /# Keypad Up #/
+ 456, 50('2'), 509, 519 /# Keypad Down #/
+ 449, 55('7'), 514, 524 /# Keypad Home #/
+ 451, 57('9'), 516, 526 /# Keypad PgUp #/
+ 457, 51('3'), 510, 520 /# Keypad PgDn #/
+ 455, 49('1'), 508, 518 /# Keypad End #/
+ 453, 53('5'), 512, 522 /# Keypad 5 #/
+
+ Win32 Console (pdcurses, MSVC/MingW32)
+ DJGPP Console (pdcurses)
+ ==============================
+ normal shift ctrl alt
+ KEY_LEFT, KEY_SLEFT, CTL_LEFT, ALT_LEFT /# Left #/
+ KEY_RIGHT, KEY_SRIGHT, CTL_RIGHT, ALT_RIGHT /# Right #/
+ KEY_UP, KEY_SUP, CTL_UP, ALT_UP /# Up #/
+ KEY_DOWN, KEY_SDOWN, CTL_DOWN, ALT_DOWN /# Down #/
+ KEY_HOME, KEY_SHOME, CTL_HOME, ALT_HOME /# Home #/
+ KEY_PPAGE, KEY_SPREVIOUS, CTL_PGUP, ALT_PGUP /# Page Up #/
+ KEY_NPAGE, KEY_SNEXTE, CTL_PGDN, ALT_PGDN /# Page Down #/
+ KEY_END, KEY_SEND, CTL_END, ALT_END /# End #/
+ KEY_B1, 52('4'), CTL_PAD4, ALT_PAD4 /# Keypad Left #/
+ KEY_B3, 54('6'), CTL_PAD6, ALT_PAD6 /# Keypad Right #/
+ KEY_A2, 56('8'), CTL_PAD8, ALT_PAD8 /# Keypad Up #/
+ KEY_C2, 50('2'), CTL_PAD2, ALT_PAD2 /# Keypad Down #/
+ KEY_A1, 55('7'), CTL_PAD7, ALT_PAD7 /# Keypad Home #/
+ KEY_A3, 57('9'), CTL_PAD9, ALT_PAD9 /# Keypad PgUp #/
+ KEY_C3, 51('3'), CTL_PAD3, ALT_PAD3 /# Keypad PgDn #/
+ KEY_C1, 49('1'), CTL_PAD1, ALT_PAD1 /# Keypad End #/
+ KEY_B2, 53('5'), CTL_PAD5, ALT_PAD5 /# Keypad 5 #/
+
+ Windows Telnet (raw)
+ ==============================
+ normal shift ctrl alt
+ ESC [D, ESC [D, ESC [D, ESC [D /# Left #/
+ ESC [C, ESC [C, ESC [C, ESC [C /# Right #/
+ ESC [A, ESC [A, ESC [A, ESC [A /# Up #/
+ ESC [B, ESC [B, ESC [B, ESC [B /# Down #/
+ ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Home #/
+ ESC [5~, ESC [5~, ESC [5~, ESC [5~ /# Page Up #/
+ ESC [6~, ESC [6~, ESC [6~, ESC [6~ /# Page Down #/
+ ESC [4~, ESC [4~, ESC [4~, ESC [4~ /# End #/
+ ESC [D, ESC [D, ESC [D, ESC [D /# Keypad Left #/
+ ESC [C, ESC [C, ESC [C, ESC [C /# Keypad Right #/
+ ESC [A, ESC [A, ESC [A, ESC [A /# Keypad Up #/
+ ESC [B, ESC [B, ESC [B, ESC [B /# Keypad Down #/
+ ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Keypad Home #/
+ ESC [5~, ESC [5~, ESC [5~, ESC [5~ /# Keypad PgUp #/
+ ESC [6~, ESC [6~, ESC [6~, ESC [6~ /# Keypad PgDn #/
+ ESC [4~, ESC [4~, ESC [4~, ESC [4~ /# Keypad End #/
+ nothing, nothing, nothing, nothing /# Keypad 5 #/
+
+ Windows Telnet (term=xterm)
+ ==============================
+ normal shift ctrl alt
+ KEY_LEFT, KEY_LEFT, KEY_LEFT, KEY_LEFT /# Left #/
+ KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, KEY_RIGHT /# Right #/
+ KEY_UP, KEY_UP, KEY_UP, KEY_UP /# Up #/
+ KEY_DOWN, KEY_DOWN, KEY_DOWN, KEY_DOWN /# Down #/
+ ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Home #/
+ KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, KEY_PPAGE /# Page Up #/
+ KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, KEY_NPAGE /# Page Down #/
+ ESC [4~, ESC [4~, ESC [4~, ESC [4~ /# End #/
+ KEY_LEFT, KEY_LEFT, KEY_LEFT, O /# Keypad Left #/
+ KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, O /# Keypad Right #/
+ KEY_UP, KEY_UP, KEY_UP, O /# Keypad Up #/
+ KEY_DOWN, KEY_DOWN, KEY_DOWN, O /# Keypad Down #/
+ ESC [1~, ESC [1~, ESC [1~, ESC [1~ /# Keypad Home #/
+ KEY_PPAGE, KEY_PPAGE, KEY_PPAGE, KEY_PPAGE /# Keypad PgUp #/
+ KEY_NPAGE, KEY_NPAGE, KEY_NPAGE, KEY_NPAGE /# Keypad PgDn #/
+ ESC [4~, ESC [4~, ESC [4~, O /# Keypad End #/
+ ESC [-71, nothing, nothing, O /# Keypad 5 #/
+
+ PuTTY
+ ==============================
+ normal shift ctrl alt
+ ESC [D, ESC [D, ESC OD, ESC [D /# Left #/
+ ESC [C, ESC [C, ESC OC, ESC [C /# Right #/
+ ESC [A, ESC [A, ESC OA, ESC [A /# Up #/
+ ESC [B, ESC [B, ESC OB, ESC [B /# Down #/
+ ESC [1~, ESC [1~, local win, ESC [1~ /# Home #/
+ ESC [5~, local win, local win, ESC [5~ /# Page Up #/
+ ESC [6~, local win, local win, ESC [6~ /# Page Down #/
+ ESC [4~, ESC [4~, local win, ESC [4~ /# End #/
+ ESC [D, ESC [D, ESC [D, O /# Keypad Left #/
+ ESC [C, ESC [C, ESC [C, O /# Keypad Right #/
+ ESC [A, ESC [A, ESC [A, O /# Keypad Up #/
+ ESC [B, ESC [B, ESC [B, O /# Keypad Down #/
+ ESC [1~, ESC [1~, ESC [1~, O /# Keypad Home #/
+ ESC [5~, ESC [5~, ESC [5~, O /# Keypad PgUp #/
+ ESC [6~, ESC [6~, ESC [6~, O /# Keypad PgDn #/
+ ESC [4~, ESC [4~, ESC [4~, O /# Keypad End #/
+ nothing, nothing, nothing, O /# Keypad 5 #/
+
+ PuTTY
+ ==============================
+ normal shift ctrl alt
+ KEY_LEFT, KEY_LEFT, ESC OD, ESC KEY_LEFT /# Left #/
+ KEY_RIGHT KEY_RIGHT, ESC OC, ESC KEY_RIGHT /# Right #/
+ KEY_UP, KEY_UP, ESC OA, ESC KEY_UP /# Up #/
+ KEY_DOWN, KEY_DOWN, ESC OB, ESC KEY_DOWN /# Down #/
+ ESC [1~, ESC [1~, local win, ESC ESC [1~ /# Home #/
+ KEY_PPAGE local win, local win, ESC KEY_PPAGE /# Page Up #/
+ KEY_NPAGE local win, local win, ESC KEY_NPAGE /# Page Down #/
+ ESC [4~, ESC [4~, local win, ESC ESC [4~ /# End #/
+ ESC Ot, ESC Ot, ESC Ot, O /# Keypad Left #/
+ ESC Ov, ESC Ov, ESC Ov, O /# Keypad Right #/
+ ESC Ox, ESC Ox, ESC Ox, O /# Keypad Up #/
+ ESC Or, ESC Or, ESC Or, O /# Keypad Down #/
+ ESC Ow, ESC Ow, ESC Ow, O /# Keypad Home #/
+ ESC Oy, ESC Oy, ESC Oy, O /# Keypad PgUp #/
+ ESC Os, ESC Os, ESC Os, O /# Keypad PgDn #/
+ ESC Oq, ESC Oq, ESC Oq, O /# Keypad End #/
+ ESC Ou, ESC Ou, ESC Ou, O /# Keypad 5 #/
+*/
+
+#define M_NORMAL 0
+#define M_ESC 1
+#define M_KEYPAD 2
+#define M_TRAIL 3
+
+int
+md_readchar(WINDOW *win)
+{
+ int ch = 0;
+ int lastch = 0;
+ int mode = M_NORMAL;
+ int mode2 = M_NORMAL;
+
+ while(1)
+ {
+ ch = wgetch(win);
+
+ if (ch == ERR) /* timed out waiting for valid sequence */
+ { /* flush input so far and start over */
+ mode = M_NORMAL;
+ nocbreak();
+ raw();
+ ch = 27;
+ break;
+ }
+
+ if (mode == M_TRAIL)
+ {
+ if (ch == '^') /* msys console : 7,5,6,8: modified*/
+ ch = MOD_MOVE( toupper(lastch) );
+
+ if (ch == '~') /* cygwin console: 1,5,6,4: normal */
+ ch = tolower(lastch); /* windows telnet: 1,5,6,4: normal */
+ /* msys console : 7,5,6,8: normal */
+
+ if (mode2 == M_ESC) /* cygwin console: 1,5,6,4: modified*/
+ ch = MOD_MOVE( toupper(ch) );
+
+ break;
+ }
+
+ if (mode == M_ESC)
+ {
+ if (ch == 27)
+ {
+ mode2 = M_ESC;
+ continue;
+ }
+
+ if ((ch == 'F') || (ch == 'O') || (ch == '['))
+ {
+ mode = M_KEYPAD;
+ continue;
+ }
+
+
+ switch(ch)
+ {
+ /* Cygwin Console */
+ /* PuTTY */
+ case KEY_LEFT : ch = MOD_MOVE('H'); break;
+ case KEY_RIGHT: ch = MOD_MOVE('L'); break;
+ case KEY_UP : ch = MOD_MOVE('K'); break;
+ case KEY_DOWN : ch = MOD_MOVE('J'); break;
+ case KEY_HOME : ch = MOD_MOVE('Y'); break;
+ case KEY_PPAGE: ch = MOD_MOVE('U'); break;
+ case KEY_NPAGE: ch = MOD_MOVE('N'); break;
+ case KEY_END : ch = MOD_MOVE('B'); break;
+
+ default: break;
+ }
+
+ break;
+ }
+
+ if (mode == M_KEYPAD)
+ {
+ switch(ch)
+ {
+ /* ESC F - Interix Console codes */
+ case '^': ch = MOD_MOVE('H'); break; /* Shift-Left */
+ case '$': ch = MOD_MOVE('L'); break; /* Shift-Right */
+
+ /* ESC [ - Interix Console codes */
+ case 'H': ch = 'y'; break; /* Home */
+ case 1: ch = MOD_MOVE('K'); break; /* Ctl-Keypad Up */
+ case 2: ch = MOD_MOVE('J'); break; /* Ctl-Keypad Down */
+ case 3: ch = MOD_MOVE('L'); break; /* Ctl-Keypad Right */
+ case 4: ch = MOD_MOVE('H'); break; /* Ctl-Keypad Left */
+ case 263: ch = MOD_MOVE('Y'); break; /* Ctl-Keypad Home */
+ case 19: ch = MOD_MOVE('U'); break; /* Ctl-Keypad PgUp */
+ case 20: ch = MOD_MOVE('N'); break; /* Ctl-Keypad PgDn */
+ case 21: ch = MOD_MOVE('B'); break; /* Ctl-Keypad End */
+
+ /* ESC [ - Cygwin Console codes */
+ case 'G': ch = '.'; break; /* Keypad 5 */
+ case '7': lastch = 'Y'; mode=M_TRAIL; break; /* Ctl-Home */
+ case '5': lastch = 'U'; mode=M_TRAIL; break; /* Ctl-PgUp */
+ case '6': lastch = 'N'; mode=M_TRAIL; break; /* Ctl-PgDn */
+
+ /* ESC [ - Win32 Telnet, PuTTY */
+ case '1': lastch = 'y'; mode=M_TRAIL; break; /* Home */
+ case '4': lastch = 'b'; mode=M_TRAIL; break; /* End */
+
+ /* ESC O - PuTTY */
+ case 'D': ch = MOD_MOVE('H'); break;
+ case 'C': ch = MOD_MOVE('L'); break;
+ case 'A': ch = MOD_MOVE('K'); break;
+ case 'B': ch = MOD_MOVE('J'); break;
+ case 't': ch = 'h'; break;
+ case 'v': ch = 'l'; break;
+ case 'x': ch = 'k'; break;
+ case 'r': ch = 'j'; break;
+ case 'w': ch = 'y'; break;
+ case 'y': ch = 'u'; break;
+ case 's': ch = 'n'; break;
+ case 'q': ch = 'b'; break;
+ case 'u': ch = '.'; break;
+ }
+
+ if (mode != M_KEYPAD)
+ continue;
+ }
+
+ if (ch == 27)
+ {
+ halfdelay(1);
+ mode = M_ESC;
+ continue;
+ }
+
+ switch(ch)
+ {
+ case KEY_LEFT : ch = 'h'; break;
+ case KEY_DOWN : ch = 'j'; break;
+ case KEY_UP : ch = 'k'; break;
+ case KEY_RIGHT : ch = 'l'; break;
+ case KEY_HOME : ch = 'y'; break;
+ case KEY_PPAGE : ch = 'u'; break;
+ case KEY_END : ch = 'b'; break;
+#ifdef KEY_LL
+ case KEY_LL : ch = 'b'; break;
+#endif
+ case KEY_NPAGE : ch = 'n'; break;
+
+#ifdef KEY_B1
+ case KEY_B1 : ch = 'h'; break;
+ case KEY_C2 : ch = 'j'; break;
+ case KEY_A2 : ch = 'k'; break;
+ case KEY_B3 : ch = 'l'; break;
+#endif
+ case KEY_A1 : ch = 'y'; break;
+ case KEY_A3 : ch = 'u'; break;
+ case KEY_C1 : ch = 'b'; break;
+ case KEY_C3 : ch = 'n'; break;
+ /* next should be '.', but for problem with putty/linux */
+ case KEY_B2 : ch = 'u'; break;
+
+#ifdef KEY_SLEFT
+ case KEY_SRIGHT : ch = MOD_MOVE('L'); break;
+ case KEY_SLEFT : ch = MOD_MOVE('H'); break;
+#ifdef KEY_SUP
+ case KEY_SUP : ch = MOD_MOVE('K'); break;
+ case KEY_SDOWN : ch = MOD_MOVE('J'); break;
+#endif
+ case KEY_SHOME : ch = MOD_MOVE('Y'); break;
+ case KEY_SPREVIOUS:ch = MOD_MOVE('U'); break;
+ case KEY_SEND : ch = MOD_MOVE('B'); break;
+ case KEY_SNEXT : ch = MOD_MOVE('N'); break;
+#endif
+ case 0x146 : ch = MOD_MOVE('K'); break; /* Shift-Up */
+ case 0x145 : ch = MOD_MOVE('J'); break; /* Shift-Down */
+
+#ifdef CTL_RIGHT
+ case CTL_RIGHT : ch = MOD_MOVE('L'); break;
+ case CTL_LEFT : ch = MOD_MOVE('H'); break;
+ case CTL_UP : ch = MOD_MOVE('K'); break;
+ case CTL_DOWN : ch = MOD_MOVE('J'); break;
+ case CTL_HOME : ch = MOD_MOVE('Y'); break;
+ case CTL_PGUP : ch = MOD_MOVE('U'); break;
+ case CTL_END : ch = MOD_MOVE('B'); break;
+ case CTL_PGDN : ch = MOD_MOVE('N'); break;
+#endif
+#ifdef KEY_EOL
+ case KEY_EOL : ch = MOD_MOVE('B'); break;
+#endif
+
+#ifndef CTL_PAD1
+ /* MSYS rxvt console */
+ case 511 : ch = MOD_MOVE('J'); break; /* Shift Dn */
+ case 512 : ch = MOD_MOVE('J'); break; /* Ctl Down */
+ case 514 : ch = MOD_MOVE('H'); break; /* Ctl Left */
+ case 516 : ch = MOD_MOVE('L'); break; /* Ctl Right*/
+ case 518 : ch = MOD_MOVE('K'); break; /* Shift Up */
+ case 519 : ch = MOD_MOVE('K'); break; /* Ctl Up */
+#endif
+
+#ifdef CTL_PAD1
+ case CTL_PAD1 : ch = MOD_MOVE('B'); break;
+ case CTL_PAD2 : ch = MOD_MOVE('J'); break;
+ case CTL_PAD3 : ch = MOD_MOVE('N'); break;
+ case CTL_PAD4 : ch = MOD_MOVE('H'); break;
+ case CTL_PAD5 : ch = '.'; break;
+ case CTL_PAD6 : ch = MOD_MOVE('L'); break;
+ case CTL_PAD7 : ch = MOD_MOVE('Y'); break;
+ case CTL_PAD8 : ch = MOD_MOVE('K'); break;
+ case CTL_PAD9 : ch = MOD_MOVE('U'); break;
+#endif
+
+#ifdef ALT_RIGHT
+ case ALT_RIGHT : ch = MOD_MOVE('L'); break;
+ case ALT_LEFT : ch = MOD_MOVE('H'); break;
+ case ALT_DOWN : ch = MOD_MOVE('J'); break;
+ case ALT_HOME : ch = MOD_MOVE('Y'); break;
+ case ALT_PGUP : ch = MOD_MOVE('U'); break;
+ case ALT_END : ch = MOD_MOVE('B'); break;
+ case ALT_PGDN : ch = MOD_MOVE('N'); break;
+#endif
+
+#ifdef ALT_PAD1
+ case ALT_PAD1 : ch = MOD_MOVE('B'); break;
+ case ALT_PAD2 : ch = MOD_MOVE('J'); break;
+ case ALT_PAD3 : ch = MOD_MOVE('N'); break;
+ case ALT_PAD4 : ch = MOD_MOVE('H'); break;
+ case ALT_PAD5 : ch = '.'; break;
+ case ALT_PAD6 : ch = MOD_MOVE('L'); break;
+ case ALT_PAD7 : ch = MOD_MOVE('Y'); break;
+ case ALT_PAD8 : ch = MOD_MOVE('K'); break;
+ case ALT_PAD9 : ch = MOD_MOVE('U'); break;
+#endif
+ }
+
+ break;
+ }
+
+ nocbreak(); /* disable halfdelay mode if on */
+ raw();
+
+ return(ch & 0x7F);
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/misc.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/misc.c Fri May 08 15:24:40 2015 -0400
@@ -0,0 +1,1202 @@
+/*
+ * misc.c - routines dealing specifically with miscellaneous magic
+ *
+ * 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
+#include "rogue.h"
+#ifdef PC7300
+#include "menu.h"
+#endif
+
+/*
+ * routines dealing specifically with miscellaneous magic
+ */
+
+/*
+ * changeclass:
+ * Change the player's class to the specified one.
+ */
+
+changeclass(newclass)
+int newclass;
+{
+ if (newclass == player.t_ctype) {
+ msg("You feel more skillful.");
+ raise_level();
+ }
+ else {
+ /*
+ * reset his class and then use check_level to reset hit
+ * points and the right level for his exp pts
+ * drop exp pts by 10%
+ */
+ long save;
+
+ msg("You feel like a whole new person!");
+
+ /*
+ * if he becomes a thief he has to have leather armor
+ */
+ if ((newclass == C_THIEF || newclass == C_ASSASIN) &&
+ cur_armor != NULL &&
+ cur_armor->o_which != LEATHER &&
+ cur_armor->o_which != STUDDED_LEATHER )
+ cur_armor->o_which = STUDDED_LEATHER;
+ /*
+ * if he becomes a monk he can't wear armor
+ */
+ if (newclass == C_MONK && cur_armor != NULL) {
+ cur_armor->o_ac = armors[cur_armor->o_which].a_class -
+ cur_armor->o_ac;
+ cur_armor->o_type = MM;
+ cur_armor->o_which = MM_PROTECT;
+ cur_armor->o_flags &= ~(ISPROT | ISKNOW | ISMETAL);
+ cur_misc[WEAR_CLOAK] = cur_armor;
+ cur_armor = NULL;
+ }
+ /*
+ * if he used to be a spell caster of some sort, kill the fuse
+ */
+ if (player.t_ctype == C_MAGICIAN || player.t_ctype == C_RANGER)
+ extinguish(spell_recovery);
+ if (player.t_ctype == C_DRUID || player.t_ctype == C_RANGER)
+ extinguish(chant_recovery);
+ if ((player.t_ctype == C_CLERIC || player.t_ctype == C_PALADIN) &&
+ !cur_relic[HEIL_ANKH])
+ extinguish(prayer_recovery);
+ /*
+ * if he becomes a spell caster of some kind, give him a fuse
+ */
+ if (newclass == C_MAGICIAN || newclass == C_RANGER)
+ fuse(spell_recovery, 0, SPELLTIME, AFTER);
+ if (newclass == C_DRUID || newclass == C_RANGER)
+ fuse(chant_recovery, 0, SPELLTIME, AFTER);
+ if ((newclass==C_CLERIC || newclass==C_PALADIN) && !cur_misc[HEIL_ANKH])
+ fuse(prayer_recovery, 0, SPELLTIME, AFTER);
+ /*
+ * if he's changing from a fighter then may have to change
+ * his sword since only fighter can use two-handed
+ * and bastard swords
+ */
+ if ((player.t_ctype == C_FIGHTER ||
+ player.t_ctype == C_RANGER ||
+ player.t_ctype == C_PALADIN) &&
+ cur_weapon != NULL &&
+ cur_weapon->o_type == WEAPON &&
+ (cur_weapon->o_which== BASWORD ||
+ cur_weapon->o_which== TWOSWORD ) &&
+ !(newclass == C_FIGHTER ||
+ newclass == C_RANGER ||
+ newclass == C_PALADIN) &&
+ !(newclass == C_ASSASIN &&
+ cur_weapon->o_which == BASWORD))
+ cur_weapon->o_which = SWORD;
+
+ /*
+ * if he was a thief then take out the trap_look() daemon
+ */
+ if (player.t_ctype == C_THIEF ||
+ player.t_ctype == C_MONK ||
+ player.t_ctype == C_ASSASIN)
+ kill_daemon(trap_look);
+
+ /*
+ * if he becomes a thief then add the trap_look() daemon
+ */
+ if (newclass == C_THIEF || newclass == C_ASSASIN || newclass == C_MONK)
+ daemon(trap_look, 0, AFTER);
+ char_type = player.t_ctype = newclass;
+ save = pstats.s_hpt;
+ max_stats.s_hpt = pstats.s_hpt = 0;
+ max_stats.s_lvl = pstats.s_lvl = 0;
+ max_stats.s_lvladj = pstats.s_lvladj = 0;
+ max_stats.s_exp = pstats.s_exp -= pstats.s_exp/10;
+ check_level();
+ if (pstats.s_hpt > save) /* don't add to current hits */
+ pstats.s_hpt = save;
+ }
+}
+
+/*
+ * Use the relic that our monster is wielding.
+ */
+m_use_relic(monster)
+register struct thing *monster;
+{
+ register struct object *obj;
+
+ /* Make sure we really have it */
+ if (monster->t_using) obj = OBJPTR(monster->t_using);
+ else {
+ debug("Relic not set!");
+ monster->t_action = A_NIL;
+ return;
+ }
+
+ /* Now let's see what we're using */
+ if (obj->o_type == RELIC) switch (obj->o_which) {
+ case MING_STAFF: {
+ static struct object missile = {
+ MISSILE, {0,0}, "", 0, "", "0d4 " , NULL, 0, WS_MISSILE, 100, 1
+ };
+
+ debug("Firing Ming's staff");
+ sprintf(missile.o_hurldmg, "%dd4", monster->t_stats.s_lvl);
+ do_motion(&missile,
+ monster->t_newpos.y, monster->t_newpos.x, monster);
+ hit_monster(unc(missile.o_pos), &missile, monster);
+ monster->t_artifact = monster->t_artifact * 4 / 5;
+ }
+ when EMORI_CLOAK:
+ debug("stunning with Emori's cloak");
+ do_zap(monster, obj, &monster->t_newpos, WS_PARALYZE, NULL);
+ obj->o_charges = 0;
+
+ when ASMO_ROD: {
+ char *name;
+
+ switch (rnd(3)) { /* Select a function */
+ case 0: name = "lightning bolt";
+ when 1: name = "flame";
+ otherwise: name = "ice";
+ }
+ shoot_bolt( monster,
+ monster->t_pos,
+ monster->t_newpos,
+ FALSE,
+ monster->t_index,
+ name,
+ roll(monster->t_stats.s_lvl,6));
+ monster->t_artifact /= 2;
+ }
+ when BRIAN_MANDOLIN:
+ /* Make sure the defendant is still around */
+ if (DISTANCE(monster->t_pos.y, monster->t_pos.x,
+ hero.y, hero.x) < 25) {
+ if (!save(VS_MAGIC, &player, -4) &&
+ !ISWEARING(R_ALERT)) {
+ msg("Some beautiful music enthralls you.");
+ player.t_no_move += movement(&player) * FREEZETIME;
+ player.t_action = A_FREEZE;
+ monster->t_artifact = monster->t_artifact * 2 / 3;
+ }
+ else {
+ msg("You wince at a sour note.");
+ monster->t_artifact /= 3;
+ }
+ }
+ when GERYON_HORN:
+ /* Make sure the defendant is still around */
+ if (DISTANCE(monster->t_pos.y, monster->t_pos.x,
+ hero.y, hero.x) < 25) {
+ if (!ISWEARING(R_HEROISM) &&
+ !save(VS_MAGIC, &player, -4)) {
+ turn_on(player, ISFLEE);
+ player.t_dest = &monster->t_pos;
+ msg("A shrill blast terrifies you.");
+ monster->t_artifact = monster->t_artifact * 3 / 4;
+ }
+ else {
+ msg("A shrill blast sends chills up your spine.");
+ monster->t_artifact /= 3;
+ }
+ }
+
+ otherwise:
+ /* Unknown RELIC! */
+ debug("Unknown wielded relic %d", obj->o_which);
+ }
+ else debug("Declared relic is %d", obj->o_type);
+
+ turn_off(*monster, CANSURPRISE);
+ /* Reset the monsters actions */
+ monster->t_action = A_NIL;
+ monster->t_using = NULL;
+}
+
+/*
+ * add something to the contents of something else
+ */
+put_contents(bag, item)
+register struct object *bag; /* the holder of the items */
+register struct linked_list *item; /* the item to put inside */
+{
+ register struct linked_list *titem;
+ register struct object *tobj;
+
+ bag->o_ac++;
+ tobj = OBJPTR(item);
+ for (titem = bag->contents; titem != NULL; titem = next(titem)) {
+ if ((OBJPTR(titem))->o_which == tobj->o_which)
+ break;
+ }
+ if (titem == NULL) { /* if not a duplicate put at beginning */
+ attach(bag->contents, item);
+ }
+ else {
+ item->l_prev = titem;
+ item->l_next = titem->l_next;
+ if (next(titem) != NULL)
+ (titem->l_next)->l_prev = item;
+ titem->l_next = item;
+ }
+}
+
+/*
+ * remove something from something else
+ */
+take_contents(bag, item)
+register struct object *bag; /* the holder of the items */
+register struct linked_list *item;
+{
+
+ if (bag->o_ac <= 0) {
+ msg("Nothing to take out");
+ return;
+ }
+ bag->o_ac--;
+ detach(bag->contents, item);
+ if (!add_pack(item, FALSE, NULL))
+ put_contents(bag, item);
+}
+
+
+do_bag(item)
+register struct linked_list *item;
+{
+
+ register struct linked_list *titem;
+ register struct object *obj, *tobj;
+ bool doit = TRUE;
+
+ obj = OBJPTR(item);
+ while (doit) {
+ msg("What do you want to do? (* for a list): ");
+ mpos = 0;
+ switch (readchar()) {
+ case EOF:
+ case ESCAPE:
+ msg ("");
+ doit = FALSE;
+ when '1':
+ inventory(obj->contents, ALL);
+
+ when '2':
+ if (obj->o_ac >= MAXCONTENTS) {
+ msg("the %s is full", m_magic[obj->o_which].mi_name);
+ break;
+ }
+ switch (obj->o_which) {
+ case MM_BEAKER:
+ titem = get_item(pack, "put in", POTION, FALSE, FALSE);
+ when MM_BOOK:
+ titem = get_item(pack, "put in", SCROLL, FALSE, FALSE);
+ }
+ if (titem == NULL)
+ break;
+ detach(pack, titem);
+ inpack--;
+ put_contents(obj, titem);
+
+ when '3':
+ titem = get_item(obj->contents,"take out",ALL,FALSE,FALSE);
+ if (titem == NULL)
+ break;
+ take_contents(obj, titem);
+
+ when '4':
+ switch (obj->o_which) {
+ case MM_BEAKER:
+ titem = get_item(obj->contents,"quaff",ALL,FALSE,FALSE);
+ if (titem == NULL)
+ break;
+ tobj = OBJPTR(titem);
+ obj->o_ac--;
+ detach(obj->contents, titem);
+ quaff(tobj->o_which,
+ tobj->o_kind,
+ tobj->o_flags,
+ TRUE);
+ if (p_know[tobj->o_which] && p_guess[tobj->o_which])
+ {
+ free(p_guess[tobj->o_which]);
+ p_guess[tobj->o_which] = NULL;
+ }
+ else if (!p_know[tobj->o_which] &&
+ askme &&
+ (tobj->o_flags & ISKNOW) == 0 &&
+ (tobj->o_flags & ISPOST) == 0 &&
+ p_guess[tobj->o_which] == NULL) {
+ nameitem(titem, FALSE);
+ }
+ o_discard(titem);
+ when MM_BOOK:
+ if (on(player, ISBLIND)) {
+ msg("You can't see to read anything");
+ break;
+ }
+ titem = get_item(obj->contents,"read",ALL,FALSE,FALSE);
+ if (titem == NULL)
+ break;
+ tobj = OBJPTR(titem);
+ obj->o_ac--;
+ detach(obj->contents, titem);
+ read_scroll(tobj->o_which,
+ tobj->o_flags & (ISCURSED|ISBLESSED),
+ TRUE);
+ if (s_know[tobj->o_which] && s_guess[tobj->o_which])
+ {
+ free(s_guess[tobj->o_which]);
+ s_guess[tobj->o_which] = NULL;
+ }
+ else if (!s_know[tobj->o_which] &&
+ askme &&
+ (tobj->o_flags & ISKNOW) == 0 &&
+ (tobj->o_flags & ISPOST) == 0 &&
+ s_guess[tobj->o_which] == NULL) {
+ nameitem(titem, FALSE);
+ }
+ o_discard(titem);
+ }
+ doit = FALSE;
+
+ otherwise:
+ wclear(hw);
+ touchwin(hw);
+ mvwaddstr(hw,0,0,"The following operations are available:");
+ mvwaddstr(hw,2,0,"[1]\tInventory\n");
+ wprintw(hw,"[2]\tPut something in the %s\n",
+ m_magic[obj->o_which].mi_name);
+ wprintw(hw,"[3]\tTake something out of the %s\n",
+ m_magic[obj->o_which].mi_name);
+ switch(obj->o_which) {
+ case MM_BEAKER: waddstr(hw,"[4]\tQuaff a potion\n");
+ when MM_BOOK: waddstr(hw,"[4]\tRead a scroll\n");
+ }
+ waddstr(hw,"[ESC]\tLeave this menu\n");
+ mvwaddstr(hw, lines-1, 0, spacemsg);
+ draw(hw);
+ wait_for (' ');
+ clearok(cw, TRUE);
+ touchwin(cw);
+ }
+ }
+}
+
+do_panic(who)
+int who; /* Kind of monster to panic (all if who is NULL) */
+{
+ register int x,y;
+ register struct linked_list *mon, *item;
+ register struct thing *th;
+
+ 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) {
+ th = THINGPTR(mon);
+
+ /* Is this the right kind of monster to panic? */
+ if (who && th->t_index != who) continue;
+
+ if (who ||
+ (!on(*th, ISUNDEAD) && !save(VS_MAGIC, th, 0) && off(*th, WASTURNED))) {
+ msg("%s %s.", prname(monster_name(th), TRUE),
+ terse ? "panics" : "turns to run in panic");
+
+ turn_on(*th, ISFLEE);
+ turn_on(*th, WASTURNED);
+ turn_off(*th, CANSURPRISE);
+
+ /* Disrupt what it was doing */
+ dsrpt_monster(th, TRUE, TRUE);
+
+ /* If monster was suffocating, stop it */
+ if (on(*th, DIDSUFFOCATE)) {
+ turn_off(*th, DIDSUFFOCATE);
+ extinguish(suffocate);
+ }
+
+ /* If monster held us, stop it */
+ if (on(*th, DIDHOLD) && (--hold_count == 0))
+ turn_off(player, ISHELD);
+ turn_off(*th, DIDHOLD);
+
+ /*
+ * if he has something he might drop it
+ */
+ if ((item = th->t_pack) != NULL &&
+ (OBJPTR(item))->o_type != RELIC &&
+ rnd(100) < 50) {
+ detach(th->t_pack, item);
+ fall(item, FALSE);
+ }
+
+ /* It is okay to turn tail */
+ th->t_oldpos = th->t_pos;
+ }
+ runto(th, &hero);
+ }
+ }
+ }
+ }
+}
+
+/*
+ * print miscellaneous magic bonuses
+ */
+char *
+misc_name(obj)
+register struct object *obj;
+{
+ static char buf[LINELEN];
+ char buf1[LINELEN];
+
+ buf[0] = '\0';
+ buf1[0] = '\0';
+ if (!(obj->o_flags & ISKNOW))
+ return (m_magic[obj->o_which].mi_name);
+ switch (obj->o_which) {
+ case MM_BRACERS:
+ case MM_PROTECT:
+ strcat(buf, num(obj->o_ac, 0));
+ strcat(buf, " ");
+ }
+ switch (obj->o_which) {
+ case MM_G_OGRE:
+ case MM_G_DEXTERITY:
+ case MM_JEWEL:
+ case MM_STRANGLE:
+ case MM_R_POWERLESS:
+ case MM_DANCE:
+ if (obj->o_flags & ISCURSED)
+ strcat(buf, "cursed ");
+ }
+ strcat(buf, m_magic[obj->o_which].mi_name);
+ switch (obj->o_which) {
+ case MM_JUG:
+ if (obj->o_ac == JUG_EMPTY)
+ strcat(buf1, " [empty]");
+ else if (p_know[obj->o_ac])
+ sprintf(buf1, " [containing a potion of %s (%s)]",
+ p_magic[obj->o_ac].mi_name,
+ p_colors[obj->o_ac]);
+ else sprintf(buf1, " [containing a%s %s liquid]",
+ vowelstr(p_colors[obj->o_ac]),
+ p_colors[obj->o_ac]);
+ when MM_BEAKER:
+ case MM_BOOK: {
+ sprintf(buf1, " [containing %d]", obj->o_ac);
+ }
+ when MM_OPEN:
+ case MM_HUNGER:
+ sprintf(buf1, " [%d ring%s]", obj->o_charges,
+ obj->o_charges == 1 ? "" : "s");
+ when MM_DRUMS:
+ sprintf(buf1, " [%d beat%s]", obj->o_charges,
+ obj->o_charges == 1 ? "" : "s");
+ when MM_DISAPPEAR:
+ case MM_CHOKE:
+ sprintf(buf1, " [%d pinch%s]", obj->o_charges,
+ obj->o_charges == 1 ? "" : "es");
+ when MM_KEOGHTOM:
+ sprintf(buf1, " [%d application%s]", obj->o_charges,
+ obj->o_charges == 1 ? "" : "s");
+ when MM_SKILLS:
+ sprintf(buf1, " [%s]", char_class[obj->o_ac].name);
+ }
+ strcat (buf, buf1);
+ return buf;
+}
+
+use_emori()
+{
+ char selection; /* Cloak function */
+ int state = 0; /* Menu state */
+
+ msg("What do you want to do? (* for a list): ");
+ do {
+ selection = tolower(readchar());
+ switch (selection) {
+ case '*':
+ if (state != 1) {
+ wclear(hw);
+ touchwin(hw);
+ mvwaddstr(hw, 2, 0, "[1] Fly\n[2] Stop flying\n");
+ waddstr(hw, "[3] Turn invisible\n[4] Turn Visible\n");
+ mvwaddstr(hw, 0, 0, "What do you want to do? ");
+ draw(hw);
+ state = 1; /* Now in prompt window */
+ }
+ break;
+
+ case ESCAPE:
+ if (state == 1) {
+ clearok(cw, TRUE); /* Set up for redraw */
+ touchwin(cw);
+ }
+ msg("");
+
+ after = FALSE;
+ return;
+
+ when '1':
+ case '2':
+ case '3':
+ case '4':
+ if (state == 1) { /* In prompt window */
+ clearok(cw, TRUE); /* Set up for redraw */
+ touchwin(cw);
+ }
+
+ msg("");
+
+ state = 2; /* Finished */
+ break;
+
+ default:
+ if (state == 1) { /* In the prompt window */
+ mvwaddstr(hw, 0, 0,
+ "Please enter a selection between 1 and 4: ");
+ draw(hw);
+ }
+ else { /* Normal window */
+ mpos = 0;
+ msg("Please enter a selection between 1 and 4: ");
+ }
+ }
+ } while (state != 2);
+
+ /* We now must have a selection between 1 and 4 */
+ switch (selection) {
+ case '1': /* Fly */
+ if (on(player, ISFLY)) {
+ extinguish(land); /* Extinguish in case of potion */
+ msg("%slready flying.", terse ? "A" : "You are a");
+ }
+ else {
+ msg("You feel lighter than air!");
+ turn_on(player, ISFLY);
+ }
+ when '2': /* Stop flying */
+ if (off(player, ISFLY))
+ msg("%sot flying.", terse ? "N" : "You are n");
+ else {
+ if (find_slot(land))
+ msg("%sot flying by the cloak.",
+ terse ? "N" : "You are n");
+ else land();
+ }
+ when '3': /* Turn invisible */
+ if (off(player, ISINVIS)) {
+ turn_on(player, ISINVIS);
+ msg("You have a tingling feeling all over your body");
+ PLAYER = IPLAYER;
+ light(&hero);
+ }
+ else {
+ extinguish(appear); /* Extinguish in case of potion */
+ extinguish(dust_appear);/* dust of disappearance */
+ msg("%slready invisible.", terse ? "A" : "You are a");
+ }
+ when '4': /* Turn visible */
+ if (off(player, ISINVIS))
+ msg("%sot invisible.", terse ? "N" : "You are n");
+ else {
+ if (find_slot(appear) || find_slot(dust_appear))
+ msg("%sot invisible by the cloak.",
+ terse ? "N" : "You are n");
+ else appear();
+ }
+ }
+}
+
+#ifdef PC7300
+static menu_t Display; /* The menu structure */
+static mitem_t Dispitems[MAXQUILL+1]; /* Info for each line */
+static char Displines[MAXQUILL+1][LINELEN+1]; /* The lines themselves */
+#endif
+/*
+ * try to write a scroll with the quill of Nagrom
+ */
+use_quill(obj)
+struct object *obj;
+{
+ struct linked_list *item;
+ register int i,
+ scroll_ability;
+ int which_scroll,
+ curlen,
+ maxlen,
+ dummy;
+ bool nohw = FALSE;
+
+ i = which_scroll = 0;
+ scroll_ability = obj->o_charges;
+
+ /* Prompt for scrolls */
+ msg("Which scroll are you writing? (* for list): ");
+
+ which_scroll = (int) (readchar() - 'a');
+ if (which_scroll == (int) ESCAPE - (int) 'a') {
+ mpos = 0;
+ msg("");
+ after = FALSE;
+ return;
+ }
+ if (which_scroll >= 0 && which_scroll < MAXQUILL) nohw = TRUE;
+
+ else if (slow_invent) {
+ register char c;
+
+ nohw = TRUE;
+ do {
+ for (i=0; i= MAXQUILL));
+
+ if (which_scroll == (int) (ESCAPE - 'a')) {
+ mpos = 0;
+ msg("");
+ after = FALSE;
+ return;
+ }
+ }
+ else {
+ /* Now display the possible scrolls */
+ wclear(hw);
+ touchwin(hw);
+ mvwaddstr(hw, 2, 0, " Cost Scroll");
+ mvwaddstr(hw, 3, 0,
+ "-----------------------------------------------");
+ maxlen = 47; /* Maximum width of header */
+
+ for (i=0; i= 0) {
+ if (Display.m_selcnt == 0) {
+ /* Menu was cancelled */
+ after = FALSE;
+ return FALSE; /* all done if abort */
+ }
+ else which_scroll = (int) Display.m_curi->mi_val;
+ goto got_scroll;
+ }
+#endif
+ /* Should we overlay? */
+ if (menu_overlay && MAXQUILL + 3 < lines / 2) {
+ over_win(cw, hw, MAXQUILL + 5, maxlen + 3, 0, curlen, NULL);
+ }
+ else draw(hw);
+ }
+
+ if (!nohw) {
+ which_scroll = (int) (readchar() - 'a');
+ while (which_scroll < 0 || which_scroll >= MAXQUILL) {
+ if (which_scroll == (int) ESCAPE - (int) 'a') {
+ after = FALSE;
+
+ /* Restore the screen */
+ touchwin(cw);
+ if (MAXQUILL + 3 < lines / 2) clearok(cw, FALSE);
+ else {
+ msg("");
+ clearok(cw, TRUE);
+ }
+ return;
+ }
+ wmove(hw, 0, 0);
+ wclrtoeol(hw);
+ waddstr(hw, "Please enter one of the listed scrolls. ");
+ getyx(hw, dummy, curlen);
+ if (maxlen < curlen) maxlen = curlen;
+
+ /* Should we overlay? */
+ if (menu_overlay && MAXQUILL + 3 < lines / 2) {
+ over_win(cw, hw, MAXQUILL + 5, maxlen + 3,
+ 0, curlen, NULL);
+ }
+ else draw(hw);
+
+ which_scroll = (int) (readchar() - 'a');
+ }
+ }
+
+ /* Now restore the screen if we have to */
+ if (!nohw) {
+ touchwin(cw);
+ if (MAXQUILL + 3 < lines / 2) clearok(cw, FALSE);
+ else {
+ msg("");
+ clearok(cw, TRUE);
+ }
+ }
+ else msg("");
+
+
+#ifdef PC7300
+got_scroll:
+#endif
+ /* We've waited our required time. */
+ player.t_using = NULL;
+ player.t_action = A_NIL;
+
+ if (quill_scrolls[which_scroll].s_cost > scroll_ability) {
+ msg("Your attempt fails.");
+ return;
+ }
+
+ obj->o_charges -= quill_scrolls[which_scroll].s_cost;
+ item = spec_item(SCROLL, quill_scrolls[which_scroll].s_which, 0, 0);
+ if (add_pack(item, FALSE, NULL) == FALSE) {
+ (OBJPTR(item))->o_pos = hero;
+ fall(item, TRUE);
+ }
+}
+
+use_mm(which)
+int which;
+{
+ register struct object *obj;
+ register struct linked_list *item;
+ bool cursed, blessed, is_mm;
+
+ cursed = FALSE;
+ is_mm = FALSE;
+
+ if (which < 0) { /* A real miscellaneous magic item */
+ /* This is miscellaneous magic. It takes 3 movement periods to use */
+ if (player.t_action != C_USE) {
+ int units; /* Number of movement units for the item */
+
+ item = get_item(pack, "use", USEABLE, FALSE, FALSE);
+
+ /*
+ * Make certain that it is a micellaneous magic item
+ */
+ if (item == NULL)
+ return;
+
+ units = usage_time(item);
+ if (units < 0) return;
+
+ player.t_using = item; /* Remember what it is */
+ player.t_action = C_USE; /* We are quaffing */
+ player.t_no_move = units * movement(&player);
+ return;
+ }
+
+ /* We have waited our time, let's use the item */
+ item = player.t_using;
+ player.t_using = NULL;
+ player.t_action = A_NIL;
+
+ is_mm = TRUE;
+
+ obj = OBJPTR(item);
+ cursed = (obj->o_flags & ISCURSED) != 0;
+ blessed = (obj->o_flags & ISBLESSED) != 0;
+ which = obj->o_which;
+ }
+
+ if (obj->o_type == POTION) { /* An potion */
+ is_mm = FALSE;
+ inpack--;
+ detach (pack, item);
+ switch (obj->o_which) {
+ case P_POISON:
+ if (cur_weapon) {
+ if (cur_weapon->o_type == RELIC) {
+ msg("The poison burns off %s",
+ inv_name(cur_weapon,FALSE));
+ }
+ else {
+ cur_weapon->o_flags |= ISPOISON;
+ msg("Your weapon has %s gooey stuff on it",
+ p_colors[cur_weapon->o_which]);
+ }
+ }
+ else
+ msg("The poison pours on the floor and disappears!");
+ }
+ o_discard(item);
+ }
+ else if (obj->o_type == RELIC) { /* An artifact */
+ is_mm = FALSE;
+ switch (obj->o_which) {
+ case EMORI_CLOAK:
+ use_emori();
+ when QUILL_NAGROM:
+ use_quill(obj);
+ when BRIAN_MANDOLIN:
+ /* Put monsters around us to sleep */
+ read_scroll(S_HOLD, 0, FALSE);
+ when GERYON_HORN:
+ /* Chase close monsters away */
+ msg("The horn blasts a shrill tone.");
+ do_panic(NULL);
+ when HEIL_ANKH:
+ case YENDOR_AMULET:
+ case STONEBONES_AMULET:
+ /* Nothing happens by this mode */
+ msg("Nothing happens.");
+ when EYE_VECNA:
+ msg("The pain subsides...");
+ when SURTUR_RING:
+ /* Panic fire giants */
+ do_panic(findmindex("fire giant"));
+ }
+ }
+ else switch (which) { /* Miscellaneous Magic */
+ /*
+ * the jug of alchemy manufactures potions when you drink
+ * the potion it will make another after a while
+ */
+ case MM_JUG:
+ if (obj->o_ac == JUG_EMPTY) {
+ msg("The jug is empty");
+ break;
+ }
+ quaff (obj->o_ac, NULL, NULL, FALSE);
+ obj->o_ac = JUG_EMPTY;
+ fuse (alchemy, obj, ALCHEMYTIME, AFTER);
+ if (!(obj->o_flags & ISKNOW))
+ whatis(item);
+
+ /*
+ * the beaker of plentiful potions is used to hold potions
+ * the book of infinite spells is used to hold scrolls
+ */
+ when MM_BEAKER:
+ case MM_BOOK:
+ do_bag(item);
+
+ /*
+ * the chime of opening opens up secret doors
+ */
+ when MM_OPEN:
+ {
+ register struct linked_list *exit;
+ register struct room *rp;
+ register coord *cp;
+
+ if (obj->o_charges <= 0) {
+ msg("The chime is cracked!");
+ break;
+ }
+ obj->o_charges--;
+ msg("chime... chime... hime... ime... me... e...");
+ if ((rp = roomin(&hero)) == NULL) {
+ search(FALSE, TRUE); /* Non-failing search for door */
+ break;
+ }
+ for (exit = rp->r_exit; exit != NULL; exit = next(exit)) {
+ cp = DOORPTR(exit);
+ if (winat(cp->y, cp->x) == SECRETDOOR) {
+ mvaddch (cp->y, cp->x, DOOR);
+ if (cansee (cp->y, cp->x))
+ mvwaddch(cw, cp->y, cp->x, DOOR);
+ }
+ }
+ }
+
+ /*
+ * the chime of hunger just makes the hero hungry
+ */
+ when MM_HUNGER:
+ if (obj->o_charges <= 0) {
+ msg("The chime is cracked!");
+ break;
+ }
+ obj->o_charges--;
+ if (food_left >= MORETIME + 5) {
+ food_left = MORETIME + 5;
+ msg(terse? "Getting hungry" : "You are starting to get hungry");
+ hungry_state = F_HUNGRY;
+ }
+ aggravate(TRUE, TRUE);
+
+ /*
+ * the drums of panic make all creatures within two squares run
+ * from the hero in panic unless they save or they are mindless
+ * undead
+ */
+ when MM_DRUMS:
+ if (obj->o_charges <= 0) {
+ msg("The drum is broken!");
+ break;
+ }
+ obj->o_charges--;
+ do_panic(NULL);
+ /*
+ * dust of disappearance makes the player invisible for a while
+ */
+ when MM_DISAPPEAR:
+ m_know[MM_DISAPPEAR] = TRUE;
+ if (obj->o_charges <= 0) {
+ msg("No more dust!");
+ break;
+ }
+ obj->o_charges--;
+ msg("aaAAACHOOOooo. Cough. Cough. Sneeze. Sneeze.");
+ if (!find_slot(dust_appear)) {
+ turn_on(player, ISINVIS);
+ fuse(dust_appear, 0, DUSTTIME, AFTER);
+ PLAYER = IPLAYER;
+ light(&hero);
+ }
+ else lengthen(dust_appear, DUSTTIME);
+
+ /*
+ * dust of choking and sneezing can kill the hero if he misses
+ * the save
+ */
+ when MM_CHOKE:
+ m_know[MM_CHOKE] = TRUE;
+ if (obj->o_charges <= 0) {
+ msg("No more dust!");
+ break;
+ }
+ obj->o_charges--;
+ msg("aaAAACHOOOooo. Cough. Cough. Sneeze. Sneeze.");
+ if (!cur_relic[SURTUR_RING] && !save(VS_POISON, &player, 0)) {
+ msg ("You choke to death!!! --More--");
+ pstats.s_hpt = -1; /* in case he hangs up the phone */
+ wait_for(' ');
+ death(D_CHOKE);
+ }
+ else {
+ msg("You begin to cough and choke uncontrollably");
+ if (find_slot(unchoke))
+ lengthen(unchoke, DUSTTIME);
+ else
+ fuse(unchoke, 0, DUSTTIME, AFTER);
+ turn_on(player, ISHUH);
+ turn_on(player, ISBLIND);
+ light(&hero);
+ }
+
+ when MM_KEOGHTOM:
+ /*
+ * this is a very powerful healing ointment
+ * but it takes a while to put on...
+ */
+ obj->o_charges--;
+ if (on(player, HASDISEASE)) {
+ extinguish(cure_disease);
+ cure_disease();
+ msg(terse ? "You feel yourself improving."
+ : "You begin to feel yourself improving again.");
+ }
+ if (on(player, HASINFEST)) {
+ turn_off(player, HASINFEST);
+ infest_dam = 0;
+ msg(terse ? "You feel yourself improving."
+ : "You begin to feel yourself improving again.");
+ }
+ if (on(player, DOROT)) {
+ msg("You feel your skin returning to normal.");
+ turn_off(player, DOROT);
+ }
+ pstats.s_hpt += roll(pstats.s_lvl, 6);
+ if (pstats.s_hpt > max_stats.s_hpt)
+ pstats.s_hpt = max_stats.s_hpt;
+ sight();
+ msg("You begin to feel much better.");
+
+ /*
+ * The book has a character class associated with it.
+ * if your class matches that of the book, it will raise your
+ * level by one. If your class does not match the one of the book,
+ * it change your class to that of book.
+ * Note that it takes a while to read.
+ */
+ when MM_SKILLS:
+ detach (pack, item);
+ inpack--;
+ changeclass(obj->o_ac);
+
+ otherwise:
+ msg("What a strange magic item you have!");
+ }
+ status(FALSE);
+ if (is_mm && m_know[which] && m_guess[which]) {
+ free(m_guess[which]);
+ m_guess[which] = NULL;
+ }
+ else if (is_mm &&
+ !m_know[which] &&
+ askme &&
+ (obj->o_flags & ISKNOW) == 0 &&
+ m_guess[which] == NULL) {
+ nameitem(item, FALSE);
+ }
+ if (item != NULL && which == MM_SKILLS)
+ o_discard(item);
+ updpack(TRUE, &player);
+}
+
+/*
+ * usage_time:
+ * Return how long it takes to use an item. For now we only give time
+ * for MM, RELIC, SCROLL, and POTION items.
+ */
+
+int
+usage_time(item)
+struct linked_list *item;
+{
+ register struct object *obj;
+ register int units = -1;
+
+ obj = OBJPTR(item);
+ switch (obj->o_type) {
+ case SCROLL: units = 4;
+ when POTION: units = 3;
+ when RELIC: /* An artifact */
+ switch (obj->o_which) {
+ case QUILL_NAGROM: units = 2;
+ when EMORI_CLOAK: units = 2;
+ when BRIAN_MANDOLIN:units = 4;
+ when GERYON_HORN: units = 3;
+ when HEIL_ANKH:
+ case YENDOR_AMULET:
+ case STONEBONES_AMULET:
+ units = 2;
+ when EYE_VECNA:
+ /* Do some effects right away! */
+ units = 6;
+
+ /* The eye will do nothing other than give a headache */
+ pstats.s_hpt -= 35;
+ msg("You feel a sudden shooting pain in your eye!");
+ if (pstats.s_hpt < 0) {
+ msg ("The pain is too much for you! -- More --");
+ wait_for(' ');
+ death(D_RELIC);
+ }
+ when SURTUR_RING:
+ units = 3;
+ msg("Your nose tickles a bit.");
+ }
+ when MM:
+ switch (obj->o_which) { /* Miscellaneous Magic */
+ case MM_JUG:
+ if (obj->o_ac == JUG_EMPTY) {
+ msg("The jug is empty");
+ return (-1);
+ }
+ units = 3;
+ when MM_BEAKER:
+ case MM_BOOK:
+ /* This is a strange case because it can go forever */
+ units = 1;
+ when MM_OPEN:
+ case MM_HUNGER:
+ /* Chimes */
+ units = 3;
+ when MM_DRUMS:
+ units = 3;
+ when MM_DISAPPEAR:
+ case MM_CHOKE:
+ /* Dust */
+ units = 3;
+ when MM_KEOGHTOM:
+ /* Ointment */
+ if (obj->o_charges <= 0) {
+ msg("The jar is empty!");
+ return (-1);
+ }
+ units = 5;
+ when MM_SKILLS:
+ /* A whole book! */
+ units = 15;
+ otherwise:
+ /* What is it? */
+ units = -1;
+ }
+ otherwise: units = -1;
+ }
+
+ return (units);
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/monsters.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/monsters.c Fri May 08 15:24:40 2015 -0400
@@ -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
+
+
+/*
+ * 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; im_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; it_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));
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/move.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/move.c Fri May 08 15:24:40 2015 -0400
@@ -0,0 +1,1874 @@
+/*
+ * move.c - Hero movement 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.
+ */
+
+/*
+ * Hero movement commands
+ *
+ */
+
+#include "curses.h"
+#include
+#include "rogue.h"
+#ifdef PC7300
+#include "menu.h"
+#endif
+
+/*
+ * Used to hold the new hero position
+ */
+
+static coord nh;
+
+static char Moves[3][3] = {
+ { 'y', 'k', 'u' },
+ { 'h', '.', 'l' },
+ { 'b', 'j', 'n' }
+};
+
+/*
+ * be_trapped:
+ * The guy stepped on a trap.... Make him pay.
+ */
+
+be_trapped(th, tc)
+register struct thing *th;
+register coord *tc;
+{
+ register struct trap *tp;
+ register char ch, *mname;
+ register bool is_player = (th == &player),
+ can_see;
+ register struct linked_list *mitem;
+ register struct thing *mp;
+
+
+ /* Can the player see the creature? */
+ can_see = (cansee(tc->y, tc->x) && (is_player || !invisible(th)));
+
+ tp = trap_at(tc->y, tc->x);
+ /*
+ * if he's wearing boots of elvenkind, he won't set off the trap
+ * unless its a magic pool (they're not really traps)
+ */
+ if (is_player &&
+ cur_misc[WEAR_BOOTS] != NULL &&
+ cur_misc[WEAR_BOOTS]->o_which == MM_ELF_BOOTS &&
+ tp->tr_type != POOL)
+ return '\0';
+
+ /*
+ * if the creature is flying then it won't set off the trap
+ */
+ if (on(*th, ISFLY))
+ return '\0';
+
+ tp->tr_flags |= ISFOUND;
+
+ if (!is_player) {
+ mitem = find_mons(th->t_pos.y, th->t_pos.x);
+ mname = monster_name(th);
+ }
+ else {
+ count = running = FALSE;
+ mvwaddch(cw, tp->tr_pos.y, tp->tr_pos.x, tp->tr_type);
+ }
+ switch (ch = tp->tr_type) {
+ case TRAPDOOR:
+ if (is_player) {
+ level++;
+ pstats.s_hpt -= roll(1, 10);
+ msg("You fell into a trap!");
+ if (pstats.s_hpt <= 0) death(D_FALL);
+ new_level(NORMLEV);
+ }
+ else {
+ if (can_see) msg("%s fell into a trap!", prname(mname, TRUE));
+
+ /*
+ * See if the fall killed the monster
+ * don't let a UNIQUE die since it might have an artifact
+ * that we need
+ */
+ if (off(*th,ISUNIQUE) && (th->t_stats.s_hpt-=roll(1,10)) <= 0){
+ killed(mitem, FALSE, FALSE, FALSE);
+ }
+ else { /* Just move monster to next level */
+ check_residue(th);
+
+ /* Erase the monster from the old position */
+ if (isalpha(mvwinch(cw, th->t_pos.y, th->t_pos.x)))
+ mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch);
+ mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
+
+ /* let him summon on next lvl */
+ if (on (*th, HASSUMMONED)) {
+ turn_off(*th, HASSUMMONED);
+ turn_on(*th, CANSUMMON);
+ }
+ turn_on(*th,ISELSEWHERE);
+ detach(mlist, mitem);
+ attach(tlist, mitem); /* remember him next level */
+
+ /* Make sure that no one is still chasing us */
+ for (mitem = mlist; mitem != NULL; mitem = next(mitem)) {
+ mp = THINGPTR(mitem);
+ if (mp->t_dest == &th->t_pos) {
+ mp->t_dest = &hero;
+ mp->t_wasshot = FALSE;
+ turn_off(*mp, ISFLEE); /* Don't run away! */
+ }
+ }
+
+ /* Make sure we were not chasing a monster here */
+ th->t_dest = &hero;
+ if (on(*th, ISFRIENDLY), turn_off(*th, ISFLEE));
+ }
+ }
+ when BEARTRAP:
+ if (is_stealth(th)) {
+ if (is_player) msg("You pass a bear trap.");
+ else if (can_see) msg("%s passes a bear trap.",
+ prname(mname, TRUE));
+ }
+ else {
+ th->t_no_move += movement(&player) * BEARTIME;
+ th->t_action = A_FREEZE;
+ if (is_player) msg("You are caught in a bear trap.");
+ else if (can_see) msg("%s is caught in a bear trap.",
+ prname(mname, TRUE));
+ }
+ when SLEEPTRAP:
+ if (is_player) {
+ msg("A strange white mist envelops you.");
+ if (!ISWEARING(R_ALERT)) {
+ msg("You fall asleep.");
+ player.t_no_move += movement(&player) * SLEEPTIME;
+ player.t_action = A_FREEZE;
+ }
+ }
+ else {
+ if (can_see)
+ msg("A strange white mist envelops %s.",
+ prname(mname, FALSE));
+ if (on(*th, ISUNDEAD)) {
+ if (can_see)
+ msg("The mist doesn't seem to affect %s.",
+ prname(mname, FALSE));
+ }
+ else {
+ th->t_no_move += movement(th) * SLEEPTIME;
+ th->t_action = A_FREEZE;
+ }
+ }
+ when ARROWTRAP:
+ if (swing(th->t_ctype, th->t_stats.s_lvl-1, th->t_stats.s_arm, 1))
+ {
+ if (is_player) {
+ msg("Oh no! An arrow shot you.");
+ if ((pstats.s_hpt -= roll(1, 6)) <= 0) {
+ msg("The arrow killed you.");
+ death(D_ARROW);
+ }
+ }
+ else {
+ if (can_see)
+ msg("An arrow shot %s.", prname(mname, FALSE));
+ if ((th->t_stats.s_hpt -= roll(1, 6)) <= 0) {
+ if (can_see)
+ msg("The arrow killed %s.", prname(mname, FALSE));
+ killed(mitem, FALSE, FALSE, TRUE);
+ }
+ }
+ }
+ else
+ {
+ register struct linked_list *item;
+ register struct object *arrow;
+
+ if (is_player) msg("An arrow shoots past you.");
+ else if (can_see)
+ msg("An arrow shoots by %s.", prname(mname, FALSE));
+ item = new_item(sizeof *arrow);
+ arrow = OBJPTR(item);
+ arrow->o_type = WEAPON;
+ arrow->contents = NULL;
+ arrow->o_which = ARROW;
+ arrow->o_hplus = rnd(3) - 1;
+ arrow->o_dplus = rnd(3) - 1;
+ init_weapon(arrow, ARROW);
+ arrow->o_count = 1;
+ arrow->o_pos = *tc;
+ arrow->o_mark[0] = '\0';
+ fall(item, FALSE);
+ }
+ when TELTRAP:
+ if (is_player) teleport();
+ else {
+ register int rm;
+ struct room *old_room; /* old room of monster */
+
+ /*
+ * Erase the monster from the old position
+ */
+ if (isalpha(mvwinch(cw, th->t_pos.y, th->t_pos.x)))
+ mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch);
+ mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
+ /*
+ * check to see if room should go dark
+ */
+ if (on(*th, HASFIRE)) {
+ old_room=roomin(&th->t_pos);
+ if (old_room != NULL) {
+ register struct linked_list *fire_item;
+
+ for (fire_item = old_room->r_fires; fire_item != NULL;
+ fire_item = next(fire_item)) {
+ if (THINGPTR(fire_item) == th) {
+ detach(old_room->r_fires, fire_item);
+ destroy_item(fire_item);
+
+ if (old_room->r_fires == NULL) {
+ old_room->r_flags &= ~HASFIRE;
+ if (can_see) light(&hero);
+ }
+ }
+ }
+ }
+ }
+
+ /* Get a new position */
+ do {
+ rm = rnd_room();
+ rnd_pos(&rooms[rm], &th->t_pos);
+ } until(winat(th->t_pos.y, th->t_pos.x) == FLOOR);
+
+ /* Put it there */
+ mvwaddch(mw, th->t_pos.y, th->t_pos.x, th->t_type);
+ th->t_oldch = CCHAR( mvwinch(cw, th->t_pos.y, th->t_pos.x) );
+ /*
+ * check to see if room that creature appears in should
+ * light up
+ */
+ if (on(*th, HASFIRE)) {
+ register struct linked_list *fire_item;
+
+ fire_item = creat_item();
+ ldata(fire_item) = (char *) th;
+ attach(rooms[rm].r_fires, fire_item);
+
+ rooms[rm].r_flags |= HASFIRE;
+ if(cansee(th->t_pos.y, th->t_pos.x) &&
+ next(rooms[rm].r_fires) == NULL)
+ light(&hero);
+ }
+ if (can_see)
+ msg("%s seems to have disappeared!", prname(mname, TRUE));
+ }
+ when DARTTRAP:
+ if (swing(th->t_ctype, th->t_stats.s_lvl+1, th->t_stats.s_arm, 1)) {
+ if (is_player) {
+ msg("A small dart just hit you in the shoulder.");
+ if ((pstats.s_hpt -= roll(1, 4)) <= 0) {
+ msg("The dart killed you.");
+ death(D_DART);
+ }
+
+ /* Now the poison */
+ if (!save(VS_POISON, &player, 0)) {
+ /* 75% chance it will do point damage - else strength */
+ if (rnd(100) < 75) {
+ pstats.s_hpt /= 2;
+ if (pstats.s_hpt == 0) death(D_POISON);
+ }
+ else if (!ISWEARING(R_SUSABILITY))
+ chg_str(-1);
+ }
+ }
+ else {
+ if (can_see)
+ msg("A small dart just hit %s in the shoulder.",
+ prname(mname, FALSE));
+ if ((th->t_stats.s_hpt -= roll(1,4)) <= 0) {
+ if (can_see)
+ msg("The dart killed %s.", prname(mname, FALSE));
+ killed(mitem, FALSE, FALSE, TRUE);
+ }
+ if (!save(VS_POISON, th, 0)) {
+ th->t_stats.s_hpt /= 2;
+ if (th->t_stats.s_hpt <= 0) {
+ if (can_see)
+ msg("The dart killed %s.", prname(mname,FALSE));
+ killed(mitem, FALSE, FALSE, TRUE);
+ }
+ }
+ }
+ }
+ else {
+ if (is_player)
+ msg("A small dart whizzes by your ear and vanishes.");
+ else if (can_see)
+ msg("A small dart whizzes by %s's ear and vanishes.",
+ prname(mname, FALSE));
+ }
+ when POOL: {
+ register int i;
+
+ i = rnd(100);
+ if (is_player) {
+ if ((tp->tr_flags & ISGONE)) {
+ if (i < 30) {
+ teleport(); /* teleport away */
+ pool_teleport = TRUE;
+ }
+ else if((i < 45) && level > 2) {
+ level -= rnd(2) + 1;
+ cur_max = level;
+ new_level(NORMLEV);
+ pool_teleport = TRUE;
+ msg("You here a faint groan from below.");
+ }
+ else if(i < 70) {
+ level += rnd(4) + 1;
+ new_level(NORMLEV);
+ pool_teleport = TRUE;
+ msg("You find yourself in strange surroundings.");
+ }
+ else if(i > 95) {
+ msg("Oh no!!! You drown in the pool!!! --More--");
+ wait_for(' ');
+ death(D_DROWN);
+ }
+ }
+ }
+ else {
+ if (i < 60) {
+ if (can_see) {
+ /* Drowns */
+ if (i < 30)
+ msg("%s drowned in the pool!", prname(mname, TRUE));
+
+ /* Teleported to another level */
+ else msg("%s disappeared!", prname(mname, TRUE));
+ }
+ killed(mitem, FALSE, FALSE, TRUE);
+ }
+ }
+ }
+ when MAZETRAP:
+ if (is_player) {
+ pstats.s_hpt -= roll(1, 10);
+ level++;
+ msg("You fell through a trap door!");
+ if (pstats.s_hpt <= 0) death(D_FALL);
+ new_level(MAZELEV);
+ msg("You are surrounded by twisty passages!");
+ }
+ else {
+ if (can_see) msg("%s fell into a trap!", prname(mname, TRUE));
+
+ if (on(*th, ISUNIQUE)) {
+ check_residue(th);
+
+ /* Erase the monster from the old position */
+ if (isalpha(mvwinch(cw, th->t_pos.y, th->t_pos.x)))
+ mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch);
+ mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
+
+ /* let him summon on next lvl */
+ if (on (*th, HASSUMMONED)) {
+ turn_off(*th, HASSUMMONED);
+ turn_on(*th, CANSUMMON);
+ }
+ turn_on(*th,ISELSEWHERE);
+ detach(mlist, mitem);
+ attach(tlist, mitem); /* remember him next level */
+
+ /* Make sure that no one is still chasing us */
+ for (mitem = mlist; mitem != NULL; mitem = next(mitem)) {
+ mp = THINGPTR(mitem);
+ if (mp->t_dest == &th->t_pos) {
+ mp->t_dest = &hero;
+ mp->t_wasshot = FALSE;
+ turn_off(*mp, ISFLEE); /* Don't run away! */
+ }
+ }
+
+ /* Make sure we were not chasing a monster here */
+ th->t_dest = &hero;
+ if (on(*th, ISFRIENDLY), turn_off(*th, ISFLEE));
+ }
+ else
+ killed(mitem, FALSE, FALSE, FALSE);
+ }
+ }
+
+ /* Move the cursor back onto the hero */
+ wmove(cw, hero.y, hero.x);
+
+ md_flushinp();
+ return(ch);
+}
+
+/*
+ * blue_light:
+ * magically light up a room (or level or make it dark)
+ */
+
+bool
+blue_light(blessed, cursed)
+bool blessed, cursed;
+{
+ register struct room *rp;
+ bool ret_val=FALSE; /* Whether or not affect is known */
+
+ rp = roomin(&hero); /* What room is hero in? */
+
+ /* Darken the room if the magic is cursed */
+ if (cursed) {
+ if ((rp == NULL) || !lit_room(rp)) msg(nothing);
+ else {
+ rp->r_flags |= ISDARK;
+ if (!lit_room(rp) && (levtype != OUTSIDE || !daytime))
+ msg("The %s suddenly goes dark.",
+ levtype == OUTSIDE ? "area" : "room");
+ else msg(nothing);
+ ret_val = TRUE;
+ }
+ }
+ else {
+ ret_val = TRUE;
+ if (rp && !lit_room(rp) &&
+ (levtype != OUTSIDE || !daytime)) {
+ addmsg("The %s is lit", levtype == OUTSIDE ? "area" : "room");
+ if (!terse)
+ addmsg(" by a %s blue light.",
+ blessed ? "bright" : "shimmering");
+ endmsg();
+ }
+ else if (winat(hero.y, hero.x) == PASSAGE)
+ msg("The corridor glows %sand then fades",
+ blessed ? "brightly " : "");
+ else {
+ ret_val = FALSE;
+ msg(nothing);
+ }
+ if (blessed) {
+ register int i; /* Index through rooms */
+
+ for (i=0; ir_flags &= ~ISDARK;
+ }
+
+ /*
+ * Light the room and put the player back up
+ */
+ light(&hero);
+ mvwaddch(cw, hero.y, hero.x, PLAYER);
+ return(ret_val);
+}
+
+/*
+ * corr_move:
+ * Check to see that a move is legal. If so, return correct character.
+ * If not, if player came from a legal place, then try to turn him.
+ */
+
+corr_move(dy, dx)
+int dy, dx;
+{
+ int legal=0; /* Number of legal alternatives */
+ register int y, x, /* Indexes though possible positions */
+ locy, locx; /* Hold delta of chosen location */
+
+ /* New position */
+ nh.y = hero.y + dy;
+ nh.x = hero.x + dx;
+
+ /* If it is a legal move, just return */
+ if (nh.x >= 0 && nh.x < cols && nh.y > 0 && nh.y < lines - 2) {
+
+ switch (winat(nh.y, nh.x)) {
+ case WALL:
+ case '|':
+ case '-':
+ break;
+ default:
+ if (diag_ok(&hero, &nh, &player))
+ return;
+ }
+ }
+
+ /* Check legal places surrounding the player -- ignore previous position */
+ for (y = hero.y - 1; y <= hero.y + 1; y++) {
+ if (y < 1 || y > lines - 3)
+ continue;
+ for (x = hero.x - 1; x <= hero.x + 1; x++) {
+ /* Ignore borders of the screen */
+ if (x < 0 || x > cols - 1)
+ continue;
+
+ /*
+ * Ignore where we came from, where we are, and where we couldn't go
+ */
+ if ((x == hero.x - dx && y == hero.y - dy) ||
+ (x == hero.x + dx && y == hero.y + dy) ||
+ (x == hero.x && y == hero.y))
+ continue;
+
+ switch (winat(y, x)) {
+ case WALL:
+ case '|':
+ case '-':
+ break;
+ default:
+ nh.y = y;
+ nh.x = x;
+ if (diag_ok(&hero, &nh, &player)) {
+ legal++;
+ locy = y - (hero.y - 1);
+ locx = x - (hero.x - 1);
+ }
+ }
+ }
+ }
+
+ /* If we have 2 or more legal moves, make no change */
+ if (legal != 1) {
+ return;
+ }
+
+ runch = Moves[locy][locx];
+
+ /*
+ * For mazes, pretend like it is the beginning of a new run at each turn
+ * in order to get the lighting correct.
+ */
+ if (levtype == MAZELEV) firstmove = TRUE;
+ return;
+}
+
+/*
+ * dip_it:
+ * Dip an object into a magic pool
+ */
+dip_it()
+{
+ reg struct linked_list *what;
+ reg struct object *ob;
+ reg struct trap *tp;
+ reg int wh, i;
+
+ tp = trap_at(hero.y,hero.x);
+ if (tp == NULL || tp->tr_type != POOL) {
+ msg("I see no shimmering pool here");
+ return;
+ }
+ if (tp->tr_flags & ISGONE) {
+ msg("This shimmering pool appears to have been used once already.");
+ return;
+ }
+
+ /* It takes 3 movement periods to dip something */
+ if (player.t_action != C_DIP) {
+ if ((what = get_item(pack, "dip", ALL, FALSE, FALSE)) == NULL) {
+ msg("");
+ after = FALSE;
+ return;
+ }
+
+ ob = OBJPTR(what);
+ if (ob == cur_armor ||
+ ob == cur_misc[WEAR_BOOTS] || ob == cur_misc[WEAR_JEWEL] ||
+ ob == cur_misc[WEAR_GAUNTLET] ||
+ ob == cur_misc[WEAR_CLOAK] ||
+ ob == cur_misc[WEAR_BRACERS] ||
+ ob == cur_misc[WEAR_NECKLACE]||
+ ob == cur_ring[LEFT_1] || ob == cur_ring[LEFT_2] ||
+ ob == cur_ring[LEFT_3] || ob == cur_ring[LEFT_4] ||
+ ob == cur_ring[RIGHT_1] || ob == cur_ring[RIGHT_2] ||
+ ob == cur_ring[RIGHT_3] || ob == cur_ring[RIGHT_4]) {
+ mpos = 0;
+ msg("You'll have to take it off first.");
+ return;
+ }
+
+ player.t_using = what; /* Remember what it is */
+ player.t_action = C_DIP; /* We are dipping */
+ player.t_no_move = 3 * movement(&player);
+ return;
+ }
+
+ /* We have waited our time, let's dip it */
+ what = player.t_using;
+ player.t_using = NULL;
+ player.t_action = A_NIL;
+
+ ob = OBJPTR(what);
+
+ tp->tr_flags |= ISGONE;
+ if (ob != NULL) {
+ wh = ob->o_which;
+ ob->o_flags |= ISKNOW;
+ i = rnd(100);
+ switch(ob->o_type) {
+ case WEAPON:
+ if(i < 50) { /* enchant weapon here */
+ if ((ob->o_flags & ISCURSED) == 0) {
+ ob->o_hplus += 1;
+ ob->o_dplus += 1;
+ }
+ else { /* weapon was prev cursed here */
+ ob->o_hplus = rnd(2);
+ ob->o_dplus = rnd(2);
+ }
+ ob->o_flags &= ~ISCURSED;
+ msg("The %s glows blue for a moment.",weaps[wh].w_name);
+ }
+ else if(i < 70) { /* curse weapon here */
+ if ((ob->o_flags & ISCURSED) == 0) {
+ ob->o_hplus = -(rnd(2)+1);
+ ob->o_dplus = -(rnd(2)+1);
+ }
+ else { /* if already cursed */
+ ob->o_hplus--;
+ ob->o_dplus--;
+ }
+ ob->o_flags |= ISCURSED;
+ msg("The %s glows red for a moment.",weaps[wh].w_name);
+ }
+ else
+ msg(nothing);
+ when ARMOR:
+ if (i < 50) { /* enchant armor */
+ if((ob->o_flags & ISCURSED) == 0)
+ ob->o_ac -= rnd(2) + 1;
+ else
+ ob->o_ac = -rnd(3)+ armors[wh].a_class;
+ ob->o_flags &= ~ISCURSED;
+ msg("The %s glows blue for a moment",armors[wh].a_name);
+ }
+ else if(i < 75){ /* curse armor */
+ if ((ob->o_flags & ISCURSED) == 0)
+ ob->o_ac = rnd(3)+ armors[wh].a_class;
+ else
+ ob->o_ac += rnd(2) + 1;
+ ob->o_flags |= ISCURSED;
+ msg("The %s glows red for a moment.",armors[wh].a_name);
+ }
+ else
+ msg(nothing);
+ when STICK: {
+ int j;
+ j = rnd(8) + 1;
+ if(i < 50) { /* add charges */
+ ob->o_charges += j;
+ ws_know[wh] = TRUE;
+ if (ob->o_flags & ISCURSED)
+ ob->o_flags &= ~ISCURSED;
+ msg("The %s %s glows blue for a moment.",
+ ws_made[wh],ws_type[wh]);
+ }
+ else if(i < 65) { /* remove charges */
+ if ((ob->o_charges -= i) < 0)
+ ob->o_charges = 0;
+ ws_know[wh] = TRUE;
+ if (ob->o_flags & ISBLESSED)
+ ob->o_flags &= ~ISBLESSED;
+ else
+ ob->o_flags |= ISCURSED;
+ msg("The %s %s glows red for a moment.",
+ ws_made[wh],ws_type[wh]);
+ }
+ else
+ msg(nothing);
+ }
+ when SCROLL:
+ s_know[wh] = TRUE;
+ msg("The '%s' scroll unfurls.",s_names[wh]);
+ when POTION:
+ p_know[wh] = TRUE;
+ msg("The %s potion bubbles for a moment.",p_colors[wh]);
+ when RING:
+ if(i < 50) { /* enchant ring */
+ if ((ob->o_flags & ISCURSED) == 0)
+ ob->o_ac += rnd(2) + 1;
+ else
+ ob->o_ac = rnd(2) + 1;
+ ob->o_flags &= ~ISCURSED;
+ }
+ else if(i < 80) { /* curse ring */
+ if ((ob->o_flags & ISCURSED) == 0)
+ ob->o_ac = -(rnd(2) + 1);
+ else
+ ob->o_ac -= (rnd(2) + 1);
+ ob->o_flags |= ISCURSED;
+ }
+ r_know[wh] = TRUE;
+ msg("The %s ring vibrates for a moment.",r_stones[wh]);
+ when MM:
+ m_know[wh] = TRUE;
+ switch (ob->o_which) {
+ case MM_BRACERS:
+ case MM_PROTECT:
+ if(i < 50) { /* enchant item */
+ if ((ob->o_flags & ISCURSED) == 0)
+ ob->o_ac += rnd(2) + 1;
+ else
+ ob->o_ac = rnd(2) + 1;
+ ob->o_flags &= ~ISCURSED;
+ }
+ else if(i < 80) { /* curse item */
+ if ((ob->o_flags & ISCURSED) == 0)
+ ob->o_ac = -(rnd(2) + 1);
+ else
+ ob->o_ac -= (rnd(2) + 1);
+ ob->o_flags |= ISCURSED;
+ }
+ msg("The item vibrates for a moment.");
+ when MM_CHOKE:
+ case MM_DISAPPEAR:
+ ob->o_ac = 0;
+ msg ("The dust dissolves in the pool!");
+ }
+ otherwise:
+ msg("The pool bubbles for a moment.");
+ }
+ updpack(FALSE, &player);
+ }
+ else
+ msg(nothing);
+}
+
+/*
+ * do_move:
+ * Check to see that a move is legal. If it is handle the
+ * consequences (fighting, picking up, etc.)
+ */
+
+do_move(dy, dx)
+int dy, dx;
+{
+ register struct room *rp, *orp;
+ register char ch;
+ struct linked_list *item;
+ register struct thing *tp;
+ coord old_hero;
+ register int wasfirstmove, moved, num_hits;
+ bool changed=FALSE; /* Did we switch places with a friendly monster? */
+
+ wasfirstmove = firstmove;
+ firstmove = FALSE;
+ curprice = -1; /* if in trading post, we've moved off obj */
+
+ /*
+ * Do a confused move (maybe)
+ */
+ if (player.t_action == A_NIL &&
+ ((on(player, ISHUH) && rnd(100) < 80) ||
+ (on(player, ISDANCE) && rnd(100) < 80) ||
+ (ISWEARING(R_DELUSION) && rnd(100) < 25)))
+ /* Get a random move */
+ nh = *rndmove(&player);
+ else {
+ nh.y = hero.y + dy;
+ nh.x = hero.x + dx;
+ }
+
+ /*
+ * Check if he tried to move off the screen or make an illegal
+ * diagonal move, and stop him if he did.
+ */
+ if (nh.x < 0 || nh.x > cols-1 || nh.y < 1 || nh.y >= lines - 2
+ || !diag_ok(&hero, &nh, &player))
+ {
+ after = running = FALSE;
+ player.t_action = A_NIL;
+ return;
+ }
+ if (running && ce(hero, nh))
+ after = running = FALSE;
+ ch = CCHAR( winat(nh.y, nh.x) );
+
+ /* Take care of hero trying to move close to something frightening */
+ if (on(player, ISFLEE)) {
+ if (rnd(100) < 10) {
+ turn_off(player, ISFLEE);
+ msg("You regain your composure.");
+ }
+ else if (DISTANCE(nh.y, nh.x, player.t_dest->y, player.t_dest->x) <
+ DISTANCE(hero.y, hero.x, player.t_dest->y, player.t_dest->x)) {
+ running = FALSE;
+ msg("You are too terrified to move that way");
+ player.t_action = A_NIL;
+ player.t_no_move = movement(&player);
+ return;
+ }
+ }
+
+ /* If we want to move to a monster, see what it is */
+ if (isalpha(ch)) {
+ item = find_mons(nh.y, nh.x);
+ if (item == NULL) {
+ debug("Cannot find monster in move.");
+ player.t_action = A_NIL;
+ return;
+ }
+ tp = THINGPTR(item);
+ }
+
+ /*
+ * Take care of hero being held. If the player is being held, he
+ * can't move unless he is either attacking a non-friendly monster
+ * or attacking a friendly monster that can't move.
+ */
+ if (on(player, ISHELD) &&
+ (!isalpha(ch) || (on(*tp, ISFRIENDLY) && off(*tp, ISHELD)))) {
+ msg("You are being held.");
+ player.t_action = A_NIL;
+ return;
+ }
+
+ /* See if we have to wait for our movement rate */
+ if (player.t_action == A_NIL) {
+ after = FALSE;
+ firstmove = wasfirstmove; /* Remember if this is first move */
+ player.t_no_move = movement(&player);
+ if (player.t_ctype == C_MONK)
+ player.t_no_move -= pstats.s_lvl/6;
+ if (on(player, ISFLY))
+ player.t_no_move /= 2; /* If flying, speed him up */
+
+ if (player.t_no_move < 1) player.t_no_move = 1;
+
+ /* Remember our action */
+ player.t_action = Moves[dy+1][dx+1];
+ return;
+ }
+
+ /* Now let's forget the old move and just do it */
+ player.t_action = A_NIL;
+
+ /* If we're moving onto a friendly monster, let's change places. */
+ if (isalpha(ch) && on(*tp, ISFRIENDLY) && off(*tp, ISHELD)) {
+ coord tpos, /* Where monster may have been going */
+ current; /* Current hero position */
+ int action; /* The monster's action */
+
+ current = hero;
+ tpos = tp->t_newpos;
+ action = tp->t_action;
+
+ /* Disrupt whatever our friend was doing */
+ tp->t_action = A_NIL;
+
+ /* Tentatively move us to where he is */
+ hero = tp->t_pos;
+
+ /* See if we can move him to where we were */
+ tp->t_newpos = current;
+ do_chase(tp);
+
+ /* Did we succeed? */
+ if (ce(tp->t_pos, current)) {
+ /* Reset our idea of what ch is */
+ ch = CCHAR( winat(nh.y, nh.x) );
+
+ /* Let it be known that we made the switch */
+ changed = TRUE;
+ old_hero = current;
+
+ /* Make the monster think it didn't move */
+ tp->t_oldpos = current;
+ tp->t_doorgoal = NULL;
+
+ /* Let the player know something funny happened. */
+ msg("What a sidestep!");
+ }
+ else {
+ /* Restore things -- we couldn't move */
+ hero = current;
+ tp->t_newpos = tpos;
+ tp->t_action = action;
+ }
+ }
+
+ /* assume he's not in a wall */
+ if (!isalpha(ch)) turn_off(player, ISINWALL);
+
+ switch (ch) {
+ case '|':
+ case '-':
+ if (levtype == OUTSIDE) {
+ hero = nh;
+ new_level(OUTSIDE);
+ return;
+ }
+ case WALL:
+ case SECRETDOOR:
+ if (off(player, CANINWALL) || running) {
+ after = running = FALSE;
+
+ /* Light if finishing run */
+ if (levtype == MAZELEV && lit_room(&rooms[0]))
+ look(FALSE, TRUE);
+
+ after = running = FALSE;
+
+ return;
+ }
+ turn_on(player, ISINWALL);
+ break;
+ case POOL:
+ if (levtype == OUTSIDE) {
+ lake_check(&nh);
+ running = FALSE;
+ break;
+ }
+ case MAZETRAP:
+ if (levtype == OUTSIDE) {
+ running = FALSE;
+ break;
+ }
+ case TRAPDOOR:
+ case TELTRAP:
+ case BEARTRAP:
+ case SLEEPTRAP:
+ case ARROWTRAP:
+ case DARTTRAP:
+ ch = be_trapped(&player, &nh);
+ if (ch == TRAPDOOR || ch == TELTRAP ||
+ pool_teleport || ch == MAZETRAP) {
+ pool_teleport = FALSE;
+ return;
+ }
+ break;
+ case GOLD:
+ case POTION:
+ case SCROLL:
+ case FOOD:
+ case WEAPON:
+ case ARMOR:
+ case RING:
+ case MM:
+ case RELIC:
+ case STICK:
+ running = FALSE;
+ take = ch;
+ break;
+ case DOOR:
+ case STAIRS:
+ case POST:
+ running = FALSE;
+ break;
+ default:
+ break;
+ }
+
+ if (isalpha(ch)) { /* if its a monster then fight it */
+ /*
+ * If we were running down a corridor and didn't start right
+ * next to the critter, don't do anything.
+ */
+ if (running && wasfirstmove == FALSE && roomin(&hero) == NULL) {
+ struct linked_list *item;
+
+ item = find_mons(nh.y, nh.x);
+ if (item != NULL && !invisible(THINGPTR(item))) {
+ after = running = FALSE;
+ return;
+ }
+ }
+
+ /* We have to add time because we're attacking */
+ player.t_no_move = FIGHTBASE;
+ player.t_no_move += weap_move(&player, cur_weapon);
+ if (on(player, ISHASTE))
+ player.t_no_move /= 2;
+ else if (on(player, ISSLOW))
+ player.t_no_move *= 2;
+
+ /* We may attack faster if we're high enough level
+ * and the right class
+ */
+ switch(player.t_ctype) {
+ case C_FIGHTER: num_hits = player.t_stats.s_lvl/9 + 1;
+ when C_PALADIN: num_hits = player.t_stats.s_lvl/12 + 1;
+ when C_RANGER: num_hits = player.t_stats.s_lvl/13 + 1;
+ when C_MONK: if(cur_weapon) num_hits= 1;
+ else num_hits= player.t_stats.s_lvl/5 + 1;
+ otherwise: num_hits = 1;
+ }
+
+ /*
+ * The player has already moved the initial movement period.
+ * Let's add that in, do our division, and then subtract it
+ * out so that the total time is divided, not just the
+ * additional attack time.
+ */
+ moved = movement(&player),
+ player.t_no_move += moved;
+ player.t_no_move /= num_hits;
+ player.t_no_move -= moved;
+ running = FALSE;
+
+ /* Mark that we are attacking and save the attack coordinate */
+ player.t_action = A_ATTACK;
+ player.t_newpos = nh;
+ runch = Moves[dy+1][dx+1]; /* Remember the direction */
+
+ if (player.t_no_move <= 0) after = FALSE;
+ return;
+ }
+
+ /*
+ * if not fighting then move the hero
+ */
+ if (changed == FALSE) {
+ old_hero = hero; /* Save hero's old position */
+ hero = nh; /* Move the hero */
+ }
+ rp = roomin(&hero);
+ orp = roomin(&old_hero);
+
+ /* Unlight any possible cross-corridor */
+ if (levtype == MAZELEV) {
+ register bool call_light = FALSE;
+ register char wall_check;
+
+ if (wasfirstmove && lit_room(&rooms[0])) {
+ /* Are we moving out of a corridor? */
+ switch (runch) {
+ case 'h':
+ case 'l':
+ if (old_hero.y + 1 < lines - 2) {
+ wall_check = CCHAR( winat(old_hero.y + 1, old_hero.x) );
+ if (!isrock(wall_check)) call_light = TRUE;
+ }
+ if (old_hero.y - 1 > 0) {
+ wall_check = CCHAR( winat(old_hero.y - 1, old_hero.x) );
+ if (!isrock(wall_check)) call_light = TRUE;
+ }
+ break;
+ case 'j':
+ case 'k':
+ if (old_hero.x + 1 < cols) {
+ wall_check = CCHAR( winat(old_hero.y, old_hero.x + 1) );
+ if (!isrock(wall_check)) call_light = TRUE;
+ }
+ if (old_hero.x - 1 >= 0) {
+ wall_check = CCHAR( winat(old_hero.y, old_hero.x - 1) );
+ if (!isrock(wall_check)) call_light = TRUE;
+ }
+ break;
+ default:
+ call_light = TRUE;
+ }
+ player.t_oldpos = old_hero;
+ if (call_light) light(&old_hero);
+ }
+ }
+
+ else if (orp != NULL && rp == NULL) { /* Leaving a room -- darken it */
+ orp->r_flags |= FORCEDARK; /* Fake darkness */
+ light(&old_hero);
+ orp->r_flags &= ~FORCEDARK; /* Restore light state */
+ }
+ else if (rp != NULL && orp == NULL){/* Entering a room */
+ light(&hero);
+ if (rp->r_flags & ISTREAS)
+ wake_room(rp);
+ }
+ ch = CCHAR( winat(old_hero.y, old_hero.x) );
+ wmove(cw, unc(old_hero));
+ waddch(cw, ch);
+ wmove(cw, unc(hero));
+ waddch(cw, PLAYER);
+}
+
+/*
+ * do_run:
+ * Start the hero running
+ */
+
+do_run(ch)
+char ch;
+{
+ firstmove = TRUE;
+ running = TRUE;
+ after = FALSE;
+ runch = ch;
+}
+
+/*
+ * getdelta:
+ * Takes a movement character (eg. h, j, k, l) and returns the
+ * y and x delta corresponding to it in the remaining arguments.
+ * Returns TRUE if it could find it, FALSE otherwise.
+ */
+bool
+getdelta(match, dy, dx)
+char match;
+int *dy, *dx;
+{
+ register y, x;
+
+ for (y = 0; y < 3; y++)
+ for (x = 0; x < 3; x++)
+ if (Moves[y][x] == match) {
+ *dy = y - 1;
+ *dx = x - 1;
+ return(TRUE);
+ }
+
+ return(FALSE);
+}
+
+/*
+ * isatrap:
+ * Returns TRUE if this character is some kind of trap
+ */
+isatrap(ch)
+reg char ch;
+{
+ switch(ch) {
+ case DARTTRAP:
+ case TELTRAP:
+ case TRAPDOOR:
+ case ARROWTRAP:
+ case SLEEPTRAP:
+ case BEARTRAP: return(TRUE);
+ case MAZETRAP:
+ case POOL: return(levtype != OUTSIDE);
+ default: return(FALSE);
+ }
+}
+
+/*
+ * Called to illuminate a room.
+ * If it is dark, remove anything that might move.
+ */
+
+light(cp)
+coord *cp;
+{
+ register struct room *rp;
+ register int j, k, x, y;
+ register char ch, rch, sch;
+ register struct linked_list *item;
+ int jlow, jhigh, klow, khigh; /* Boundaries of lit area */
+
+ if ((rp = roomin(cp)) != NULL) {
+ /*
+ * is he wearing ring of illumination?
+ */
+ if (&hero == cp && ISWEARING(R_LIGHT)) /* Must be hero's room */
+ rp->r_flags &= ~ISDARK;
+
+ /* If we are in a maze, don't look at the whole room (level) */
+ if (levtype == MAZELEV) {
+ int see_radius;
+
+ see_radius = 1;
+
+ /* If we are looking at the hero in a rock, broaden our sights */
+ if (&hero == cp || &player.t_oldpos == cp) {
+ ch = CCHAR( winat(hero.y, hero.x) );
+ if (isrock(ch)) see_radius = 2;
+ ch = CCHAR( winat(player.t_oldpos.y, player.t_oldpos.x) );
+ if (isrock(ch)) see_radius = 2;
+ }
+
+ jlow = max(0, cp->y - see_radius - rp->r_pos.y);
+ jhigh = min(rp->r_max.y, cp->y + see_radius + 1 - rp->r_pos.y);
+ klow = max(0, cp->x - see_radius - rp->r_pos.x);
+ khigh = min(rp->r_max.x, cp->x + see_radius + 1 - rp->r_pos.x);
+ }
+ else {
+ jlow = klow = 0;
+ jhigh = rp->r_max.y;
+ khigh = rp->r_max.x;
+ }
+ for (j = 0; j < rp->r_max.y; j++)
+ {
+ for (k = 0; k < rp->r_max.x; k++)
+ {
+ bool see_here, see_before;
+
+ /* Is this in the give area -- needed for maze */
+ if ((j < jlow || j >= jhigh) && (k < klow || k >= khigh))
+ continue;
+
+ y = rp->r_pos.y + j;
+ x = rp->r_pos.x + k;
+
+ /*
+ * If we are in a maze do not look at this area unless
+ * we can see it from where we are or where we last were
+ * (for erasing purposes).
+ */
+ if (levtype == MAZELEV) {
+ /* If we can't see it from here, could we see it before? */
+ if ((see_here = maze_view(y, x)) == FALSE) {
+ coord savhero;
+
+ /* Could we see it from where we were? */
+ savhero = hero;
+ hero = player.t_oldpos;
+ see_before = maze_view(y, x);
+ hero = savhero;
+
+ if (!see_before) continue;
+ }
+ }
+
+ ch = show(y, x);
+ wmove(cw, y, x);
+ /*
+ * Figure out how to display a secret door
+ */
+ if (ch == SECRETDOOR) {
+ if (j == 0 || j == rp->r_max.y - 1)
+ ch = '-';
+ else
+ ch = '|';
+ }
+ /* For monsters, if they were previously not seen and
+ * now can be seen, or vice-versa, make sure that will
+ * happen. This is for dark rooms as opposed to invisibility.
+ *
+ * Call winat() in the test because ch will not reveal
+ * invisible monsters.
+ */
+ if (isalpha(winat(y, x))) {
+ struct thing *tp; /* The monster */
+
+ item = wake_monster(y, x);
+ tp = THINGPTR(item);
+
+ /* Previously not seen -- now can see it */
+ if (tp->t_oldch == ' ' && cansee(tp->t_pos.y, tp->t_pos.x))
+ tp->t_oldch = CCHAR( mvinch(y, x) );
+
+ /* Previously seen -- now can't see it */
+ else if (!cansee(tp->t_pos.y, tp->t_pos.x) &&
+ roomin(&tp->t_pos) != NULL)
+ switch (tp->t_oldch) {
+ /*
+ * Only blank it out if it is in a room and not
+ * the border (or other wall) of the room.
+ */
+ case DOOR:
+ case SECRETDOOR:
+ case '-':
+ case '|':
+ break;
+
+ otherwise:
+ tp->t_oldch = ' ';
+ }
+ }
+
+ /*
+ * If the room is a dark room, we might want to remove
+ * monsters and the like from it (since they might
+ * move).
+ * A dark room.
+ */
+ if ((!lit_room(rp) && (levtype != OUTSIDE)) ||
+ (levtype == OUTSIDE && !daytime) ||
+ on(player, ISBLIND) ||
+ (rp->r_flags & FORCEDARK) ||
+ (levtype == MAZELEV && !see_here && see_before)) {
+ sch = CCHAR( mvwinch(cw, y, x) ); /* What's seen */
+ rch = CCHAR( mvinch(y, x) ); /* What's really there */
+ switch (rch) {
+ case DOOR:
+ case SECRETDOOR:
+ case STAIRS:
+ case TRAPDOOR:
+ case TELTRAP:
+ case BEARTRAP:
+ case SLEEPTRAP:
+ case ARROWTRAP:
+ case DARTTRAP:
+ case MAZETRAP:
+ case POOL:
+ case POST:
+ case '|':
+ case '-':
+ case WALL:
+ if (isalpha(sch)) ch = rch;
+ else if (sch != FLOOR) ch = sch;
+ else ch = ' '; /* Hide undiscoverd things */
+ when FLOOR:
+ ch = ' ';
+ otherwise:
+ ch = ' ';
+ }
+ /* Take care of our magic bookkeeping. */
+ switch (sch) {
+ case MAGIC:
+ case BMAGIC:
+ case CMAGIC:
+ ch = sch;
+ }
+ }
+ mvwaddch(cw, y, x, ch);
+ }
+ }
+ }
+}
+
+/*
+ * lit_room:
+ * Called to see if the specified room is lit up or not.
+ */
+
+bool
+lit_room(rp)
+register struct room *rp;
+{
+ register struct linked_list *fire_item;
+ register struct thing *fire_creature;
+
+ if (!(rp->r_flags & ISDARK)) return(TRUE); /* A definitely lit room */
+
+ /* Is it lit by fire light? */
+ if (rp->r_flags & HASFIRE) {
+ switch ((int)levtype) {
+ case MAZELEV:
+ /* See if a fire creature is in line of sight */
+ for (fire_item = rp->r_fires; fire_item != NULL;
+ fire_item = next(fire_item)) {
+ fire_creature = THINGPTR(fire_item);
+ if (maze_view(fire_creature->t_pos.y,
+ fire_creature->t_pos.x)) return(TRUE);
+ }
+
+ /* Couldn't find any in line-of-sight */
+ return(FALSE);
+
+ /* We should probably do something special for the outside */
+ otherwise:
+ return TRUE;
+ }
+ }
+ return(FALSE);
+}
+
+/*
+ * movement:
+ * Given a pointer to a player/monster structure, calculate the
+ * movement rate for that character.
+ */
+
+short
+movement(tp)
+register struct thing *tp;
+{
+ register int result;
+ register int carry; /* Percentage carried */
+
+ result = 0;
+
+ /* Adjust for armor (player only) */
+ if (tp == &player && cur_armor) {
+ int diff; /* Now armor class differs from normal one of same type */
+
+ /* Blessed armor adds less */
+ diff = cur_armor->o_ac - armors[cur_armor->o_which].a_class;
+ switch (cur_armor->o_which) {
+ case LEATHER:
+ case RING_MAIL:
+ case STUDDED_LEATHER:
+ case SCALE_MAIL:
+ case PADDED_ARMOR:
+ diff += 1;
+ when CHAIN_MAIL:
+ case SPLINT_MAIL:
+ case BANDED_MAIL:
+ case PLATE_MAIL:
+ diff += 2;
+ when PLATE_ARMOR:
+ diff += 3;
+ otherwise:
+ debug("forgot an armor in movement()");
+ }
+ if (diff < 0) diff = 0;
+ result += diff;
+
+ }
+
+ /* Adjust for the pack */
+ carry = 100 * tp->t_stats.s_pack / tp->t_stats.s_carry;
+ if (carry > 75) result++;
+
+ /* Get a bonus for dexterity */
+ result -= dext_plus(tp == &player ? dex_compute() : tp->t_stats.s_dext);
+
+ /* only allow adjust for the minus's */
+ if (result < 0) result = 0;
+ result += tp->t_movement; /* now add in movement rate */
+
+ /* Is the character slowed? */
+ if (on(*tp, ISSLOW) || on(*tp, ISDANCE)) result *= 2;
+
+ /* Is the character hasted? */
+ if (on(*tp, ISHASTE)) result /= 2;
+
+ /* We have a minimum of 1 */
+ if (result < 1) result = 1;
+
+ return(result);
+}
+
+/*
+ * rndmove:
+ * move in a random direction if the monster/person is confused
+ */
+
+coord *
+rndmove(who)
+struct thing *who;
+{
+ register int x, y;
+ register int ex, ey, nopen = 0;
+ static coord ret; /* what we will be returning */
+ static coord dest;
+
+ ret = who->t_pos;
+ /*
+ * Now go through the spaces surrounding the player and
+ * set that place in the array to true if the space can be
+ * moved into
+ */
+ ey = ret.y + 1;
+ ex = ret.x + 1;
+ for (y = who->t_pos.y - 1; y <= ey; y++)
+ if (y > 0 && y < lines - 2)
+ for (x = who->t_pos.x - 1; x <= ex; x++)
+ {
+ if (x < 0 || x >= cols)
+ continue;
+ if (step_ok(y, x, NOMONST, who) == TRUE)
+ {
+ dest.y = y;
+ dest.x = x;
+ if (!diag_ok(&who->t_pos, &dest, who))
+ continue;
+ if (rnd(++nopen) == 0)
+ ret = dest;
+ }
+ }
+ return &ret;
+}
+
+
+
+#define TRAPTYPES 9 /* 9 total trap types that can be set */
+#define WIZARDTRAPS 3 /* Only wizards can set 3 of these */
+
+static char *trap_types[TRAPTYPES] = {
+ "Trap Door",
+ "Bear Trap",
+ "Sleep Trap",
+ "Arrow Trap",
+ "Teleport Trap",
+ "Dart Trap",
+ "Magic pool",
+ "Maze Trap",
+ "Trading Post"
+};
+
+#ifdef PC7300
+#define TRAPWIDTH 13 /* Length of longest named trap from above list */
+#define TRAPPREFIX 4 /* Length of prefix (eg. "[9] ") */
+static menu_t Display; /* The menu structure */
+static mitem_t Dispitems[TRAPTYPES+1]; /* Info for each line */
+static char Displines[TRAPTYPES+1][TRAPWIDTH+TRAPPREFIX+1];
+#endif
+
+/*
+ * set_trap:
+ * set a trap at (y, x) on screen.
+ */
+
+set_trap(tp, y, x)
+register struct thing *tp;
+register int y, x;
+{
+ register bool is_player = (tp == &player);
+ register int selection = rnd(TRAPTYPES-WIZARDTRAPS) + '1';
+ register int i, num_traps;
+ register char ch, och;
+ int thief_bonus = 0;
+ int s_dext;
+
+ if (is_player && player.t_ctype != C_THIEF && player.t_ctype != C_ASSASIN) {
+ msg("Only thieves and assassins can set traps.");
+ return;
+ }
+ switch (och = CCHAR( mvinch(y, x) )) {
+ case WALL:
+ case FLOOR:
+ case PASSAGE:
+ break;
+ default:
+ if (is_player) msg("The trap failed!");
+ return;
+ }
+
+ if (is_player) {
+ int state = 0, /* 0 -> current screen, 1 -> prompt screen, 2 -> done */
+ units; /* Number of movement units for the given trap */
+
+ if (player.t_action == C_SETTRAP) {
+ selection = player.t_selection;
+ player.t_selection = 0;
+ player.t_using = NULL;
+ player.t_action = A_NIL;
+ }
+ else {
+ msg("Which kind of trap do you wish to set? (* for a list): ");
+ num_traps = TRAPTYPES - (wizard ? 0 : WIZARDTRAPS);
+ do {
+ selection = tolower(readchar());
+ switch (selection) {
+ case '*':
+ if (state != 1) {
+#ifdef PC7300
+ for (i=0; i= 0) {
+ if (Display.m_selcnt == 0) {
+ /* Cancelled menu */
+ msg("");
+
+ trap_tries--; /* Don't count this one */
+ after = FALSE;
+ return;
+ }
+ selection = Display.m_curi->mi_val;
+ state = 2;
+ break;
+ }
+#endif
+
+ wclear(hw);
+ touchwin(hw);
+ for (i=0; i= nfloors) {
+ if (state == 1) draw(cw);
+ msg("There is no level below this one.");
+ return;
+ }
+ state = 2; /* Finished */
+ break;
+ }
+
+ /* Fall through for non-wizard, unusual trap case */
+ default:
+ if (state == 1) { /* In the prompt window */
+ wmove(hw, 0, 0);
+ wprintw(hw,
+ "Please enter a selection between 1 and %d: ",
+ num_traps);
+ if (menu_overlay)
+ /*
+ * Put out the selection. The longest line is
+ * the prompt line (43 characters long).
+ */
+ over_win(cw, hw, num_traps+3, 45, 0, 43, NULL);
+ else
+ draw(hw);
+ }
+ else { /* Normal window */
+ mpos = 0;
+ msg("Please enter a selection between 1 and %d: ",
+ num_traps);
+ }
+ }
+ } while (state != 2);
+
+ switch ((player.t_selection = selection)) {
+ case '1': units = 20; /* Trap door */
+ when '2': units = 5; /* Bear trap */
+ when '3': units = 6; /* Sleeping gas trap */
+ when '4': units = 5; /* Arrow trap */
+ when '5': units = 8; /* Teleport trap */
+ when '6': units = 5; /* Dart trap */
+ otherwise: units = 10; /* Unknown trap */
+ }
+ player.t_no_move = units * movement(&player);
+ player.t_action = C_SETTRAP;
+ player.t_using = NULL;
+ return;
+ }
+ }
+
+ if (is_player && player.t_ctype == C_THIEF) thief_bonus = 30;
+ if (is_player && player.t_ctype == C_ASSASIN) thief_bonus = 20;
+
+ s_dext = (tp == &player) ? dex_compute() : tp->t_stats.s_dext;
+
+ if (ntraps >= MAXTRAPS || ++trap_tries >= MAXTRPTRY || levtype == POSTLEV ||
+ rnd(80) >= (s_dext + tp->t_stats.s_lvl/2 + thief_bonus)) {
+ if (is_player) msg("The trap failed!");
+ return;
+ }
+
+ switch (selection) {
+ case '1': ch = TRAPDOOR;
+ when '2': ch = BEARTRAP;
+ when '3': ch = SLEEPTRAP;
+ when '4': ch = ARROWTRAP;
+ when '5': ch = TELTRAP;
+ when '6': ch = DARTTRAP;
+ when '7': ch = POOL;
+ when '8': ch = MAZETRAP;
+ when '9': ch = POST;
+ }
+
+ mvaddch(y, x, ch);
+ traps[ntraps].tr_show = och;
+ traps[ntraps].tr_type = ch;
+ traps[ntraps].tr_pos.y = y;
+ traps[ntraps].tr_pos.x = x;
+ if (is_player)
+ traps[ntraps].tr_flags = ISTHIEFSET;
+ if (ch == POOL || ch == POST) {
+ traps[ntraps].tr_flags |= ISFOUND;
+ }
+
+ ntraps++;
+}
+
+/*
+ * show:
+ * returns what a certain thing will display as to the un-initiated
+ */
+
+show(y, x)
+register int y, x;
+{
+ register char ch = CCHAR( winat(y, x) );
+ register struct linked_list *it;
+ register struct thing *tp;
+
+ if (isatrap(ch)) {
+ register struct trap *trp = trap_at(y, x);
+
+ return (trp->tr_flags & ISFOUND) ? ch : trp->tr_show;
+ }
+ else if (isalpha(ch)) {
+ if ((it = find_mons(y, x)) == NULL) {
+ msg("Show: Can't find monster in show (%d, %d)", y, x);
+ return(mvwinch(stdscr, y, x));
+ }
+ tp = THINGPTR(it);
+
+ if (on(*tp, ISDISGUISE)) ch = tp->t_disguise; /* As a mimic */
+
+ /* Hide invisible creatures */
+ else if (invisible(tp)) {
+ /* We can't see surprise-type creatures through "see invisible" */
+ if (off(player,CANSEE) || on(*tp,CANSURPRISE))
+ ch = CCHAR( mvwinch(stdscr, y, x) ); /* Invisible */
+ }
+ else if (on(*tp, CANINWALL)) {
+ if (isrock(mvwinch(stdscr, y, x))) ch = CCHAR( winch(stdscr) ); /* As Xorn */
+ }
+ }
+ return ch;
+}
+
+
+/*
+ * trap_at:
+ * find the trap at (y,x) on screen.
+ */
+
+struct trap *
+trap_at(y, x)
+register int y, x;
+{
+ register struct trap *tp, *ep;
+
+ ep = &traps[ntraps];
+ for (tp = traps; tp < ep; tp++)
+ if (tp->tr_pos.y == y && tp->tr_pos.x == x)
+ break;
+ if (tp == ep)
+ debug((sprintf(prbuf, "Trap at %d,%d not in array", y, x), prbuf));
+ return tp;
+}
+
+/*
+ * weap_move:
+ * Calculate how many segments it will take to swing the given
+ * weapon (note that the weapon may actually be a stick or
+ * even something else).
+ */
+
+weap_move(wielder, weap)
+register struct thing *wielder; /* Who's wielding the weapon */
+register struct object *weap; /* The weapon */
+{
+ register int weap_rate;
+ int dexterity;
+ int strength;
+
+ if (weap == NULL) return(1); /* hand, claw, bite attacks are quick */
+
+ switch (weap->o_type) {
+ case STICK:
+ if (EQUAL(ws_type[weap->o_which], "staff"))
+ weap_rate = 2;
+ else weap_rate = 1; /* A wand */
+
+ when WEAPON:
+ weap_rate = weaps[weap->o_which].w_rate;
+
+ /* Adjust for blessed or cursed weapon */
+ if (weap->o_hplus < 0) /* Cursed */
+ weap_rate -= (weap->o_hplus - 2) / 3;
+ else if (weap_rate > 0) /* Blessed */
+ weap_rate -= (2*weap->o_hplus + weap_rate - 1) / weap_rate;
+
+ when RELIC:
+ switch (weap->o_which) {
+ case MUSTY_DAGGER:
+ case HRUGGEK_MSTAR:
+ case AXE_AKLAD:
+ case YEENOGHU_FLAIL:
+ case MING_STAFF:
+ case ORCUS_WAND:
+ case ASMO_ROD:
+ /* These operate in the blink of an eye */
+ weap_rate = 1;
+ otherwise:
+ /* What is it? */
+ weap_rate = 10;
+ debug("unknown weapon in weap_move()");
+ }
+ otherwise:
+ /* What is it? */
+ weap_rate = 10;
+ debug("unknown weapon in weap_move()");
+ }
+
+ /* Put in a dexterity bonus */
+ if (wielder == &player) dexterity = dex_compute();
+ else dexterity = wielder->t_stats.s_dext;
+ weap_rate -= dext_plus(dexterity) / 2;
+
+ /* Put in a strength bonus */
+ if (wielder == &player) strength = str_compute();
+ else strength = wielder->t_stats.s_str;
+ weap_rate -= str_plus(strength) / 2;
+
+ /* It can't speed you up and it must take SOME time */
+ if (weap_rate <= 0) weap_rate = 1;
+
+ /* Do we need to adjust for fast/slow movement? */
+ if (on(*wielder, ISSLOW) || on(*wielder, ISDANCE)) weap_rate *= 2;
+ if (on(*wielder, ISHASTE)) weap_rate /= 2;
+
+ /* Return the result */
+ return(weap_rate);
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/network.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/network.h Fri May 08 15:24:40 2015 -0400
@@ -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" */
diff -r d10fc4a065ac -r adfa37e67084 arogue7/new_level.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/new_level.c Fri May 08 15:24:40 2015 -0400
@@ -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; it_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; jr_max.y-1; j++)
+ for (i=1; ir_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;
+ }
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/options.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/options.c Fri May 08 15:24:40 2015 -0400
@@ -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
+#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; io_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);
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/outside.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/outside.c Fri May 08 15:24:40 2015 -0400
@@ -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 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;
+{
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/pack.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/pack.c Fri May 08 15:24:40 2015 -0400
@@ -0,0 +1,1548 @@
+/*
+ * pack.c - Routines to deal with the pack.
+ *
+ * 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
+#include "rogue.h"
+#ifdef PC7300
+#include "menu.h"
+#endif
+
+/*
+ * Routines to deal with the pack
+ */
+
+/*
+ * add_pack:
+ * Pick up an object and add it to the pack. If the argument is non-null
+ * use it as the linked_list pointer instead of gettting it off the ground.
+ */
+bool
+add_pack(item, silent, packret)
+register struct linked_list *item, **packret;
+bool silent;
+{
+ register struct linked_list *ip, *lp, *ap;
+ register struct object *obj, *op;
+ register bool exact, from_floor;
+
+ if (packret != NULL)
+ *packret = NULL;
+
+ if (item == NULL)
+ {
+ from_floor = TRUE;
+ if ((item = find_obj(hero.y, hero.x)) == NULL)
+ return(FALSE);
+ }
+ else
+ from_floor = FALSE;
+ obj = OBJPTR(item);
+ /*
+ * If it is gold, just add its value to rogue's purse and get rid
+ * of it.
+ */
+ if (obj->o_type == GOLD) {
+ register struct linked_list *mitem;
+ register struct thing *tp;
+
+ if (!silent) {
+ if (!terse) addmsg("You found ");
+ msg("%d gold pieces.", obj->o_count);
+ }
+
+ /* First make sure no greedy monster is after this gold.
+ * If so, make the monster run after the rogue instead.
+ */
+ for (mitem = mlist; mitem != NULL; mitem = next(mitem)) {
+ tp = THINGPTR(mitem);
+ if (tp->t_dest == &obj->o_pos) tp->t_dest = &hero;
+ }
+
+ purse += obj->o_count;
+ if (from_floor) {
+ detach(lvl_obj, item);
+ if ((ap = find_obj(hero.y, hero.x)) == NULL)
+ mvaddch(hero.y,hero.x,(roomin(&hero)==NULL ? PASSAGE : FLOOR));
+ else
+ mvaddch(hero.y,hero.x,(OBJPTR(ap))->o_type);
+ }
+ o_discard(item);
+ return(TRUE);
+ }
+
+ /*
+ * see if he can carry any more weight
+ */
+ if (itemweight(obj) + pstats.s_pack > pstats.s_carry) {
+ msg("Too much for you to carry.");
+ return FALSE;
+ }
+ /*
+ * Link it into the pack. Search the pack for a object of similar type
+ * if there isn't one, stuff it at the beginning, if there is, look for one
+ * that is exactly the same and just increment the count if there is.
+ * it that. Food is always put at the beginning for ease of access, but
+ * is not ordered so that you can't tell good food from bad. First check
+ * to see if there is something in thr same group and if there is then
+ * increment the count.
+ */
+ if (obj->o_group)
+ {
+ for (ip = pack; ip != NULL; ip = next(ip))
+ {
+ op = OBJPTR(ip);
+ if (op->o_group == obj->o_group)
+ {
+ /*
+ * Put it in the pack and notify the user
+ */
+ op->o_count += obj->o_count;
+ if (from_floor)
+ {
+ detach(lvl_obj, item);
+ if ((ap = find_obj(hero.y, hero.x)) == NULL)
+ mvaddch(hero.y,hero.x,
+ (roomin(&hero)==NULL ? PASSAGE : FLOOR));
+ else
+ mvaddch(hero.y,hero.x,(OBJPTR(ap))->o_type);
+ }
+ o_discard(item);
+ item = ip;
+ goto picked_up;
+ }
+ }
+ }
+
+ /*
+ * Check for and deal with scare monster scrolls
+ */
+ if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
+ if (obj->o_flags & ISCURSED)
+ {
+ msg("The scroll turns to dust as you pick it up.");
+ detach(lvl_obj, item);
+ if ((ap = find_obj(hero.y, hero.x)) == NULL)
+ mvaddch(hero.y,hero.x,(roomin(&hero)==NULL ? PASSAGE : FLOOR));
+ else
+ mvaddch(hero.y,hero.x,(OBJPTR(ap))->o_type);
+ return(TRUE);
+ }
+
+ /*
+ * Search for an object of the same type
+ */
+ exact = FALSE;
+ for (ip = pack; ip != NULL; ip = next(ip))
+ {
+ op = OBJPTR(ip);
+ if (obj->o_type == op->o_type)
+ break;
+ }
+ if (ip == NULL)
+ {
+ /*
+ * Put it at the end of the pack since it is a new type
+ */
+ for (ip = pack; ip != NULL; ip = next(ip))
+ {
+ op = OBJPTR(ip);
+ if (op->o_type != FOOD)
+ break;
+ lp = ip;
+ }
+ }
+ else
+ {
+ /*
+ * Search for an object which is exactly the same
+ */
+ while (ip != NULL && op->o_type == obj->o_type)
+ {
+ if (op->o_which == obj->o_which)
+ {
+ exact = TRUE;
+ break;
+ }
+ lp = ip;
+ if ((ip = next(ip)) == NULL)
+ break;
+ op = OBJPTR(ip);
+ }
+ }
+ /*
+ * Check if there is room
+ */
+ if (ip == NULL || !exact || !ISMULT(obj->o_type)) {
+ if (inpack == MAXPACK-1) {
+ msg(terse ? "No room." : "You can't carry anything else.");
+ return(FALSE);
+ }
+ }
+ inpack++;
+ if (from_floor)
+ {
+ detach(lvl_obj, item);
+ if ((ap = find_obj(hero.y, hero.x)) == NULL)
+ mvaddch(hero.y,hero.x,(roomin(&hero)==NULL ? PASSAGE : FLOOR));
+ else
+ mvaddch(hero.y,hero.x,(OBJPTR(ap))->o_type);
+ }
+ if (ip == NULL)
+ {
+ /*
+ * Didn't find an exact match, just stick it here
+ */
+ if (pack == NULL)
+ pack = item;
+ else
+ {
+ lp->l_next = item;
+ item->l_prev = lp;
+ item->l_next = NULL;
+ }
+ }
+ else
+ {
+ /*
+ * If we found an exact match. If it is food,
+ * increase the count, otherwise put it with its clones.
+ */
+ if (exact && ISMULT(obj->o_type))
+ {
+ op->o_count += obj->o_count;
+ inpack--; /* adjust for previous addition */
+ o_discard(item);
+ item = ip;
+ goto picked_up;
+ }
+ if ((item->l_prev = prev(ip)) != NULL)
+ item->l_prev->l_next = item;
+ else
+ pack = item;
+ item->l_next = ip;
+ ip->l_prev = item;
+ }
+picked_up:
+ /*
+ * Notify the user
+ */
+ obj = OBJPTR(item);
+ if (!silent)
+ {
+ if (!terse)
+ addmsg("You now have ");
+ msg("%s (%c)", inv_name(obj, !terse), pack_char(pack, obj));
+ }
+
+ /* Relics can do strange things when you pick them up */
+ if (obj->o_type == RELIC) {
+ switch (obj->o_which) {
+ /* the ankh of Heil gives you prayers */
+ case HEIL_ANKH:
+ msg("The ankh welds itself into your hand.");
+ if (player.t_ctype != C_CLERIC && player.t_ctype != C_PALADIN)
+ fuse(prayer_recovery, 0, SPELLTIME, AFTER);
+
+ /* A cloak must be worn. */
+ when EMORI_CLOAK:
+ if (cur_armor != NULL || cur_misc[WEAR_CLOAK]) {
+ msg("The cloak insists you remove your current garments.");
+ if (!dropcheck(cur_armor != NULL ? cur_armor
+ : cur_misc[WEAR_CLOAK])) {
+ pstats.s_hpt = -1;
+ msg("The cloak constricts around you.");
+ msg("It draws your life force from you!!! -- More --");
+ wait_for(' ');
+ death(D_RELIC);
+ }
+ }
+ if (obj->o_charges < 0) /* should never happen, but.... */
+ obj->o_charges = 0;
+ if (obj->o_charges == 0)
+ fuse(cloak_charge, obj, CLOAK_TIME, AFTER);
+
+ /* The amulet must be worn. */
+ when STONEBONES_AMULET:
+ case YENDOR_AMULET:
+ if (cur_misc[WEAR_JEWEL] ||
+ cur_relic[STONEBONES_AMULET] ||
+ cur_relic[YENDOR_AMULET]) {
+ msg("You have an urge to remove your current amulet.");
+ }
+ if((cur_misc[WEAR_JEWEL] && !dropcheck(cur_misc[WEAR_JEWEL])) ||
+ cur_relic[STONEBONES_AMULET] ||
+ cur_relic[YENDOR_AMULET]) {
+ pstats.s_hpt = -1;
+ msg("The %s begins pulsing.", inv_name(obj, TRUE));
+ msg("It fades away.... -- More --");
+ wait_for(' ');
+ death(D_RELIC);
+ }
+ msg("The %s welds itself into your chest.",inv_name(obj,TRUE));
+
+ /* The eye must be inserted in eye socket */
+ when EYE_VECNA:
+ msg("The eye forces you to jam it into your eye socket!");
+ pstats.s_hpt -= 75;
+ if (pstats.s_hpt < 0) {
+ msg ("The pain is too much for you! -- More --");
+ wait_for(' ');
+ death(D_RELIC);
+ }
+ waste_time();
+ msg("The excrutiating pain slowly turns into a dull throb.");
+
+ when QUILL_NAGROM:
+ fuse(quill_charge,0,player.t_ctype==C_MAGICIAN ? 4 : 8,AFTER);
+
+ /* Weapons will insist on being wielded. */
+ when MUSTY_DAGGER:
+ case HRUGGEK_MSTAR:
+ case YEENOGHU_FLAIL:
+ case AXE_AKLAD:
+ /* For the daggers start a fuse to change player to a thief. */
+ /* and set a daemon to eat gold. */
+ if (obj->o_which == MUSTY_DAGGER) {
+ fuse(changeclass, C_THIEF, roll(20, 20), AFTER);
+ if (purse > 0)
+ msg("Your purse feels lighter");
+ else
+ purse = 1; /* fudge to get right msg from eat_gold() */
+ eat_gold(obj);
+ daemon(eat_gold, obj, AFTER);
+ }
+ /* For the axe start a fuse to change player to a fighter. */
+ if (obj->o_which == AXE_AKLAD)
+ fuse(changeclass, C_FIGHTER, roll(20, 20), AFTER);
+ if (cur_weapon != NULL) {
+ msg("The artifact insists you release your current weapon.");
+ if (!dropcheck(cur_weapon)) {
+ pstats.s_hpt = -1;
+ msg("The artifact forces your weapon into your heart.");
+ msg("It hums with satisfaction. -- More --");
+ wait_for(' ');
+ death(D_RELIC);
+ }
+ }
+ cur_weapon = obj;
+
+ when SURTUR_RING:
+ msg("The ring forces itself through your nose!");
+ pstats.s_hpt -= 22;
+ if (pstats.s_hpt < 0) {
+ msg ("The pain is too much for you! -- More --");
+ wait_for(' ');
+ death(D_RELIC);
+ }
+ waste_time();
+ turn_on(player, NOFIRE);
+ msg("The pain slowly subsides.");
+ otherwise:
+ break;
+ }
+ cur_relic[obj->o_which]++; /* Note that we have it */
+ }
+
+ updpack(FALSE, &player);
+ if (packret != NULL)
+ *packret = item;
+ return(TRUE);
+}
+
+#ifdef PC7300
+static menu_t Display; /* The menu structure */
+static mitem_t Dispitems[MAXPACK+1]; /* Info for each line */
+static char Displines[MAXPACK+1][LINELEN+1]; /* The lines themselves */
+#endif
+
+/*
+ * inventory:
+ * list what is in the pack
+ */
+inventory(list, type)
+register struct linked_list *list;
+register int type;
+{
+ register struct object *obj;
+ register char ch;
+ register int n_objs, cnt, maxx, curx;
+ char inv_temp[2*LINELEN+1];
+
+ cnt = 0;
+ n_objs = 0;
+ for (ch = 'a'; list != NULL; ch++, list = next(list)) {
+ obj = OBJPTR(list);
+ if (!is_type(obj, type))
+ continue;
+ switch (n_objs++) {
+ /*
+ * For the first thing in the inventory, just save the string
+ * in case there is only one.
+ */
+ case 0:
+ sprintf(inv_temp, "%c) %s", ch, inv_name(obj, FALSE));
+ break;
+ /*
+ * If there is more than one, clear the screen, print the
+ * saved message and fall through to ...
+ */
+ case 1:
+ if (slow_invent)
+ msg(inv_temp);
+ else
+ {
+ wclear(hw);
+ waddstr(hw, inv_temp);
+ waddch(hw, '\n');
+
+ maxx = strlen(inv_temp); /* Length of the listing */
+
+#ifdef PC7300
+ /* Put it into the PC menu display */
+ strcpy(Displines[0], inv_temp);
+ Dispitems[0].mi_name = Displines[0];
+ Dispitems[0].mi_flags = 0;
+ Dispitems[0].mi_val = 0;
+#endif
+ }
+ /*
+ * Print the line for this object
+ */
+ default:
+ if (ch > 'z')
+ ch = 'A';
+ if (slow_invent)
+ msg("%c) %s", ch, inv_name(obj, FALSE));
+ else {
+ if (++cnt >= lines - 2) { /* if bottom of screen */
+ dbotline(hw, morestr);
+ cnt = 0;
+ wclear(hw);
+ }
+ sprintf(inv_temp, "%c) %s\n", ch, inv_name(obj, FALSE));
+ curx = strlen(inv_temp) - 1; /* Don't count new-line */
+ if (curx > maxx) maxx = curx;
+ waddstr(hw, inv_temp);
+#ifdef PC7300
+ /* Put it into the PC menu display */
+ strcpy(Displines[n_objs-1], inv_temp);
+ Displines[n_objs-1][curx] = '\0'; /* Strip newline */
+ Dispitems[n_objs-1].mi_name = Displines[n_objs-1];
+ Dispitems[n_objs-1].mi_flags = 0;
+ Dispitems[n_objs-1].mi_val = 0;
+#endif
+ }
+ }
+ }
+ if (n_objs == 0) {
+ if (terse)
+ msg(type == ALL ? "Empty handed." :
+ "Nothing appropriate");
+ else
+ msg(type == ALL ? "You are empty handed." :
+ "You don't have anything appropriate");
+ return FALSE;
+ }
+ if (n_objs == 1) {
+ msg(inv_temp);
+ return TRUE;
+ }
+ if (!slow_invent)
+ {
+#ifdef PC7300
+ /* Place an end marker for the items */
+ Dispitems[n_objs].mi_name = 0;
+
+ /* Set up the main menu structure */
+ Display.m_label = "Inventory";
+ Display.m_title = "Pack Contents";
+ Display.m_prompt = "Press Cancl to continue.";
+ Display.m_curptr = '\0';
+ Display.m_markptr = '\0';
+ Display.m_flags = 0;
+ Display.m_selcnt = 0;
+ 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) return TRUE;
+#endif
+ waddstr(hw, spacemsg);
+ curx = strlen(spacemsg);
+ if (curx > maxx) maxx = curx;
+
+ /*
+ * If we have fewer than half a screenful, don't clear the screen.
+ * Leave an extra blank line at the bottom and 3 blank columns
+ * to he right.
+ */
+ if (menu_overlay && n_objs < lines / 2 + 2) {
+ over_win(cw, hw, n_objs + 2, maxx + 3, n_objs, curx, ' ');
+ return TRUE;
+ }
+
+ draw(hw);
+ wait_for(' ');
+ clearok(cw, TRUE);
+ touchwin(cw);
+ }
+ return TRUE;
+}
+
+/*
+ * picky_inven:
+ * Allow player to inventory a single item
+ */
+void
+picky_inven()
+{
+ register struct linked_list *item;
+ register char ch, mch;
+
+ if (pack == NULL)
+ msg("You aren't carrying anything");
+ else if (next(pack) == NULL)
+ msg("a) %s", inv_name(OBJPTR(pack), FALSE));
+ else
+ {
+ msg(terse ? "Item: " : "Which item do you wish to inventory: ");
+ mpos = 0;
+ if ((mch = readchar()) == ESCAPE)
+ {
+ msg("");
+ return;
+ }
+
+ /* Check for a special character */
+ switch (mch) {
+ case FOOD:
+ case SCROLL:
+ case POTION:
+ case RING:
+ case STICK:
+ case RELIC:
+ case ARMOR:
+ case WEAPON:
+ case MM:
+ msg("");
+ if (get_item(pack, NULL, mch, FALSE, FALSE) == NULL) {
+ if (terse) msg("None in pack.");
+ else msg("You have no %c in your pack.", mch);
+ }
+ return;
+ }
+
+ for (ch = 'a', item = pack; item != NULL; item = next(item), ch++)
+ if (ch == mch)
+ {
+ msg("%c) %s",ch,inv_name(OBJPTR(item), FALSE));
+ return;
+ }
+ if (!terse)
+ msg("'%s' not in pack.", unctrl(mch));
+ msg("Range is 'a' to '%c'", --ch);
+ }
+}
+
+
+/*
+ * get_item:
+ * pick something out of a pack for a purpose
+ */
+struct linked_list *
+get_item(list, purpose, type, askfirst, showcost)
+reg struct linked_list *list;
+char *purpose; /* NULL if we should be silent (no prompts) */
+int type;
+bool askfirst, showcost;
+{
+ reg struct linked_list *item;
+ reg struct object *obj;
+ reg int cnt, pagecnt, ch, och, maxx, curx, confused;
+ struct linked_list *saveitem;
+ char description[2*LINELEN+1];
+ char cost[LINELEN/2];
+#ifdef PC7300
+ int menucount = 0;
+ int usemenu = 1;
+#endif
+
+ /*
+ * If this is the player's pack and the player is confused, we
+ * might just take anything.
+ */
+ if (list == player.t_pack && on(player, ISHUH) && rnd(100) < 75)
+ confused = 1;
+ else confused = 0;
+
+ cnt = 0;
+ if (list == NULL) {
+ msg("You aren't carrying anything.");
+ return NULL;
+ }
+ /* see if we have any of the type requested */
+ for(ch = 'a',item = list ; item != NULL ; item = next(item), ch++) {
+ obj = OBJPTR(item);
+ if (is_type(obj, type)) {
+ cnt++;
+ saveitem = item;
+ }
+ }
+ if (cnt == 0) {
+ if (purpose) msg("Nothing to %s", purpose);
+ after = FALSE;
+ return NULL;
+ }
+ else if (cnt == 1) { /* only found one of 'em */
+ obj = OBJPTR(saveitem);
+ while(TRUE) {
+ if (purpose) { /* Should we prompt the player? */
+ msg("%s what (* for the item)?",purpose);
+ ch = tolower(readchar());
+ }
+ else {
+ ch = pack_char(list, obj);
+ msg("%c) %s", ch, inv_name(obj,FALSE));
+ }
+
+ if (ch == '*') {
+ mpos = 0;
+ msg("%c) %s",pack_char(list, obj),inv_name(obj,FALSE));
+ continue;
+ }
+ if (ch == ESCAPE) {
+ msg("");
+ after = FALSE;
+ return NULL;
+ }
+ for(item = list,och = 'a'; item != NULL; item = next(item),och++) {
+ if (ch == och) break;
+ if (och == 'z') och = 'A' - 1;
+ }
+ if (item == NULL) {
+ msg("Please specify a letter between 'a' and '%c'",
+ och == 'A' ? 'z' : och-1);
+ continue;
+ }
+ if (is_type (OBJPTR(item), type)) {
+ if (purpose) mpos = 0;
+ return item;
+ }
+ else
+ msg ("You can't %s that!", purpose);
+
+ }
+ }
+ while (TRUE) {
+ if (!askfirst && purpose) {
+ msg("%s what? (* for list): ",purpose);
+ ch = readchar();
+ }
+ else ch = '*';
+
+ mpos = 0;
+ if (ch == ESCAPE) { /* abort if escape hit */
+ after = FALSE;
+ msg(""); /* clear display */
+ return NULL;
+ }
+
+ if (ch == '*') {
+ wclear(hw);
+ pagecnt = 0;
+ maxx = 0;
+ for(item = list,ch = 'a'; item != NULL ; item = next(item), ch++) {
+ obj = OBJPTR(item);
+ if (!is_type(OBJPTR(item), type))
+ continue;
+ cost[0] = '\0';
+ if (showcost) {
+ sprintf(description, "[%d] ", get_worth(obj));
+ sprintf(cost, "%8.8s", description);
+ }
+ sprintf(description,"%c) %s%s\n\r",ch,cost,inv_name(obj,FALSE));
+ waddstr(hw, description);
+ curx = strlen(description) - 2; /* Don't count \n or \r */
+ if (maxx < curx) maxx = curx;
+#ifdef PC7300
+ if (usemenu) {
+ /* Put it into the PC menu display */
+ strcpy(Displines[menucount], description);
+ Displines[menucount][curx] = '\0'; /* Strip newline */
+ Dispitems[menucount].mi_name = Displines[menucount];
+ Dispitems[menucount].mi_flags = 0;
+ Dispitems[menucount++].mi_val = (int) item;
+ }
+#endif
+ if (++pagecnt >= lines - 2 && next(item) != NULL) {
+ pagecnt = 0;
+ dbotline(hw, spacemsg);
+ wclear(hw);
+ }
+ if (ch == 'z') ch = 'A' - 1;
+ }
+
+ /* Put in the prompt */
+ if (purpose) sprintf(description, "%s what? ", purpose);
+ else strcpy(description, spacemsg);
+ waddstr(hw, description);
+ curx = strlen(description);
+ if (maxx < curx) maxx = curx;
+
+#ifdef PC7300
+ if (usemenu) {
+ /* Place an end marker for the items */
+ Dispitems[menucount].mi_name = 0;
+
+ /* Set up the main menu structure */
+ Display.m_label = "Sub-Inventory";
+ if (purpose) {
+ Display.m_title = description;
+ Display.m_prompt =
+ "Select an item or press Cancl for no selection.";
+ Display.m_selcnt = 1;
+ }
+ else {
+ Display.m_title = 0;
+ Display.m_prompt = "Press Cancl to continue.";
+ Display.m_selcnt = 0;
+ }
+ Display.m_curptr = '\0';
+ Display.m_markptr = '\0';
+ Display.m_flags = 0;
+ 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) {
+ msg("");
+ if (Display.m_selcnt == 0) {
+ /* Menu was cancelled */
+ if (purpose) {
+ after = FALSE;
+ return NULL; /* all done if abort */
+ }
+ else return saveitem;
+ }
+ else return (struct linked_list *) Display.m_curi->mi_val;
+ }
+ else {
+ usemenu = 0; /* Can't use the menu facilities */
+ }
+ }
+#endif
+ /* Write the screen */
+ if ((menu_overlay && cnt < lines / 2 + 2) || cnt == 1) {
+ over_win(cw, hw, cnt + 2, maxx + 3, cnt, curx, NULL);
+ cnt = -1; /* Indicate we used over_win */
+ }
+ else draw(hw);
+
+ if (purpose) {
+ do {
+ ch = tolower(readchar());
+ } until (isalpha(ch) || ch == ESCAPE);
+ }
+ else {
+ ch = pack_char(list, OBJPTR(saveitem)); /* Pick a valid item */
+ wait_for(' ');
+ }
+
+ /* Redraw original screen */
+ if (cnt < 0) {
+ clearok(cw, FALSE); /* Setup to redraw current screen */
+ touchwin(cw); /* clearing first */
+ }
+ else restscr(cw);
+
+ if(ch == ESCAPE) {
+ after = FALSE;
+ msg(""); /* clear top line */
+ return NULL; /* all done if abort */
+ }
+ /* ch has item to get from list */
+ }
+
+ for (item = list,och = 'a'; item != NULL; item = next(item),och++) {
+ if (confused) {
+ /*
+ * Confused is incremented each time so that if the rnd(cnt)
+ * clause keeps failing, confused will equal cnt for the
+ * last item of the correct type and rnd(cnt) < cnt will
+ * have to be true.
+ */
+ if (is_type(OBJPTR(item), type) && rnd(cnt) < confused++)
+ break;
+ }
+ else if (ch == och) break;
+ if (och == 'z') och = 'A' - 1;
+ }
+
+ if (item == NULL) {
+ msg("Please specify a letter between 'a' and '%c'",
+ och == 'A' ? 'z' : och-1);
+ continue;
+ }
+
+ if (is_type(OBJPTR(item), type))
+ return (item);
+ else
+ msg ("You can't %s that!", purpose);
+ }
+}
+
+pack_char(list, obj)
+register struct object *obj;
+struct linked_list *list;
+{
+ register struct linked_list *item;
+ register char c;
+
+ c = 'a';
+ for (item = list; item != NULL; item = next(item)) {
+ if (OBJPTR(item) == obj)
+ return c;
+ else {
+ if (c == 'z') c = 'A';
+ else c++;
+ }
+ }
+ return 'z';
+}
+
+
+/*
+ * cur_null:
+ * This updates cur_weapon etc for dropping things
+ */
+cur_null(op)
+reg struct object *op;
+{
+ if (op == cur_weapon) cur_weapon = NULL;
+ else if (op == cur_armor) cur_armor = NULL;
+ else if (op == cur_ring[LEFT_1]) cur_ring[LEFT_1] = NULL;
+ else if (op == cur_ring[LEFT_2]) cur_ring[LEFT_2] = NULL;
+ else if (op == cur_ring[LEFT_3]) cur_ring[LEFT_3] = NULL;
+ else if (op == cur_ring[LEFT_4]) cur_ring[LEFT_4] = NULL;
+ else if (op == cur_ring[RIGHT_1]) cur_ring[RIGHT_1] = NULL;
+ else if (op == cur_ring[RIGHT_2]) cur_ring[RIGHT_2] = NULL;
+ else if (op == cur_ring[RIGHT_3]) cur_ring[RIGHT_3] = NULL;
+ else if (op == cur_ring[RIGHT_4]) cur_ring[RIGHT_4] = NULL;
+ else if (op == cur_misc[WEAR_BOOTS]) cur_misc[WEAR_BOOTS] = NULL;
+ else if (op == cur_misc[WEAR_JEWEL]) cur_misc[WEAR_JEWEL] = NULL;
+ else if (op == cur_misc[WEAR_GAUNTLET]) cur_misc[WEAR_GAUNTLET] = NULL;
+ else if (op == cur_misc[WEAR_CLOAK]) cur_misc[WEAR_CLOAK] = NULL;
+ else if (op == cur_misc[WEAR_BRACERS]) cur_misc[WEAR_BRACERS] = NULL;
+ else if (op == cur_misc[WEAR_NECKLACE]) cur_misc[WEAR_NECKLACE] = NULL;
+}
+
+/*
+ * idenpack:
+ * Identify all the items in the pack
+ */
+idenpack()
+{
+ reg struct linked_list *pc;
+
+ for (pc = pack ; pc != NULL ; pc = next(pc))
+ whatis(pc);
+}
+
+is_type (obj, type)
+register struct object *obj;
+register int type;
+{
+ register bool current;
+
+ if (type == obj->o_type)
+ return (TRUE);
+
+ switch (type) {
+ case ALL:
+ return (TRUE);
+ when READABLE:
+ if (obj->o_type == SCROLL ||
+ (obj->o_type == MM && obj->o_which == MM_SKILLS))
+ return (TRUE);
+ when QUAFFABLE:
+ if (obj->o_type == POTION ||
+ (obj->o_type == MM && obj->o_which == MM_JUG))
+ return (TRUE);
+ when ZAPPABLE:
+ if (obj->o_type == STICK) return (TRUE);
+ if (obj->o_type == RELIC)
+ switch (obj->o_which) {
+ case MING_STAFF:
+ case ASMO_ROD:
+ case ORCUS_WAND:
+ case EMORI_CLOAK:
+ return (TRUE);
+ }
+ when WEARABLE:
+ case REMOVABLE:
+ current = is_current(obj);
+
+ /*
+ * Don't wear thing we are already wearing or remove things
+ * we aren't wearing.
+ */
+ if (type == WEARABLE && current) return (FALSE);
+ else if (type == REMOVABLE && !current) return (FALSE);
+
+ switch (obj->o_type) {
+ case RELIC:
+ switch (obj->o_which) {
+ case HEIL_ANKH:
+ case EMORI_CLOAK:
+ return (TRUE);
+ }
+ when MM:
+ switch (obj->o_which) {
+ case MM_ELF_BOOTS:
+ case MM_DANCE:
+ case MM_BRACERS:
+ case MM_DISP:
+ case MM_PROTECT:
+ case MM_G_DEXTERITY:
+ case MM_G_OGRE:
+ case MM_JEWEL:
+ case MM_R_POWERLESS:
+ case MM_FUMBLE:
+ case MM_STRANGLE:
+ case MM_ADAPTION:
+ return (TRUE);
+ }
+ when ARMOR:
+ case RING:
+ return (TRUE);
+ }
+ when CALLABLE:
+ switch (obj->o_type) {
+ case RING: if (!r_know[obj->o_which]) return(TRUE);
+ when POTION: if (!p_know[obj->o_which]) return(TRUE);
+ when STICK: if (!ws_know[obj->o_which]) return(TRUE);
+ when SCROLL: if (!s_know[obj->o_which]) return(TRUE);
+ when MM: if (!m_know[obj->o_which]) return(TRUE);
+ }
+ when WIELDABLE:
+ switch (obj->o_type) {
+ case STICK:
+ case WEAPON:
+ return(TRUE);
+ when RELIC:
+ switch (obj->o_which) {
+ case MUSTY_DAGGER:
+ case HRUGGEK_MSTAR:
+ case YEENOGHU_FLAIL:
+ case AXE_AKLAD:
+ case MING_STAFF:
+ case ORCUS_WAND:
+ case ASMO_ROD:
+ return(TRUE);
+ }
+ }
+ when IDENTABLE:
+ if (!(obj->o_flags & ISKNOW) && obj->o_type != FOOD)
+ return (TRUE);
+ if (obj->o_type == MM) {
+ switch (obj->o_which) {
+ case MM_JUG:
+ /* Can still identify a jug if we don't know the potion */
+ if (obj->o_ac != JUG_EMPTY && !p_know[obj->o_ac])
+ return (TRUE);
+ }
+ }
+ when USEABLE:
+ if (obj->o_type == MM) {
+ switch(obj->o_which) {
+ case MM_BEAKER:
+ case MM_BOOK:
+ case MM_OPEN:
+ case MM_HUNGER:
+ case MM_DRUMS:
+ case MM_DISAPPEAR:
+ case MM_CHOKE:
+ case MM_KEOGHTOM:
+ return (TRUE);
+ }
+ }
+ else if (obj->o_type == RELIC) {
+ switch (obj->o_which) {
+ case EMORI_CLOAK:
+ case BRIAN_MANDOLIN:
+ case HEIL_ANKH:
+ case YENDOR_AMULET:
+ case STONEBONES_AMULET:
+ case GERYON_HORN:
+ case EYE_VECNA:
+ case QUILL_NAGROM:
+ case SURTUR_RING:
+ return (TRUE);
+ }
+ }
+ else if (obj->o_type == POTION) {
+ /*
+ * only assassins can use poison
+ */
+ if (player.t_ctype == C_ASSASIN && obj->o_which == P_POISON)
+ return(TRUE);
+ }
+ when PROTECTABLE:
+ switch (obj->o_type) {
+ case WEAPON:
+ if ((obj->o_flags & ISMETAL) == 0) return (FALSE);
+
+ /* Fall through */
+ case ARMOR:
+ return (TRUE);
+
+ when MM:
+ if (obj->o_which == MM_BRACERS) return (TRUE);
+ }
+ }
+ return(FALSE);
+}
+
+del_pack(item)
+register struct linked_list *item;
+{
+ register struct object *obj;
+
+ obj = OBJPTR(item);
+ if (obj->o_count > 1) {
+ obj->o_count--;
+ }
+ else {
+ cur_null(obj);
+ detach(pack, item);
+ o_discard(item);
+ inpack--;
+ }
+}
+
+/*
+ * carry_obj:
+ * Check to see if a monster is carrying something and, if so, give
+ * it to him.
+ */
+
+carry_obj(mp, chance)
+register struct thing *mp;
+int chance;
+{
+ reg struct linked_list *item;
+ reg struct object *obj;
+
+ /*
+ * If there is no chance, just return.
+ * Note that this means there must be a "chance" in order for
+ * the creature to carry a relic.
+ */
+ if (chance <= 0) return;
+
+ /*
+ * check for the relic/artifacts
+ * Do the relics first so they end up last in the pack. Attach()
+ * always adds things to the beginning. This way they will be the
+ * last things dropped when the creature is killed. This will ensure
+ * the relic will be on top if there is a stack of item lying on the
+ * floor and so the hero will know where it is if he's trying to
+ * avoid it. Note that only UNIQUEs carry relics.
+ */
+ if (on(*mp, ISUNIQUE)) {
+ if (on(*mp, CARRYMDAGGER)) {
+ item = spec_item(RELIC, MUSTY_DAGGER, NULL, NULL);
+ obj = OBJPTR(item);
+ obj->o_pos = mp->t_pos;
+ attach(mp->t_pack, item);
+ }
+
+ if (on(*mp, CARRYCLOAK)) {
+ item = spec_item(RELIC, EMORI_CLOAK, NULL, NULL);
+ obj = OBJPTR(item);
+ obj->o_pos = mp->t_pos;
+ attach(mp->t_pack, item);
+ }
+
+ if (on(*mp, CARRYANKH)) {
+ item = spec_item(RELIC, HEIL_ANKH, NULL, NULL);
+ obj = OBJPTR(item);
+ obj->o_pos = mp->t_pos;
+ attach(mp->t_pack, item);
+ }
+
+ if (on(*mp, CARRYSTAFF)) {
+ item = spec_item(RELIC, MING_STAFF, NULL, NULL);
+ obj = OBJPTR(item);
+ obj->o_pos = mp->t_pos;
+ attach(mp->t_pack, item);
+ }
+
+ if (on(*mp, CARRYWAND)) {
+ item = spec_item(RELIC, ORCUS_WAND, NULL, NULL);
+ obj = OBJPTR(item);
+ obj->o_pos = mp->t_pos;
+ attach(mp->t_pack, item);
+ }
+
+ if (on(*mp, CARRYROD)) {
+ item = spec_item(RELIC, ASMO_ROD, NULL, NULL);
+ obj = OBJPTR(item);
+ obj->o_pos = mp->t_pos;
+ attach(mp->t_pack, item);
+ }
+
+ if (on(*mp, CARRYYAMULET)) {
+ item = spec_item(RELIC, YENDOR_AMULET, NULL, NULL);
+ obj = OBJPTR(item);
+ obj->o_pos = mp->t_pos;
+ attach(mp->t_pack, item);
+ }
+
+ if (on(*mp, CARRYBAMULET)) {
+ item = spec_item(RELIC, STONEBONES_AMULET, NULL, NULL);
+ obj = OBJPTR(item);
+ obj->o_pos = mp->t_pos;
+ attach(mp->t_pack, item);
+ }
+
+ if (on(*mp, CARRYMANDOLIN)) {
+ item = spec_item(RELIC, BRIAN_MANDOLIN, NULL, NULL);
+ obj = OBJPTR(item);
+ obj->o_pos = mp->t_pos;
+ attach(mp->t_pack, item);
+ }
+ if (on(*mp, CARRYEYE)) {
+ item = spec_item(RELIC, EYE_VECNA, NULL, NULL);
+ obj = OBJPTR(item);
+ obj->o_pos = mp->t_pos;
+ attach(mp->t_pack, item);
+ }
+ if (on(*mp, CARRYAXE)) {
+ item = spec_item(RELIC, AXE_AKLAD, NULL, NULL);
+ obj = OBJPTR(item);
+ obj->o_pos = mp->t_pos;
+ attach(mp->t_pack, item);
+ }
+ if (on(*mp, CARRYQUILL)) {
+ register int i, howmany;
+
+ item = spec_item(RELIC, QUILL_NAGROM, NULL, NULL);
+ obj = OBJPTR(item);
+ obj->o_pos = mp->t_pos;
+ obj->o_charges = rnd(QUILLCHARGES);
+ attach(mp->t_pack, item);
+ howmany = roll(4,3);
+ for (i=0; io_pos = mp->t_pos;
+ attach(mp->t_pack, item);
+ }
+ }
+ if (on(*mp, CARRYMSTAR)) {
+ item = spec_item(RELIC, HRUGGEK_MSTAR, NULL, NULL);
+ obj = OBJPTR(item);
+ obj->o_pos = mp->t_pos;
+ attach(mp->t_pack, item);
+ }
+ if (on(*mp, CARRYFLAIL)) {
+ item = spec_item(RELIC, YEENOGHU_FLAIL, NULL, NULL);
+ obj = OBJPTR(item);
+ obj->o_pos = mp->t_pos;
+ attach(mp->t_pack, item);
+ }
+ if (on(*mp, CARRYHORN)) {
+ item = spec_item(RELIC, GERYON_HORN, NULL, NULL);
+ obj = OBJPTR(item);
+ obj->o_pos = mp->t_pos;
+ attach(mp->t_pack, item);
+ }
+ if (on(*mp, CARRYSURTURRING)) {
+ item = spec_item(RELIC, SURTUR_RING, NULL, NULL);
+ obj = OBJPTR(item);
+ obj->o_pos = mp->t_pos;
+ attach(mp->t_pack, item);
+ }
+ }
+ /*
+ * If it carries gold, give it some
+ */
+ if (on(*mp, CARRYGOLD) && rnd(100) < chance) {
+ item = spec_item(GOLD, NULL, NULL, NULL);
+ obj = OBJPTR(item);
+ obj->o_count = GOLDCALC + GOLDCALC;
+ obj->o_pos = mp->t_pos;
+ attach(mp->t_pack, item);
+ }
+
+ /*
+ * If it carries food, give it some
+ */
+ if (on(*mp, CARRYFOOD) && rnd(100) < chance) {
+ item = spec_item(FOOD, NULL, NULL, NULL);
+ obj = OBJPTR(item);
+ obj->o_weight = things[TYP_FOOD].mi_wght;
+ obj->o_pos = mp->t_pos;
+ attach(mp->t_pack, item);
+ }
+
+ /*
+ * If it carries a weapon, give it one
+ */
+ if (on(*mp, CARRYWEAPON) && rnd(100) < chance) {
+ int type, hit, dam;
+
+ /* Get the "bonuses" */
+ hit = rnd(5 + (vlevel / 5)) - 2;
+ dam = rnd(5 + (vlevel / 5)) - 2;
+
+ /* Only choose an appropriate type of weapon */
+ switch (rnd(12)) {
+ case 0: type = DAGGER;
+ when 1: type = BATTLEAXE;
+ when 2: type = MACE;
+ when 3: type = SWORD;
+ when 4: type = PIKE;
+ when 5: type = HALBERD;
+ when 6: type = SPETUM;
+ when 7: type = BARDICHE;
+ when 8: type = TRIDENT;
+ when 9: type = BASWORD;
+ when 10:type = DART;
+ otherwise: type = TWOSWORD;
+ }
+
+ /* Create the item */
+ item = spec_item(WEAPON, type, hit, dam);
+ obj = OBJPTR(item);
+ obj->o_pos = mp->t_pos;
+ attach(mp->t_pack, item);
+ }
+
+ /*
+ * If it carries a dagger, give it one
+ */
+ if (on(*mp, CARRYDAGGER) && rnd(100) < chance) {
+ int hit, dam;
+
+ /* Get the "bonuses" */
+ hit = rnd(3 + (vlevel / 5)) - 1;
+ dam = rnd(3 + (vlevel / 5)) - 1;
+
+ /* Create the item */
+ item = spec_item(WEAPON, DAGGER, hit, dam);
+ obj = OBJPTR(item);
+ obj->o_pos = mp->t_pos;
+ attach(mp->t_pack, item);
+ }
+
+ /*
+ * If it carries a scroll, give it one
+ */
+ if (on(*mp, CARRYSCROLL) && rnd(100) < chance) {
+ item = new_thing(TYP_SCROLL, TRUE);
+ obj = OBJPTR(item);
+ obj->o_pos = mp->t_pos;
+
+ /* Can the monster carry this scroll? */
+ if (obj->o_which == S_SCARE && mp->t_stats.s_intel < 16)
+ fall(item, FALSE); /* This would scare us! */
+ else attach(mp->t_pack, item);
+ }
+
+ /*
+ * If it carries a potion, give it one
+ */
+ if (on(*mp, CARRYPOTION) && rnd(100) < chance) {
+ item = new_thing(TYP_POTION, TRUE);
+ obj = OBJPTR(item);
+ obj->o_pos = mp->t_pos;
+ attach(mp->t_pack, item);
+ }
+
+ /*
+ * If it carries a ring, give it one
+ */
+ if (on(*mp, CARRYRING) && rnd(100) < chance) {
+ item = new_thing(TYP_RING, TRUE);
+ obj = OBJPTR(item);
+ obj->o_pos = mp->t_pos;
+ attach(mp->t_pack, item);
+ }
+
+ /*
+ * If it carries a wand or staff, give it one
+ */
+ if (on(*mp, CARRYSTICK) && rnd(100) < chance) {
+ item = new_thing(TYP_STICK, TRUE);
+ obj = OBJPTR(item);
+ obj->o_pos = mp->t_pos;
+ attach(mp->t_pack, item);
+ }
+
+ /*
+ * If it carries any miscellaneous magic, give it one
+ */
+ if (on(*mp, CARRYMISC) && rnd(100) < chance) {
+ item = new_thing(TYP_MM, TRUE);
+ obj = OBJPTR(item);
+ obj->o_pos = mp->t_pos;
+ attach(mp->t_pack, item);
+ }
+
+ /* Update the monster's encumberance */
+ updpack(TRUE, mp);
+}
+
+
+/*
+ * grab():
+ * See what is on the spot where the player is standing. If
+ * nothing is there, do nothing. If there is one thing, pick it
+ * up. If there are multiple things, prompt the player for what
+ * he wants (* means everything).
+ */
+
+grab(y, x)
+register y, x;
+{
+ register struct linked_list *next_item, *item;
+ register struct object *obj;
+ register int cnt, pagecnt;
+ int num_there = 0, ch, och;
+
+ /*
+ * Count how many objects there are and move them to the front
+ * of the level list.
+ */
+ for (item = lvl_obj; item != NULL; item = next_item) {
+ obj = OBJPTR(item);
+ next_item = next(item);
+ if (obj->o_pos.y == y && obj->o_pos.x == x) {
+ num_there++;
+ detach(lvl_obj, item); /* Remove it from the list */
+ attach(lvl_obj, item); /* Place it at the front of the list */
+ }
+ }
+
+ /* Nothing there. */
+ if (num_there < 1) msg("Nothing %s", terse ? "there." : "to pick up.");
+
+ /* Something or things there */
+ else {
+ char linebuf[2*LINELEN+1];
+ int curlen, maxlen = 0;
+
+ wclear(hw);
+ cnt = 0;
+ pagecnt = 0;
+ for (item = lvl_obj, ch = 'a'; item != NULL && cnt < num_there;
+ item = next(item), ch++, cnt++) {
+ obj = OBJPTR(item);
+ /* Construct how the line will look */
+ sprintf(linebuf, "%c) %s\n\r", ch, inv_name(obj,FALSE));
+
+ /* See how long it is */
+ curlen = strlen(linebuf) - 2; /* Don't count \n or \r */
+ if (maxlen < curlen) maxlen = curlen;
+
+ /* Draw it in the window */
+ waddstr(hw, linebuf);
+
+ if (++pagecnt >= lines - 2 && next(item) != NULL) {
+ pagecnt = 0;
+ maxlen = 0;
+ dbotline(hw, spacemsg);
+ wclear(hw);
+ }
+ if (ch == 'z') ch = 'A' - 1;
+ }
+
+ strcpy(linebuf, "Pick up what? (* for all): ");
+
+ /* See how long it is */
+ curlen = strlen(linebuf); /* Don't count \n or \r */
+ if (maxlen < curlen) maxlen = curlen;
+
+ /* Draw it in the window */
+ waddstr(hw, linebuf);
+
+ /*
+ * If we have fewer than half a screenful, don't clear the screen.
+ * Leave an extra blank line at the bottom and 3 blank columns
+ * to he right.
+ */
+ if (menu_overlay && num_there < lines / 2 + 2) {
+ over_win(cw, hw, num_there + 2, maxlen + 3, num_there, curlen, NULL);
+ pagecnt = -1; /* Indicate we used over_win */
+ }
+ else draw(hw); /* write screen */
+
+ for (;;) {
+ do {
+ ch = tolower(readchar());
+ } until (isalpha(ch) || ch == '*' || ch == ESCAPE);
+
+ /* Redraw original screen */
+ if (pagecnt < 0) {
+ clearok(cw, FALSE); /* Setup to redraw current screen */
+ touchwin(cw); /* clearing first */
+ }
+ else restscr(cw);
+
+ if (ch == ESCAPE) {
+ after = FALSE;
+ msg(""); /* clear top line */
+ break;
+ }
+ if (ch == '*') {
+ player.t_action = A_PICKUP;
+ return(1); /* set action to PICKUP and delay for first one */
+ }
+ /* ch has item to get from list */
+
+ cnt = 0;
+ for (item = lvl_obj, och = 'a'; item != NULL && cnt < num_there;
+ item = next(item), och++, cnt++) {
+ if (ch == och)
+ break;
+ if (och == 'z') och = 'A' - 1;
+ }
+ if (item == NULL || cnt >= num_there) {
+ wmove(hw, pagecnt < 0 ? num_there : pagecnt, 25);
+ wprintw(hw, " [between 'a' and '%c']: ",
+ och == 'A' ? 'z' : och-1);
+ if (maxlen < 49) maxlen = 49;
+
+ /*
+ * If we have fewer than half a screenful, don't clear the
+ * screen. Leave an extra blank line at the bottom and
+ * 3 blank columns to he right.
+ */
+ if (menu_overlay && num_there < lines / 2 + 2) {
+ over_win(cw, hw, num_there + 2, maxlen + 3,
+ num_there, 49, NULL);
+ cnt = -1; /* Indicate we used over_win */
+ }
+ else draw(hw); /* write screen */
+ continue;
+ }
+ else {
+ detach(lvl_obj, item);
+ if (add_pack(item, FALSE, NULL)) {
+ /*
+ * We make sure here that the dungeon floor gets
+ * updated with what's left on the vacated spot.
+ */
+ if ((item = find_obj(y, x)) == NULL) {
+ coord roomcoord; /* Needed to pass to roomin() */
+
+ roomcoord.y = y;
+ roomcoord.x = x;
+ mvaddch(y, x,
+ (roomin(&roomcoord) == NULL ? PASSAGE : FLOOR));
+ }
+ else mvaddch(y, x, (OBJPTR(item))->o_type);
+ return(1);
+ }
+ else attach(lvl_obj, item); /* Couldn't pick it up! */
+ break;
+ }
+ }
+ }
+
+ return(0);
+}
+
+/*
+ * make_sell_pack:
+ *
+ * Create a pack for sellers (a la quartermaster)
+ */
+
+make_sell_pack(tp)
+struct thing *tp;
+{
+ reg struct linked_list *item;
+ reg struct object *obj;
+ reg int sell_type, nitems, i;
+
+ /* Select the items */
+ nitems = rnd(6) + 5;
+
+ switch (rnd(9)) {
+ /* Armor */
+ case 0:
+ case 1:
+ turn_on(*tp, CARRYARMOR);
+ sell_type = TYP_ARMOR;
+ break;
+
+ /* Weapon */
+ case 2:
+ case 3:
+ turn_on(*tp, CARRYWEAPON);
+ sell_type = TYP_WEAPON;
+ break;
+
+ /* Staff or wand */
+ case 4:
+ turn_on(*tp, CARRYSTICK);
+ sell_type = TYP_STICK;
+ break;
+
+ /* Ring */
+ case 5:
+ turn_on(*tp, CARRYRING);
+ sell_type = TYP_RING;
+ break;
+
+ /* scroll */
+ case 6:
+ turn_on(*tp, CARRYSCROLL);
+ sell_type = TYP_SCROLL;
+ break;
+
+ /* potions */
+ case 7:
+ turn_on(*tp, CARRYPOTION);
+ sell_type = TYP_POTION;
+ break;
+
+ /* Miscellaneous magic */
+ case 8:
+ turn_on(*tp, CARRYMISC);
+ sell_type = TYP_MM;
+ break;
+ }
+ for (i=0; io_pos = tp->t_pos;
+ attach(tp->t_pack, item);
+ }
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/passages.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/passages.c Fri May 08 15:24:40 2015 -0400
@@ -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);
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/player.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/player.c Fri May 08 15:24:40 2015 -0400
@@ -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
+#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));
+
+ 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= 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);
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/potions.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/potions.c Fri May 08 15:24:40 2015 -0400
@@ -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 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);
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/rings.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/rings.c Fri May 08 15:24:40 2015 -0400
@@ -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);
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/rip.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/rip.c Fri May 08 15:24:40 2015 -0400
@@ -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
+#else
+#include
+#endif
+#include
+#include
+#include
+#include
+#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 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; isc_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> 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);
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/rogue.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/rogue.c Fri May 08 15:24:40 2015 -0400
@@ -0,0 +1,1689 @@
+/*
+ * rogue.c - Global game variables
+ *
+ * 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
+#include "curses.h"
+#include "rogue.h"
+#ifdef PC7300
+#include
+#endif
+
+#ifdef BSD
+char
+tolower(c)
+{
+ if (isupper(c)) return(_tolower(c));
+ else return(c);
+}
+char
+toupper(c)
+{
+ if (islower(c)) return(_toupper(c));
+ else return(c);
+}
+#endif
+
+/*
+ * Now all the global variables
+ */
+struct trap traps[MAXTRAPS];
+struct room rooms[MAXROOMS]; /* One for each room -- A level */
+struct room *oldrp; /* Roomin(&player.t_oldpos) */
+struct thing player; /* The rogue */
+struct object *cur_armor; /* What a well dresssed rogue wears */
+struct object *cur_ring[NUM_FINGERS]; /* Which rings are being worn */
+struct object *cur_misc[NUM_MM]; /* which MM's are in use */
+int cur_relic[MAXRELIC]; /* Currently used relics */
+struct linked_list *lvl_obj = NULL;
+struct linked_list *mlist = NULL;
+struct linked_list *tlist = NULL; /* list of monsters fallen down traps */
+struct linked_list *monst_dead = NULL; /* monster killed by monster */
+struct object *cur_weapon = NULL;
+int char_type = -1; /* what type of character is player */
+int foodlev = 1; /* how fast he eats food */
+int ntraps; /* Number of traps on this level */
+int trader = 0; /* no. of purchases */
+int curprice = -1; /* current price of item */
+int seed; /* Random number seed */
+int dnum; /* Dungeon number */
+int max_level; /* Deepest player has gone ever */
+int cur_max; /* Deepest player has gone currently */
+int mpos = 0;
+int level = 0;
+int purse = 0;
+int inpack = 0;
+int total = 0;
+int no_food = 0; /* how long has he gone with no food */
+int foods_this_level = 0; /* foods made per level */
+int count = 0;
+int food_left = STOMACHSIZE-MORETIME-1;
+int group = 1;
+int hungry_state = F_OKAY;
+int infest_dam=0;
+int lost_str=0;
+int lastscore = -1;
+int hold_count = 0;
+int trap_tries = 0;
+int chant_time = 0;
+int pray_time = 0;
+int spell_power = 0;
+int turns = 0; /* Number of turns player has taken */
+int quest_item = 0; /* Item player is looking for */
+int cols = 0; /* number of columns in terminal */
+int lines = 0; /* number of lines on the terminal */
+char nfloors = -1; /* Number of floors in this dungeon */
+char curpurch[LINELEN]; /* name of item ready to buy */
+char PLAYER = VPLAYER; /* what the player looks like */
+char take; /* Thing the rogue is taking */
+char prbuf[LINELEN*2]; /* Buffer for sprintfs */
+char outbuf[BUFSIZ]; /* Output buffer for stdout */
+char runch; /* Direction player is running */
+char *s_names[MAXSCROLLS]; /* Names of the scrolls */
+char *p_colors[MAXPOTIONS]; /* Colors of the potions */
+char *r_stones[MAXRINGS]; /* Stone settings of the rings */
+char *ws_made[MAXSTICKS]; /* What sticks are made of */
+char whoami[LINELEN]; /* Name of player */
+char huh[LINELEN]; /* The last message printed */
+char *s_guess[MAXSCROLLS]; /* Players guess at what scroll is */
+char *p_guess[MAXPOTIONS]; /* Players guess at what potion is */
+char *r_guess[MAXRINGS]; /* Players guess at what ring is */
+char *ws_guess[MAXSTICKS]; /* Players guess at what wand is */
+char *m_guess[MAXMM]; /* Players guess at what MM is */
+char *ws_type[MAXSTICKS]; /* Is it a wand or a staff */
+char file_name[LINELEN]; /* Save file name */
+char score_file[LINELEN]; /* Score file name */
+char home[LINELEN]; /* User's home directory */
+WINDOW *cw; /* Window that the player sees */
+WINDOW *hw; /* Used for the help command */
+WINDOW *mw; /* Used to store monsters */
+WINDOW *msgw; /* Used to display messages */
+bool pool_teleport = FALSE; /* just teleported from a pool */
+bool inwhgt = FALSE; /* true if from wghtchk() */
+bool after; /* True if we want after daemons */
+bool waswizard; /* Was a wizard sometime */
+bool s_know[MAXSCROLLS]; /* Does he know what a scroll does */
+bool p_know[MAXPOTIONS]; /* Does he know what a potion does */
+bool r_know[MAXRINGS]; /* Does he know what a ring does */
+bool ws_know[MAXSTICKS]; /* Does he know what a stick does */
+bool m_know[MAXMM]; /* Does he know what a MM does */
+bool playing = TRUE;
+bool running = FALSE;
+bool wizard = FALSE;
+bool notify = TRUE;
+bool fight_flush = FALSE;
+bool terse = FALSE;
+bool auto_pickup = TRUE;
+bool menu_overlay = TRUE;
+bool door_stop = FALSE;
+bool jump = FALSE;
+bool slow_invent = FALSE;
+bool firstmove = FALSE;
+bool askme = FALSE;
+bool in_shell = FALSE;
+bool daytime = TRUE;
+LEVTYPE levtype; /* type of level i'm on */
+
+char *nothing = "Nothing seems to happen.";
+char *spacemsg = "--Press space to continue--";
+char *morestr = "-- More --";
+char *retstr = "[Press return to continue]";
+#ifdef PC7300
+struct uwdata wdata, oldwin; /* Static window information */
+char oldtext[WTXTNUM][WTXTLEN]; /* Saved window text */
+#endif
+
+/*
+ * This lays out all the class specific details
+ *
+ * Here are the beginning experience levels for all players.
+ * All further experience levels are computed by muliplying by 2
+ * up through MAXDOUBLE. Then exp pts are calculated by adding
+ * in the cap figure. You must change MAXDOUBLE if you change the
+ * cap figure.
+ */
+struct character_types char_class[NUM_CHARTYPES] = {
+/* name exppts cap hitpts Base Maxlvl, Factor, Offset, Range */
+{ "fighter", 80, 1310720, 12, 10, 30, 2, 1, 2 },
+{ "ranger", 140, 2293760, 8, 10, 20, 2, 1, 2 },
+{ "paladin", 120, 1966080, 10, 10, 23, 2, 1, 2 },
+{ "magic user", 130, 2129920, 6, 9, 18, 2, 1, 5 },
+{ "cleric", 110, 1802240, 8, 10, 19, 2, 1, 3 },
+{ "thief", 75, 1228800, 6, 10, 25, 2, 1, 4 },
+{ "assassin", 85, 1392640, 6, 10, 25, 2, 1, 4 },
+{ "druid", 100, 1638400, 8, 10, 19, 2, 1, 3 },
+{ "monk", 95, 1556480, 6, 10, 25, 2, 1, 3 },
+{ "monster", 0, 0, 8, 7, 30, 1, 0, 2 },
+};
+
+
+/*
+ * This array lists the names of the character's abilities. It must be ordered
+ * according to the ability definitions in rogue.h.
+ */
+
+char *abilities[NUMABILITIES] = {
+ "Intelligence", "Strength", "Wisdom", "Dexterity", "Constitution", "Charisma"
+};
+
+/*
+ * NOTE: the ordering of the points in this array is critical. They MUST
+ * be listed in the following sequence:
+ *
+ * 7 4 6
+ * 1 0 2
+ * 5 3 8
+ */
+
+coord grid[9] = {{0,0},
+ { 0,-1}, { 0, 1}, {-1, 0}, { 1, 0},
+ {-1,-1}, { 1, 1}, { 1,-1}, {-1, 1}
+ };
+
+struct death_type deaths[DEATHNUM] = {
+ { D_ARROW, "an arrow"},
+ { D_DART, "a dart"},
+ { D_BOLT, "a bolt"},
+ { D_POISON, "poison"},
+ { D_POTION, "a cursed potion"},
+ { D_PETRIFY, "petrification"},
+ { D_SUFFOCATION, "suffocation"},
+ { D_INFESTATION, "a parasite"},
+ { D_DROWN, "drowning"},
+ { D_ROT, "body rot"},
+ { D_CONSTITUTION, "poor health"},
+ { D_STRENGTH, "being too weak"},
+ { D_SIGNAL, "a bug"},
+ { D_CHOKE, "dust of choking"},
+ { D_STRANGLE, "strangulation"},
+ { D_FALL, "a fall"},
+ { D_RELIC, "an artifact's wrath"},
+ { D_STARVATION, "starvation"},
+ { D_FOOD_CHOKE, "choking on food"},
+ { D_SCROLL, "reading a scroll"},
+};
+
+
+/*
+ * weapons and their attributes
+ */
+struct init_weps weaps[MAXWEAPONS] = {
+ { "mace", "2d4", "1d3", NONE, ISMETAL, 3, 100, 8 },
+ { "long sword", "1d12", "1d2", NONE, ISMETAL, 4, 60, 18 },
+ { "short bow", "1d1", "1d1", NONE, 0, 6, 40, 15 },
+ { "arrow", "1d1", "1d6", BOW, ISMANY|ISMISL, 1, 5, 1 },
+ { "dagger", "1d6", "1d4", NONE, ISMETAL|ISMISL|ISMANY,1,7,2},
+ { "rock", "1d2", "1d4", SLING, ISMANY|ISMISL, 1, 5, 1 },
+ { "two-handed sword","3d6", "1d2", NONE, ISMETAL, 5, 250, 40 },
+ { "sling", "0d0", "0d0", NONE, 0, 1, 5, 1 },
+ { "dart", "1d1", "1d3", NONE, ISMANY|ISMISL, 1, 5, 1 },
+ { "crossbow", "1d1", "1d1", NONE, 0, 6, 100, 15 },
+ { "crossbow bolt", "1d2", "1d12", CROSSBOW,ISMANY|ISMISL, 1, 7, 1 },
+ { "spear", "1d8", "2d6", NONE, ISMANY|ISMETAL|ISMISL,2,20,8},
+ { "trident", "3d4", "1d4", NONE, ISMETAL, 4, 50, 20 },
+ { "spetum", "2d6", "1d3", NONE, ISMETAL, 4, 50, 20 },
+ { "bardiche", "3d4", "1d2", NONE, ISMETAL, 4, 125, 20 },
+ { "pike", "1d12", "1d8", NONE, ISMETAL, 4, 80, 18 },
+ { "bastard sword", "2d8", "1d2", NONE, ISMETAL, 5, 100, 30 },
+ { "halberd", "2d6", "1d3", NONE, ISMETAL, 4, 175, 10 },
+ { "battle axe", "1d8", "1d3", NONE, ISMETAL, 3, 80, 10 },
+};
+
+struct init_armor armors[MAXARMORS] = {
+ { "leather armor", 11, 8, 70, 100 },
+ { "ring mail", 22, 7, 50, 250 },
+ { "studded leather armor", 33, 7, 50, 200 },
+ { "scale mail", 45, 6, 70, 250 },
+ { "padded armor", 57, 6, 150, 150 },
+ { "chain mail", 69, 5, 100, 300 },
+ { "splint mail", 80, 4, 150, 350 },
+ { "banded mail", 90, 4, 150, 350 },
+ { "plate mail", 96, 3, 400, 400 },
+ { "plate armor", 100, 2, 650, 450 },
+};
+
+struct magic_item things[NUMTHINGS] = {
+ { "potion", 260, 10 }, /* potion */
+ { "scroll", 260, 30 }, /* scroll */
+ { "food", 180, 20 }, /* food */
+ { "weapon", 80, 0 }, /* weapon */
+ { "armor", 80, 0 }, /* armor */
+ { "ring", 50, 5 }, /* ring */
+ { "stick", 60, 0 }, /* stick */
+ { "miscellaneous magic", 30, 50 }, /* miscellaneous magic */
+ { "artifact", 0, 10 }, /* artifact */
+};
+
+struct magic_item s_magic[MAXSCROLLS] = {
+ { "monster confusion", 50, 125, 0, 0 },
+ { "magic mapping", 50, 150, 0, 0 },
+ { "light", 70, 100, 21, 15 },
+ { "hold monster", 30, 200, 33, 20 },
+ { "sleep", 20, 150, 20, 0 },
+ { "enchantment", 170, 200, 9, 9 },
+ { "identify", 200, 100, 0, 25 },
+ { "scare monster", 40, 250, 27, 21 },
+ { "gold detection", 30, 110, 0, 0 },
+ { "teleportation", 60, 165, 10, 20 },
+ { "create monster", 30, 75, 0, 0 },
+ { "remove curse", 70, 120, 9, 15 },
+ { "petrification", 10, 185, 0, 0 },
+ { "genocide", 10, 300, 0, 0 },
+ { "cure disease", 80, 160, 0, 0 },
+ { "acquirement", 10, 700, 0, 0 },
+ { "protection", 30, 190, 20, 0 },
+ { "trap finding", 10, 180, 0, 0 },
+ { "runes", 10, 50, 0, 0 },
+ { "charm monster", 20, 275, 0, 15 },
+};
+
+struct magic_item p_magic[MAXPOTIONS] = {
+ { "clear thought", 50, 180, 27, 10 },
+ { "gain ability", 160, 210, 15, 15 },
+ { "see invisible", 50, 150, 25, 15 },
+ { "healing", 160, 130, 27, 27 },
+ { "monster detection", 60, 120, 0, 0 },
+ { "magic detection", 60, 105, 0, 0 },
+ { "raise level", 10, 450, 11, 10 },
+ { "haste self", 90, 180, 30, 5 },
+ { "restore abilities", 140, 140, 0, 10 },
+ { "phasing", 50, 210, 21, 20 },
+ { "invisibility", 50, 230, 0, 15 },
+ { "flying", 40, 130, 0, 20 },
+ { "food detection", 10, 150, 0, 0 },
+ { "skill", 10, 200, 20, 10 },
+ { "fire resistance", 10, 250, 0, 10 },
+ { "cold resistance", 10, 250, 0, 10 },
+ { "lightning protection", 10, 250, 0, 10 },
+ { "poison", 30, 205, 0, 0 },
+};
+
+struct magic_item r_magic[MAXRINGS] = {
+ { "protection", 50, 200, 33, 25 },
+ { "add strength", 60, 200, 33, 25 },
+ { "sustain ability", 50, 500, 0, 0 },
+ { "searching", 50, 400, 0, 0 },
+ { "extra sight", 40, 350, 0, 0 },
+ { "alertness", 40, 380, 0, 0 },
+ { "aggravate monster", 30, 100, 100, 0 },
+ { "dexterity", 60, 220, 33, 25 },
+ { "increase damage", 60, 220, 33, 25 },
+ { "regeneration", 40, 600, 0, 0 },
+ { "slow digestion", 40, 240, 15, 15 },
+ { "teleportation", 20, 100, 100, 0 },
+ { "stealth", 30, 300, 0, 0 },
+ { "add intelligence", 60, 240, 33, 25 },
+ { "increase wisdom", 60, 220, 33, 25 },
+ { "sustain health", 80, 500, 0, 0 },
+ { "carrying", 20, 100, 100, 0 },
+ { "illumination", 30, 520, 0, 0 },
+ { "delusion", 20, 100, 75, 0 },
+ { "fear", 20, 100, 100, 0},
+ { "heroism", 30, 390, 0, 0 },
+ { "fire resistance", 40, 400, 0, 0 },
+ { "warmth", 40, 400, 0, 0 },
+ { "vampiric regeneration", 10,1000, 0, 0},
+ { "free action", 10, 370, 0, 0},
+ { "teleport control", 10, 700, 0, 0},
+};
+
+struct magic_item ws_magic[MAXSTICKS] = {
+ { "light", 90, 120, 20, 20 },
+ { "striking", 60, 115, 0, 0 },
+ { "lightning", 35, 200, 0, 0 },
+ { "fire", 35, 200, 0, 0 },
+ { "cold", 35, 200, 0, 0 },
+ { "polymorph", 80, 150, 0, 0 },
+ { "magic missile", 80, 170, 0, 0 },
+ { "slow", 80, 220, 25, 20 },
+ { "drain life", 80, 210, 20, 0 },
+ { "charging", 70, 400, 0, 0 },
+ { "teleport", 90, 140, 25, 20 },
+ { "cancellation", 40, 130, 0, 0 },
+ { "confusion", 35, 100, 15, 0},
+ { "disintegration", 10, 300, 33, 0},
+ { "petrification", 30, 240, 0, 0},
+ { "paralyzation", 30, 180, 15, 0},
+ { "degeneration", 30, 250, 30, 0},
+ { "curing", 10, 250, 25, 0},
+ { "wonder", 50, 110, 0, 0},
+ { "fear", 30, 180, 0, 0},
+};
+
+/*
+ * WARNING: unique miscellaneous magic items must be put at the end
+ * of this list. They MUST be the last items. The function
+ * create_obj() in wizard.c depends on it.
+ */
+struct magic_item m_magic[MAXMM] = {
+ { "alchemy jug", 40, 240, 0, 0},
+ { "beaker of potions", 60, 300, 0, 0},
+ { "book of spells", 60, 300, 0, 0},
+ { "boots of elvenkind", 50, 500, 0, 0},
+ { "bracers of defense", 140, 100, 15, 0},
+ { "chime of opening", 50, 250, 0, 0},
+ { "chime of hunger", 50, 100,100, 0},
+ { "cloak of displacement", 60, 500, 0, 0},
+ { "cloak of protection", 70, 200, 15, 0},
+ { "drums of panic", 40, 350, 0, 0},
+ { "dust of disappearance", 40, 300, 0, 0},
+ { "dust of choking", 30, 100,100, 0},
+ { "gauntlets of dexterity", 30, 600, 25, 0},
+ { "gauntlets of ogre power", 30, 600, 25, 0},
+ { "jewel of attacks", 40, 150,100, 0},
+ { "keoghtoms ointment", 50, 200, 0, 0},
+ { "robe of powerlessness", 30, 100,100, 0},
+ { "gauntlets of fumbling", 30, 100,100, 0},
+ { "necklace of adaptation", 20, 500, 0, 0},
+ { "necklace of strangulation",30, 110,100, 0},
+ { "boots of dancing", 30, 120,100, 0},
+ { "book of skills", 20, 650, 0, 0},
+};
+
+
+struct magic_item rel_magic[MAXRELIC] = {
+ { "Daggers of Musty Doit", 0, 50000, 0, 0},
+ { "Cloak of Emori", 0, 50000, 0, 0},
+ { "Ankh of Heil", 0, 50000, 0, 0},
+ { "Staff of Ming", 0, 50000, 0, 0},
+ { "Wand of Orcus", 0, 50000, 0, 0},
+ { "Rod of Asmodeus", 0, 50000, 0, 0},
+ { "Amulet of Yendor", 0, 50000, 0, 0},
+ { "Mandolin of Brian", 0, 50000, 0, 0},
+ { "Horn of Geryon", 0, 50000, 0, 0},
+ { "Morning Star of Hruggek", 0, 50000, 0, 0},
+ { "Flail of Yeenoghu", 0, 50000, 0, 0},
+ { "Eye of Vecna", 0, 50000, 0, 0},
+ { "Axe of Aklad", 0, 50000, 0, 0},
+ { "Quill of Nagrom", 0, 50000, 0, 0},
+ { "Amulet of Stonebones", 0, 50000, 0, 0},
+ { "Ring of Surtur", 0, 50000, 0, 0},
+};
+/*
+ * food and fruits that you get
+ */
+struct magic_item foods[MAXFOODS] = {
+ { "food ration", 800, 50, 750, 0},
+ { "apple", 10, 20, 300, 0},
+ { "banana", 10, 20, 300, 0},
+ { "blueberry", 10, 20, 300, 0},
+ { "candleberry", 10, 20, 300, 0},
+ { "caprifig", 10, 20, 300, 0},
+ { "dewberry", 10, 20, 300, 0},
+ { "elderberry", 10, 20, 300, 0},
+ { "gooseberry", 10, 20, 300, 0},
+ { "guanabana", 10, 20, 300, 0},
+ { "hagberry", 10, 20, 300, 0},
+ { "jaboticaba", 10, 20, 300, 0},
+ { "peach", 10, 20, 300, 0},
+ { "pitanga", 10, 20, 300, 0},
+ { "prickly pear", 10, 20, 300, 0},
+ { "rambutan", 10, 20, 300, 0},
+ { "sapodilla", 10, 20, 300, 0},
+ { "soursop", 10, 20, 300, 0},
+ { "strawberry", 10, 20, 300, 0},
+ { "sweetsop", 10, 20, 300, 0},
+ { "whortleberry", 10, 20, 300, 0},
+};
+
+/*
+ * these are the spells that a magic user can cast
+ */
+struct spells magic_spells[MAXSPELLS] = {
+ { P_TFIND, 3, TYP_POTION, 0 },
+ { S_IDENT, 5, TYP_SCROLL, 0 },
+ { S_LIGHT, 7, TYP_SCROLL, ISBLESSED },
+ { S_REMOVE, 7, TYP_SCROLL, 0 },
+ { S_CONFUSE, 10, TYP_SCROLL, 0 },
+ { WS_MISSILE, 15, TYP_STICK, 0 },
+ { S_TELEP, 20, TYP_SCROLL, 0 },
+ { S_SLEEP, 20, TYP_SCROLL, 0 },
+ { P_FLY, 20, TYP_POTION, 0 },
+ { P_SEEINVIS, 20, TYP_POTION, 0 },
+ { WS_COLD, 25, TYP_STICK, 0 },
+ { WS_ELECT, 25, TYP_STICK, 0 },
+ { WS_FIRE, 25, TYP_STICK, 0 },
+ { P_HASTE, 30, TYP_POTION, 0 },
+ { WS_CANCEL, 30, TYP_STICK, 0 },
+ { P_PHASE, 40, TYP_POTION, 0 },
+ { S_HOLD, 50, TYP_SCROLL, 0 },
+ { WS_CHARGE, 55, TYP_STICK, ISBLESSED },
+ { S_PROTECT, 60, TYP_SCROLL, 0 },
+ { S_ALLENCH, 70, TYP_SCROLL, 0 },
+};
+
+/*
+ * these are the spells that a cleric can cast
+ */
+struct spells cleric_spells[MAXPRAYERS] = {
+ { P_MFIND, 3, TYP_POTION, 0 },
+ { P_TFIND, 7, TYP_POTION, 0 },
+ { S_LIGHT, 10, TYP_SCROLL, ISBLESSED },
+ { S_REMOVE, 15, TYP_SCROLL, 0 },
+ { P_HEALING, 20, TYP_POTION, 0 },
+ { P_FFIND, 24, TYP_POTION, 0 },
+ { S_FINDTRAPS, 26, TYP_SCROLL, 0 },
+ { S_CURING, 27, TYP_SCROLL, 0 },
+ { WS_PARALYZE, 30, TYP_STICK, ISBLESSED },
+ { S_MAP, 31, TYP_SCROLL, 0 },
+ { P_CLEAR, 32, TYP_POTION, 0 },
+ { WS_FEAR, 33, TYP_STICK, ISBLESSED },
+ { P_SEEINVIS, 35, TYP_POTION, 0 },
+ { P_RESTORE, 40, TYP_POTION, 0 },
+ { P_PHASE, 43, TYP_POTION, 0 },
+ { S_TELEP, 45, TYP_SCROLL, 0 },
+ { WS_CURING, 50, TYP_STICK, ISBLESSED },
+ { WS_DRAIN, 50, TYP_STICK, 0 },
+};
+
+/*
+ * these are the spells that a druid can chant
+ */
+struct spells druid_spells[MAXCHANTS] = {
+ { P_TFIND, 3, TYP_POTION, 0 },
+ { P_MFIND, 3, TYP_POTION, 0 },
+ { S_LIGHT, 7, TYP_SCROLL, ISBLESSED },
+ { S_CONFUSE, 10, TYP_SCROLL, 0 },
+ { S_MAP, 10, TYP_SCROLL, 0 },
+ { P_FFIND, 15, TYP_POTION, 0 },
+ { P_HEALING, 20, TYP_POTION, 0 },
+ { S_CURING, 25, TYP_SCROLL, 0 },
+ { P_FLY, 27, TYP_POTION, ISBLESSED },
+ { P_FIRE, 30, TYP_POTION, ISBLESSED },
+ { P_COLD, 30, TYP_POTION, ISBLESSED },
+ { P_LIGHTNING, 30, TYP_POTION, ISBLESSED },
+ { S_HOLD, 35, TYP_SCROLL, 0 },
+ { WS_CURING, 40, TYP_STICK, ISBLESSED },
+ { P_PHASE, 45, TYP_POTION, 0 },
+ { S_CHARM, 50, TYP_SCROLL, ISBLESSED },
+};
+
+
+/*
+ * these are the scrolls that a quill can write
+ */
+struct quill quill_scrolls[MAXQUILL] = {
+ { S_GFIND, 4, },
+ { S_IDENT, 5, },
+ { S_LIGHT, 6, },
+ { S_REMOVE, 7, },
+ { S_MAP, 10, },
+ { S_SLEEP, 20, },
+ { S_TELEP, 30, },
+ { S_CONFUSE, 40, },
+ { S_CURING, 50, },
+ { S_HOLD, 70, },
+ { S_PROTECT, 90, },
+ { S_SCARE, 110, },
+ { S_ALLENCH, 130, },
+};
+
+char *cnames[NUM_CHARTYPES-1][NUM_CNAMES] = {
+{ "Veteran", "Warrior", /* Fighter */
+ "Swordsman", "Hero",
+ "Swashbuckler", "Myrmidon",
+ "Champion", "Superhero",
+ "Lord", "Lord",
+ "Lord", "Lord",
+ "Lord", "Lord",
+ "Lord", "Lord",
+ "Lord"
+},
+{ "Runner", "Strider", /* Ranger */
+ "Scout", "Courser",
+ "Tracker", "Guide",
+ "Pathfinder", "Ranger",
+ "Ranger Knight", "Ranger Lord",
+ "Ranger Lord", "Ranger Lord",
+ "Ranger Lord", "Ranger Lord",
+ "Ranger Lord", "Ranger Lord",
+ "Ranger Lord"
+},
+{ "Gallant", "Keeper", /* Paladin */
+ "Protector", "Defender",
+ "Warder", "Guardian",
+ "Chevalier", "Justiciar",
+ "Paladin", "Paladin",
+ "Paladin", "Paladin",
+ "Paladin", "Paladin",
+ "Paladin", "Paladin",
+ "Paladin"
+},
+{ "Prestidigitator", "Evoker", /* Magic User */
+ "Conjurer", "Theurgist",
+ "Thaumaturgist", "Magician",
+ "Enchanter", "Warlock",
+ "Sorcerer", "Necromancer",
+ "Wizard I", "Wizard II",
+ "Wizard III", "Wizard IV",
+ "Wizard V", "Wizard VI",
+ "High Wizard"
+},
+{ "Acolyte", "Adept", /* Cleric */
+ "Priest", "Curate",
+ "Prefect", "Canon",
+ "Lama", "Patriarch",
+ "High Priest", "High Priest",
+ "High Priest", "High Priest",
+ "High Priest", "High Priest",
+ "High Priest", "High Priest",
+ "High Priest"
+},
+{ "Rogue", "Footpad", /* Thief */
+ "Cutpurse", "Robber",
+ "Burglar", "Filcher",
+ "Sharper", "Magsman",
+ "Thief", "Master Thief",
+ "Master Thief", "Master Thief",
+ "Master Thief", "Master Thief",
+ "Master Thief", "Master Thief",
+ "Master Thief"
+},
+{ "Bravo", "Rutterkin", /* Assassin */
+ "Waghalter", "Murderer",
+ "Thug", "Killer",
+ "Cutthroat", "Executioner",
+ "Assassin", "Expert Assassin",
+ "Senior Assassin", "Chief Assassin",
+ "Prime Assassin", "Guildmaster Assassin",
+ "Grandfather Assassin", "Grandfather Assassin",
+ "Grandfather Assassin"
+},
+{ "Aspirant", "Ovate", /* Druid */
+ "Initiate 1st Circle", "Initiate 2nd Circle",
+ "Initiate 3rd Circle", "Initiate 4th Circle",
+ "Initiate 5th Circle", "Initiate 6th Circle",
+ "Initiate 7th Circle", "Initiate 8th Circle",
+ "Initiate 9th Circle", "Druid",
+ "Archdruid", "The Great Druid",
+ "The Great Druid", "The Great Druid",
+ "The Great Druid",
+},
+{ "Novice", "Initiate", /* Monk */
+ "Brother", "Disciple",
+ "Immaculate", "Master",
+ "Superior Master", "Master of Dragons",
+ "Master of North Wind", "Master of West Wind",
+ "Master of South Wind", "Master of East Wind",
+ "Master of Winter", "Master of Autumn",
+ "Master of Summer", "Master of Spring",
+ "Grand Master"
+}
+} ;
+
+struct h_list helpstr[] = {
+ '?', " prints help",
+ '/', " identify object",
+ '=', " identify screen character",
+ 'h', " left",
+ 'j', " down",
+ 'k', " up",
+ 'l', " right",
+ 'y', " up & left",
+ 'u', " up & right",
+ 'b', " down & left",
+ 'n', " down & right",
+ 'H', " run left",
+ 'J', " run down",
+ 'K', " run up",
+ 'L', " run right",
+ 'Y', " run up & left",
+ 'U', " run up & right",
+ 'B', " run down & left",
+ 'N', " run down & right",
+ 't', " throw something",
+ 'f', " forward until find something",
+ 'z', " zap a wand or staff",
+ '>', " go down a staircase",
+ '<', " go up a staircase",
+ 's', " search for trap/secret door",
+ '.', " rest for a while",
+ 'i', " inventory",
+ 'I', " inventory single item",
+ 'q', " quaff potion",
+ 'r', " read paper",
+ 'e', " eat food",
+ 'w', " wield a weapon",
+ 'W', " wear something",
+ 'T', " take off something",
+ 'd', " drop object",
+ 'P', " pick up object(s)",
+ CTRL('N'), " name object or monster",
+ 'm', " mark object (specific)",
+ 'o', " examine/set options",
+ 'c', " chant",
+ 'C', " cast a spell",
+ 'p', " pray",
+ 'a', " affect the undead",
+ '^', " set a trap",
+ 'G', " sense gold",
+ 'D', " dip something (into a pool)",
+ '*', " count up gold pieces",
+ CTRL('T'), " take (steal) from (direction)",
+ CTRL('U'), " use miscellaneous magic item",
+ CTRL('L'), " redraw screen",
+ CTRL('R'), " repeat last message",
+ ESCAPE, " cancel command",
+ 'v', " print program version number",
+ '!', " shell escape",
+ 'S', " save game",
+ 'Q', " quit",
+ 0, 0
+} ;
+
+struct h_list wiz_help[] = {
+ CTRL('A'), " system activity",
+ CTRL('C'), " move to another dungeon level",
+ CTRL('D'), " down 1 dungeon level",
+ CTRL('E'), " food remaining",
+ CTRL('F'), " display entire level",
+ CTRL('H'), " jump 9 experience levels",
+ CTRL('I'), " inventory of level",
+ CTRL('J'), " teleport",
+ CTRL('M'), " recharge staff",
+ CTRL('P'), " toggle wizard status",
+ CTRL('U'), " up 1 dungeon level",
+ CTRL('X'), " detect monsters",
+ CTRL('Z'), " identify",
+ 'M', " make object",
+ 0, 0
+};
+
+
+#define HPT(x) x
+struct monster monsters[NUMMONST+1] = {
+/* {"Name",
+ CARRY, NORMAL, WANDER, APPEAR, INTEL,
+ {ATTRIBUTES},
+ "SUMMONED_CREATURE", NUMBER_SUMMONED,
+ ADDED_EXPERIENCE/HIT_POINT,
+ {str dex, move, exp, level, "armor", hit_points,
+ "damage"}}, */
+{"unknown",
+ 0, FALSE, FALSE, '\0', "",
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ 0,
+ 0, 0,
+ {0, 0, 0, 0, 0, 0, HPT(""),
+ ""}},
+{"giant rat",
+ 0, TRUE, TRUE, 'R', "2-4",
+ {ISMEAN, CANDISEASE},
+ 0, 0,
+ 1,
+ {10, 10, 6, 7, 1, 7, HPT("1d4"),
+ "1d3"}},
+{"kobold",
+ 10, TRUE, TRUE, 'K', "8",
+ {ISMEAN, CANSHOOT, CARRYWEAPON},
+ 0, 0,
+ 1,
+ {9, 10, 6, 5, 1, 7, HPT("1d4"),
+ "1d4"}},
+{"gnome",
+ 10, TRUE, FALSE, 'G', "11-12",
+ {CANSHOOT, CARRYPOTION, CARRYWEAPON},
+ 0, 0,
+ 1,
+ {10, 10, 6, 8, 1, 5, HPT("1d6"),
+ "1d6"}},
+{"bat",
+ 0, TRUE, TRUE, 'b', "2-4",
+ {ISMEAN, CANDISEASE, ISFLY, AREMANY},
+ 0, 0,
+ 0,
+ {10, 10, 6, 5, 1, 10, HPT("1d4"),
+ "1d1"}},
+{"halfling",
+ 10, TRUE, FALSE, 'H', "11-12",
+ {CANSHOOT, CARRYPOTION, CARRYWEAPON},
+ 0, 0,
+ 1,
+ {8, 10, 6, 9, 1, 4, HPT("1d6"),
+ "1d6"}},
+{"dwarf",
+ 15, TRUE, FALSE, 'D', "11-12",
+ {CANSHOOT, CARRYPOTION, CARRYWEAPON},
+ 0, 0,
+ 1,
+ {10, 10, 6, 10, 1, 4, HPT("1d8"),
+ "1d8"}},
+{"orc",
+ 15, TRUE, TRUE, 'O', "8",
+ {ISMEAN, CANSHOOT, CARRYGOLD, CARRYWEAPON},
+ 0, 0,
+ 1,
+ {12, 10, 6, 10, 1, 6, HPT("1d8"),
+ "1d8"}},
+{"xvart",
+ 100, TRUE, TRUE, 'x', "14-15",
+ {ISMEAN, CARRYDAGGER, AREMANY},
+ 0, 0,
+ 1,
+ {8, 10, 6, 7, 1, 7, HPT("1d4"),
+ "1d4"}},
+{"manes",
+ 0, TRUE, TRUE, 'M', "2-4",
+ {ISMEAN, MAGICHIT, ISUNDEAD, TURNABLE},
+ 0, 0,
+ 1,
+ {10, 10, 6, 18, 1, 7, HPT("1d8"),
+ "1d2/1d2/1d4"}},
+{"elf",
+ 50, TRUE, FALSE, 'E', "13-20",
+ {CANSHOOT, CARRYPOTION, CARRYSCROLL, CARRYWEAPON},
+ 0, 0,
+ 2,
+ {12, 10, 6, 20, 1, 5, HPT("1d8+1"),
+ "1d10"}},
+{"hobgoblin",
+ 10, TRUE, TRUE, 'h', "8-10",
+ {ISMEAN, CANSHOOT, CARRYWEAPON},
+ 0, 0,
+ 2,
+ {14, 10, 6, 20, 1, 5, HPT("1d8+1"),
+ "1d8"}},
+{"fire beetle",
+ 0, TRUE, TRUE, 'B', "0",
+ {ISMEAN, HASFIRE},
+ 0, 0,
+ 2,
+ {10, 10, 6, 20, 1, 4, HPT("1d8+2"),
+ "2d4"}},
+{"giant ant",
+ 0, TRUE, TRUE, 'A', "1",
+ {ISMEAN, CANPOISON},
+ 0, 0,
+ 3,
+ {10, 10, 6, 40, 2, 3, HPT("2d8"),
+ "1d6/1d6"}},
+{"zombie",
+ 0, TRUE, TRUE, 'Z', "0",
+ {ISMEAN, ISUNDEAD, TURNABLE},
+ 0, 0,
+ 2,
+ {10, 10, 6, 20, 2, 8, HPT("2d8"),
+ "1d8"}},
+{"ear seeker",
+ 0, TRUE, TRUE, 'e', "0",
+ {ISMEAN, CANINFEST, AREMANY, CANSURPRISE},
+ 0, 0,
+ 0,
+ {10, 10, 6, 5, 1, 9, HPT("1d1"),
+ "1d1"}},
+{"shrieker",
+ 0, TRUE, FALSE, 'S', "0",
+ {CANSHRIEK, NOMOVE, NOSTAB},
+ 0, 0,
+ 1,
+ {10, 10, 6, 10, 3, 7, HPT("3d8"),
+ "0d0"}},
+{"stirge",
+ 0, TRUE, TRUE, 's', "1",
+ {ISMEAN, CANDRAW, ISFLY},
+ 0, 0,
+ 2,
+ {10, 10, 6, 36, 4, 8, HPT("1d8+1"),
+ "1d3"}},
+{"gas spore",
+ 0, TRUE, FALSE, 'a', "0",
+ {ISMEAN, CANEXPLODE, CANINFEST, ISFLY},
+ 0, 0,
+ 5,
+ {10, 10, 18, 90, 1, 9, HPT("1d1"),
+ "1d1"}},
+{"troglodyte",
+ 5, TRUE, TRUE, 'T', "5-7",
+ {ISMEAN, CANSMELL, CANSHOOT, CARRYGOLD, CARRYWEAPON},
+ 0, 0,
+ 2,
+ {10, 10, 6, 36, 2, 5, HPT("2d8"),
+ "1d3/1d3/2d5"}},
+{"lemure",
+ 0, TRUE, FALSE, 'L', "2-4",
+ {ISMEAN, ISREGEN, MAGICHIT, ISUNDEAD, TURNABLE},
+ 0, 0,
+ 3,
+ {10, 10, 9, 65, 3, 7, HPT("3d8"),
+ "1d3"}},
+{"bugbear",
+ 5, TRUE, TRUE, 'b', "5-8",
+ {ISMEAN, CANSHOOT, CANSURPRISE, CARRYGOLD, CARRYPOTION,
+ CARRYWEAPON},
+ 0, 0,
+ 4,
+ {16, 10, 6, 135, 3, 5, HPT("3d8+1"),
+ "2d4"}},
+{"wererat",
+ 20, TRUE, TRUE, 'r', "11-12",
+ {ISMEAN, MAGICHIT, CARRYFOOD, CANSUMMON},
+ "giant rat", 2,
+ 4,
+ {10, 10, 6, 150, 3, 6, HPT("3d8+1"),
+ "1d8"}},
+{"ghoul",
+ 0, TRUE, TRUE, 'g', "5-7",
+ {ISMEAN, CANPARALYZE, ISUNDEAD, TURNABLE},
+ 0, 0,
+ 2,
+ {10, 10, 6, 65, 2, 6, HPT("2d8"),
+ "1d3/1d3/1d6"}},
+{"leprechaun",
+ 100, TRUE, FALSE, 'l', "15-16",
+ {CARRYGOLD, STEALGOLD},
+ 0, 0,
+ 1,
+ {10, 10, 3, 80, 6, 3, HPT("1d4+1"),
+ "0d0"}},
+{"gray ooze",
+ 50, TRUE, FALSE, 'o', "1",
+ {ISMEAN, CANRUST, ISSCAVENGE, NOCOLD, NOFIRE, NOSTAB,CARRYFOOD},
+ 0, 0,
+ 5,
+ {10, 10, 10, 200, 3, 8, HPT("3d8+3"),
+ "2d8"}},
+{"giant tick",
+ 0, TRUE, TRUE, 't', "0",
+ {ISMEAN, CANDRAW, CANDISEASE},
+ 0, 0,
+ 2,
+ {10, 10, 9, 105, 3, 3, HPT("3d8"),
+ "1d4"}},
+{"ogre",
+ 50, TRUE, TRUE, 'O', "5-7",
+ {ISMEAN, CARRYGOLD, CARRYWEAPON},
+ 0, 0,
+ 5,
+ {18, 10, 7, 90, 4, 5, HPT("4d8+1"),
+ "1d10"}},
+{"very young dragon",
+ 10, TRUE, FALSE, 'd', "15-16",
+ {ISMEAN, CANBRANDOM, ISGREED, CARRYGOLD},
+ 0, 0,
+ 9,
+ {10, 10, 6, 100, 9, -1, HPT("9d1"),
+ "1d4/1d4/2d4"}},
+{"centaur",
+ 15, TRUE, FALSE, 'C', "5-10",
+ {CANSHOOT, CARRYPOTION, CARRYGOLD, CARRYWEAPON},
+ 0, 0,
+ 4,
+ {10, 10, 2, 85, 4, 4, HPT("4d8"),
+ "1d6/1d6"}},
+{"nymph",
+ 100, TRUE, FALSE, 'N', "15-16",
+ {STEALMAGIC, CARRYSCROLL, CARRYPOTION, CARRYSTICK},
+ 0, 0,
+ 3,
+ {10, 10, 6, 350, 4, 9, HPT("3d8"),
+ "0d0"}},
+{"violet fungi",
+ 0, TRUE, FALSE, 'F', "0",
+ {ISMEAN, CANHOLD, NOMOVE, CANROT, NOSTAB},
+ 0, 0,
+ 4,
+ {10, 10, 6, 135, 3, 7, HPT("3d8"),
+ "5d1"}},
+{"gelatinous cube",
+ 90, TRUE, TRUE, 'c', "0",
+ {ISMEAN, ISSCAVENGE, CANPARALYZE, NOSTAB, CARRYFOOD},
+ 0, 0,
+ 4,
+ {10, 10, 8, 150, 4, 8, HPT("4d8"),
+ "2d4"}},
+{"fire toad",
+ 0, TRUE, TRUE, 'f', "5-7",
+ {ISMEAN, CANBFIRE, NOFIRE},
+ 0, 0,
+ 4,
+ {10, 10, 6, 150, 4, 10, HPT("4d8+1"),
+ "2d4"}},
+{"blink dog",
+ 0, TRUE, TRUE, 'B', "8-10",
+ {ISMEAN, CANBLINK},
+ 0, 0,
+ 5,
+ {10, 10, 6, 170, 4, 5, HPT("4d8"),
+ "1d6"}},
+{"rust monster",
+ 0, TRUE, TRUE, 'R', "1",
+ {ISMEAN, CANRUST},
+ 0, 0,
+ 4,
+ {10, 10, 6, 185, 5, 2, HPT("3d8"),
+ "0d0/0d0"}},
+{"ghast",
+ 0, TRUE, TRUE, 'G', "11-12",
+ {CANPARALYZE, CANSTINK, ISMEAN, ISUNDEAD, TURNABLE},
+ 0, 0,
+ 4,
+ {10, 10, 6, 190, 4, 4, HPT("4d8"),
+ "1d4/1d4/1d8"}},
+{"blindheim",
+ 0, TRUE, FALSE, 'b', "1",
+ {CANBLIND, ISMEAN},
+ 0, 0,
+ 4,
+ {8, 10, 6, 200, 2, 1, HPT("4d8+2"),
+ "1d8"}},
+{"shadow",
+ 0, TRUE, TRUE, 'S', "5-7",
+ {ISSHADOW, ISMEAN, CANCHILL, ISUNDEAD, TURNABLE},
+ 0, 0,
+ 4,
+ {10, 10, 6, 255, 3, 7, HPT("3d8+3"),
+ "1d4+1"}},
+{"gargoyle",
+ 5, TRUE, TRUE, 'g', "5-7",
+ {ISMEAN, MAGICHIT},
+ 0, 0,
+ 5,
+ {10, 10, 6, 165, 4, 5, HPT("4d8+4"),
+ "1d3/1d3/1d6/1d4"}},
+{"quasit",
+ 30, TRUE, TRUE, 'Q', "5-7",
+ {ISMEAN, ISREGEN, MAGICHIT, CANSURPRISE, CANITCH, CARRYSTICK,
+ CARRYSCROLL, CARRYGOLD, CARRYPOTION, NOCOLD, NOFIRE, NOBOLT},
+ 0, 0,
+ 3,
+ {10, 10, 6, 325, 7, 2, HPT("3d8"),
+ "1d2/1d2/1d4"}},
+{"imp",
+ 25, TRUE, TRUE, 'I', "8-10",
+ {ISMEAN, ISREGEN, MAGICHIT, CANPOISON, CANSURPRISE,
+ CANTELEPORT, CARRYRING, CARRYSTICK, NOCOLD, NOBOLT, NOFIRE},
+ 0, 0,
+ 3,
+ {10, 10, 6, 275, 2, 2, HPT("2d8+2"),
+ "1d4"}},
+{"su-monster", 10, TRUE, TRUE, 's', "8-10",
+ {ISMEAN, CARRYSCROLL, CARRYGOLD, CARRYFOOD},
+ 0, 0,
+ 6,
+ {10, 10, 5, 225, 5, 6, HPT("5d8+5"),
+ "4d4/2d4"}},
+{"owlbear",
+ 5, TRUE, TRUE, 'O', "5-7",
+ {ISMEAN, CANHUG, CARRYRING, CARRYFOOD},
+ 0, 0,
+ 8,
+ {10, 10, 8, 225, 5, 5, HPT("5d8+2"),
+ "1d6/1d6/2d6"}},
+{"doppleganger",
+ 0, TRUE, TRUE, 'D', "11-12",
+ {ISMEAN, CANSURPRISE},
+ 0, 0,
+ 4,
+ {10, 10, 6, 330, 10, 5, HPT("4d8"),
+ "1d12"}},
+{"yeti",
+ 30, TRUE, TRUE, 'Y', "8-10",
+ {ISMEAN, CANPARALYZE, CANHUG, NOCOLD, CANSURPRISE,
+ CARRYGOLD, CARRYPOTION},
+ 0, 0,
+ 8,
+ {13, 10, 6, 500, 6, 6, HPT("4d8+4"),
+ "1d6/1d6"}},
+{"leucrotta",
+ 0, TRUE, FALSE, 'L', "8-10",
+ {ISMEAN},
+ 0, 0,
+ 8,
+ {10, 10, 2, 475, 6, 4, HPT("6d8+1"),
+ "3d6/1d6/1d6"}},
+{"cockatrice",
+ 0, TRUE, TRUE, 'C', "1",
+ {ISMEAN, TOUCHSTONE},
+ 0, 0,
+ 5,
+ {10, 10, 5, 315, 5, 6, HPT("5d8"),
+ "1d3"}},
+{"wight",
+ 0, TRUE, TRUE, 'W', "8-10",
+ {ISMEAN, CANDRAIN, MAGICHIT, ISUNDEAD, TURNABLE},
+ 0, 0,
+ 5,
+ {10, 10, 6, 540, 4, 5, HPT("4d8+3"),
+ "1d4"}},
+{"troll",
+ 50, TRUE, FALSE, 'T', "5-7",
+ {ISMEAN, ISREGEN, CARRYFOOD, CARRYGOLD},
+ 0, 0,
+ 8,
+ {18, 10, 8, 600, 6, 4, HPT("6d8+6"),
+ "1d4+4/1d4+4/2d6"}},
+{"jackalwere",
+ 50, TRUE, TRUE, 'J', "11-12",
+ {ISMEAN, CANSHOOT, CANSNORE, MAGICHIT, CARRYFOOD, CARRYGOLD,
+ CARRYSCROLL},
+ 0, 0,
+ 4,
+ {10, 10, 6, 800, 4, 4, HPT("4d8"),
+ "2d4"}},
+{"wraith",
+ 0, TRUE, TRUE, 'w', "11-12",
+ {ISMEAN, CANDRAIN, MAGICHIT, ISUNDEAD, TURNABLE},
+ 0, 0,
+ 6,
+ {10, 10, 6, 575, 5, 4, HPT("5d8+3"),
+ "1d6"}},
+{"mimic",
+ 20, TRUE, FALSE, 'M', "2-10",
+ {ISMEAN, ISDISGUISE, NODETECT, CANHOLD, CARRYFOOD, CARRYRING,
+ CARRYGOLD, NOMOVE},
+ 0, 0,
+ 12,
+ {10, 10, 6, 1300, 9, 7, HPT("10d8"),
+ "3d4"}},
+{"erinyes",
+ 25, TRUE, TRUE, 'E', "8-10",
+ {ISMEAN, CANFRIGHTEN, CANSUMMON, TURNABLE, CANPAIN, CANSEE,
+ NOFIRE, CANTELEPORT, CARRYRING, CARRYSTICK},
+ "ghoul", 3,
+ 8,
+ {10, 10, 6, 875, 7, 2, HPT("6d8+6"),
+ "2d4"}},
+{"lava child",
+ 0, TRUE, TRUE, 'l', "8-10",
+ {ISMEAN, NOMETAL},
+ 0, 0,
+ 8,
+ {10, 10, 6, 950, 5, 4, HPT("5d8+1"),
+ "1d6/1d6/2d12"}},
+{"basilisk",
+ 0, TRUE, FALSE, 'B', "1",
+ {ISMEAN, LOOKSTONE},
+ 0, 0,
+ 8,
+ {10, 10, 6, 1000, 6, 4, HPT("6d8+1"),
+ "1d10"}},
+{"mummy",
+ 20, TRUE, FALSE, 'm', "5-7",
+ {ISMEAN,CANINFEST, MAGICHIT, CANFRIGHTEN, HALFDAMAGE, ISUNDEAD,
+ TURNABLE, CARRYRING},
+ 0, 0,
+ 8,
+ {10, 10, 6, 1150, 6, 3, HPT("6d8+3"),
+ "1d12"}},
+{"otyugh",
+ 0, TRUE, TRUE, 'o', "5-10",
+ {ISMEAN, CANDISEASE},
+ 0, 0,
+ 8,
+ {10, 10, 6, 700, 7, 3, HPT("7d8"),
+ "1d8/1d8/1d4+1"}},
+{"adult dragon",
+ 30, TRUE, FALSE, 'd', "15-16",
+ {ISMEAN, CANBRANDOM, ISGREED, CANFRIGHTEN, CARRYGOLD,
+ CARRYPOTION},
+ 0, 0,
+ 9,
+ {10, 10, 6, 1000, 9, -1, HPT("45d1"),
+ "1d6/1d6/2d6"}},
+{"invisible stalker",
+ 0, TRUE, TRUE, 'i', "13-14",
+ {ISMEAN, ISINVIS},
+ 0, 0,
+ 10,
+ {10, 10, 4, 1090, 8, 3, HPT("8d8"),
+ "4d4"}},
+{"xorn",
+ 0, TRUE, TRUE, 'X', "8-10",
+ {ISMEAN, CANINWALL, NOCOLD, NOFIRE, CANSURPRISE, NOBOLT},
+ 0, 0,
+ 10,
+ {10, 10, 6, 1275, 7, -2, HPT("7d8+7"),
+ "1d3/1d3/1d3/4d6"}},
+{"chimera",
+ 0, TRUE, FALSE, 'c', "2-4",
+ {ISMEAN, CANBFIRE, NOFIRE},
+ 0, 0,
+ 12,
+ {10, 10, 6, 1000, 9, 6, HPT("9d8"),
+ "1d3/1d3/1d4/1d4/2d4/3d4"}},
+{"horned devil",
+ 5, TRUE, TRUE, 'H', "13-14",
+ {ISMEAN, CANFRIGHTEN, CANINFEST, CANPOISON, MAGICHIT, CANSUMMON,
+ NOFIRE, CANTELEPORT, CARRYGOLD, CARRYRING, CARRYSTICK},
+ "wight", 2,
+ 6,
+ {10, 10, 6, 1320, 7, -3, HPT("5d8+5"),
+ "1d4/1d4/1d4+1/1d3"}},
+{"specter",
+ 0, TRUE, TRUE, 'S', "13-14",
+ {ISMEAN, DOUBLEDRAIN, ISUNDEAD, TURNABLE},
+ 0, 0,
+ 10,
+ {10, 10, 6, 1650, 7, 2, HPT("7d8+3"),
+ "1d8"}},
+{"will-o-wisp", 100, TRUE, FALSE, 'W', "15-16",
+ {ISMEAN, CANSURPRISE, ISFLY, CARRYGOLD, CARRYMISC, NOBOLT},
+ 0, 0,
+ 12,
+ {10, 10, 5, 2000, 9, -8, HPT("9d8"),
+ "2d8"}},
+{"lamia",
+ 0, TRUE, TRUE, 'L', "13-14",
+ {ISMEAN, TAKEWISDOM},
+ 0, 0,
+ 9,
+ {10, 10, 2, 1500, 9, 3, HPT("9d8"),
+ "1d4/1d4"}},
+{"neo-otyugh",
+ 0, TRUE, TRUE, 'N', "10-12",
+ {ISMEAN, CANDISEASE},
+ 0, 0,
+ 10,
+ {12, 10, 6, 1500, 10, 0, HPT("12d8"),
+ "2d6/2d6/1d3"}},
+{"barbed devil",
+ 0, TRUE, TRUE, 'B', "11-12",
+ {TOUCHFEAR, CANSUMMON, ISMEAN, CANHOLD, TURNABLE, NOFIRE,
+ CANTELEPORT},
+ "ghast", 4,
+ 10,
+ {10, 10, 6, 1425, 8, 0, HPT("8d8"),
+ "2d4/2d4/3d4"}},
+{"vrock",
+ 10, TRUE, TRUE, 'V', "5-7",
+ {ISMEAN, CANSUMMON, CANSEE, TURNABLE, CANTELEPORT, CARRYGOLD,
+ CARRYRING, CARRYSTICK},
+ "erinyes", 2,
+ 10,
+ {10, 10, 6, 1500, 8, 0, HPT("8d8"),
+ "1d4/1d4/1d8/1d8/1d6"}},
+{"shambling mound",
+ 25, TRUE, TRUE, 's', "5-7",
+ {ISMEAN, CANSUFFOCATE, NOCOLD, NOFIRE, CANHOLD, CARRYGOLD,
+ CARRYFOOD, CARRYRING},
+ 0, 0,
+ 10,
+ {10, 10, 7, 1800, 9, 0, HPT("9d8"),
+ "2d8/2d8"}},
+{"umber hulk",
+ 40, TRUE, TRUE, 'U', "8-10",
+ {ISMEAN, CANHUH, CANINWALL, CANTUNNEL, CARRYSCROLL,
+ CARRYPOTION, CARRYFOOD},
+ 0, 0,
+ 12,
+ {10, 10, 6, 1700, 8, 2, HPT("8d8+8"),
+ "3d4/3d4/2d5"}},
+{"ettin",
+ 0, TRUE, TRUE, 'e', "5-7",
+ {ISMEAN, CANSHOOT, AREMANY},
+ 0, 0,
+ 14,
+ {10, 10, 6, 1950, 10, 3, HPT("10d8"),
+ "2d8/3d6"}},
+{"black pudding",
+ 30, TRUE, FALSE, 'P', "0",
+ {ISMEAN, CANRUST, NOCOLD, BOLTDIVIDE, BLOWDIVIDE, ISSCAVENGE,
+ NOSTAB, CARRYSCROLL, CARRYPOTION, CARRYRING},
+ 0, 0,
+ 14,
+ {10, 10, 6, 2000, 10, 6, HPT("10d8"),
+ "3d8"}},
+{"hezrou",
+ 15, TRUE, TRUE, 'h', "5-7",
+ {ISMEAN, CANFRIGHTEN, CANSEE, CANSUMMON, TURNABLE, CANTELEPORT,
+ CARRYPOTION, CARRYRING, CARRYSTICK},
+ "wight", 3,
+ 12,
+ {10, 10, 6, 2000, 9, -2, HPT("9d8"),
+ "1d3/1d3/4d4"}},
+{"glabrezu",
+ 25, TRUE, FALSE, 'G', "8-10",
+ {ISMEAN, CANFRIGHTEN, CANSEE, CANSUMMON, TURNABLE, CANTELEPORT,
+ CARRYSCROLL, CARRYPOTION, CARRYGOLD},
+ "wraith", 3,
+ 14,
+ {10, 10, 6, 2400, 10, -4, HPT("10d8"),
+ "2d6/2d6/1d3/1d3/1d4+1"}},
+{"bone devil",
+ 0, TRUE, TRUE, 'b', "11-12",
+ {ISMEAN, CANFRIGHTEN, CANSEE, CANSUMMON, CANSURPRISE, CANCHILL,
+ TURNABLE, NOFIRE, NOCOLD, CANTELEPORT},
+ "ghast", 3,
+ 12,
+ {10, 10, 6, 2800, 9, -1, HPT("9d8"),
+ "2d4"}},
+{"white pudding",
+ 30, TRUE, FALSE, 'w', "0",
+ {ISMEAN, CANDISSOLVE, NOCOLD, BOLTDIVIDE, BLOWDIVIDE,
+ ISSCAVENGE, NOSTAB, CARRYRING, CARRYSCROLL,
+ CARRYPOTION},
+ 0, 0,
+ 14,
+ {10, 10, 6, 2200, 9, 8, HPT("10d8"),
+ "7d4"}},
+{"vampire",
+ 20, TRUE, TRUE, 'v', "15-16",
+ {ISMEAN, ISREGEN, CANSUCK, ISUNDEAD, TURNABLE, CARRYMISC},
+ 0, 0,
+ 12,
+ {20, 10, 6, 3800, 8, 1, HPT("8d8+3"),
+ "1d6+4"}},
+{"ghost",
+ 20, TRUE, FALSE, 'g', "13-14",
+ {ISMEAN, CANFRIGHTEN, CANAGE, ISUNDEAD, TURNABLE, CARRYMISC,
+ CMAGICHIT, CANINWALL},
+ 0, 0,
+ 10,
+ {13, 10, 5, 5000, 12, 0, HPT("10d8"),
+ "1d12"}},
+{"intellect devourer",
+ 0, TRUE, FALSE, 'D', "11-12",
+ {ISMEAN, TAKEINTEL, CMAGICHIT, HALFDAMAGE, CANSURPRISE, NOFIRE,
+ NOCOLD},
+ 0, 0,
+ 9,
+ {10, 10, 4, 5000, 7, 4, HPT("6d8+6"),
+ "1d4/1d4/1d4/1d4"}},
+{"ice devil",
+ 30, TRUE, FALSE, 'I', "13-14",
+ {ISMEAN, CANSEE, ISREGEN, CANFRIGHTEN, CANSUMMON, CANBICE,
+ NOCOLD, NOFIRE, TOUCHSLOW, CANTELEPORT, CARRYSCROLL, CARRYRING,
+ CARRYSTICK},
+ "bone devil", 2,
+ 16,
+ {20, 10, 6, 4400, 11, -4, HPT("11d8"),
+ "1d4/1d4/2d4/3d4"}},
+{"purple worm",
+ 70, TRUE, TRUE, 'p', "0",
+ {ISMEAN, CANPOISON, CANINWALL, CANTUNNEL, CARRYFOOD, CARRYGOLD},
+ 0, 0,
+ 20,
+ {10, 10, 6, 4900, 15, 6, HPT("15d8"),
+ "2d12/2d4"}},
+{"ancient brass dragon",
+ 70, TRUE, FALSE, 'r', "13-14",
+ {CANBSGAS, CANBFGAS, ISGREED, CANSEE, NOSLEEP, NOFEAR,
+ CARRYGOLD, CARRYRING},
+ 0, 0,
+ 50,
+ {10, 10, 6, 10000, 8, 2, HPT("0d8+64"),
+ "1d4/1d4/4d4"}},
+{"pit fiend",
+ 100, TRUE, TRUE, 'f', "15-16",
+ {ISMEAN, CANSEE, BMAGICHIT, CANFRIGHTEN, CANHOLD, CANSUMMON,
+ CANBFIRE, NOFIRE, CANTELEPORT, CARRYSTICK, HASFIRE, ISFLY},
+ "barbed devil", 3,
+ 18,
+ {22, 10, 6, 10000, 13, -3, HPT("13d8"),
+ "1d4+4/1d6+6"}},
+{"ancient white dragon",
+ 70, TRUE, TRUE, 'W', "8-9",
+ {ISMEAN, CANBICE, ISGREED, CANSEE, NOCOLD, CARRYGOLD,
+ CARRYRING},
+ 0, 0,
+ 50,
+ {10, 10, 6, 15000, 7, 3, HPT("0d8+56"),
+ "1d4/1d4/2d8"}},
+{"ancient black dragon",
+ 70, TRUE, TRUE, 'a', "8-10",
+ {ISMEAN, CANBACID, NOACID, ISGREED, CANSEE, CARRYGOLD,
+ CARRYSTICK},
+ 0, 0,
+ 50,
+ {10, 10, 6, 20000, 8, 3, HPT("0d8+64"),
+ "1d4/1d4/3d6"}},
+{"lich",
+ 60, TRUE, TRUE, 'l', "19-20",
+ {ISMEAN, CANDRAIN, CANSEE, CANPARALYZE, CANFRIGHTEN, MAGICHIT,
+ ISUNDEAD, TURNABLE, NOBOLT, CANMISSILE, CANSUMMON, CARRYGOLD,
+ CARRYSCROLL, CARRYPOTION, CARRYRING, CARRYSTICK},
+ "specter", 2,
+ 16,
+ {10, 10, 6, 20000, 17, 0, HPT("11d8"),
+ "1d10"}},
+{"titan",
+ 80, TRUE, FALSE, 't', "17-20",
+ {ISMEAN, ISSHADOW, CANSEE, CANMISSILE, CARRYRING, CARRYSTICK,
+ CANTELEPORT},
+ 0, 0,
+ 30,
+ {13, 10, 5, 20000, 19, -3, HPT("22d8"),
+ "8d6"}},
+{"ancient copper dragon",
+ 70, TRUE, FALSE, 'c', "13-14",
+ {CANBACID, NOACID, CANBSLGAS, ISGREED, CANSEE, NOSLOW,
+ CARRYGOLD, CARRYSTICK},
+ 0, 0,
+ 50,
+ {10, 10, 6, 20000, 9, 1, HPT("0d8+72"),
+ "1d4/1d4/5d4"}},
+{"ancient green dragon",
+ 50, TRUE, TRUE, 'E', "10-12",
+ {ISMEAN, CANBGAS, ISGREED, CANSEE, NOGAS, CARRYGOLD,
+ CARRYRING, CARRYSTICK},
+ 0, 0,
+ 50,
+ {10, 10, 6, 20000, 9, 2, HPT("0d8+72"),
+ "1d6/1d6/2d10"}},
+{"ancient bronze dragon",
+ 50, TRUE, FALSE, 'L', "15-16",
+ {CANBCGAS, CANBBOLT, CANBFGAS, ISGREED, CANSEE, NOFEAR, NOBOLT,
+ ISCLEAR, CARRYGOLD, CARRYRING, CARRYSTICK},
+ 0, 0,
+ 50,
+ {10, 10, 6, 20000, 10, 0, HPT("0d8+80"),
+ "1d6/1d6/4d6"}},
+{"ancient blue dragon",
+ 50, TRUE, TRUE, 'u', "12-14",
+ {ISMEAN, CANBBOLT, ISGREED, CANSEE, NOBOLT, CARRYGOLD,
+ CARRYSCROLL, CARRYRING, CARRYSTICK},
+ 0, 0,
+ 50,
+ {10, 10, 6, 20000, 10, 2, HPT("0d8+80"),
+ "1d6/1d6/3d8"}},
+{"ancient silver dragon",
+ 40, TRUE, FALSE, 'S', "15-16",
+ {CANBICE, CANBPGAS, ISGREED, CANSEE, CANMISSILE, NOCOLD,
+ NOPARALYZE, CARRYGOLD, CARRYSCROLL, CARRYRING, CARRYSTICK},
+ 0, 0,
+ 50,
+ {10, 10, 6, 20000, 11, -1, HPT("0d8+88"),
+ "1d6/1d6/5d6"}},
+{"frost giant",
+ 50, TRUE, TRUE, 'F', "5-10",
+ {ISMEAN, NOCOLD, CARRYGOLD, AREMANY},
+ 0, 0,
+ 40,
+ {25, 10, 5, 20000, 15, 4, HPT("10d8+4"),
+ "4d6"}},
+{"ancient red dragon",
+ 40, TRUE, TRUE, 'R', "15-16",
+ {ISMEAN, CANBFIRE, ISGREED, CANSEE, NOFIRE, CARRYGOLD,
+ CARRYPOTION, CARRYRING, CARRYSTICK},
+ 0, 0,
+ 50,
+ {10, 10, 6, 20000, 11, -1, HPT("0d8+88"),
+ "1d8/1d8/3d10"}},
+{"ancient gold dragon",
+ 50, TRUE, FALSE, 'G', "17-18",
+ {CANBFIRE, CANBGAS, ISGREED, CANSEE, CANMISSILE, NOFIRE, NOGAS,
+ CARRYGOLD, CARRYPOTION, CARRYRING, CARRYSTICK, CANTELEPORT},
+ 0, 0,
+ 50,
+ {10, 10, 6, 20000, 12, -2, HPT("0d8+96"),
+ "1d8/1d8/6d6"}},
+{"fire giant",
+ 30, TRUE, TRUE, 'f', "6-10",
+ {ISMEAN, CARRYGOLD, NOFIRE, AREMANY},
+ 0, 0,
+ 45,
+ {27, 10, 5, 26000, 15, 4, HPT("11d8+5"),
+ "5d6"}},
+{"storm giant",
+ 30, TRUE, TRUE, 's', "8-10",
+ {ISMEAN, NOBOLT, CANBBOLT, CARRYRING},
+ 0, 0,
+ 50,
+ {30, 10, 5, 30000, 15, 2, HPT("15d8+8"),
+ "7d6"}},
+{"dwarven thief (Musty Doit)",
+ 50, TRUE, TRUE, 'm', "16",
+ {ISMEAN, ISUNIQUE, ISINVIS, NOFIRE, NOGAS, NOSTAB, STEALGOLD,
+ STEALMAGIC, CANPAIN, ISFLY, CARRYGOLD, CANSURPRISE, CANSEE,
+ CARRYMDAGGER, CARRYMISC, CARRYPOTION, CANBSTAB, ISSCAVENGE,
+ NODETECT},
+ 0, 0,
+ 0,
+ {9, 18, 8, 300000, 22, -5, HPT("0d8+95"),
+ "6d4+70/6d4+70"}},
+{"demon prince (Jubilex)",
+ 100, TRUE, FALSE, 'J', "18",
+ {ISMEAN, ISUNIQUE, CANFRIGHTEN, ISREGEN, BMAGICHIT, ISSHADOW,
+ CANHOLD, CANDISEASE, CANSUMMON, CANSEE, CANROT, CANINFEST,
+ CANRUST, NOSTAB, CANTELEPORT, CARRYMISC, CANSMELL, CANSTINK,
+ NOFIRE},
+ "black pudding", 4,
+ 0,
+ {18, 18, 5, 100000, 20, -7, HPT("0d8+88"),
+ "4d10"}},
+{"arch devil (Geryon)",
+ 100, TRUE, FALSE, 'g', "16",
+ {ISMEAN, ISUNIQUE, BMAGICHIT, CANSEE, ISSHADOW, CANFRIGHTEN,
+ CANHUH, CANPOISON, CANSUMMON, NOFIRE, CANTELEPORT, NOFIRE,
+ CARRYMISC, CARRYHORN},
+ "ice devil", 5,
+ 0,
+ {18, 18, 5, 110000, 30, -3, HPT("0d8+133"),
+ "3d6/3d6/2d4"}},
+{"arch devil (Dispater)",
+ 100, TRUE, FALSE, 'd', "18",
+ {ISMEAN, ISUNIQUE, CANSEE, CANFRIGHTEN, CANHUH, BMAGICHIT,
+ CANSUMMON, CARRYSTICK, NOFIRE, CANTELEPORT, CARRYMISC},
+ "ghost", 9,
+ 0,
+ {18, 18, 5, 120000, 36, -2, HPT("0d8+144"),
+ "4d6"}},
+{"demon prince (Yeenoghu)",
+ 100, TRUE, FALSE, 'Y', "16",
+ {ISMEAN, ISREGEN, ISUNIQUE, MAGICHIT, CANSEE, ISSHADOW, CANHOLD,
+ CARRYFLAIL, CANFRIGHTEN, CANPARALYZE, CANSUMMON, CANHUH,
+ CANMISSILE, CANTELEPORT, CARRYMISC, NOFIRE},
+ "lich", 5,
+ 0,
+ {18, 18, 5, 130000, 23, -5, HPT("0d8+100"),
+ "3d6/3d6"}},
+{"witch (Emori)",
+ 50, TRUE, TRUE, 'w', "18",
+ {ISMEAN, CANMISSILE, ISINVIS, CANBBOLT, CANBFIRE, CANBICE,
+ CANSEE, CANSUMMON, ISUNIQUE, CANSNORE, ISFLY, TAKEINTEL,
+ CANDANCE, CANDISEASE, NOBOLT, NOCOLD, NOFIRE, CARRYCLOAK,
+ ISCLEAR, CARRYSCROLL, CARRYSTICK, CANTELEPORT, CANSLOW},
+ "shambling mound", 7,
+ 0,
+ {21, 12, 6, 140000, 25, 0, HPT("0d8+102"),
+ "1d4/1d4"}},
+{"cleric of Thoth (Heil)",
+ 100, TRUE, TRUE, 'h', "16",
+ {ISMEAN, CANSEE, NOFEAR, ISREGEN, CANHOLD, CANBFIRE, ISUNIQUE,
+ DOUBLEDRAIN, CANSUMMON, NOFIRE, TOUCHFEAR, CANDISEASE, CANSUCK,
+ CANSEE, TAKEWISDOM, CARRYANKH, CARRYRING, ISINVIS, ISFLY},
+ "vampire", 9,
+ 0,
+ {25, 15, 6, 150000, 25, -8, HPT("0d8+116"),
+ "0d6+11"}},
+{"magician (Tsoming Zen)",
+ 80, TRUE, FALSE, 'z', "18",
+ {ISMEAN, ISUNIQUE, ISINVIS, ISREGEN, CANBFIRE, CANBICE,
+ CANBBOLT, CANMISSILE, NOFIRE, CANHOLD, CANFRIGHTEN, CANDISEASE,
+ CANPAIN, CANSUMMON, CANSEE, ISFLY, CANTELEPORT,
+ CARRYSTAFF, CARRYSTICK, NOSLOW, NOBOLT, NOCOLD},
+ "ancient black dragon", 5,
+ 0,
+ {18, 16, 6, 160000, 21, -4, HPT("0d8+125"),
+ "2d4+1/2d4+1/2d4+1/2d4+1"}},
+{"poet (Brian)",
+ 80, TRUE, TRUE, 'p', "16",
+ {ISMEAN, ISUNIQUE, STEALGOLD, ISSHADOW, CANSUMMON, ISREGEN,
+ CANDISEASE, NOCOLD, NOBOLT, NOFIRE, NOFEAR, CANTUNNEL, CANSEE,
+ CANINWALL, ISCLEAR, CARRYMANDOLIN, CARRYPOTION, CARRYRING},
+ "umber hulk", 6,
+ 0,
+ {19, 18, 5, 170000, 20, -2, HPT("0d8+156"),
+ "8d8+48/4d4+36"}},
+{"lesser god (Hruggek)",
+ 100, TRUE, FALSE, 'H', "17",
+ {ISMEAN, CANSEE, ISUNIQUE, CANSUMMON, ISREGEN, CANFRIGHTEN,
+ CANTELEPORT, CARRYMISC, CARRYMSTAR, CANSMELL, CANBLINK},
+ "purple worm", 6,
+ 0,
+ {19, 18, 5, 180000, 25, 0, HPT("0d8+221"),
+ "2d8/2d8"}},
+{"lesser god (Kurtulmak)",
+ 100, TRUE, TRUE, 'K', "19",
+ {ISMEAN, CANFRIGHTEN, CANPOISON, CANSEE, ISUNIQUE, CANSUMMON,
+ CANTELEPORT, CARRYMISC, CANBLINK},
+ "lich", 3,
+ 0,
+ {19, 18, 5, 190000, 27, 0, HPT("0d8+219"),
+ "2d12/1d6"}},
+{"demigod (Vaprak \"The Destroyer\")",
+ 100, TRUE, TRUE, 'v', "18",
+ {ISMEAN, ISUNIQUE, ISREGEN, MAGICHIT, CANSEE, CANSUMMON,
+ CANTELEPORT, CARRYMISC, CANSMELL},
+ "troll", 9,
+ 0,
+ {18, 18, 5, 200000, 26, 0, HPT("0d8+198"),
+ "2d10/2d10/1d12"}},
+{"hero (Aklad)",
+ 100, TRUE, FALSE, 'k', "16",
+ {ISMEAN, ISUNIQUE, CANSUMMON, ISREGEN, NOCOLD, NOBOLT, NOFIRE,
+ NOPARALYZE, NOFEAR, CANSEE, ISCLEAR, CARRYAXE, CARRYRING,
+ CARRYMISC, CANBLINK},
+ "ancient green dragon", 4,
+ 0,
+ {25, 16, 4, 210000, 25, -10, HPT("0d8+196"),
+ "2d8+23/2d8+23/1d6+19/1d6+19"}},
+{"magician/thief (Nagrom)",
+ 100, TRUE, TRUE, 'N', "19",
+ {ISMEAN, ISUNIQUE, STEALMAGIC, ISINVIS, CANSUMMON, ISREGEN,
+ CANMISSILE, CANSEE, CARRYQUILL, CARRYSCROLL, CARRYRING, ISFLY,
+ CANBSTAB, CANBFIRE, CANBBOLT, CANBICE, NOCOLD, NOBOLT, NOFIRE,
+ CANSURPRISE, NODETECT, CANTELEPORT, CANSLOW,
+ CARRYSTICK},
+ "ancient blue dragon", 5,
+ 0,
+ {18, 18, 8, 220000, 26, -2, HPT("0d8+150"),
+ "1d10+3/1d4+3"}},
+{"platinum dragon (Bahamut)",
+ 100, TRUE, FALSE, 'P', "20",
+ {ISUNIQUE, CANBICE, CANBGAS, CANBBOLT, CANBRANDOM, CANSEE,
+ NOCOLD, NOBOLT, NOGAS, NOFIRE, NOFEAR, NOSLEEP, NOSLOW,
+ NOPARALYZE, CANMISSILE, CANSONIC, CANFRIGHTEN, CANSUMMON,
+ CARRYMISC, CANTELEPORT, ISFLY},
+ "ancient gold dragon", 4,
+ 0,
+ {18, 18, 5, 230000, 38, -3, HPT("0d8+168"),
+ "2d6/2d6/6d8"}},
+{"arch devil (Baalzebul)",
+ 100, TRUE, FALSE, 'B', "18",
+ {ISMEAN, ISSHADOW, ISUNIQUE, BMAGICHIT, CANHOLD, CANPOISON,
+ CANFRIGHTEN, CANHUH, CANSUMMON, CANSEE, NOFIRE, CANTELEPORT,
+ CARRYMISC, CARRYSTICK, CANDRAIN},
+ "ice devil", 9,
+ 0,
+ {18, 18, 5, 240000, 37, -5, HPT("0d8+166"),
+ "2d6"}},
+{"chromatic dragon (Tiamat)",
+ 100, TRUE, FALSE, 'C', "18",
+ {ISMEAN, ISUNIQUE, CANBFIRE, CANBACID, CANBBOLT, CANBICE,
+ CANBGAS, CANBRANDOM, CANSEE, NOFIRE, NOBOLT, NOCOLD, NOACID,
+ NOGAS, CANSUMMON, CANMISSILE, CANFRIGHTEN, CARRYMISC,
+ CARRYRING, CANTELEPORT, ISFLY},
+ "ancient red dragon", 6,
+ 0,
+ {18, 18, 5, 250000, 29, 0, HPT("0d8+128"),
+ "2d8/3d6/2d10/3d8/3d10/1d6"}},
+{"demon prince (Orcus)",
+ 100, TRUE, FALSE, 'O', "20",
+ {ISMEAN, ISUNIQUE, BMAGICHIT, CANPOISON, CANFRIGHTEN, CANSEE,
+ CANBBOLT, CANSUMMON, NOBOLT, CANTELEPORT, CARRYWAND, NOFIRE,
+ CARRYMISC, ISFLY, CARRYSTICK},
+ "vampire", 9,
+ 0,
+ {18, 18, 5, 260000, 27, -6, HPT("0d8+120"),
+ "1d10+3/2d4"}},
+{"arch devil (Asmodeus)",
+ 100, TRUE, FALSE, 'A', "20",
+ {ISMEAN, ISUNIQUE, CANSEE, ISSHADOW, CANHOLD, BMAGICHIT,
+ CANFRIGHTEN, CANHUH, TOUCHSLOW, CANSUMMON, NOFIRE,
+ CANTELEPORT, CARRYROD, CARRYMISC, CARRYSTICK, CANDRAIN},
+ "pit fiend", 5,
+ 0,
+ {18, 18, 5, 270000, 45, -7, HPT("0d8+199"),
+ "1d10+4"}},
+{"demon prince (Demogorgon)",
+ 100, TRUE, FALSE, 'D', "20",
+ {ISMEAN, CANHUH, BMAGICHIT, DOUBLEDRAIN, CANINFEST, CANSEE,
+ CANFRIGHTEN, ISUNIQUE, CANSUMMON, CANROT, CANTELEPORT, NOFIRE,
+ CANDISEASE, CARRYMISC, CANSUCK, CARRYSTICK},
+ "pit fiend", 9,
+ 0,
+ {18, 18, 5, 280000, 45, -8, HPT("0d8+200"),
+ "1d6/1d6"}},
+{"greater god (Maglubiyet)",
+ 100, TRUE, FALSE, 'M', "19",
+ {ISMEAN, ISUNIQUE, CMAGICHIT, CANSEE, ISREGEN, CANSUMMON,
+ CANTELEPORT, CARRYMISC, CANFRIGHTEN, CARRYSTICK},
+ "lich", 6,
+ 0,
+ {19, 18, 5, 290000, 45, -1, HPT("0d8+350"),
+ "2d10/2d10"}},
+{"greater god (Gruumsh)",
+ 100, TRUE, FALSE, 'G', "19",
+ {ISMEAN, ISUNIQUE, CMAGICHIT, CANSEE, ISREGEN, CANSUMMON,
+ CANTELEPORT, CARRYMISC, CANFRIGHTEN, CARRYSTICK},
+ "lich", 9,
+ 0,
+ {19, 18, 5, 300000, 45, -1, HPT("0d8+350"),
+ "3d10/3d10"}},
+{"lesser god (Thrym)",
+ 100, TRUE, FALSE, 'T', "16",
+ {ISMEAN, NOCOLD, ISUNIQUE, ISREGEN, CMAGICHIT, CANSEE,
+ CANSUMMON, CARRYMISC, CANTELEPORT, CANFRIGHTEN, CARRYSTICK},
+ "frost giant", 9,
+ 0,
+ {25, 18, 5, 310000, 45, -2, HPT("0d8+360"),
+ "4d10/4d10"}},
+{"lesser god (Surtur)",
+ 100, TRUE, FALSE, 't', "19",
+ {ISMEAN, NOFIRE, ISUNIQUE, ISREGEN, CMAGICHIT, CANSEE,
+ CANFRIGHTEN, CANSUMMON, CANMISSILE, CANTELEPORT, CARRYMISC,
+ CARRYSTICK, CARRYFOOD, CARRYSURTURRING},
+ "fire giant", 9,
+ 0,
+ {25, 18, 5, 320000, 45, -2, HPT("0d8+380"),
+ "5d10/5d10"}},
+{"lesser god (Skoraeus Stonebones)",
+ 100, TRUE, FALSE, 'b', "19",
+ {ISMEAN, ISUNIQUE, ISREGEN, CMAGICHIT, CANSEE, CANSUMMON, ISFLY,
+ CANMISSILE, CANINWALL, CANTELEPORT, CARRYMISC, CARRYSTICK,
+ CANFRIGHTEN, CARRYBAMULET},
+ "storm giant", 9,
+ 0,
+ {25, 25, 6, 330000, 45, -1, HPT("0d8+380"),
+ "6d10/6d10"}},
+{"ruler of greater titans (Yendor)",
+ 100, TRUE, TRUE, 'y', "25",
+ {ISMEAN, CANINWALL, ISUNIQUE, ISREGEN, CMAGICHIT,ISFLY,
+ CANSUMMON, CANMISSILE, CANFRIGHTEN, CANBFIRE, NOFIRE,
+ CANHOLD, CARRYYAMULET, CANSEE, CANDANCE, ISSHADOW,
+ CANTELEPORT, CARRYMISC, CARRYRING, CARRYSTICK},
+ "titan", 15,
+ 0,
+ {25, 25, 6, 340000, 45, -6, HPT("0d8+400"),
+ "7d10/7d10"}},
+{"the creator of liches (Vecna)",
+ 100, TRUE, TRUE, 'V', "25",
+ {ISMEAN, CANINWALL, ISUNIQUE, ISREGEN, CMAGICHIT, CANSNORE,
+ CANSUMMON, CANMISSILE, CANFRIGHTEN, CANBFIRE, NOFIRE, ISFLY,
+ CANHOLD, CARRYEYE, CANSEE, CANDANCE, ISINVIS, HALFDAMAGE,
+ CANTELEPORT, CARRYMISC, CARRYRING, CARRYSTICK, LOOKSTONE,
+ CANSLOW, CANBLIND},
+ "lich", 15,
+ 0,
+ {25, 25, 6, 350000, 47, -8, HPT("0d8+450"),
+ "6d10/6d10"}},
+{"quartermaster",
+ 0, FALSE, TRUE, 'q', "18",
+ {CANSELL, ISCLEAR, CANTELEPORT, ISFLY, CANSEE, STEALMAGIC,
+ NOFEAR, CANBSTAB},
+ 0, 0,
+ 50,
+ {25, 18, 12, 20, 1, -4, HPT("1d8+1"),
+ "1d10"}},
+};
diff -r d10fc4a065ac -r adfa37e67084 arogue7/rogue.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/rogue.h Fri May 08 15:24:40 2015 -0400
@@ -0,0 +1,1297 @@
+/*
+ * rogue.h - Rogue definitions and variable declarations
+ *
+ * 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.
+ */
+
+/*
+ * Rogue definitions and variable declarations
+ *
+ */
+
+#define reg register
+#undef lines /* AIX's term.h defines this, causing a conflict */
+#ifdef BSD
+#undef tolower(c)
+#define _tolower(c) ((c)-'A'+'a')
+extern char tolower();
+#undef toupper(c)
+#define _toupper(c) ((c)-'a'+'A')
+extern char toupper();
+#define strchr index
+
+#define exfork vfork /* Better way to do a fork followed by an exec */
+#else
+#define exfork fork /* Standard fork with no paging available */
+#endif
+
+/*
+ * Maximum number of different things
+ */
+#define MAXDAEMONS 10
+#define MAXFUSES 20
+#define MAXROOMS 9
+#define MAXTHINGS 9
+#define MAXOBJ 9
+#define MAXSTATS 72 /* max total of all stats at startup */
+#define MAXPACK 23
+#define MAXDOUBLE 14 /* Maximum number of times exppts is doubled */
+#define MAXCONTENTS 10
+#define MAXENCHANT 10 /* max number of enchantments on an item */
+#define MAXTREAS 15 /* number monsters/treasure in treasure room */
+#define MAXTRAPS 25
+#define MAXTRPTRY 8 /* attempts/level allowed for setting traps */
+#define MAXDOORS 4 /* Maximum doors to a room */
+#define MAXCHANTS 16 /* Maximum number of chants for a druid */
+#define MAXPRAYERS 18 /* Maximum number of prayers for cleric */
+#define MAXSPELLS 20 /* Maximum number of spells (for magician) */
+#define MAXQUILL 13 /* scrolls the Quill of Nagrom can write */
+#define QUILLCHARGES 160 /* max num of charges in the Quill of Nagrom */
+#define NUMMONST 125 /* Current number of monsters */
+#define NUM_CNAMES 17 /* number of names per character level */
+#define NUMUNIQUE 27 /* number of UNIQUE creatures */
+#define NLEVMONS 3 /* Number of new monsters per level */
+#define NUMSCORE 10 /* number of entries in score file */
+#define HARDER 35 /* at this level start making things harder */
+#define LINELEN 256 /* characters in a buffer */
+#define JUG_EMPTY -1 /* signifys that the alchemy jug is empty */
+#define MAXPURCH (pstats.s_charisma/3) /* # of purchases at post */
+
+/* Movement penalties */
+#define BACKPENALTY 3
+#define SHOTPENALTY 2 /* In line of sight of missile */
+#define DOORPENALTY 1 /* Moving out of current room */
+
+/*
+ * these defines are used in calls to get_item() to signify what
+ * it is we want
+ */
+#define ALL -1
+#define WEARABLE -2
+#define CALLABLE -3
+#define WIELDABLE -4
+#define USEABLE -5
+#define IDENTABLE -6
+#define REMOVABLE -7
+#define PROTECTABLE -8
+#define ZAPPABLE -9
+#define READABLE -10
+#define QUAFFABLE -11
+
+/*
+ * stuff to do with encumberance
+ */
+#define NORMENCB 1500 /* normal encumberance */
+#define F_SATIATED 0 /* player's stomach is very full */
+#define F_OKAY 1 /* have plenty of food in stomach */
+#define F_HUNGRY 2 /* player is hungry */
+#define F_WEAK 3 /* weak from lack of food */
+#define F_FAINT 4 /* fainting from lack of food */
+
+/*
+ * actions a player/monster will take
+ */
+#define A_MOVE 0200 /* normal movement */
+#define A_FREEZE 0201 /* frozen in place */
+#define A_ATTACK 0202 /* trying to hit */
+#define A_SELL 0203 /* trying to sell goods */
+#define A_NIL 0204 /* not doing anything */
+#define A_BREATHE 0205 /* breathing */
+#define A_MISSILE 0206 /* Firing magic missiles */
+#define A_SONIC 0207 /* Sounding a sonic blast */
+#define A_SUMMON 0210 /* Summoning help */
+#define A_USERELIC 0211 /* Monster uses a relic */
+#define A_SLOW 0212 /* monster slows the player */
+#define A_ZAP 0213 /* monster shoots a wand */
+#define A_PICKUP 0214 /* player is picking something up */
+#define A_USEWAND 0215 /* monster is shooting a wand */
+#define A_THROW 't'
+#define C_CAST 'C'
+#define C_COUNT '*'
+#define C_DIP 'D'
+#define C_DROP 'd'
+#define C_EAT 'e'
+#define C_PRAY 'p'
+#define C_CHANT 'c'
+#define C_QUAFF 'q'
+#define C_READ 'r'
+#define C_SEARCH 's'
+#define C_SETTRAP '^'
+#define C_TAKEOFF 'T'
+#define C_USE CTRL('U')
+#define C_WEAR 'W'
+#define C_WIELD 'w'
+#define C_ZAP 'z'
+
+/* Possible ways for the hero to move */
+#define H_TELEPORT 0
+
+/*
+ * return values for get functions
+ */
+#define NORM 0 /* normal exit */
+#define QUIT 1 /* quit option setting */
+#define MINUS 2 /* back up one option */
+
+/*
+ * The character types
+ */
+#define C_FIGHTER 0
+#define C_RANGER 1
+#define C_PALADIN 2
+#define C_MAGICIAN 3
+#define C_CLERIC 4
+#define C_THIEF 5
+#define C_ASSASIN 6
+#define C_DRUID 7
+#define C_MONK 8
+#define C_MONSTER 9
+#define NUM_CHARTYPES 10
+
+/*
+ * define the ability types
+ */
+#define A_INTELLIGENCE 0
+#define A_STRENGTH 1
+#define A_WISDOM 2
+#define A_DEXTERITY 3
+#define A_CONSTITUTION 4
+#define A_CHARISMA 5
+#define NUMABILITIES 6
+
+/*
+ * values for games end
+ */
+#define UPDATE -2
+#define SCOREIT -1
+#define KILLED 0
+#define CHICKEN 1
+#define WINNER 2
+
+/*
+ * definitions for function step_ok:
+ * MONSTOK indicates it is OK to step on a monster -- it
+ * is only OK when stepping diagonally AROUND a monster;
+ * it is also OK if the stepper is a friendly monster and
+ * is in a fighting mood.
+ */
+#define MONSTOK 1
+#define NOMONST 2
+#define FIGHTOK 3
+
+/*
+ * used for ring stuff
+ */
+#define LEFT_1 0
+#define LEFT_2 1
+#define LEFT_3 2
+#define LEFT_4 3
+#define RIGHT_1 4
+#define RIGHT_2 5
+#define RIGHT_3 6
+#define RIGHT_4 7
+#define NUM_FINGERS 8
+
+/*
+ * used for micellaneous magic (MM) stuff
+ */
+#define WEAR_BOOTS 0
+#define WEAR_BRACERS 1
+#define WEAR_CLOAK 2
+#define WEAR_GAUNTLET 3
+#define WEAR_JEWEL 4
+#define WEAR_NECKLACE 5
+#define NUM_MM 6
+
+/*
+ * All the fun defines
+ */
+#define next(ptr) (*ptr).l_next
+#define prev(ptr) (*ptr).l_prev
+#define ldata(ptr) (*ptr).l_data
+#define inroom(rp, cp) (\
+ (cp)->x <= (rp)->r_pos.x + ((rp)->r_max.x - 1) && (rp)->r_pos.x <= (cp)->x \
+ && (cp)->y <= (rp)->r_pos.y + ((rp)->r_max.y - 1) && (rp)->r_pos.y <= (cp)->y)
+#define winat(y, x) (mvwinch(mw, y, x)==' '?mvwinch(stdscr, y, x):winch(mw))
+#define debug if (wizard) msg
+#define RN (((seed = seed*11109+13849) & 0x7fff) >> 1)
+#define unc(cp) (cp).y, (cp).x
+#define cmov(xy) move((xy).y, (xy).x)
+#define DISTANCE(y1, x1, y2, x2) ((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1))
+#define OBJPTR(what) (struct object *)((*what).l_data)
+#define THINGPTR(what) (struct thing *)((*what).l_data)
+#define DOORPTR(what) (coord *)((*what).l_data)
+#define when break;case
+#define otherwise break;default
+#define until(expr) while(!(expr))
+#define ce(a, b) ((a).x == (b).x && (a).y == (b).y)
+#define draw(window) wrefresh(window)
+#define hero player.t_pos
+#define pstats player.t_stats
+#define max_stats player.maxstats
+#define pack player.t_pack
+#define attach(a, b) _attach(&a, b)
+#define detach(a, b) _detach(&a, b)
+#define o_free_list(a) _o_free_list(&a)
+#define r_free_list(a) _r_free_list(&a)
+#define t_free_list(a) _t_free_list(&a)
+#ifndef max
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#endif
+#define on(thing, flag) \
+ (((thing).t_flags[(flag >> FLAGSHIFT) & FLAGINDEX] & flag) != 0)
+#define off(thing, flag) \
+ (((thing).t_flags[(flag >> FLAGSHIFT) & FLAGINDEX] & flag) == 0)
+#define turn_on(thing, flag) \
+ ((thing).t_flags[(flag >> FLAGSHIFT) & FLAGINDEX] |= (flag & ~FLAGMASK))
+#define turn_off(thing, flag) \
+ ((thing).t_flags[(flag >> FLAGSHIFT) & FLAGINDEX] &= ~flag)
+
+#undef CTRL
+#define CTRL(ch) (ch & 037)
+
+#define ALLOC(x) calloc((unsigned int) x,1)
+#define FREE(x) free((char *) x)
+#define EQSTR(a, b, c) (strncmp(a, b, c) == 0)
+#define EQUAL(a, b) (strcmp(a, b) == 0)
+#define GOLDCALC (rnd(50 + 10 * level) + 2)
+#define ISRING(h, r) (cur_ring[h] != NULL && cur_ring[h]->o_which == r)
+#define ISWEARING(r) (ISRING(LEFT_1, r) || ISRING(LEFT_2, r) ||\
+ ISRING(LEFT_3, r) || ISRING(LEFT_4, r) ||\
+ ISRING(RIGHT_1, r) || ISRING(RIGHT_2, r) ||\
+ ISRING(RIGHT_3, r) || ISRING(RIGHT_4, r))
+#define newgrp() ++group
+#define o_charges o_ac
+#define o_kind o_ac
+#define ISMULT(type) (type == FOOD)
+#define isrock(ch) ((ch == WALL) || (ch == '-') || (ch == '|') || (ch == SECRETDOOR))
+#define invisible(monst) \
+ (((on(*monst, ISINVIS) || \
+ (on(*monst, ISSHADOW) && rnd(100) < 90)) && \
+ off(player, CANSEE)) || \
+ (on(*monst, CANSURPRISE) && !ISWEARING(R_ALERT)))
+#define is_stealth(tp) \
+ (rnd(25) < (tp)->t_stats.s_dext || (tp == &player && ISWEARING(R_STEALTH)))
+
+#define has_light(rp) (((rp)->r_flags & HASFIRE) || ISWEARING(R_LIGHT))
+
+#define mi_wght mi_worth
+#define mi_food mi_curse
+
+/*
+ * Ways to die
+ */
+#define D_PETRIFY -1
+#define D_ARROW -2
+#define D_DART -3
+#define D_POISON -4
+#define D_BOLT -5
+#define D_SUFFOCATION -6
+#define D_POTION -7
+#define D_INFESTATION -8
+#define D_DROWN -9
+#define D_ROT -10
+#define D_CONSTITUTION -11
+#define D_STRENGTH -12
+#define D_SIGNAL -13
+#define D_CHOKE -14
+#define D_STRANGLE -15
+#define D_FALL -16
+#define D_RELIC -17
+#define D_STARVATION -18
+#define D_FOOD_CHOKE -19
+#define D_SCROLL -20
+#define DEATHNUM 20 /* number of ways to die */
+
+/*
+ * Things that appear on the screens
+ */
+#define WALL ' '
+#define PASSAGE '#'
+#define DOOR '+'
+#define FLOOR '.'
+#define VPLAYER '@'
+#define IPLAYER '_'
+#define POST '^'
+#define TRAPDOOR '>'
+#define ARROWTRAP '{'
+#define SLEEPTRAP '$'
+#define BEARTRAP '}'
+#define TELTRAP '~'
+#define DARTTRAP '`'
+#define POOL '"'
+#define MAZETRAP '\''
+#define SECRETDOOR '&'
+#define STAIRS '%'
+#define GOLD '*'
+#define POTION '!'
+#define SCROLL '?'
+#define MAGIC '$'
+#define BMAGIC '>' /* Blessed magic */
+#define CMAGIC '<' /* Cursed magic */
+#define FOOD ':'
+#define WEAPON ')'
+#define MISSILE '*' /* Magic Missile */
+#define ARMOR ']'
+#define MM ';'
+#define RELIC ','
+#define RING '='
+#define STICK '/'
+#define FOREST '\\'
+
+/*
+ * Various constants
+ */
+#define PASSWD "mTdNfNGDrwAZ."
+#define FIGHTBASE 10
+#define SPELLTIME ((max(30-pstats.s_lvl,5)))
+#define BEARTIME 17
+#define CLOAK_TIME (roll(20,20))
+#define SLEEPTIME 7
+#define FREEZETIME 11
+#define PAINTIME (roll(2, 12))
+#define HEALTIME 30
+#define CHILLTIME (roll(20, 4))
+#define SMELLTIME 20
+#define STONETIME (roll(10,2))
+#define HASTETIME 11
+#define SICKTIME 25
+#define WANDERTIME (max(5, (HARDER*2)-rnd(vlevel)))
+#define BEFORE 1
+#define AFTER 2
+#define HUHDURATION (50+rnd(30))
+#define SEEDURATION 850
+#define SKILLDURATION (100+rnd(50))
+#define CLRDURATION 50
+#define GONETIME 200
+#define FIRETIME (200+roll(5,5))
+#define COLDTIME (200+roll(5,5))
+#define BOLTTIME (200+roll(5,5))
+#define FLYTIME 300
+#define DUSTTIME (30+roll(5,10))
+#define PHASEDURATION 300
+#define MORETIME 100
+#define STINKTIME 16
+#define STOMACHSIZE 1500
+#define ESCAPE 27
+#define BOLT_LENGTH 10
+#define MARKLEN 20
+#define DAYLENGTH 400
+#define ALCHEMYTIME (400+rnd(150))
+
+/*
+ * Save against things
+ */
+#define VS_POISON 00
+#define VS_PARALYZATION 00
+#define VS_DEATH 00
+#define VS_PETRIFICATION 01
+#define VS_WAND 02
+#define VS_BREATH 03
+#define VS_MAGIC 04
+
+/*
+ * attributes for treasures in dungeon
+ */
+#define ISCURSED 01
+#define ISKNOW 02
+#define ISPOST 04 /* object is in a trading post */
+#define ISMETAL 010
+#define ISPROT 020 /* object is protected */
+#define ISBLESSED 040
+#define ISPOISON 0100
+#define ISMISL 020000
+#define ISMANY 040000
+/*
+ * Various flag bits
+ */
+#define ISDARK 01
+#define ISGONE 02
+#define ISTREAS 04
+#define ISFOUND 010
+#define ISTHIEFSET 020
+#define FORCEDARK 040
+/*
+ * 1st set of creature flags (this might include player)
+ */
+#define ISBLIND 0x00000001
+#define ISINWALL 0x00000002
+#define ISRUN 0x00000004
+#define ISFLEE 0x00000008
+#define ISINVIS 0x00000010
+#define ISMEAN 0x00000020
+#define ISGREED 0x00000040
+#define CANSHOOT 0x00000080
+#define ISHELD 0x00000100
+#define ISHUH 0x00000200
+#define ISREGEN 0x00000400
+#define CANHUH 0x00000800
+#define CANSEE 0x00001000
+#define HASFIRE 0x00002000
+#define ISSLOW 0x00004000
+#define ISHASTE 0x00008000
+#define ISCLEAR 0x00010000
+#define CANINWALL 0x00020000
+#define ISDISGUISE 0x00040000
+#define CANBLINK 0x00080000
+#define CANSNORE 0x00100000
+#define HALFDAMAGE 0x00200000
+#define CANSUCK 0x00400000
+#define CANRUST 0x00800000
+#define CANPOISON 0x01000000
+#define CANDRAIN 0x02000000
+#define ISUNIQUE 0x04000000
+#define STEALGOLD 0x08000000
+/*
+ * Second set of flags
+ */
+#define STEALMAGIC 0x10000001
+#define CANDISEASE 0x10000002
+#define HASDISEASE 0x10000004
+#define CANSUFFOCATE 0x10000008
+#define DIDSUFFOCATE 0x10000010
+#define BOLTDIVIDE 0x10000020
+#define BLOWDIVIDE 0x10000040
+#define NOCOLD 0x10000080
+#define TOUCHFEAR 0x10000100
+#define BMAGICHIT 0x10000200
+#define NOFIRE 0x10000400
+#define NOBOLT 0x10000800
+#define CARRYGOLD 0x10001000
+#define CANITCH 0x10002000
+#define HASITCH 0x10004000
+#define DIDDRAIN 0x10008000
+#define WASTURNED 0x10010000
+#define CANSELL 0x10020000
+#define CANBLIND 0x10040000
+#define NOACID 0x10080000
+#define NOSLOW 0x10100000
+#define NOFEAR 0x10200000
+#define NOSLEEP 0x10400000
+#define NOPARALYZE 0x10800000
+#define NOGAS 0x11000000
+#define CANMISSILE 0x12000000
+#define CMAGICHIT 0x14000000
+#define CANPAIN 0x18000000
+
+/*
+ * Third set of flags
+ */
+#define CANSLOW 0x20000001
+#define CANTUNNEL 0x20000002
+#define TAKEWISDOM 0x20000004
+#define NOMETAL 0x20000008
+#define MAGICHIT 0x20000010
+#define CANINFEST 0x20000020
+#define HASINFEST 0x20000040
+#define NOMOVE 0x20000080
+#define CANSHRIEK 0x20000100
+#define CANDRAW 0x20000200
+#define CANSMELL 0x20000400
+#define CANPARALYZE 0x20000800
+#define CANROT 0x20001000
+#define ISSCAVENGE 0x20002000
+#define DOROT 0x20004000
+#define CANSTINK 0x20008000
+#define HASSTINK 0x20010000
+#define ISSHADOW 0x20020000
+#define CANCHILL 0x20040000
+#define CANHUG 0x20080000
+#define CANSURPRISE 0x20100000
+#define CANFRIGHTEN 0x20200000
+#define CANSUMMON 0x20400000
+#define TOUCHSTONE 0x20800000
+#define LOOKSTONE 0x21000000
+#define CANHOLD 0x22000000
+#define DIDHOLD 0x24000000
+#define DOUBLEDRAIN 0x28000000
+
+/*
+ * Fourth set of flags
+ */
+#define CANBRANDOM 0x30000001 /* Types of breath */
+#define CANBACID 0x30000002 /* acid */
+#define CANBFIRE 0x30000004 /* Fire */
+#define CANBCGAS 0x30000008 /* confusion gas */
+#define CANBBOLT 0x30000010 /* lightning bolt */
+#define CANBGAS 0x30000020 /* clorine gas */
+#define CANBICE 0x30000040 /* ice */
+#define CANBFGAS 0x30000080 /* Fear gas */
+#define CANBPGAS 0x30000100 /* Paralyze gas */
+#define CANBSGAS 0x30000200 /* Sleeping gas */
+#define CANBSLGAS 0x30000400 /* Slow gas */
+#define CANBREATHE 0x300007ff /* Can it breathe at all? */
+/*
+ * Fifth set of flags
+ */
+#define ISUNDEAD 0x40000001
+#define CANSONIC 0x40000002
+#define TURNABLE 0x40000004
+#define TAKEINTEL 0x40000008
+#define NOSTAB 0x40000010
+#define CANDISSOLVE 0x40000020
+#define ISFLY 0x40000040 /* creature can fly */
+#define CANTELEPORT 0x40000080 /* creature can teleport */
+#define CANEXPLODE 0x40000100 /* creature explodes when hit */
+#define CANDANCE 0x40000200 /* creature can make hero "dance" */
+#define ISDANCE 0x40000400 /* creature (hero) is dancing */
+#define CARRYFOOD 0x40000800
+#define CARRYSCROLL 0x40001000
+#define CARRYPOTION 0x40002000
+#define CARRYRING 0x40004000
+#define CARRYSTICK 0x40008000
+#define CARRYMISC 0x40010000
+#define CARRYMDAGGER 0x40020000 /* Dagger of Musty */
+#define CARRYCLOAK 0x40040000 /* Cloak of Emori */
+#define CARRYANKH 0x40080000 /* Ankh of Heil */
+#define CARRYSTAFF 0x40100000 /* Staff of Ming */
+#define CARRYWAND 0x40200000 /* Wand of Orcus */
+#define CARRYROD 0x40400000 /* Rod of Asmodeus */
+#define CARRYYAMULET 0x40800000 /* Amulet of Yendor */
+#define CARRYMANDOLIN 0x41000000 /* Mandolin of Brian */
+#define MISSEDDISP 0x42000000 /* Missed Cloak of Displacement */
+#define CANBSTAB 0x44000000 /* Can backstab */
+#define ISGUARDIAN 0x48000000 /* Guardian of a treasure room */
+
+
+#define CARRYHORN 0x50000001 /* Horn of Geryon */
+#define CARRYMSTAR 0x50000002 /* Morning Star of Hruggek */
+#define CARRYFLAIL 0x50000004 /* Flail of Yeenoghu */
+#define CARRYWEAPON 0x50000008 /* A generic weapon */
+#define CANAGE 0x50000010 /* can age you */
+#define CARRYDAGGER 0x50000020 /* carry's a dumb old dagger */
+#define AREMANY 0x50000040 /* they come in droves */
+#define CARRYEYE 0x50000080 /* has the eye of Vecna */
+#define HASSUMMONED 0x50000100 /* has already summoned */
+#define ISSTONE 0x50000200 /* has been turned to stone */
+#define NODETECT 0x50000400 /* detect monster will not show him */
+#define NOSTONE 0x50000800 /* creature made its save vrs stone */
+#define CARRYQUILL 0x50001000 /* has the quill of Nagrom */
+#define CARRYAXE 0x50002000 /* has the axe of Aklad */
+#define TOUCHSLOW 0x50004000 /* touch will slow hero */
+#define WASDISRUPTED 0x50008000 /* creature was disrupted by player */
+#define CARRYARMOR 0x50010000 /* creature will pick up armor */
+#define CARRYBAMULET 0x50020000 /* amulet of skoraus stonebones */
+#define CARRYSURTURRING 0x50040000 /* ring of Surtur */
+#define ISCHARMED 0x50080000 /* is the monster charmed? */
+#define ISFRIENDLY 0x50080000 /* monster friendly for any reason? */
+
+#define ISREADY 0x60000001
+#define ISDEAD 0x60000002
+#define ISELSEWHERE 0x60000004
+
+/* Masks for choosing the right flag */
+#define FLAGMASK 0xf0000000
+#define FLAGINDEX 0x0000000f
+#define FLAGSHIFT 28
+#define MAXFLAGS 25 /* max initial flags per creature */
+
+/*
+ * Mask for cancelling special abilities
+ * The flags listed here will be the ones left on after the
+ * cancellation takes place
+ */
+#define CANC0MASK ( ISBLIND | ISINWALL | ISRUN | \
+ ISFLEE | ISMEAN | ISGREED | \
+ CANSHOOT | ISHELD | ISHUH | \
+ ISSLOW | ISHASTE | ISCLEAR | \
+ ISUNIQUE )
+#define CANC1MASK ( HASDISEASE | DIDSUFFOCATE | CARRYGOLD | \
+ HASITCH | CANSELL | DIDDRAIN | \
+ WASTURNED )
+#define CANC2MASK ( HASINFEST | NOMOVE | ISSCAVENGE | \
+ DOROT | HASSTINK | DIDHOLD )
+#define CANC3MASK ( CANBREATHE )
+#define CANC4MASK ( ISUNDEAD | CANSONIC | NOSTAB | \
+ ISFLY | CARRYFOOD | CANEXPLODE | \
+ ISDANCE | CARRYSCROLL | CARRYPOTION | \
+ CARRYRING | CARRYSTICK | CARRYMISC | \
+ CARRYMDAGGER | CARRYCLOAK | CARRYANKH | \
+ CARRYSTAFF | CARRYWAND | CARRYROD | \
+ CARRYYAMULET | CARRYMANDOLIN | ISGUARDIAN )
+#define CANC5MASK ( CARRYHORN | CARRYMSTAR | CARRYFLAIL | \
+ CARRYEYE | CARRYDAGGER | HASSUMMONED | \
+ AREMANY | CARRYWEAPON | NOSTONE | \
+ CARRYQUILL | CARRYAXE | WASDISRUPTED | \
+ CARRYARMOR | CARRYBAMULET | CARRYSURTURRING )
+#define CANC6MASK ( 0 )
+#define CANC7MASK ( 0 )
+#define CANC8MASK ( 0 )
+#define CANC9MASK ( 0 )
+#define CANCAMASK ( 0 )
+#define CANCBMASK ( 0 )
+#define CANCCMASK ( 0 )
+#define CANCDMASK ( 0 )
+#define CANCEMASK ( 0 )
+#define CANCFMASK ( 0 )
+
+/* types of things */
+#define TYP_POTION 0
+#define TYP_SCROLL 1
+#define TYP_FOOD 2
+#define TYP_WEAPON 3
+#define TYP_ARMOR 4
+#define TYP_RING 5
+#define TYP_STICK 6
+#define TYP_MM 7
+#define TYP_RELIC 8
+#define NUMTHINGS 9
+/*
+ * food types
+ */
+#define E_RATION 0
+#define E_APPLE 1
+#define E_BANANA 2
+#define E_BLUEBERRY 3
+#define E_CANDLEBERRY 4
+#define E_CAPRIFIG 5
+#define E_DEWBERRY 6
+#define E_ELDERBERRY 7
+#define E_GOOSEBERRY 8
+#define E_GUANABANA 9
+#define E_HAGBERRY 10
+#define E_JABOTICABA 11
+#define E_PEACH 12
+#define E_PITANGA 13
+#define E_PRICKLEY 14
+#define E_RAMBUTAN 15
+#define E_SAPODILLA 16
+#define E_SOURSOP 17
+#define E_STRAWBERRY 18
+#define E_SWEETSOP 19
+#define E_WHORTLEBERRY 20
+#define MAXFOODS 21
+/*
+ * Potion types
+ */
+#define P_CLEAR 0
+#define P_ABIL 1
+#define P_SEEINVIS 2
+#define P_HEALING 3
+#define P_MFIND 4
+#define P_TFIND 5
+#define P_RAISE 6
+#define P_HASTE 7
+#define P_RESTORE 8
+#define P_PHASE 9
+#define P_INVIS 10
+#define P_FLY 11
+#define P_FFIND 12
+#define P_SKILL 13
+#define P_FIRE 14
+#define P_COLD 15
+#define P_LIGHTNING 16
+#define P_POISON 17
+#define MAXPOTIONS 18
+/*
+ * Scroll types
+ */
+#define S_CONFUSE 0
+#define S_MAP 1
+#define S_LIGHT 2
+#define S_HOLD 3
+#define S_SLEEP 4
+#define S_ALLENCH 5
+#define S_IDENT 6
+#define S_SCARE 7
+#define S_GFIND 8
+#define S_TELEP 9
+#define S_CREATE 10
+#define S_REMOVE 11
+#define S_PETRIFY 12
+#define S_GENOCIDE 13
+#define S_CURING 14
+#define S_MAKEIT 15
+#define S_PROTECT 16
+#define S_FINDTRAPS 17
+#define S_RUNES 18
+#define S_CHARM 19
+#define MAXSCROLLS 20
+
+/*
+ * Weapon types
+ */
+#define MACE 0 /* mace */
+#define SWORD 1 /* long sword */
+#define BOW 2 /* short bow */
+#define ARROW 3 /* arrow */
+#define DAGGER 4 /* dagger */
+#define ROCK 5 /* rocks */
+#define TWOSWORD 6 /* two-handed sword */
+#define SLING 7 /* sling */
+#define DART 8 /* darts */
+#define CROSSBOW 9 /* crossbow */
+#define BOLT 10 /* crossbow bolt */
+#define SPEAR 11 /* spear */
+#define TRIDENT 12 /* trident */
+#define SPETUM 13 /* spetum */
+#define BARDICHE 14 /* bardiche */
+#define PIKE 15 /* pike */
+#define BASWORD 16 /* bastard sword */
+#define HALBERD 17 /* halberd */
+#define BATTLEAXE 18 /* battle axe */
+#define MAXWEAPONS 19 /* types of weapons */
+#define NONE 100 /* no weapon */
+
+/*
+ * Armor types
+ */
+#define LEATHER 0
+#define RING_MAIL 1
+#define STUDDED_LEATHER 2
+#define SCALE_MAIL 3
+#define PADDED_ARMOR 4
+#define CHAIN_MAIL 5
+#define SPLINT_MAIL 6
+#define BANDED_MAIL 7
+#define PLATE_MAIL 8
+#define PLATE_ARMOR 9
+#define MAXARMORS 10
+
+/*
+ * Ring types
+ */
+#define R_PROTECT 0
+#define R_ADDSTR 1
+#define R_SUSABILITY 2
+#define R_SEARCH 3
+#define R_SEEINVIS 4
+#define R_ALERT 5
+#define R_AGGR 6
+#define R_ADDHIT 7
+#define R_ADDDAM 8
+#define R_REGEN 9
+#define R_DIGEST 10
+#define R_TELEPORT 11
+#define R_STEALTH 12
+#define R_ADDINTEL 13
+#define R_ADDWISDOM 14
+#define R_HEALTH 15
+#define R_CARRY 16
+#define R_LIGHT 17
+#define R_DELUSION 18
+#define R_FEAR 19
+#define R_HEROISM 20
+#define R_FIRE 21
+#define R_WARMTH 22
+#define R_VAMPREGEN 23
+#define R_FREEDOM 24
+#define R_TELCONTROL 25
+#define MAXRINGS 26
+
+/*
+ * Rod/Wand/Staff types
+ */
+
+#define WS_LIGHT 0
+#define WS_HIT 1
+#define WS_ELECT 2
+#define WS_FIRE 3
+#define WS_COLD 4
+#define WS_POLYMORPH 5
+#define WS_MISSILE 6
+#define WS_SLOW_M 7
+#define WS_DRAIN 8
+#define WS_CHARGE 9
+#define WS_TELMON 10
+#define WS_CANCEL 11
+#define WS_CONFMON 12
+#define WS_DISINTEGRATE 13
+#define WS_PETRIFY 14
+#define WS_PARALYZE 15
+#define WS_MDEG 16
+#define WS_CURING 17
+#define WS_WONDER 18
+#define WS_FEAR 19
+#define MAXSTICKS 20
+
+/*
+ * miscellaneous magic items
+ */
+#define MM_JUG 0
+#define MM_BEAKER 1
+#define MM_BOOK 2
+#define MM_ELF_BOOTS 3
+#define MM_BRACERS 4
+#define MM_OPEN 5
+#define MM_HUNGER 6
+#define MM_DISP 7
+#define MM_PROTECT 8
+#define MM_DRUMS 9
+#define MM_DISAPPEAR 10
+#define MM_CHOKE 11
+#define MM_G_DEXTERITY 12
+#define MM_G_OGRE 13
+#define MM_JEWEL 14
+#define MM_KEOGHTOM 15
+#define MM_R_POWERLESS 16
+#define MM_FUMBLE 17
+#define MM_ADAPTION 18
+#define MM_STRANGLE 19
+#define MM_DANCE 20
+#define MM_SKILLS 21
+#define MAXMM 22
+
+/*
+ * Relic types
+ */
+#define MUSTY_DAGGER 0
+#define EMORI_CLOAK 1
+#define HEIL_ANKH 2
+#define MING_STAFF 3
+#define ORCUS_WAND 4
+#define ASMO_ROD 5
+#define YENDOR_AMULET 6
+#define BRIAN_MANDOLIN 7
+#define GERYON_HORN 8
+#define HRUGGEK_MSTAR 9
+#define YEENOGHU_FLAIL 10
+#define EYE_VECNA 11
+#define AXE_AKLAD 12
+#define QUILL_NAGROM 13
+#define STONEBONES_AMULET 14
+#define SURTUR_RING 15
+#define MAXRELIC 16
+
+
+#define LEVEL 600
+#define vlevel max(level, turns/LEVEL + 1)
+/*
+ * Now we define the structures and types
+ */
+/*
+ * character types
+ */
+struct character_types {
+ char name[40]; /* name of character class */
+ long start_exp; /* starting exp pts for 2nd level */
+ long cap; /* stop doubling here */
+ int hit_pts; /* hit pts gained per level */
+ int base; /* Base to-hit value (AC 10) */
+ int max_lvl; /* Maximum level for changing value */
+ int factor; /* Amount base changes each time */
+ int offset; /* What to offset level */
+ int range; /* Range of levels for each offset */
+};
+
+/*
+ * level types
+ */
+typedef enum {
+ NORMLEV, /* normal level */
+ POSTLEV, /* trading post level */
+ MAZELEV, /* maze level */
+ OUTSIDE, /* outside level */
+ STARTLEV /* beginning of the game */
+} LEVTYPE;
+
+/*
+ * Help list
+ */
+
+struct h_list {
+ char h_ch;
+ char *h_desc;
+};
+
+/*
+ * Coordinate data type
+ */
+typedef struct {
+ int x;
+ int y;
+} coord;
+
+/*
+ * structure for the ways to die
+ */
+struct death_type {
+ int reason;
+ char *name;
+};
+
+
+/*
+ * Linked list data type
+ */
+struct linked_list {
+ struct linked_list *l_next;
+ struct linked_list *l_prev;
+ char *l_data; /* Various structure pointers */
+};
+
+/*
+ * Stuff about magic items
+ */
+
+struct magic_item {
+ char *mi_name;
+ int mi_prob;
+ int mi_worth;
+ int mi_curse;
+ int mi_bless;
+};
+
+/*
+ * Room structure
+ */
+struct room {
+ coord r_pos; /* Upper left corner */
+ coord r_max; /* Size of room */
+ long r_flags; /* Info about the room */
+ struct linked_list *r_fires; /* List of fire creatures in room */
+ struct linked_list *r_exit; /* Linked list of exits */
+};
+
+/*
+ * Array of all traps on this level
+ */
+
+struct trap {
+ char tr_type; /* What kind of trap */
+ char tr_show; /* Where disguised trap looks like */
+ coord tr_pos; /* Where trap is */
+ long tr_flags; /* Info about trap (i.e. ISFOUND) */
+};
+
+/*
+ * Structure describing a fighting being
+ */
+struct stats {
+ short s_str; /* Strength */
+ short s_intel; /* Intelligence */
+ short s_wisdom; /* Wisdom */
+ short s_dext; /* Dexterity */
+ short s_const; /* Constitution */
+ short s_charisma; /* Charisma */
+ unsigned long s_exp; /* Experience */
+ int s_lvladj; /* how much level is adjusted */
+ int s_lvl; /* Level of mastery */
+ int s_arm; /* Armor class */
+ int s_hpt; /* Hit points */
+ int s_pack; /* current weight of his pack */
+ int s_carry; /* max weight he can carry */
+ char s_dmg[30]; /* String describing damage done */
+};
+
+/*
+ * Structure describing a fighting being (monster at initialization)
+ */
+struct mstats {
+ short s_str; /* Strength */
+ short s_dex; /* dexterity */
+ short s_move; /* movement rate */
+ unsigned long s_exp; /* Experience */
+ short s_lvl; /* Level of mastery */
+ short s_arm; /* Armor class */
+ char *s_hpt; /* Hit points */
+ char *s_dmg; /* String describing damage done */
+};
+
+/*
+ * Structure for monsters and player
+ */
+struct thing {
+ bool t_wasshot; /* Was character shot last round? */
+ char t_type; /* What it is */
+ char t_disguise; /* What mimic looks like */
+ char t_oldch; /* Character that was where it was */
+ short t_ctype; /* Character type */
+ short t_index; /* Index into monster table */
+ short t_no_move; /* How long the thing can't move */
+ short t_quiet; /* used in healing */
+ short t_movement; /* Base movement rate */
+ short t_action; /* Action we're waiting to do */
+ short t_artifact; /* base chance of using artifact */
+ short t_wand; /* base chance of using wands */
+ short t_summon; /* base chance of summoning */
+ short t_cast; /* base chance of casting a spell */
+ short t_breathe; /* base chance to swing at player */
+ char *t_name; /* name player gave his pet */
+ coord *t_doorgoal; /* What door are we heading to? */
+ coord *t_dest; /* Where it is running to */
+ coord t_pos; /* Position */
+ coord t_oldpos; /* Last position */
+ coord t_newpos; /* Where we want to go */
+ unsigned long t_flags[16]; /* State word */
+ struct linked_list *t_pack; /* What the thing is carrying */
+ struct linked_list *t_using; /* What the thing is using */
+ int t_selection;
+ struct stats t_stats; /* Physical description */
+ struct stats maxstats; /* maximum(or initial) stats */
+ int t_reserved;
+};
+
+/*
+ * Array containing information on all the various types of monsters
+ */
+struct monster {
+ char *m_name; /* What to call the monster */
+ short m_carry; /* Probability of carrying something */
+ bool m_normal; /* Does monster exist? */
+ bool m_wander; /* Does monster wander? */
+ char m_appear; /* What does monster look like? */
+ char *m_intel; /* Intelligence range */
+ long m_flags[MAXFLAGS]; /* Things about the monster */
+ char *m_typesum; /* type of creature can he summon */
+ short m_numsum; /* how many creatures can he summon */
+ short m_add_exp; /* Added experience per hit point */
+ struct mstats m_stats; /* Initial stats */
+};
+
+/*
+ * Structure for a thing that the rogue can carry
+ */
+
+struct object {
+ int o_type; /* What kind of object it is */
+ coord o_pos; /* Where it lives on the screen */
+ char *o_text; /* What it says if you read it */
+ char o_launch; /* What you need to launch it */
+ char o_damage[8]; /* Damage if used like sword */
+ char o_hurldmg[8]; /* Damage if thrown */
+ struct linked_list *contents; /* contents of this object */
+ int o_count; /* Count for plural objects */
+ int o_which; /* Which object of a type it is */
+ int o_hplus; /* Plusses to hit */
+ int o_dplus; /* Plusses to damage */
+ int o_ac; /* Armor class */
+ long o_flags; /* Information about objects */
+ int o_group; /* Group number for this object */
+ int o_weight; /* weight of this object */
+ char o_mark[MARKLEN]; /* Mark the specific object */
+};
+/*
+ * weapon structure
+ */
+struct init_weps {
+ char *w_name; /* name of weapon */
+ char *w_dam; /* hit damage */
+ char *w_hrl; /* hurl damage */
+ char w_launch; /* need to launch it */
+ int w_flags; /* flags */
+ int w_rate; /* rate of fire */
+ int w_wght; /* weight of weapon */
+ int w_worth; /* worth of this weapon */
+};
+
+/*
+ * armor structure
+ */
+struct init_armor {
+ char *a_name; /* name of armor */
+ int a_prob; /* chance of getting armor */
+ int a_class; /* normal armor class */
+ int a_worth; /* worth of armor */
+ int a_wght; /* weight of armor */
+};
+
+struct spells {
+ short s_which; /* which scroll or potion */
+ short s_cost; /* cost of casting spell */
+ short s_type; /* scroll or potion */
+ int s_flag; /* is the spell blessed/cursed? */
+};
+
+struct quill {
+ short s_which; /* which scroll to write */
+ short s_cost; /* cost of writing it */
+};
+
+struct delayed_action {
+ int d_type;
+ int (*d_func)();
+ union {
+ int arg;
+ void *varg;
+ } d_;
+ int d_time;
+} ;
+
+struct linked_list *find_mons(), *find_obj(), *get_item(), *new_item(),
+ *new_thing(), *wake_monster(), *get_hurl(),
+ *spec_item(), *creat_item(), *wield_weap();
+struct room *roomin();
+struct trap *trap_at();
+
+/* char *malloc(), *getenv(), *tr_name(), *new(), *sprintf(), */
+char *getenv(), *tr_name(), *new(),
+ *vowelstr(), *inv_name(), *strcpy(), *strcat();
+char *num(), *ring_num(), *misc_num(), *blesscurse(), *p_kind(),
+ *typ_name(), *prname(), *monster_name(), *weap_name(), *misc_name();
+coord *rndmove(), *can_shoot(), *fallpos(), *doorway(), get_coordinates();
+short randmonster(), id_monst(), movement();
+void quit(int), auto_save(int), bugkill(int), endit(int), tstp(int),
+ byebye(int);
+int nohaste(), spell_recovery(),
+ doctor(), runners(), swander(), unconfuse(), unsee(), fumble(),
+ unclrhead(), unphase(), noslow(), rollwand(), stomach(), sight(),
+ unstink(), suffocate(), cure_disease(), shoot_bolt(), changeclass(),
+ appear(), dust_appear(), unchoke(), alchemy(), trap_look(), strangle(),
+ ring_teleport(), ring_search(), grab(), dsrpt_player(), quill_charge(),
+ make_sell_pack(), unskill(), findmindex(), nobolt(), nofire(), nocold(),
+ usage_time(), eat_gold(), chant_recovery(), prayer_recovery(),
+ dsrpt_monster();
+bool blue_light(), can_blink(), creat_mons(), add_pack(),
+ straight_shot(), maze_view(), lit_room(), getdelta(), save_file(),
+ save_game(), m_use_it(), m_use_pack(), get_dir(), need_dir();
+long lseek(), check_level();
+void genmonsters(),
+ add_intelligence(), add_strength(), add_wisdom(), add_dexterity(),
+ add_constitution(), add_charisma(), res_intelligence(), res_strength(int),
+ res_wisdom(), res_dexterity(), res_constitution(), res_charisma();
+
+
+#ifdef CHECKTIME
+int checkout();
+#endif
+
+
+/*
+ * Now all the global variables
+ */
+
+extern struct trap traps[];
+extern struct h_list helpstr[];
+extern struct h_list wiz_help[];
+extern struct character_types char_class[];/* character classes */
+extern struct room rooms[]; /* One for each room -- A level */
+extern struct room *oldrp; /* Roomin(&oldpos) */
+extern struct linked_list *mlist; /* List of monsters on the level */
+extern struct linked_list *tlist; /* list of monsters fallen down traps */
+extern struct death_type deaths[]; /* all the ways to die */
+extern struct thing player; /* The rogue */
+extern struct monster monsters[NUMMONST+1]; /* The initial monster states */
+extern struct linked_list *lvl_obj; /* List of objects on this level */
+extern struct linked_list *monst_dead; /* Indicates monster that got killed */
+extern struct object *cur_weapon; /* Which weapon he is weilding */
+extern struct object *cur_armor; /* What a well dresssed rogue wears */
+extern struct object *cur_ring[]; /* Which rings are being worn */
+extern struct object *cur_misc[]; /* which MM's are in use */
+extern struct magic_item things[]; /* Chances for each type of item */
+extern struct magic_item s_magic[]; /* Names and chances for scrolls */
+extern struct magic_item p_magic[]; /* Names and chances for potions */
+extern struct magic_item r_magic[]; /* Names and chances for rings */
+extern struct magic_item ws_magic[]; /* Names and chances for sticks */
+extern struct magic_item m_magic[]; /* Names and chances for MM */
+extern struct magic_item rel_magic[]; /* Names and chances for relics */
+extern struct magic_item foods[]; /* Names and chances for foods */
+extern struct spells magic_spells[]; /* spells for magic users */
+extern struct spells cleric_spells[]; /* spells for clerics */
+extern struct spells druid_spells[]; /* spells for druids */
+extern struct quill quill_scrolls[]; /* scrolls for quill */
+extern char *cnames[][17]; /* Character level names */
+extern char *abilities[NUMABILITIES]; /* Names of the various abilities */
+extern char curpurch[]; /* name of item ready to buy */
+extern char PLAYER; /* what the player looks like */
+extern char nfloors; /* Number of floors in this dungeon */
+extern int cols; /* number of columns on terminal */
+extern int lines; /* number of lines in terminal */
+extern int char_type; /* what type of character is player */
+extern int foodlev; /* how fast he eats food */
+extern int level; /* What level rogue is on */
+extern int trader; /* number of purchases */
+extern int curprice; /* price of an item */
+extern int purse; /* How much gold the rogue has */
+extern int mpos; /* Where cursor is on top line */
+extern int ntraps; /* Number of traps on this level */
+extern int inpack; /* Number of things in pack */
+extern int total; /* Total dynamic memory bytes */
+extern int lastscore; /* Score before this turn */
+extern int no_food; /* Number of levels without food */
+extern int foods_this_level; /* num of foods this level */
+extern int seed; /* Random number seed */
+extern int count; /* Number of times to repeat command */
+extern int dnum; /* Dungeon number */
+extern int max_level; /* Deepest player has gone */
+extern int cur_max; /* Deepest player has gone currently */
+extern int food_left; /* Amount of food in hero's stomach */
+extern int group; /* Current group number */
+extern int hungry_state; /* How hungry is he */
+extern int infest_dam; /* Damage from parasites */
+extern int lost_str; /* Amount of strength lost */
+extern int hold_count; /* Number of monsters holding player */
+extern int trap_tries; /* Number of attempts to set traps */
+extern int chant_time; /* Number of chant points/exp level */
+extern int pray_time; /* Number of prayer points/exp level */
+extern int spell_power; /* Spell power left at this level */
+extern int turns; /* Number of turns player has taken */
+extern int quest_item; /* Item hero is looking for */
+extern int cur_relic[]; /* Current relics */
+extern char take; /* Thing the rogue is taking */
+extern char prbuf[]; /* Buffer for sprintfs */
+extern char outbuf[]; /* Output buffer for stdout */
+extern char runch; /* Direction player is running */
+extern char *s_names[]; /* Names of the scrolls */
+extern char *p_colors[]; /* Colors of the potions */
+extern char *r_stones[]; /* Stone settings of the rings */
+extern struct init_weps weaps[]; /* weapons and attributes */
+extern struct init_armor armors[]; /* armors and attributes */
+extern char *ws_made[]; /* What sticks are made of */
+extern char *release; /* Release number of rogue */
+extern char whoami[]; /* Name of player */
+extern char fruit[]; /* Favorite fruit */
+extern char huh[]; /* The last message printed */
+extern char *s_guess[]; /* Players guess at what scroll is */
+extern char *p_guess[]; /* Players guess at what potion is */
+extern char *r_guess[]; /* Players guess at what ring is */
+extern char *ws_guess[]; /* Players guess at what wand is */
+extern char *m_guess[]; /* Players guess at what MM is */
+extern char *ws_type[]; /* Is it a wand or a staff */
+extern char file_name[]; /* Save file name */
+extern char score_file[]; /* Score file name */
+extern char home[]; /* User's home directory */
+extern WINDOW *cw; /* Window that the player sees */
+extern WINDOW *hw; /* Used for the help command */
+extern WINDOW *mw; /* Used to store mosnters */
+extern WINDOW *msgw; /* Message window */
+extern bool pool_teleport; /* just teleported from a pool */
+extern bool inwhgt; /* true if from wghtchk() */
+extern bool running; /* True if player is running */
+extern bool playing; /* True until he quits */
+extern bool wizard; /* True if allows wizard commands */
+extern bool after; /* True if we want after daemons */
+extern bool notify; /* True if player wants to know */
+extern bool fight_flush; /* True if toilet input */
+extern bool terse; /* True if we should be short */
+extern bool auto_pickup; /* pick up things automatically? */
+extern bool menu_overlay; /* use overlay type menu */
+extern bool door_stop; /* Stop running when we pass a door */
+extern bool jump; /* Show running as series of jumps */
+extern bool slow_invent; /* Inventory one line at a time */
+extern bool firstmove; /* First move after setting door_stop */
+extern bool waswizard; /* Was a wizard sometime */
+extern bool askme; /* Ask about unidentified things */
+extern bool s_know[]; /* Does he know what a scroll does */
+extern bool p_know[]; /* Does he know what a potion does */
+extern bool r_know[]; /* Does he know what a ring does */
+extern bool ws_know[]; /* Does he know what a stick does */
+extern bool m_know[]; /* Does he know what a MM does */
+extern bool in_shell; /* True if executing a shell */
+extern bool daytime; /* Indicates whether it is daytime */
+extern coord oldpos; /* Position before last look() call */
+extern coord grid[]; /* used for random pos generation */
+extern char *nothing; /* "nothing happens" msg */
+extern char *spacemsg;
+extern char *morestr;
+extern char *retstr;
+extern LEVTYPE levtype;
+extern void (*add_abil[NUMABILITIES])(); /* Functions to change abilities */
+extern void (*res_abil[NUMABILITIES])(); /* Functions to change abilities */
+extern int cNCOLORS, cNWOOD, cNMETAL, cNSTONES;
+extern char *rainbow[], *stones[], *wood[], *metal[];
+extern int land(), wghtchk(), undance(), cloak_charge(struct object *);
+extern struct delayed_action d_list[MAXDAEMONS];
+extern struct delayed_action f_list[MAXFUSES];
+extern int demoncnt, fusecnt, between, chance;
+#define CCHAR(x) ( (char) (x & A_CHARTEXT) )
+extern char *md_gethostname(), *md_getusername(), *md_gethomedir(), *md_getroguedir(), *md_crypt();
diff -r d10fc4a065ac -r adfa37e67084 arogue7/rooms.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/rooms.c Fri May 08 15:24:40 2015 -0400
@@ -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; jy, 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('|');
+ }
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/save.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/save.c Fri May 08 15:24:40 2015 -0400
@@ -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
+#include
+#include
+#include
+#include "rogue.h"
+#include
+#include
+#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;
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/scrolls.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/scrolls.c Fri May 08 15:24:40 2015 -0400
@@ -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
+#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; io_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 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);
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/state.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/state.c Fri May 08 15:24:40 2015 -0400
@@ -0,0 +1,2674 @@
+/*
+ state.c - Portable Rogue Save State Code
+
+ Copyright (C) 1999, 2000, 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.
+*/
+
+/************************************************************************/
+/* Save State Code */
+/************************************************************************/
+
+#define RSID_STATS 0xABCD0001
+#define RSID_MSTATS 0xABCD0002
+#define RSID_THING 0xABCD0003
+#define RSID_OBJECT 0xABCD0004
+#define RSID_MAGICITEMS 0xABCD0005
+#define RSID_KNOWS 0xABCD0006
+#define RSID_GUESSES 0xABCD0007
+#define RSID_OBJECTLIST 0xABCD0008
+#define RSID_BAGOBJECT 0xABCD0009
+#define RSID_MONSTERLIST 0xABCD000A
+#define RSID_MONSTERSTATS 0xABCD000B
+#define RSID_MONSTERS 0xABCD000C
+#define RSID_TRAP 0xABCD000D
+#define RSID_WINDOW 0xABCD000E
+#define RSID_DAEMONS 0xABCD000F
+#define RSID_STICKS 0xABCD0010
+#define RSID_IARMOR 0xABCD0011
+#define RSID_SPELLS 0xABCD0012
+#define RSID_ILIST 0xABCD0013
+#define RSID_HLIST 0xABCD0014
+#define RSID_DEATHTYPE 0xABCD0015
+#define RSID_CTYPES 0XABCD0016
+#define RSID_COORDLIST 0XABCD0017
+#define RSID_ROOMS 0XABCD0018
+
+#include
+#include
+#include
+#include "rogue.h"
+
+#define READSTAT (format_error || read_error )
+#define WRITESTAT (write_error)
+
+static int read_error = FALSE;
+static int write_error = FALSE;
+static int format_error = FALSE;
+static int endian = 0x01020304;
+#define big_endian ( *((char *)&endian) == 0x01 )
+
+int
+rs_write(FILE *savef, void *ptr, size_t size)
+{
+ if (write_error)
+ return(WRITESTAT);
+
+ if (encwrite(ptr, size, fileno(savef)) != size)
+ write_error = 1;
+
+ return(WRITESTAT);
+}
+
+int
+rs_read(int inf, void *ptr, size_t size)
+{
+ if (read_error || format_error)
+ return(READSTAT);
+
+ if (encread(ptr, size, inf) != size)
+ read_error = 1;
+
+ return(READSTAT);
+}
+
+int
+rs_write_uchar(FILE *savef, unsigned char c)
+{
+ if (write_error)
+ return(WRITESTAT);
+
+ rs_write(savef, &c, 1);
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_uchar(int inf, unsigned char *c)
+{
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read(inf, c, 1);
+
+ return(READSTAT);
+}
+
+int
+rs_write_char(FILE *savef, char c)
+{
+ if (write_error)
+ return(WRITESTAT);
+
+ rs_write(savef, &c, 1);
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_char(int inf, char *c)
+{
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read(inf, c, 1);
+
+ return(READSTAT);
+}
+
+int
+rs_write_chars(FILE *savef, char *c, int count)
+{
+ if (write_error)
+ return(WRITESTAT);
+
+ rs_write_int(savef, count);
+ rs_write(savef, c, count);
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_chars(int inf, char *i, int count)
+{
+ int value = 0;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read_int(inf, &value);
+
+ if (value != count)
+ format_error = TRUE;
+
+ rs_read(inf, i, count);
+
+ return(READSTAT);
+}
+
+int
+rs_write_int(FILE *savef, int c)
+{
+ unsigned char bytes[4];
+ unsigned char *buf = (unsigned char *) &c;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ if (big_endian)
+ {
+ bytes[3] = buf[0];
+ bytes[2] = buf[1];
+ bytes[1] = buf[2];
+ bytes[0] = buf[3];
+ buf = bytes;
+ }
+
+ rs_write(savef, buf, 4);
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_int(int inf, int *i)
+{
+ unsigned char bytes[4];
+ int input = 0;
+ unsigned char *buf = (unsigned char *)&input;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read(inf, &input, 4);
+
+ if (big_endian)
+ {
+ bytes[3] = buf[0];
+ bytes[2] = buf[1];
+ bytes[1] = buf[2];
+ bytes[0] = buf[3];
+ buf = bytes;
+ }
+
+ *i = *((int *) buf);
+
+ return(READSTAT);
+}
+
+int
+rs_write_ints(FILE *savef, int *c, int count)
+{
+ int n = 0;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ rs_write_int(savef, count);
+
+ for(n = 0; n < count; n++)
+ if( rs_write_int(savef,c[n]) != 0)
+ break;
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_ints(int inf, int *i, int count)
+{
+ int n, value;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read_int(inf,&value);
+
+ if (value != count)
+ format_error = TRUE;
+
+ for(n = 0; n < count; n++)
+ if (rs_read_int(inf, &i[n]) != 0)
+ break;
+
+ return(READSTAT);
+}
+
+int
+rs_write_boolean(FILE *savef, bool c)
+{
+ unsigned char buf = (c == 0) ? 0 : 1;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ rs_write(savef, &buf, 1);
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_boolean(int inf, bool *i)
+{
+ unsigned char buf = 0;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read(inf, &buf, 1);
+
+ *i = (buf != 0);
+
+ return(READSTAT);
+}
+
+int
+rs_write_booleans(FILE *savef, bool *c, int count)
+{
+ int n = 0;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ rs_write_int(savef, count);
+
+ for(n = 0; n < count; n++)
+ if (rs_write_boolean(savef, c[n]) != 0)
+ break;
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_booleans(int inf, bool *i, int count)
+{
+ int n = 0, value = 0;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read_int(inf,&value);
+
+ if (value != count)
+ format_error = TRUE;
+
+ for(n = 0; n < count; n++)
+ if (rs_read_boolean(inf, &i[n]) != 0)
+ break;
+
+ return(READSTAT);
+}
+
+int
+rs_write_short(FILE *savef, short c)
+{
+ unsigned char bytes[2];
+ unsigned char *buf = (unsigned char *) &c;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ if (big_endian)
+ {
+ bytes[1] = buf[0];
+ bytes[0] = buf[1];
+ buf = bytes;
+ }
+
+ rs_write(savef, buf, 2);
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_short(int inf, short *i)
+{
+ unsigned char bytes[2];
+ short input;
+ unsigned char *buf = (unsigned char *)&input;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read(inf, &input, 2);
+
+ if (big_endian)
+ {
+ bytes[1] = buf[0];
+ bytes[0] = buf[1];
+ buf = bytes;
+ }
+
+ *i = *((short *) buf);
+
+ return(READSTAT);
+}
+
+int
+rs_write_shorts(FILE *savef, short *c, int count)
+{
+ int n = 0;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ rs_write_int(savef, count);
+
+ for(n = 0; n < count; n++)
+ if (rs_write_short(savef, c[n]) != 0)
+ break;
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_shorts(int inf, short *i, int count)
+{
+ int n = 0, value = 0;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read_int(inf,&value);
+
+ if (value != count)
+ format_error = TRUE;
+
+ for(n = 0; n < value; n++)
+ if (rs_read_short(inf, &i[n]) != 0)
+ break;
+
+ return(READSTAT);
+}
+
+int
+rs_write_ushort(FILE *savef, unsigned short c)
+{
+ unsigned char bytes[2];
+ unsigned char *buf = (unsigned char *) &c;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ if (big_endian)
+ {
+ bytes[1] = buf[0];
+ bytes[0] = buf[1];
+ buf = bytes;
+ }
+
+ rs_write(savef, buf, 2);
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_ushort(int inf, unsigned short *i)
+{
+ unsigned char bytes[2];
+ unsigned short input;
+ unsigned char *buf = (unsigned char *)&input;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read(inf, &input, 2);
+
+ if (big_endian)
+ {
+ bytes[1] = buf[0];
+ bytes[0] = buf[1];
+ buf = bytes;
+ }
+
+ *i = *((unsigned short *) buf);
+
+ return(READSTAT);
+}
+
+int
+rs_write_uint(FILE *savef, unsigned int c)
+{
+ unsigned char bytes[4];
+ unsigned char *buf = (unsigned char *) &c;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ if (big_endian)
+ {
+ bytes[3] = buf[0];
+ bytes[2] = buf[1];
+ bytes[1] = buf[2];
+ bytes[0] = buf[3];
+ buf = bytes;
+ }
+
+ rs_write(savef, buf, 4);
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_uint(int inf, unsigned int *i)
+{
+ unsigned char bytes[4];
+ int input;
+ unsigned char *buf = (unsigned char *)&input;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read(inf, &input, 4);
+
+ if (big_endian)
+ {
+ bytes[3] = buf[0];
+ bytes[2] = buf[1];
+ bytes[1] = buf[2];
+ bytes[0] = buf[3];
+ buf = bytes;
+ }
+
+ *i = *((unsigned int *) buf);
+
+ return(READSTAT);
+}
+
+int
+rs_write_long(FILE *savef, long c)
+{
+ int c2;
+ unsigned char bytes[4];
+ unsigned char *buf = (unsigned char *)&c;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ if (sizeof(long) == 8)
+ {
+ c2 = c;
+ buf = (unsigned char *) &c2;
+ }
+
+ if (big_endian)
+ {
+ bytes[3] = buf[0];
+ bytes[2] = buf[1];
+ bytes[1] = buf[2];
+ bytes[0] = buf[3];
+ buf = bytes;
+ }
+
+ rs_write(savef, buf, 4);
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_long(int inf, long *i)
+{
+ unsigned char bytes[4];
+ long input;
+ unsigned char *buf = (unsigned char *) &input;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read(inf, &input, 4);
+
+ if (big_endian)
+ {
+ bytes[3] = buf[0];
+ bytes[2] = buf[1];
+ bytes[1] = buf[2];
+ bytes[0] = buf[3];
+ buf = bytes;
+ }
+
+ *i = *((long *) buf);
+
+ return(READSTAT);
+}
+
+int
+rs_write_longs(FILE *savef, long *c, int count)
+{
+ int n = 0;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ rs_write_int(savef,count);
+
+ for(n = 0; n < count; n++)
+ rs_write_long(savef, c[n]);
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_longs(int inf, long *i, int count)
+{
+ int n = 0, value = 0;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read_int(inf,&value);
+
+ if (value != count)
+ format_error = TRUE;
+
+ for(n = 0; n < value; n++)
+ if (rs_read_long(inf, &i[n]) != 0)
+ break;
+
+ return(READSTAT);
+}
+
+int
+rs_write_ulong(FILE *savef, unsigned long c)
+{
+ unsigned int c2;
+ unsigned char bytes[4];
+ unsigned char *buf = (unsigned char *)&c;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ if ( (sizeof(long) == 8) && (sizeof(int) == 4) )
+ {
+ c2 = c;
+ buf = (unsigned char *) &c2;
+ }
+
+ if (big_endian)
+ {
+ bytes[3] = buf[0];
+ bytes[2] = buf[1];
+ bytes[1] = buf[2];
+ bytes[0] = buf[3];
+ buf = bytes;
+ }
+
+ rs_write(savef, buf, 4);
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_ulong(int inf, unsigned long *i)
+{
+ unsigned char bytes[4];
+ unsigned long input;
+ unsigned char *buf = (unsigned char *) &input;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read(inf, &input, 4);
+
+ if (big_endian)
+ {
+ bytes[3] = buf[0];
+ bytes[2] = buf[1];
+ bytes[1] = buf[2];
+ bytes[0] = buf[3];
+ buf = bytes;
+ }
+
+ *i = *((unsigned long *) buf);
+
+ return(READSTAT);
+}
+
+int
+rs_write_ulongs(FILE *savef, unsigned long *c, int count)
+{
+ int n = 0;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ rs_write_int(savef,count);
+
+ for(n = 0; n < count; n++)
+ if (rs_write_ulong(savef,c[n]) != 0)
+ break;
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_ulongs(int inf, unsigned long *i, int count)
+{
+ int n = 0, value = 0;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read_int(inf,&value);
+
+ if (value != count)
+ format_error = TRUE;
+
+ for(n = 0; n < count; n++)
+ if (rs_read_ulong(inf, &i[n]) != 0)
+ break;
+
+ return(READSTAT);
+}
+
+int
+rs_write_marker(FILE *savef, int id)
+{
+ if (write_error)
+ return(WRITESTAT);
+
+ rs_write_int(savef, id);
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_marker(int inf, int id)
+{
+ int nid;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ if (rs_read_int(inf, &nid) == 0)
+ if (id != nid)
+ format_error = 1;
+
+ return(READSTAT);
+}
+
+
+
+/******************************************************************************/
+
+int
+rs_write_string(FILE *savef, char *s)
+{
+ int len = 0;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ len = (s == NULL) ? 0 : (int) strlen(s) + 1;
+
+ rs_write_int(savef, len);
+ rs_write_chars(savef, s, len);
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_string(int inf, char *s, int max)
+{
+ int len = 0;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read_int(inf, &len);
+
+ if (len > max)
+ format_error = TRUE;
+
+ rs_read_chars(inf, s, len);
+
+ return(READSTAT);
+}
+
+int
+rs_read_new_string(int inf, char **s)
+{
+ int len=0;
+ char *buf=0;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read_int(inf, &len);
+
+ if (len == 0)
+ buf = NULL;
+ else
+ {
+ buf = malloc(len);
+
+ if (buf == NULL)
+ read_error = TRUE;
+ }
+
+ rs_read_chars(inf, buf, len);
+
+ *s = buf;
+
+ return(READSTAT);
+}
+
+int
+rs_write_strings(FILE *savef, char *s[], int count)
+{
+ int n = 0;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ rs_write_int(savef, count);
+
+ for(n = 0; n < count; n++)
+ if (rs_write_string(savef, s[n]) != 0)
+ break;
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_strings(int inf, char **s, int count, int max)
+{
+ int n = 0;
+ int value = 0;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read_int(inf, &value);
+
+ if (value != count)
+ format_error = TRUE;
+
+ for(n = 0; n < count; n++)
+ if (rs_read_string(inf, s[n], max) != 0)
+ break;
+
+ return(READSTAT);
+}
+
+int
+rs_read_new_strings(int inf, char **s, int count)
+{
+ int n = 0;
+ int value = 0;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read_int(inf, &value);
+
+ if (value != count)
+ format_error = TRUE;
+
+ for(n = 0; n < count; n++)
+ if (rs_read_new_string(inf, &s[n]) != 0)
+ break;
+
+ return(READSTAT);
+}
+
+int
+rs_write_string_index(FILE *savef, char *master[], int max, const char *str)
+{
+ int i;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ for(i = 0; i < max; i++)
+ if (str == master[i])
+ return( rs_write_int(savef, i) );
+
+ return( rs_write_int(savef,-1) );
+}
+
+int
+rs_read_string_index(int inf, char *master[], int maxindex, char **str)
+{
+ int i;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read_int(inf, &i);
+
+ if (i > maxindex)
+ format_error = TRUE;
+ else if (i >= 0)
+ *str = master[i];
+ else
+ *str = NULL;
+
+ return(READSTAT);
+}
+
+int
+rs_write_coord(FILE *savef, coord c)
+{
+ if (write_error)
+ return(WRITESTAT);
+
+ rs_write_int(savef, c.x);
+ rs_write_int(savef, c.y);
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_coord(int inf, coord *c)
+{
+ coord in;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read_int(inf,&in.x);
+ rs_read_int(inf,&in.y);
+
+ if (READSTAT == 0)
+ {
+ c->x = in.x;
+ c->y = in.y;
+ }
+
+ return(READSTAT);
+}
+
+int
+rs_write_coord_list(FILE *savef, struct linked_list *l)
+{
+ rs_write_marker(savef, RSID_COORDLIST);
+ rs_write_int(savef, list_size(l));
+
+ while (l != NULL)
+ {
+ rs_write_coord(savef, *(coord *) l->l_data);
+ l = l->l_next;
+ }
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_coord_list(int inf, struct linked_list **list)
+{
+ int i, cnt;
+ struct linked_list *l = NULL, *previous = NULL, *head = NULL;
+
+ rs_read_marker(inf, RSID_COORDLIST);
+
+ if (rs_read_int(inf,&cnt) != 0)
+ return(READSTAT);
+
+ for (i = 0; i < cnt; i++)
+ {
+ l = new_item(sizeof(coord));
+ l->l_prev = previous;
+
+ if (previous != NULL)
+ previous->l_next = l;
+
+ rs_read_coord(inf,(coord *) l->l_data);
+
+ if (previous == NULL)
+ head = l;
+
+ previous = l;
+ }
+
+ if (l != NULL)
+ l->l_next = NULL;
+
+ *list = head;
+
+ return(READSTAT);
+}
+
+int
+rs_write_window(FILE *savef, WINDOW *win)
+{
+ int row,col,height,width;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ width = getmaxx(win);
+ height = getmaxy(win);
+
+ rs_write_marker(savef,RSID_WINDOW);
+ rs_write_int(savef,height);
+ rs_write_int(savef,width);
+
+ for(row=0;rowl_next)
+ if (count == i)
+ return(l->l_data);
+
+ return(NULL);
+}
+
+int
+find_list_ptr(struct linked_list *l, void *ptr)
+{
+ int count;
+
+ for(count = 0; l != NULL; count++, l = l->l_next)
+ if (l->l_data == ptr)
+ return(count);
+
+ return(-1);
+}
+
+int
+list_size(struct linked_list *l)
+{
+ int count;
+
+ for(count = 0; l != NULL; count++, l = l->l_next)
+ ;
+
+ return(count);
+}
+
+/******************************************************************************/
+
+int
+rs_write_levtype(FILE *savef, LEVTYPE c)
+{
+ int lt;
+
+ switch(c)
+ {
+ case NORMLEV: lt = 1; break;
+ case POSTLEV: lt = 2; break;
+ case MAZELEV: lt = 3; break;
+ case OUTSIDE: lt = 4; break;
+ case STARTLEV: lt = 5; break;
+ default: lt = -1; break;
+ }
+
+ rs_write_int(savef,lt);
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_levtype(int inf, LEVTYPE *l)
+{
+ int lt;
+
+ rs_read_int(inf, <);
+
+ switch(lt)
+ {
+ case 1: *l = NORMLEV; break;
+ case 2: *l = POSTLEV; break;
+ case 3: *l = MAZELEV; break;
+ case 4: *l = OUTSIDE; break;
+ case 5: *l = STARTLEV; break;
+ default: *l = NORMLEV; break;
+ }
+
+ return(READSTAT);
+}
+
+int
+rs_write_stats(FILE *savef, struct stats *s)
+{
+ if (write_error)
+ return(WRITESTAT);
+
+ rs_write_marker(savef, RSID_STATS);
+ rs_write_short(savef, s->s_str);
+ rs_write_short(savef, s->s_intel);
+ rs_write_short(savef, s->s_wisdom);
+ rs_write_short(savef, s->s_dext);
+ rs_write_short(savef, s->s_const);
+ rs_write_short(savef, s->s_charisma);
+ rs_write_ulong(savef, s->s_exp);
+ rs_write_int(savef, s->s_lvladj);
+ rs_write_int(savef, s->s_lvl);
+ rs_write_int(savef, s->s_arm);
+ rs_write_int(savef, s->s_hpt);
+ rs_write_int(savef, s->s_pack);
+ rs_write_int(savef, s->s_carry);
+ rs_write(savef, s->s_dmg, sizeof(s->s_dmg));
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_stats(int inf, struct stats *s)
+{
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read_marker(inf, RSID_STATS);
+ rs_read_short(inf,&s->s_str);
+ rs_read_short(inf,&s->s_intel);
+ rs_read_short(inf,&s->s_wisdom);
+ rs_read_short(inf,&s->s_dext);
+ rs_read_short(inf,&s->s_const);
+ rs_read_short(inf,&s->s_charisma);
+ rs_read_ulong(inf,&s->s_exp);
+ rs_read_int(inf,&s->s_lvladj);
+ rs_read_int(inf,&s->s_lvl);
+ rs_read_int(inf,&s->s_arm);
+ rs_read_int(inf,&s->s_hpt);
+ rs_read_int(inf,&s->s_pack);
+ rs_read_int(inf,&s->s_carry);
+ rs_read(inf,s->s_dmg,sizeof(s->s_dmg));
+
+ return(READSTAT);
+}
+
+int
+rs_write_magic_items(FILE *savef, struct magic_item *i, int count)
+{
+ int n;
+
+ rs_write_marker(savef, RSID_MAGICITEMS);
+ rs_write_int(savef, count);
+
+ for(n=0;n count)
+ format_error = TRUE;
+
+ for(i=0; i < count; i++)
+ {
+ func = 0;
+ rs_read_int(inf, &d_list[i].d_type);
+ rs_read_int(inf, &func);
+
+ switch(func)
+ {
+ case 1: d_list[i].d_func = rollwand;
+ break;
+ case 2: d_list[i].d_func = doctor;
+ break;
+ case 3: d_list[i].d_func = stomach;
+ break;
+ case 4: d_list[i].d_func = trap_look;
+ break;
+ case 5: d_list[i].d_func = eat_gold;
+ break;
+ case 6: d_list[i].d_func = ring_search;
+ break;
+ case 7: d_list[i].d_func = ring_teleport;
+ break;
+ case 8: d_list[i].d_func = fumble;
+ break;
+ case 9: d_list[i].d_func = strangle;
+ break;
+ case 10: d_list[i].d_func = unconfuse;
+ break;
+ case 11: d_list[i].d_func = swander;
+ break;
+ case 12: d_list[i].d_func = spell_recovery;
+ break;
+ case 13: d_list[i].d_func = chant_recovery;
+ break;
+ case 14: d_list[i].d_func = prayer_recovery;
+ break;
+ case 15: d_list[i].d_func = cure_disease;
+ break;
+ case 16: d_list[i].d_func = unstink;
+ break;
+ case 17: d_list[i].d_func = (int (*)()) res_strength;
+ break;
+ case 18: d_list[i].d_func = undance;
+ break;
+ case 19: d_list[i].d_func = suffocate;
+ break;
+ case 20: d_list[i].d_func = wghtchk;
+ break;
+ case 21: d_list[i].d_func = dust_appear;
+ break;
+ case 22: d_list[i].d_func = unchoke;
+ break;
+ case 23: d_list[i].d_func = sight;
+ break;
+ case 24: d_list[i].d_func = changeclass;
+ break;
+ case 25: d_list[i].d_func = cloak_charge;
+ break;
+ case 26: d_list[i].d_func = quill_charge;
+ break;
+ case 27: d_list[i].d_func = nohaste;
+ break;
+ case 28: d_list[i].d_func = noslow;
+ break;
+ case 29: d_list[i].d_func = unclrhead;
+ break;
+ case 30: d_list[i].d_func = unsee;
+ break;
+ case 31: d_list[i].d_func = unphase;
+ break;
+ case 32: d_list[i].d_func = land;
+ break;
+ case 33: d_list[i].d_func = appear;
+ break;
+ case 34: d_list[i].d_func = unskill;
+ break;
+ case 35: d_list[i].d_func = nofire;
+ break;
+ case 36: d_list[i].d_func = nocold;
+ break;
+ case 37: d_list[i].d_func = nobolt;
+ break;
+ case 0:
+ case -1:
+ default: d_list[i].d_func = NULL;
+ break;
+ }
+
+ if (d_list[i].d_func == doctor)
+ {
+ rs_read_int(inf, &dummy);
+ d_list[i].d_.varg = &player;
+ }
+ else if (d_list[i].d_func == eat_gold)
+ {
+ rs_read_int(inf, &dummy);
+ d_list[i].d_.varg = get_list_item(player.t_pack, dummy);
+ if (d_list[i].d_.varg == NULL)
+ d_list[i].d_type = 0;
+ }
+ else if (d_list[i].d_func == changeclass)
+ {
+ rs_read_int(inf, &d_list[i].d_.arg);
+ }
+ else if (d_list[i].d_func == cloak_charge)
+ {
+ rs_read_int(inf, &dummy);
+ d_list[i].d_.varg = get_list_item(player.t_pack,dummy);
+
+ if (d_list[i].d_.varg == NULL)
+ d_list[i].d_type = 0;
+ }
+ else
+ rs_read_int(inf, &d_list[i].d_.arg);
+
+ rs_read_int(inf, &d_list[i].d_time);
+
+ if (d_list[i].d_func == NULL)
+ {
+ d_list[i].d_time = 0;
+ d_list[i].d_.varg = NULL;
+ d_list[i].d_type = 0;
+ }
+
+ }
+
+ return(READSTAT);
+}
+
+int
+rs_write_room(FILE *savef, struct room *r)
+{
+ struct linked_list *l;
+ int i;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ rs_write_coord(savef, r->r_pos);
+ rs_write_coord(savef, r->r_max);
+ rs_write_long(savef, r->r_flags);
+
+ l = r->r_fires;
+ i = list_size(l);
+
+ rs_write_int(savef, i);
+
+ if (i >0)
+ while (l != NULL)
+ {
+ i = find_list_ptr(mlist, l->l_data);
+ rs_write_int(savef,i);
+ l = l->l_next;
+ }
+
+ rs_write_coord_list(savef, r->r_exit);
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_room(int inf, struct room *r)
+{
+ int value = 0, n = 0, i = 0, index = 0, id = 0;
+ struct linked_list *fires=NULL, *item = NULL;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read_coord(inf,&r->r_pos);
+ rs_read_coord(inf,&r->r_max);
+ rs_read_long(inf,&r->r_flags);
+
+ rs_read_int(inf, &i);
+ fires = NULL;
+
+ while (i>0)
+ {
+ rs_read_int(inf,&index);
+
+ if (index >= 0)
+ {
+ void *data;
+ data = get_list_item(mlist,index);
+ item = creat_item();
+ item->l_data = data;
+ if (fires == NULL)
+ fires = item;
+ else
+ attach(fires,item);
+ }
+ i--;
+ }
+
+ r->r_fires=fires;
+
+ rs_read_coord_list(inf, &r->r_exit);
+
+ return(READSTAT);
+}
+
+int
+rs_write_rooms(FILE *savef, struct room r[], int count)
+{
+ int n = 0;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ rs_write_int(savef, count);
+
+ for(n = 0; n < count; n++)
+ rs_write_room(savef, &r[n]);
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_rooms(int inf, struct room *r, int count)
+{
+ int value = 0, n = 0;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read_int(inf,&value);
+
+ if (value > count)
+ format_error = TRUE;
+
+ for(n = 0; n < value; n++)
+ rs_read_room(inf,&r[n]);
+
+ return(READSTAT);
+}
+
+int
+rs_write_room_reference(FILE *savef, struct room *rp)
+{
+ int i, room = -1;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ for (i = 0; i < MAXROOMS; i++)
+ if (&rooms[i] == rp)
+ room = i;
+
+ rs_write_int(savef, room);
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_room_reference(int inf, struct room **rp)
+{
+ int i;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read_int(inf, &i);
+
+ *rp = &rooms[i];
+
+ return(READSTAT);
+}
+
+int
+rs_write_door_reference(FILE *savef, coord *exit)
+{
+ int i, idx;
+
+ for (i = 0; i < MAXROOMS; i++)
+ {
+ idx = find_list_ptr(rooms[i].r_exit, exit);
+
+ if (idx != -1)
+ break;
+ }
+
+ if (i >= MAXROOMS)
+ {
+ rs_write_int(savef,-1);
+ rs_write_int(savef,-1);
+ if (exit != NULL)
+ abort();
+ }
+ else
+ {
+ rs_write_int(savef,i);
+ rs_write_int(savef,idx);
+ }
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_door_reference(int inf, coord **exit)
+{
+ int i, idx;
+
+ rs_read_int(inf, &i);
+ rs_read_int(inf, &idx);
+
+ if ( (i == -1) || (idx == -1) )
+ *exit = NULL;
+ else
+ *exit = get_list_item(rooms[i].r_exit, idx);
+
+ return(READSTAT);
+}
+
+int
+rs_write_traps(FILE *savef, struct trap *trap,int count)
+{
+ int n;
+
+ rs_write_int(savef, RSID_TRAP);
+ rs_write_int(savef, count);
+
+ for(n=0; no_type);
+ rs_write_coord(savef, o->o_pos);
+ rs_write_char(savef, o->o_launch);
+ rs_write(savef, o->o_damage, sizeof(o->o_damage));
+ rs_write(savef, o->o_hurldmg, sizeof(o->o_hurldmg));
+ rs_write_object_list(savef, o->contents);
+ rs_write_int(savef, o->o_count);
+ rs_write_int(savef, o->o_which);
+ rs_write_int(savef, o->o_hplus);
+ rs_write_int(savef, o->o_dplus);
+ rs_write_int(savef, o->o_ac);
+ rs_write_long(savef, o->o_flags);
+ rs_write_int(savef, o->o_group);
+ rs_write_int(savef, o->o_weight);
+ rs_write(savef, o->o_mark, MARKLEN);
+
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_object(int inf, struct object *o)
+{
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read_marker(inf, RSID_OBJECT);
+ rs_read_int(inf, &o->o_type);
+ rs_read_coord(inf, &o->o_pos);
+ rs_read_char(inf, &o->o_launch);
+ rs_read(inf, o->o_damage, sizeof(o->o_damage));
+ rs_read(inf, o->o_hurldmg, sizeof(o->o_hurldmg));
+ rs_read_object_list(inf,&o->contents);
+ rs_read_int(inf, &o->o_count);
+ rs_read_int(inf, &o->o_which);
+ rs_read_int(inf, &o->o_hplus);
+ rs_read_int(inf, &o->o_dplus);
+ rs_read_int(inf, &o->o_ac);
+ rs_read_long(inf,&o->o_flags);
+ rs_read_int(inf, &o->o_group);
+ rs_read_int(inf, &o->o_weight);
+ rs_read(inf, o->o_mark, MARKLEN);
+
+ return(READSTAT);
+}
+
+int
+rs_write_object_list(FILE *savef, struct linked_list *l)
+{
+ if (write_error)
+ return(WRITESTAT);
+
+ rs_write_marker(savef, RSID_OBJECTLIST);
+ rs_write_int(savef, list_size(l));
+
+ for( ;l != NULL; l = l->l_next)
+ rs_write_object(savef, OBJPTR(l));
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_object_list(int inf, struct linked_list **list)
+{
+ int i, cnt;
+ struct linked_list *l = NULL, *previous = NULL, *head = NULL;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read_marker(inf, RSID_OBJECTLIST);
+ rs_read_int(inf, &cnt);
+
+ for (i = 0; i < cnt; i++)
+ {
+ l = new_item(sizeof(struct object));
+
+ l->l_prev = previous;
+
+ if (previous != NULL)
+ previous->l_next = l;
+
+ rs_read_object(inf,OBJPTR(l));
+
+ if (previous == NULL)
+ head = l;
+
+ previous = l;
+ }
+
+ if (l != NULL)
+ l->l_next = NULL;
+
+ *list = head;
+
+ return(READSTAT);
+}
+
+int
+rs_write_object_reference(FILE *savef, struct linked_list *list, struct object *item)
+{
+ int i;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ i = find_list_ptr(list, item);
+
+ rs_write_int(savef, i);
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_object_reference(int inf, struct linked_list *list, struct object **item)
+{
+ int i;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read_int(inf, &i);
+
+ *item = get_list_item(list,i);
+
+ return(READSTAT);
+}
+
+int
+find_thing_coord(struct linked_list *monlist, coord *c)
+{
+ struct linked_list *mitem;
+ struct thing *tp;
+ int i = 0;
+
+ for(mitem = monlist; mitem != NULL; mitem = mitem->l_next)
+ {
+ tp = THINGPTR(mitem);
+
+ if (c == &tp->t_pos)
+ return(i);
+
+ i++;
+ }
+
+ return(-1);
+}
+
+int
+find_object_coord(struct linked_list *objlist, coord *c)
+{
+ struct linked_list *oitem;
+ struct object *obj;
+ int i = 0;
+
+ for(oitem = objlist; oitem != NULL; oitem = oitem->l_next)
+ {
+ obj = OBJPTR(oitem);
+
+ if (c == &obj->o_pos)
+ return(i);
+
+ i++;
+ }
+
+ return(-1);
+}
+
+int
+rs_write_thing(FILE *savef, struct thing *t)
+{
+ int i = -1;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ rs_write_marker(savef, RSID_THING);
+
+ if (t == NULL)
+ {
+ rs_write_int(savef, 0);
+ return(WRITESTAT);
+ }
+
+ rs_write_int(savef, 1);
+ rs_write_boolean(savef,t->t_wasshot);
+ rs_write_char(savef, t->t_type);
+ rs_write_char(savef, t->t_disguise);
+ rs_write_char(savef, t->t_oldch);
+ rs_write_short(savef, t->t_ctype);
+ rs_write_short(savef, t->t_index);
+ rs_write_short(savef, t->t_no_move);
+ rs_write_short(savef, t->t_quiet);
+ rs_write_short(savef, t->t_movement);
+ rs_write_short(savef, t->t_action);
+ rs_write_short(savef, t->t_artifact);
+ rs_write_short(savef, t->t_wand);
+ rs_write_short(savef, t->t_summon);
+ rs_write_short(savef, t->t_cast);
+ rs_write_short(savef, t->t_breathe);
+
+ rs_write_string(savef,t->t_name);
+ rs_write_door_reference(savef, t->t_doorgoal);
+
+ if (t->t_dest == &hero)
+ {
+ rs_write_int(savef,0);
+ rs_write_int(savef,1);
+ }
+ else if (t->t_dest != NULL)
+ {
+ i = find_thing_coord(mlist, t->t_dest);
+
+ if (i >= 0)
+ {
+ rs_write_int(savef,1);
+ rs_write_int(savef,i);
+ }
+ else
+ {
+ i = find_object_coord(lvl_obj, t->t_dest);
+
+ if (i >= 0)
+ {
+ rs_write_int(savef,2);
+ rs_write_int(savef,i);
+ }
+ else
+ {
+ rs_write_int(savef,0);
+ rs_write_int(savef,1); /* chase the hero anyway */
+ }
+ }
+ }
+ else
+ {
+ rs_write_int(savef,0);
+ rs_write_int(savef,0);
+ }
+
+ rs_write_coord(savef, t->t_pos);
+ rs_write_coord(savef, t->t_oldpos);
+ rs_write_coord(savef, t->t_newpos);
+ rs_write_ulongs(savef, t->t_flags, 16);
+ rs_write_object_list(savef, t->t_pack);
+ i = -1;
+ if (t->t_using != NULL)
+ i = find_list_ptr(t->t_pack, t->t_using->l_data);
+ rs_write_int(savef, i);
+ rs_write_int(savef, t->t_selection);
+ rs_write_stats(savef, &t->t_stats);
+ rs_write_stats(savef, &t->maxstats);
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_thing(int inf, struct thing *t)
+{
+ int listid = 0, index = -1;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read_marker(inf, RSID_THING);
+
+ rs_read_int(inf, &index);
+
+ if (index == 0)
+ return(READSTAT);
+
+ rs_read_boolean(inf, &t->t_wasshot);
+ rs_read_char(inf, &t->t_type);
+ rs_read_char(inf, &t->t_disguise);
+ rs_read_char(inf, &t->t_oldch);
+ rs_read_short(inf, &t->t_ctype);
+ rs_read_short(inf, &t->t_index);
+ rs_read_short(inf, &t->t_no_move);
+ rs_read_short(inf, &t->t_quiet);
+ rs_read_short(inf, &t->t_movement);
+ rs_read_short(inf, &t->t_action);
+ rs_read_short(inf, &t->t_artifact);
+ rs_read_short(inf, &t->t_wand);
+ rs_read_short(inf, &t->t_summon);
+ rs_read_short(inf, &t->t_cast);
+ rs_read_short(inf, &t->t_breathe);
+ rs_read_new_string(inf,&t->t_name);
+ rs_read_door_reference(inf,&t->t_doorgoal);
+
+ rs_read_int(inf,&listid);
+ rs_read_int(inf,&index);
+ t->t_reserved = -1;
+ if (listid == 0)
+ {
+ if (index == 1)
+ t->t_dest = &hero;
+ else
+ t->t_dest = NULL;
+ }
+ else if (listid == 1)
+ {
+ t->t_dest = NULL;
+ t->t_reserved = index;
+ }
+ else if (listid == 2)
+ {
+ struct object *obj;
+ obj = get_list_item(lvl_obj,index);
+ if (obj != NULL)
+ {
+ t->t_dest = &obj->o_pos;
+ }
+ }
+ else
+ t->t_dest = NULL;
+
+ rs_read_coord(inf,&t->t_pos);
+ rs_read_coord(inf,&t->t_oldpos);
+ rs_read_coord(inf,&t->t_newpos);
+ rs_read_ulongs(inf,t->t_flags,16);
+ rs_read_object_list(inf,&t->t_pack);
+ rs_read_int(inf,&index);
+ t->t_using = get_list_item(t->t_pack, index);
+ rs_read_int(inf, &t->t_selection);
+ rs_read_stats(inf,&t->t_stats);
+ rs_read_stats(inf,&t->maxstats);
+
+ return(READSTAT);
+}
+
+int
+rs_fix_thing(struct thing *t)
+{
+ struct thing *tp;
+
+ if (t->t_reserved < 0)
+ return;
+
+ tp = get_list_item(mlist,t->t_reserved);
+
+ if (tp != NULL)
+ {
+ t->t_dest = &tp->t_pos;
+ }
+}
+
+int
+rs_write_thing_list(FILE *savef, struct linked_list *l)
+{
+ int cnt = 0;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ rs_write_marker(savef, RSID_MONSTERLIST);
+
+ cnt = list_size(l);
+
+ rs_write_int(savef, cnt);
+
+ if (cnt < 1)
+ return(WRITESTAT);
+
+ while (l != NULL) {
+ rs_write_thing(savef, (struct thing *)l->l_data);
+ l = l->l_next;
+ }
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_thing_list(int inf, struct linked_list **list)
+{
+ int i, cnt;
+ struct linked_list *l = NULL, *previous = NULL, *head = NULL;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read_marker(inf, RSID_MONSTERLIST);
+
+ rs_read_int(inf, &cnt);
+
+ for (i = 0; i < cnt; i++)
+ {
+ l = new_item(sizeof(struct thing));
+
+ l->l_prev = previous;
+
+ if (previous != NULL)
+ previous->l_next = l;
+
+ rs_read_thing(inf,THINGPTR(l));
+
+ if (previous == NULL)
+ head = l;
+
+ previous = l;
+ }
+
+ if (l != NULL)
+ l->l_next = NULL;
+
+ *list = head;
+
+ return(READSTAT);
+}
+
+int
+rs_fix_thing_list(struct linked_list *list)
+{
+ struct linked_list *item;
+
+ for(item = list; item != NULL; item = item->l_next)
+ rs_fix_thing(THINGPTR(item));
+}
+
+int
+rs_write_thing_reference(FILE *savef, struct linked_list *list, struct thing *item)
+{
+ int i;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ if (item == NULL)
+ rs_write_int(savef,-1);
+ else
+ {
+ i = find_list_ptr(list, item);
+
+ rs_write_int(savef, i);
+ }
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_thing_reference(int inf, struct linked_list *list, struct thing **item)
+{
+ int i;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read_int(inf, &i);
+
+ if (i == -1)
+ *item = NULL;
+ else
+ *item = get_list_item(list,i);
+
+ return(READSTAT);
+}
+
+int
+rs_write_thing_references(FILE *savef, struct linked_list *list, struct thing *items[], int count)
+{
+ int i;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ for(i = 0; i < count; i++)
+ rs_write_thing_reference(savef,list,items[i]);
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_thing_references(int inf, struct linked_list *list, struct thing *items[], int count)
+{
+ int i;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ for(i = 0; i < count; i++)
+ rs_read_thing_reference(inf,list,&items[i]);
+
+ return(WRITESTAT);
+}
+
+int
+rs_save_file(FILE *savef)
+{
+ int i;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ rs_write_object_list(savef, lvl_obj);
+ rs_write_thing(savef, &player);
+ rs_write_thing_list(savef, mlist);
+ rs_write_thing_list(savef, tlist);
+ rs_write_thing_list(savef, monst_dead);
+
+ rs_write_traps(savef, traps, MAXTRAPS);
+ rs_write_rooms(savef, rooms, MAXROOMS);
+ rs_write_room_reference(savef,oldrp);
+
+ rs_write_object_reference(savef, player.t_pack, cur_armor);
+
+ for (i = 0; i < NUM_FINGERS; i++)
+ rs_write_object_reference(savef, player.t_pack, cur_ring[i]);
+
+ for (i = 0; i < NUM_MM; i++)
+ rs_write_object_reference(savef, player.t_pack, cur_misc[i]);
+
+ rs_write_ints(savef, cur_relic, MAXRELIC);
+
+ rs_write_object_reference(savef, player.t_pack, cur_weapon);
+
+ rs_write_int(savef,char_type);
+ rs_write_int(savef,foodlev);
+ rs_write_int(savef,ntraps);
+ rs_write_int(savef,trader);
+ rs_write_int(savef,curprice);
+ rs_write_int(savef,seed);
+ rs_write_int(savef,dnum);
+ rs_write_int(savef,max_level);
+ rs_write_int(savef,cur_max);
+ rs_write_int(savef,mpos);
+ rs_write_int(savef,level);
+ rs_write_int(savef,purse);
+ rs_write_int(savef,inpack);
+ rs_write_int(savef,total);
+ rs_write_int(savef,no_food);
+ rs_write_int(savef,foods_this_level);
+ rs_write_int(savef,count);
+ rs_write_int(savef,food_left);
+ rs_write_int(savef,group);
+ rs_write_int(savef,hungry_state);
+ rs_write_int(savef,infest_dam);
+ rs_write_int(savef,lost_str);
+ rs_write_int(savef,lastscore);
+ rs_write_int(savef,hold_count);
+ rs_write_int(savef,trap_tries);
+ rs_write_int(savef,chant_time);
+ rs_write_int(savef,pray_time);
+ rs_write_int(savef,spell_power);
+ rs_write_int(savef,turns);
+ rs_write_int(savef,quest_item);
+ rs_write_int(savef,cols);
+ rs_write_int(savef,lines);
+ rs_write_char(savef,nfloors);
+ rs_write(savef,curpurch,LINELEN);
+ rs_write_char(savef,PLAYER);
+ rs_write_char(savef,take);
+ rs_write(savef,prbuf,LINELEN*2);
+ rs_write(savef,outbuf,BUFSIZ);
+ rs_write_char(savef,runch);
+ rs_write_scrolls(savef);
+ rs_write_potions(savef);
+ rs_write_rings(savef);
+ rs_write_sticks(savef);
+ rs_write_misc(savef);
+ rs_write(savef,whoami,LINELEN);
+ rs_write(savef,huh,LINELEN);
+ rs_write(savef,file_name,LINELEN);
+ rs_write(savef,score_file,LINELEN);
+ rs_write(savef,home,LINELEN);
+ rs_write_window(savef, cw);
+ rs_write_window(savef, hw);
+ rs_write_window(savef, mw);
+ rs_write_window(savef, msgw);
+ rs_write_window(savef, stdscr);
+ rs_write_boolean(savef, pool_teleport);
+ rs_write_boolean(savef, inwhgt);
+ rs_write_boolean(savef, after);
+ rs_write_boolean(savef, waswizard);
+ rs_write_boolean(savef, playing);
+ rs_write_boolean(savef, running);
+ rs_write_boolean(savef, wizard);
+ rs_write_boolean(savef, notify);
+ rs_write_boolean(savef, fight_flush);
+ rs_write_boolean(savef, terse);
+ rs_write_boolean(savef, auto_pickup);
+ rs_write_boolean(savef, menu_overlay);
+ rs_write_boolean(savef, door_stop);
+ rs_write_boolean(savef, jump);
+ rs_write_boolean(savef, slow_invent);
+ rs_write_boolean(savef, firstmove);
+ rs_write_boolean(savef, askme);
+ rs_write_boolean(savef, in_shell);
+ rs_write_boolean(savef, daytime);
+ rs_write_levtype(savef, levtype);
+ rs_write_magic_items(savef, things, MAXTHINGS);
+ rs_write_magic_items(savef, s_magic, MAXSCROLLS);
+ rs_write_magic_items(savef, p_magic, MAXPOTIONS);
+ rs_write_magic_items(savef, r_magic, MAXRINGS);
+ rs_write_magic_items(savef, ws_magic, MAXSTICKS);
+ rs_write_magic_items(savef, m_magic, MAXMM);
+ rs_write_magic_items(savef, rel_magic, MAXRELIC);
+ rs_write_magic_items(savef, foods, MAXFOODS);
+
+ rs_write_monsters(savef, monsters, NUMMONST+1);
+
+ rs_write_daemons(savef, d_list, MAXDAEMONS);
+ rs_write_daemons(savef, f_list, MAXFUSES);
+ rs_write_int(savef, demoncnt);
+ rs_write_int(savef, fusecnt);
+
+ rs_write_int(savef, between);
+
+ rs_write_int(savef, chance);
+
+ return(WRITESTAT);
+}
+
+int
+rs_restore_file(int inf)
+{
+ int i;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read_object_list(inf, &lvl_obj);
+ rs_read_thing(inf, &player);
+ rs_read_thing_list(inf, &mlist);
+ rs_read_thing_list(inf, &tlist);
+ rs_read_thing_list(inf, &monst_dead);
+
+ rs_fix_thing(&player);
+ rs_fix_thing_list(mlist);
+ rs_fix_thing_list(tlist);
+ rs_fix_thing_list(monst_dead);
+
+ rs_read_traps(inf, traps, MAXTRAPS);
+ rs_read_rooms(inf, rooms, MAXROOMS);
+ rs_read_room_reference(inf,&oldrp);
+
+ rs_read_object_reference(inf, player.t_pack, &cur_armor);
+
+ for(i = 0; i < NUM_FINGERS; i++)
+ rs_read_object_reference(inf, player.t_pack, &cur_ring[i]);
+
+ for(i = 0; i < NUM_MM; i++)
+ rs_read_object_reference(inf, player.t_pack, &cur_misc[i]);
+
+ rs_read_ints(inf, cur_relic, MAXRELIC);
+
+ rs_read_object_reference(inf, player.t_pack, &cur_weapon);
+
+ rs_read_int(inf,&char_type);
+ rs_read_int(inf,&foodlev);
+ rs_read_int(inf,&ntraps);
+ rs_read_int(inf,&trader);
+ rs_read_int(inf,&curprice);
+ rs_read_int(inf,&seed);
+ rs_read_int(inf,&dnum);
+ rs_read_int(inf,&max_level);
+ rs_read_int(inf,&cur_max);
+ rs_read_int(inf,&mpos);
+ rs_read_int(inf,&level);
+ rs_read_int(inf,&purse);
+ rs_read_int(inf,&inpack);
+ rs_read_int(inf,&total);
+ rs_read_int(inf,&no_food);
+ rs_read_int(inf,&foods_this_level);
+ rs_read_int(inf,&count);
+ rs_read_int(inf,&food_left);
+ rs_read_int(inf,&group);
+ rs_read_int(inf,&hungry_state);
+ rs_read_int(inf,&infest_dam);
+ rs_read_int(inf,&lost_str);
+ rs_read_int(inf,&lastscore);
+ rs_read_int(inf,&hold_count);
+ rs_read_int(inf,&trap_tries);
+ rs_read_int(inf,&chant_time);
+ rs_read_int(inf,&pray_time);
+ rs_read_int(inf,&spell_power);
+ rs_read_int(inf,&turns);
+ rs_read_int(inf,&quest_item);
+ rs_read_int(inf,&cols);
+ rs_read_int(inf,&lines);
+ rs_read_char(inf,&nfloors);
+ rs_read(inf,curpurch,LINELEN);
+ rs_read_char(inf,&PLAYER);
+ rs_read_char(inf,&take);
+ rs_read(inf,prbuf,LINELEN*2);
+ rs_read(inf,outbuf,BUFSIZ);
+ rs_read_char(inf,&runch);
+ rs_read_scrolls(inf);
+ rs_read_potions(inf);
+ rs_read_rings(inf);
+ rs_read_sticks(inf);
+ rs_read_misc(inf);
+ rs_read(inf,whoami,LINELEN);
+ rs_read(inf,huh,LINELEN);
+ rs_read(inf,file_name,LINELEN);
+ rs_read(inf,score_file,LINELEN);
+ rs_read(inf,home,LINELEN);
+ rs_read_window(inf, cw);
+ rs_read_window(inf, hw);
+ rs_read_window(inf, mw);
+ rs_read_window(inf, msgw);
+ rs_read_window(inf, stdscr);
+ rs_read_boolean(inf, &pool_teleport);
+ rs_read_boolean(inf, &inwhgt);
+ rs_read_boolean(inf, &after);
+ rs_read_boolean(inf, &waswizard);
+ rs_read_boolean(inf, &playing);
+ rs_read_boolean(inf, &running);
+ rs_read_boolean(inf, &wizard);
+ rs_read_boolean(inf, ¬ify);
+ rs_read_boolean(inf, &fight_flush);
+ rs_read_boolean(inf, &terse);
+ rs_read_boolean(inf, &auto_pickup);
+ rs_read_boolean(inf, &menu_overlay);
+ rs_read_boolean(inf, &door_stop);
+ rs_read_boolean(inf, &jump);
+ rs_read_boolean(inf, &slow_invent);
+ rs_read_boolean(inf, &firstmove);
+ rs_read_boolean(inf, &askme);
+ rs_read_boolean(inf, &in_shell);
+ rs_read_boolean(inf, &daytime);
+ rs_read_levtype(inf, &levtype);
+ rs_read_magic_items(inf, things, MAXTHINGS);
+ rs_read_magic_items(inf, s_magic, MAXSCROLLS);
+ rs_read_magic_items(inf, p_magic, MAXPOTIONS);
+ rs_read_magic_items(inf, r_magic, MAXRINGS);
+ rs_read_magic_items(inf, ws_magic, MAXSTICKS);
+ rs_read_magic_items(inf, m_magic, MAXMM);
+ rs_read_magic_items(inf, rel_magic, MAXRELIC);
+ rs_read_magic_items(inf, foods, MAXFOODS);
+ rs_read_monsters(inf, monsters, NUMMONST + 1);
+
+ rs_read_daemons(inf, d_list, MAXDAEMONS);
+ rs_read_daemons(inf, f_list, MAXFUSES);
+ rs_read_int(inf, &demoncnt);
+ rs_read_int(inf, &fusecnt);
+
+ rs_read_int(inf, &between);
+
+ rs_read_int(inf, &chance);
+
+ return(READSTAT);
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/sticks.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/sticks.c Fri May 08 15:24:40 2015 -0400
@@ -0,0 +1,1247 @@
+/*
+ * sticks.c - Functions to implement the various sticks one might find
+ *
+ * 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 to implement the various sticks one might find
+ * while wandering around the dungeon.
+ */
+
+#include "curses.h"
+#include
+#include "rogue.h"
+
+
+/*
+ * zap a stick and see what happens
+ */
+do_zap(zapper, obj, direction, which, flags)
+struct thing *zapper;
+struct object *obj;
+coord *direction;
+int which;
+int flags;
+{
+ register struct linked_list *item;
+ register struct thing *tp;
+ register int y, x, bonus;
+ struct linked_list *nitem;
+ struct object *nobj;
+ bool cursed, blessed, is_player;
+ char *mname;
+
+ cursed = flags & ISCURSED;
+ blessed = flags & ISBLESSED;
+
+ if (obj && obj->o_type != RELIC) { /* all relics are chargeless */
+ if (obj->o_charges < 1) {
+ msg(nothing);
+ return;
+ }
+ obj->o_charges--;
+ }
+ if (which == WS_WONDER) {
+ switch (rnd(14)) {
+ case 0: which = WS_ELECT;
+ when 1: which = WS_FIRE;
+ when 2: which = WS_COLD;
+ when 3: which = WS_POLYMORPH;
+ when 4: which = WS_MISSILE;
+ when 5: which = WS_SLOW_M;
+ when 6: which = WS_TELMON;
+ when 7: which = WS_CANCEL;
+ when 8: which = WS_CONFMON;
+ when 9: which = WS_DISINTEGRATE;
+ when 10: which = WS_PETRIFY;
+ when 11: which = WS_PARALYZE;
+ when 12: which = WS_MDEG;
+ when 13: which = WS_FEAR;
+ }
+ if(ws_magic[which].mi_curse>0 && rnd(100)<=ws_magic[which].mi_curse){
+ cursed = TRUE;
+ blessed = FALSE;
+ }
+ }
+
+ tp = NULL;
+ switch (which) {
+ case WS_POLYMORPH:
+ case WS_SLOW_M:
+ case WS_TELMON:
+ case WS_CANCEL:
+ case WS_CONFMON:
+ case WS_DISINTEGRATE:
+ case WS_PETRIFY:
+ case WS_PARALYZE:
+ case WS_MDEG:
+ case WS_FEAR:
+ y = zapper->t_pos.y;
+ x = zapper->t_pos.x;
+
+ do {
+ y += direction->y;
+ x += direction->x;
+ }
+ while (shoot_ok(winat(y, x)) && !(y == hero.y && x == hero.x));
+
+ if (y == hero.y && x == hero.x)
+ is_player = TRUE;
+ else if (isalpha(mvwinch(mw, y, x))) {
+ item = find_mons(y, x);
+ tp = THINGPTR(item);
+ runto(tp, &hero);
+ turn_off(*tp, CANSURPRISE);
+ mname = monster_name(tp);
+ is_player = FALSE;
+
+ /* The monster may not like being shot at */
+ if ((zapper == &player) &&
+ on(*tp, ISCHARMED) &&
+ save(VS_MAGIC, tp, 0)) {
+ msg("The eyes of %s turn clear.", prname(mname, FALSE));
+ turn_off(*tp, ISCHARMED);
+ mname = monster_name(tp);
+ }
+ }
+ else {
+ /*
+ * if monster misses player because the player dodged then lessen
+ * the chances he will use the wand again since the player appears
+ * to be rather dextrous
+ */
+ if (zapper != &player)
+ zapper->t_wand = zapper->t_wand * 3 / 4;
+ }
+ }
+ switch (which) {
+ case WS_LIGHT:
+ /*
+ * Reddy Kilowat wand. Light up the room
+ */
+ blue_light(blessed, cursed);
+ when WS_DRAIN:
+ /*
+ * Take away 1/2 of hero's hit points, then take it away
+ * evenly from the monsters in the room or next to hero
+ * if he is in a passage (but leave the monsters alone
+ * if the stick is cursed)
+ */
+ if (pstats.s_hpt < 2) {
+ msg("You are too weak to use it.");
+ }
+ else if (cursed)
+ pstats.s_hpt /= 2;
+ else
+ drain(hero.y-1, hero.y+1, hero.x-1, hero.x+1);
+
+ when WS_POLYMORPH:
+ {
+ register char oldch;
+ register struct room *rp;
+ register struct linked_list *pitem;
+ coord delta;
+
+ if (tp == NULL)
+ break;
+ if (save(VS_MAGIC, tp, 0)) {
+ msg(nothing);
+ break;
+ }
+ rp = roomin(&tp->t_pos);
+ check_residue(tp);
+ delta.x = x;
+ delta.y = y;
+ detach(mlist, item);
+ oldch = tp->t_oldch;
+ pitem = tp->t_pack; /* save his pack */
+ tp->t_pack = NULL;
+ new_monster(item,rnd(NUMMONST-NUMUNIQUE-1)+1,&delta,FALSE);
+ if (tp->t_pack != NULL)
+ o_free_list (tp->t_pack);
+ tp->t_pack = pitem;
+ if (isalpha(mvwinch(cw, y, x)))
+ mvwaddch(cw, y, x, tp->t_type);
+ tp->t_oldch = oldch;
+ /*
+ * should the room light up?
+ */
+ if (on(*tp, HASFIRE)) {
+ 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 (cansee(tp->t_pos.y,tp->t_pos.x) &&
+ next(rp->r_fires) == NULL) light(&hero);
+ }
+ }
+ runto(tp, &hero);
+ msg(terse ? "A new %s!"
+ : "You have created a new %s!",
+ monster_name(tp));
+ }
+
+ when WS_PETRIFY:
+ if (tp == NULL)
+ break;
+ if (save(VS_MAGIC, tp, 0)) {
+ msg(nothing);
+ break;
+ }
+ check_residue(tp);
+ turn_on(*tp, ISSTONE);
+ turn_on(*tp, NOSTONE);
+ turn_off(*tp, ISRUN);
+ turn_off(*tp, ISINVIS);
+ turn_off(*tp, CANSURPRISE);
+ turn_off(*tp, ISDISGUISE);
+ tp->t_action = A_NIL;
+ tp->t_no_move = 0;
+ msg("%s is turned to stone!",prname(mname, TRUE));
+
+ when WS_TELMON:
+ {
+ register int rm;
+ register struct room *rp;
+
+ if (tp == NULL)
+ break;
+ if (save(VS_MAGIC, tp, 0)) {
+ msg(nothing);
+ break;
+ }
+ rp = NULL;
+ check_residue(tp);
+ tp->t_action = A_FREEZE; /* creature is disoriented */
+ tp->t_no_move = 2;
+ if (cursed) { /* Teleport monster to player */
+ if ((y == (hero.y + direction->y)) &&
+ (x == (hero.x + direction->x)))
+ msg(nothing);
+ else {
+ tp->t_pos.y = hero.y + direction->y;
+ tp->t_pos.x = hero.x + direction->x;
+ }
+ }
+ else if (blessed) { /* Get rid of monster */
+ killed(item, FALSE, TRUE, TRUE);
+ return;
+ }
+ else {
+ register int i=0;
+
+ do { /* Move monster to another room */
+ rm = rnd_room();
+ rnd_pos(&rooms[rm], &tp->t_pos);
+ }until(winat(tp->t_pos.y,tp->t_pos.x)==FLOOR ||i++>500);
+ rp = &rooms[rm];
+ }
+
+ /* Now move the monster */
+ if (isalpha(mvwinch(cw, y, x)))
+ mvwaddch(cw, y, x, tp->t_oldch);
+ mvwaddch(mw, y, x, ' ');
+ mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, tp->t_type);
+ if (tp->t_pos.y != y || tp->t_pos.x != x)
+ tp->t_oldch = CCHAR( mvwinch(cw, tp->t_pos.y, tp->t_pos.x) );
+ /*
+ * check to see if room that creature appears in should
+ * light up
+ */
+ if (on(*tp, HASFIRE)) {
+ 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(cansee(tp->t_pos.y, tp->t_pos.x) &&
+ next(rp->r_fires) == NULL)
+ light(&hero);
+ }
+ }
+ }
+ when WS_CANCEL:
+ if (tp == NULL)
+ break;
+ if (save(VS_MAGIC, tp, 0)) {
+ msg(nothing);
+ break;
+ }
+ check_residue(tp);
+ tp->t_flags[0] &= CANC0MASK;
+ tp->t_flags[1] &= CANC1MASK;
+ tp->t_flags[2] &= CANC2MASK;
+ tp->t_flags[3] &= CANC3MASK;
+ tp->t_flags[4] &= CANC4MASK;
+ tp->t_flags[5] &= CANC5MASK;
+ tp->t_flags[6] &= CANC6MASK;
+ tp->t_flags[7] &= CANC7MASK;
+ tp->t_flags[8] &= CANC8MASK;
+ tp->t_flags[9] &= CANC9MASK;
+ tp->t_flags[10] &= CANCAMASK;
+ tp->t_flags[11] &= CANCBMASK;
+ tp->t_flags[12] &= CANCCMASK;
+ tp->t_flags[13] &= CANCDMASK;
+ tp->t_flags[14] &= CANCEMASK;
+ tp->t_flags[15] &= CANCFMASK;
+
+ when WS_MISSILE:
+ {
+ int dice;
+ static struct object bolt =
+ {
+ MISSILE , {0, 0}, "", 0, "", "1d4 " , NULL, 0, WS_MISSILE, 50, 1
+ };
+
+ if (!obj)
+ dice = zapper->t_stats.s_lvl;
+ if (obj->o_type == RELIC)
+ dice = 15;
+ else if (EQUAL(ws_type[which], "staff"))
+ dice = 10;
+ else
+ dice = 6;
+ sprintf(bolt.o_hurldmg, "%dd4", dice);
+ do_motion(&bolt, direction->y, direction->x, zapper);
+ if (!hit_monster(unc(bolt.o_pos), &bolt, zapper))
+ msg("The missile vanishes with a puff of smoke");
+ }
+ when WS_HIT:
+ {
+ register char ch;
+ struct object strike; /* don't want to change sticks attributes */
+
+ direction->y += hero.y;
+ direction->x += hero.x;
+ ch = CCHAR( winat(direction->y, direction->x) );
+ if (isalpha(ch))
+ {
+ strike = *obj;
+ strike.o_hplus = 6;
+ if (EQUAL(ws_type[which], "staff"))
+ strncpy(strike.o_damage,"3d8",sizeof(strike.o_damage));
+ else
+ strncpy(strike.o_damage,"2d8",sizeof(strike.o_damage));
+ fight(direction, &strike, FALSE);
+ }
+ }
+ when WS_SLOW_M:
+ if (is_player) {
+ add_slow();
+ break;
+ }
+ if (tp == NULL)
+ break;
+ if (cursed) {
+ if (on(*tp, ISSLOW))
+ turn_off(*tp, ISSLOW);
+ else
+ turn_on(*tp, ISHASTE);
+ break;
+ }
+ if ((on(*tp,ISUNIQUE) && save(VS_MAGIC,tp,0)) || on(*tp,NOSLOW)) {
+ msg(nothing);
+ break;
+ }
+ else if (blessed) {
+ turn_off(*tp, ISRUN);
+ turn_on(*tp, ISHELD);
+ }
+ /*
+ * always slow in case he breaks free of HOLD
+ */
+ if (on(*tp, ISHASTE))
+ turn_off(*tp, ISHASTE);
+ else
+ turn_on(*tp, ISSLOW);
+
+ when WS_CHARGE:
+ if (ws_know[WS_CHARGE] != TRUE && obj)
+ msg("This is a wand of charging.");
+ nitem = get_item(pack, "charge", STICK, FALSE, FALSE);
+ if (nitem != NULL) {
+ nobj = OBJPTR(nitem);
+ if ((++(nobj->o_charges) == 1) && (nobj->o_which == WS_HIT))
+ fix_stick(nobj);
+ if (blessed) ++(nobj->o_charges);
+ if (EQUAL(ws_type[nobj->o_which], "staff")) {
+ if (nobj->o_charges > 100)
+ nobj->o_charges = 100;
+ }
+ else {
+ if (nobj->o_charges > 50)
+ nobj->o_charges = 50;
+ }
+ }
+ when WS_ELECT:
+ shoot_bolt( zapper, zapper->t_pos, *direction, TRUE, D_BOLT,
+ "lightning bolt", roll(zapper->t_stats.s_lvl,6));
+
+ when WS_FIRE:
+ shoot_bolt( zapper, zapper->t_pos, *direction, TRUE, D_BOLT,
+ "flame", roll(zapper->t_stats.s_lvl,6));
+
+ when WS_COLD:
+ shoot_bolt( zapper, zapper->t_pos, *direction, TRUE, D_BOLT,
+ "ice", roll(zapper->t_stats.s_lvl,6));
+
+ when WS_CONFMON:
+ if (cursed || is_player) {
+ if (!save(VS_WAND, &player, 0)) {
+ dsrpt_player();
+ confus_player();
+ }
+ else {
+ if (zapper != &player) zapper->t_wand /= 2;
+ msg(nothing);
+ }
+ }
+ else {
+ if (tp == NULL)
+ break;
+ if (save(VS_MAGIC, tp, 0) || on(*tp, ISCLEAR))
+ msg(nothing);
+ else
+ turn_on (*tp, ISHUH);
+ }
+ when WS_PARALYZE:
+ if (is_player || cursed) {
+ if ((obj && obj->o_type==RELIC) || !save(VS_WAND, &player, 0)){
+ player.t_no_move += 2 * movement(&player) * FREEZETIME;
+ player.t_action = A_FREEZE;
+ msg("You can't move.");
+ }
+ else {
+ if (zapper != &player) zapper->t_wand /= 2;
+ msg(nothing);
+ }
+ }
+ else {
+ if (tp == NULL)
+ break;
+ bonus = 0;
+ if (blessed) bonus = -3;
+ if (((obj && obj->o_type==RELIC) || !save(VS_WAND,tp,bonus)) &&
+ off(*tp, NOPARALYZE)) {
+ tp->t_no_move += 2 * movement(tp) * FREEZETIME;
+ tp->t_action = A_FREEZE;
+ }
+ else {
+ msg(nothing);
+ }
+ }
+ when WS_FEAR:
+ if (is_player) {
+ if (!on(player, ISFLEE) ||
+ ISWEARING(R_HEROISM) ||
+ save(VS_WAND, &player, 0)) {
+ msg(nothing);
+ zapper->t_wand /= 2;
+ }
+ else {
+ turn_on(player, ISFLEE);
+ player.t_dest = &zapper->t_pos;
+ msg("The sight of %s terrifies you.", prname(mname, FALSE));
+ }
+ break;
+ }
+ if (tp == NULL)
+ break;
+ bonus = 0;
+ if (blessed) bonus = -3;
+ if(save(VS_WAND, tp,bonus) || on(*tp,ISUNDEAD) || on(*tp,NOFEAR)){
+ msg(nothing);
+ break;
+ }
+ turn_on(*tp, ISFLEE);
+ turn_on(*tp, WASTURNED);
+
+ /* Stop it from attacking us */
+ dsrpt_monster(tp, TRUE, cansee(tp->t_pos.y, tp->t_pos.x));
+
+ /* 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;
+
+ when WS_MDEG:
+ if (is_player) {
+ if (save(VS_WAND, &player, 0)) {
+ msg (nothing);
+ zapper->t_wand /= 2;
+ break;
+ }
+ pstats.s_hpt /= 2;
+ if (pstats.s_hpt <= 0) {
+ msg("Your life has been sucked from you -- More --");
+ wait_for(' ');
+ death(zapper);
+ }
+ else
+ msg("You feel a great drain on your system");
+ }
+ if (tp == NULL)
+ break;
+ if (cursed) {
+ tp->t_stats.s_hpt *= 2;
+ msg("%s appears to be stronger now!", prname(mname, TRUE));
+ }
+ else if (on(*tp, ISUNIQUE) && save(VS_WAND, tp, 0))
+ msg (nothing);
+ else {
+ tp->t_stats.s_hpt /= 2;
+ msg("%s appears to be weaker now", prname(mname, TRUE));
+ }
+ if (tp->t_stats.s_hpt < 1)
+ killed(item, TRUE, TRUE, TRUE);
+ when WS_DISINTEGRATE:
+ if (tp == NULL)
+ break;
+ if (cursed) {
+ register int m1, m2;
+ coord mp;
+ struct linked_list *titem;
+ char ch;
+ struct thing *th;
+
+ if (on(*tp, ISUNIQUE)) {
+ msg (nothing);
+ break;
+ }
+ for (m1=tp->t_pos.x-1 ; m1 <= tp->t_pos.x+1 ; m1++) {
+ for(m2=tp->t_pos.y-1 ; m2<=tp->t_pos.y+1 ; m2++) {
+ if (m1 == hero.x && m2 == hero.y)
+ continue;
+ ch = CCHAR( winat(m2,m1) );
+ if (shoot_ok(ch)) {
+ mp.x = m1; /* create it */
+ mp.y = m2;
+ titem = new_item(sizeof(struct thing));
+ new_monster(titem,(short)tp->t_index,&mp,FALSE);
+ th = THINGPTR(titem);
+ turn_on (*th, ISMEAN);
+ runto(th,&hero);
+ if (on(*th, HASFIRE)) {
+ register struct room *rp;
+
+ rp = roomin(&th->t_pos);
+ if (rp) {
+ register struct linked_list *fire_item;
+
+ fire_item = creat_item();
+ ldata(fire_item) = (char *) th;
+ attach(rp->r_fires, fire_item);
+ rp->r_flags |= HASFIRE;
+ if (cansee(th->t_pos.y, th->t_pos.x) &&
+ next(rp->r_fires) == NULL)
+ light(&hero);
+ }
+ }
+ }
+ }
+ }
+ }
+ else { /* if its a UNIQUE it might still live */
+ if (on(*tp, ISUNIQUE) && save(VS_MAGIC, tp, 0)) {
+ tp->t_stats.s_hpt /= 2;
+ if (tp->t_stats.s_hpt < 1) {
+ killed(item, FALSE, TRUE, TRUE);
+ msg("You have disintegrated %s", prname(mname, FALSE));
+ }
+ else {
+ msg("%s appears wounded", prname(mname, TRUE));
+ }
+ }
+ else {
+ msg("You have disintegrated %s", prname(mname, FALSE));
+ killed (item, FALSE, TRUE, TRUE);
+ }
+ }
+ when WS_CURING:
+ if (cursed) {
+ if (!save(VS_POISON, &player, 0)) {
+ msg("You feel extremely sick now");
+ pstats.s_hpt /=2;
+ if (pstats.s_hpt == 0) death (D_POISON);
+ }
+ if (!save(VS_WAND, &player, 0) && !ISWEARING(R_HEALTH)) {
+ turn_on(player, HASDISEASE);
+ turn_on(player, HASINFEST);
+ turn_on(player, DOROT);
+ fuse(cure_disease, 0, roll(HEALTIME,SICKTIME), AFTER);
+ infest_dam++;
+ }
+ else msg("You fell momentarily sick");
+ }
+ else {
+ if (on(player, HASDISEASE) || on(player, HASINFEST)) {
+ extinguish(cure_disease);
+ turn_off(player, HASINFEST);
+ infest_dam = 0;
+ cure_disease(); /* this prints message */
+ }
+ if (on(player, DOROT)) {
+ msg("You feel your skin returning to normal.");
+ turn_off(player, DOROT);
+ }
+ pstats.s_hpt += roll(pstats.s_lvl, blessed ? 6 : 4);
+ if (pstats.s_hpt > max_stats.s_hpt)
+ pstats.s_hpt = max_stats.s_hpt;
+ msg("You begin to feel %sbetter.", blessed ? "much " : "");
+
+ }
+ otherwise:
+ msg("What a bizarre schtick!");
+ }
+}
+
+
+/*
+ * drain:
+ * Do drain hit points from player shtick
+ */
+
+drain(ymin, ymax, xmin, xmax)
+int ymin, ymax, xmin, xmax;
+{
+ register int i, j, count;
+ register struct thing *ick;
+ register struct linked_list *item;
+
+ /*
+ * First count how many things we need to spread the hit points among
+ */
+ count = 0;
+ for (i = ymin; i <= ymax; i++) {
+ if (i < 1 || i > lines - 3)
+ continue;
+ for (j = xmin; j <= xmax; j++) {
+ if (j < 0 || j > cols - 1)
+ continue;
+ if (isalpha(mvwinch(mw, i, j)))
+ count++;
+ }
+ }
+ if (count == 0)
+ {
+ msg("You have a tingling feeling");
+ return;
+ }
+ count = pstats.s_hpt / count;
+ pstats.s_hpt /= 2;
+ /*
+ * Now zot all of the monsters
+ */
+ for (i = ymin; i <= ymax; i++) {
+ if (i < 1 || i > lines - 3)
+ continue;
+ for (j = xmin; j <= xmax; j++) {
+ if (j < 0 || j > cols - 1)
+ continue;
+ if (isalpha(mvwinch(mw, i, j)) &&
+ ((item = find_mons(i, j)) != NULL)) {
+ ick = THINGPTR(item);
+ if (on(*ick, ISUNIQUE) && save(VS_MAGIC, ick, 0))
+ ick->t_stats.s_hpt -= count / 2;
+ else
+ ick->t_stats.s_hpt -= count;
+ if (ick->t_stats.s_hpt < 1)
+ killed(item,
+ cansee(i,j)&&(!on(*ick,ISINVIS)||on(player,CANSEE)),
+ TRUE, TRUE);
+ else {
+ runto(ick, &hero);
+
+ /*
+ * The monster may not like being shot at. Since the
+ * shot is not aimed directly at the monster, we will
+ * give him a poorer save.
+ */
+ if (on(*ick, ISCHARMED) && save(VS_MAGIC, ick, -2)) {
+ msg("The eyes of %s turn clear.",
+ prname(monster_name(ick), FALSE));
+ turn_off(*ick, ISCHARMED);
+ }
+ if (cansee(i,j) && (!on(*ick,ISINVIS)||on(player,CANSEE)))
+ msg("%s appears wounded",
+ prname(monster_name(ick), TRUE));
+ }
+ }
+ }
+ }
+}
+
+/*
+ * initialize a stick
+ */
+fix_stick(cur)
+register struct object *cur;
+{
+ if (EQUAL(ws_type[cur->o_which], "staff")) {
+ cur->o_weight = 100;
+ cur->o_charges = 5 + rnd(10);
+ strncpy(cur->o_damage, "2d3", sizeof(cur->o_damage));
+ cur->o_hplus = 1;
+ cur->o_dplus = 0;
+ switch (cur->o_which) {
+ case WS_HIT:
+ cur->o_hplus = 3;
+ cur->o_dplus = 3;
+ strncpy(cur->o_damage, "2d8", sizeof(cur->o_damage));
+ when WS_LIGHT:
+ cur->o_charges = 20 + rnd(10);
+ }
+ }
+ else {
+ strncpy(cur->o_damage, "1d3", sizeof(cur->o_damage));
+ cur->o_weight = 60;
+ cur->o_hplus = 1;
+ cur->o_dplus = 0;
+ cur->o_charges = 3 + rnd(5);
+ switch (cur->o_which) {
+ case WS_HIT:
+ cur->o_hplus = 3;
+ cur->o_dplus = 3;
+ strncpy(cur->o_damage, "1d8", sizeof(cur->o_damage));
+ when WS_LIGHT:
+ cur->o_charges = 10 + rnd(10);
+ }
+ }
+ strncpy(cur->o_hurldmg, "1d1", sizeof(cur->o_hurldmg));
+
+}
+
+/*
+ * Use the wand that our monster is wielding.
+ */
+m_use_wand(monster)
+register struct thing *monster;
+{
+ register struct object *obj;
+
+ /* Make sure we really have it */
+ if (monster->t_using)
+ obj = OBJPTR(monster->t_using);
+ else {
+ debug("Stick not set!");
+ monster->t_action = A_NIL;
+ return;
+ }
+
+ if (obj->o_type != STICK) {
+ debug("Stick not selected!");
+ monster->t_action = A_NIL;
+ return;
+ }
+ /*
+ * shoot the stick!
+ * assume all blessed sticks are normal for now.
+ * Note that we don't get here if the wand is cursed.
+ */
+ msg("%s points a %s at you!", prname(monster_name(monster), TRUE),
+ ws_type[obj->o_which]);
+ do_zap(monster, obj, &monster->t_newpos, obj->o_which, NULL);
+ monster->t_wand /= 2; /* chance lowers with each use */
+}
+
+bool
+need_dir(type, which)
+int type, /* type of item, NULL means stick */
+ which; /* which item */
+{
+ if (type == STICK || type == 0) {
+ switch (which) {
+ case WS_LIGHT:
+ case WS_DRAIN:
+ case WS_CHARGE:
+ case WS_CURING:
+ return(FALSE);
+ default:
+ return(TRUE);
+ }
+ }
+ else if (type == RELIC) {
+ switch (which) {
+ case MING_STAFF:
+ case ASMO_ROD:
+ case EMORI_CLOAK:
+ return(TRUE);
+ default:
+ return(FALSE);
+ }
+ }
+return (FALSE); /* hope we don't get here */
+}
+/*
+ * let the player zap a stick and see what happens
+ */
+player_zap(which, flag)
+int which;
+int flag;
+{
+ register struct linked_list *item;
+ register struct object *obj;
+
+ obj = NULL;
+ if (which == 0) {
+ /* This is a stick. It takes 2 movement periods to zap it */
+ if (player.t_action != C_ZAP) {
+ if ((item = get_item(pack,"zap with",ZAPPABLE,FALSE,FALSE)) == NULL)
+ return(FALSE);
+
+ obj = OBJPTR(item);
+
+ if (need_dir(obj->o_type, obj->o_which)) {
+ if (!get_dir(&player.t_newpos))
+ return(FALSE);
+ }
+ player.t_using = item; /* Remember what it is */
+ player.t_action = C_ZAP; /* We are quaffing */
+ player.t_no_move = 2 * movement(&player);
+ return(TRUE);
+ }
+
+ item = player.t_using;
+ /* We've waited our time, let's shoot 'em up! */
+ player.t_using = NULL;
+ player.t_action = A_NIL;
+
+ obj = OBJPTR(item);
+
+ /* Handle relics specially here */
+ if (obj->o_type == RELIC) {
+ switch (obj->o_which) {
+ case ORCUS_WAND:
+ msg(nothing);
+ return(TRUE);
+ when MING_STAFF:
+ which = WS_MISSILE;
+ when EMORI_CLOAK:
+ which = WS_PARALYZE;
+ obj->o_charges = 0; /* one zap/day(whatever that is) */
+ fuse(cloak_charge, obj, CLOAK_TIME, AFTER);
+ when ASMO_ROD:
+ switch (rnd(3)) {
+ case 0: which = WS_ELECT;
+ when 1: which = WS_COLD;
+ otherwise: which = WS_FIRE;
+ }
+ }
+ }
+ else {
+ which = obj->o_which;
+ ws_know[which] = TRUE;
+ flag = obj->o_flags;
+ }
+ }
+ do_zap(&player, obj, &player.t_newpos, which, flag);
+ return(TRUE);
+}
+
+
+/*
+ * shoot_bolt fires a bolt from the given starting point in the
+ * given direction
+ */
+
+shoot_bolt(shooter, start, dir, get_points, reason, name, damage)
+struct thing *shooter;
+coord start, dir;
+bool get_points;
+short reason;
+char *name;
+int damage;
+{
+ register char dirch, ch;
+ register bool used, change;
+ register short y, x, bounces;
+ coord pos;
+ struct linked_list *target=NULL;
+ struct {
+ coord place;
+ char oldch;
+ } spotpos[BOLT_LENGTH];
+
+ switch (dir.y + dir.x) {
+ case 0: dirch = '/';
+ when 1: case -1: dirch = (dir.y == 0 ? '-' : '|');
+ when 2: case -2: dirch = '\\';
+ }
+ pos.y = start.y + dir.y;
+ pos.x = start.x + dir.x;
+ used = FALSE;
+ change = FALSE;
+
+ bounces = 0; /* No bounces yet */
+ for (y = 0; y < BOLT_LENGTH && !used; y++)
+ {
+ ch = CCHAR( winat(pos.y, pos.x) );
+ spotpos[y].place = pos;
+ spotpos[y].oldch = CCHAR( mvwinch(cw, pos.y, pos.x) );
+
+ /* Are we at hero? */
+ if (ce(pos, hero)) goto at_hero;
+
+ switch (ch)
+ {
+ case SECRETDOOR:
+ case '|':
+ case '-':
+ case ' ':
+ if (dirch == '-' || dirch == '|') {
+ dir.y = -dir.y;
+ dir.x = -dir.x;
+ }
+ else {
+ char chx = CCHAR( mvinch(pos.y-dir.y, pos.x) ),
+ chy = CCHAR( mvinch(pos.y, pos.x-dir.x) );
+ bool anychange = FALSE; /* Did we change anthing */
+
+ if (chy == WALL || chy == SECRETDOOR ||
+ chy == '-' || chy == '|') {
+ dir.y = -dir.y;
+ change ^= TRUE; /* Change at least one direction */
+ anychange = TRUE;
+ }
+ if (chx == WALL || chx == SECRETDOOR ||
+ chx == '-' || chx == '|') {
+ dir.x = -dir.x;
+ change ^= TRUE; /* Change at least one direction */
+ anychange = TRUE;
+ }
+
+ /* If we didn't make any change, make both changes */
+ if (!anychange) {
+ dir.x = -dir.x;
+ dir.y = -dir.y;
+ }
+ }
+
+ /* Do we change how the bolt looks? */
+ if (change) {
+ change = FALSE;
+ if (dirch == '\\') dirch = '/';
+ else if (dirch == '/') dirch = '\\';
+ }
+
+ y--; /* The bounce doesn't count as using up the bolt */
+
+ /* Make sure we aren't in an infinite bounce */
+ if (++bounces > BOLT_LENGTH) used = TRUE;
+ msg("The %s bounces", name);
+ break;
+ default:
+ if (isalpha(ch)) {
+ register struct linked_list *item;
+ register struct thing *tp;
+ register char *mname;
+ bool see_monster = cansee(pos.y, pos.x);
+
+ item = find_mons(unc(pos));
+ tp = THINGPTR(item);
+ mname = monster_name(tp);
+
+ /*
+ * If our prey shot this, let's record the fact that
+ * he can shoot, regardless of whether he hits us.
+ */
+ if ((tp->t_dest != NULL) && ce(*tp->t_dest, shooter->t_pos)) tp->t_wasshot = TRUE;
+
+ if (!save(VS_BREATH, tp, -(shooter->t_stats.s_lvl/10))) {
+ if (see_monster) {
+ if (on(*tp, ISDISGUISE) &&
+ (tp->t_type != tp->t_disguise)) {
+ msg("Wait! That's a %s!", mname);
+ turn_off(*tp, ISDISGUISE);
+ }
+
+ turn_off(*tp, CANSURPRISE);
+ msg("The %s hits %s", name, prname(mname, FALSE));
+ }
+
+ /* Should we start to chase the shooter? */
+ if (shooter != &player &&
+ shooter != tp &&
+ shooter->t_index != tp->t_index &&
+ (tp->t_dest == NULL || rnd(100) < 25)) {
+ /*
+ * If we're intelligent enough to realize that this
+ * is a friendly monster, we will attack the hero
+ * instead.
+ */
+ if (on(*shooter, ISFRIENDLY) &&
+ roll(3,6) < tp->t_stats.s_intel)
+ runto(tp, &hero);
+
+ /* Otherwise, let's chase the monster */
+ else runto(tp, &shooter->t_pos);
+ }
+ else if (shooter == &player) {
+ runto(tp, &hero);
+
+ /*
+ * If the player shot a charmed monster, it may
+ * not like being shot at.
+ */
+ if (on(*tp, ISCHARMED) && save(VS_MAGIC, tp, 0)) {
+ msg("The eyes of %s turn clear.",
+ prname(mname, FALSE));
+ turn_off(*tp, ISCHARMED);
+ mname = monster_name(tp);
+ }
+ }
+
+ /*
+ * Let the defender know that the attacker has
+ * missiles!
+ */
+ if (ce(*tp->t_dest, shooter->t_pos))
+ tp->t_wasshot = TRUE;
+
+ used = TRUE;
+
+ /* Hit the monster -- does it do anything? */
+ if ((EQUAL(name,"ice") &&
+ (on(*tp, NOCOLD) || on(*tp, ISUNDEAD))) ||
+ (EQUAL(name,"flame") && on(*tp, NOFIRE)) ||
+ (EQUAL(name,"acid") && on(*tp, NOACID)) ||
+ (EQUAL(name,"lightning bolt")&& on(*tp,NOBOLT)) ||
+ (EQUAL(name,"nerve gas") &&on(*tp,NOPARALYZE))||
+ (EQUAL(name,"sleeping gas") &&
+ (on(*tp, NOSLEEP) || on(*tp, ISUNDEAD))) ||
+ (EQUAL(name,"slow gas") && on(*tp,NOSLOW)) ||
+ (EQUAL(name,"fear gas") && on(*tp,NOFEAR)) ||
+ (EQUAL(name,"confusion gas") && on(*tp,ISCLEAR)) ||
+ (EQUAL(name,"chlorine gas") && on(*tp,NOGAS))) {
+ if (see_monster)
+ msg("The %s has no effect on %s.",
+ name, prname(mname, FALSE));
+ }
+
+ else {
+ bool see_him;
+
+ see_him =
+ 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));
+
+ /* Did a spell get disrupted? */
+ dsrpt_monster(tp, FALSE, see_him);
+
+ /*
+ * Check for gas with special effects
+ */
+ if (EQUAL(name, "nerve gas")) {
+ tp->t_no_move = movement(tp) * FREEZETIME;
+ tp->t_action = A_FREEZE;
+ }
+ else if (EQUAL(name, "sleeping gas")) {
+ tp->t_no_move = movement(tp) * SLEEPTIME;
+ tp->t_action = A_FREEZE;
+ }
+ else if (EQUAL(name, "slow gas")) {
+ if (on(*tp, ISHASTE))
+ turn_off(*tp, ISHASTE);
+ else
+ turn_on(*tp, ISSLOW);
+ }
+ else if (EQUAL(name, "fear gas")) {
+ turn_on(*tp, ISFLEE);
+ tp->t_dest = &hero;
+
+ /* It is okay to turn tail */
+ tp->t_oldpos = tp->t_pos;
+ }
+ else if (EQUAL(name, "confusion gas")) {
+ turn_on(*tp, ISHUH);
+ tp->t_dest = &hero;
+ }
+ else if ((EQUAL(name, "lightning bolt")) &&
+ on(*tp, BOLTDIVIDE)) {
+ if (creat_mons(tp, tp->t_index, FALSE)) {
+ if (see_monster)
+ msg("The %s divides %s.",
+ name,prname(mname, FALSE));
+ light(&hero);
+ }
+ else if (see_monster)
+ msg("The %s has no effect on %s.",
+ name, prname(mname, FALSE));
+ }
+ else {
+ if (save(VS_BREATH, tp,
+ -(shooter->t_stats.s_lvl/10)))
+ damage /= 2;
+
+ /* The poor fellow got killed! */
+ if ((tp->t_stats.s_hpt -= damage) <= 0) {
+ if (see_monster)
+ msg("The %s kills %s",
+ name, prname(mname, FALSE));
+ else
+ msg("You hear a faint groan in the distance");
+ /*
+ * Instead of calling killed() here, we
+ * will record that the monster was killed
+ * and call it at the end of the routine,
+ * after we restore what was under the bolt.
+ * We have to do this because in the case
+ * of a bolt that first misses the monster
+ * and then gets it on the bounce. If we
+ * call killed here, the 'missed' space in
+ * spotpos puts the monster back on the
+ * screen
+ */
+ target = item;
+ }
+ else { /* Not dead, so just scream */
+ if (!see_monster)
+ msg("You hear a scream in the distance");
+ }
+ }
+ }
+ }
+ else if (isalpha(show(pos.y, pos.x))) {
+ if (see_monster) {
+ if (terse)
+ msg("%s misses", name);
+ else
+ msg("The %s whizzes past %s",
+ name, prname(mname, FALSE));
+ }
+ if (get_points) runto(tp, &hero);
+ }
+ }
+ else if (pos.y == hero.y && pos.x == hero.x) {
+at_hero: if (!save(VS_BREATH, &player,
+ -(shooter->t_stats.s_lvl/10))){
+ if (terse)
+ msg("The %s hits you", name);
+ else
+ msg("You are hit by the %s", name);
+ used = TRUE;
+
+ /*
+ * The Amulet of Yendor protects against all "breath"
+ *
+ * The following two if statements could be combined
+ * into one, but it makes the compiler barf, so split
+ * it up
+ */
+ if (cur_relic[YENDOR_AMULET] ||
+ (EQUAL(name,"chlorine gas")&&on(player, NOGAS)) ||
+ (EQUAL(name,"sleeping gas")&&ISWEARING(R_ALERT))){
+ msg("The %s has no affect", name);
+ }
+ else if((EQUAL(name, "flame") && on(player, NOFIRE)) ||
+ (EQUAL(name, "ice") && on(player, NOCOLD)) ||
+ (EQUAL(name,"lightning bolt")&&
+ on(player,NOBOLT)) ||
+ (EQUAL(name,"fear gas")&&ISWEARING(R_HEROISM))){
+ msg("The %s has no affect", name);
+ }
+
+ else {
+ dsrpt_player();
+
+ /*
+ * Check for gas with special effects
+ */
+ if (EQUAL(name, "nerve gas")) {
+ msg("The nerve gas paralyzes you.");
+ player.t_no_move +=
+ movement(&player) * FREEZETIME;
+ player.t_action = A_FREEZE;
+ }
+ else if (EQUAL(name, "sleeping gas")) {
+ msg("The sleeping gas puts you to sleep.");
+ player.t_no_move +=
+ movement(&player) * SLEEPTIME;
+ player.t_action = A_FREEZE;
+ }
+ else if (EQUAL(name, "confusion gas")) {
+ if (off(player, ISCLEAR)) {
+ if (on(player, ISHUH))
+ lengthen(unconfuse,
+ rnd(20)+HUHDURATION);
+ else {
+ turn_on(player, ISHUH);
+ fuse(unconfuse, 0,
+ rnd(20)+HUHDURATION, AFTER);
+ msg(
+ "The confusion gas has confused you.");
+ }
+ }
+ else msg("You feel dizzy for a moment, but it quickly passes.");
+ }
+ else if (EQUAL(name, "slow gas")) {
+ add_slow();
+ }
+ else if (EQUAL(name, "fear gas")) {
+ turn_on(player, ISFLEE);
+ player.t_dest = &shooter->t_pos;
+ msg("The fear gas terrifies you.");
+ }
+ else {
+ if (EQUAL(name, "acid") &&
+ cur_armor != NULL &&
+ !(cur_armor->o_flags & ISPROT) &&
+ !save(VS_BREATH, &player, -2) &&
+ cur_armor->o_ac < pstats.s_arm+1) {
+ msg("Your armor corrodes from the acid");
+ cur_armor->o_ac++;
+ }
+ if (save(VS_BREATH, &player,
+ -(shooter->t_stats.s_lvl/10)))
+ damage /= 2;
+ if ((pstats.s_hpt -= damage) <= 0)
+ death(reason);
+ }
+ }
+ }
+ else
+ msg("The %s whizzes by you", name);
+ }
+
+ mvwaddch(cw, pos.y, pos.x, dirch);
+ draw(cw);
+ }
+
+ pos.y += dir.y;
+ pos.x += dir.x;
+ }
+
+ /* Restore what was under the bolt */
+ for (x = y - 1; x >= 0; x--)
+ mvwaddch(cw, spotpos[x].place.y, spotpos[x].place.x, spotpos[x].oldch);
+
+ /* If we killed something, do so now. This will also blank the monster. */
+ if (target) killed(target, FALSE, get_points, TRUE);
+ return;
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/things.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/things.c Fri May 08 15:24:40 2015 -0400
@@ -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
+#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);
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/trader.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/trader.c Fri May 08 15:24:40 2015 -0400
@@ -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; wpto_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; io_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);
+}
+
+
diff -r d10fc4a065ac -r adfa37e67084 arogue7/util.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/util.c Fri May 08 15:24:40 2015 -0400
@@ -0,0 +1,1283 @@
+/*
+ * util.c - all sorts of miscellaneous 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.
+ */
+
+#include "curses.h"
+#include "rogue.h"
+#include
+#ifdef PC7300
+#include
+#include
+#include
+extern struct uwdata wdata;
+#endif
+
+/*
+ * all sorts of miscellaneous routines
+ *
+ */
+
+
+
+
+/*
+ * this routine computes the players current AC without dex bonus's
+ */
+int
+ac_compute(ignoremetal)
+bool ignoremetal;
+{
+ register int ac;
+
+ ac = pstats.s_arm; /* base armor of "skin" */
+ if (cur_armor) {
+ if (!ignoremetal ||
+ (cur_armor->o_which != LEATHER &&
+ cur_armor->o_which != STUDDED_LEATHER &&
+ cur_armor->o_which != PADDED_ARMOR))
+ ac -= (10 - cur_armor->o_ac);
+ }
+ if (player.t_ctype == C_MONK)
+ ac -= pstats.s_lvl * 2 / 3;
+ ac -= ring_value(R_PROTECT);
+ if (cur_misc[WEAR_BRACERS] != NULL)
+ ac -= cur_misc[WEAR_BRACERS]->o_ac;
+ if (cur_misc[WEAR_CLOAK] != NULL)
+ ac -= cur_misc[WEAR_CLOAK]->o_ac;
+
+ /* If player has the cloak, must be wearing it */
+ if (cur_relic[EMORI_CLOAK]) ac -= 5;
+
+ if (ac > 10)
+ ac = 10;
+ return(ac);
+}
+
+/*
+ * aggravate:
+ * aggravate all the monsters on this level
+ */
+
+aggravate(do_uniques, do_good)
+bool do_uniques, do_good;
+{
+ register struct linked_list *mi;
+ register struct thing *thingptr;
+
+ for (mi = mlist; mi != NULL; mi = next(mi)) {
+ thingptr = THINGPTR(mi);
+ if (do_good == FALSE && off(*thingptr, ISMEAN)) continue;
+ if (do_uniques || off(*thingptr, ISUNIQUE)) runto(thingptr, &hero);
+ }
+}
+
+/*
+ * cansee:
+ * returns true if the hero can see a certain coordinate.
+ */
+
+cansee(y, x)
+register int y, x;
+{
+ register struct room *rer;
+ register int radius;
+ coord tp;
+
+ if (on(player, ISBLIND))
+ return FALSE;
+
+ tp.y = y;
+ tp.x = x;
+ rer = roomin(&tp);
+
+ /* How far can we see? */
+ if (levtype == OUTSIDE) {
+ if (daytime) radius = 36;
+ else if (lit_room(rer)) radius = 9;
+ else radius = 3;
+ }
+ else radius = 3;
+
+ /*
+ * We can only see if the hero in the same room as
+ * the coordinate and the room is lit or if it is close.
+ */
+ return ((rer != NULL &&
+ levtype != OUTSIDE &&
+ (levtype != MAZELEV || /* Maze level needs direct line */
+ maze_view(tp.y, tp.x)) &&
+ rer == roomin(&hero) &&
+ lit_room(rer)) ||
+ DISTANCE(y, x, hero.y, hero.x) < radius);
+}
+
+/*
+ * check_level:
+ * Check to see if the guy has gone up a level.
+ *
+ * Return points needed to obtain next level.
+ *
+ * These are certain beginning experience levels for all players.
+ * All further experience levels are computed by muliplying by 2
+ * up through MAXDOUBLE. Then the cap is added in to compute
+ * further levels
+ */
+long
+check_level()
+{
+ register int i, j, add = 0;
+ register unsigned long exp;
+ long retval; /* Return value */
+ int nsides;
+
+ pstats.s_lvl -= pstats.s_lvladj; /* correct for level adjustment */
+ /* See if we are past the doubling stage */
+ exp = char_class[player.t_ctype].cap;
+ if (pstats.s_exp >= exp) {
+ i = pstats.s_exp/exp; /* First get amount above doubling area */
+ retval = exp + i * exp; /* Compute next higher boundary */
+ i += MAXDOUBLE; /* Add in the previous doubled levels */
+ }
+ else {
+ i = 0;
+ exp = char_class[player.t_ctype].start_exp;
+ while (exp <= pstats.s_exp) {
+ i++;
+ exp <<= 1;
+ }
+ retval = exp;
+ }
+ if (++i > pstats.s_lvl) {
+ nsides = char_class[player.t_ctype].hit_pts;
+ for (j=0; j<(i-pstats.s_lvl); j++) /* Take care of multi-level jumps */
+ add += max(1, roll(1,nsides) + const_bonus());
+ max_stats.s_hpt += add;
+ if ((pstats.s_hpt += add) > max_stats.s_hpt)
+ pstats.s_hpt = max_stats.s_hpt;
+ msg("Welcome, %s, to level %d",
+ cnames[player.t_ctype][min(i-1, NUM_CNAMES-1)], i);
+ }
+ pstats.s_lvl = i;
+ pstats.s_lvl += pstats.s_lvladj; /* correct for level adjustment */
+ return(retval);
+}
+
+/*
+ * Used to modify the players strength
+ * it keeps track of the highest it has been, just in case
+ */
+
+chg_str(amt)
+register int amt;
+{
+ register int ring_str; /* ring strengths */
+ register struct stats *ptr; /* for speed */
+
+ ptr = &pstats;
+ ring_str = ring_value(R_ADDSTR);
+ ptr->s_str -= ring_str;
+ ptr->s_str += amt;
+ if (ptr->s_str > 25)
+ ptr->s_str = 25;
+ if (ptr->s_str > max_stats.s_str)
+ max_stats.s_str = ptr->s_str;
+ ptr->s_str += ring_str;
+ if (ptr->s_str <= 0)
+ death(D_STRENGTH);
+ updpack(TRUE, &player);
+}
+
+/*
+ * let's confuse the player
+ */
+confus_player()
+{
+ if (off(player, ISCLEAR))
+ {
+ msg("Wait, what's going on here. Huh? What? Who?");
+ if (find_slot(unconfuse))
+ lengthen(unconfuse, HUHDURATION);
+ else
+ fuse(unconfuse, 0, HUHDURATION, AFTER);
+ turn_on(player, ISHUH);
+ }
+ else msg("You feel dizzy for a moment, but it quickly passes.");
+}
+
+/*
+ * this routine computes the players current dexterity
+ */
+dex_compute()
+{
+ if (cur_misc[WEAR_GAUNTLET] != NULL &&
+ cur_misc[WEAR_GAUNTLET]->o_which == MM_G_DEXTERITY) {
+ if (cur_misc[WEAR_GAUNTLET]->o_flags & ISCURSED)
+ return (3);
+ else
+ return (18);
+ }
+ else
+ return (pstats.s_dext);
+}
+
+/*
+ * diag_ok:
+ * Check to see if the move is legal if it is diagonal
+ */
+
+diag_ok(sp, ep, flgptr)
+register coord *sp, *ep;
+struct thing *flgptr;
+{
+ register int numpaths = 0;
+
+ /* Horizontal and vertical moves are always ok */
+ if (ep->x == sp->x || ep->y == sp->y)
+ return TRUE;
+
+ /* Diagonal moves are not allowed if there is a horizontal or
+ * vertical path to the destination
+ */
+ if (step_ok(ep->y, sp->x, MONSTOK, flgptr)) numpaths++;
+ if (step_ok(sp->y, ep->x, MONSTOK, flgptr)) numpaths++;
+ return(numpaths != 1);
+}
+
+/*
+ * pick a random position around the give (y, x) coordinates
+ */
+coord *
+fallpos(pos, be_clear, range)
+register coord *pos;
+bool be_clear;
+int range;
+{
+ register int tried, i, j;
+ register char ch;
+ static coord ret;
+ static short masks[] = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x100 };
+
+/*
+ * Pick a spot at random centered on the position given by 'pos' and
+ * up to 'range' squares away from 'pos'
+ *
+ * If 'be_clear' is TRUE, the spot must be either FLOOR or PASSAGE
+ * inorder to be considered valid
+ *
+ *
+ * Generate a number from 0 to 8, representing the position to pick.
+ * Note that this DOES include the positon 'pos' itself
+ *
+ * If this position is not valid, mark it as 'tried', and pick another.
+ * Whenever a position is picked that has been tried before,
+ * sequentially find the next untried position. This eliminates costly
+ * random number generation
+ */
+
+ tried = 0;
+ while( tried != 0x1ff ) {
+ i = rnd(9);
+ while( tried & masks[i] )
+ i = (i + 1) % 9;
+
+ tried |= masks[i];
+
+ for( j = 1; j <= range; j++ ) {
+ ret.x = pos->x + j*grid[i].x;
+ ret.y = pos->y + j*grid[i].y;
+
+ if (ret.x == hero.x && ret.y == hero.y)
+ continue; /* skip the hero */
+
+ if (ret.x < 0 || ret.x > cols - 1 ||
+ ret.y < 1 || ret.y > lines - 3)
+ continue; /* off the screen? */
+
+ ch = CCHAR( winat(ret.y, ret.x) );
+
+ /*
+ * Check to make certain the spot is valid
+ */
+ switch( ch ) {
+ case FLOOR:
+ case PASSAGE:
+ return( &ret );
+ case GOLD:
+ case SCROLL:
+ case POTION:
+ case STICK:
+ case RING:
+ case WEAPON:
+ case ARMOR:
+ case MM:
+ case FOOD:
+ if(!be_clear && levtype != POSTLEV)
+ return( &ret );
+ default:
+ break;
+ }
+ }
+ }
+ return( NULL );
+}
+
+
+/*
+ * findmindex:
+ * Find the index into the monster table of a monster given its name.
+ */
+
+findmindex(name)
+char *name;
+{
+ int which;
+
+ for (which=1; which= NUMMONST) {
+ debug("couldn't find monster index");
+ which = 1;
+ }
+ return(which);
+}
+
+/*
+ * find_mons:
+ * Find the monster from his coordinates
+ */
+
+struct linked_list *
+find_mons(y, x)
+register int y;
+register int x;
+{
+ register struct linked_list *item;
+ register struct thing *th;
+
+ for (item = mlist; item != NULL; item = next(item))
+ {
+ th = THINGPTR(item);
+ if (th->t_pos.y == y && th->t_pos.x == x)
+ return item;
+ }
+ return NULL;
+}
+
+/*
+ * find_obj:
+ * find the unclaimed object at y, x
+ */
+
+struct linked_list *
+find_obj(y, x)
+register int y;
+register int x;
+{
+ register struct linked_list *obj;
+ register struct object *op;
+
+ for (obj = lvl_obj; obj != NULL; obj = next(obj))
+ {
+ op = OBJPTR(obj);
+ if (op->o_pos.y == y && op->o_pos.x == x)
+ return obj;
+ }
+ return NULL;
+}
+
+/*
+ * get coordinates from the player using the cursor keys (or mouse)
+ */
+coord
+get_coordinates()
+{
+ register int which;
+ coord c;
+#ifdef PC7300
+ struct umdata startmouse, listenmouse; /* Mouse parameters */
+ int xmouse, /* x-position of mouse */
+ ymouse, /* y-position of mouse */
+ bmouse, /* button value of mouse */
+ rmouse; /* reason for mouse change */
+#endif
+
+ c = hero;
+ wmove(cw, hero.y, hero.x);
+ draw(cw);
+#ifdef PC7300
+ keypad(0, 1); /* Turn on escape sequences */
+ ioctl(0, WIOCGETMOUSE, &startmouse); /* Get current mouse parameters */
+ listenmouse = startmouse; /* Make a copy */
+ listenmouse.um_flags |= MSDOWN; /* Enable detection of button down */
+ ioctl(0, WIOCSETMOUSE, &listenmouse); /* Make the change */
+#endif
+ for (;;) {
+#ifdef PC7300
+ which = wgetc(0);
+#else
+ which = (getchar() & 0177);
+#endif
+ switch(which) {
+#ifdef PC7300
+ case Home:
+ c.x = 0; c.y = 1;
+ when Beg:
+ c.x = 0;
+ when End:
+ c.x = cols - 1;
+ when Mouse:
+ case ESCAPE:
+ case Cancl:
+ case s_Cancl:
+ if (which == Mouse) {
+ if (wreadmouse(0,&xmouse,&ymouse,&bmouse,&rmouse) != 0 ||
+ (rmouse & MSDOWN) == 0)
+ break;
+ c.y = ymouse / wdata.uw_vs;
+ c.x = xmouse / wdata.uw_hs;
+ c.y = max(c.y, 1);
+ c.y = min(c.y, lines - 3);
+ c.x = max(c.x, 0);
+ c.x = min(c.x, cols - 1);
+ }
+ else c = hero;
+ wmove(cw, c.y, c.x);
+ draw(cw);
+ case '\n':
+ case '\c':
+ keypad(0, 0); /* Turn off escape interpretation */
+ ioctl(0, WIOCSETMOUSE, &startmouse); /* No mouse tracking */
+ return(c);
+ when 'h':
+ case 'H':
+ case Back:
+ case s_Back:
+ c.x--;
+ when 'j':
+ case 'J':
+ case Down:
+ case RollDn:
+ c.y++;
+ when 'k':
+ case 'K':
+ case Up:
+ case RollUp:
+ c.y--;
+ when 'l':
+ case 'L':
+ case Forward:
+ case s_Forward:
+ c.x++;
+ when 'y':
+ case 'Y':
+ case Prev:
+ c.x--; c.y--;
+ when 'u':
+ case 'U':
+ case Next:
+ c.x++; c.y--;
+ when 'b':
+ case 'B':
+ case s_Prev:
+ c.x--; c.y++;
+ when 'n':
+ case 'N':
+ case s_Next:
+ c.x++; c.y++;
+ when '*':
+ msg("Select location via mouse, or");
+ msg("Use cursor keys,h,j,k,l,y,u,b,or n, then hit return.");
+#else
+ case ESCAPE:
+ c = hero;
+ wmove(cw, c.y, c.x);
+ draw(cw);
+ case '\n':
+ case '\r':
+ return(c);
+ when 'h':
+ case 'H':
+ c.x--;
+ when 'j':
+ case 'J':
+ c.y++;
+ when 'k':
+ case 'K':
+ c.y--;
+ when 'l':
+ case 'L':
+ c.x++;
+ when 'y':
+ case 'Y':
+ c.x--; c.y--;
+ when 'u':
+ case 'U':
+ c.x++; c.y--;
+ when 'b':
+ case 'B':
+ c.x--; c.y++;
+ when 'n':
+ case 'N':
+ c.x++; c.y++;
+ when '*':
+ msg("Use h,j,k,l,y,u,b,n to position cursor, then hit return.");
+#endif
+ }
+ c.y = max(c.y, 1);
+ c.y = min(c.y, lines - 3);
+ c.x = max(c.x, 0);
+ c.x = min(c.x, cols - 1);
+ wmove(cw, c.y, c.x);
+ draw(cw);
+ }
+}
+
+/*
+ * set up the direction co_ordinate for use in various "prefix" commands
+ */
+bool
+get_dir(direction)
+coord *direction;
+{
+ register char *prompt;
+ register bool gotit;
+ int x,y;
+
+ prompt = terse ? "Direction?" : "Which direction? ";
+ msg(prompt);
+ do
+ {
+ gotit = TRUE;
+ switch (md_readchar(msgw))
+ {
+ case 'h': case'H': direction->y = 0; direction->x = -1;
+ when 'j': case'J': direction->y = 1; direction->x = 0;
+ when 'k': case'K': direction->y = -1; direction->x = 0;
+ when 'l': case'L': direction->y = 0; direction->x = 1;
+ when 'y': case'Y': direction->y = -1; direction->x = -1;
+ when 'u': case'U': direction->y = -1; direction->x = 1;
+ when 'b': case'B': direction->y = 1; direction->x = -1;
+ when 'n': case'N': direction->y = 1; direction->x = 1;
+ case 0:
+ when 3: quit(0);
+ return(FALSE);
+ when ESCAPE: return (FALSE);
+ otherwise:
+ mpos = 0;
+ msg(prompt);
+ gotit = FALSE;
+ }
+ } until (gotit);
+ if ((on(player, ISHUH) || on(player, ISDANCE)) && rnd(100) > 20) {
+ do
+ {
+ *direction = grid[rnd(9)];
+ } while (direction->y == 0 && direction->x == 0);
+ }
+ else if (on(player, ISFLEE)) {
+ y = hero.y;
+ x = hero.x;
+ while (shoot_ok(winat(y, x))) {
+ y += direction->y;
+ x += direction->x;
+ }
+ if (isalpha(mvwinch(mw, y, x))) {
+ if (y == player.t_dest->y && x == player.t_dest->x) {
+ mpos = 0;
+ msg("You are too frightened to!");
+ return(FALSE);
+ }
+ }
+ }
+ mpos = 0;
+ return TRUE;
+}
+
+/*
+ * see if the object is one of the currently used items
+ */
+is_current(obj)
+register struct object *obj;
+{
+ if (obj == NULL)
+ return FALSE;
+ if (obj == cur_armor || obj == cur_weapon ||
+ obj == cur_ring[LEFT_1] || obj == cur_ring[LEFT_2] ||
+ obj == cur_ring[LEFT_3] || obj == cur_ring[LEFT_4] ||
+ obj == cur_ring[RIGHT_1] || obj == cur_ring[RIGHT_2] ||
+ obj == cur_ring[RIGHT_3] || obj == cur_ring[RIGHT_4] ||
+ obj == cur_misc[WEAR_BOOTS] || obj == cur_misc[WEAR_JEWEL] ||
+ obj == cur_misc[WEAR_BRACERS] || obj == cur_misc[WEAR_CLOAK] ||
+ obj == cur_misc[WEAR_GAUNTLET] || obj == cur_misc[WEAR_NECKLACE]) {
+
+ return TRUE;
+ }
+
+ /* Is it a "current" relic? */
+ if (obj->o_type == RELIC) {
+ switch (obj->o_which) {
+ case MUSTY_DAGGER:
+ case EMORI_CLOAK:
+ case HEIL_ANKH:
+ case YENDOR_AMULET:
+ case STONEBONES_AMULET:
+ case HRUGGEK_MSTAR:
+ case AXE_AKLAD:
+ case YEENOGHU_FLAIL:
+ case SURTUR_RING:
+ if (cur_relic[obj->o_which]) return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+/*
+ * Look:
+ * A quick glance all around the player
+ */
+
+look(wakeup, runend)
+bool wakeup; /* Should we wake up monsters */
+bool runend; /* At end of a run -- for mazes */
+{
+ register int x, y, radius;
+ register char ch, och;
+ register int oldx, oldy;
+ register bool inpass, horiz, vert, do_light = FALSE, do_blank = FALSE;
+ register int passcount = 0, curfloorcount = 0, nextfloorcount = 0;
+ register struct room *rp;
+ register int ey, ex;
+
+ inpass = ((rp = roomin(&hero)) == NULL); /* Are we in a passage? */
+
+ /* Are we moving vertically or horizontally? */
+ if (runch == 'h' || runch == 'l') horiz = TRUE;
+ else horiz = FALSE;
+ if (runch == 'j' || runch == 'k') vert = TRUE;
+ else vert = FALSE;
+
+ /* How far around himself can the player see? */
+ if (levtype == OUTSIDE) {
+ if (daytime) radius = 6;
+ else if (lit_room(rp)) radius = 3;
+ else radius = 1;
+ }
+ else radius = 1;
+
+ getyx(cw, oldy, oldx); /* Save current position */
+
+ /* Blank out the floor around our last position and check for
+ * moving out of a corridor in a maze.
+ */
+ if (levtype == OUTSIDE) do_blank = !daytime;
+ else if (oldrp != NULL && !lit_room(oldrp) && off(player, ISBLIND))
+ do_blank = TRUE;
+
+ /* Now move around the old position and blank things out */
+ ey = player.t_oldpos.y + radius;
+ ex = player.t_oldpos.x + radius;
+ for (x = player.t_oldpos.x - radius; x <= ex; x++)
+ if (x >= 0 && x < cols)
+ for (y = player.t_oldpos.y - radius; y <= ey; y++) {
+ struct linked_list *it;
+ coord here; /* Current coordinate */
+ char savech; /* Saves character in monster window */
+ bool in_room; /* Are we in a room? */
+
+ if (y < 1 || y > lines - 3) continue;
+
+ /* See what's there -- ignore monsters, just see what they're on */
+ savech = CCHAR( mvwinch(mw, y, x) );
+ waddch(mw, ' ');
+ ch = show(y, x);
+ mvwaddch(mw, y, x, savech); /* Restore monster */
+
+ /*
+ * If we have a monster that we can't see anymore, make sure
+ * that we can note that fact.
+ */
+ if (isalpha(savech) &&
+ (y < hero.y - radius || y > hero.y + radius ||
+ x < hero.x - radius || x > hero.x + radius)) {
+ /* Find the monster */
+ it = find_mons(y, x);
+ }
+ else it = NULL;
+
+ /* Are we in a room? */
+ here.y = y;
+ here.x = x;
+ in_room = (roomin(&here) != NULL);
+
+ if ((do_blank || !in_room) && (y != hero.y || x != hero.x))
+ switch (ch) {
+ case DOOR:
+ case SECRETDOOR:
+ case PASSAGE:
+ case STAIRS:
+ case TRAPDOOR:
+ case TELTRAP:
+ case BEARTRAP:
+ case SLEEPTRAP:
+ case ARROWTRAP:
+ case DARTTRAP:
+ case MAZETRAP:
+ case POOL:
+ case POST:
+ case '|':
+ case '-':
+ case WALL:
+ /* If there was a monster showing, make it disappear */
+ if (isalpha(savech)) {
+ mvwaddch(cw, y, x, ch);
+
+ /*
+ * If we found it (we should!), set it to
+ * the right character!
+ */
+ if (it) (THINGPTR(it))->t_oldch = ch;
+ }
+ break;
+ when FLOOR:
+ case FOREST:
+ default:
+ mvwaddch(cw, y, x, in_room ? ' ' : PASSAGE);
+
+ /* If we found a monster, set it to darkness! */
+ if (it) (THINGPTR(it))->t_oldch = CCHAR( mvwinch(cw, y, x) );
+ }
+
+ /* Moving out of a corridor? */
+ if (levtype == MAZELEV && !ce(hero, player.t_oldpos) &&
+ !running && !isrock(ch) && /* Not running and not a wall */
+ ((vert && x != player.t_oldpos.x && y==player.t_oldpos.y) ||
+ (horiz && y != player.t_oldpos.y && x==player.t_oldpos.x)))
+ do_light = off(player, ISBLIND);
+ }
+
+ /* Take care of unlighting a corridor */
+ if (do_light && lit_room(rp)) light(&player.t_oldpos);
+
+ /* Are we coming or going between a wall and a corridor in a maze? */
+ och = show(player.t_oldpos.y, player.t_oldpos.x);
+ ch = show(hero.y, hero.x);
+ if (levtype == MAZELEV &&
+ ((isrock(och) && !isrock(ch)) || (isrock(ch) && !isrock(och)))) {
+ do_light = off(player, ISBLIND); /* Light it up if not blind */
+
+ /* Unlight what we just saw */
+ if (do_light && lit_room(&rooms[0])) light(&player.t_oldpos);
+ }
+
+ /* Look around the player */
+ ey = hero.y + radius;
+ ex = hero.x + radius;
+ for (x = hero.x - radius; x <= ex; x++)
+ if (x >= 0 && x < cols) for (y = hero.y - radius; y <= ey; y++) {
+ if (y < 1 || y >= lines - 2)
+ continue;
+ if (isalpha(mvwinch(mw, y, x)))
+ {
+ register struct linked_list *it;
+ register struct thing *tp;
+
+ if (wakeup)
+ it = wake_monster(y, x);
+ else
+ it = find_mons(y, x);
+
+ if (it) {
+ tp = THINGPTR(it);
+ tp->t_oldch = CCHAR( mvinch(y, x) );
+ if (isatrap(tp->t_oldch)) {
+ register struct trap *trp = trap_at(y, x);
+
+ tp->t_oldch = (trp->tr_flags & ISFOUND) ? tp->t_oldch
+ : trp->tr_show;
+ }
+ if (tp->t_oldch == FLOOR && !lit_room(rp) &&
+ off(player, ISBLIND))
+ tp->t_oldch = ' ';
+ }
+ }
+
+ /*
+ * Secret doors show as walls
+ */
+ if ((ch = show(y, x)) == SECRETDOOR)
+ ch = secretdoor(y, x);
+ /*
+ * Don't show room walls if he is in a passage and
+ * check for maze turns
+ */
+ if (off(player, ISBLIND))
+ {
+ if (y == hero.y && x == hero.x
+ || (inpass && (ch == '-' || ch == '|')))
+ continue;
+
+ /* Did we come to a crossroads in a maze? */
+ if (levtype == MAZELEV &&
+ (runend || !ce(hero, player.t_oldpos)) &&
+ !isrock(ch) && /* Not a wall */
+ ((vert && x != hero.x && y == hero.y) ||
+ (horiz && y != hero.y && x == hero.x)))
+ /* Just came to a turn */
+ do_light = off(player, ISBLIND);
+ }
+ else if (y != hero.y || x != hero.x)
+ continue;
+
+ wmove(cw, y, x);
+ waddch(cw, ch);
+ if (door_stop && !firstmove && running)
+ {
+ switch (runch)
+ {
+ case 'h':
+ if (x == hero.x + 1)
+ continue;
+ when 'j':
+ if (y == hero.y - 1)
+ continue;
+ when 'k':
+ if (y == hero.y + 1)
+ continue;
+ when 'l':
+ if (x == hero.x - 1)
+ continue;
+ when 'y':
+ if ((x + y) - (hero.x + hero.y) >= 1)
+ continue;
+ when 'u':
+ if ((y - x) - (hero.y - hero.x) >= 1)
+ continue;
+ when 'n':
+ if ((x + y) - (hero.x + hero.y) <= -1)
+ continue;
+ when 'b':
+ if ((y - x) - (hero.y - hero.x) <= -1)
+ continue;
+ }
+ switch (ch)
+ {
+ case DOOR:
+ if (x == hero.x || y == hero.y)
+ running = FALSE;
+ break;
+ case PASSAGE:
+ if (x == hero.x || y == hero.y)
+ passcount++;
+ break;
+ case FLOOR:
+ /* Stop by new passages in a maze (floor next to us) */
+ if ((levtype == MAZELEV) &&
+ !(hero.y == y && hero.x == x)) {
+ if (vert) { /* Moving vertically */
+ /* We have a passage on our row */
+ if (y == hero.y) curfloorcount++;
+
+ /* Some passage on the next row */
+ else if (y != player.t_oldpos.y)
+ nextfloorcount++;
+ }
+ else { /* Moving horizontally */
+ /* We have a passage on our column */
+ if (x == hero.x) curfloorcount++;
+
+ /* Some passage in the next column */
+ else if (x != player.t_oldpos.x)
+ nextfloorcount++;
+ }
+ }
+ case '|':
+ case '-':
+ case ' ':
+ break;
+ default:
+ running = FALSE;
+ break;
+ }
+ }
+ }
+
+ /* Have we passed a side passage, with multiple choices? */
+ if (curfloorcount > 0 && nextfloorcount > 0) running = FALSE;
+
+ else if (door_stop && !firstmove && passcount > 1)
+ running = FALSE;
+
+ /* Do we have to light up the area (just stepped into a new corridor)? */
+ if (do_light && !running && lit_room(rp)) light(&hero);
+
+ mvwaddch(cw, hero.y, hero.x, PLAYER);
+ wmove(cw, oldy, oldx);
+ if (!ce(player.t_oldpos, hero)) {
+ player.t_oldpos = hero; /* Don't change if we didn't move */
+ oldrp = rp;
+ }
+}
+
+/*
+ * Lower a level of experience
+ */
+
+lower_level(who)
+short who;
+{
+ int fewer, nsides;
+ unsigned int exp;
+
+ msg("You suddenly feel less skillful.");
+ if (--pstats.s_lvl == 0)
+ death(who); /* All levels gone */
+ if (pstats.s_lvladj > 0) { /* lose artificial levels first */
+ pstats.s_lvladj--;
+ return;
+ }
+ exp = char_class[player.t_ctype].cap;
+ if (pstats.s_exp >= exp*2)
+ pstats.s_exp -= exp;
+ else
+ pstats.s_exp /= 2;
+
+ nsides = char_class[player.t_ctype].hit_pts;
+ fewer = max(1, roll(1,nsides) + const_bonus());
+ pstats.s_hpt -= fewer;
+ max_stats.s_hpt -= fewer;
+ if (pstats.s_hpt < 1)
+ pstats.s_hpt = 1;
+ if (max_stats.s_hpt < 1)
+ death(who);
+}
+
+/*
+ * print out the name of a monster
+ */
+char *
+monster_name(tp)
+register struct thing *tp;
+{
+ prbuf[0] = '\0';
+ if (on(*tp, ISFLEE) || on(*tp, WASTURNED))
+ strcat(prbuf, "terrified ");
+ if (on(*tp, ISHUH))
+ strcat(prbuf, "confused ");
+ if (on(*tp, ISCHARMED))
+ strcat(prbuf, "charmed ");
+ else if (on(*tp, ISFLY))
+ strcat(prbuf, "flying ");
+
+ /* If it is sleeping or stoned, write over any of the above attributes */
+ if (off(*tp, ISRUN))
+ strcpy(prbuf, "sleeping ");
+ if (on(*tp, ISSTONE))
+ strcpy(prbuf, "petrified ");
+
+ if (tp->t_name) strcat(prbuf, tp->t_name);
+ else strcat(prbuf, monsters[tp->t_index].m_name);
+
+ return(prbuf);
+}
+
+/*
+ * move_hero:
+ * Try to move the hero somplace besides next to where he is. We ask him
+ * where. There can be restrictions based on why he is moving.
+ */
+
+bool
+move_hero(why)
+int why;
+{
+ char *action;
+ char which;
+ coord c;
+
+ switch (why) {
+ case H_TELEPORT:
+ action = "teleport";
+ }
+
+ msg("Where do you wish to %s to? (* for help) ", action);
+ c = get_coordinates();
+ mpos = 0;
+ which = CCHAR( winat(c.y, c.x) );
+ switch (which) {
+ default:
+ if (!isrock(which) || off(player, CANINWALL)) break;
+
+ case FLOOR:
+ case PASSAGE:
+ case DOOR:
+ case STAIRS:
+ case POST:
+ case GOLD:
+ case POTION:
+ case SCROLL:
+ case FOOD:
+ case WEAPON:
+ case ARMOR:
+ case RING:
+ case MM:
+ case RELIC:
+ case STICK:
+ hero = c;
+ return(TRUE);
+ }
+ return(FALSE);
+}
+
+/*
+ * raise_level:
+ * The guy just magically went up a level.
+ */
+
+raise_level()
+{
+ unsigned long test; /* Next level -- be sure it is not an overflow */
+
+ test = check_level(); /* Get next boundary */
+
+ /* Be sure it is higher than what we have no -- else overflow */
+ if (test > pstats.s_exp) pstats.s_exp = test;
+ check_level();
+}
+
+/*
+ * saving throw matrix for character saving throws
+ * this table is indexed by char type and saving throw type
+ */
+static int st_matrix[NUM_CHARTYPES][5] = {
+/* Poison, Petrify, wand, Breath, Magic */
+{ 14, 15, 16, 16, 17 },
+{ 14, 15, 16, 16, 17 },
+{ 14, 15, 16, 16, 17 },
+{ 14, 13, 11, 15, 12 },
+{ 10, 13, 14, 16, 15 },
+{ 13, 12, 14, 16, 15 },
+{ 13, 12, 14, 16, 15 },
+{ 10, 13, 14, 16, 15 },
+{ 13, 12, 14, 16, 15 },
+{ 14, 15, 16, 16, 17 }
+};
+
+/*
+ * save:
+ * See if a creature saves against something
+ */
+save(which, who, adj)
+int which; /* which type of save */
+struct thing *who; /* who is saving */
+int adj; /* saving throw adjustment */
+{
+ register int need, level, protect;
+
+ protect = 0;
+ level = who->t_stats.s_lvl;
+ need = st_matrix[who->t_ctype][which];
+ switch (who->t_ctype) {
+ case C_FIGHTER:
+ case C_RANGER:
+ case C_PALADIN:
+ case C_MONSTER:
+ need -= (level-1) / 2;
+ when C_MAGICIAN:
+ need -= 2 * (level-1) / 5;
+ when C_CLERIC:
+ case C_DRUID:
+ need -= (level-1) / 3;
+ when C_THIEF:
+ case C_ASSASIN:
+ case C_MONK:
+ need -= 2 * (level-1) / 4;
+ }
+ /*
+ * add in pluses against poison for execeptional constitution
+ */
+ if (which == VS_POISON && who->t_stats.s_const > 18)
+ need -= (who->t_stats.s_const - 17) / 2;
+ if (who == &player) {
+ /*
+ * does the player have a ring of protection on?
+ */
+ protect += ring_value(R_PROTECT);
+ /*
+ * does the player have a cloak of protection on?
+ */
+ if (cur_misc[WEAR_CLOAK])
+ protect += cur_misc[WEAR_CLOAK]->o_ac;
+
+ protect = min(protect, 4);/* no more than a +4 bonus */
+ need -= protect;
+ }
+ need -= adj;
+ /*
+ * always miss or save on a 1 (except for UNIQUEs
+ */
+ if (who == &player || off(*who, ISUNIQUE))
+ need = max(need, 2);
+ need = min(20, need); /* always make our save on a 20 */
+ debug("need a %d to save", need);
+ return (roll(1, 20) >= need);
+}
+
+
+/*
+ * secret_door:
+ * Figure out what a secret door looks like.
+ */
+
+secretdoor(y, x)
+register int y, x;
+{
+ register int i;
+ register struct room *rp;
+ register coord *cpp;
+ static coord cp;
+
+ cp.y = y;
+ cp.x = x;
+ cpp = &cp;
+ for (rp = rooms, i = 0; i < MAXROOMS; rp++, i++)
+ if (inroom(rp, cpp))
+ if (y == rp->r_pos.y || y == rp->r_pos.y + rp->r_max.y - 1)
+ return('-');
+ else
+ return('|');
+
+ return('p');
+}
+
+/*
+ * this routine computes the players current strength
+ */
+str_compute()
+{
+ if (cur_misc[WEAR_GAUNTLET] != NULL &&
+ cur_misc[WEAR_GAUNTLET]->o_which == MM_G_OGRE) {
+ if (cur_misc[WEAR_GAUNTLET]->o_flags & ISCURSED)
+ return (3);
+ else
+ return (18);
+ }
+ else
+ return (pstats.s_str);
+}
+
+/*
+ * copy string using unctrl for things
+ */
+strucpy(s1, s2, len)
+register char *s1, *s2;
+register int len;
+{
+ register char *sp;
+
+ while (len--)
+ {
+ strcpy(s1, (sp = unctrl(*s2++)));
+ s1 += strlen(sp);
+ }
+ *s1 = '\0';
+}
+
+/*
+ * tr_name:
+ * print the name of a trap
+ */
+
+char *
+tr_name(ch)
+char ch;
+{
+ register char *s;
+
+ switch (ch)
+ {
+ case TRAPDOOR:
+ s = terse ? "A trapdoor." : "You found a trapdoor.";
+ when BEARTRAP:
+ s = terse ? "A beartrap." : "You found a beartrap.";
+ when SLEEPTRAP:
+ s = terse ? "A sleeping gas trap.":"You found a sleeping gas trap.";
+ when ARROWTRAP:
+ s = terse ? "An arrow trap." : "You found an arrow trap.";
+ when TELTRAP:
+ s = terse ? "A teleport trap." : "You found a teleport trap.";
+ when DARTTRAP:
+ s = terse ? "A dart trap." : "You found a poison dart trap.";
+ when POOL:
+ s = terse ? "A shimmering pool." : "You found a shimmering pool";
+ when MAZETRAP:
+ s = terse ? "A maze entrance." : "You found a maze entrance";
+ }
+ return s;
+}
+
+/*
+ * for printfs: if string starts with a vowel, return "n" for an "an"
+ */
+char *
+vowelstr(str)
+register char *str;
+{
+ switch (*str)
+ {
+ case 'a':
+ case 'e':
+ case 'i':
+ case 'o':
+ case 'u':
+ return "n";
+ default:
+ return "";
+ }
+}
+
+/*
+ * wake up a room full (hopefully) of creatures
+ */
+wake_room(rp)
+register struct room *rp;
+{
+ register struct linked_list *item;
+ register struct thing *tp;
+
+ for (item=mlist; item!=NULL; item=next(item)) {
+ tp = THINGPTR(item);
+ if (off(*tp,ISRUN) && on(*tp,ISMEAN) && roomin(&tp->t_pos) == rp)
+ runto(tp, &hero);
+ }
+}
+
+
+/*
+ * waste_time:
+ * Do nothing but let other things happen
+ */
+
+waste_time()
+{
+ if (inwhgt) /* if from wghtchk then done */
+ return;
+ do_daemons(BEFORE);
+ do_fuses(BEFORE);
+ do_daemons(AFTER);
+ do_fuses(AFTER);
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/vers.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/vers.c Fri May 08 15:24:40 2015 -0400
@@ -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";
diff -r d10fc4a065ac -r adfa37e67084 arogue7/weapons.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/weapons.c Fri May 08 15:24:40 2015 -0400
@@ -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
+#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;
+}
+
diff -r d10fc4a065ac -r adfa37e67084 arogue7/wear.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/wear.c Fri May 08 15:24:40 2015 -0400
@@ -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; io_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; io_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? */
+ }
+}
diff -r d10fc4a065ac -r adfa37e67084 arogue7/wizard.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/wizard.c Fri May 08 15:24:40 2015 -0400
@@ -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
+#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)) {
+ 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 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));
+}
+
diff -r d10fc4a065ac -r adfa37e67084 arogue7/xcrypt.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/xcrypt.c Fri May 08 15:24:40 2015 -0400
@@ -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 .
+ *
+ * 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
+#include
+
+#ifdef MASTER
+# include
+#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);
+}