# HG changeset patch
# User elwin
# Date 1344553128 0
# Node ID 0ed67132cf10828b1e8f148cea7eb890420ec2d3
# Parent 0ef99244acb869c6c06acf5e04e0aa996dc25817
Import Advanced Rogue 5.8 from the Roguelike Restoration Project (r1490)
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/LICENSE.TXT
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/LICENSE.TXT Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,178 @@
+Copyright (C) 1984, 1985 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 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 (save/restore game state) are based on the work
+of Nicholas J. Kisseberth. Used under license:
+
+Copyright (C) 2005 Nicholas J. Kisseberth
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name(s) of the author(s) nor the names of other contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+===========================================================================
+
+Portions of this software (encryption) 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 0ef99244acb8 -r 0ed67132cf10 arogue5/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/Makefile Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,203 @@
+#
+# Makefile for rogue
+#
+# Advanced Rogue
+# Copyright (C) 1984, 1985 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.
+#
+
+DISTNAME=arogue5.8.2
+PROGRAM=arogue58
+
+O=o
+
+HDRS = rogue.h mach_dep.h network.h
+OBJS1 = chase.$(O) command.$(O) daemon.$(O) daemons.$(O) encumb.$(O) \
+ fight.$(O) init.$(O) io.$(O) list.$(O) main.$(O) maze.$(O) mdport.$(O)\
+ misc.$(O) monsters.$(O) move.$(O) new_level.$(O) options.$(O) \
+ outside.$(O)
+OBJS2 = 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) vers.$(O) weapons.$(O) wear.$(O) \
+ wizard.$(O) xcrypt.$(O)
+OBJS = $(OBJS1) $(OBJS2)
+CFILES= \
+ vers.c chase.c command.c daemon.c daemons.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= Makefile LICENSE.TXT arogue58.sln arogue58.vcproj
+DOCS= arogue58.doc arogue58.html
+
+CC = gcc
+CFLAGS= -g
+CRLIB = -lcurses
+RM = rm -f
+TAR = tar
+.SUFFIXES: .obj
+
+.c.obj:
+ $(CC) $(CFLAGS) /c $*.c
+
+$(PROGRAM): $(OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(CRLIB) -o $@
+
+tags: $(HDRS) $(CFILES)
+ ctags -u $?
+ ed - tags < :ctfix
+ sort tags -o tags
+
+lint:
+ lint -hxbc $(CFILES) $(CRLIB) > linterrs
+
+clean:
+ $(RM) $(OBJS1)
+ $(RM) $(OBJS2)
+ $(RM) core a.exe a.out a.exe.stackdump $(PROGRAM) $(PROGRAM).exe $(PROGRAM).tar $(PROGRAM).tar.gz $(PROGRAM).zip
+
+count:
+ wc -l $(HDRS) $(CFILES)
+
+realcount:
+ cc -E $(CFILES) | ssp - | wc -l
+
+update:
+ ar uv .SAVE $(CFILES) $(HDRS) $(MISC)
+
+dist:
+ @mkdir dist
+ cp $(CFILES) $(HDRS) $(MISC) dist
+
+dist.src:
+ make clean
+ tar cf $(DISTNAME)-src.tar $(CFILES) $(HDRS) $(MISC) $(DOCS)
+ gzip -f $(DISTNAME)-src.tar
+
+dist.irix:
+ make clean
+ make CC=cc CFLAGS="-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 CFLAGS="-qmaxmem=16768 -O3 -qstrict" $(PROGRAM)
+ tar cf $(DISTNAME)-aix.tar $(PROGRAM) LICENSE.TXT $(DOCS)
+ gzip -f $(DISTNAME)-aix.tar
+
+debug.linux:
+ make clean
+ make CFLAGS="-g -DWIZARD" $(PROGRAM)
+
+dist.linux:
+ make clean
+ make $(PROGRAM)
+ tar cf $(DISTNAME)-linux.tar $(PROGRAM) LICENSE.TXT $(DOCS)
+ gzip -f $(DISTNAME)-linux.tar
+
+debug.interix:
+ make clean
+ make CFLAGS="-g3 -DWIZARD" $(PROGRAM)
+
+dist.interix:
+ make clean
+ make $(PROGRAM)
+ tar cf $(DISTNAME)-interix.tar $(PROGRAM) LICENSE.TXT $(DOCS)
+ gzip -f $(DISTNAME)-interix.tar
+
+debug.cygwin:
+ make clean
+ make CFLAGS="-g3 -DWIZARD" $(PROGRAM)
+
+dist.cygwin:
+ make clean
+ make CRLIB="-static -lcurses" $(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 CRLIB="-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 CRLIB="-lcurses" $(PROGRAM)
+ tar cf $(DISTNAME)-msys.tar $(PROGRAM).exe LICENSE.TXT $(DOCS)
+ gzip -f $(DISTNAME)-msys.tar
+
+debug.djgpp:
+ make clean
+ make CFGLAGS="-g3 -DWIZARD" LDFLAGS="-L$(DJDIR)/LIB" CRLIB="-lpdcurses" $(PROGRAM)
+
+dist.djgpp:
+ make clean
+ make LDFLAGS="-L$(DJDIR)/LIB" CRLIB="-lpdcurses" $(PROGRAM)
+ rm -f $(DISTNAME)-djgpp.zip
+ zip $(DISTNAME)-djgpp.zip $(PROGRAM).exe LICENSE.TXT $(DOCS)
+
+#
+# Use NMAKE to build this target
+#
+
+debug.win32:
+ nmake O="obj" RM="-del" clean
+ nmake O="obj" CC="CL" CRLIB="..\pdcurses\pdcurses.lib shfolder.lib user32.lib Advapi32.lib" CFLAGS="-DWIZARD -nologo -I..\pdcurses -Ox -wd4033 -wd4716" $(PROGRAM)
+
+dist.win32:
+ nmake O="obj" RM="-del" clean
+ nmake O="obj" CC="CL" CRLIB="..\pdcurses\pdcurses.lib shfolder.lib user32.lib Advapi32.lib" CFLAGS="-nologo -I..\pdcurses -Ox -wd4033 -wd4716" $(PROGRAM)
+ -del $(DISTNAME)-win32.zip
+ zip $(DISTNAME)-win32.zip $(PROGRAM).exe LICENSE.TXT $(DOCS)
+
+vers.$(O): vers.c rogue.h
+chase.$(O): chase.c rogue.h
+command.$(O): command.c rogue.h
+daemon.$(O): daemon.c rogue.h
+daemons.$(O): daemons.c rogue.h
+encumb.$(O): encumb.c rogue.h
+fight.$(O): fight.c rogue.h
+init.$(O): init.c rogue.h
+io.$(O): io.c rogue.h
+list.$(O): list.c rogue.h
+main.$(O): main.c rogue.h
+maze.$(O): maze.c rogue.h
+misc.$(O): misc.c rogue.h
+monsters.$(O): monsters.c rogue.h
+move.$(O): move.c rogue.h
+new_level.$(O): new_level.c rogue.h
+options.$(O): options.c rogue.h
+outside.$(O): outside.c rogue.h
+pack.$(O): pack.c rogue.h
+passages.$(O): passages.c rogue.h
+player.$(O): player.c rogue.h
+potions.$(O): potions.c rogue.h
+rings.$(O): rings.c rogue.h
+rip.$(O): rip.c rogue.h
+rogue.$(O): rogue.c rogue.h
+rooms.$(O): rooms.c rogue.h
+save.$(O): save.c rogue.h
+scrolls.$(O): scrolls.c rogue.h
+state.$(O): state.c rogue.h
+sticks.$(O): sticks.c rogue.h
+things.$(O): things.c rogue.h
+trader.$(O): trader.c rogue.h
+util.$(O): util.c rogue.h
+weapons.$(O): weapons.c rogue.h
+wear.$(O): wear.c rogue.h
+wizard.$(O): wizard.c rogue.h
+xcrypt.$(O): xcrypt.c
+
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/arogue58.doc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/arogue58.doc Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,1025 @@
+
+
+
+
+
+ The Dungeons of Doom
+
+ AT&T Bell Laboratories
+ The Dungeons of Doom
+
+
+ 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 AND ATTRIBUTES
+
+ Before placing the player in the dungeon, the game
+ requests the player to select a character class: a fighter,
+ a magic user, a cleric, or a thief.
+
+ 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 10 extra hit points for
+
+
+
+
+
+
+
+
+
+
+
+ - 2 -
+
+
+
+ every new experience level.
+
+ 2.2 The_Magician
+
+ A magician's major attribute is intelligence, which
+ enables the magician to cast spells. The number and variety
+ of spells increases as the magician gains experience and
+ intelligence. Other types of characters can cast spells,
+ but only if they manage to gain extraordinarily high
+ intelligence. Magic users are not as hearty as fighters;
+ they receive 1 to 8 extra hit points for every new
+ experience level.
+
+ 2.3 The_Cleric
+
+ A cleric has a high wisdom rating and can thus pray.
+ The number and variety of prayers which the gods are willing
+ to grant to a cleric increase as the cleric gains experience
+ and wisdom. Other character types can pray only if they
+ manage to gain extraordinary 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_Thief
+
+ A thief is exceptionally dextrous and has a good chance
+ to set a trap or rob a monster. Any type of character can
+ try to set a trap or steal from a monster standing next to
+ the character, but the chances of success are low compared
+ to a thief's chances.
+
+ 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.
+
+
+
+
+
+
+
+
+
+
+
+ - 3 -
+
+
+
+ 2.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.
+
+ 2.6 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. Magicians
+ receive new spells, and clerics receive new prayers.
+
+ Thieves have the lowest threshold for gaining
+ experience levels, followed by clerics. Fighters are next,
+ and magicians have the highest threshold.
+
+
+ 3. 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.
+
+ 3.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 -
+
+
+
+ 3.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.
+
+ _ 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
+
+
+
+
+
+
+
+
+
+
+
+
+ - 5 -
+
+
+
+ } 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 ('/').
+
+ 3.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 Encumbrance (Carry)
+
+ Intelligence, strength, wisdom, dexterity, and
+ constitution have a normal maximum of 25, but can be higher
+ when augmented by a ring. Encumbrance 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.
+
+
+
+
+
+
+
+
+
+
+
+ - 6 -
+
+
+
+ o How much gold (Au) the player is carrying.
+
+ 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 and
+ rings currently worn by the player. 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
+ 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.
+
+
+ 4. 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:
+
+
+
+
+
+
+
+
+
+
+
+
+ - 7 -
+
+
+
+ ? 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.
+
+ 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, followed by a directional 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.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - 8 -
+
+
+
+ z This command must be followed by a directional command.
+ Rogue then 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 or miscellaneous magic item from the
+ player's pack.
+
+ T Take off whatever the player is wearing.
+
+ P Put on a ring from the player's pack. The player can
+ wear a maximum of eight rings.
+
+ R Remove a ring from the player's hand.
+
+ ^U Uuse a miscellaneous magic item in the player's pack.
+
+ d Drop an item from the player's pack.
+
+ c When the player types this command, Rogue prompts for an
+ item from the player's pack and a one-line name. Rogue
+ then calls all similar items (such as all the blue
+ potions) by 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
+
+
+
+
+
+
+
+
+
+
+
+ - 9 -
+
+
+
+ the options or change any or all of them.
+
+ C This command, restricted to magicians and characters
+ with exceptionally high intelligence, produces a listing
+ of the magician's 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.
+
+ p This command, restricted to clerics and characters with
+ exceptionally high wisdom, produces a listing of the
+ cleric'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 characters
+ with exceptionally high wisdom and 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.
+
+ ^ This command sets a trap and is most likely to succeed
+ for a character with a high dexterity, such as a thief.
+ 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. It causes Rogue
+ to display all the gold on the current level.
+
+ D Dip something into a magic pool.
+
+ ^T This command is most likely to succeed for a character
+ with a high dexterity, such as a thief, and 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.
+
+
+
+
+
+
+
+
+
+
+
+
+ - 10 -
+
+
+
+ ^[ 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.
+
+
+ 5. 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.
+
+
+ 6. 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.
+
+
+ 7. 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
+
+
+
+
+
+
+
+
+
+
+
+ - 11 -
+
+
+
+ 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.
+
+
+ 8. 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.
+
+
+ 9. 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.
+
+
+ 10. 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.
+
+
+
+
+
+
+
+
+
+
+
+ - 12 -
+
+
+
+ 11. 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.
+
+
+ 12. 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 "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.
+
+
+ 13. 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.
+
+
+ 14. 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.
+
+
+ 15. 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.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - 13 -
+
+
+
+ 16. 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. These latter monsters 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.
+
+ 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.
+
+
+ 17. 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
+
+
+
+
+
+
+
+
+
+
+
+ - 14 -
+
+
+
+ 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.
+
+ name This string is the player's name and defaults to the
+ player's account name.
+
+ fruit This string identifies the player's favorite fruit,
+ sometimes encountered in the dungeon. It defaults to
+ slime-mold.
+
+ file This string, which defaults to rogue.save, specifies
+ the file to use for saving the game.
+
+ score This string identifies the top-ten 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.
+
+ 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,
+ fruit=pomegranate" would set the terse, jump, flush, and
+ askme Boolean options, clear the step Boolean option, set
+ the player's name to "Ivan the Terrible," set the player's
+ favorite fruit to a pomegranate, 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.
+
+
+ 18. 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
+
+
+
+
+
+
+
+
+
+
+
+ - 15 -
+
+
+
+ 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 ten 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.
+
+
+ 19. ACKNOWLEDGEMENTS
+ This version of Rogue is based on a version developed
+ at the University of California at Berkeley by Michael Toy
+ and Ken Arnold.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The Dungeons of Doom
+
+ AT&T Bell Laboratories
+ The Dungeons of Doom
+
+
+ ABSTRACT
+
+
+
+ Rogue was first introduced by Michael Toy 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.
+
+ The version of Rogue described in this guide has been
+ expanded to include over 110 monsters with many new capabil-
+ ities. 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 abili-
+ ties. Experience, rather than gold, decides the player's
+ score.
+
+
+
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/arogue58.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/arogue58.html Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,953 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+AT&T Bell Laboratories
+
+
+
+
+
+ Advanced Rogue
+ Copyright (C) 1984, 1985 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.
+
+ABSTRACT
+
+
+ Rogue was first introduced by Michael Toy 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.
+ 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.
+
+
+
+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 AND ATTRIBUTES
+
+ Before placing the player in the dungeon, the game requests the player to
+ select a character class: a fighter, a magic user, a cleric, or a thief.
+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 10 extra hit points for every new experience level.
+2.2 The Magician
+
+ A magician's major attribute is intelligence, which enables the magician to
+ cast spells. The number and variety of spells increases as the magician
+ gains experience and intelligence. Other types of characters can cast
+ spells, but only if they manage to gain extraordinarily high intelligence.
+ Magic users are not as hearty as fighters; they receive 1 to 8 extra hit
+ points for every new experience level.
+2.3 The Cleric
+
+ A cleric has a high wisdom rating and can thus pray. The number and variety
+ of prayers which the gods are willing to grant to a cleric increase as the
+ cleric gains experience and wisdom. Other character types can pray only if
+ they manage to gain extraordinary 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 Thief
+
+ A thief is exceptionally dextrous and has a good chance to set a trap or rob
+ a monster. Any type of character can try to set a trap or steal from a
+ monster standing next to the character, but the chances of success are low
+ compared to a thief's chances.
+
+
+ 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.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.
+2.6 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. Magicians receive new spells, and clerics receive new
+ prayers.
+
+ Thieves have the lowest threshold for gaining experience levels, followed by
+ clerics. Fighters are next, and magicians have the highest threshold.
+
+ 3. 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.
+3.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.
+
+
+ 3.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. |
+
+
+ _ |
+ |
+ 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 ('/'). |
+
+
+
+3.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)
+ -
+
Encumbrance (Carry)
+
+
+
+ Intelligence, strength, wisdom, dexterity, and constitution have a normal
+ maximum of 25, but can be higher when augmented by a ring. Encumbrance 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.
+ -
+
How much gold (Au) the player is carrying.
+ -
+
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 and rings currently worn by the
+ player. 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.
+
+
+4. 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. |
+
+
+ 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, followed by a directional 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 must be followed by a directional command. Rogue then
+ 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 or miscellaneous magic item from the player's pack. |
+
+
+ T |
+ |
+ Take off whatever the player is wearing. |
+
+
+ P |
+ |
+ Put on a ring from the player's pack. The player can wear a maximum
+ of eight rings. |
+
+
+ R |
+ |
+ Remove a ring from the player's hand. |
+
+
+ ^U |
+ |
+ Use a miscellaneous magic item in the player's pack. |
+
+
+ d |
+ |
+ Drop an item from the player's pack. |
+
+
+ c |
+ |
+ When the player types this command, Rogue prompts for an item from
+ the player's pack and a one-line name. Rogue then calls all similar
+ items (such as all the blue potions) by 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 characters with
+ exceptionally high intelligence, produces a listing of the magician's
+ 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. |
+
+
+ p |
+ |
+ This command, restricted to clerics and characters with
+ exceptionally high wisdom, produces a listing of the cleric'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 characters with
+ exceptionally high wisdom and 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. |
+
+
+ ^ |
+ |
+ This command sets a trap and is most likely to succeed for a
+ character with a high dexterity, such as a thief. 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. It causes Rogue to display
+ all the gold on the current level. |
+
+
+ D |
+ |
+ Dip something into a magic pool. |
+
+
+ ^T |
+ |
+ This command is most likely to succeed for a character
+ with a high dexterity, such as a thief, and 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. |
+
+
+
+5. 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.
+6. 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.
+7. 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.
+8. 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.
+9. 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.
+10. 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.
+11. 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.
+12. 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
+"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.
+13. 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.
+14. 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.
+15. 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.
+16. 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. These latter monsters 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.
+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.
+17. 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 type ahead
+ (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. |
+
+
+ name |
+ |
+ This string is the player's name and defaults to the player's
+ account name. |
+
+
+ fruit |
+ |
+ This string identifies the player's favorite fruit, sometimes
+ encountered in the dungeon. It defaults to slime-mold. |
+
+
+ file |
+ |
+ This string, which defaults to rogue.save, specifies the file to use
+ for saving the game. |
+
+
+ score |
+ |
+ This string identifies the top-ten 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. |
+
+
+
+
+ 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, fruit=pomegranate" would set the
+ terse, jump, flush, and askme Boolean options, clear the step Boolean
+ option, set the player's name to "Ivan the Terrible," set the player's
+ favorite fruit to a pomegranate, 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.
+18. 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 ten 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.
+19. ACKNOWLEDGEMENTS
+
+ This version of Rogue is based on a version developed at the University of
+ California at Berkeley by Michael Toy and Ken Arnold.
\ No newline at end of file
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/arogue58.sln
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/arogue58.sln Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,24 @@
+Microsoft Visual Studio Solution File, Format Version 7.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "arogue58", "arogue58.vcproj", "{2EEE53AB-A85A-4D4D-8DB2-B5F23513F415}"
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ ConfigName.0 = Debug
+ ConfigName.1 = Release
+ ConfigName.2 = test
+ EndGlobalSection
+ GlobalSection(ProjectDependencies) = postSolution
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {2EEE53AB-A85A-4D4D-8DB2-B5F23513F415}.Debug.ActiveCfg = Debug|Win32
+ {2EEE53AB-A85A-4D4D-8DB2-B5F23513F415}.Debug.Build.0 = Debug|Win32
+ {2EEE53AB-A85A-4D4D-8DB2-B5F23513F415}.Release.ActiveCfg = Release|Win32
+ {2EEE53AB-A85A-4D4D-8DB2-B5F23513F415}.Release.Build.0 = Release|Win32
+ {2EEE53AB-A85A-4D4D-8DB2-B5F23513F415}.test.ActiveCfg = Debug|Win32
+ {2EEE53AB-A85A-4D4D-8DB2-B5F23513F415}.test.Build.0 = Debug|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/arogue58.vcproj
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/arogue58.vcproj Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,305 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/chase.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/chase.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,1008 @@
+/*
+ * Code for one object to chase another
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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
+
+coord ch_ret; /* Where chasing takes you */
+
+
+
+
+
+/*
+ * 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) ||
+ (on(*tp, ISSLOW) && off(*tp, ISHASTE) && !(tp->t_turn)) ||
+ tp->t_no_move ||
+ (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 player (ee). If so, it returns the direction in which to shoot.
+ */
+
+coord *
+can_shoot(er, ee)
+register coord *er, *ee;
+{
+ static coord shoot_dir;
+
+ /* Make sure we are chasing the player */
+ if (!ce((*ee), hero)) return(NULL);
+
+ /*
+ * They must be in the same room or very close (at door)
+ */
+ if (roomin(er) != roomin(&hero) && 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). Returns TRUE if we want to keep on chasing later
+ * FALSE if we reach the goal.
+ */
+
+chase(tp, ee, flee, mdead)
+register struct thing *tp;
+register coord *ee;
+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
+ */
+bool *mdead;
+{
+ int damage, dist, thisdist, monst_dist = MAXINT;
+ struct linked_list *weapon;
+ register coord *er = &tp->t_pos;
+ coord *shoot_dir;
+ char ch, mch;
+ bool next_player = FALSE;
+
+ if (mdead != NULL)
+ *mdead = 0;
+
+ /*
+ * 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);
+
+ /*
+ * If the thing is confused or it can't see the player,
+ * let it move randomly.
+ */
+ if ((on(*tp, ISHUH) && rnd(10) < 8) ||
+ (on(player, ISINVIS) && off(*tp, CANSEE))) { /* Player is invisible */
+ /*
+ * get a valid random move
+ */
+ ch_ret = *rndmove(tp);
+ dist = DISTANCE(ch_ret.y, ch_ret.x, ee->y, ee->x);
+ /*
+ * check to see if random move takes creature away from player
+ * if it does then turn off ISHELD
+ */
+ 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);
+ }
+ }
+ }
+
+ /* If we can breathe, we may do so */
+ else if (on(*tp, CANBREATHE) &&
+ (dist < BOLT_LENGTH*BOLT_LENGTH) &&
+ (shoot_dir = can_shoot(er, ee)) &&
+ !on(player, ISINWALL) &&
+ (rnd(100) < 75)) {
+ register char *breath = NULL;
+
+ damage = tp->t_stats.s_hpt;
+ /* 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 */
+ *mdead = shoot_bolt( tp, *er, *shoot_dir, FALSE,
+ tp->t_index, breath, damage);
+
+ ch_ret = *er;
+ running = FALSE;
+ if (*mdead) return(TRUE);
+ }
+
+ /* We may shoot missiles if we can */
+ else if (on(*tp, CANMISSILE) &&
+ (shoot_dir = can_shoot(er, ee)) &&
+ !on(player, ISINWALL) &&
+ (rnd(100) < 75)) {
+ 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, shoot_dir->y, shoot_dir->x, tp);
+ hit_monster(unc(missile.o_pos), &missile, tp);
+ turn_off(*tp, CANMISSILE);
+ ch_ret = *er;
+ running = FALSE;
+ }
+
+ /* We may use a sonic blast if we can */
+ else if (on(*tp, CANSONIC) &&
+ (dist < BOLT_LENGTH*2) &&
+ (shoot_dir = can_shoot(er, ee)) &&
+ !on(player, ISINWALL) &&
+ (rnd(100) < 50)) {
+ static struct object blast =
+ {
+ MISSILE, {0, 0}, "", 0, "", "150" , NULL, 0, 0, 0, 0
+ };
+
+ turn_off(*tp, CANSONIC);
+ do_motion(&blast, shoot_dir->y, shoot_dir->x, tp);
+ damage = 150;
+ if (save(VS_BREATH, &player, -3))
+ damage /= 2;
+ msg ("The %s's sonic blast hits you", monsters[tp->t_index].m_name);
+ if ((pstats.s_hpt -= damage) <= 0)
+ death(tp->t_index);
+ ch_ret = *er;
+ running = FALSE;
+ }
+ /*
+ * If we have a special magic item, we might use it. We will restrict
+ * this options to uniques with relics for now.
+ */
+ else if (on(*tp, ISUNIQUE) && m_use_item(tp, er, ee)) {
+ ch_ret = *er;
+ running = FALSE;
+ }
+ /*
+ * If we can shoot or throw something, we might do so.
+ * If next to player, then 80% prob will fight.
+ */
+ else if(on(*tp, CANSHOOT) &&
+ (shoot_dir = can_shoot(er, ee)) &&
+ !on(player, ISINWALL) &&
+ (dist > 3 || (rnd(100) > 80)) &&
+ (weapon = get_hurl(tp))) {
+ missile(shoot_dir->y, shoot_dir->x, weapon, tp);
+ ch_ret = *er;
+ }
+
+ /*
+ * Otherwise, find the empty spot next to the chaser that is
+ * closest to the chasee.
+ */
+ else {
+ register int ey, ex, x, y;
+ register struct room *rer, *ree;
+ int dist_to_old = MININT; /* Dist from goal to old position */
+
+ /* Get rooms */
+ rer = roomin(er); /* Room the chasER (monster) is in */
+ ree = roomin(ee); /* Room the chasEE is in */
+
+ /*
+ * 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)) return(FALSE);
+
+ 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)) && 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 (step_ok(y, x, NOMONST, 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 &&
+ ce(hero, *ee)) {
+ /* 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)
+ */
+ if (next_player && off(*tp, WASTURNED) &&
+ ((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 */
+ ch_ret = hero;
+ return(FALSE);
+ }
+
+
+ /* 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)
+ ch_ret = *er;
+
+ /* 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;
+ }
+ }
+
+ /* May actually hit here from a confused move */
+ return(!ce(ch_ret, hero));
+}
+
+/*
+ * do_chase:
+ * Make one thing chase another.
+ */
+
+do_chase(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 */
+ *orig_rer, /* Original room of chaser */
+ *new_room; /* new room of monster */
+ int dist = MININT;
+ int mindist = MAXINT, maxdist = MININT;
+ bool stoprun = FALSE, /* TRUE means we are there */
+ rundoor; /* TRUE means run to a door */
+ bool mdead = 0;
+ char rch, sch;
+ coord *last_door=0, /* Door we just came from */
+ this; /* Temporary destination for chaser */
+
+ /* Make sure the monster can move */
+ if (th->t_no_move != 0) {
+ th->t_no_move--;
+ return;
+ }
+
+ rer = roomin(&th->t_pos); /* Find room of chaser */
+ ree = roomin(th->t_dest); /* Find room of chasee */
+ orig_rer = rer; /* Original room of chaser (including doors) */
+
+ /*
+ * We don't count monsters on doors as inside rooms for this routine
+ */
+ if ((sch = CCHAR( mvwinch(stdscr, th->t_pos.y, th->t_pos.x) )) == DOOR ||
+ sch == PASSAGE) {
+ rer = NULL;
+ }
+ this = *th->t_dest;
+
+ /*
+ * If we are not in a corridor and not a Xorn, then if we are running
+ * after the player, we run to a door if he is not in the same room.
+ * If we are fleeing, we run to a door if he IS in the same room.
+ * Note: We don't bother with doors in mazes.
+ */
+ if (levtype != MAZELEV && rer != NULL && 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 */
+ 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, hero))) { /* Player should not
+ * be at door if we are
+ * running away
+ */
+ 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 the player and
+ * he is standing on it
+ */
+ if (flee && ce(*exit, hero)) 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 */
+
+ /*
+ * this now contains what we want to run to this time
+ * so we run to it. If we hit it we either want to fight it
+ * or stop running
+ */
+ if (!chase(th, &this, flee, &mdead)) {
+ if (ce(ch_ret, hero)) {
+ /* merchants try to sell something --> others attack */
+ if (on(*th, CANSELL)) sell(th);
+ else attack(th, NULL, FALSE);
+ return;
+ }
+ else if (on(*th, NOMOVE))
+ stoprun = TRUE;
+ }
+
+ if (mdead) return; /* Did monster kill someone? */
+
+ if (on(*th, NOMOVE)) return;
+
+ /* If we have a scavenger, it can pick something up */
+ if (on(*th, ISSCAVENGE)) {
+ register struct linked_list *n_item, *o_item;
+
+ while ((n_item = find_obj(ch_ret.y, ch_ret.x)) != NULL) {
+ char floor = (roomin(&ch_ret) == NULL) ? PASSAGE : FLOOR;
+ register struct object *n_obj, *o_obj;
+
+ /*
+ * see if he's got one of this group already
+ */
+ o_item = NULL;
+ n_obj = OBJPTR(n_item);
+ detach(lvl_obj, n_item);
+ 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 (cansee(ch_ret.y, ch_ret.x))
+ mvwaddch(cw, ch_ret.y, ch_ret.x, floor);
+ mvaddch(ch_ret.y, ch_ret.x, floor);
+ }
+ }
+
+ mvwaddch(cw, th->t_pos.y, th->t_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 */
+
+ /* Get new room of monster */
+ new_room=roomin(&ch_ret);
+
+ /* 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(th->t_pos.y, th->t_pos.x))
+ light(&th->t_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 == ree && 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 (rer != NULL && !lit_room(orig_rer) && sch == FLOOR &&
+ DISTANCE(ch_ret.y, ch_ret.x, th->t_pos.y, th->t_pos.x) < 3 &&
+ off(player, ISBLIND))
+ th->t_oldch = ' ';
+ else
+ */
+ 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);
+
+ /*
+ * 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);
+
+ /* Record monster's last position (if new one is different) */
+ if (!ce(ch_ret, th->t_pos)) th->t_oldpos = th->t_pos;
+ th->t_pos = ch_ret; /* Mark the monster's new position */
+
+ /* 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);
+ }
+
+
+ /*
+ * And stop running if need be
+ */
+ if (stoprun && ce(th->t_pos, *(th->t_dest)))
+ turn_off(*th, ISRUN);
+}
+
+
+/*
+ * 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, *bolt, *rock;
+ register struct linked_list *pitem;
+ bool bow=FALSE, crossbow=FALSE, sling=FALSE;
+
+ arrow = bolt = rock = NULL; /* Don't point to anything to begin with */
+ for (pitem=tp->t_pack; pitem; pitem=next(pitem))
+ if ((OBJPTR(pitem))->o_type == WEAPON)
+ switch ((OBJPTR(pitem))->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;
+ }
+
+ /* Use crossbow bolt if possible */
+ if (crossbow && bolt) return(bolt);
+ if (bow && arrow) return(arrow);
+ if (sling && rock) return(rock);
+ return(NULL);
+}
+
+/*
+ * runners:
+ * Make all the running monsters move.
+ */
+
+runners()
+{
+ register struct linked_list *item;
+ register struct thing *tp = NULL;
+
+ /*
+ * 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 (on(*tp, ISHELD) && rnd(tp->t_stats.s_lvl) > 11) {
+ turn_off(*tp, ISHELD);
+ turn_on(*tp, ISRUN);
+ turn_off(*tp, ISDISGUISE);
+ tp->t_dest = &hero;
+ if (tp->t_stats.s_hpt < tp->maxstats.s_hpt)
+ turn_on(*tp, ISFLEE);
+ if (cansee(tp->t_pos.y, tp->t_pos.x))
+ msg("The %s breaks free from the hold spell",
+ monsters[tp->t_index].m_name);
+ }
+ if (off(*tp, ISHELD) && on(*tp, ISRUN)) {
+ register bool flee;
+
+ /* Should monster run away? */
+ flee = on(*tp, ISFLEE) ||
+ ((tp->t_dest == &hero) && on(player, ISINWALL) &&
+ off(*tp, CANINWALL));
+
+ if (off(*tp, ISSLOW) || tp->t_turn) {
+ doctor(tp);
+ do_chase(tp, flee);
+ }
+ if (off(*tp, ISDEAD) && off(*tp, ISELSEWHERE) && on(*tp, ISHASTE)) {
+ doctor(tp);
+ do_chase(tp, flee);
+ }
+ if (off(*tp, ISDEAD) && off(*tp, ISELSEWHERE)) {
+ tp->t_turn ^= TRUE;
+ tp->t_wasshot = FALSE; /* Not shot anymore */
+ }
+ }
+ }
+}
+
+/*
+ * runto:
+ * Set a monster running after something
+ */
+
+runto(runner, spot)
+register struct thing *runner;
+coord *spot;
+{
+ /*
+ * 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 player */
+ 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 0ef99244acb8 -r 0ed67132cf10 arogue5/command.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/command.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,938 @@
+/*
+ * Read and execute the user commands
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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
+#include
+#include "mach_dep.h"
+#include "rogue.h"
+
+/*
+ * command:
+ * Process the user commands
+ */
+
+command()
+{
+ register char ch;
+ register int ntimes = 1; /* Number of player moves */
+ static char countch, direction, newcount = FALSE;
+ struct linked_list *item;
+ bool an_after = FALSE;
+
+ if (on(player, ISHASTE)) {
+ ntimes++;
+ turns--; /* correct for later */
+ }
+ if (on(player, ISSLOW) || on(player, ISDANCE)) {
+ if (player.t_turn != TRUE) {
+ ntimes--;
+ turns++;
+ an_after = TRUE;
+ }
+ player.t_turn ^= TRUE;
+ }
+
+ /*
+ * Let the daemons start up
+ */
+ do_daemons(BEFORE);
+ do_fuses(BEFORE);
+ while (ntimes-- > 0)
+ {
+ /* One more tick of the clock. */
+ if ((++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);
+ }
+
+ look(after, FALSE);
+ if (!running) door_stop = FALSE;
+ lastscore = purse;
+ wmove(cw, hero.y, hero.x);
+ if (!((running || count) && jump)) {
+ status(FALSE);
+ wmove(cw, hero.y, hero.x);
+ draw(cw); /* Draw screen */
+ }
+ take = 0;
+ after = TRUE;
+ /*
+ * Read command or continue run
+ */
+ if (!no_command)
+ {
+ if (running) {
+ /* If in a corridor or maze, if we are at a turn with only one
+ * way to go, turn that way.
+ */
+ if ((winat(hero.y, hero.x) == PASSAGE || 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("");
+ }
+ }
+ else ch = '.';
+ if (no_command)
+ {
+ if (--no_command == 0)
+ msg("You can move again.");
+ }
+ else
+ {
+ /*
+ * 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 'q': case 'r': case 's': case 'f':
+ case 't': case 'C': case 'I': case '.':
+ case 'z': case 'p':
+ 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 't':
+ if((item=get_item(pack,"throw", ALL)) != NULL && get_dir())
+ missile(delta.y, delta.x, item, &player);
+ else
+ after = FALSE;
+ when 'Q' : after = FALSE; quit(-1);
+ when 'i' : after = FALSE; inventory(pack, ALL);
+ when 'I' : after = FALSE; picky_inven();
+ when 'd' : drop(NULL);
+ when 'P' : grab(hero.y, hero.x);
+ when 'q' : quaff(-1, NULL, TRUE);
+ when 'r' : read_scroll(-1, NULL, TRUE);
+ when 'e' : eat();
+ when 'w' : wield();
+ when 'W' : wear();
+ when 'T' : take_off();
+ when 'o' : option();
+ when 'c' : call(FALSE);
+ when 'm' : call(TRUE);
+ when '>' : after = FALSE; d_level();
+ when '<' : after = FALSE; u_level();
+ when '?' : after = FALSE; help();
+ when '/' : after = FALSE; identify();
+ when CTRL('U') : use_mm(-1);
+ when CTRL('T') :
+ if (get_dir()) steal();
+ else after = FALSE;
+ when 'D' : dip_it();
+ when 'G' : gsense();
+ when '^' : set_trap(&player, hero.y, hero.x);
+ when 's' : search(FALSE, FALSE);
+ when 'z' : if (!do_zap(TRUE, NULL, FALSE))
+ after=FALSE;
+ when 'p' : pray();
+ when 'C' : cast();
+ when 'a' :
+ if (get_dir())
+ affect();
+ else after = FALSE;
+ 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();
+ printf("\n");
+ exit(0);
+ }
+ when '.' : ; /* Rest command */
+ 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') : sprintf(outstring,"food left: %d\tfood level: %d",
+ food_left, foodlev);
+ msg(outstring);
+ when CTRL('A') : activity();
+ when CTRL('C') :
+ {
+ int tlev;
+ prbuf[0] = '\0';
+ msg("Which level? ");
+ if(get_str(prbuf,cw) == 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('N') :
+ {
+ if ((item=get_item(pack, "charge", STICK)) != NULL){
+ (OBJPTR(item))->o_charges=10000;
+ }
+ }
+ when CTRL('H') :
+ {
+ register int i;
+ register struct object *obj;
+
+ for (i = 0; i < 9; i++)
+ raise_level(TRUE);
+ /*
+ * 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);
+ cur_weapon->o_flags |= (ISKNOW | ISPROT);
+ }
+ /*
+ * And his suit of armor
+ */
+ if (player.t_ctype == C_THIEF)
+ item = spec_item(ARMOR, STUDDED_LEATHER, 10, 0);
+ else
+ item = spec_item(ARMOR, PLATE_ARMOR, 7, 0);
+ obj = OBJPTR(item);
+ 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;
+ }
+ }
+ /*
+ * turn off flags if no longer needed
+ */
+ if (!running)
+ door_stop = FALSE;
+ }
+ /*
+ * If he ran into something to take, let him pick it up.
+ * unless its a trading post
+ */
+ if (auto_pickup && take != 0 && levtype != POSTLEV)
+ pick_up(take);
+ if (!running)
+ door_stop = FALSE;
+
+ /* If after is true, mark an_after as true so that if
+ * we are hasted, the first "after" will be noted.
+ * if after is FALSE then stay in this loop
+ */
+ if (after) an_after = TRUE;
+ else ntimes++;
+ }
+
+ /*
+ * Kick off the rest if the daemons and fuses
+ */
+ if (an_after)
+ {
+ /*
+ * If player is infested, take off a hit point
+ */
+ if (on(player, HASINFEST)) {
+ if ((pstats.s_hpt -= infest_dam) <= 0) death(D_INFESTATION);
+ }
+ /*
+ * 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);
+ if (!((running || count) && jump)) look(FALSE, FALSE);
+
+
+ }
+ t_free_list(monst_dead);
+}
+
+/*
+ * quit:
+ * Have player make certain, then exit.
+ */
+
+void
+quit(int sig)
+{
+ NOOP(sig);
+
+ /*
+ * Reset the signal in case we got here via an interrupt
+ */
+ if (signal(SIGINT, &quit) != &quit)
+ mpos = 0;
+ msg("Really quit? ");
+ draw(cw);
+ if (readchar() == 'y')
+ {
+ clear();
+ move(LINES-1, 0);
+ draw(stdscr);
+ score(pstats.s_exp + (long) purse, CHICKEN, 0);
+ 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 && CCHAR(mvwinch(cw, y, x)) == mch)
+ mp->t_oldch = ch; /* Will change when monst moves */
+ else mvwaddch(cw, y, x, ch);
+
+ count = 0;
+ running = FALSE;
+ msg(tr_name(tp->tr_type));
+ }
+ else if (ch == SECRETDOOR) {
+ if (door_chime == TRUE || (!is_thief && rnd(100) < 20)) {
+ /* 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;
+ }
+ }
+ }
+}
+
+
+/*
+ * 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(cw, 0, 0);
+ while (strp->h_ch) {
+ if (strp->h_ch == helpch) {
+ sprintf(outstring,"%s%s", unctrl(strp->h_ch), strp->h_desc);
+ msg(outstring);
+ return;
+ }
+ strp++;
+ }
+#ifdef WIZARD
+ if (wizard) {
+ while (wizp->h_ch) {
+ if (wizp->h_ch == helpch) {
+ sprintf(outstring,"%s%s", unctrl(wizp->h_ch), wizp->h_desc);
+ msg(outstring);
+ 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(hw,' ');
+ 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(hw,' ');
+ wclear(hw);
+ cnt = 0;
+ }
+ }
+ }
+#endif
+ wmove(hw, LINES-1, 0);
+ wprintw(hw, spacemsg);
+ draw(hw);
+ wait_for(hw,' ');
+ wclear(hw);
+ draw(hw);
+ wmove(cw, 0, 0);
+ wclrtoeol(cw);
+ status(FALSE);
+ touchwin(cw);
+}
+/*
+ * identify:
+ * Tell the player what a certain thing is.
+ */
+
+identify()
+{
+ register char ch;
+ const char *str;
+
+ 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";
+ }
+ sprintf(outstring,"'%s' : %s", unctrl(ch), str);
+ msg(outstring);
+}
+
+/*
+ * d_level:
+ * He wants to go down a level
+ */
+
+d_level()
+{
+ bool no_phase=FALSE;
+
+
+ /* If we are at a top-level trading post, we probably can't go down */
+ if (levtype == POSTLEV && level == 0 && rnd(100) < 80) {
+ 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()
+{
+ /*
+ * Set the terminal back to original mode
+ */
+ wclear(hw);
+ wmove(hw, LINES-1, 0);
+ draw(hw);
+ endwin();
+ in_shell = TRUE;
+ fflush(stdout);
+
+ md_shellescape();
+
+ printf(retstr);
+ fflush(stdout);
+ noecho();
+ raw();
+ keypad(cw,1);
+ in_shell = FALSE;
+ wait_for(hw,'\n');
+ clearok(cw, TRUE);
+ touchwin(cw);
+ wmove(cw,0,0);
+ draw(cw);
+}
+
+/*
+ * allow a user to call a potion, scroll, or ring something
+ */
+call(mark)
+bool mark;
+{
+ register struct object *obj;
+ register struct linked_list *item;
+ register char **guess = NULL, *elsewise = NULL;
+ register bool *know;
+
+ if (mark) item = get_item(pack, "mark", ALL);
+ else item = get_item(pack, "call", CALLABLE);
+ /*
+ * Make certain that it is somethings that we want to wear
+ */
+ if (item == NULL)
+ return;
+ 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 {
+ addmsg(terse ? "C" : "Was c");
+ msg("alled \"%s\"", elsewise);
+ msg(terse ? "Call it: " : "What do you want to call it? ");
+ if (guess[obj->o_which] != NULL)
+ free(guess[obj->o_which]);
+ strcpy(prbuf, elsewise);
+ }
+ if (get_str(prbuf, cw) == NORM) {
+ if (mark) {
+ strncpy(obj->o_mark, prbuf, MARKLEN-1);
+ obj->o_mark[MARKLEN-1] = '\0';
+ }
+ else {
+ guess[obj->o_which] = new((unsigned int) strlen(prbuf) + 1);
+ strcpy(guess[obj->o_which], prbuf);
+ }
+ }
+}
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/daemon.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/daemon.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,244 @@
+/*
+ * Contains functions for dealing with things that happen in the future.
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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 EMPTY 0
+#define DAEMON -1
+
+#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_func != NULL && 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()
+{
+ sprintf(outstring,"Daemons = %d : Fuses = %d : Memory Items = %d : Memory Used = %d",
+ demoncnt,fusecnt,total,md_memused());
+ msg(outstring);
+}
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/daemons.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/daemons.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,487 @@
+/*
+ * All the daemon and fuse functions are in here
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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"
+
+int between = 0;
+
+/*
+ * 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:
+ limit = 8 - curp->s_lvl;
+ new_points = curp->s_lvl - 2;
+ when C_CLERIC:
+ limit = 8 - curp->s_lvl;
+ new_points = curp->s_lvl - 3;
+ when C_FIGHTER:
+ 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
+ */
+
+rollwand()
+{
+ if (++between >= 4)
+ {
+ /* Theives may not awaken a monster */
+ if ((roll(1, 6) == 4) &&
+ ((player.t_ctype != C_THIEF) || (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
+ */
+
+res_strength()
+{
+
+ /* 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;
+ }
+
+ /* Otherwise, put player at the maximum strength */
+ else {
+ pstats.s_str = max_stats.s_str + ring_value(R_ADDSTR);
+ }
+
+ updpack(TRUE);
+}
+
+/*
+ * 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;
+
+ old_hunger = hungry_state;
+ if (food_left <= 0)
+ {
+ /*
+ * the hero is fainting
+ */
+ if (no_command || rnd(100) > 20)
+ return;
+ no_command = rnd(8)+4;
+ if (!terse)
+ addmsg("You feel too weak from lack of food. ");
+ msg("You faint");
+ running = FALSE;
+ 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;
+ 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;
+ }
+
+ }
+ if (old_hunger != hungry_state)
+ updpack(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");
+}
+
+/*
+ * daemon for adding back dexterity
+ */
+un_itch()
+{
+ if (--lost_dext < 1) {
+ lost_dext = 0;
+ turn_off(player, HASITCH);
+ }
+ res_dexterity(1);
+}
+/*
+ * 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 = NULL;
+ 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(9)) {
+ 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;
+ }
+}
+/*
+ * 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_type!=RELIC && rnd(100)<3) {
+ for (item = pack; item != NULL; item = next(item)) {
+ if (OBJPTR(item) == cur_weapon)
+ break;
+ }
+ if (item != NULL) {
+ drop(item);
+ running = FALSE;
+ }
+ }
+}
+/*
+ * 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();
+}
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/encumb.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/encumb.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,175 @@
+/*
+ * Stuff to do with encumberence
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+ * All rights reserved.
+ *
+ * Based on "Super-Rogue"
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "curses.h"
+#include "rogue.h"
+
+/*
+ * updpack:
+ * Update his pack weight and adjust fooduse accordingly
+ */
+updpack(getmax)
+int getmax;
+{
+
+ reg int topcarry, curcarry;
+
+ if (getmax)
+ pstats.s_carry = totalenc(); /* get total encumb */
+ curcarry = packweight(); /* get pack weight */
+ topcarry = pstats.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 */
+ pstats.s_pack = curcarry; /* update pack weight */
+}
+
+
+/*
+ * packweight:
+ * Get the total weight of the hero's pack
+ */
+packweight()
+{
+ reg struct object *obj;
+ reg struct linked_list *pc;
+ reg int weight;
+
+ weight = 0;
+ for(pc = pack ; pc != NULL ; pc = next(pc)) {
+ obj = OBJPTR(pc);
+ weight += itemweight(obj);
+ }
+ if(weight < 0) /* in case of amulet */
+ weight = 0;
+ if(ISWEARING(R_HEAVY))
+ weight += 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()
+{
+ return ((str_compute()-8)*50);
+}
+
+
+/*
+ * totalenc:
+ * Get total weight that the hero can carry
+ */
+totalenc()
+{
+ reg int wtotal;
+
+ wtotal = NORMENCB + playenc();
+ switch(hungry_state) {
+ 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 == FALSE) {
+ 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 0ef99244acb8 -r 0ed67132cf10 arogue5/fight.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/fight.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,1579 @@
+/*
+ * All the fighting gets done here
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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
+#include "rogue.h"
+
+#define CONF_DAMAGE -1
+#define PARAL_DAMAGE -2
+#define DEST_DAMAGE -3
+
+static const struct matrix att_mat[5] = {
+/* Base Max_lvl, Factor, Offset, Range */
+{ 10, 25, 2, 1, 2 },
+{ 9, 18, 2, 1, 5 },
+{ 10, 19, 2, 1, 3 },
+{ 10, 21, 2, 1, 4 },
+{ 7, 25, 1, 0, 2 }
+};
+
+/*
+ * 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 back_stab = FALSE;
+
+ /*
+ * 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.
+ */
+ player.t_quiet = 0;
+ tp->t_quiet = 0;
+
+ /*
+ * if its in the wall, we can't hit it
+ */
+ if (on(*tp, ISINWALL) && off(player, CANINWALL))
+ return(FALSE);
+
+ /*
+ * 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))
+ {
+ msg("Wait! That's a %s!", monsters[tp->t_index].m_name);
+ turn_off(*tp, ISDISGUISE);
+ did_hit = thrown;
+ }
+ if (on(*tp, CANSURPRISE) && off(player, ISBLIND) && !ISWEARING(R_ALERT)) {
+ msg("Wait! There's a %s!", monsters[tp->t_index].m_name);
+ turn_off(*tp, CANSURPRISE);
+ did_hit = thrown;
+ }
+ /*
+ * if he's a thief and the creature is asleep then he gets a chance
+ * for a backstab
+ */
+ if (player.t_ctype == C_THIEF &&
+ (!on(*tp, ISRUN) || on(*tp, ISHELD) || tp->t_no_move > 0)&&
+ !on(*tp, NOSTAB))
+ back_stab = TRUE;
+
+ runto(tp, &hero);
+
+ if (did_hit)
+ {
+ register const char *mname;
+
+ did_hit = FALSE;
+ mname = (on(player, ISBLIND)) ? "it" : monsters[tp->t_index].m_name;
+ if (!can_blink(tp) &&
+ ( ((weap != NULL) && (weap->o_type == RELIC)) ||
+ ((off(*tp, MAGICHIT) || ((weap != NULL) && (weap->o_hplus > 0 || weap->o_dplus > 0)) ) &&
+ (off(*tp, BMAGICHIT) || ((weap != NULL) && (weap->o_hplus > 1 || weap->o_dplus > 1)) ) &&
+ (off(*tp, CMAGICHIT) || ((weap != NULL) && (weap->o_hplus > 2 || weap->o_dplus > 2)) ) ) )
+ && 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) {
+ sprintf(outstring,"Your %s passes right through the %s!",
+ weaps[weap->o_which].w_name, mname);
+ msg(outstring);
+ }
+ else if (thrown) {
+ tp->t_wasshot = TRUE;
+ thunk(weap, tp, mname);
+ }
+ else
+ hit(weap, tp, NULL, mname, back_stab);
+
+ /* If the player hit a rust monster, he better have a + weapon */
+ if (on(*tp, CANRUST) && !thrown && (weap != NULL) &&
+ weap->o_type != RELIC &&
+ (weap->o_flags & ISMETAL) &&
+ !(weap->o_flags & ISPROT) &&
+ (weap->o_hplus < 1) && (weap->o_dplus < 1)) {
+ if (rnd(100) < 50) weap->o_hplus--;
+ else weap->o_dplus--;
+ msg(terse ? "Your %s weakens!"
+ : "Your %s appears to be weaker now!",
+ weaps[weap->o_which].w_name);
+ }
+
+ /* If the player hit something that shrieks, wake the dungeon */
+ if (on(*tp, CANSHRIEK)) {
+ turn_off(*tp, CANSHRIEK);
+ msg("The %s emits a piercing shriek.", mname);
+ aggravate();
+ }
+
+ /* If the player hit something that can surprise, it can't now */
+ if (on(*tp, CANSURPRISE)) turn_off(*tp, CANSURPRISE);
+
+
+ /*
+ * Can the player confuse?
+ */
+ if (on(player, CANHUH) && !thrown) {
+ msg("Your hands stop glowing red");
+ msg("The %s appears confused.", mname);
+ turn_on(*tp, ISHUH);
+ turn_off(player, CANHUH);
+ }
+ /*
+ * does the creature explode when hit?
+ */
+ if (on(*tp, CANEXPLODE))
+ explode(tp);
+
+ /*
+ * Merchants just disappear if hit
+ */
+ if (on(*tp, CANSELL)) {
+ msg("The %s disappears with his wares in a flash.",mname);
+ killed(item, FALSE, FALSE);
+ }
+
+ else if (tp->t_stats.s_hpt <= 0)
+ killed(item, TRUE, TRUE);
+
+ /* If the monster is fairly intelligent and about to die, it
+ * may turn tail and run.
+ */
+ else 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);
+ }
+ }
+ else {
+ if (thrown)
+ bounce(weap, tp, mname);
+ else
+ miss(weap, tp, NULL, mname);
+ }
+ }
+ 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 const char *mname;
+ register bool did_hit = FALSE;
+ register struct object *wielded; /* The wielded weapon */
+
+ /*
+ * Since this is an attack, stop running and any healing that was
+ * going on at the time.
+ */
+ running = FALSE;
+ player.t_quiet = 0;
+ mp->t_quiet = 0;
+
+ if (on(*mp, ISDISGUISE) && off(player, ISBLIND))
+ turn_off(*mp, ISDISGUISE);
+ mname = on(player, ISBLIND) ? "it" : monsters[mp->t_index].m_name;
+
+ /*
+ * 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.
+ */
+ wielded = wield_weap(weapon, mp);
+ if (weapon == NULL) weapon = wielded;
+
+ if (roll_em(mp, &player, weapon, thrown, wielded, FALSE)) {
+ did_hit = TRUE;
+
+ if (thrown) m_thunk(weapon, mp, mname);
+ else hit(weapon, mp, mname, NULL, FALSE);
+
+ if (pstats.s_hpt <= 0)
+ death(mp->t_index); /* Bye bye life ... */
+
+ /*
+ * suprising monsters appear after they shoot at you
+ */
+ if (thrown) {
+ if (on(*mp, CANSURPRISE))
+ turn_off(*mp, CANSURPRISE);
+ }
+ if (!thrown) {
+ /*
+ * If a vampire hits, it may take half your hit points
+ */
+ if (on(*mp, CANSUCK) && !save(VS_MAGIC, &player, 0)) {
+ if (pstats.s_hpt == 1) death(mp->t_index);
+ else {
+ pstats.s_hpt /= 2;
+ msg("You feel your life force being drawn from you.");
+ }
+ }
+
+ /*
+ * Stinking monsters make player weaker (to hit)
+ */
+ if (on(*mp, CANSTINK)) {
+ turn_off(*mp, CANSTINK);
+ if (!save(VS_POISON, &player, 0)) {
+ msg("The stench of the %s sickens you.", mname);
+ if (on(player, HASSTINK)) lengthen(unstink, STINKTIME);
+ else {
+ turn_on(player, HASSTINK);
+ fuse(unstink, 0, STINKTIME, AFTER);
+ }
+ }
+ }
+
+ /*
+ * Chilling monster reduces strength each time
+ */
+ if (on(*mp, CANCHILL)) {
+ if (!ISWEARING(R_SUSABILITY) && !save(VS_POISON, &player, 0)) {
+ msg("You cringe at the %s's chilling touch.", mname);
+ chg_str(-1);
+ if (lost_str++ == 0)
+ fuse(res_strength, 0, CHILLTIME, AFTER);
+ else lengthen(res_strength, CHILLTIME);
+ }
+ }
+
+ /*
+ * itching monsters reduce dexterity (temporarily)
+ */
+ if (on(*mp, CANITCH) && !save(VS_POISON, &player, 0)) {
+ msg("The claws of the %s scratch you", mname);
+ if(ISWEARING(R_SUSABILITY)) {
+ msg("The scratch has no effect");
+ }
+ else {
+ turn_on(player, HASITCH);
+ add_dexterity(TRUE);
+ lost_dext++;
+ fuse(un_itch, 0, roll(HEALTIME,SICKTIME), AFTER);
+ }
+ }
+
+
+ /*
+ * If a hugging monster hits, it may SQUEEEEEEEZE
+ */
+ if (on(*mp, CANHUG)) {
+ if (roll(1,20) >= 18 || roll(1,20) >= 18) {
+ msg("The %s squeezes you against itself.", mname);
+ if ((pstats.s_hpt -= roll(2,8)) <= 0)
+ death(mp->t_index);
+ }
+ }
+
+ /*
+ * If a disease-carrying monster hits, there is a chance the
+ * player will catch the disease
+ */
+ if (on(*mp, CANDISEASE) &&
+ (rnd(pstats.s_const) < mp->t_stats.s_lvl) &&
+ off(player, HASDISEASE)) {
+ if (ISWEARING(R_HEALTH)) msg("The wound heals quickly.");
+ else {
+ turn_on(player, HASDISEASE);
+ fuse(cure_disease, 0, roll(HEALTIME,SICKTIME), AFTER);
+ msg(terse ? "You have been diseased."
+ : "You have contracted a disease!");
+ }
+ }
+
+ /*
+ * If a rust monster hits, you lose armor
+ */
+ if (on(*mp, 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 < pstats.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
+ */
+ if (on(*mp, 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 < pstats.s_arm+1) {
+ msg(terse ? "Your armor dissolves"
+ : "Your armor appears to dissolve. Oh my!");
+ cur_armor->o_ac++;
+ }
+
+ /* If a surprising monster hit you, you can see it now */
+ if (on(*mp, CANSURPRISE)) turn_off(*mp, CANSURPRISE);
+
+ /*
+ * If an infesting monster hits you, you get a parasite or rot
+ */
+ if (on(*mp, CANINFEST) && rnd(pstats.s_const) < mp->t_stats.s_lvl) {
+ if (ISWEARING(R_HEALTH)) msg("The wound quickly heals.");
+ else {
+ turn_off(*mp, CANINFEST);
+ msg(terse ? "You have been infested."
+ : "You have contracted a parasitic infestation!");
+ infest_dam++;
+ turn_on(player, HASINFEST);
+ }
+ }
+
+ /*
+ * Ants have poisonous bites
+ */
+ if (on(*mp, CANPOISON) && !save(VS_POISON, &player, 0)) {
+ 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");
+ }
+ }
+ /*
+ * does it take wisdom away?
+ */
+ if (on(*mp, TAKEWISDOM) &&
+ !save(VS_MAGIC, &player, 0) &&
+ !ISWEARING(R_SUSABILITY)) {
+ add_wisdom(TRUE);
+ }
+ /*
+ * does it take intelligence away?
+ */
+ if (on(*mp, TAKEINTEL) &&
+ !save(VS_MAGIC, &player, 0) &&
+ !ISWEARING(R_SUSABILITY)) {
+ add_intelligence(TRUE);
+ }
+ /*
+ * Cause fear by touching
+ */
+ if (on(*mp, TOUCHFEAR)) {
+ turn_off(*mp, TOUCHFEAR);
+ if (!ISWEARING(R_HEROISM) &&
+ !save(VS_WAND, &player, 0) &&
+ !(on(player, ISFLEE) && (player.t_dest == &mp->t_pos))) {
+ turn_on(player, ISFLEE);
+ player.t_dest = &mp->t_pos;
+ msg("The %s's touch terrifies you.", mname);
+ }
+ }
+
+ /*
+ * make the hero dance (as in otto's irresistable dance)
+ */
+ if (on(*mp, CANDANCE) &&
+ !on(player, ISDANCE) &&
+ !save(VS_MAGIC, &player, -4)) {
+ turn_off(*mp, CANDANCE);
+ turn_on(player, ISDANCE);
+ msg("You begin to dance uncontrollably!");
+ fuse(undance, 0, roll(2,4), AFTER);
+ }
+
+ /*
+ * Suffocating our hero
+ */
+ if (on(*mp, CANSUFFOCATE) && (rnd(100) < 15) &&
+ (find_slot(suffocate) == FALSE)) {
+ turn_on(*mp, DIDSUFFOCATE);
+ msg("The %s is beginning to suffocate you.", mname);
+ fuse(suffocate, 0, roll(4,2), AFTER);
+ }
+
+ /*
+ * Turning to stone
+ */
+ if (on(*mp, TOUCHSTONE)) {
+ turn_off(*mp, TOUCHSTONE);
+ if (on(player, CANINWALL))
+ msg("The %s's touch has no effect.", mname);
+ else {
+ if (!save(VS_PETRIFICATION, &player, 0) && rnd(100) < 15) {
+ msg("Your body begins to solidify.");
+ msg("You are turned to stone !!! --More--");
+ wait_for(cw,' ');
+ death(D_PETRIFY);
+ }
+ else {
+ msg("The %s's touch stiffens your limbs.", mname);
+ no_command += STONETIME;
+ }
+ }
+ }
+
+ /*
+ * Wraiths might drain energy levels
+ */
+ if ((on(*mp, CANDRAIN) || on(*mp, DOUBLEDRAIN)) && rnd(100) < 15) {
+ lower_level(mp->t_index);
+ if (on(*mp, DOUBLEDRAIN)) lower_level(mp->t_index);
+ turn_on(*mp, DIDDRAIN);
+ }
+
+ /*
+ * Violet fungi stops the poor guy from moving
+ */
+ if (on(*mp, CANHOLD) && off(*mp, DIDHOLD)) {
+ turn_on(player, ISHELD);
+ turn_on(*mp, DIDHOLD);
+ hold_count++;
+ }
+
+ /*
+ * Sucker will suck blood and run
+ */
+ if (on(*mp, CANDRAW)) {
+ turn_off(*mp, CANDRAW);
+ turn_on(*mp, ISFLEE);
+ msg("The %s sates itself with your blood.", mname);
+ if ((pstats.s_hpt -= 12) <= 0) death(mp->t_index);
+ }
+
+ /*
+ * Bad smell will force a reduction in strength
+ */
+ if (on(*mp, CANSMELL)) {
+ turn_off(*mp, CANSMELL);
+ if (save(VS_MAGIC, &player, 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);
+ }
+ }
+
+ /*
+ * Paralyzation
+ */
+ if (on(*mp, CANPARALYZE)) {
+ turn_off(*mp, CANPARALYZE);
+ if (!save(VS_PARALYZATION, &player, 0)) {
+ if (on(player, CANINWALL))
+ msg("The %s's touch has no effect.", mname);
+ else {
+ msg("The %s's touch paralyzes you.", mname);
+ no_command += FREEZETIME;
+ }
+ }
+ }
+
+ /*
+ * Painful wounds make you faint
+ */
+ if (on(*mp, CANPAIN)) {
+ turn_off(*mp, CANPAIN);
+ if (!ISWEARING(R_ALERT) && !save(VS_POISON, &player, 0)) {
+ msg("You faint from the painful wound");
+ no_command += PAINTIME;
+ }
+ }
+
+ /*
+ * The monsters touch slows the hero down
+ */
+ if (on(*mp, CANSLOW)) {
+ turn_off(*mp, CANSLOW);
+ if (!save(VS_PARALYZATION, &player, 0))
+ add_slow();
+ }
+
+ /*
+ * Rotting
+ */
+ if (on(*mp, CANROT)) {
+ if (!ISWEARING(R_HEALTH) &&
+ !save(VS_POISON, &player, 0) &&
+ off(player, DOROT)) {
+ turn_on(player, DOROT);
+ msg("You feel your skin starting to rot away!");
+ }
+ }
+
+ if (on(*mp, 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, &player, mp->t_stats.s_lvl/10)) {
+ if (on(*mp, 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=mp->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;
+ strcpy(obj->o_damage,"0d0");
+ strcpy(obj->o_hurldmg,"0d0");
+ obj->o_ac = 11;
+ obj->contents = NULL;
+ obj->o_group = 0;
+ obj->o_flags = 0;
+ obj->o_mark[0] = '\0';
+ obj->o_pos = mp->t_pos;
+
+ attach(mp->t_pack, item);
+ }
+ }
+
+ turn_on(*mp, ISFLEE);
+ turn_on(*mp, ISINVIS);
+ }
+
+ if (on(*mp, 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 = pack; list != NULL; list = next(list))
+ {
+ obj = OBJPTR(list);
+ if (!is_current(obj) &&
+ is_magic(obj) &&
+ rnd(++nobj) == 0)
+ steal = list;
+ }
+ if (steal != NULL)
+ {
+ register struct object *obj;
+ struct linked_list *item;
+
+ obj = OBJPTR(steal);
+ if (on(*mp, ISUNIQUE))
+ monsters[mp->t_index].m_normal = TRUE;
+ item = find_mons(mp->t_pos.y, mp->t_pos.x);
+ killed(item, FALSE, FALSE);
+ if (obj->o_count > 1 && obj->o_group == 0) {
+ register int oc;
+
+ oc = --(obj->o_count);
+ obj->o_count = 1;
+ sprintf(outstring,"The %s stole %s!", mname, inv_name(obj, TRUE));
+ msg(outstring);
+ obj->o_count = oc;
+ }
+ else {
+ sprintf(outstring,"The %s stole %s!", mname, inv_name(obj, TRUE));
+ msg(outstring);
+ detach(pack, steal);
+
+ /* If this is a relic, clear its holding field */
+ if (obj->o_type == RELIC)
+ cur_relic[obj->o_which] = 0;
+
+ o_discard(steal);
+ inpack--;
+ }
+ updpack(FALSE);
+ }
+ }
+ }
+ }
+ else {
+ /* If the thing was trying to surprise, no good */
+ if (on(*mp, CANSURPRISE)) turn_off(*mp, CANSURPRISE);
+
+ else if (thrown) m_bounce(weapon, mp, mname);
+ else miss(weapon, mp, mname, NULL);
+ }
+ 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 = att_mat[class].base -
+ att_mat[class].factor *
+ ((min(at_lvl, att_mat[class].max_lvl) -
+ att_mat[class].offset)/att_mat[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 = NULL;
+ register int ndice, nsides, nplus, def_arm;
+ bool did_hit = FALSE;
+ int prop_hplus, prop_dplus;
+ int vampiric_damage;
+
+ /* Get statistics */
+ att = &att_er->t_stats;
+ def = &def_er->t_stats;
+
+ prop_hplus = prop_dplus = 0;
+ if (weap == NULL)
+ cp = att->s_dmg;
+ 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 {
+ 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";
+ }
+ }
+ else cp = weap->o_damage;
+ /*
+ * Drain a staff of striking
+ */
+ if (weap->o_type == STICK && weap->o_which == WS_HIT
+ && weap->o_charges == 0)
+ {
+ strcpy(weap->o_damage,"0d0");
+ weap->o_hplus = weap->o_dplus = 0;
+ }
+ }
+ 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;
+ }
+ }
+ 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 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 */
+ def_arm = ac_compute() - dext_prot(dex_compute());
+ hplus += str_plus(att->s_str)+dext_plus(att->s_dext);
+ }
+ else { /* Player attacks monster */
+ def_arm = def->s_arm - dext_prot(def->s_dext);
+ hplus += str_plus(str_compute())+dext_plus(dex_compute());
+ }
+
+ 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, rnd(8)+HUHDURATION);
+ else
+ fuse(unconfuse, 0, rnd(8)+HUHDURATION, AFTER);
+ turn_on(player, ISHUH);
+ }
+ else msg("You feel dizzy, but it quickly passes.");
+ }
+ /* Player hits monster */
+ else if (!save(VS_MAGIC, def_er, 0) && off(*def_er, ISCLEAR)) {
+ 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.");
+ no_command += FREEZETIME;
+ }
+ }
+ else if (!save(VS_MAGIC, def_er, 0)) { /* Player hits monster */
+ 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)) {
+ msg("The artifact draws energy.");
+
+ /* Give the player 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;
+ 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 (def == &pstats)
+ damage += add_dam(att->s_str);
+ else
+ damage += add_dam(str_compute());
+
+ /* 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 && att != &pstats)
+ mult = 5;/*be nice with maximum of 5x for monsters*/
+ if (weap->o_type == RELIC && weap->o_which == MUSTY_DAGGER)
+ mult++;
+ damage *= mult;
+ }
+
+ /* Check for no-damage and division */
+ if (on(*def_er, BLOWDIVIDE)) {
+ damage = 0;
+ creat_mons(def_er, def_er->t_index, FALSE);
+ 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 defender is wearing a cloak of displacement -- no damage
+ * the first time. (unless its a hurled magic missile)
+ */
+ if ( ((weap == NULL) || weap->o_type != MISSILE) &&
+ def == &pstats &&
+ cur_misc[WEAR_CLOAK] != NULL &&
+ cur_misc[WEAR_CLOAK]->o_which == MM_DISP &&
+ off(*att_er, MISSEDDISP)) {
+ damage = 0;
+ did_hit = FALSE;
+ turn_on(*att_er, MISSEDDISP);
+ if (cansee(att_er->t_pos.y, att_er->t_pos.x) &&
+ !invisible(att_er))
+ msg("The %s looks amazed",
+ monsters[att_er->t_index].m_name);
+ }
+ else {
+ 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))
+ strcpy(tbuf, "it");
+ else
+ {
+ strcpy(tbuf, "the ");
+ strcat(tbuf, who);
+ }
+ if (upper)
+ *tbuf = toupper(*tbuf);
+ return tbuf;
+}
+
+/*
+ * hit:
+ * Print a message to indicate a succesful hit
+ */
+
+hit(weapon, tp, er, ee, back_stab)
+register struct object *weapon;
+register struct thing *tp;
+register char *er, *ee;
+bool back_stab;
+{
+ register char *s = NULL;
+ char
+ att_name[80], /* Name of attacker */
+ def_name[80];/* Name of defender */
+ bool see_monst = !invisible(tp); /* Can the player see the monster? */
+
+ /* What do we call the attacker? */
+ if (er == NULL) { /* Player is attacking */
+ strcpy(att_name, prname(er, TRUE));
+ strcpy(def_name, see_monst ? prname(ee, FALSE) : "something");
+ }
+ else {
+ strcpy(att_name, see_monst ? prname(er, TRUE) : "Something");
+
+ /* If the monster is using a weapon and we can see it, report it */
+ if (weapon != NULL && see_monst) {
+ strcat(att_name, "'s ");
+ strcat(att_name, weap_name(weapon));
+ }
+
+ strcpy(def_name, prname(ee, FALSE));
+ }
+
+ addmsg(att_name);
+ if (terse) {
+ if (back_stab)
+ s = " backstab!";
+ else
+ s = " hit.";
+ }
+ else {
+ if (back_stab)
+ s = (er == 0 ? " have backstabbed " : " has backstabbed ");
+ else {
+ switch (rnd(4))
+ {
+ case 0: s = " scored an excellent hit on ";
+ when 1: s = " hit ";
+ when 2: s = (er == 0 ? " have injured " : " has injured ");
+ when 3: s = (er == 0 ? " swing and hit " : " swings and hits ");
+ }
+ }
+ }
+ addmsg(s);
+ if (!terse)
+ addmsg(def_name);
+ endmsg();
+}
+
+/*
+ * miss:
+ * Print a message to indicate a poor swing
+ */
+
+miss(weapon, tp, er, ee)
+register struct object *weapon;
+register struct thing *tp;
+register char *er, *ee;
+{
+ register char *s = NULL;
+ char
+ att_name[80], /* Name of attacker */
+ def_name[80];/* Name of defender */
+ bool see_monst = !invisible(tp); /* Can the player see the monster? */
+
+ /* What do we call the attacker? */
+ if (er == NULL) { /* Player is attacking */
+ strcpy(att_name, prname(er, TRUE));
+ strcpy(def_name, see_monst ? prname(ee, FALSE) : "something");
+ }
+ else {
+ strcpy(att_name, see_monst ? prname(er, TRUE) : "Something");
+
+ /* If the monster is using a weapon and we can see it, report it */
+ if (weapon != NULL && see_monst) {
+ strcat(att_name, "'s ");
+ strcat(att_name, weap_name(weapon));
+ }
+
+ strcpy(def_name, prname(ee, FALSE));
+ }
+
+ addmsg(att_name);
+ switch (terse ? 0 : rnd(4))
+ {
+ case 0: s = (er == 0 ? " miss" : " misses");
+ when 1: s = (er == 0 ? " swing and miss" : " swings and misses");
+ when 2: s = (er == 0 ? " barely miss" : " barely misses");
+ when 3: s = (er == 0 ? " don't hit" : " doesn't hit");
+ }
+ addmsg(s);
+ if (!terse)
+ addmsg(" %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 = 0;
+
+ switch(hungry_state) {
+ case F_OKAY:
+ case F_HUNGRY: howmuch = 0;
+ when F_WEAK: howmuch = -1;
+ when F_FAINT: howmuch = -2;
+ }
+ return howmuch;
+}
+
+/*
+ * 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){
+ sprintf(outstring,"The %s hits %s", weaps[weap->o_which].w_name, def_name);
+ msg(outstring);
+ }
+ else if (weap->o_type == MISSILE){
+ sprintf(outstring,"The %s hits %s",ws_magic[weap->o_which].mi_name, def_name);
+ msg(outstring);
+ }
+ 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){
+ sprintf(outstring,"%s's %s hits you.", att_name, weaps[weap->o_which].w_name);
+ msg(outstring);
+ }
+ else if (weap->o_type == MISSILE){
+ sprintf(outstring,"%s's %s hits you.", att_name, ws_magic[weap->o_which].mi_name);
+ msg(outstring);
+ }
+ 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){
+ sprintf(outstring,"The %s misses %s",weaps[weap->o_which].w_name, def_name);
+ msg(outstring);
+ }
+ else if (weap->o_type == MISSILE){
+ sprintf(outstring,"The %s misses %s",ws_magic[weap->o_which].mi_name, def_name);
+ msg(outstring);
+ }
+ 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){
+ sprintf(outstring,"%s's %s misses you.", att_name, weaps[weap->o_which].w_name);
+ msg(outstring);
+ }
+ else if (weap->o_type == MISSILE){
+ sprintf(outstring,"%s's %s misses you.", att_name, ws_magic[weap->o_which].mi_name);
+ msg(outstring);
+ }
+ else
+ msg("%s misses you.", att_name);
+}
+
+
+/*
+ * 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
+ */
+
+killed(item, pr, points)
+register struct linked_list *item;
+bool pr, points;
+{
+ register struct thing *tp;
+ register struct linked_list *pitem, *nexti;
+ const 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 = monsters[tp->t_index].m_name;
+ 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);
+
+ if (points) {
+ unsigned long test; /* For overflow check */
+
+ test = pstats.s_exp + tp->t_stats.s_exp;
+
+ /* Do an overflow check before increasing experience */
+ if (test > pstats.s_exp) pstats.s_exp = test;
+
+ /*
+ * Do adjustments if he went up a level
+ */
+ check_level(TRUE);
+ }
+
+ /*
+ * 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);
+ /*
+ * empty his pack
+ */
+ while (pitem != NULL)
+ {
+ nexti = next(tp->t_pack);
+ (OBJPTR(pitem))->o_pos = tp->t_pos;
+ detach(tp->t_pack, pitem);
+ if (points)
+ 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 object *
+wield_weap(thrown, mp)
+struct object *thrown;
+struct thing *mp;
+{
+ int look_for = 0, /* 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;
+ register struct object *obj, *candidate = NULL;
+
+ 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(obj);
+
+ /* 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 MING_STAFF:
+ case ASMO_ROD:
+ case ORCUS_WAND:
+ return(obj);
+ }
+ }
+
+ /* 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:
+ 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 = obj;
+ }
+ }
+ }
+
+ return(candidate);
+}
+
+explode(tp)
+register struct thing *tp;
+{
+
+ register int x,y, damage;
+ struct linked_list *item;
+ struct thing *th;
+
+ msg("the %s explodes!", monsters[tp->t_index].m_name);
+ /*
+ * check to see if it got the hero
+ */
+ if (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;
+ if ((pstats.s_hpt -= damage) <= 0)
+ death(tp->t_index);
+ }
+
+ /*
+ * 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 */
+ continue;
+ damage = roll(6, 6);
+ if (save(VS_WAND, th, 0))
+ damage /= 2;
+ if ((tp->t_stats.s_hpt -= damage) <= 0) {
+ msg("the explosion kills the %s",
+ monsters[th->t_index].m_name);
+ killed(item, FALSE, FALSE);
+ }
+ }
+ }
+ }
+ }
+}
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/init.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/init.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,497 @@
+/*
+ * global variable initializaton
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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"
+#include "mach_dep.h"
+
+
+char *rainbow[NCOLORS] = {
+
+"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",
+};
+
+char *sylls[NSYLLS] = {
+ "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", "nes", "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[NSTONES] = {
+ "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",
+};
+
+char *wood[NWOOD] = {
+ "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",
+};
+
+char *metal[NMETAL] = {
+ "aluminium", "bone", "brass", "bronze",
+ "copper", "chromium", "iron", "lead",
+ "magnesium", "pewter", "platinum", "silver",
+ "steel", "tin", "titanium", "zinc",
+};
+
+
+
+
+/*
+ * 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;
+ bool used[NCOLORS];
+
+ 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);
+}
+
+/*
+ * init_materials:
+ * Initialize the construction materials for wands and staffs
+ */
+
+init_materials()
+{
+ register int i, j;
+ register char *str;
+ bool metused[NMETAL], woodused[NWOOD];
+
+ for(i = 0; i < NWOOD; i++)
+ woodused[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 (!woodused[j])
+ {
+ ws_type[i] = "staff";
+ str = wood[j];
+ woodused[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, ch = 0, wpt = 0, i, j;
+ struct linked_list *weap_item, *armor_item, *food_item;
+ struct object *obj;
+ char *class;
+
+ weap_item = armor_item = NULL;
+
+ if (char_type == -1) {
+ /* See what type character will be */
+ wclear(hw);
+ touchwin(hw);
+ mvwaddstr(hw,2,0,"[1] Fighter\n[2] Magician\n[3] Cleric\n[4] Thief");
+ mvwaddstr(hw, 0, 0, "What character class do you desire? ");
+ draw(hw);
+ char_type = (wgetch(hw) - '0');
+ while (char_type < 1 || char_type > 4) {
+ mvwaddstr(hw,0,0,"Please enter a character type between 1 and 4: ");
+ draw(hw);
+ char_type = (wgetch(hw) - '0');
+ }
+ char_type--;
+ }
+ player.t_ctype = char_type;
+ player.t_quiet = 0;
+ pack = NULL;
+
+#ifdef WIZARD
+ /*
+ * allow me to describe a super character
+ */
+ if (wizard && md_getuid() == AUTHOR && 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 = 7500000L;
+ pstats.s_lvl = 20;
+ pstats.s_hpt = 500;
+ pstats.s_carry = totalenc();
+ strcpy(pstats.s_dmg,"3d4");
+ if (player.t_ctype == C_FIGHTER)
+ 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;
+ j = PLATE_ARMOR;
+ if (player.t_ctype == C_THIEF)
+ 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
+
+ {
+ wclear(hw);
+ do {
+ if (armor_item != NULL) {
+ o_discard(armor_item);
+ armor_item = NULL;
+ }
+ if (weap_item != NULL) {
+ o_discard(weap_item);
+ weap_item = NULL;
+ }
+ pstats.s_lvl = 1;
+ pstats.s_exp = 0L;
+ pstats.s_hpt = 12 + rnd(10);
+ pstats.s_str = 7 + rnd(5);
+ pstats.s_intel = 7 + rnd(5);
+ pstats.s_wisdom = 7 + rnd(5);
+ pstats.s_dext = 7 + rnd(5);
+ pstats.s_const = 14 + rnd(5);
+ pstats.s_charisma = 7 + rnd(5);
+
+ /* Now for the special ability */
+ switch (char_type) {
+ case C_FIGHTER: pstats.s_str = (rnd(10) == 7) ? 18 : 16;
+ when C_MAGICIAN: pstats.s_intel = (rnd(10) == 7) ? 18 : 16;
+ when C_CLERIC: pstats.s_wisdom= (rnd(10) == 7) ? 18 : 16;
+ when C_THIEF: pstats.s_dext = (rnd(10) == 7) ? 18 : 16;
+ }
+ strcpy(pstats.s_dmg,"1d4");
+ stat_total =pstats.s_str + pstats.s_intel + pstats.s_wisdom +
+ pstats.s_dext + pstats.s_const;
+ /*
+ * since the player can re-roll stats at will, keep the maximum
+ * to some reasonable limit
+ */
+ if (stat_total > MAXSTATS)
+ pstats.s_const -= (stat_total - MAXSTATS);
+ pstats.s_carry = totalenc();
+
+ /*
+ * Give the rogue his weaponry.
+ */
+ do {
+ i = rnd(8); /* number of acceptable weapons */
+ switch(i) {
+ case 0: ch = 25; wpt = MACE;
+ when 1: ch = 25; wpt = SWORD;
+ when 2: ch = 20; wpt = BATTLEAXE;
+ when 3: ch = 20; wpt = TRIDENT;
+ when 4: ch = 20; wpt = SPETUM;
+ when 5: ch = 20; wpt = BARDICHE;
+ when 6: ch = 15; wpt = PIKE;
+ when 7: ch = 20; wpt = HALBERD;
+ }
+ } while(rnd(100) > ch);
+ if (player.t_ctype == C_FIGHTER)
+ wpt = TWOSWORD;
+ weap_item = spec_item(WEAPON, wpt, rnd(2), rnd(2)+1);
+ obj = OBJPTR(weap_item);
+ obj->o_flags |= ISKNOW;
+ /*
+ * And his suit of armor.......
+ * Thieves can only wear leather armor
+ * fighters get better armor on an average
+ */
+ if (player.t_ctype == C_THIEF)
+ j = STUDDED_LEATHER;
+ else {
+ if (player.t_ctype == C_FIGHTER)
+ i = 50 + rnd(50);
+ else
+ i = rnd(100);
+ j = 0;
+ while (armors[j].a_prob < i)
+ j++;
+ }
+ armor_item = spec_item(ARMOR, j, 0, 0);
+ obj = OBJPTR(armor_item);
+ obj->o_flags |= ISKNOW;
+ obj->o_weight = armors[j].a_wght;
+ switch(player.t_ctype) {
+ case C_FIGHTER: class = "fighter";
+ when C_MAGICIAN:class = "magic user";
+ when C_CLERIC: class = "cleric";
+ when C_THIEF: class = "thief";
+ otherwise: class = "unknown";
+ }
+ wmove(hw, 2, 0);
+ wprintw(hw, "You have rolled a %s with the following attributes:",class);
+ wmove(hw,4,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, " Const: %2d", pstats.s_const);
+ wclrtoeol(hw);
+ wmove(hw, 6, 0);
+ wprintw(hw, " Hp: %2d", pstats.s_hpt);
+ wclrtoeol(hw);
+ mvwaddstr(hw, 8, 5, inv_name(OBJPTR(weap_item), FALSE));
+ wclrtoeol(hw);
+ mvwaddstr(hw, 9, 5, inv_name(OBJPTR(armor_item), FALSE));
+ wclrtoeol(hw);
+ mvwaddstr(hw,0,0,"Would you like to re-roll the character? ");
+ draw(hw);
+ } while(wgetch(hw) == 'y');
+
+ obj = OBJPTR(weap_item);
+ add_pack(weap_item, TRUE, NULL);
+ cur_weapon = obj;
+ obj = OBJPTR(armor_item);
+ add_pack(armor_item, TRUE, NULL);
+ cur_armor = obj;
+ }
+ /*
+ * Give him some food
+ */
+ food_item = spec_item(FOOD, 0, 0, 0);
+ obj = OBJPTR(food_item);
+ obj->o_weight = things[TYP_FOOD].mi_wght;
+ add_pack(food_item, TRUE, NULL);
+ pstats.s_arm = 10;
+ max_stats = pstats;
+}
+
+
+
+
+
+
+/*
+ * init_stones:
+ * Initialize the ring stone setting scheme for this time
+ */
+
+init_stones()
+{
+ register int i, j;
+ bool used[NSTONES];
+
+ 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 0ef99244acb8 -r 0ed67132cf10 arogue5/io.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/io.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,489 @@
+/*
+ * Various input/output functions
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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
+#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()
+{
+ strncpy(huh, msgbuf, sizeof(huh));
+
+ huh[ sizeof(huh) - 1 ] = 0;
+
+ if (mpos)
+ {
+ wmove(msgw, 0, mpos);
+ waddstr(msgw, morestr);
+ draw(cw);
+ draw(msgw);
+ wait_for(msgw,' ');
+ overwrite(cw,msgw);
+ wmove(msgw,0,0);
+ touchwin(cw);
+ }
+ else {
+ overwrite(cw,msgw);
+ wmove(msgw,0,0);
+ }
+ waddstr(msgw, msgbuf);
+ mpos = newpos;
+ newpos = 0;
+ msgbuf[0] = '\0';
+ draw(cw);
+ clearok(msgw, FALSE);
+ draw(msgw);
+}
+
+doadd(char *fmt, va_list ap)
+{
+ /*
+ * Do the sprintf into newmsg and append to msgbuf
+ */
+
+ vsnprintf(&msgbuf[newpos], sizeof(msgbuf)-newpos-1, 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;
+ 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) );
+
+ 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));
+ }
+}
+/*
+ * 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 = 0, ox = 0, temp;
+ register char *pb;
+ static char buf[LINELEN];
+ static int hpwidth = 0, s_hungry = -1;
+ static int s_lvl = -1, s_pur, 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;
+
+ /* Use a mini status version if we have a small window */
+ if (COLS < 80) {
+ ministat();
+ return;
+ }
+
+ 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_pack == stat_ptr->s_pack &&
+ s_carry == stat_ptr->s_carry &&
+ 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) Const:%d(%d) Carry:%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_pack/10,
+ stat_ptr->s_carry/10);
+
+ /* 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();
+ s_pack = stat_ptr->s_pack;
+ s_carry = stat_ptr->s_carry;
+ 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);
+ wclrtoeol(cw);
+
+ /*
+ * If nothing has changed since the last status, don't
+ * bother.
+ */
+line_two:
+ if (!display &&
+ s_hp == stat_ptr->s_hpt &&
+ s_exp == stat_ptr->s_exp &&
+ s_pur == purse &&
+ s_ac == ac_compute() - dext_prot(s_dext) &&
+ s_lvl == level &&
+ s_hungry == hungry_state ) 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 Au:%d Hp:%*d(%*d) Ac:%d Exp:%d/%lu %s",
+ level, purse, hpwidth, stat_ptr->s_hpt, hpwidth, max_ptr->s_hpt,
+ ac_compute() - dext_prot(s_dext),stat_ptr->s_lvl, stat_ptr->s_exp,
+ cnames[player.t_ctype][min(stat_ptr->s_lvl-1, 10)]);
+
+ /*
+ * Save old status
+ */
+ s_lvl = level;
+ s_pur = purse;
+ s_hp = stat_ptr->s_hpt;
+ s_exp = stat_ptr->s_exp;
+ s_ac = ac_compute() - dext_prot(s_dext);
+ mvwaddstr(cw, LINES - 1, 0, buf);
+ switch (hungry_state)
+ {
+ case 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;
+ wmove(cw, oy, ox);
+}
+
+ministat()
+{
+ register int oy, ox, temp;
+ static char buf[LINELEN];
+ static int hpwidth = 0;
+ static int s_lvl = -1, s_pur, s_hp = -1;
+
+ /*
+ * If nothing has changed since the last status, don't
+ * bother.
+ */
+ if (s_hp == pstats.s_hpt && s_pur == purse && s_lvl == level)
+ return;
+
+ getyx(cw, oy, ox);
+ if (s_hp != max_stats.s_hpt)
+ {
+ temp = s_hp = max_stats.s_hpt;
+ for (hpwidth = 0; temp; hpwidth++)
+ temp /= 10;
+ }
+ sprintf(buf, "Lv: %d Au: %-5d Hp: %*d(%*d)",
+ level, purse, hpwidth, pstats.s_hpt, hpwidth, max_stats.s_hpt);
+
+ /*
+ * Save old status
+ */
+ s_lvl = level;
+ s_pur = purse;
+ s_hp = pstats.s_hpt;
+ 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(win,ch)
+WINDOW *win;
+register char ch;
+{
+ register char c;
+
+ if (ch == '\n')
+ while ((c = wgetch(win)) != '\n' && c != '\r')
+ continue;
+ else
+ while (wgetch(win) != ch)
+ continue;
+}
+
+/*
+ * show_win:
+ * function used to display a window and wait before returning
+ */
+
+show_win(scr, message)
+register WINDOW *scr;
+char *message;
+{
+ mvwaddstr(scr, 0, 0, message);
+ touchwin(scr);
+ wmove(scr, hero.y, hero.x);
+ draw(scr);
+ wait_for(scr,' ');
+ clearok(cw, TRUE);
+ touchwin(cw);
+}
+
+/*
+ * dbotline:
+ * Displays message on bottom line and waits for a space to return
+ */
+dbotline(scr,message)
+WINDOW *scr;
+char *message;
+{
+ mvwaddstr(scr,LINES-1,0,message);
+ draw(scr);
+ wait_for(scr,' ');
+}
+
+
+/*
+ * restscr:
+ * Restores the screen to the terminal
+ */
+restscr(scr)
+WINDOW *scr;
+{
+ clearok(scr,TRUE);
+ touchwin(scr);
+}
+
+/*
+ * netread:
+ * Read a byte, short, or long machine independently
+ * Always returns the value as an unsigned long.
+ */
+
+unsigned long
+netread(error, size, stream)
+int *error;
+int size;
+FILE *stream;
+{
+ unsigned long result = 0L, /* What we read in */
+ partial; /* Partial value */
+ int nextc, /* The next byte */
+ i; /* To index through the result a byte at a time */
+
+ /* Be sure we have a right sized chunk */
+ if (size < 1 || size > 4) {
+ *error = 1;
+ return(0L);
+ }
+
+ for (i=0; i 4) return(0);
+
+ for (i=0; i> (8 * i)) & 0xff);
+ putc(outc, stream);
+ }
+ return(size);
+}
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/list.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/list.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,185 @@
+/*
+ * Functions for dealing with linked lists of goodies
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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"
+
+/*
+ * 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(item->l_data);
+ 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)
+struct linked_list *item;
+{
+ total -= 2;
+ FREE(item->l_data);
+ 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 0ef99244acb8 -r 0ed67132cf10 arogue5/mach_dep.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/mach_dep.h Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,64 @@
+/*
+ * machine dependicies
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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 1
+
+/*
+ * define if you want to limit scores to one per class per userid
+ */
+#undef LIMITSCORE
+
+/*
+ * where scorefile should live
+ */
+#define SCOREFILE "/bnr/contrib/lib/rogue/scorefile"
+
+/*
+ * Variables for checking to make sure the system isn't too loaded
+ * for people to play
+ */
+
+#undef MAXUSERS /*40*/ /* max number of users for this game */
+#undef MAXLOAD /*40*/ /* 10 * max 15 minute load average */
+
+#undef CHECKTIME /*15*/ /* number of minutes between load checks */
+ /* if not defined checks are only on startup */
+
+#ifdef MAXLOAD
+#define LOADAV /* defined if rogue should provide loadav() */
+
+#ifdef LOADAV
+#define NAMELIST "/unix" /* where the system namelist lives */
+#endif
+#endif
+
+#ifdef MAXUSERS
+#define UCOUNT /* defined if rogue should provide ucount() */
+
+#ifdef UCOUNT
+#define UTMP "/etc/utmp" /* where utmp file lives */
+#endif
+#endif
+
+#undef AUTHOR /*212*/
+
+/*
+ * define the current author of the program for "special handling"
+ */
+#ifndef AUTHOR
+#define AUTHOR 0 /* Default to root if not specified above */
+#endif
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/main.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/main.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,530 @@
+/*
+ * Rogue
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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
+#include
+#include
+#include
+#include "mach_dep.h"
+#include "network.h"
+#include "rogue.h"
+
+#ifdef CHECKTIME
+static int num_checks; /* times we've gone over in checkout() */
+#endif
+
+/*
+ * fruits that you get at startup
+ */
+static char *funfruit[] = {
+ "candleberry", "caprifig", "dewberry", "elderberry",
+ "gooseberry", "guanabana", "hagberry", "ilama",
+ "imbu", "jaboticaba", "jujube", "litchi",
+ "mombin", "pitanga", "prickly pear", "rambutan",
+ "sapodilla", "soursop", "sweetsop", "whortleberry",
+ "jellybean", "apple", "strawberry", "blueberry",
+ "peach", "banana"
+};
+#define NFRUIT (sizeof(funfruit) / sizeof (char *))
+
+main(argc, argv, envp)
+char **argv;
+char **envp;
+{
+ register char *env;
+ int lowtime;
+ time_t now;
+ char *roguedir = md_getroguedir();
+
+ md_init();
+
+ /*
+ * get home and options from environment
+ */
+
+ strncpy(home,md_gethomedir(),LINELEN);
+
+ /* Get default save file */
+ strcpy(file_name, home);
+ strcat(file_name, "arogue58.sav");
+
+ /* Get default score file */
+ strcpy(score_file, roguedir);
+
+ if (*score_file)
+ strcat(score_file,"/");
+
+ strcat(score_file, "arogue58.scr");
+
+ if ((env = getenv("ROGUEOPTS")) != NULL)
+ parse_opts(env);
+
+ if (whoami[0] == '\0')
+ strucpy(whoami, md_getusername(), strlen(md_getusername()));
+
+ if (env == NULL || fruit[0] == '\0') {
+ md_srand((long)(getpid()+time(0)));
+ strcpy(fruit, funfruit[rnd(NFRUIT)]);
+ }
+
+ /*
+ * 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: "), "Si")) == 0)
+ {
+ printf("Hail Mighty Wizard\n");
+ wizard = TRUE;
+ argv++;
+ argc--;
+ }
+#endif
+
+#if MAXLOAD|MAXUSERS
+ if (too_much() && !wizard && !author())
+ {
+ printf("Sorry, %s, but the system is too loaded now.\n", whoami);
+ printf("Try again later. Meanwhile, why not enjoy a%s %s?\n",
+ vowelstr(fruit), fruit);
+ exit(1);
+ }
+#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\n", whoami, dnum);
+ else
+ printf("Hello %s, just a moment while I dig the dungeon...\n", whoami);
+ fflush(stdout);
+ seed = dnum;
+ md_srand(seed);
+
+ init_things(); /* Set up probabilities of things */
+ init_colors(); /* Set up colors of potions */
+ init_stones(); /* Set up stone settings of rings */
+ init_materials(); /* Set up materials of wands */
+ initscr(); /* Start up cursor package */
+ init_names(); /* Set up names of scrolls */
+ init_misc(); /* Set up miscellaneous magic */
+ if (LINES < 24 || COLS < 80) {
+ printf("\nERROR: screen size to small for rogue\n");
+ byebye(-1);
+ }
+
+ if ((whoami == NULL) || (*whoami == '\0') || (strcmp(whoami,"dosuser")==0))
+ {
+ echo();
+ mvaddstr(23,2,"Rogue's Name? ");
+ wgetnstr(stdscr,whoami,LINELEN);
+ noecho();
+ }
+
+ if ((whoami == NULL) || (*whoami == '\0'))
+ strcpy(whoami,"Rodney");
+
+ 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);
+
+ init_player(); /* Roll up the rogue */
+ waswizard = wizard;
+ new_level(NORMLEV); /* Draw current level */
+ /*
+ * Start up daemons and fuses
+ */
+ daemon(doctor, &player, AFTER);
+ fuse(swander, 0, WANDERTIME, AFTER);
+ daemon(stomach, 0, AFTER);
+ daemon(runners, 0, AFTER);
+ if (player.t_ctype == C_THIEF)
+ daemon(trap_look, 0, AFTER);
+
+ /* Choose a quest item */
+ quest_item = rnd(MAXRELIC);
+ 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(int sig)
+{
+ NOOP(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();
+ printf("\n"); /* So the cursor 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(int a)
+{
+ mvcur(0, COLS - 1, LINES - 1, 0);
+ endwin();
+ fflush(stdout);
+ kill(0, SIGTSTP);
+ signal(SIGTSTP, tstp);
+ raw();
+ noecho();
+ keypad(cw,1);
+ clearok(curscr, TRUE);
+ touchwin(cw);
+ draw(cw);
+ md_flushinp();
+}
+# endif
+
+setup()
+{
+#ifdef CHECKTIME
+ int checkout();
+#endif
+
+#ifndef DUMP
+#ifdef SIGHUP
+ signal(SIGHUP, auto_save);
+#endif
+ signal(SIGILL, bugkill);
+#ifdef SIGTRAP
+ signal(SIGTRAP, bugkill);
+#endif
+#ifdef SIGIOT
+ signal(SIGIOT, bugkill);
+#endif
+#if 0
+ signal(SIGEMT, bugkill);
+ signal(SIGFPE, bugkill);
+ signal(SIGBUS, bugkill);
+ signal(SIGSEGV, bugkill);
+ signal(SIGSYS, bugkill);
+ signal(SIGPIPE, bugkill);
+#endif
+ signal(SIGTERM, auto_save);
+#endif
+
+ signal(SIGINT, quit);
+#ifndef DUMP
+#ifdef SIGQUIT
+ signal(SIGQUIT, endit);
+#endif
+#endif
+#ifdef SIGTSTP
+ signal(SIGTSTP, tstp);
+#endif
+#ifdef CHECKTIME
+ if (!author())
+ {
+ signal(SIGALRM, checkout);
+ alarm(CHECKTIME * 60);
+ num_checks = 0;
+ }
+#endif
+ crmode(); /* 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;
+ while (playing)
+ command(); /* Command execution */
+ endit(0);
+}
+
+#if MAXLOAD|MAXUSERS
+/*
+ * see if the system is being used too much for this game
+ */
+too_much()
+{
+#ifdef MAXLOAD
+ double avec[3];
+#endif
+
+#ifdef MAXLOAD
+ loadav(avec);
+ return (avec[2] > (MAXLOAD / 10.0));
+#else
+ return (ucount() > MAXUSERS);
+#endif
+}
+#endif
+
+/*
+ * author:
+ * See if a user is an author of the program
+ */
+author()
+{
+ switch (md_getuid()) {
+#if AUTHOR
+ case AUTHOR:
+#endif
+ case 0:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+
+#ifdef CHECKTIME
+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()) {
+ wclear(cw);
+ mvwaddstr(cw, LINES / 2, 0,
+ "Game time is over. Your game is being saved.\n\n");
+ draw(cw);
+ 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 LOADAV
+
+#include
+
+struct nlist avenrun =
+{
+ "_avenrun"
+};
+
+loadav(avg)
+reg double *avg;
+{
+ reg int kmem;
+
+ if ((kmem = open("/dev/kmem", 0)) < 0)
+ goto bad;
+ nlist(NAMELIST, &avenrun);
+ if (avenrun.n_type == 0) {
+bad:
+ avg[0] = avg[1] = avg[2] = 0.0;
+ return;
+ }
+ lseek(kmem, (long) avenrun.n_value, 0);
+ read(kmem, avg, 3 * sizeof (double));
+}
+#endif
+
+#ifdef UCOUNT
+/*
+ * 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)
+ if (buf.ut_type == USER_PROCESS)
+ count++;
+ fclose(utmp);
+ return count;
+}
+#endif
+
+/*
+ * holiday:
+ * Returns TRUE when it is a good time to play rogue
+ */
+holiday()
+{
+ time_t 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 >= 17)
+ return TRUE; /* OK before 8AM & after 5PM */
+ if(ntime->tm_yday <= 7 || ntime->tm_yday >= 350)
+ return TRUE; /* OK during Christmas */
+#if 0 /* not for now */
+ if (access("/usr/tmp/.ryes",0) == 0)
+ return TRUE; /* if author permission */
+#endif
+
+ return FALSE; /* All other times are bad */
+}
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/maze.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/maze.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,369 @@
+/*
+ * maze
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+ * All rights reserved.
+ *
+ * Based on "Super-Rogue"
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include
+#include "curses.h"
+#include "rogue.h"
+
+struct cell {
+ char y_pos;
+ char x_pos;
+};
+
+struct bordercells {
+ char num_pos; /* number of frontier cells next to you */
+ struct cell conn[4]; /* the y,x position of above cell */
+} border_cells;
+
+static char *frontier,
+ *bits;
+static int maze_lines,
+ maze_cols;
+char *moffset(),
+ *foffset();
+
+
+/*
+ * crankout:
+ * Does actual drawing of maze to window
+ */
+crankout()
+{
+ reg int x, y;
+
+ for (y = 0; y < LINES - 3; y++) {
+ move(y + 1, 0);
+ for (x = 0; x < COLS - 1; x++) {
+ if (*moffset(y, x)) { /* here is a wall */
+ if(y==0 || y==LINES-4) /* top or bottom line */
+ addch('-');
+ else if(x==0 || x==COLS-2) /* left | right side */
+ addch('|');
+ else if (y % 2 == 0 && x % 2 == 0) {
+ if(*moffset(y, x-1) || *moffset(y, x+1))
+ addch('-');
+ else
+ addch('|');
+ }
+ else if (y % 2 == 0)
+ addch('-');
+ else
+ addch('|');
+ }
+ else
+ addch(FLOOR);
+ }
+ }
+}
+
+/*
+ * domaze:
+ * Draw the maze on this level.
+ */
+do_maze()
+{
+ reg int least;
+ reg struct room *rp;
+ reg struct linked_list *item;
+ reg struct object *obj;
+ int cnt;
+ bool treas;
+ coord tp;
+
+ for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) {
+ rp->r_flags = ISGONE; /* kill all rooms */
+ rp->r_fires = NULL; /* no fires */
+ }
+ rp = &rooms[0]; /* point to only room */
+ rp->r_flags = ISDARK; /* mazes always dark */
+ rp->r_pos.x = 0; /* room fills whole screen */
+ rp->r_pos.y = 1;
+ rp->r_max.x = COLS - 1;
+ rp->r_max.y = LINES - 3;
+ draw_maze(); /* put maze into window */
+ /*
+ * add some gold to make it worth looking for
+ */
+ item = spec_item(GOLD, NULL, NULL, NULL);
+ obj = OBJPTR(item);
+ obj->o_count *= (rnd(10) + 1); /* 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) < 10) { /* 10% for treasure maze */
+ treas = TRUE;
+ least = 6;
+ debug("treasure maze");
+ }
+ else { /* normal maze level */
+ least = 1;
+ 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 = 0, xcheck = 0, absy, absx, see_radius;
+ register bool row;
+ char ch; /* What we are standing on (or near) */
+
+ /* 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 (ch = CCHAR( 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 0ef99244acb8 -r 0ed67132cf10 arogue5/mdport.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/mdport.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,1194 @@
+/*
+ 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
+#undef MOUSE_MOVED
+#elif defined(__DJGPP__)
+#include
+#else
+#include
+#include
+#include
+#endif
+
+#include
+
+#if defined(_WIN32) && !defined(__MINGW32__)
+#define PATH_MAX MAX_PATH
+#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(lrand48() & 0x7fffffff);
+#endif
+}
+
+int
+md_srand(seed)
+register int seed;
+{
+#ifdef _WIN32
+ srand(seed);
+#else
+ srand48(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;
+
+ for(;;)
+ {
+ 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 0ef99244acb8 -r 0ed67132cf10 arogue5/misc.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/misc.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,736 @@
+/*
+ * routines dealing specifically with miscellaneous magic
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "curses.h"
+#include
+#include "rogue.h"
+
+/*
+ * See if a monster has some magic it can use. Use it and return TRUE if so.
+ */
+bool
+m_use_item(monster, monst_pos, defend_pos)
+register struct thing *monster;
+register coord *monst_pos, *defend_pos;
+{
+ register struct linked_list *pitem;
+ register struct object *obj;
+ register coord *shoot_dir = can_shoot(monst_pos, defend_pos);
+ int dist=DISTANCE(monst_pos->y, monst_pos->x, defend_pos->y, defend_pos->x);
+
+ for (pitem=monster->t_pack; pitem; pitem=next(pitem)) {
+ obj = OBJPTR(pitem);
+ if (obj->o_type != RELIC) continue; /* Only care about relics now */
+ switch (obj->o_which) {
+ case MING_STAFF: {
+ static struct object missile = {
+ MISSILE, {0,0}, "", 0, "", "0d4 " , NULL, 0, WS_MISSILE, 100, 1
+ };
+
+ if (shoot_dir != NULL) {
+ sprintf(missile.o_hurldmg, "%dd4", monster->t_stats.s_lvl);
+ do_motion(&missile, shoot_dir->y, shoot_dir->x, monster);
+ hit_monster(unc(missile.o_pos), &missile, monster);
+ return(TRUE);
+ }
+ }
+ when ASMO_ROD:
+ /* The bolt must be able to reach the defendant */
+ if (shoot_dir != NULL && dist < BOLT_LENGTH * BOLT_LENGTH) {
+ char *name;
+
+ switch (rnd(3)) { /* Select a function */
+ case 0: name = "lightning bolt";
+ when 1: name = "flame";
+ otherwise: name = "ice";
+ }
+ shoot_bolt( monster,
+ *monst_pos,
+ *shoot_dir,
+ FALSE,
+ monster->t_index,
+ name,
+ roll(monster->t_stats.s_lvl,6));
+ return(TRUE);
+ }
+ when BRIAN_MANDOLIN:
+ /* The defendant must be the player and within 2 spaces */
+ if (ce(*defend_pos, hero) && dist < 9 && no_command == 0 &&
+ rnd(100) < 33) {
+ if (!save(VS_MAGIC, &player, -4) &&
+ !ISWEARING(R_ALERT)) {
+ msg("Some beautiful music enthralls you.");
+ no_command += FREEZETIME;
+ }
+ else msg("You wince at a sour note.");
+ return(TRUE);
+ }
+ when GERYON_HORN:
+ /* The defendant must be the player and within 2 spaces */
+ if (ce(*defend_pos, hero) && dist < 9 &&
+ (off(player, ISFLEE) || player.t_dest != &monster->t_pos)
+ && rnd(100) < 33) {
+ 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.");
+ }
+ else msg("A shrill blast sends chills up your spine.");
+ return(TRUE);
+ }
+ }
+ }
+ return(FALSE);
+}
+
+/*
+ * 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 = NULL;
+ register struct object *obj;
+ 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);
+ when MM_BOOK: titem = get_item(pack, "put in", SCROLL);
+ }
+ if (titem == NULL)
+ break;
+ detach(pack, titem);
+ inpack--;
+ put_contents(obj, titem);
+
+ when '3':
+ titem = get_item(obj->contents,"take out",ALL);
+ if (titem == NULL)
+ break;
+ take_contents(obj, titem);
+
+ when '4':
+ switch (obj->o_which) {
+ case MM_BEAKER:
+ titem = get_item(obj->contents,"quaff",ALL);
+ if (titem == NULL)
+ break;
+ obj->o_ac--;
+ detach(obj->contents, titem);
+ quaff((OBJPTR(titem))->o_which,
+ (OBJPTR(titem))->o_flags & (ISCURSED | ISBLESSED),
+ TRUE);
+ 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);
+ if (titem == NULL)
+ break;
+ obj->o_ac--;
+ detach(obj->contents, titem);
+ read_scroll((OBJPTR(titem))->o_which,
+ (OBJPTR(titem))->o_flags & (ISCURSED|ISBLESSED),
+ TRUE);
+ 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 (hw,' ');
+ clearok(cw, TRUE);
+ touchwin(cw);
+ }
+ }
+}
+
+do_panic()
+{
+ register int x,y;
+ register struct linked_list *mon;
+ 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);
+ if (!on(*th, ISUNDEAD) && !save(VS_MAGIC, th, 0)) {
+ turn_on(*th, ISFLEE);
+ turn_on(*th, WASTURNED);
+
+ /* 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);
+ }
+ 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:
+ switch (obj->o_ac) {
+ case C_MAGICIAN: strcpy(buf1, " [magic user]");
+ when C_FIGHTER: strcpy(buf1, " [fighter]");
+ when C_CLERIC: strcpy(buf1, " [cleric]");
+ when C_THIEF: strcpy(buf1, " [thief]");
+ }
+ }
+ 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();
+ }
+ }
+}
+
+use_mm(which)
+int which;
+{
+ register struct object *obj = NULL;
+ register struct linked_list *item = NULL;
+ bool cursed, blessed, is_mm;
+ char buf[LINELEN];
+
+ cursed = FALSE;
+ is_mm = FALSE;
+
+ if (which < 0) { /* A real miscellaneous magic item */
+ is_mm = TRUE;
+ item = get_item(pack, "use", USEABLE);
+ /*
+ * Make certain that it is a micellaneous magic item
+ */
+ if (item == NULL)
+ return;
+
+ obj = OBJPTR(item);
+ cursed = (obj->o_flags & ISCURSED) != 0;
+ blessed = (obj->o_flags & ISBLESSED) != 0;
+ which = obj->o_which;
+ }
+
+ if (obj->o_type == RELIC) { /* An artifact */
+ is_mm = FALSE;
+ switch (obj->o_which) {
+ case EMORI_CLOAK:
+ use_emori();
+ 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();
+ when HEIL_ANKH:
+ case YENDOR_AMULET:
+ /* Nothing happens by this mode */
+ msg("Nothing happens.");
+ }
+ }
+ 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, 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--;
+ food_left = MORETIME + 5;
+ msg(terse ? "Getting hungry" : "You are starting to get hungry");
+ hungry_state = F_HUNGRY;
+ aggravate();
+
+ /*
+ * 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--;
+ /*
+ * 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 (!save(VS_POISON, &player, 0)) {
+ msg ("You choke to death!!! --More--");
+ pstats.s_hpt = -1; /* in case he hangs up the phone */
+ wait_for(cw,' ');
+ 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...
+ */
+ if (obj->o_charges <= 0) {
+ msg("The jar is empty!");
+ break;
+ }
+ obj->o_charges--;
+ waste_time();
+ 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--;
+ waste_time();
+ waste_time();
+ waste_time();
+ waste_time();
+ waste_time();
+ if (obj->o_ac == player.t_ctype) {
+ msg("You feel more skillful");
+ raise_level(TRUE);
+ }
+ 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 (obj->o_ac == C_THIEF &&
+ cur_armor != NULL &&
+ cur_armor->o_which != LEATHER &&
+ cur_armor->o_which != STUDDED_LEATHER )
+ cur_armor->o_which = STUDDED_LEATHER;
+ /*
+ * 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 &&
+ cur_weapon != NULL &&
+ cur_weapon->o_type == WEAPON &&
+ (cur_weapon->o_which== BASWORD ||
+ cur_weapon->o_which== TWOSWORD ))
+ cur_weapon->o_which = SWORD;
+
+ /*
+ * if he was a thief then take out the trap_look() daemon
+ */
+ if (player.t_ctype == C_THIEF)
+ kill_daemon(trap_look);
+ /*
+ * if he becomes a thief then add the trap_look() daemon
+ */
+ if (obj->o_ac == C_THIEF)
+ daemon(trap_look, 0, AFTER);
+ char_type = player.t_ctype = obj->o_ac;
+ save = pstats.s_hpt;
+ max_stats.s_hpt = pstats.s_hpt = 0;
+ max_stats.s_lvl = pstats.s_lvl = 0;
+ max_stats.s_exp = pstats.s_exp -= pstats.s_exp/10;
+ check_level(TRUE);
+ if (pstats.s_hpt > save) /* don't add to current hits */
+ pstats.s_hpt = save;
+ }
+
+ 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) {
+ msg(terse ? "Call it: " : "What do you want to call it? ");
+ if (get_str(buf, cw) == NORM) {
+ m_guess[which] = new((unsigned int) strlen(buf) + 1);
+ strcpy(m_guess[which], buf);
+ }
+ }
+ if (item != NULL && which == MM_SKILLS)
+ o_discard(item);
+ updpack(TRUE);
+}
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/monsters.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/monsters.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,1034 @@
+/*
+ * File with various monster functions in it
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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
+#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);
+
+ /* If it has lowered player, give him back a level */
+ if (on(*tp, DIDDRAIN)) raise_level(FALSE);
+
+ /* 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);
+
+ /* 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);
+ tp->t_no_move = 1; /* since it just got here, it is disoriented */
+ carry_obj(tp, monsters[tp->t_index].m_carry/2); /* only half chance */
+ 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);
+
+ /* 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;
+register 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;
+
+ attach(mlist, item);
+ tp = THINGPTR(item);
+ tp->t_turn = TRUE;
+ 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_no_move = 0;
+ tp->t_doorgoal = 0;
+ tp->t_quiet = 0;
+ 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_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;
+ if (vlevel > HARDER) { /* the deeper, the meaner we get */
+ tp->t_stats.s_lvl += (vlevel - HARDER);
+ num_dice += (vlevel - HARDER)/2;
+ }
+ 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_dext = 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]);
+
+ /* 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 is it 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.
+ */
+ if (on(*tp, CANSELL)) {
+ tp->t_stats.s_exp = vlevel * 100;
+ tp->t_stats.s_lvl = vlevel/2 + 1;
+ attach(tp->t_pack, new_thing(ALL));
+ }
+
+ /* 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);
+ strcpy(cur->o_damage,"0d0");
+ strcpy(cur->o_hurldmg,"0d0");
+ strcpy(cur1->o_damage,"0d0");
+ strcpy(cur1->o_hurldmg,"0d0");
+ 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);
+ }
+
+
+ if (ISWEARING(R_AGGR))
+ runto(tp, &hero);
+ if (on(*tp, ISDISGUISE))
+ {
+ char mch = 0;
+
+ 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) < 3) 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;
+ register struct object *obj;
+ register int i, j, min_worth, nitems, goods = 0, chance, which_item;
+ char buffer[LINELEN];
+ struct {
+ int which;
+ int plus1, plus2;
+ int count;
+ int worth;
+ char *name;
+ } selection[10];
+
+ min_worth = 100000;
+ item = find_mons(tp->t_pos.y, tp->t_pos.x); /* Get pointer to monster */
+
+ /* Select the items */
+ nitems = rnd(6) + 5;
+
+ for (i=0; i selection[i].worth)
+ min_worth = selection[i].worth;
+ }
+ break;
+
+ /* Weapon */
+ case 2:
+ case 3:
+ goods = WEAPON;
+ for (i=0; i selection[i].worth)
+ min_worth = selection[i].worth;
+ }
+ break;
+
+ /* Staff or wand */
+ case 4:
+ goods = STICK;
+ for (i=0; i selection[i].worth)
+ min_worth = selection[i].worth;
+ }
+ break;
+
+ /* Ring */
+ case 5:
+ goods = RING;
+ for (i=0; i 2) selection[i].plus1 = 2;
+ else if (selection[i].plus1 < 1) selection[i].plus1 = 1;
+ /* fall thru here to other cases */
+ case R_ADDSTR:
+ case R_ADDDAM:
+ case R_PROTECT:
+ case R_ADDHIT:
+ case R_ADDINTEL:
+ case R_ADDWISDOM:
+ if (selection[i].plus1 > 0)
+ selection[i].worth += selection[i].plus1 * 50;
+ }
+ if(min_worth > selection[i].worth)
+ min_worth = selection[i].worth;
+ }
+ break;
+
+ /* scroll */
+ case 6:
+ goods = SCROLL;
+ for (i=0; i selection[i].worth)
+ min_worth = selection[i].worth;
+ }
+ break;
+
+ /* potions */
+ case 7:
+ goods = POTION;
+ for (i=0; i selection[i].worth)
+ min_worth = selection[i].worth;
+ }
+ break;
+
+ /* Miscellaneous magic */
+ case 8:
+ goods = MM;
+ for (i=0; i selection[i].worth)
+ min_worth = selection[i].worth;
+ }
+ break;
+ }
+
+ /* See if player can afford an item */
+ if (min_worth > purse) {
+ msg("The %s eyes your small purse and departs.",
+ monsters[NUMMONST].m_name);
+ /* Get rid of the monster */
+ killed(item, FALSE, FALSE);
+ return;
+ }
+
+ /* Display the goods */
+ msg("The %s shows you his wares.--More--", monsters[NUMMONST].m_name);
+ wait_for(cw,' ');
+ msg("");
+ clearok(cw, TRUE);
+ touchwin(cw);
+
+ wclear(hw);
+ touchwin(hw);
+ for (i=0; i < nitems; i++) {
+ mvwaddch(hw, i+2, 0, '[');
+ waddch(hw, (char) ((int) 'a' + i));
+ waddstr(hw, "] ");
+ switch (goods) {
+ case ARMOR:
+ waddstr(hw, "Some ");
+ when WEAPON:
+ if (selection[i].count == 1)
+ waddstr(hw, " A ");
+ else {
+ sprintf(buffer, "%2d ", selection[i].count);
+ waddstr(hw, buffer);
+ }
+ when STICK:
+ wprintw(hw, "A %-5s of ", ws_type[selection[i].which]);
+ when RING:
+ waddstr(hw, "A ring of ");
+ when SCROLL:
+ waddstr(hw, "A scroll of ");
+ when POTION:
+ waddstr(hw, "A potion of ");
+ }
+ if (selection[i].count > 1)
+ sprintf(buffer, "%s%s ", selection[i].name, "s");
+ else
+ sprintf(buffer, "%s ", selection[i].name);
+ wprintw(hw, "%-24s", buffer);
+ wprintw(hw, " Price:%5d", selection[i].worth);
+ }
+ sprintf(buffer, "Purse: %d", purse);
+ mvwaddstr(hw, nitems+3, 0, buffer);
+ mvwaddstr(hw, 0, 0, "How about one of the following goods? ");
+ draw(hw);
+ /* Get rid of the monster */
+ killed(item, FALSE, FALSE);
+
+ which_item = (int) (wgetch(hw) - 'a');
+ while (which_item < 0 || which_item >= nitems) {
+ if (which_item == (int) ESCAPE - (int) 'a') {
+ return;
+ }
+ mvwaddstr(hw, 0, 0, "Please enter one of the listed items. ");
+ draw(hw);
+ which_item = (int) (wgetch(hw) - 'a');
+ }
+
+ if (selection[which_item].worth > purse) {
+ msg("You cannot afford it.");
+ return;
+ }
+
+ purse -= selection[which_item].worth;
+
+ item = spec_item(goods, selection[which_item].which,
+ selection[which_item].plus1, selection[which_item].plus2);
+
+ obj = OBJPTR(item);
+ if (selection[which_item].count > 1) {
+ obj->o_count = selection[which_item].count;
+ obj->o_group = newgrp();
+ }
+ /* If a stick or ring, let player know the type */
+ switch (goods) {
+ case RING: r_know[selection[which_item].which] = TRUE;
+ when POTION:p_know[selection[which_item].which] = TRUE;
+ when SCROLL:s_know[selection[which_item].which] = TRUE;
+ when STICK: ws_know[selection[which_item].which] = TRUE;
+ when MM: m_know[selection[which_item].which] = TRUE;
+
+ }
+
+ 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 const char *mname;
+ bool nasty; /* Will the monster "attack"? */
+ char ch;
+
+ if ((it = find_mons(y, x)) == NULL) {
+ msg("Can't find monster in show");
+ return (NULL);
+ }
+ tp = THINGPTR(it);
+ ch = tp->t_type;
+
+ trp = roomin(&tp->t_pos); /* Current room for monster */
+ mname = monsters[tp->t_index].m_name;
+
+ /*
+ * 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 */
+ tp->t_dest = &cur->o_pos;
+ turn_on(*tp, ISRUN);
+ turn_off(*tp, ISDISGUISE);
+
+ /* 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) > 95)) &&
+ (off(player, ISINVIS) || on(*tp, CANSEE)) ||
+ (trp != NULL && (trp->r_flags & ISTREAS))) {
+ tp->t_dest = &hero;
+ turn_on(*tp, ISRUN);
+ turn_off(*tp, ISDISGUISE);
+ }
+
+ /* See if the monster will bother the player */
+ nasty = (on(*tp, ISRUN) && cansee(tp->t_pos.y, tp->t_pos.x));
+
+ /*
+ * Let the creature summon if it can.
+ * Also check to see if there is room around the player,
+ * if not then the creature will wait
+ */
+ if (on(*tp, CANSUMMON) && nasty &&
+ rnd(40) < tp->t_stats.s_lvl &&
+ fallpos(&hero, FALSE, 2) != NULL) {
+ const char *helpname;
+ int fail;
+ register int which, i;
+
+ turn_off(*tp, CANSUMMON);
+ helpname = monsters[tp->t_index].m_typesum;
+ for (which=1; which= NUMMONST)
+ debug("couldn't find summoned one");
+ 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("The %s appears dismayed", mname);
+ monsters[tp->t_index].m_numsum = 0;
+ }
+ else {
+ sprintf(outstring,"The %s summons %ss for help", mname, helpname);
+ msg(outstring);
+ }
+ }
+ else {
+ if (monsters[which].m_normal == FALSE) /* genocided? */
+ monsters[tp->t_index].m_numsum = 0;
+ else
+ msg("%ss seem to appear from nowhere!", helpname);
+ }
+ /*
+ * try to make all the creatures around player but remember
+ * if unsuccessful
+ */
+ for (i=0, fail=0; it_index].m_numsum; i++) {
+ if (!creat_mons(&player, which, FALSE))
+ fail++; /* remember the failures */
+ }
+ /*
+ * try once again to make the buggers
+ */
+ for (i=0; it_pos))) {
+ turn_on(player, ISFLEE);
+ player.t_dest = &tp->t_pos;
+ msg("The sight of the %s terrifies you.", mname);
+ }
+ }
+
+ /* blinding creatures */
+ if(on(*tp, CANBLIND) &&
+ !find_slot(sight) &&
+ !save(VS_WAND,&player, 0)){
+ msg("The gaze of the %s blinds you", mname);
+ 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 the %s ages you!", mname);
+ 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 the %s has no effect.", mname);
+ else {
+ if (!save(VS_PETRIFICATION, &player, 0) && rnd(100) < 15) {
+ pstats.s_hpt = -1;
+ msg("The gaze of the %s petrifies you.", mname);
+ msg("You are turned to stone !!! --More--");
+ wait_for(cw,' ');
+ death(D_PETRIFY);
+ }
+ else {
+ msg("The gaze of the %s stiffens your limbs.", mname);
+ no_command += STONETIME;
+ }
+ }
+ }
+ }
+
+ 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 const 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_dest = &hero;
+ tp->t_pos = cp; /* Assign the position to the monster */
+ seehim = cansee(tp->t_pos.y, tp->t_pos.x);
+ if (on(*tp, HASFIRE)) {
+ register struct room *rp;
+
+ rp = roomin(&tp->t_pos);
+ if (rp) {
+ register struct linked_list *fire_item;
+
+ fire_item = creat_item();
+ ldata(fire_item) = (char *) tp;
+ attach(rp->r_fires, fire_item);
+
+ rp->r_flags |= HASFIRE;
+ if (seehim && next(rp->r_fires) == NULL)
+ light(&hero);
+ }
+ }
+
+ /* See if we give the monster anything */
+ carry = monsters[tp->t_index].m_carry;
+ if (off(*tp, ISUNIQUE)) carry /= 2; /* Non-unique has only a half chance */
+ carry_obj(tp, carry);
+
+ /* Alert the player if a monster just teleported in */
+ if (hr == &rooms[i] && canteleport && seehim && !invisible(tp)) {
+ msg("A %s just teleported in", monsters[rmonst].m_name);
+ light(&hero);
+ running = FALSE;
+ }
+
+ if (wizard)
+ msg("Started a wandering %s", monsters[tp->t_index].m_name);
+}
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/move.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/move.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,1386 @@
+/*
+ * Hero movement commands
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+ * All rights reserved.
+ *
+ * Based on "Super-Rogue"
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * 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"
+
+/*
+ * Used to hold the new hero position
+ */
+
+static coord nh;
+
+static const char Moves[3][3] = {
+ { 'y', 'k', 'u' },
+ { 'h', '\0', '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;
+ register const char *mname = NULL;
+ register bool is_player = (th == &player),
+ can_see;
+ register struct linked_list *mitem = NULL;
+
+
+ /* 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 = monsters[th->t_index].m_name;
+ }
+ 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("The %s fell into a trap!", mname);
+
+ /* See if the fall killed the monster */
+ if ((th->t_stats.s_hpt -= roll(1, 10)) <= 0) {
+ killed(mitem, 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, ' ');
+ turn_on(*th, ISELSEWHERE);
+ detach(mlist, mitem);
+ attach(tlist, mitem); /* remember him next level */
+ }
+ }
+ when BEARTRAP:
+ if (is_stealth(th)) {
+ if (is_player) msg("You pass a bear trap.");
+ else if (can_see) msg("The %s passes a bear trap.", mname);
+ }
+ else {
+ th->t_no_move += BEARTIME;
+ if (is_player) msg("You are caught in a bear trap.");
+ else if (can_see) msg("The %s is caught in a bear trap.",
+ mname);
+ }
+ when SLEEPTRAP:
+ if (is_player) {
+ msg("A strange white mist envelops you.");
+ if (!ISWEARING(R_ALERT)) {
+ msg("You fall asleep.");
+ no_command += SLEEPTIME;
+ }
+ }
+ else {
+ if (can_see)
+ msg("A strange white mist envelops the %s.",mname);
+ if (on(*th, ISUNDEAD)) {
+ if (can_see)
+ msg("The mist doesn't seem to affect the %s.",mname);
+ }
+ else {
+ th->t_no_move += SLEEPTIME;
+ }
+ }
+ 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 the %s.", mname);
+ if ((th->t_stats.s_hpt -= roll(1, 6)) <= 0) {
+ if (can_see) msg("The arrow killed the %s.", mname);
+ killed(mitem, FALSE, FALSE);
+ }
+ }
+ }
+ 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 the %s.", mname);
+ 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("The %s seems to have disappeared!", mname);
+ }
+ 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 the %s in the shoulder.",
+ mname);
+ if ((th->t_stats.s_hpt -= roll(1,4)) <= 0) {
+ if (can_see) msg("The dart killed the %s.", mname);
+ killed(mitem, FALSE, FALSE);
+ }
+ 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 the %s.", mname);
+ killed(mitem, FALSE, FALSE);
+ }
+ }
+ }
+ }
+ else {
+ if (is_player)
+ msg("A small dart whizzes by your ear and vanishes.");
+ else if (can_see)
+ msg("A small dart whizzes by the %s's ear and vanishes.",
+ mname);
+ }
+ 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(cw,' ');
+ death(D_DROWN);
+ }
+ }
+ }
+ else {
+ if (i < 60) {
+ if (can_see) {
+ /* Drowns */
+ if (i < 30) msg("The %s drowned in the pool!", mname);
+
+ /* Teleported to another level */
+ else msg("The %s disappeared!", mname);
+ }
+ killed(mitem, FALSE, FALSE);
+ }
+ }
+ }
+ 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("The %s fell into a trap!", mname);
+ killed(mitem, FALSE, FALSE);
+ }
+ }
+
+ /* Move the cursor back onto the hero */
+ wmove(cw, hero.y, hero.x);
+
+ md_flushinp(); /* flush typeahead */
+
+ 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 = 0, locx = 0; /* 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 used once already");
+ return;
+ }
+ if ((what = get_item(pack, "dip", ALL)) == NULL) {
+ msg("");
+ after = FALSE;
+ return;
+ }
+ ob = OBJPTR(what);
+ mpos = 0;
+ 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]) {
+ msg("You'll have to take it off first.");
+ return;
+ }
+ 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;
+ sprintf(outstring,"The %s %s glows blue for a moment.",
+ ws_made[wh],ws_type[wh]);
+ msg(outstring);
+ }
+ 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;
+ sprintf(outstring,"The %s %s glows red for a moment.",
+ ws_made[wh],ws_type[wh]);
+ msg(outstring);
+ }
+ 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);
+ }
+ 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;
+ coord old_hero;
+ int i, wasfirstmove;
+
+ wasfirstmove = firstmove;
+ firstmove = FALSE;
+ curprice = -1; /* if in trading post, we've moved off obj */
+ if (player.t_no_move) {
+ player.t_no_move--;
+ msg("You are still stuck in the bear trap");
+ return;
+ }
+ /*
+ * Do a confused move (maybe)
+ */
+ if ((on(player, ISHUH) && rnd(100) < 80) ||
+ (on(player, ISDANCE) && rnd(100) < 80) ||
+ (ISWEARING(R_DELUSION) && rnd(100) < 25))
+ 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;
+ 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))
+ return;
+ }
+
+ /* Take care of hero being held */
+ if (on(player, ISHELD) && !isalpha(ch))
+ {
+ msg("You are being held");
+ return;
+ }
+
+ /* 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:
+ running = FALSE;
+ break;
+ case POST:
+ running = FALSE;
+ new_level(POSTLEV);
+ return;
+ default:
+ break;
+ }
+
+ if (isalpha(ch)) { /* if its a monster then fight it */
+ running = FALSE;
+ i = 1;
+ if (player.t_ctype == C_FIGHTER)
+ i += pstats.s_lvl/10;
+ while (i--)
+ fight(&nh, cur_weapon, FALSE);
+ return;
+ }
+
+ /*
+ * if not fighting then move the hero
+ */
+ 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);
+ }
+ 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 = 0, see_before = 0;
+
+ /* 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 (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);
+}
+
+/*
+ * 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;
+}
+
+
+
+/*
+ * 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 char selection = rnd(7) + '1';
+ register char ch = 0, och;
+ int thief_bonus = 0;
+ int s_dext;
+
+ switch (och = CCHAR( mvinch(y, x) )) {
+ case WALL:
+ case FLOOR:
+ case PASSAGE:
+ break;
+ default:
+ msg("The trap failed!");
+ return;
+ }
+
+ if (is_player && player.t_ctype == C_THIEF) thief_bonus = 30;
+
+ 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;
+ }
+
+
+ if (is_player) {
+ int state = 0; /* 0 -> current screen, 1 -> prompt screen, 2 -> done */
+
+ msg("Which kind of trap do you wish to set? (* for a list): ");
+ do {
+ selection = tolower(readchar());
+ switch (selection) {
+ case '*':
+ if (state != 1) {
+ wclear(hw);
+ touchwin(hw);
+ mvwaddstr(hw, 2, 0, "[1] Trap Door\n[2] Bear Trap\n");
+ waddstr(hw, "[3] Sleep Trap\n[4] Arrow Trap\n");
+ waddstr(hw, "[5] Teleport Trap\n[6] Dart Trap\n");
+ if (wizard) {
+ waddstr(hw, "[7] Magic pool\n[8] Maze Trap\n");
+ waddstr(hw, "[9] Trading Post\n");
+ }
+ mvwaddstr(hw, 0, 0, "Which kind of trap do you wish to set? ");
+ draw(hw);
+ state = 1; /* Now in prompt window */
+ }
+ break;
+
+ case ESCAPE:
+ if (state == 1) {
+ clearok(cw, TRUE); /* Set up for redraw */
+ touchwin(cw);
+ }
+ msg("");
+
+ trap_tries--; /* Don't count this one */
+ after = FALSE;
+ return;
+
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (selection < '7' || wizard) {
+ if (state == 1) { /* In prompt window */
+ clearok(cw, TRUE); /* Set up for redraw */
+ touchwin(cw);
+ }
+
+ msg("");
+
+ /* Make sure there is a floor below us for trap doors */
+ if (selection == '1' && level >= 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 */
+ mvwaddstr(hw, 0, 0, "Please enter a selection between 1 and 6: ");
+ draw(hw);
+ }
+ else { /* Normal window */
+ mpos = 0;
+ msg("Please enter a selection between 1 and 6: ");
+ }
+ }
+ } while (state != 2);
+ }
+
+ 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("Can't find monster in show");
+ 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;
+}
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/network.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/network.h Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,21 @@
+/*
+ * Networking information -- should not vary among networking machines
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#define SYSLEN 9
+#define LOGLEN 8
+#define NUMNET 6
+#undef NUMNET
+struct network {
+ char *system;
+ char *rogue;
+};
+extern struct network Network[];
+
+/* This system's name -- should not be defined if uname() is available */
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/new_level.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/new_level.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,579 @@
+/*
+ * new_level: Dig and draw a new level
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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(ltype)
+LEVTYPE ltype; /* designates type of level to create */
+{
+ register int rm = 0, 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 = 0, startx = 0, deltay = 0, deltax = 0;
+ bool fresh=TRUE, vert = 0, top;
+ struct room *rp;
+ struct linked_list *nitem, *savmonst=NULL, *savitems=NULL;
+ coord stairs = { 0, 0 };
+
+ 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;
+ }
+ }
+ 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++)
+ t_free_list(rp->r_exit); /* Free up the exit lists */
+
+ levtype = ltype;
+ foods_this_level = 0; /* food for hero this level */
+ if (ltype == POSTLEV) {
+ do_post(); /* do post stuff */
+ }
+ 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 */
+ cnt = 0;
+ do {
+ rm = rnd_room();
+ if (rooms[rm].r_flags & ISTREAS)
+ continue;
+ rnd_pos(&rooms[rm], &hero);
+ } until( cnt++ > 5000 ||
+ (winat(hero.y, hero.x) == FLOOR &&
+ DISTANCE(hero.y, hero.x, stairs.y, stairs.x) > 16));
+ }
+ 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();
+ light(&hero);
+ wmove(cw, hero.y, hero.x);
+ waddch(cw, PLAYER);
+
+ if (level > cur_max)
+ cur_max = level;
+
+ status(TRUE);
+}
+
+/*
+ * 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, *exitptr;
+ bool got_unique = FALSE;
+ 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
+ * Increasing chance after level 9
+ */
+ if (ltype != MAZELEV && rnd(HARDER) < level - 8) {
+ 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 = next(item)) {
+ register struct thing *tp;
+
+ tp = THINGPTR(item);
+ if (rp == roomin(&tp->t_pos)) {
+ turn_on(*tp, ISMEAN);
+ if (off(*tp, CANINWALL)) {
+ tp->t_dest = &hero;
+ turn_on(*tp, ISRUN);
+ }
+ if (on(*tp, ISUNIQUE))
+ got_unique = TRUE;
+
+ /* If it is a mimic, undisguise it */
+ if (on(*tp, ISDISGUISE))
+ turn_off(*tp, ISDISGUISE);
+ }
+ }
+
+
+ /* 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;
+
+ /* Make a monster */
+ item = new_item(sizeof *tp);
+ tp = THINGPTR(item);
+
+ /*
+ * Put it there and aggravate it (unless it can escape)
+ * only put one UNIQUE per treasure room at most
+ */
+ if (got_unique)
+ new_monster(item,randmonster(FALSE, TRUE),&trp,TRUE);
+ else
+ new_monster(item,randmonster(FALSE, FALSE),&trp,TRUE);
+ if (on(*tp, ISUNIQUE)) {
+ got_unique = TRUE;
+ carry_obj(tp, monsters[tp->t_index].m_carry);
+ }
+ turn_on(*tp, ISMEAN);
+ if (off(*tp, CANINWALL)) {
+ tp->t_dest = &hero;
+ turn_on(*tp, ISRUN);
+ }
+
+ /* If it is a mimic, undisguise it */
+ if (on(*tp, ISDISGUISE))
+ turn_off(*tp, ISDISGUISE);
+
+ 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;
+ }
+ }
+
+ /* Treasures */
+ if ((rnd(100) < (MAXTREAS*100)/(width*length)) &&
+ (mvinch(rp->r_pos.y+j, rp->r_pos.x+i) == FLOOR)) {
+ item = new_thing(ALL);
+ 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
+ */
+ for (i = 0; i < MAXOBJ; i++)
+ if (rnd(100) < 45) {
+ /*
+ * Pick a new object and link it in the list
+ */
+ item = new_thing(ALL);
+ 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 0ef99244acb8 -r 0ed67132cf10 arogue5/options.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/options.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,469 @@
+/*
+ * 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.
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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"
+
+#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 },
+ {"name", "Name: ",
+ (int *) whoami, put_str, get_str },
+ {"fruit", "Fruit: ",
+ (int *) fruit, 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 == cw)
+ 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(hw,' ');
+ 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[80];
+
+ /*
+ * 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, value);
+
+ else if (*op->o_opt == -1) { /* Only init ability once */
+ register int len = strlen(value);
+
+ if (isupper(value[0])) value[0] = tolower(value[0]);
+ if (EQSTR(value, "fighter", len))
+ *op->o_opt = C_FIGHTER;
+ else if (EQSTR(value, "magic", min(len, 5)))
+ *op->o_opt = C_MAGICIAN;
+ else if (EQSTR(value, "cleric", len))
+ *op->o_opt = C_CLERIC;
+ else if (EQSTR(value, "thief", len))
+ *op->o_opt = C_THIEF;
+ }
+ }
+ 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;
+{
+ char *abil;
+
+ switch (*ability) {
+ case C_MAGICIAN:abil = "Magic User";
+ when C_FIGHTER: abil = "Fighter";
+ when C_CLERIC: abil = "Cleric";
+ when C_THIEF: abil = "Thief";
+ otherwise: abil = "??";
+ }
+ waddstr(win, abil);
+}
+
+
+/*
+ * 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 0ef99244acb8 -r 0ed67132cf10 arogue5/outside.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/outside.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,210 @@
+/*
+ * functions for dealing with the "outside" level
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+ * 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;
+{
+ NOOP(place);
+}
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/pack.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/pack.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,1143 @@
+/*
+ * Routines to deal with the pack
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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"
+
+char outstring[512]; /* ridiculously long string for use with msg */
+
+/*
+ * 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 = NULL, *ap;
+ register struct object *obj, *op = NULL;
+ 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 ");
+ sprintf(outstring,"%s (%c)", inv_name(obj, !terse), pack_char(pack, obj));
+ msg(outstring);
+ }
+
+ /* Relics can do strange things when you pick them up */
+ if (obj->o_type == RELIC) {
+ cur_relic[obj->o_which]++; /* Note that we have it */
+ switch (obj->o_which) {
+ case HEIL_ANKH:
+ msg("The ankh welds itself into your hand.");
+
+ /* 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(cw,' ');
+ death(D_RELIC);
+ }
+ }
+
+ /* The amulet must be worn. */
+ when YENDOR_AMULET:
+ if (cur_misc[WEAR_JEWEL]) {
+ msg("You have an urge to remove your current amulet.");
+ if (!dropcheck(cur_misc[WEAR_JEWEL])) {
+ pstats.s_hpt = -1;
+ msg("The Amulet of Yendor begins pulsing.");
+ msg("It fades away.... -- More --");
+ wait_for(cw,' ');
+ death(D_RELIC);
+ }
+ }
+ msg("The amulet welds itself into your chest.");
+
+ /* Weapons will insist on being wielded. */
+ when MUSTY_DAGGER:
+ case HRUGGEK_MSTAR:
+ case YEENOGHU_FLAIL:
+ 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(cw,' ');
+ death(D_RELIC);
+ }
+ }
+ cur_weapon = obj;
+ }
+ }
+
+ updpack(FALSE);
+ if (packret != NULL)
+ *packret = item;
+ return(TRUE);
+}
+
+/*
+ * 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;
+ register int cnt;
+ char inv_temp[LINELEN];
+
+ 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');
+ }
+ /*
+ * Print the line for this object
+ */
+ default:
+ if (ch > 'z')
+ ch = 'A';
+ if (slow_invent){
+ sprintf(outstring,"%c) %s", ch, inv_name(obj, FALSE));
+ msg(outstring);
+ }
+ else {
+ if (++cnt >= LINES - 2) { /* if bottom of screen */
+ dbotline(hw, morestr);
+ cnt = 0;
+ wclear(hw);
+ }
+ wprintw(hw, "%c) %s\n", ch, inv_name(obj, FALSE));
+ }
+ }
+ }
+ if (n_objs == 0) {
+ if (terse)
+ msg(type == 0 ? "Empty handed." :
+ "Nothing appropriate");
+ else
+ msg(type == 0 ? "You are empty handed." :
+ "You don't have anything appropriate");
+ return FALSE;
+ }
+ if (n_objs == 1) {
+ msg(inv_temp);
+ return TRUE;
+ }
+ if (!slow_invent)
+ {
+ mvwaddstr(hw, LINES-1, 0, spacemsg);
+ draw(hw);
+ wait_for(hw,' ');
+ clearok(cw, TRUE);
+ touchwin(cw);
+ }
+ return TRUE;
+}
+
+/*
+ * pick_up:
+ * Add something to characters pack.
+ */
+pick_up(ch)
+char ch;
+{
+ switch (ch) {
+ default:
+ debug("Where did you pick that up???");
+ case GOLD:
+ case ARMOR:
+ case POTION:
+ case FOOD:
+ case WEAPON:
+ case SCROLL:
+ case MM:
+ case RING:
+ case STICK:
+ case RELIC:
+ while (add_pack(NULL, FALSE, NULL)); /* pick up everything there */
+ break;
+ }
+}
+
+/*
+ * 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) == 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)
+ {
+ sprintf(outstring, "%c) %s",ch ,inv_name(OBJPTR(item), FALSE));
+ msg(outstring);
+ 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)
+reg struct linked_list *list;
+char *purpose; /* NULL if we should be silent (no prompts) */
+int type;
+{
+ reg struct linked_list *item;
+ reg struct object *obj;
+ reg int cnt, ch, och;
+ struct linked_list *saveitem = NULL;
+
+ 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);
+ for(;;) {
+ if (purpose) { /* Should we prompt the player? */
+ msg("%s what (* for the item)? ",purpose);
+ ch = tolower(readchar());
+ }
+ else {
+ sprintf(outstring, "%c) %s", pack_char(list, obj), inv_name(obj,FALSE));
+ msg(outstring);
+ }
+
+ if (ch == '*') {
+ mpos = 0;
+ sprintf(outstring, "%c) %s", pack_char(list, obj), inv_name(obj,FALSE));
+ msg(outstring);
+ 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);
+
+ }
+ }
+ for(;;) {
+ if (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);
+ cnt = 0;
+ for(item = list,ch = 'a'; item != NULL ; item = next(item), ch++) {
+ obj = OBJPTR(item);
+ if (!is_type(OBJPTR(item), type))
+ continue;
+ wprintw(hw,"%c) %s\n\r",ch,inv_name(obj,FALSE));
+ if (++cnt >= LINES - 2 && next(item) != NULL) {
+ cnt = 0;
+ dbotline(hw, spacemsg);
+ wclear(hw);
+ }
+ if (ch == 'z') ch = 'A' - 1;
+ }
+ wmove(hw, LINES - 1,0);
+ if (purpose) wprintw(hw,"%s what? ",purpose);
+ else waddstr(hw, spacemsg);
+
+ draw(hw); /* write screen */
+
+ if (purpose) {
+ do {
+ ch = tolower(wgetch(hw));
+ } until (isalpha(ch) || ch == ESCAPE);
+ }
+ else {
+ ch = pack_char(list, OBJPTR(saveitem)); /* Pick a valid item */
+ wait_for(hw,' ');
+ }
+
+ restscr(cw); /* redraw orig screen */
+ 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 (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 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:
+ 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:
+ case POTION:
+ case STICK:
+ case SCROLL:
+ case MM:
+ 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 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_JUG:
+ case MM_BEAKER:
+ case MM_BOOK:
+ case MM_SKILLS:
+ 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 GERYON_HORN:
+ 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
+ */
+ if (on(*mp, CARRYDAGGER)) {
+ 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, CARRYAMULET)) {
+ 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, 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, 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 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) - 2;
+ dam = rnd(5) - 2;
+
+ /* Only choose an appropriate type of weapon */
+ switch (rnd(11)) {
+ 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;
+ 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 scroll, give it one
+ */
+ if (on(*mp, CARRYSCROLL) && rnd(100) < chance) {
+ item = new_thing(TYP_SCROLL);
+ 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);
+ 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);
+ 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);
+ 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);
+ obj = OBJPTR(item);
+ obj->o_pos = mp->t_pos;
+ attach(mp->t_pack, item);
+ }
+}
+
+
+/*
+ * 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;
+ 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.");
+
+ /* One thing there */
+ else if (num_there == 1) {
+ add_pack(FALSE, FALSE, NULL);
+ return(1);
+ }
+
+ /* Multiple things there */
+ else {
+ wclear(hw);
+ cnt = 0;
+ for (item = lvl_obj, ch = 'a'; item != NULL && cnt < num_there;
+ item = next(item), ch++) {
+ obj = OBJPTR(item);
+ wprintw(hw,"%c) %s\n\r", ch, inv_name(obj,FALSE));
+ if (++cnt >= LINES - 2 && next(item) != NULL) {
+ cnt = 0;
+ dbotline(hw, spacemsg);
+ wclear(hw);
+ }
+ if (ch == 'z') ch = 'A' - 1;
+ }
+ wmove(hw, LINES - 1,0);
+ wprintw(hw, "Pick up what? (* for all): ");
+ draw(hw); /* write screen */
+
+ for (;;) {
+ do {
+ ch = tolower(wgetch(hw));
+ } until (isalpha(ch) || ch == '*' || ch == ESCAPE);
+ restscr(cw); /* redraw orig screen */
+ if (ch == ESCAPE) {
+ after = FALSE;
+ msg(""); /* clear top line */
+ break;
+ }
+ if (ch == '*') {
+ while (add_pack(NULL, TRUE, NULL)); /* pick up everything there */
+ return(num_there);
+ }
+ /* 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, LINES - 1, 25);
+ wprintw(hw, " [between 'a' and '%c']:%c ",
+ och == 'A' ? 'z' : och-1, '\007');
+ draw(hw); /* write screen */
+ continue;
+ }
+ else {
+ detach(lvl_obj, item);
+ if (add_pack(item, FALSE, NULL)) {
+ /*
+ * There should always be at least one item left since we
+ * handle the one item case up above. But it never hurts
+ * to make sure we don't have a NULL pointer.
+ */
+ if ((item = find_obj(hero.y, hero.x)) == NULL)
+ mvaddch(y, x, (OBJPTR(item))->o_type);
+ return(1);
+ }
+ else attach(lvl_obj, item); /* Couldn't pick it up! */
+ break;
+ }
+ }
+ }
+
+ return(0);
+}
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/passages.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/passages.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,284 @@
+/*
+ * Draw the connecting passages
+ *
+ * @(#)passages.c 3.4 (Berkeley) 6/15/81
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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"
+
+/*
+ * do_passages:
+ * Draw all the passages on a level.
+ */
+
+do_passages()
+{
+ register struct rdes *r1, *r2 = NULL;
+ 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 = NULL;
+ register char rmt;
+ register int distance = 0, turn_spot = 0, turn_distance = 0;
+ register int rm;
+ register char direc;
+ coord delta = { 0, 0 }, curr, turn_delta = { 0, 0 }, spos = { 0, 0 }, epos = { 0, 0 };
+
+ if (r1 < r2)
+ {
+ rm = r1;
+ if (r1 + 1 == r2)
+ direc = 'r';
+ else
+ direc = 'd';
+ }
+ else
+ {
+ rm = r2;
+ if (r2 + 1 == r1)
+ direc = 'r';
+ else
+ direc = 'd';
+ }
+ rpf = &rooms[rm];
+ /*
+ * Set up the movement variables, in two cases:
+ * first drawing one down.
+ */
+ if (direc == 'd')
+ {
+ rmt = rm + 3; /* room # of dest */
+ rpt = &rooms[rmt]; /* room pointer of dest */
+ 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);
+ turn_distance = abs(spos.x - epos.x); /* how far to turn */
+ turn_spot = rnd(distance-1) + 1; /* where turn starts */
+ }
+ else if (direc == 'r') /* setup for moving right */
+ {
+ rmt = rm + 1;
+ rpt = &rooms[rmt];
+ 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;
+ turn_distance = abs(spos.y - epos.y);
+ turn_spot = rnd(distance-1) + 1;
+ }
+ else
+ debug("error in connection tables");
+ /*
+ * Draw in the doors on either side of the passage or just put #'s
+ * if the rooms are gone.
+ */
+ if (!(rpf->r_flags & ISGONE)) door(rpf, &spos);
+ else
+ {
+ cmov(spos);
+ addch('#');
+ }
+ if (!(rpt->r_flags & ISGONE)) door(rpt, &epos);
+ else
+ {
+ cmov(epos);
+ addch('#');
+ }
+ /*
+ * Get ready to move...
+ */
+ curr.x = spos.x;
+ curr.y = spos.y;
+ while(distance)
+ {
+ /*
+ * Move to new position
+ */
+ curr.x += delta.x;
+ curr.y += delta.y;
+ /*
+ * Check if we are at the turn place, if so do the turn
+ */
+ if (distance == turn_spot && turn_distance > 0)
+ while(turn_distance--)
+ {
+ cmov(curr);
+ addch(PASSAGE);
+ curr.x += turn_delta.x;
+ curr.y += turn_delta.y;
+ }
+ /*
+ * Continue digging along
+ */
+ cmov(curr);
+ addch(PASSAGE);
+ distance--;
+ }
+ curr.x += delta.x;
+ curr.y += delta.y;
+ if (!ce(curr, epos))
+ msg("Warning, connectivity problem on this level.");
+}
+
+/*
+ * 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 0ef99244acb8 -r 0ed67132cf10 arogue5/player.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/player.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,587 @@
+/*
+ * This file contains functions for dealing with special player abilities
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "curses.h"
+#include "rogue.h"
+
+
+/*
+ * affect:
+ * cleric affecting undead
+ */
+
+affect()
+{
+ register struct linked_list *item;
+ register struct thing *tp;
+ register const char *mname;
+ bool see;
+ coord new_pos;
+
+ if (player.t_ctype != C_CLERIC && cur_relic[HEIL_ANKH] == 0) {
+ msg("Only clerics can affect undead.");
+ return;
+ }
+
+ new_pos.y = hero.y + delta.y;
+ new_pos.x = hero.x + delta.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 = monsters[tp->t_index].m_name;
+
+ if (on(player, ISINVIS) && off(*tp, CANSEE)) {
+ sprintf(outstring,"%s%s cannot see you", see ? "The " : "It",
+ see ? mname : "");
+ msg(outstring);
+ return;
+ }
+
+ if (off(*tp, TURNABLE) || on(*tp, WASTURNED))
+ goto annoy;
+ turn_off(*tp, TURNABLE);
+
+ /* Can cleric kill it? */
+ if (pstats.s_lvl >= 3 * tp->t_stats.s_lvl) {
+ unsigned long test; /* For overflow check */
+
+ sprintf(outstring,"You have destroyed %s%s.", see ? "the " : "it", see ? mname : "");
+ msg(outstring);
+ 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);
+ check_level(TRUE);
+ return;
+ }
+
+ /* Can cleric turn it? */
+ if (rnd(100) + 1 >
+ (100 * ((2 * tp->t_stats.s_lvl) - pstats.s_lvl)) / pstats.s_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);
+
+ /* Let player know */
+ sprintf(outstring,"You have turned %s%s.", see ? "the " : "it", see ? mname : "");
+ msg(outstring);
+
+ /* 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(TRUE);
+
+ /* 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);
+ return;
+ }
+
+ /* Otherwise -- no go */
+annoy:
+ sprintf(outstring,"You do not affect %s%s.", see ? "the " : "it", see ? mname : "");
+ msg(outstring);
+
+ /* Annoy monster */
+ if (off(*tp, ISFLEE)) runto(tp, &hero);
+}
+
+/*
+ * the magic user is going to try and cast a spell
+ */
+cast()
+{
+ register int i, num_spells, spell_ability;
+ int which_spell;
+ bool nohw = FALSE;
+
+ i = num_spells = spell_ability = which_spell = 0;
+
+ if (player.t_ctype != C_MAGICIAN && pstats.s_intel < 16) {
+ msg("You are not permitted to cast spells.");
+ return;
+ }
+ if (cur_misc[WEAR_CLOAK] != NULL &&
+ cur_misc[WEAR_CLOAK]->o_which == MM_R_POWERLESS) {
+ msg("You can't seem to cast a spell!");
+ return;
+ }
+ num_spells = 0;
+
+ /* Get the number of avilable spells */
+ if (pstats.s_intel >= 16)
+ num_spells = pstats.s_intel - 15;
+
+ if (player.t_ctype == C_MAGICIAN)
+ num_spells += pstats.s_lvl;
+
+ if (num_spells > MAXSPELLS)
+ num_spells = MAXSPELLS;
+
+ spell_ability = pstats.s_lvl * pstats.s_intel;
+ if (player.t_ctype != C_MAGICIAN)
+ spell_ability /= 2;
+
+ /* Prompt for spells */
+ msg("Which spell are you casting? (* for list): ");
+
+ which_spell = (int) (readchar() - 'a');
+ if (which_spell == (int) ESCAPE - (int) 'a') {
+ mpos = 0;
+ msg("");
+ after = FALSE;
+ return;
+ }
+ if (which_spell >= 0 && which_spell < num_spells) nohw = TRUE;
+
+ else if (slow_invent) {
+ register char c;
+
+ for (i=0; i= num_spells) {
+ if (which_spell == (int) ESCAPE - (int) 'a') {
+ after = FALSE;
+ return;
+ }
+ wmove(hw, 0, 0);
+ wclrtoeol(hw);
+ waddstr(hw, "Please enter one of the listed spells. ");
+ draw(hw);
+ which_spell = (int) (wgetch(hw) - 'a');
+ }
+ }
+
+ if ((spell_power + magic_spells[which_spell].s_cost) > spell_ability) {
+ msg("Your attempt fails.");
+ return;
+ }
+ if (nohw)
+ msg("Your spell is successful.");
+ else {
+ mvwaddstr(hw, 0, 0, "Your spell is successful.--More--");
+ wclrtoeol(hw);
+ draw(hw);
+ wait_for(hw,' ');
+ }
+ if (magic_spells[which_spell].s_type == TYP_POTION)
+ quaff( magic_spells[which_spell].s_which,
+ 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 (!do_zap( TRUE,
+ magic_spells[which_spell].s_which,
+ magic_spells[which_spell].s_flag)) {
+ after = FALSE;
+ return;
+ }
+ }
+ spell_power += magic_spells[which_spell].s_cost;
+}
+
+/* Constitution bonus */
+
+const_bonus() /* Hit point adjustment for changing levels */
+{
+ if (pstats.s_const > 6 && pstats.s_const <= 14)
+ return(0);
+ if (pstats.s_const > 14)
+ return(pstats.s_const-14);
+ if (pstats.s_const > 3)
+ return(-1);
+ return(-2);
+}
+
+
+/* Routines for thieves */
+
+/*
+ * gsense:
+ * Sense gold
+ */
+
+gsense()
+{
+ /* Only thieves can do this */
+ if (player.t_ctype != C_THIEF) {
+ msg("You seem to have no gold sense.");
+ return;
+ }
+
+ if (lvl_obj != NULL) {
+ struct linked_list *gitem;
+ struct object *cur;
+ int gtotal = 0;
+
+ wclear(hw);
+ for (gitem = lvl_obj; gitem != NULL; gitem = next(gitem)) {
+ cur = OBJPTR(gitem);
+ if (cur->o_type == GOLD) {
+ gtotal += cur->o_count;
+ mvwaddch(hw, cur->o_pos.y, cur->o_pos.x, GOLD);
+ }
+ }
+ if (gtotal) {
+ s_know[S_GFIND] = TRUE;
+ msg("You sense gold!");
+ overlay(hw,cw);
+ return;
+ }
+ }
+ msg("You can sense no gold on this level.");
+}
+
+/*
+ * the cleric asks his deity for a spell
+ */
+pray()
+{
+ register int i, num_prayers, prayer_ability;
+ int which_prayer;
+ bool nohw = FALSE;
+
+ which_prayer = num_prayers = prayer_ability = i = 0;
+
+ if (player.t_ctype != C_CLERIC && pstats.s_wisdom < 17 &&
+ 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;
+ }
+ num_prayers = 0;
+
+ /* Get the number of avilable prayers */
+ if (pstats.s_wisdom > 16)
+ num_prayers = (pstats.s_wisdom - 15) / 2;
+
+ if (player.t_ctype == C_CLERIC)
+ num_prayers += pstats.s_lvl;
+
+ if (cur_relic[HEIL_ANKH]) num_prayers += 3;
+
+ if (num_prayers > MAXPRAYERS)
+ num_prayers = MAXPRAYERS;
+
+ prayer_ability = pstats.s_lvl * pstats.s_wisdom;
+ if (player.t_ctype != C_CLERIC)
+ prayer_ability /= 2;
+
+ if (cur_relic[HEIL_ANKH]) prayer_ability *= 2;
+
+ /* Prompt for prayer */
+ msg("Which prayer are you offering? (* for list): ");
+ which_prayer = (int) (readchar() - 'a');
+ if (which_prayer == (int) ESCAPE - (int) 'a') {
+ mpos = 0;
+ msg("");
+ after = FALSE;
+ return;
+ }
+ if (which_prayer >= 0 && which_prayer < num_prayers) nohw = TRUE;
+
+ else if (slow_invent) {
+ register char c;
+
+ for (i=0; i= num_prayers) {
+ if (which_prayer == (int) ESCAPE - (int) 'a') {
+ after = FALSE;
+ return;
+ }
+ wmove(hw, 0, 0);
+ wclrtoeol(hw);
+ mvwaddstr(hw, 0, 0, "Please enter one of the listed prayers.");
+ draw(hw);
+ which_prayer = (int) (wgetch(hw) - 'a');
+ }
+ }
+
+
+ if (cleric_spells[which_prayer].s_cost + pray_time > prayer_ability) {
+ msg("Your prayer fails.");
+ return;
+ }
+
+ if (nohw)
+ msg("Your prayer has been granted.");
+ else {
+ mvwaddstr(hw, 0, 0, "Your prayer has been granted.--More--");
+ wclrtoeol(hw);
+ draw(hw);
+ wait_for(hw,' ');
+ }
+ if (cleric_spells[which_prayer].s_type == TYP_POTION)
+ quaff( cleric_spells[which_prayer].s_which,
+ 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 (!do_zap( TRUE,
+ 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 const char *mname;
+ coord new_pos;
+ int thief_bonus = -50;
+ bool isinvisible = FALSE;
+
+ new_pos.y = hero.y + delta.y;
+ new_pos.x = hero.x + delta.x;
+
+ if (on(player, ISBLIND)) {
+ msg("You can't see anything.");
+ return;
+ }
+
+ /* 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 (isinvisible = invisible(tp)) mname = "creature";
+ else mname = monsters[tp->t_index].m_name;
+
+ /* Can player steal something unnoticed? */
+ if (player.t_ctype == C_THIEF) thief_bonus = 10;
+ if (on(*tp, ISUNIQUE)) thief_bonus -= 15;
+ if (isinvisible) thief_bonus -= 20;
+ if (on(*tp, ISINWALL) && off(player, CANINWALL)) thief_bonus -= 50;
+
+ if (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 &&
+ rnd(++count) == 0)
+ s_item = pack_ptr;
+
+ /*
+ * Find anything?
+ *
+ * if we have a merchant, and his pack is empty then the
+ * rogue has already stolen once
+ */
+ if (s_item == NULL) {
+ if (tp->t_index == NUMMONST)
+ msg("The %s seems to be shielding his pack from you.", mname);
+ else
+ msg("The %s apparently has nothing to steal.", mname);
+ return;
+ }
+
+ /* Take it from monster */
+ if (tp->t_pack) detach(tp->t_pack, s_item);
+
+ /* 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(TRUE);
+ }
+
+ else {
+ msg("Your attempt fails.");
+
+ /* Annoy monster (maybe) */
+ if (rnd(35) >= dex_compute() + thief_bonus) {
+ if (tp->t_index == NUMMONST) {
+ if (!isinvisible)
+ msg("The %s looks insulted and leaves", mname);
+ killed(item, FALSE, FALSE);
+ }
+ else
+ runto(tp, &hero);
+ }
+ }
+}
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/potions.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/potions.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,698 @@
+/*
+ * Function(s) for dealing with potions
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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"
+
+
+
+/*
+ * Increase player's constitution
+ */
+
+add_const(cursed)
+bool cursed;
+{
+ /* Do the potion */
+ if (cursed) {
+ msg("You feel less healthy now.");
+ pstats.s_const--;
+ if (pstats.s_const <= 0)
+ death(D_CONSTITUTION);
+ }
+ else {
+ msg("You feel healthier now.");
+ pstats.s_const = min(pstats.s_const + 1, 25);
+ }
+
+ /* Adjust the maximum */
+ if (max_stats.s_const < pstats.s_const)
+ max_stats.s_const = pstats.s_const;
+}
+
+/*
+ * Increase player's dexterity
+ */
+
+add_dexterity(cursed)
+bool cursed;
+{
+ 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 (cursed) {
+ msg("You feel less dextrous now.");
+ pstats.s_dext--;
+ }
+ else {
+ msg("You feel more dextrous now. Watch those hands!");
+ pstats.s_dext = min(pstats.s_dext + 1, 25);
+ }
+
+ /* 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 (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.");
+ no_command += rnd(hasttime);
+ lengthen(nohaste, roll(hasttime,hasttime));
+ }
+ else {
+ turn_on(player, ISHASTE);
+ fuse(nohaste, 0, roll(hasttime, hasttime), AFTER);
+ }
+}
+
+/*
+ * Increase player's intelligence
+ */
+add_intelligence(cursed)
+bool cursed;
+{
+ 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 (cursed) {
+ msg("You feel slightly less intelligent now.");
+ pstats.s_intel--;
+ }
+ else {
+ msg("You feel more intelligent now. What a mind!");
+ pstats.s_intel = min(pstats.s_intel + 1, 25);
+ }
+
+ /* 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()
+{
+ 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);
+ player.t_turn = TRUE;
+ fuse(noslow, 0, roll(HASTETIME,HASTETIME), AFTER);
+ }
+ }
+}
+
+/*
+ * Increase player's strength
+ */
+
+add_strength(cursed)
+bool cursed;
+{
+
+ if (cursed) {
+ msg("You feel slightly weaker now.");
+ chg_str(-1);
+ }
+ else {
+ msg("You feel stronger now. What bulging muscles!");
+ chg_str(1);
+ }
+}
+
+/*
+ * Increase player's wisdom
+ */
+
+add_wisdom(cursed)
+bool cursed;
+{
+ 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 (cursed) {
+ msg("You feel slightly less wise now.");
+ pstats.s_wisdom--;
+ }
+ else {
+ msg("You feel wiser now. What a sage!");
+ pstats.s_wisdom = min(pstats.s_wisdom + 1, 25);
+ }
+
+ /* 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;
+}
+
+
+/*
+ * Lower a level of experience
+ */
+
+lower_level(who)
+short who;
+{
+ int fewer, nsides = 0;
+
+ if (--pstats.s_lvl == 0)
+ death(who); /* All levels gone */
+ msg("You suddenly feel less skillful.");
+ pstats.s_exp /= 2;
+ switch (player.t_ctype) {
+ case C_FIGHTER: nsides = HIT_FIGHTER;
+ when C_MAGICIAN:nsides = HIT_MAGICIAN;
+ when C_CLERIC: nsides = HIT_CLERIC;
+ when C_THIEF: nsides = HIT_THIEF;
+ }
+ 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);
+}
+
+quaff(which, flag, is_potion)
+int which;
+int flag;
+bool is_potion;
+{
+ register struct object *obj = NULL;
+ register struct linked_list *item, *titem;
+ register struct thing *th;
+ bool cursed, blessed;
+ char buf[LINELEN];
+
+ blessed = FALSE;
+ cursed = FALSE;
+ item = NULL;
+
+ if (which < 0) { /* figure out which ourselves */
+ item = get_item(pack, "quaff", POTION);
+ /*
+ * Make certain that it is somethings that we want to drink
+ */
+ if (item == NULL)
+ return;
+
+ obj = OBJPTR(item);
+ /* remove it from the pack */
+ inpack--;
+ detach(pack, item);
+
+ /*
+ * Calculate the effect it has on the poor guy.
+ */
+ 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 P_CLEAR:
+ if (cursed) {
+ if (off(player, ISCLEAR))
+ {
+ msg("Wait, what's going on here. Huh? What? Who?");
+ if (find_slot(unconfuse))
+ lengthen(unconfuse, rnd(8)+HUHDURATION);
+ else
+ fuse(unconfuse, 0, rnd(8)+HUHDURATION, AFTER);
+ turn_on(player, ISHUH);
+ }
+ else msg("You feel dizzy for a moment, but it quickly passes.");
+ }
+ 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) == FALSE)
+ 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) {
+ if (!save(VS_POISON, &player, 0)) {
+ msg("You feel very sick now.");
+ pstats.s_hpt /= 2;
+ pstats.s_const--;
+ if (pstats.s_const <= 0 || pstats.s_hpt <= 0)
+ death(D_POISON);
+ }
+ else msg("You feel momentarily sick.");
+ }
+ else {
+ if (blessed) {
+ if ((pstats.s_hpt += roll(pstats.s_lvl, 8)) > max_stats.s_hpt)
+ pstats.s_hpt = ++max_stats.s_hpt;
+ if (on(player, ISHUH)) {
+ extinguish(unconfuse);
+ unconfuse();
+ }
+ }
+ else {
+ if ((pstats.s_hpt += roll(pstats.s_lvl, 4)) > 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:
+ {
+ int ctype;
+
+ /*
+ * if blessed then fix all attributes
+ */
+ if (blessed) {
+ add_intelligence(FALSE);
+ add_dexterity(FALSE);
+ add_strength(FALSE);
+ add_wisdom(FALSE);
+ add_const(FALSE);
+ }
+ /* probably will be own ability */
+ else {
+ if (rnd(100) < 70)
+ ctype = player.t_ctype;
+ else do {
+ ctype = rnd(4);
+ } while (ctype == player.t_ctype);
+
+ /* Small chance of doing constitution instead */
+ if (rnd(100) < 10)
+ add_const(cursed);
+ else switch (ctype) {
+ case C_FIGHTER: add_strength(cursed);
+ when C_MAGICIAN: add_intelligence(cursed);
+ when C_CLERIC: add_wisdom(cursed);
+ when C_THIEF: add_dexterity(cursed);
+ otherwise: msg("You're a strange type!");
+ }
+ }
+ if (is_potion) p_know[P_ABIL] = TRUE;
+ }
+ when P_MFIND:
+ /*
+ * Potion of monster detection, if there are monters, detect them
+ */
+ if (mlist != NULL)
+ {
+ msg("You begin to sense the presence of monsters.");
+ waddstr(cw, morestr);
+ overlay(mw, cw);
+ draw(cw);
+ wait_for(cw,' ');
+ 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
+ */
+ if (lvl_obj != NULL)
+ {
+ 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);
+ }
+ if (is_potion) p_know[P_TFIND] = TRUE;
+ }
+ for (titem = mlist; titem != NULL; titem = next(titem)) {
+ register struct linked_list *pitem;
+
+ th = THINGPTR(titem);
+ 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 (is_potion) p_know[P_TFIND] = TRUE;
+ }
+ }
+ if (show) {
+ msg("You sense the presence of magic on this level.");
+ waddstr(cw, morestr);
+ overlay(hw,cw);
+ draw(cw);
+ wait_for(cw,' ');
+ msg("");
+ break;
+ }
+ }
+ 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) != FALSE)
+ lengthen(unsee, blessed ? SEEDURATION*3 : SEEDURATION);
+ sight();
+ }
+ when P_PHASE:
+ if (cursed) {
+ msg("You can't move.");
+ no_command = FREEZETIME;
+ }
+ 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)
+ 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(TRUE);
+ if (blessed) raise_level(TRUE);
+ }
+ when P_HASTE:
+ if (cursed) { /* Slow player down */
+ add_slow();
+ }
+ else {
+ if (off(player, ISSLOW))
+ msg("You feel yourself moving %sfaster.",
+ blessed ? "much " : "");
+ add_haste(blessed);
+ if (is_potion) p_know[P_HASTE] = TRUE;
+ }
+ when P_RESTORE: {
+ register int i;
+
+ msg("Hey, this tastes great. It make you feel warm all over.");
+ if (lost_str) {
+ extinguish(res_strength);
+ lost_str = 0;
+ }
+ for (i=0; io_flags & ISKNOW) == 0 &&
+ (obj->o_flags & ISPOST) == 0 &&
+ p_guess[which] == NULL)
+ {
+ msg(terse ? "Call it: " : "What do you want to call it? ");
+ if (get_str(buf, cw) == NORM)
+ {
+ p_guess[which] = new((unsigned int) strlen(buf) + 1);
+ strcpy(p_guess[which], buf);
+ }
+ }
+ if (item != NULL) o_discard(item);
+ updpack(TRUE);
+}
+
+
+/*
+ * res_dexterity:
+ * Restore player's dexterity
+ * if called with zero the restore fully
+ */
+
+res_dexterity(howmuch)
+int howmuch;
+{
+ short save_max;
+ int ring_str;
+
+ /* 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
+ */
+
+res_intelligence()
+{
+ short save_max;
+ int ring_str;
+
+ /* Discount the ring value */
+ ring_str = ring_value(R_ADDINTEL);
+ pstats.s_intel -= ring_str;
+
+ if (pstats.s_intel < max_stats.s_intel ) pstats.s_intel = 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
+ */
+
+res_wisdom()
+{
+ short save_max;
+ int ring_str;
+
+ /* Discount the ring value */
+ ring_str = ring_value(R_ADDWISDOM);
+ pstats.s_wisdom -= ring_str;
+
+ if (pstats.s_wisdom < max_stats.s_wisdom )
+ pstats.s_wisdom = 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;
+ }
+}
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/rings.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/rings.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,161 @@
+/*
+ * routines dealing specifically with rings
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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"
+
+/*
+ * 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(obj)
+register struct object *obj;
+{
+ register int save_max;
+ char buf[LINELEN];
+
+ /*
+ * 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();
+ 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) {
+ msg(terse ? "Call it: " : "What do you want to call it? ");
+ if (get_str(buf, cw) == NORM)
+ {
+ r_guess[obj->o_which] = new((unsigned int) strlen(buf) + 1);
+ strcpy(r_guess[obj->o_which], buf);
+ }
+ msg("");
+ }
+}
+
+/*
+ * 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_HEAVY:
+ 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 0ef99244acb8 -r 0ed67132cf10 arogue5/rip.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/rip.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,768 @@
+/*
+ * File for the fun ends
+ * Death or a total win
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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 */
+
+#include
+#include
+#include
+#include "curses.h"
+#include
+#include
+#include
+#include
+#include "network.h"
+#include "rogue.h"
+#include "mach_dep.h"
+
+/*
+ * 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[LINELEN];
+ char sc_system[SYSLEN];
+ char sc_login[LOGLEN];
+ short sc_flgs;
+ short sc_level;
+ short sc_ctype;
+ short sc_monster;
+ short sc_quest;
+};
+
+#define SCORELEN \
+ (sizeof(unsigned long) + LINELEN + SYSLEN + LOGLEN + 5*sizeof(short))
+
+static char *rip[] = {
+" __________",
+" / \\",
+" / REST \\",
+" / IN \\",
+" / PEACE \\",
+" / \\",
+" | |",
+" | |",
+" | killed by |",
+" | |",
+" | 1984 |",
+" *| * * * | *",
+" ________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______",
+ 0
+};
+
+char *killname();
+
+
+
+
+
+void
+byebye(sig)
+int sig;
+{
+ NOOP(sig);
+ if (!isendwin()) {
+ clear();
+ endwin();
+ }
+ 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[80];
+ 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);
+ exit(0);
+}
+
+char *
+killname(monst)
+register short monst;
+{
+ static char mons_name[LINELEN];
+ int i;
+
+ if (monst > NUMMONST) return("a strange monster");
+
+ if (monst >= 0) {
+ switch (monsters[monst].m_name[0]) {
+ case 'a':
+ case 'e':
+ case 'i':
+ case 'o':
+ case 'u':
+ sprintf(mons_name, "an %s", monsters[monst].m_name);
+ break;
+ default:
+ sprintf(mons_name, "a %s", monsters[monst].m_name);
+ }
+ return(mons_name);
+ }
+ for (i = 0; i< DEATHNUM; i++) {
+ if (deaths[i].reason == monst)
+ break;
+ }
+ if (i >= DEATHNUM)
+ return ("strange death");
+ return (deaths[i].name);
+}
+
+
+/*
+ * score -- figure score and post it.
+ */
+
+/* VARARGS2 */
+score(amount, flags, monst)
+unsigned long amount;
+short monst;
+{
+ static struct sc_ent top_ten[NUMSCORE];
+ register struct sc_ent *scp;
+ register int i;
+ register struct sc_ent *sc2;
+ register FILE *outf;
+ register char *killer;
+ register int prflags = 0;
+ register int fd;
+ short upquest = 0, wintype = 0, uplevel = 0, uptype = 0; /* 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 */
+#define REASONLEN 3
+ static char *reason[] = {
+ "killed",
+ "quit",
+ "A total winner",
+ "somehow left",
+ };
+ char *packend;
+ memset(top_ten,0,sizeof(top_ten));
+ 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();
+ wgetnstr(cw,prbuf,80);
+ showpack(packend);
+ }
+ purse = 0; /* Steal all the gold */
+
+ /*
+ * Open file and read list
+ */
+
+ if ((fd = open(score_file, O_RDWR | O_CREAT, 0666)) < 0)
+ {
+ printf("\nCannot open score_file.\n");
+ return;
+ }
+ outf = (FILE *) fdopen(fd, "w");
+
+ /* Get this system's name */
+ thissys = md_gethostname();
+
+ for (scp = top_ten; scp <= &top_ten[NUMSCORE-1]; scp++)
+ {
+ scp->sc_score = 0L;
+ for (i = 0; i < 80; i++)
+ scp->sc_name[i] = rnd(255);
+ scp->sc_quest= RN;
+ scp->sc_flgs = 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);
+ wgetnstr(stdscr,prbuf,80);
+ }
+
+ /* 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 */
+ scorein(top_ten, fd); /* Convert it */
+
+ /* Get some values if this is an update */
+ if (flags == UPDATE) {
+ int errcheck, errors = 0;
+
+ upquest = (short) netread(&errcheck, sizeof(short), stdin);
+ if (errcheck) errors++;
+
+ if (fread(whoami, 1, LINELEN, stdin) != LINELEN) 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) {
+ fclose(outf);
+ free(compatstr);
+ return;
+ }
+ }
+
+ /*
+ * Insert player in list if need be
+ */
+ if (!waswizard) {
+ char *login = NULL;
+
+ 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[80];
+ int atoi();
+
+ 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, LINELEN);
+
+ /* 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);
+ switch (buffer[0]) {
+ case 'F':
+ case 'f':
+ default:
+ player.t_ctype = C_FIGHTER;
+ break;
+
+ case 'C':
+ case 'c':
+ player.t_ctype = C_CLERIC;
+ break;
+
+ case 'M':
+ case 'm':
+ player.t_ctype = C_MAGICIAN;
+ break;
+
+ case 'T':
+ case 't':
+ player.t_ctype = C_THIEF;
+ break;
+ }
+
+ /* Get the win type */
+ move(8, 8);
+ get_str(buffer, stdscr);
+ switch (buffer[0]) {
+ case 'W':
+ case 'w':
+ case 'T':
+ case 't':
+ flags = WINNER;
+ break;
+
+ case 'Q':
+ case 'q':
+ flags = CHICKEN;
+ break;
+
+ case 'k':
+ case 'K':
+ default:
+ flags = KILLED;
+ break;
+ }
+
+ /* Get the monster if player was killed */
+ if (flags == KILLED) {
+ mvaddstr(9, 0, "Death type: ");
+ get_str(buffer, stdscr);
+ if (buffer[0] == 'M' || buffer[0] == 'm')
+ monst = makemonster(FALSE);
+ else monst = getdeath();
+ }
+ }
+#endif
+
+ if (update(top_ten, amount, (short) quest_item, whoami, flags,
+ (flags == WINNER) ? (short) max_level : (short) level,
+ monst, player.t_ctype, thissys, login)
+#ifdef NUMNET
+ && fork() == 0 /* Spin off network process */
+#endif
+ ) {
+#ifdef NUMNET
+ /* Send this update to the other systems in the network */
+ int i, j;
+ char cmd[256]; /* Command for remote execution */
+ FILE *rmf, *popen(); /* For input to remote command */
+
+ for (i=0; i/dev/null",
+ Network[i].system, Network[i].rogue);
+
+ /* Execute the command */
+ if ((rmf=popen(cmd, "w")) != NULL) {
+ unsigned long temp; /* Temporary value */
+
+ /* Write out the parameters */
+ (void) netwrite((unsigned long) amount,
+ sizeof(unsigned long), rmf);
+
+ (void) netwrite((unsigned long) monst,
+ sizeof(short), rmf);
+
+ (void) netwrite((unsigned long) quest_item,
+ sizeof(short), rmf);
+
+ (void) fwrite(whoami, 1, strlen(whoami), rmf);
+ for (j=strlen(whoami); jsc_score != 0) {
+ switch (scp->sc_ctype) {
+ case C_FIGHTER: class = "fighter";
+ when C_MAGICIAN: class = "magician";
+ when C_CLERIC: class = "cleric";
+ when C_THIEF: class = "thief";
+ otherwise: class = "unknown";
+ }
+
+ /* Make sure we have an in-bound reason */
+ if (scp->sc_flgs > REASONLEN) scp->sc_flgs = 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_flgs],
+ scp->sc_level);
+
+ switch (scp->sc_flgs) {
+ 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);
+ fgets(prbuf,80,stdin);
+ 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 < 80; i++)
+ top_ten[NUMSCORE-1].sc_name[i] = rnd(255);
+ top_ten[NUMSCORE-1].sc_flgs = RN;
+ top_ten[NUMSCORE-1].sc_level = RN;
+ top_ten[NUMSCORE-1].sc_monster = RN;
+ scp--;
+ }
+ else if (prbuf[0] == 'e') {
+ printf("Death type: ");
+ fgets(prbuf,80,stdin);
+ if (prbuf[0] == 'M' || prbuf[0] == 'm')
+ scp->sc_monster = makemonster(FALSE);
+ 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 */
+ }
+ fseek(outf, 0L, 0);
+ /*
+ * Update the list file
+ */
+ scoreout(top_ten, outf);
+ fclose(outf);
+}
+
+/*
+ * scorein:
+ * Convert a character string that has been translated from a
+ * score file by scoreout() back to a score file structure.
+ */
+scorein(scores, fd)
+struct sc_ent scores[];
+int fd;
+{
+ int i;
+ char scoreline[100];
+
+ for(i = 0; i < NUMSCORE; i++)
+ {
+ encread((char *) &scores[i].sc_name, LINELEN, fd);
+ encread((char *) &scores[i].sc_system, SYSLEN, fd);
+ encread((char *) &scores[i].sc_login, LINELEN, fd);
+ encread((char *) scoreline, 100, fd);
+ sscanf(scoreline, " %lu %d %d %d %d %d \n",
+ &scores[i].sc_score, &scores[i].sc_flgs,
+ &scores[i].sc_level, &scores[i].sc_ctype,
+ &scores[i].sc_monster, &scores[i].sc_quest);
+ }
+}
+
+/*
+ * 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, outf)
+struct sc_ent scores[];
+FILE *outf;
+{
+ int i;
+ char scoreline[100];
+
+ for(i = 0; i < NUMSCORE; i++) {
+ memset(scoreline,0,100);
+ encwrite((char *) scores[i].sc_name, LINELEN, outf);
+ encwrite((char *) scores[i].sc_system, SYSLEN, outf);
+ encwrite((char *) scores[i].sc_login, LINELEN, outf);
+ sprintf(scoreline, " %lu %d %d %d %d %d \n",
+ scores[i].sc_score, scores[i].sc_flgs,
+ scores[i].sc_level, scores[i].sc_ctype,
+ scores[i].sc_monster,scores[i].sc_quest);
+ encwrite((char *) scoreline, 100, outf);
+ }
+}
+
+/*
+ * 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(stdscr,' ');
+ 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("fighters guild.\n");
+ when C_CLERIC: addstr("monastery.\n");
+ when C_THIEF: addstr("thief's guild.\n");
+ otherwise: addstr("tavern.\n");
+ }
+ mvaddstr(LINES - 1, 0, spacemsg);
+ refresh();
+ wait_for(stdscr,' ');
+ 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');
+ 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, LINELEN);
+ scp->sc_flgs = 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 0ef99244acb8 -r 0ed67132cf10 arogue5/rogue.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/rogue.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,1432 @@
+/*
+ * global variable declaration
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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"
+
+/*
+ * 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 no_move; /* Number of turns held in place */
+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 lost_dext; /* amount of lost dexterity */
+int mpos = 0;
+int no_command = 0;
+int level = 1;
+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 = HUNGERTIME;
+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 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 */
+char nfloors = -1; /* Number of floors in this dungeon */
+char curpurch[15]; /* 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 fruit[LINELEN]; /* Favorite fruit */
+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 mosnters */
+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 door_stop = FALSE;
+bool jump = FALSE;
+bool slow_invent = FALSE;
+bool firstmove = FALSE;
+bool askme = FALSE;
+bool in_shell = FALSE;
+bool daytime = TRUE;
+coord delta; /* Change indicated to get_dir() */
+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]";
+
+
+/*
+ * 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"},
+};
+
+
+/*
+ * weapons and their attributes
+ */
+struct init_weps weaps[MAXWEAPONS] = {
+ { "mace", "2d4", "1d3", NONE, ISMETAL, 100, 8 },
+ { "long sword", "1d12", "1d2", NONE, ISMETAL, 60, 18 },
+ { "short bow", "1d1", "1d1", NONE, 0, 40, 15 },
+ { "arrow", "1d1", "1d6", BOW, ISMANY|ISMISL, 5, 1 },
+ { "dagger", "1d6", "1d4", NONE, ISMETAL|ISMISL|ISMANY, 10, 2 },
+ { "rock", "1d2", "1d4", SLING, ISMANY|ISMISL, 5, 1 },
+ { "two-handed sword","3d6", "1d2", NONE, ISMETAL, 250, 40 },
+ { "sling", "0d0", "0d0", NONE, 0, 5, 1 },
+ { "dart", "1d1", "1d3", NONE, ISMANY|ISMISL, 5, 1 },
+ { "crossbow", "1d1", "1d1", NONE, 0, 100, 15 },
+ { "crossbow bolt", "1d2", "1d12", CROSSBOW, ISMANY|ISMISL, 7, 1 },
+ { "spear", "1d6", "1d8", NONE, ISMETAL|ISMISL, 50, 8 },
+ { "trident", "3d4", "1d4", NONE, ISMETAL, 50, 20 },
+ { "spetum", "2d6", "1d3", NONE, ISMETAL, 50, 20 },
+ { "bardiche", "3d4", "1d2", NONE, ISMETAL, 125, 20 },
+ { "pike", "1d12", "1d8", NONE, ISMETAL, 80, 18 },
+ { "bastard sword", "2d8", "1d2", NONE, ISMETAL, 100, 30 },
+ { "halberd", "2d6", "1d3", NONE, ISMETAL, 175, 10 },
+ { "battle axe", "1d8", "1d3", NONE, ISMETAL, 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", 60, 125, 0, 0 },
+ { "magic mapping", 50, 150, 0, 0 },
+ { "light", 80, 100, 21, 15 },
+ { "hold monster", 30, 200, 33, 20 },
+ { "sleep", 30, 150, 20, 0 },
+ { "enchantment", 180, 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, 400, 0, 0 },
+ { "protection", 30, 190, 20, 0 },
+};
+
+struct magic_item p_magic[MAXPOTIONS] = {
+ { "clear thought", 60, 180, 27, 10 },
+ { "gain ability", 160, 210, 15, 15 },
+ { "see invisible", 60, 150, 25, 15 },
+ { "healing", 170, 130, 27, 27 },
+ { "monster detection", 60, 120, 0, 0 },
+ { "magic detection", 60, 105, 0, 0 },
+ { "raise level", 20, 350, 11, 10 },
+ { "haste self", 100, 180, 30, 5 },
+ { "restore abilities", 160, 140, 0, 0 },
+ { "phasing", 50, 210, 21, 20 },
+ { "invisibility", 50, 230, 0, 15 },
+ { "flying", 50, 130, 0, 20 },
+};
+
+struct magic_item r_magic[MAXRINGS] = {
+ { "protection", 50, 200, 33, 25 },
+ { "add strength", 60, 200, 33, 25 },
+ { "sustain ability", 50, 500, 0, 0 },
+ { "searching", 60, 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", 40, 300, 0, 0 },
+ { "add intelligence", 60, 240, 33, 25 },
+ { "increase wisdom", 60, 220, 33, 25 },
+ { "sustain health", 80, 500, 0, 0 },
+ { "burden", 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},
+};
+
+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 monster", 80, 220, 25, 20 },
+ { "drain life", 90, 210, 20, 0 },
+ { "charging", 80, 400, 0, 0 },
+ { "teleport monster", 90, 140, 25, 20 },
+ { "cancellation", 40, 130, 0, 0 },
+ { "confuse monster", 35, 100, 15, 0},
+ { "disintegration", 10, 300, 33, 0},
+ { "petrification", 10, 300, 0, 0},
+ { "paralyze monster", 30, 180, 15, 0},
+ { "degenerate monster", 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},
+};
+
+/*
+ * 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 },
+ { S_MAP, 10, TYP_SCROLL, 0 },
+ { WS_MISSILE, 15, TYP_STICK, 0 },
+ { P_CLEAR, 20, TYP_POTION, 0 },
+ { S_TELEP, 20, TYP_SCROLL, 0 },
+ { S_SLEEP, 20, TYP_SCROLL, 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 },
+ { 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_IDENT, 15, TYP_SCROLL, 0 },
+ { S_LIGHT, 15, TYP_SCROLL, ISBLESSED },
+ { S_REMOVE, 20, TYP_SCROLL, 0 },
+ { P_HEALING, 25, TYP_POTION, 0 },
+ { S_CURING, 30, TYP_SCROLL, 0 },
+ { S_MAP, 30, TYP_SCROLL, 0 },
+ { P_CLEAR, 30, TYP_POTION, 0 },
+ { P_SEEINVIS, 35, TYP_POTION, 0 },
+ { P_RESTORE, 40, TYP_POTION, 0 },
+ { P_PHASE, 40, TYP_POTION, 0 },
+ { S_TELEP, 45, TYP_SCROLL, 0 },
+ { WS_CURING, 50, TYP_STICK, ISBLESSED },
+ { WS_DRAIN, 50, TYP_STICK, 0 },
+};
+
+char *cnames[4][11] = {
+{ "Veteran", "Warrior",
+ "Swordsman", "Hero",
+ "Swashbuckler", "Myrmidon",
+ "Champion", "Superhero",
+ "Lord", "Lord",
+ "Lord"
+},
+{ "Prestidigitator", "Evoker",
+ "Conjurer", "Theurgist",
+ "Thaumaturgist", "Magician",
+ "Enchanter", "Warlock",
+ "Sorcerer", "Necromancer",
+ "Wizard"
+},
+{ "Acolyte", "Adept",
+ "Priest", "Curate",
+ "Prefect", "Canon",
+ "Lama", "Patriarch",
+ "High Priest", "High Priest",
+ "High Priest"
+},
+{ "Rogue", "Footpad",
+ "Cutpurse", "Robber",
+ "Burglar", "Filcher",
+ "Sharper", "Magsman",
+ "Thief", "Master Thief",
+ "Master Thief"
+}
+} ;
+
+struct h_list helpstr[] = {
+ '?', " prints help",
+ '/', " identify object",
+ '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)",
+ 'c', " call object (generic)",
+ 'm', " mark object (specific)",
+ 'o', " examine/set options",
+ 'C', " cast a spell",
+ 'p', " pray",
+ 'a', " affect the undead",
+ '^', " set a trap",
+ 'G', " sense gold",
+ 'D', " dip something (into a pool)",
+ 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('N'), " 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 exp, level, "armor", hit_points,
+ "damage"}}, */
+{"unknown",
+ 0, FALSE, FALSE, '\0', "",
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ 0,
+ 0, 0,
+ {10, 0, 0, 0, HPT(""),
+ ""}},
+{"bat",
+ 0, TRUE, FALSE, 'b', "2-4",
+ {ISMEAN, ISHUH, CANDISEASE, ISFLY, ISHASTE},
+ 0, 0,
+ 0,
+ {10, 5, 2, 1, HPT("1d4"),
+ "1d2"}},
+{"giant rat",
+ 0, TRUE, TRUE, 'R', "2-4",
+ {ISMEAN, CANDISEASE},
+ 0, 0,
+ 1,
+ {10, 7, 1, 7, HPT("1d4"),
+ "1d3"}},
+{"kobold",
+ 10, TRUE, TRUE, 'K', "8",
+ {ISMEAN, CANSHOOT, CARRYWEAPON},
+ 0, 0,
+ 1,
+ {9, 5, 1, 7, HPT("1d4"),
+ "1d4"}},
+{"gnome",
+ 10, TRUE, TRUE, 'G', "11-12",
+ {CANSHOOT, CARRYPOTION, CARRYWEAPON},
+ 0, 0,
+ 1,
+ {10, 8, 1, 5, HPT("1d6"),
+ "1d6"}},
+{"halfling",
+ 10, TRUE, TRUE, 'H', "11-12",
+ {CANSHOOT, CARRYPOTION, CARRYWEAPON},
+ 0, 0,
+ 1,
+ {8, 9, 1, 4, HPT("1d6"),
+ "1d6"}},
+{"dwarf",
+ 15, TRUE, TRUE, 'D', "11-12",
+ {CANSHOOT, CARRYPOTION, CARRYWEAPON},
+ 0, 0,
+ 1,
+ {14, 10, 1, 4, HPT("1d8"),
+ "1d8"}},
+{"orc",
+ 15, TRUE, TRUE, 'O', "8",
+ {ISMEAN, CANSHOOT, CARRYGOLD, CARRYWEAPON},
+ 0, 0,
+ 1,
+ {12, 10, 1, 6, HPT("1d8"),
+ "1d8"}},
+{"manes",
+ 0, TRUE, TRUE, 'M', "2-4",
+ {ISMEAN, MAGICHIT, ISUNDEAD, TURNABLE},
+ 0, 0,
+ 1,
+ {10, 18, 1, 7, HPT("1d8"),
+ "1d2/1d2/1d4"}},
+{"elf",
+ 50, TRUE, TRUE, 'E', "13-20",
+ {CANSHOOT, CARRYPOTION, CARRYSCROLL, CARRYWEAPON},
+ 0, 0,
+ 2,
+ {12, 20, 1, 5, HPT("1d8+1"),
+ "1d10"}},
+{"hobgoblin",
+ 10, TRUE, TRUE, 'h', "8-10",
+ {ISMEAN, CANSHOOT, CARRYWEAPON},
+ 0, 0,
+ 2,
+ {14, 20, 1, 5, HPT("1d8+1"),
+ "1d8"}},
+{"fire beetle",
+ 0, TRUE, TRUE, 'B', "0",
+ {ISMEAN, HASFIRE},
+ 0, 0,
+ 2,
+ {10, 20, 1, 4, HPT("1d8+2"),
+ "2d4"}},
+{"giant ant",
+ 0, TRUE, TRUE, 'A', "1",
+ {ISMEAN, CANPOISON},
+ 0, 0,
+ 3,
+ {10, 40, 2, 3, HPT("2d8"),
+ "1d6/1d6"}},
+{"zombie",
+ 0, TRUE, TRUE, 'Z', "0",
+ {ISMEAN, ISUNDEAD, TURNABLE},
+ 0, 0,
+ 2,
+ {10, 20, 2, 8, HPT("2d8"),
+ "1d8"}},
+{"ear seeker",
+ 0, TRUE, TRUE, 'e', "0",
+ {ISMEAN, CANINFEST},
+ 0, 0,
+ 0,
+ {10, 0, 1, 9, HPT("1d1"),
+ "0d0"}},
+{"shrieker",
+ 0, TRUE, FALSE, 'S', "0",
+ {CANSHRIEK, NOMOVE, NOSTAB},
+ 0, 0,
+ 1,
+ {10, 5, 3, 7, HPT("3d8"),
+ "0d0"}},
+{"stirge",
+ 0, TRUE, TRUE, 's', "1",
+ {ISMEAN, CANDRAW, ISFLY},
+ 0, 0,
+ 2,
+ {10, 36, 4, 8, HPT("1d8+1"),
+ "1d3"}},
+{"gas spore",
+ 0, TRUE, FALSE, 'a', "0",
+ {ISMEAN, CANEXPLODE, CANINFEST, ISFLY},
+ 0, 0,
+ 5,
+ {10, 90, 1, 9, HPT("1d1"),
+ "1d1"}},
+{"troglodyte",
+ 5, TRUE, TRUE, 'T', "5-7",
+ {ISMEAN, CANSMELL, CANSHOOT, CARRYGOLD, CARRYWEAPON},
+ 0, 0,
+ 2,
+ {10, 36, 2, 5, HPT("2d8"),
+ "1d3/1d3/2d5"}},
+{"lemure",
+ 0, TRUE, FALSE, 'L', "2-4",
+ {ISMEAN, ISREGEN, MAGICHIT, ISUNDEAD, TURNABLE},
+ 0, 0,
+ 3,
+ {10, 65, 3, 7, HPT("3d8"),
+ "1d3"}},
+{"bugbear",
+ 5, TRUE, TRUE, 'b', "5-8",
+ {ISMEAN, CANSHOOT, CANSURPRISE, CARRYGOLD, CARRYPOTION,
+ CARRYWEAPON},
+ 0, 0,
+ 4,
+ {16, 135, 3, 5, HPT("3d8+1"),
+ "2d4"}},
+{"wererat",
+ 20, TRUE, TRUE, 'r', "11-12",
+ {ISMEAN, MAGICHIT, CARRYFOOD},
+ 0, 0,
+ 4,
+ {10, 150, 3, 6, HPT("3d8+1"),
+ "1d8"}},
+{"ghoul",
+ 0, TRUE, TRUE, 'g', "5-7",
+ {ISMEAN, CANPARALYZE, ISUNDEAD, TURNABLE},
+ 0, 0,
+ 2,
+ {10, 65, 2, 6, HPT("2d8"),
+ "1d3/1d3/1d6"}},
+{"leprechaun",
+ 100, TRUE, FALSE, 'l', "15-16",
+ {CARRYGOLD, STEALGOLD},
+ 0, 0,
+ 1,
+ {10, 80, 6, 3, HPT("1d4+1"),
+ "0d0"}},
+{"ogre",
+ 50, TRUE, TRUE, 'o', "5-7",
+ {ISMEAN, CARRYGOLD, CARRYWEAPON},
+ 0, 0,
+ 5,
+ {18, 90, 4, 5, HPT("4d8+1"),
+ "1d10"}},
+{"centaur",
+ 15, TRUE, TRUE, 'C', "5-10",
+ {CANSHOOT, CARRYPOTION, CARRYGOLD},
+ 0, 0,
+ 4,
+ {10, 85, 4, 4, HPT("4d8"),
+ "1d6/1d6"}},
+{"nymph",
+ 100, TRUE, FALSE, 'N', "15-16",
+ {STEALMAGIC, CARRYSCROLL, CARRYPOTION},
+ 0, 0,
+ 3,
+ {10, 350, 4, 9, HPT("3d8"),
+ "0d0"}},
+{"violet fungi",
+ 0, TRUE, FALSE, 'F', "0",
+ {ISMEAN, CANHOLD, NOMOVE, CANROT, NOSTAB},
+ 0, 0,
+ 4,
+ {10, 135, 3, 7, HPT("3d8"),
+ "5d1"}},
+{"giant tick",
+ 0, TRUE, TRUE, 't', "0",
+ {ISMEAN, CANDRAW, CANDISEASE},
+ 0, 0,
+ 2,
+ {10, 105, 3, 3, HPT("3d8"),
+ "1d4"}},
+{"gelatinous cube",
+ 90, TRUE, TRUE, 'c', "0",
+ {ISMEAN, ISSCAVENGE, CANPARALYZE, NOSTAB, CARRYFOOD},
+ 0, 0,
+ 4,
+ {10, 150, 4, 8, HPT("4d8"),
+ "2d4"}},
+{"blink dog",
+ 0, TRUE, TRUE, 'B', "8-10",
+ {ISMEAN, CANBLINK},
+ 0, 0,
+ 5,
+ {10, 170, 4, 5, HPT("4d8"),
+ "1d6"}},
+{"very young dragon",
+ 10, TRUE, FALSE, 'd', "15-16",
+ {ISMEAN, CANBRANDOM, ISGREED, CARRYGOLD, CARRYSTICK},
+ 0, 0,
+ 9,
+ {10, 100, 9, -1, HPT("9d1"),
+ "1d4/1d4/2d4"}},
+{"rust monster",
+ 0, TRUE, TRUE, 'R', "1",
+ {ISMEAN, CANRUST},
+ 0, 0,
+ 4,
+ {10, 185, 5, 2, HPT("3d8"),
+ "0d0/0d0"}},
+{"ghast",
+ 0, TRUE, TRUE, 'G', "11-12",
+ {CANPARALYZE, CANSTINK, ISMEAN, ISUNDEAD, TURNABLE},
+ 0, 0,
+ 4,
+ {10, 190, 4, 4, HPT("4d8"),
+ "1d4/1d4/1d8"}},
+{"blindheim",
+ 0, TRUE, FALSE, 'b', "1",
+ {CANBLIND, ISMEAN},
+ 0, 0,
+ 4,
+ {8, 200, 2, 1, HPT("4d8+2"),
+ "1d8"}},
+{"shadow",
+ 0, TRUE, TRUE, 'S', "5-7",
+ {ISSHADOW, ISMEAN, CANCHILL, ISUNDEAD, TURNABLE},
+ 0, 0,
+ 4,
+ {10, 255, 3, 7, HPT("3d8+3"),
+ "1d4+1"}},
+{"gargoyle",
+ 5, TRUE, TRUE, 'g', "5-7",
+ {ISMEAN, MAGICHIT, CARRYSTICK},
+ 0, 0,
+ 5,
+ {10, 165, 4, 5, HPT("4d8+4"),
+ "1d3/1d3/1d6/1d4"}},
+{"su-monster", 10, TRUE, TRUE, 's', "8-10",
+ {ISMEAN, CARRYSCROLL, CARRYGOLD, CARRYFOOD},
+ 0, 0,
+ 6,
+ {10, 225, 5, 6, HPT("5d8+5"),
+ "4d4/2d4"}},
+{"gray ooze",
+ 50, TRUE, FALSE, 'o', "1",
+ {ISMEAN, NOMOVE, CANRUST, ISSCAVENGE, NOCOLD, NOFIRE, NOSTAB,
+ CARRYSTICK, CARRYFOOD},
+ 0, 0,
+ 5,
+ {10, 200, 3, 8, HPT("3d8+3"),
+ "2d8"}},
+{"owlbear",
+ 5, TRUE, TRUE, 'O', "5-7",
+ {ISMEAN, CANHUG, CARRYRING, CARRYFOOD},
+ 0, 0,
+ 8,
+ {10, 225, 5, 5, HPT("5d8+2"),
+ "1d6/1d6/2d6"}},
+{"quasit",
+ 30, TRUE, TRUE, 'Q', "5-7",
+ {ISMEAN, ISREGEN, MAGICHIT, CANSURPRISE, CANITCH,
+ CARRYSCROLL, CARRYGOLD, CARRYPOTION, NOCOLD, NOFIRE, NOBOLT},
+ 0, 0,
+ 3,
+ {10, 325, 7, 2, HPT("3d8"),
+ "1d2/1d2/1d4"}},
+{"doppleganger",
+ 0, TRUE, TRUE, 'D', "11-12",
+ {ISMEAN, CANSURPRISE},
+ 0, 0,
+ 4,
+ {10, 330, 10, 5, HPT("4d8"),
+ "1d12"}},
+{"yeti",
+ 30, TRUE, TRUE, 'Y', "8-10",
+ {ISMEAN, CANPARALYZE, CANHUG, NOCOLD, CANSURPRISE,
+ CARRYGOLD, CARRYPOTION},
+ 0, 0,
+ 8,
+ {13, 500, 6, 6, HPT("4d8+4"),
+ "1d6/1d6"}},
+{"leucrotta",
+ 0, TRUE, FALSE, 'L', "8-10",
+ {ISMEAN},
+ 0, 0,
+ 8,
+ {10, 475, 6, 4, HPT("6d8+1"),
+ "3d6/1d6/1d6"}},
+{"imp",
+ 25, TRUE, TRUE, 'I', "8-10",
+ {ISMEAN, ISREGEN, MAGICHIT, CANPOISON, CANSURPRISE,
+ CANTELEPORT, CARRYRING, CARRYSTICK, NOCOLD, NOBOLT, NOFIRE},
+ 0, 0,
+ 3,
+ {10, 275, 2, 2, HPT("2d8+2"),
+ "1d4"}},
+{"cockatrice",
+ 0, TRUE, TRUE, 'C', "1",
+ {ISMEAN, TOUCHSTONE},
+ 0, 0,
+ 5,
+ {10, 315, 5, 6, HPT("5d8"),
+ "1d3"}},
+{"wight",
+ 0, TRUE, TRUE, 'W', "8-10",
+ {ISMEAN, CANDRAIN, MAGICHIT, ISUNDEAD, TURNABLE},
+ 0, 0,
+ 5,
+ {10, 540, 4, 5, HPT("4d8+3"),
+ "1d4"}},
+{"troll",
+ 50, TRUE, FALSE, 'T', "5-7",
+ {ISMEAN, ISREGEN, CARRYFOOD, CARRYGOLD, CARRYSTICK},
+ 0, 0,
+ 8,
+ {18, 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, 800, 4, 4, HPT("4d8"),
+ "2d4"}},
+{"wraith",
+ 0, TRUE, TRUE, 'w', "11-12",
+ {ISMEAN, CANDRAIN, MAGICHIT, ISUNDEAD, TURNABLE},
+ 0, 0,
+ 6,
+ {10, 575, 5, 4, HPT("5d8+3"),
+ "1d6"}},
+{"erinyes",
+ 25, TRUE, TRUE, 'E', "8-10",
+ {ISMEAN, CANFRIGHTEN, CANSUMMON, TURNABLE, CANPAIN, CANSEE,
+ NOFIRE, CANTELEPORT, CARRYRING, CARRYSTICK},
+ "ghoul", 3,
+ 8,
+ {10, 875, 7, 2, HPT("6d8+6"),
+ "2d4"}},
+{"lava child",
+ 0, TRUE, TRUE, 'l', "8-10",
+ {ISMEAN, NOMETAL},
+ 0, 0,
+ 8,
+ {10, 950, 5, 4, HPT("5d8+1"),
+ "1d6/1d6/2d12"}},
+{"basilisk",
+ 0, TRUE, FALSE, 'B', "1",
+ {ISMEAN, LOOKSTONE},
+ 0, 0,
+ 8,
+ {10, 1000, 6, 4, HPT("6d8+1"),
+ "1d10"}},
+{"mummy",
+ 20, TRUE, FALSE, 'm', "5-7",
+ {ISMEAN,CANINFEST, MAGICHIT, CANFRIGHTEN, HALFDAMAGE, ISUNDEAD,
+ TURNABLE, CARRYRING, CARRYSTICK},
+ 0, 0,
+ 8,
+ {10, 1150, 6, 3, HPT("6d8+3"),
+ "1d12"}},
+{"otyugh",
+ 0, TRUE, TRUE, 'o', "5-10",
+ {ISMEAN, CANDISEASE},
+ 0, 0,
+ 8,
+ {10, 700, 7, 3, HPT("7d8"),
+ "1d8/1d8/1d4+1"}},
+{"adult dragon",
+ 30, TRUE, FALSE, 'd', "15-16",
+ {ISMEAN, CANBRANDOM, ISGREED, CANFRIGHTEN, CARRYGOLD,
+ CARRYPOTION, CARRYSTICK},
+ 0, 0,
+ 9,
+ {10, 1000, 9, -1, HPT("45d1"),
+ "1d6/1d6/2d6"}},
+{"invisible stalker",
+ 0, TRUE, TRUE, 'i', "13-14",
+ {ISMEAN, ISINVIS},
+ 0, 0,
+ 10,
+ {10, 1090, 8, 3, HPT("8d8"),
+ "4d4"}},
+{"xorn",
+ 0, TRUE, TRUE, 'X', "8-10",
+ {ISMEAN, CANINWALL, NOCOLD, NOFIRE, CANSURPRISE, NOBOLT},
+ 0, 0,
+ 10,
+ {10, 1275, 7, -2, HPT("7d8+7"),
+ "1d3/1d3/1d3/4d6"}},
+{"will-o-wisp", 100, TRUE, FALSE, 'W', "15-16",
+ {ISMEAN, CANSURPRISE, ISFLY, CARRYGOLD, CARRYMISC, NOBOLT},
+ 0, 0,
+ 12,
+ {10, 2000, 9, -8, HPT("9d8"),
+ "2d8"}},
+{"chimera",
+ 0, TRUE, FALSE, 'c', "2-4",
+ {ISMEAN, CANBFIRE, NOFIRE},
+ 0, 0,
+ 12,
+ {10, 1000, 9, 6, HPT("9d8"),
+ "1d3/1d3/1d4/1d4/2d4/3d4"}},
+{"mimic",
+ 20, TRUE, FALSE, 'M', "2-10",
+ {ISDISGUISE, CANHOLD, CARRYFOOD, CARRYRING, CARRYGOLD},
+ 0, 0,
+ 12,
+ {10, 1300, 9, 7, HPT("9d8"),
+ "3d4"}},
+{"horned devil",
+ 5, TRUE, TRUE, 'H', "13-14",
+ {ISMEAN, CANFRIGHTEN, CANINFEST, CANPOISON, MAGICHIT, CANSUMMON,
+ NOFIRE, CANTELEPORT, CARRYGOLD, CARRYRING, CARRYSTICK},
+ "wight", 2,
+ 6,
+ {10, 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, 1650, 7, 2, HPT("7d8+3"),
+ "1d8"}},
+{"lamia",
+ 0, TRUE, TRUE, 'L', "13-14",
+ {ISMEAN, TAKEWISDOM},
+ 0, 0,
+ 9,
+ {10, 1500, 9, 3, HPT("9d8"),
+ "1d4/1d4"}},
+{"neo-otyugh",
+ 0, TRUE, TRUE, 'N', "10-12",
+ {ISMEAN, CANDISEASE},
+ 0, 0,
+ 10,
+ {12, 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, 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, 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, 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, 1700, 8, 2, HPT("8d8+8"),
+ "3d4/3d4/2d5"}},
+{"ettin",
+ 0, TRUE, TRUE, 'e', "0",
+ {ISMEAN, CANSHOOT},
+ 0, 0,
+ 14,
+ {10, 1950, 10, 3, HPT("10d8"),
+ "2d8/3d6"}},
+{"black pudding",
+ 30, TRUE, FALSE, 'P', "0",
+ {ISMEAN, CANRUST, NOCOLD, BOLTDIVIDE, BLOWDIVIDE, ISSCAVENGE,
+ NOSTAB, CARRYSCROLL, CARRYSTICK, CARRYPOTION, CARRYRING},
+ 0, 0,
+ 14,
+ {10, 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, 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, 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, 2800, 9, -1, HPT("9d8"),
+ "2d4"}},
+{"white pudding",
+ 30, TRUE, FALSE, 'w', "0",
+ {ISMEAN, CANDISSOLVE, NOCOLD, BOLTDIVIDE, BLOWDIVIDE,
+ ISSCAVENGE, NOSTAB, CARRYRING, CARRYSTICK, CARRYSCROLL,
+ CARRYPOTION},
+ 0, 0,
+ 14,
+ {10, 2200, 9, 8, HPT("10d8"),
+ "7d4"}},
+{"vampire",
+ 20, TRUE, TRUE, 'v', "15-16",
+ {ISMEAN, ISREGEN, CANSUCK, ISUNDEAD, TURNABLE, CARRYMISC},
+ 0, 0,
+ 12,
+ {20, 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, 5000, 12, 0, HPT("10d8"),
+ "1d12"}},
+{"intellect devourer",
+ 0, TRUE, FALSE, 'D', HPT("11-12"),
+ {ISMEAN, TAKEINTEL, CMAGICHIT, HALFDAMAGE, CANSURPRISE, NOFIRE,
+ NOCOLD},
+ 0, 0,
+ 9,
+ {10, 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, CANSLOW, CANTELEPORT, CARRYSCROLL, CARRYRING,
+ CARRYSTICK},
+ "bone devil", 2,
+ 16,
+ {20, 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, 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, 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},
+ "barbed devil", 3,
+ 18,
+ {22, 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, 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, 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},
+ "specter", 2,
+ 16,
+ {10, 20000, 17, 0, HPT("11d8"),
+ "1d10"}},
+{"titan",
+ 80, TRUE, FALSE, 't', "17-20",
+ {ISSHADOW, CANSEE, CANMISSILE, CARRYRING, CARRYSTICK,
+ CANTELEPORT},
+ 0, 0,
+ 30,
+ {13, 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, 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, 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, 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, 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, 20000, 11, -1, HPT("0d8+88"),
+ "1d6/1d6/5d6"}},
+{"frost giant",
+ 50, TRUE, TRUE, 'F', "5-10",
+ {ISMEAN, NOCOLD, CARRYGOLD, CARRYSTICK},
+ 0, 0,
+ 40,
+ {25, 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, 20000, 11, -1, HPT("0d8+88"),
+ "1d8/1d8/3d10"}},
+{"ancient gold dragon",
+ 50, TRUE, TRUE, 'G', "17-18",
+ {CANBFIRE, CANBGAS, ISGREED, CANSEE, CANMISSILE, NOFIRE, NOGAS,
+ CARRYGOLD, CARRYPOTION, CARRYRING, CARRYSTICK, CANTELEPORT},
+ 0, 0,
+ 50,
+ {10, 20000, 12, -2, HPT("0d8+96"),
+ "1d8/1d8/6d6"}},
+{"fire giant",
+ 30, TRUE, TRUE, 'f', "6-10",
+ {ISMEAN, CARRYGOLD, NOFIRE, CARRYSTICK},
+ 0, 0,
+ 45,
+ {27, 26000, 15, 4, HPT("11d8+5"),
+ "5d6"}},
+{"storm giant",
+ 30, TRUE, TRUE, 's', "8-10",
+ {ISMEAN, NOBOLT, CANBBOLT, CARRYRING},
+ 0, 0,
+ 50,
+ {30, 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,
+ CARRYDAGGER, CARRYMISC, CARRYPOTION, CANBSTAB, ISSCAVENGE},
+ 0, 0,
+ 0,
+ {11, 300000, 20, -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},
+ "black pudding", 4,
+ 0,
+ {10, 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,
+ CARRYMISC, CARRYHORN},
+ "ice devil", 5,
+ 0,
+ {13, 110000, 30, -3, HPT("0d8+133"),
+ "3d6/3d6/2d4"}},
+{"arch devil (Dispater)",
+ 100, TRUE, FALSE, 'd', "18",
+ {ISMEAN, ISUNIQUE, CANSEE, CANFRIGHTEN, CANHUH, BMAGICHIT,
+ CANSUMMON, NOFIRE, CANTELEPORT, CARRYMISC},
+ "ghost", 9,
+ 0,
+ {10, 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},
+ "lich", 5,
+ 0,
+ {10, 130000, 23, -5, HPT("0d8+100"),
+ "3d6/3d6"}},
+{"witch (Emori)",
+ 50, TRUE, FALSE, 'w', "18",
+ {ISMEAN, CANMISSILE, ISINVIS, CANBBOLT, CANBFIRE, CANBICE,
+ CANSEE, CANSUMMON, ISUNIQUE, CANSNORE, ISFLY, TAKEINTEL,
+ CANDANCE, CANDISEASE, NOBOLT, NOCOLD, NOFIRE, CARRYCLOAK,
+ ISCLEAR, CARRYSCROLL, CARRYSTICK, CANTELEPORT},
+ "shambling mound", 5,
+ 0,
+ {11, 240000, 25, 6, HPT("0d8+102"),
+ "1d4/1d4"}},
+{"cleric of Thoth (Heil)",
+ 100, TRUE, FALSE, 'h', "16",
+ {ISMEAN, CANSEE, NOFEAR, ISREGEN, CANHOLD, CANBFIRE, ISUNIQUE,
+ DOUBLEDRAIN, CANSUMMON, NOFIRE, TOUCHFEAR, CANDISEASE,
+ CANSEE, TAKEWISDOM, CARRYANKH, CARRYRING, ISINVIS, ISFLY},
+ "mummy", 9,
+ 0,
+ {15, 295000, 20, -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, CANBLINK, CANTELEPORT,
+ CARRYSTAFF, CARRYSTICK, NOSLOW, NOBOLT, NOCOLD},
+ "blink dog", 5,
+ 0,
+ {16, 310000, 21, 0, 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, 320000, 20, -2, HPT("0d8+153"),
+ "8d8+48/4d4+36"}},
+{"lesser god (Hruggek)",
+ 100, TRUE, FALSE, 'H', "17",
+ {ISMEAN, CANSEE, ISUNIQUE, CANSUMMON, ISREGEN,
+ CANTELEPORT, CARRYMISC, CARRYMSTAR},
+ "purple worm", 6,
+ 0,
+ {19, 140000, 25, 0, HPT("0d8+221"),
+ "2d8/2d8"}},
+{"lesser god (Kurtulmak)",
+ 100, TRUE, TRUE, 'K', "19",
+ {ISMEAN, CANFRIGHTEN, CANPOISON, CANSEE, ISUNIQUE, CANSUMMON,
+ CANTELEPORT, CARRYMISC},
+ "lich", 3,
+ 0,
+ {19, 150000, 27, 0, HPT("0d8+219"),
+ "2d12/1d6"}},
+{"demigod (Vaprak \"The Destroyer\")",
+ 100, TRUE, TRUE, 'v', "18",
+ {ISMEAN, ISUNIQUE, ISREGEN, MAGICHIT, CANSEE, CANSUMMON,
+ CANTELEPORT, CARRYMISC},
+ "troll", 9,
+ 0,
+ {16, 160000, 26, 0, HPT("0d8+198"),
+ "2d10/2d10/1d12"}},
+{"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,
+ CARRYSTICK, CARRYMISC, CANTELEPORT},
+ "ancient gold dragon", 4,
+ 0,
+ {10, 170000, 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},
+ "horned devil", 9,
+ 0,
+ {10, 180000, 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},
+ "ancient red dragon", 6,
+ 0,
+ {10, 190000, 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,
+ CARRYMISC, CANTELEPORT},
+ "vampire", 9,
+ 0,
+ {13, 200000, 27, -6, HPT("0d8+120"),
+ "1d10+3/2d4"}},
+{"arch devil (Asmodeus)",
+ 100, TRUE, FALSE, 'A', "20",
+ {ISMEAN, ISUNIQUE, CANSEE, ISSHADOW, CANHOLD, BMAGICHIT,
+ CANFRIGHTEN, CANHUH, CANSLOW, CANSUMMON, NOFIRE,
+ CANTELEPORT, CARRYROD, CARRYMISC},
+ "pit fiend", 5,
+ 0,
+ {10, 210000, 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,
+ CANDISEASE, CARRYMISC},
+ "glabrezu", 9,
+ 0,
+ {10, 220000, 45, -8, HPT("0d8+200"),
+ "1d6/1d6"}},
+{"greater god (Maglubiyet)",
+ 100, TRUE, FALSE, 'M', "19",
+ {ISMEAN, ISUNIQUE, CMAGICHIT, CANSEE, ISREGEN, CANSUMMON,
+ CANTELEPORT, CARRYMISC},
+ "lich", 6,
+ 0,
+ {10, 230000, 45, -1, HPT("0d8+350"),
+ "4d10"}},
+{"greater god (Gruumsh)",
+ 100, TRUE, FALSE, 'G', "19",
+ {ISMEAN, ISUNIQUE, CMAGICHIT, CANSEE, ISREGEN, CANSUMMON,
+ CANTELEPORT, CARRYMISC},
+ "lich", 9,
+ 0,
+ {10, 240000, 45, -1, HPT("0d8+350"),
+ "4d10"}},
+{"lesser god (Thrym)",
+ 100, TRUE, FALSE, 'T', "16",
+ {ISMEAN, NOCOLD, ISUNIQUE, ISREGEN, CMAGICHIT, CANSEE,
+ CANSUMMON, CARRYMISC, CANTELEPORT},
+ "frost giant", 9,
+ 0,
+ {25, 250000, 45, -2, HPT("0d8+300"),
+ "4d10/4d10"}},
+{"lesser god (Surtur)",
+ 100, TRUE, FALSE, 't', "19",
+ {ISMEAN, NOFIRE, ISUNIQUE, ISREGEN, CMAGICHIT, CANSEE,
+ CANSUMMON, CANMISSILE, CANTELEPORT, CARRYMISC},
+ "fire giant", 9,
+ 0,
+ {25, 260000, 45, -2, HPT("0d8+380"),
+ "5d10/5d10"}},
+{"lesser god (Skoraeus Stonebones)",
+ 100, TRUE, FALSE, 'b', "19",
+ {ISMEAN, ISUNIQUE, ISREGEN, CMAGICHIT, CANSEE, CANSUMMON,
+ CANMISSILE, CANINWALL, CANTELEPORT, CARRYMISC, CARRYSTICK},
+ "storm giant", 9,
+ 0,
+ {25, 270000, 45, -1, HPT("0d8+380"),
+ "6d10/6d10"}},
+{"ruler of greater titans (Yendor)",
+ 100, TRUE, TRUE, 'y', "25",
+ {ISMEAN, CANINWALL, ISUNIQUE, ISREGEN, CMAGICHIT,
+ CANSUMMON, CANMISSILE, CANFRIGHTEN, CANBFIRE, NOFIRE,
+ CANHOLD, CARRYAMULET, CANSEE, CANDANCE, ISSHADOW,
+ CANTELEPORT, CARRYMISC, CARRYRING, CARRYSTICK},
+ "titan", 15,
+ 0,
+ {25, 300000, 45, -3, HPT("0d8+400"),
+ "7d10/7d10"}},
+{"quartermaster",
+ 50, FALSE, TRUE, 'q', "18",
+ {CANSELL, CARRYPOTION, CARRYSCROLL, CARRYMISC, CARRYRING,
+ CARRYSTICK, CANTELEPORT},
+ 0, 0,
+ 2,
+ {12, 20, 1, -4, HPT("1d8+1"),
+ "1d10"}},
+};
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/rogue.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/rogue.h Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,1117 @@
+/*
+ * Rogue definitions and variable declarations
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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 reg register /* register abbr. */
+#define NOOP(x) (x += 0)
+#define CCHAR(x) ( (char) (x & A_CHARTEXT) )
+
+/*
+ * Maximum number of different things
+ */
+
+#define MAXDAEMONS 10
+#define MAXFUSES 20
+
+#define NCOLORS 32
+#define NSTONES 47
+#define NWOOD 24
+#define NMETAL 16
+#define NSYLLS 159
+
+#define MAXROOMS 9
+#define MAXTHINGS 9
+#define MAXOBJ 9
+#define MAXSTATS 62 /* max total of all stats at startup */
+#define MAXPACK 23
+#define MAXCONTENTS 10
+#define MAXENCHANT 10 /* max number of enchantments on an item */
+#define MAXTREAS 15 /* number monsters/treasure in treasure room */
+#define MAXTRAPS 20
+#define MAXTRPTRY 8 /* attempts/level allowed for setting traps */
+#define MAXDOORS 4 /* Maximum doors to a room */
+#define MAXPRAYERS 15 /* Maximum number of prayers for cleric */
+#define MAXSPELLS 20 /* Maximum number of spells (for magician) */
+#define NUMMONST 120 /* Current number of monsters */
+#define NUMUNIQUE 24 /* number of UNIQUE creatures */
+#define NLEVMONS 3 /* Number of new monsters per level */
+#define MAXFOODS 1
+#define NUMSCORE 20 /* number of entries in score file */
+#define HARDER 35 /* at this level start making things harder */
+#define MAXPURCH 4 /* max purchases per trading post visit */
+#define LINELEN 80 /* characters in a buffer */
+#define JUG_EMPTY -1 /* signifys that the alchemy jug is empty */
+
+/* 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
+
+/*
+ * stuff to do with encumberance
+ */
+#define NORMENCB 1500 /* normal encumberance */
+#define F_OKAY 0 /* have plenty of food in stomach */
+#define F_HUNGRY 1 /* player is hungry */
+#define F_WEAK 2 /* weak from lack of food */
+#define F_FAINT 3 /* fainting from lack of food */
+
+/*
+ * 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_MAGICIAN 1
+#define C_CLERIC 2
+#define C_THIEF 3
+#define C_MONSTER 4
+
+/*
+ * Number of hit points for going up a level
+ */
+#define HIT_FIGHTER 10
+#define HIT_MAGICIAN 8
+#define HIT_CLERIC 8
+#define HIT_THIEF 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
+ */
+#define MONSTOK 1
+#define NOMONST 2
+
+/*
+ * 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 t_free_list(a) _t_free_list(&a)
+#undef max
+#undef min
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#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 ISMULT(type) (type == FOOD)
+#define isrock(ch) ((ch == WALL) || (ch == '-') || (ch == '|'))
+#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
+
+/*
+ * 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 DEATHNUM 17 /* 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 "SihQX7.LYSmbo"
+#define BEARTIME 3
+#define SLEEPTIME 4
+#define FREEZETIME 6
+#define PAINTIME (roll(1, 6))
+#define HEALTIME 30
+#define CHILLTIME (roll(20, 4))
+#define SMELLTIME 20
+#define STONETIME 8
+#define HASTETIME 6
+#define SICKTIME 10
+#define STPOS 0
+#define WANDERTIME (max(5, HARDER-rnd(vlevel)))
+#define BEFORE 1
+#define AFTER 2
+#define HUHDURATION 20
+#define SEEDURATION 850
+#define CLRDURATION 15
+#define GONETIME 200
+#define FLYTIME 300
+#define DUSTTIME (20+roll(1,10))
+#define PHASEDURATION 300
+#define HUNGERTIME 1300
+#define MORETIME 150
+#define STINKTIME 6
+#define STOMACHSIZE 2000
+#define ESCAPE 27
+#define BOLT_LENGTH 10
+#define MARKLEN 20
+#define DAYLENGTH 400
+#define ALCHEMYTIME (400+rnd(100))
+
+/*
+ * 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 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 CARRYDAGGER 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 CARRYAMULET 0x40800000 /* Amulet of Yendor */
+#define CARRYMANDOLIN 0x41000000 /* Mandolin of Brian */
+#define MISSEDDISP 0x42000000 /* Missed Cloak of Displacement */
+#define CANBSTAB 0x44000000 /* Can backstab */
+
+
+#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 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 | \
+ CARRYDAGGER | CARRYCLOAK | CARRYANKH | \
+ CARRYSTAFF | CARRYWAND | CARRYROD | \
+ CARRYAMULET | CARRYMANDOLIN )
+#define CANC5MASK ( CARRYHORN | CARRYMSTAR | CARRYFLAIL )
+
+/* 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
+/*
+ * 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 MAXPOTIONS 12
+/*
+ * 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 MAXSCROLLS 17
+
+/*
+ * 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_HEAVY 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 MAXRINGS 24
+
+/*
+ * 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 MAXRELIC 11
+
+
+#define LEVEL 600
+#define vlevel max(level, turns/LEVEL + 1)
+/*
+ * Now we define the structures and types
+ */
+
+struct delayed_action {
+ int d_type;
+ int (*d_func)();
+ int d_arg;
+ int d_time;
+};
+
+/*
+ * level types
+ */
+typedef enum {
+ NORMLEV, /* normal level */
+ POSTLEV, /* trading post level */
+ MAZELEV, /* maze level */
+ OUTSIDE /* outside level */
+} 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_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 */
+ unsigned long s_exp; /* Experience */
+ int s_lvl; /* Level of mastery */
+ int 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_turn; /* If slowed, is it a turn to move */
+ 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 */
+ coord *t_doorgoal; /* What door are we heading to? */
+ coord t_pos; /* Position */
+ coord t_oldpos; /* Last position */
+ coord *t_dest; /* Where it is running to */
+ unsigned long t_flags[16]; /* State word */
+ struct linked_list *t_pack; /* What the thing is carrying */
+ struct stats t_stats; /* Physical description */
+ struct stats maxstats; /* maximum(or initial) stats */
+ int t_reserved;
+ int t_reserved2;
+ int t_reserved3;
+};
+
+/*
+ * Array containing information on all the various types of monsters
+ */
+struct monster {
+ const char *m_name; /* What to call the monster */
+ const short m_carry; /* Probability of carrying something */
+ bool m_normal; /* Does monster exist? */
+ bool m_wander; /* Does monster wander? */
+ const char m_appear; /* What does monster look like? */
+ const char *m_intel; /* Intelligence range */
+ const long m_flags[MAXFLAGS]; /* Things about the monster */
+ const char *m_typesum; /* type of creature can he summon */
+ short m_numsum; /* how many creatures can he summon */
+ const short m_add_exp; /* Added experience per hit point */
+ const 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_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 matrix {
+ 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 */
+};
+
+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 linked_list *find_mons(), *find_obj(), *get_item(), *new_item(),
+ *new_thing(), *wake_monster(), *get_hurl(),
+ *spec_item(), *creat_item();
+struct object *wield_weap();
+struct room *roomin();
+struct trap *trap_at();
+
+char *getenv(), *tr_name(), *new(),
+ *vowelstr(), *inv_name(),
+ *ctime(), *num(), *ring_num(), *misc_num(), *blesscurse(), *typ_name(),
+ *weap_name(), *misc_name();
+coord *rndmove(), *can_shoot(), *fallpos();
+short randmonster(), id_monst();
+void quit(int sig), tstp(int sig), auto_save(int sig), bugkill(int sig), endit(int sig);
+int rnd(), wghtchk(), nohaste(), res_strength(),
+ doctor(), runners(), swander(), unconfuse(), unsee(), fumble(),
+ unclrhead(), unphase(), noslow(), rollwand(), stomach(), sight(),
+ unstink(), suffocate(), cure_disease(), un_itch(), shoot_bolt(),
+ appear(), dust_appear(), unchoke(), alchemy(), trap_look(), strangle(),
+ ring_teleport(), ring_search(), grab();
+bool blue_light(), can_blink(), creat_mons(), add_pack(),
+ straight_shot(), maze_view(), lit_room(), getdelta(), save_file(),
+ save_game();
+long check_level();
+void byebye(int sig), genmonsters();
+int land(), undance();
+#ifdef CHECKTIME
+int checkout();
+#endif
+extern char *md_getusername();
+extern char *md_gethomedir();
+extern void md_flushinp();
+extern char *md_getshell();
+extern char *md_gethostname();
+extern void md_dobinaryio();
+extern char *md_getpass();
+extern char *md_crypt();
+extern char *md_getroguedir();
+extern void md_init();
+
+/*
+ * Now all the global variables
+ */
+
+extern char outstring[]; /* string for use with msg */
+extern struct trap traps[];
+extern struct h_list helpstr[];
+extern struct h_list wiz_help[];
+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[]; /* 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 spells magic_spells[]; /* spells for magic users */
+extern struct spells cleric_spells[]; /* spells for magic users */
+extern char *cnames[][11]; /* Character level names */
+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 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 no_move; /* Number of turns held in place */
+extern int no_command; /* Number of turns asleep */
+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 lost_dext; /* amount of dexterity lost */
+extern int hold_count; /* Number of monsters holding player */
+extern int trap_tries; /* Number of attempts to set traps */
+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[LINELEN]; /* 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; /* Used to display messages */
+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 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 delta; /* Change indicated to get_dir() */
+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 int demoncnt;
+extern int fusecnt;
+extern int between;
+extern struct delayed_action d_list[MAXDAEMONS];
+extern struct delayed_action f_list[MAXFUSES];
+extern char *rainbow[NCOLORS];
+extern char *sylls[NSYLLS];
+extern char *stones[NSTONES];
+extern char *metal[NMETAL];
+extern char *wood[NWOOD];
+extern coord ch_ret;
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/rooms.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/rooms.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,239 @@
+/*
+ * Draw the nine rooms on the screen
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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"
+
+do_rooms()
+{
+ register int i;
+ register struct room *rp;
+ register struct linked_list *item;
+ register struct thing *tp;
+ register int left_out;
+ coord top;
+ coord bsze;
+ coord mp;
+
+ /*
+ * bsze is the maximum room size
+ */
+ bsze.x = COLS/3;
+ bsze.y = (LINES-2)/3;
+ /*
+ * Clear things for a new level
+ */
+ for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) {
+ rp->r_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();
+ printf("\n");
+ abort();
+ }
+ }
+
+ /*
+ * Put the monster in
+ */
+ if (rnd(100) < (has_gold ? 80 : 25) + vlevel/2)
+ {
+ item = new_item(sizeof *tp);
+ tp = THINGPTR(item);
+ do
+ {
+ rnd_pos(rp, &mp);
+ } until(mvwinch(stdscr, mp.y, mp.x) == FLOOR);
+ new_monster(item, randmonster(FALSE, FALSE), &mp, FALSE);
+ /*
+ * See if we want to give it a treasure to carry around.
+ */
+ carry_obj(tp, monsters[tp->t_index].m_carry);
+
+ /*
+ * 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;
+ }
+ }
+ }
+}
+
+
+/*
+ * 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 0ef99244acb8 -r 0ed67132cf10 arogue5/save.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/save.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,289 @@
+/*
+ * save and restore routines
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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
+#include
+#include
+#include
+#include
+#include "rogue.h"
+
+typedef struct stat STAT;
+
+extern char version[], encstr[];
+/* extern bool _endwin; */
+
+STAT sbuf;
+
+bool
+save_game()
+{
+ register FILE *savef;
+ 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, cw) == QUIT)
+ {
+ msg("");
+ return FALSE;
+ }
+ msg("");
+ strcpy(file_name, buf);
+gotfile:
+ if ((savef = fopen(file_name, "w")) == NULL)
+ msg(strerror(errno)); /* fake perror() */
+ } while (savef == NULL);
+
+ /*
+ * write out encrpyted file (after a stat)
+ * The fwrite is to force allocation of the buffer before the write
+ */
+ if (save_file(savef) != 0) {
+ 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(int sig)
+{
+ register FILE *savef;
+ register int i;
+
+ NOOP(sig);
+
+ for (i = 0; i < NSIG; i++)
+ signal(i, SIG_IGN);
+ if (file_name[0] != '\0' &&
+ pstats.s_hpt > 0 &&
+ (savef = fopen(file_name, "w")) != NULL)
+ save_file(savef);
+ exit(1);
+}
+
+/*
+ * write the saved game on the file
+ */
+bool
+save_file(savef)
+register FILE *savef;
+{
+ int ret;
+ int slines = LINES;
+ int scols = COLS;
+
+ wmove(cw, LINES-1, 0);
+ draw(cw);
+ fwrite("junk", 1, 5, savef);
+ fseek(savef, 0L, 0);
+ /* _endwin = TRUE; */
+ fstat(fileno(savef), &sbuf);
+
+ encwrite(version,strlen(version)+1,savef);
+ sprintf(prbuf,"%d x %d\n", LINES, COLS);
+ encwrite(prbuf,80,savef);
+
+ msg("");
+ ret = rs_save_file(savef);
+
+ fclose(savef);
+
+ return(ret);
+}
+
+restore(file, envp)
+register char *file;
+char **envp;
+{
+ register int inf;
+#ifndef _AIX
+ extern char **environ;
+#endif
+ 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, O_RDONLY)) < 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);
+
+ /*
+ * Set the new terminal and make sure we aren't going to a smaller screen.
+ */
+
+ initscr();
+
+ if (COLS < oldcol || LINES < oldline) {
+ endwin();
+ printf("\nCannot restart the game on a smaller screen.\n");
+ return FALSE;
+ }
+
+ 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);
+
+ mpos = 0;
+ mvwprintw(cw, 0, 0, "%s: %s", file, ctime(&sbuf2.st_mtime));
+
+ /*
+ * defeat multiple restarting from the same place
+ */
+ if (!wizard) {
+ if (sbuf2.st_nlink != 1) {
+ endwin();
+ printf("\nCannot restore from a linked file\n");
+ return FALSE;
+ }
+ }
+
+ if (rs_restore_file(inf) != 0)
+ {
+ endwin();
+ printf("\nCannot restore file\n");
+ return(FALSE);
+ }
+
+ if (!wizard)
+ {
+ if (unlink(file) < 0) {
+ close(inf); /* only close if system insists */
+ if (unlink(file) < 0) {
+ endwin();
+ printf("\nCannot unlink file\n");
+ return FALSE;
+ }
+ }
+ }
+
+ environ = envp;
+ strcpy(file_name, file);
+ setup();
+ clearok(curscr, TRUE);
+ touchwin(cw);
+ srand(getpid());
+ playit();
+ /*NOTREACHED*/
+ return(FALSE);
+}
+
+/*
+ * perform an encrypted write
+ */
+encwrite(start, size, outf)
+register char *start;
+register unsigned size;
+register FILE *outf;
+{
+ register char *ep;
+ register num_written = 0;
+
+ ep = encstr;
+
+ while (size--)
+ {
+ if (putc(*start++ ^ *ep++, outf) == EOF && ferror(outf))
+ return(num_written);
+ num_written++;
+ if (*ep == '\0')
+ ep = encstr;
+ }
+ 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 0ef99244acb8 -r 0ed67132cf10 arogue5/scrolls.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/scrolls.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,709 @@
+/*
+ * Read a scroll and let it happen
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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"
+
+
+
+/*
+ * 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 int i;
+ 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;
+ char monst_name[40];
+
+ /* 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(hw,' ');
+ }
+
+ else {
+ mvwaddstr(hw, 0, 0, "Which monster");
+ if (!terse) waddstr(hw, " do you wish to wipe out");
+ waddstr(hw, "? ");
+ draw(hw);
+ }
+ }
+
+get_monst:
+ get_str(monst_name, hw);
+ which_monst = atoi(monst_name);
+ if ((which_monst < 1 || which_monst > NUMMONST-NUMUNIQUE-1)) {
+ mvwaddstr(hw, 0, 0, "Please enter a number in the displayed range -- ");
+ draw(hw);
+ goto get_monst;
+ }
+
+ /* Set up for redraw */
+ clearok(cw, TRUE);
+ touchwin(cw);
+
+ /* 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);
+ }
+ }
+
+ /* 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 = NULL, *nobj;
+ register struct linked_list *item, *nitem;
+ register int i,j;
+ register char ch, nch;
+ bool cursed, blessed;
+ char buf[LINELEN];
+
+ blessed = FALSE;
+ cursed = FALSE;
+ item = NULL;
+
+ if (which < 0) {
+ if (on(player, ISBLIND)) {
+ msg("You can't see to read anything");
+ return;
+ }
+ item = get_item(pack, "read", SCROLL);
+ if (item == NULL)
+ return;
+
+ 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();
+ 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.");
+ no_command += 4 + rnd(SLEEPTIME);
+ }
+ }
+ 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 += SLEEPTIME;
+ 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
+ */
+ if (lvl_obj != NULL) {
+ register struct linked_list *gitem;
+ struct object *cur;
+ int gtotal = 0;
+
+ wclear(hw);
+ for (gitem = lvl_obj; gitem != NULL; gitem = next(gitem)) {
+ cur = OBJPTR(gitem);
+ if (cur->o_type == GOLD) {
+ gtotal += cur->o_count;
+ mvwaddch(hw, cur->o_pos.y, cur->o_pos.x, GOLD);
+ }
+ }
+ if (gtotal) {
+ if (is_scroll) s_know[S_GFIND] = TRUE;
+ msg("You begin to feel greedy and you sense gold.");
+ overlay(hw,cw);
+ 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();
+ }
+ 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 {
+ if ((nitem = get_item(pack, "remove the curse on",ALL))!=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)) != 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:
+ case MM_PROTECT:
+ 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));
+ }
+ 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");
+ }
+ }
+ otherwise:
+ msg("What a puzzling scroll!");
+ return;
+ }
+ look(TRUE, FALSE); /* put the result of the scroll on the screen */
+ status(FALSE);
+ if (is_scroll && s_know[which] && s_guess[which])
+ {
+ free(s_guess[which]);
+ s_guess[which] = NULL;
+ }
+ else if (is_scroll &&
+ !s_know[which] &&
+ askme &&
+ (obj->o_flags & ISKNOW) == 0 &&
+ (obj->o_flags & ISPOST) == 0 &&
+ s_guess[which] == NULL) {
+ msg(terse ? "Call it: " : "What do you want to call it? ");
+ if (get_str(buf, cw) == NORM)
+ {
+ s_guess[which] = new(strlen(buf) + 1);
+ strcpy(s_guess[which], buf);
+ }
+ }
+ if (item != NULL) o_discard(item);
+ updpack(TRUE);
+}
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/state.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/state.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,2477 @@
+/*
+ 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, 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;
+ 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;
+ 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_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_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; n++)
+ {
+ rs_write_int(savef,i[n].mi_prob);
+ }
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_magic_items(int inf, struct magic_item *mi, int count)
+{
+ int n;
+ int value;
+
+ rs_read_marker(inf, RSID_MAGICITEMS);
+
+ rs_read_int(inf, &value);
+
+ if (value != count)
+ format_error = 1;
+ else
+ {
+ for(n = 0; n < value; n++)
+ {
+ rs_read_int(inf,&mi[n].mi_prob);
+ }
+ }
+
+ return(READSTAT);
+}
+
+int
+rs_write_scrolls(FILE *savef)
+{
+ int i;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ for(i = 0; i < MAXSCROLLS; i++)
+ {
+ rs_write_string(savef, s_names[i]);
+ rs_write_boolean(savef,s_know[i]);
+ rs_write_string(savef,s_guess[i]);
+ }
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_scrolls(int inf)
+{
+ int i;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ for(i = 0; i < MAXSCROLLS; i++)
+ {
+ rs_read_new_string(inf,&s_names[i]);
+ rs_read_boolean(inf,&s_know[i]);
+ rs_read_new_string(inf,&s_guess[i]);
+ }
+
+ return(READSTAT);
+}
+
+int
+rs_write_potions(FILE *savef)
+{
+ int i;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ for(i = 0; i < MAXPOTIONS; i++)
+ {
+ rs_write_string_index(savef,rainbow,NCOLORS,p_colors[i]);
+ rs_write_boolean(savef,p_know[i]);
+ rs_write_string(savef,p_guess[i]);
+ }
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_potions(int inf)
+{
+ int i;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ for(i = 0; i < MAXPOTIONS; i++)
+ {
+ rs_read_string_index(inf,rainbow,NCOLORS,&p_colors[i]);
+ rs_read_boolean(inf,&p_know[i]);
+ rs_read_new_string(inf,&p_guess[i]);
+ }
+
+ return(READSTAT);
+}
+
+int
+rs_write_rings(FILE *savef)
+{
+ int i;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ for(i = 0; i < MAXRINGS; i++)
+ {
+ rs_write_string_index(savef,stones,NSTONES,r_stones[i]);
+ rs_write_boolean(savef,r_know[i]);
+ rs_write_string(savef,r_guess[i]);
+ }
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_rings(int inf)
+{
+ int i;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ for(i = 0; i < MAXRINGS; i++)
+ {
+ rs_read_string_index(inf,stones,NSTONES,&r_stones[i]);
+ rs_read_boolean(inf,&r_know[i]);
+ rs_read_new_string(inf,&r_guess[i]);
+ }
+
+ return(READSTAT);
+}
+
+int
+rs_write_sticks(FILE *savef)
+{
+ int i;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ rs_write_marker(savef, RSID_STICKS);
+
+ for (i = 0; i < MAXSTICKS; i++)
+ {
+ if (strcmp(ws_type[i],"staff") == 0)
+ {
+ rs_write_int(savef,0);
+ rs_write_string_index(savef,wood,NWOOD,ws_made[i]);
+ }
+ else
+ {
+ rs_write_int(savef,1);
+ rs_write_string_index(savef,metal,NMETAL,ws_made[i]);
+ }
+
+ rs_write_boolean(savef, ws_know[i]);
+ rs_write_string(savef, ws_guess[i]);
+ }
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_sticks(int inf)
+{
+ int i = 0, j = 0, list = 0;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read_marker(inf, RSID_STICKS);
+
+ for(i = 0; i < MAXSTICKS; i++)
+ {
+ rs_read_int(inf,&list);
+ ws_made[i] = NULL;
+
+ if (list == 0)
+ {
+ rs_read_string_index(inf,wood,NWOOD,&ws_made[i]);
+ ws_type[i] = "staff";
+ }
+ else
+ {
+ rs_read_string_index(inf,metal,NMETAL,&ws_made[i]);
+ ws_type[i] = "wand";
+ }
+ rs_read_boolean(inf, &ws_know[i]);
+ rs_read_new_string(inf, &ws_guess[i]);
+ }
+
+ return(READSTAT);
+}
+
+int
+rs_write_daemons(FILE *savef, struct delayed_action *d_list, int count)
+{
+ int i = 0;
+ int func = 0;
+
+ if (write_error)
+ return(WRITESTAT);
+
+ rs_write_marker(savef, RSID_DAEMONS);
+ rs_write_int(savef, count);
+
+ for(i = 0; i < count; i++)
+ {
+ if ( d_list[i].d_func == rollwand)
+ func = 1;
+ else if ( d_list[i].d_func == doctor)
+ func = 2;
+ else if ( d_list[i].d_func == stomach)
+ func = 3;
+ else if ( d_list[i].d_func == runners)
+ func = 4;
+ else if ( d_list[i].d_func == swander)
+ func = 5;
+ else if ( d_list[i].d_func == trap_look)
+ func = 6;
+ else if ( d_list[i].d_func == ring_search)
+ func = 7;
+ else if ( d_list[i].d_func == ring_teleport)
+ func = 8;
+ else if ( d_list[i].d_func == strangle)
+ func = 9;
+ else if ( d_list[i].d_func == fumble)
+ func = 10;
+ else if ( d_list[i].d_func == wghtchk)
+ func = 11;
+ else if ( d_list[i].d_func == unstink)
+ func = 12;
+ else if ( d_list[i].d_func == res_strength)
+ func = 13;
+ else if ( d_list[i].d_func == un_itch)
+ func = 14;
+ else if ( d_list[i].d_func == cure_disease)
+ func = 15;
+ else if ( d_list[i].d_func == unconfuse)
+ func = 16;
+ else if ( d_list[i].d_func == suffocate)
+ func = 17;
+ else if ( d_list[i].d_func == undance)
+ func = 18;
+ else if ( d_list[i].d_func == alchemy)
+ func = 19;
+ else if ( d_list[i].d_func == dust_appear)
+ func = 20;
+ else if ( d_list[i].d_func == unchoke)
+ func = 21;
+ else if ( d_list[i].d_func == sight)
+ func = 22;
+ else if ( d_list[i].d_func == noslow)
+ func = 23;
+ else if ( d_list[i].d_func == nohaste)
+ func = 24;
+ else if ( d_list[i].d_func == unclrhead)
+ func = 25;
+ else if ( d_list[i].d_func == unsee)
+ func = 26;
+ else if ( d_list[i].d_func == unphase)
+ func = 27;
+ else if ( d_list[i].d_func == land)
+ func = 28;
+ else if ( d_list[i].d_func == appear)
+ func = 29;
+ else if (d_list[i].d_func == NULL)
+ func = 0;
+ else
+ func = -1;
+
+ rs_write_int(savef, d_list[i].d_type);
+ rs_write_int(savef, func);
+ rs_write_int(savef, d_list[i].d_arg);
+ rs_write_int(savef, d_list[i].d_time);
+ }
+
+ return(WRITESTAT);
+}
+
+int
+rs_read_daemons(int inf, struct delayed_action *d_list, int count)
+{
+ int i = 0;
+ int func = 0;
+ int value = 0;
+ int dummy = 0;
+
+ if (read_error || format_error)
+ return(READSTAT);
+
+ rs_read_marker(inf, RSID_DAEMONS);
+ rs_read_int(inf, &value);
+
+ if (value > 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 = runners;
+ break;
+ case 5: d_list[i].d_func = swander;
+ break;
+ case 6: d_list[i].d_func = trap_look;
+ break;
+ case 7: d_list[i].d_func = ring_search;
+ break;
+ case 8: d_list[i].d_func = ring_teleport;
+ break;
+ case 9: d_list[i].d_func = strangle;
+ break;
+ case 10: d_list[i].d_func = fumble;
+ break;
+ case 11: d_list[i].d_func = wghtchk;
+ break;
+ case 12: d_list[i].d_func = unstink;
+ break;
+ case 13: d_list[i].d_func = res_strength;
+ break;
+ case 14: d_list[i].d_func = un_itch;
+ break;
+ case 15: d_list[i].d_func = cure_disease;
+ break;
+ case 16: d_list[i].d_func = unconfuse;
+ break;
+ case 17: d_list[i].d_func = suffocate;
+ break;
+ case 18: d_list[i].d_func = undance;
+ break;
+ case 19: d_list[i].d_func = alchemy;
+ break;
+ case 20: d_list[i].d_func = dust_appear;
+ break;
+ case 21: d_list[i].d_func = unchoke;
+ break;
+ case 22: d_list[i].d_func = sight;
+ break;
+ case 23: d_list[i].d_func = noslow;
+ break;
+ case 24: d_list[i].d_func = nohaste;
+ break;
+ case 25: d_list[i].d_func = unclrhead;
+ break;
+ case 26: d_list[i].d_func = unsee;
+ break;
+ case 27: d_list[i].d_func = unphase;
+ break;
+ case 28: d_list[i].d_func = land;
+ break;
+ case 29: d_list[i].d_func = appear;
+ break;
+ case 0:
+ case -1:
+ default: d_list[i].d_func = NULL;
+ break;
+ }
+
+ 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_arg = 0;
+ 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);
+}
+
+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_turn);
+ 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_door_reference(savef, t->t_doorgoal);
+
+ rs_write_coord(savef, t->t_pos);
+ rs_write_coord(savef, t->t_oldpos);
+
+ /*
+ t_dest can be:
+ 0,0: NULL
+ 0,1: location of hero
+ 0,3: global coord 'delta'
+ 1,i: location of a thing (monster)
+ 2,i: location of an object
+ 3,i: location of gold in a room
+
+ We need to remember what we are chasing rather than
+ the current location of what we are chasing.
+ */
+
+ 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_ulongs(savef, t->t_flags, 16);
+ rs_write_object_list(savef, t->t_pack);
+ 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_turn);
+ 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_door_reference(inf,&t->t_doorgoal);
+ rs_read_coord(inf, &t->t_pos);
+ rs_read_coord(inf, &t->t_oldpos);
+
+ /*
+ t_dest can be (listid,index):
+ 0,0: NULL
+ 0,1: location of hero
+ 1,i: location of a thing (monster)
+ 2,i: location of an object
+ 3,i: location of gold in a room
+
+ We need to remember what we are chasing rather than
+ the current location of what we are chasing.
+ */
+
+ rs_read_int(inf, &listid);
+ rs_read_int(inf, &index);
+ t->t_reserved = -1;
+
+ if (listid == 0) /* hero or NULL */
+ {
+ if (index == 1)
+ t->t_dest = &hero;
+ else
+ t->t_dest = NULL;
+ }
+ else if (listid == 1) /* monster/thing */
+ {
+ t->t_dest = NULL;
+ t->t_reserved = index;
+ }
+ else if (listid == 2) /* object */
+ {
+ 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_ulongs(inf, t->t_flags, 16);
+ rs_read_object_list(inf, &t->t_pack);
+ 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_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, no_move);
+ 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, lost_dext);
+ rs_write_int(savef, no_command);
+ 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, pray_time);
+ rs_write_int(savef, spell_power);
+ rs_write_int(savef, turns);
+ rs_write_int(savef, quest_item);
+ rs_write_char(savef, nfloors);
+ rs_write(savef, curpurch, 15);
+ rs_write_char(savef, PLAYER);
+ rs_write_char(savef, take);
+ rs_write(savef, prbuf, LINELEN);
+ rs_write_char(savef, runch);
+ rs_write(savef, whoami, LINELEN);
+ rs_write(savef, fruit, LINELEN);
+ rs_write_scrolls(savef);
+ rs_write_potions(savef);
+ rs_write_rings(savef);
+ rs_write_sticks(savef);
+ for(i = 0; i < MAXMM; i++)
+ rs_write_string(savef, m_guess[i]);
+ rs_write_window(savef, cw);
+ rs_write_window(savef, mw);
+ 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_booleans(savef, m_know, MAXMM);
+ 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, 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_coord(savef, delta);
+ rs_write_levtype(savef, levtype);
+
+ rs_write_monsters(savef, monsters, NUMMONST+1);
+
+ rs_write_magic_items(savef, things, NUMTHINGS);
+ 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_coord(savef, ch_ret);
+ rs_write_int(savef, demoncnt);
+ rs_write_int(savef, fusecnt);
+ rs_write_daemons(savef, d_list, MAXDAEMONS);
+ rs_write_daemons(savef, f_list, MAXFUSES);
+ rs_write_int(savef, between);
+
+ fflush(savef);
+
+ return(WRITESTAT);
+}
+
+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, &no_move);
+ 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, &lost_dext);
+ rs_read_int(inf, &no_command);
+ 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, &pray_time);
+ rs_read_int(inf, &spell_power);
+ rs_read_int(inf, &turns);
+ rs_read_int(inf, &quest_item);
+ rs_read_char(inf, &nfloors);
+ rs_read(inf, &curpurch, 15);
+ rs_read_char(inf, &PLAYER);
+ rs_read_char(inf, &take);
+ rs_read(inf, &prbuf, LINELEN);
+ rs_read_char(inf, &runch);
+ rs_read(inf, &whoami, LINELEN);
+ rs_read(inf, &fruit, LINELEN);
+ rs_read_scrolls(inf);
+ rs_read_potions(inf);
+ rs_read_rings(inf);
+ rs_read_sticks(inf);
+ for(i = 0; i < MAXMM; i++)
+ rs_read_new_string(inf, &m_guess[i]);
+ rs_read_window(inf, cw);
+ rs_read_window(inf, mw);
+ 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_booleans(inf, m_know, MAXMM);
+ 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, &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_coord(inf, &delta);
+ rs_read_levtype(inf, &levtype);
+
+ rs_read_monsters(inf, monsters, NUMMONST+1);
+
+ rs_read_magic_items(inf, things, NUMTHINGS);
+ 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_coord(inf, &ch_ret);
+ rs_read_int(inf, &demoncnt);
+ rs_read_int(inf, &fusecnt);
+ rs_read_daemons(inf, d_list, MAXDAEMONS);
+ rs_read_daemons(inf, f_list, MAXFUSES);
+ rs_read_int(inf, &between);
+
+ return(READSTAT);
+}
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/sticks.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/sticks.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,1076 @@
+/*
+ * Functions to implement the various sticks one might find
+ * while wandering around the dungeon.
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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"
+
+
+/*
+ * zap a stick and see what happens
+ */
+do_zap(gotdir, which, flag)
+bool gotdir;
+int which;
+int flag;
+{
+ register struct linked_list *item;
+ register struct object *obj = NULL;
+ register struct thing *tp;
+ register int y, x;
+ struct linked_list *nitem;
+ struct object *nobj;
+ bool cursed, blessed, is_stick;
+
+ blessed = FALSE;
+ cursed = FALSE;
+ is_stick = FALSE;
+
+ if (which == 0) {
+ if ((item = get_item(pack, "zap with", ZAPPABLE)) == NULL)
+ return(FALSE);
+ 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 ASMO_ROD:
+ switch (rnd(3)) {
+ case 0:
+ which = WS_ELECT;
+ when 1:
+ which = WS_COLD;
+ otherwise:
+ which = WS_FIRE;
+ }
+ }
+ cursed = FALSE;
+ blessed = FALSE;
+ }
+ else {
+ which = obj->o_which;
+ ws_know[which] = TRUE;
+ cursed = (obj->o_flags & ISCURSED) != 0;
+ blessed = (obj->o_flags & ISBLESSED) != 0;
+ is_stick = TRUE;
+ }
+ }
+ else {
+ cursed = flag & ISCURSED;
+ blessed = flag & ISBLESSED;
+ }
+ switch (which) { /* no direction for these */
+ case WS_LIGHT:
+ case WS_DRAIN:
+ case WS_CHARGE:
+ case WS_CURING:
+ break;
+
+ default:
+ if (!get_dir())
+ return(FALSE);
+ if (!gotdir) {
+ do {
+ delta.y = rnd(3) - 1;
+ delta.x = rnd(3) - 1;
+ } while (delta.y == 0 && delta.x == 0);
+ }
+ }
+
+ if (is_stick) {
+ if (obj->o_charges < 1) {
+ msg(nothing);
+ return(TRUE);
+ }
+ 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;
+ }
+ }
+
+ 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.");
+ return(TRUE);
+ }
+ if (cursed)
+ pstats.s_hpt /= 2;
+ else
+ drain(hero.y-1, hero.y+1, hero.x-1, hero.x+1);
+ when WS_POLYMORPH:
+ case WS_TELMON:
+ case WS_CANCEL:
+ {
+ register char monster, oldch;
+ register int rm;
+
+ y = hero.y;
+ x = hero.x;
+ while (shoot_ok(winat(y, x))) {
+ y += delta.y;
+ x += delta.x;
+ }
+ if (isalpha(monster = CCHAR( mvwinch(mw, y, x) ))) {
+ register struct room *rp;
+
+ item = find_mons(y, x);
+ tp = THINGPTR(item);
+ /* if the monster gets the saving throw, leave the case */
+ if (save(VS_MAGIC, tp, 0)) {
+ msg(nothing);
+ break;
+ }
+
+ /* Unhold player */
+ if (on(*tp, DIDHOLD)) {
+ turn_off(*tp, DIDHOLD);
+ if (--hold_count == 0) turn_off(player, ISHELD);
+ }
+ /* unsuffocate player */
+ if (on(*tp, DIDSUFFOCATE)) {
+ turn_off(*tp, DIDSUFFOCATE);
+ extinguish(suffocate);
+ }
+ rp = roomin(&tp->t_pos);
+ /*
+ * check to see if room should go dark
+ */
+ if (on(*tp, HASFIRE)) {
+ if (rp != NULL) {
+ register struct linked_list *fire_item;
+
+ 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;
+ }
+ }
+ }
+ }
+
+ if (which == WS_POLYMORPH) {
+ register struct linked_list *pitem;
+
+ 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;
+ monster = tp->t_type;
+ if (isalpha(mvwinch(cw, y, x)))
+ mvwaddch(cw, y, x, monster);
+ 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);
+ }
+ }
+ msg(terse ? "A new %s!" : "You have created a new %s!",
+ monsters[tp->t_index].m_name);
+ }
+ else if (which == WS_CANCEL) {
+ 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[4] &= CANC5MASK;
+ }
+ else { /* A teleport stick */
+ if (cursed) { /* Teleport monster to player */
+ if ((y == (hero.y + delta.y)) &&
+ (x == (hero.x + delta.x)))
+ msg(nothing);
+ else {
+ tp->t_pos.y = hero.y + delta.y;
+ tp->t_pos.x = hero.x + delta.x;
+ }
+ }
+ else if (blessed) { /* Get rid of monster */
+ killed(item, FALSE, TRUE);
+ return(TRUE);
+ }
+ 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);
+ turn_off(*tp, ISDISGUISE);
+ mvwaddch(mw, y, x, ' ');
+ mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, monster);
+ 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)) {
+ 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);
+ }
+ }
+ when WS_MISSILE:
+ {
+ static struct object bolt =
+ {
+ MISSILE , {0, 0}, "", 0, "", "1d4 " , NULL, 0, WS_MISSILE, 50, 1
+ };
+
+ sprintf(bolt.o_hurldmg, "%dd4", pstats.s_lvl);
+ do_motion(&bolt, delta.y, delta.x, &player);
+ if (!hit_monster(unc(bolt.o_pos), &bolt, &player))
+ 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 */
+
+ delta.y += hero.y;
+ delta.x += hero.x;
+ ch = CCHAR( winat(delta.y, delta.x) );
+ if (isalpha(ch))
+ {
+ strike = *obj;
+ strike.o_hplus = 6;
+ if (EQUAL(ws_type[which], "staff"))
+ strcpy(strike.o_damage,"3d8");
+ else
+ strcpy(strike.o_damage,"2d8");
+ fight(&delta, &strike, FALSE);
+ }
+ }
+ case WS_SLOW_M:
+ y = hero.y;
+ x = hero.x;
+ while (shoot_ok(winat(y, x))) {
+ y += delta.y;
+ x += delta.x;
+ }
+ if (isalpha(mvwinch(mw, y, x))) {
+ item = find_mons(y, x);
+ tp = THINGPTR(item);
+ runto(tp, &hero);
+ if (on(*tp, ISUNIQUE) && save(VS_MAGIC, tp, 0))
+ msg(nothing);
+ else if (on(*tp, NOSLOW))
+ msg(nothing);
+ else if (cursed) {
+ if (on(*tp, ISSLOW))
+ turn_off(*tp, ISSLOW);
+ else
+ turn_on(*tp, ISHASTE);
+ }
+ else if (blessed) {
+ turn_off(*tp, ISRUN);
+ turn_on(*tp, ISHELD);
+ return(TRUE);
+ }
+ else {
+ if (on(*tp, ISHASTE))
+ turn_off(*tp, ISHASTE);
+ else
+ turn_on(*tp, ISSLOW);
+ tp->t_turn = TRUE;
+ }
+ }
+ when WS_CHARGE:
+ if (ws_know[WS_CHARGE] != TRUE && is_stick)
+ msg("This is a wand of charging.");
+ if ((nitem = get_item(pack, "charge", STICK)) != NULL) {
+ nobj = OBJPTR(nitem);
+ if ((++(nobj->o_charges) == 1) && (nobj->o_which == WS_HIT))
+ fix_stick(nobj);
+ 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:
+ case WS_FIRE:
+ case WS_COLD:
+ {
+ char *name;
+
+ if (which == WS_ELECT)
+ name = "lightning bolt";
+ else if (which == WS_FIRE)
+ name = "flame";
+ else
+ name = "ice";
+
+ shoot_bolt( &player, hero,
+ delta, TRUE, D_BOLT,
+ name, roll(pstats.s_lvl,6));
+ }
+ when WS_PETRIFY: {
+ reg int m1, m2, x1, y1;
+ reg char ch;
+ reg struct linked_list *ll;
+ reg struct thing *lt;
+
+ y1 = hero.y;
+ x1 = hero.x;
+ do {
+ y1 += delta.y;
+ x1 += delta.x;
+ ch = CCHAR( winat(y1,x1) );
+ } while (ch == PASSAGE || ch == FLOOR);
+ for (m1 = x1 - 1 ; m1 <= x1 + 1 ; m1++) {
+ for(m2 = y1 - 1 ; m2 <= y1 + 1 ; m2++) {
+ ch = CCHAR( winat(m2,m1) );
+ if (m1 == hero.x && m2 == hero.y)
+ continue;
+ if (ch != ' ') {
+ ll = find_obj(m2,m1);
+ if (ll != NULL) {
+ detach(lvl_obj,ll);
+ o_discard(ll);
+ }
+ ll = find_mons(m2,m1);
+ if (ll != NULL) {
+ lt = THINGPTR(ll);
+ if (on(*lt, ISUNIQUE))
+ monsters[lt->t_index].m_normal = TRUE;
+ check_residue(lt);
+ detach(mlist,ll);
+ t_discard(ll);
+ mvwaddch(mw,m2,m1,' ');
+ }
+ mvaddch(m2,m1,' ');
+ mvwaddch(cw,m2,m1,' ');
+ }
+ }
+ }
+ touchwin(cw);
+ touchwin(mw);
+ }
+ when WS_CONFMON:
+ if (cursed) {
+ 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("Wait, what's going on here. Huh? What? Who?");
+ }
+ }
+ else msg("You feel dizzy for a moment, but it quickly passes.");
+ }
+ else {
+ y = hero.y;
+ x = hero.x;
+ while (shoot_ok(winat(y, x)))
+ {
+ y += delta.y;
+ x += delta.x;
+ }
+ if (isalpha(mvwinch(mw, y, x)))
+ {
+ item = find_mons(y, x);
+ tp = THINGPTR(item);
+ if (save(VS_MAGIC, tp, 0) || on(*tp, ISCLEAR))
+ msg(nothing);
+ else
+ turn_on (*tp, ISHUH);
+ runto(tp, &hero);
+ }
+ }
+ when WS_PARALYZE:
+ if (cursed) {
+ no_command += FREEZETIME;
+ msg("You can't move.");
+ }
+ else {
+ y = hero.y;
+ x = hero.x;
+ while (shoot_ok(winat(y, x)))
+ {
+ y += delta.y;
+ x += delta.x;
+ }
+ if (isalpha(mvwinch(mw, y, x)))
+ {
+ item = find_mons(y, x);
+ tp = THINGPTR(item);
+ if (save(VS_WAND, tp, 0) || on(*tp, NOPARALYZE))
+ msg(nothing);
+ else {
+ tp->t_no_move = FREEZETIME;
+ }
+ runto(tp, &hero);
+ }
+ }
+ when WS_FEAR:
+ y = hero.y;
+ x = hero.x;
+ while (shoot_ok(winat(y, x)))
+ {
+ y += delta.y;
+ x += delta.x;
+ }
+ if (isalpha(mvwinch(mw, y, x)))
+ {
+ item = find_mons(y, x);
+ tp = THINGPTR(item);
+ runto(tp, &hero);
+ if (save(VS_WAND, tp, 0) ||
+ on(*tp, ISUNDEAD) ||
+ on(*tp, NOFEAR))
+ msg(nothing);
+ else {
+ turn_on(*tp, ISFLEE);
+ turn_on(*tp, WASTURNED);
+
+ /* 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);
+ }
+ }
+ when WS_MDEG:
+ y = hero.y;
+ x = hero.x;
+ while (shoot_ok(winat(y, x)))
+ {
+ y += delta.y;
+ x += delta.x;
+ }
+ if (isalpha(mvwinch(mw, y, x)))
+ {
+ item = find_mons(y, x);
+ tp = THINGPTR(item);
+ if (cursed) {
+ tp->t_stats.s_hpt *= 2;
+ msg("The %s appears to be stronger now!",
+ monsters[tp->t_index].m_name);
+ }
+ else if (on(*tp, ISUNIQUE) && save(VS_WAND, tp, 0))
+ msg (nothing);
+ else {
+ tp->t_stats.s_hpt /= 2;
+ msg("The %s appears to be weaker now",
+ monsters[tp->t_index].m_name);
+ }
+ runto(tp, &hero);
+ if (tp->t_stats.s_hpt < 1)
+ killed(item, TRUE, TRUE);
+ }
+ when WS_DISINTEGRATE:
+ y = hero.y;
+ x = hero.x;
+ while (shoot_ok(winat(y, x))) {
+ y += delta.y;
+ x += delta.x;
+ }
+ if (isalpha(mvwinch(mw, y, x))) {
+ item = find_mons(y, x);
+ tp = THINGPTR(item);
+ turn_on (*tp, ISMEAN);
+ runto(tp, &hero);
+ 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++) {
+ ch = CCHAR( winat(m2,m1) );
+ if (shoot_ok(ch) && ch != PLAYER) {
+ 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 */
+ tp = THINGPTR(item);
+ 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);
+ msg("You have disintegrated the %s",
+ monsters[tp->t_index].m_name);
+ }
+ else {
+ msg("The %s appears wounded",
+ monsters[tp->t_index].m_name);
+ }
+ }
+ else {
+ msg("You have disintegrated the %s",
+ monsters[tp->t_index].m_name);
+ killed (item, FALSE, TRUE);
+ }
+ }
+ }
+ when WS_CURING:
+ ws_know[WS_CURING] = TRUE;
+ 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)) {
+ 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, 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!");
+ }
+ return(TRUE);
+}
+
+
+/*
+ * 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);
+ else {
+ runto(ick, &hero);
+ if (cansee(i,j) && (!on(*ick,ISINVIS)||on(player,CANSEE)))
+ msg("The %s appears wounded",
+ monsters[ick->t_index].m_name);
+ }
+ }
+ }
+ }
+}
+
+/*
+ * 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);
+ strcpy(cur->o_damage,"2d3");
+ cur->o_hplus = 1;
+ cur->o_dplus = 0;
+ switch (cur->o_which) {
+ case WS_HIT:
+ cur->o_hplus = 3;
+ cur->o_dplus = 3;
+ strcpy(cur->o_damage,"2d8");
+ when WS_LIGHT:
+ cur->o_charges = 20 + rnd(10);
+ }
+ }
+ else {
+ strcpy(cur->o_damage,"1d3");
+ 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;
+ strcpy(cur->o_damage,"1d8");
+ when WS_LIGHT:
+ cur->o_charges = 10 + rnd(10);
+ }
+ }
+ strcpy(cur->o_hurldmg,"1d1");
+
+}
+
+/*
+ * 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 = 0, ch;
+ register bool used, change;
+ register short y, x, bounces;
+ bool mdead = FALSE;
+ coord pos;
+ 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 const char *mname;
+ bool see_monster = cansee(pos.y, pos.x);
+
+ item = find_mons(unc(pos));
+ tp = THINGPTR(item);
+ mname = monsters[tp->t_index].m_name;
+
+ 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);
+ }
+
+ sprintf(outstring,"The %s hits the %s", name, mname);
+ msg(outstring);
+ }
+
+ tp->t_wasshot = TRUE;
+ runto(tp, &hero);
+ 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){
+ sprintf(outstring,"The %s has no effect on the %s.",
+ name, mname);
+ msg(outstring);
+ }
+ }
+
+ /*
+ * Check for gas with special effects
+ */
+ else if (EQUAL(name, "nerve gas")) {
+ tp->t_no_move = FREEZETIME;
+ }
+ else if (EQUAL(name, "sleeping gas")) {
+ tp->t_no_move = SLEEPTIME;
+ }
+ else if (EQUAL(name, "slow gas")) {
+ if (on(*tp, ISHASTE))
+ turn_off(*tp, ISHASTE);
+ else
+ turn_on(*tp, ISSLOW);
+ tp->t_turn = TRUE;
+ }
+ else if (EQUAL(name, "fear gas")) {
+ turn_on(*tp, ISFLEE);
+ tp->t_dest = &hero;
+ }
+ 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){
+ sprintf(outstring,"The %s divides the %s.",name,mname);
+ msg(outstring);
+ }
+ light(&hero);
+ }
+ else if (see_monster){
+ sprintf(outstring,"The %s has no effect on the %s.",
+ name, mname);
+ msg(outstring);
+ }
+ }
+ 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){
+ sprintf(outstring,"The %s kills the %s", name, mname);
+ msg(outstring);
+ }
+ else
+ msg("You hear a faint groan in the distance");
+ killed(item, FALSE, get_points);
+
+ /* Replace the screen character */
+ spotpos[y].oldch = CCHAR( mvwinch(cw, pos.y, pos.x) );
+
+ mdead = TRUE;
+ }
+ 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 {
+ sprintf(outstring,"The %s whizzes past the %s", name, mname);
+ msg(outstring);
+ }
+ }
+ 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,"fear gas")&&ISWEARING(R_HEROISM))){
+ msg("The %s has no affect", name);
+ }
+ /*
+ * Check for gas with special effects
+ */
+ else if (EQUAL(name, "nerve gas")) {
+ msg("The nerve gas paralyzes you.");
+ no_command += FREEZETIME;
+ }
+ else if (EQUAL(name, "sleeping gas")) {
+ msg("The sleeping gas puts you to sleep.");
+ no_command += SLEEPTIME;
+ }
+ 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(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;
+ }
+ for (x = y - 1; x >= 0; x--)
+ mvwaddch(cw, spotpos[x].place.y, spotpos[x].place.x, spotpos[x].oldch);
+ return(mdead);
+}
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/things.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/things.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,849 @@
+/*
+ * Contains functions for dealing with things like
+ * potions and scrolls
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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"
+
+/*
+ * 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, "called %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 (obj->o_flags & ISPOST)
+ sprintf(pb, "of %s", p_magic[obj->o_which].mi_name);
+ else if (p_know[obj->o_which])
+ sprintf(pb, "of %s (%s)", p_magic[obj->o_which].mi_name,
+ p_colors[obj->o_which]);
+ else if (p_guess[obj->o_which])
+ sprintf(pb, "called %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_which == 1)
+ if (obj->o_count == 1)
+ sprintf(pb, "A%s %s", vowelstr(fruit), fruit);
+ else
+ sprintf(pb, "%d %ss", obj->o_count, fruit);
+ else
+ if (obj->o_count == 1)
+ strcpy(pb, "Some food");
+ else
+ sprintf(pb, "%d rations of food", obj->o_count);
+ 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)");
+ 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 (obj->o_flags & ISPOST)
+ sprintf(pb, "of %s", ws_magic[obj->o_which].mi_name);
+ else if (ws_know[obj->o_which])
+ sprintf(pb, "of %s%s (%s)", ws_magic[obj->o_which].mi_name,
+ charge_str(obj), ws_made[obj->o_which]);
+ else if (ws_guess[obj->o_which])
+ sprintf(pb, "called %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 (obj->o_flags & ISPOST)
+ sprintf(pb, "A ring of %s", r_magic[obj->o_which].mi_name);
+ else if (r_know[obj->o_which])
+ 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 (r_guess[obj->o_which])
+ sprintf(pb, "A ring called %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)
+ 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 BRIAN_MANDOLIN:
+ strcpy(pb, "A gleaming mandolin");
+ when HRUGGEK_MSTAR:
+ strcpy(pb, "A huge morning star");
+ when GERYON_HORN:
+ strcpy(pb, "A jet black horn");
+ when YEENOGHU_FLAIL:
+ strcpy(pb, "A shimmering flail");
+ 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)");
+ when HEIL_ANKH:
+ if (cur_relic[HEIL_ANKH]) strcat(pb, " (in hand)");
+ when YENDOR_AMULET:
+ if (cur_relic[YENDOR_AMULET] &&
+ cur_misc[WEAR_JEWEL] == NULL)
+ strcat(pb, " (in chest)");
+ when MUSTY_DAGGER:
+ case HRUGGEK_MSTAR:
+ case YEENOGHU_FLAIL:
+ case MING_STAFF:
+ case ASMO_ROD:
+ case ORCUS_WAND:
+ if (cur_weapon == obj) strcat(pb, " (weapon in hand)");
+ }
+ 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, " called: ");
+ 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 RELIC:
+ switch (obj->o_which) {
+ case MUSTY_DAGGER:
+ return("daggers");
+ when YEENOGHU_FLAIL:
+ return("flail");
+ 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 = 0;
+ register struct linked_list *obj, *nobj;
+ register struct object *op;
+
+ if (item == NULL) {
+ 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);
+ }
+ if ((obj = get_item(pack, "drop", ALL)) == NULL)
+ 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);
+ 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 (cw,' ');
+ 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 == cur_armor) {
+ waste_time();
+ }
+ else if (op->o_type == RING) {
+ if (cur_misc[WEAR_GAUNTLET] != NULL) {
+ msg ("You have to remove your gauntlets first!");
+ return FALSE;
+ }
+
+ 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 (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: turn_off(player, NOCOLD);
+ when R_FIRE: 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);
+ }
+ }
+ cur_null(op); /* set current to NULL */
+ return TRUE;
+}
+
+/*
+ * return a new thing
+ */
+struct linked_list *
+new_thing(thing_type)
+int thing_type;
+{
+ register struct linked_list *item;
+ register struct object *cur;
+ register int j, k;
+ register int blesschance, cursechance;
+
+ item = new_item(sizeof *cur);
+ cur = OBJPTR(item);
+ cur->o_hplus = cur->o_dplus = 0;
+ strcpy(cur->o_damage,"0d0");
+ strcpy(cur->o_hurldmg,"0d0");
+ 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);
+ cursechance = rnd(100);
+
+ /* 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;
+ cur->o_which = pick_one(p_magic, MAXPOTIONS);
+ cur->o_weight = things[TYP_POTION].mi_wght;
+ if (cursechance < p_magic[cur->o_which].mi_curse)
+ cur->o_flags |= ISCURSED;
+ else if (blesschance < p_magic[cur->o_which].mi_bless)
+ cur->o_flags |= ISBLESSED;
+ when TYP_SCROLL:
+ cur->o_type = SCROLL;
+ cur->o_which = pick_one(s_magic, MAXSCROLLS);
+ cur->o_weight = things[TYP_SCROLL].mi_wght;
+ if (cursechance < s_magic[cur->o_which].mi_curse)
+ cur->o_flags |= ISCURSED;
+ else if (blesschance < s_magic[cur->o_which].mi_bless)
+ cur->o_flags |= ISBLESSED;
+ 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;
+ if (rnd(100) > 10)
+ cur->o_which = 0;
+ else
+ cur->o_which = 1;
+ 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 ((k = rnd(100)) < 20)
+ {
+ cur->o_flags |= ISCURSED;
+ cur->o_ac += rnd(3)+1;
+ }
+ else if (k < 35)
+ cur->o_ac -= rnd(3)+1;
+ when TYP_RING:
+ cur->o_type = RING;
+ cur->o_which = pick_one(r_magic, MAXRINGS);
+ cur->o_weight = things[TYP_RING].mi_wght;
+ if (cursechance < r_magic[cur->o_which].mi_curse)
+ cur->o_flags |= ISCURSED;
+ else if (blesschance < r_magic[cur->o_which].mi_bless)
+ cur->o_flags |= ISBLESSED;
+ switch (cur->o_which)
+ {
+ case R_ADDSTR:
+ case R_ADDWISDOM:
+ case R_ADDINTEL:
+ case R_PROTECT:
+ case R_ADDHIT:
+ case R_ADDDAM:
+ 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;
+ cur->o_which = pick_one(ws_magic, MAXSTICKS);
+ fix_stick(cur);
+ if (cursechance < ws_magic[cur->o_which].mi_curse)
+ cur->o_flags |= ISCURSED;
+ else if (blesschance < ws_magic[cur->o_which].mi_bless)
+ cur->o_flags |= ISBLESSED;
+ when TYP_MM:
+ cur->o_type = MM;
+ cur->o_which = pick_one(m_magic, MAXMM);
+ 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(7)) {
+ 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 MM_OPEN:
+ case 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:
+ cur->o_ac = rnd(4); /* set it to some character class */
+ otherwise:
+ cur->o_ac = 0;
+ }
+ otherwise:
+ debug("Picked a bad kind of object");
+ wait_for(msg,' ');
+ }
+ 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;
+ strcpy(obj->o_damage,"0d0");
+ strcpy(obj->o_hurldmg,"0d0");
+ obj->o_hplus = 0;
+ obj->o_dplus = 0;
+ obj->o_flags = 0;
+ obj->o_mark[0] = '\0';
+ obj->o_text = NULL;
+ obj->o_launch = 0;
+ obj->o_weight = 0;
+
+ /* 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;
+
+ }
+ 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)
+ {
+ sprintf(outstring,"bad pick_one: %d from %d items", i, nitems);
+ msg(outstring);
+ for (magic = start; magic < end; magic++){
+ sprintf(outstring,"%s: %d%%", magic->mi_name, magic->mi_prob);
+ msg(outstring);
+ }
+ }
+ 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("");
+}
+
+/*
+ * 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 0ef99244acb8 -r 0ed67132cf10 arogue5/trader.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/trader.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,336 @@
+/*
+ * Anything to do with trading posts
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+ * All rights reserved.
+ *
+ * Based on "Super-Rogue"
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#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()
+{
+ coord tp;
+ reg int i;
+ 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 */
+ i = roll(4,10); /* 10 to 40 items */
+ for (; i > 0 ; i--) { /* place all the items */
+ ll = new_thing(ALL); /* 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);
+ }
+ trader = 0;
+ wmove(cw,12,0);
+ 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) {
+ 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)
+ 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;
+ worth *= 3; /* slightly expensive */
+ str = inv_name(obj, TRUE);
+ sprintf(outstring,"%s for only %d pieces of gold", str, worth);
+ msg(outstring);
+ 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)) == 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;
+ sprintf(outstring,"Your %s is worth %d pieces of gold.",typ_name(obj),wo);
+ msg(outstring);
+ 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 (!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 0ef99244acb8 -r 0ed67132cf10 arogue5/util.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/util.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,921 @@
+/*
+ * all sorts of miscellaneous routines
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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
+
+/*
+ * aggravate:
+ * aggravate all the monsters on this level
+ */
+
+aggravate()
+{
+ register struct linked_list *mi;
+
+ for (mi = mlist; mi != NULL; mi = next(mi))
+ runto(THINGPTR(mi), &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 the beginning experience levels for all players.
+ * All further experience levels are computed by muliplying by 2
+ * up through MAXDOUBLE.
+ */
+#define MAXDOUBLE 14 /* Maximum number of times score is doubled */
+static struct {
+ long base; /* What it starts out at for doubling */
+ long cap; /* The maximum before doubling stops */
+} e_levels[4] = {
+ /* You must change MAXDOUBLE if you change the cap figure */
+ { 90L, 1474560L }, /* Fighter */
+ { 130L, 2129920L }, /* Magician */
+ { 110L, 1802240L }, /* cleric */
+ { 75L, 1228800L } /* Thief */
+};
+
+long
+check_level(get_spells)
+bool get_spells;
+{
+ register int i, j, add = 0;
+ register unsigned long exp;
+ long retval; /* Return value */
+ int nsides = 0;
+
+ /* See if we are past the doubling stage */
+ exp = e_levels[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 = e_levels[player.t_ctype].base;
+ while (exp <= pstats.s_exp) {
+ i++;
+ exp <<= 1;
+ }
+ retval = exp;
+ }
+ if (++i > pstats.s_lvl) {
+ switch (player.t_ctype) {
+ case C_FIGHTER: nsides = 10;
+ when C_MAGICIAN: nsides = 4;
+ when C_CLERIC: nsides = 8;
+ when C_THIEF: nsides = 6;
+ }
+
+ /* Take care of multi-level jumps */
+ for (j=0; j < (i-pstats.s_lvl); j++)
+ 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;
+ sprintf(outstring,"Welcome, %s, to level %d",
+ cnames[player.t_ctype][min(i-1, 10)], i);
+ msg(outstring);
+ if (get_spells) {
+ pray_time = 0; /* A new round of prayers */
+ spell_power = 0; /* A new round of spells */
+ }
+ }
+ pstats.s_lvl = i;
+ return(retval);
+}
+
+/*
+ * Used to modify the playes 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);
+}
+
+/*
+ * this routine computes the players current AC without dex bonus's
+ */
+int
+ac_compute()
+{
+ register int ac;
+
+ ac = cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm;
+ 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);
+}
+
+/*
+ * 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);
+}
+
+/*
+ * 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);
+}
+
+/*
+ * eat:
+ * He wants to eat something, so let him try
+ */
+
+eat()
+{
+ register struct linked_list *item;
+
+ if ((item = get_item(pack, "eat", FOOD)) == NULL)
+ return;
+ if ((OBJPTR(item))->o_which == 1)
+ msg("My, that was a yummy %s", fruit);
+ else {
+ if (rnd(100) > 70) {
+ msg("Yuk, this food tastes awful");
+
+ /* Do a check for overflow before increasing experience */
+ if (pstats.s_exp + 1L > pstats.s_exp) pstats.s_exp++;
+ check_level(TRUE);
+ }
+ else
+ msg("Yum, that tasted good");
+ }
+ if ((food_left += HUNGERTIME + rnd(400) - 200) > STOMACHSIZE)
+ food_left = STOMACHSIZE;
+ del_pack(item);
+ hungry_state = F_OKAY;
+ updpack(TRUE);
+}
+
+/*
+ * 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 );
+}
+
+
+/*
+ * find_mons:
+ * Find the monster from his corrdinates
+ */
+
+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;
+}
+
+
+/*
+ * set up the direction co_ordinate for use in varios "prefix" commands
+ */
+get_dir()
+{
+ register char *prompt;
+ register bool gotit;
+
+ prompt = terse ? "Direction?" : "Which direction? ";
+ msg(prompt);
+ do
+ {
+ gotit = TRUE;
+ switch (readchar())
+ {
+ case 'h': case'H': delta.y = 0; delta.x = -1;
+ when 'j': case'J': delta.y = 1; delta.x = 0;
+ when 'k': case'K': delta.y = -1; delta.x = 0;
+ when 'l': case'L': delta.y = 0; delta.x = 1;
+ when 'y': case'Y': delta.y = -1; delta.x = -1;
+ when 'u': case'U': delta.y = -1; delta.x = 1;
+ when 'b': case'B': delta.y = 1; delta.x = -1;
+ when 'n': case'N': delta.y = 1; delta.x = 1;
+ when ESCAPE: return FALSE;
+ otherwise:
+ mpos = 0;
+ msg(prompt);
+ gotit = FALSE;
+ }
+ } until (gotit);
+ if ((on(player, ISHUH) || on(player, ISDANCE)) && rnd(100) > 20) {
+ do
+ {
+ delta = grid[rnd(9)];
+ } while (delta.y == 0 && delta.x == 0);
+ }
+ 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 HRUGGEK_MSTAR:
+ case YEENOGHU_FLAIL:
+ 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++) {
+ char savech; /* Saves character in monster window */
+
+ 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 (do_blank && (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);
+ break;
+ when FLOOR:
+ case FOREST:
+ default:
+ mvwaddch(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);
+ 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;
+ }
+}
+
+/*
+ * raise_level:
+ * The guy just magically went up a level.
+ */
+
+raise_level(get_spells)
+bool get_spells;
+{
+ unsigned long test; /* Next level -- be sure it is not an overflow */
+
+ test = check_level(FALSE); /* 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(get_spells);
+}
+
+/*
+ * saving throw matrix for character saving throws
+ * this table is indexed by char type and saving throw type
+ */
+static int st_matrix[5][5] = {
+/* Poison, Petrify, wand, Breath, Magic */
+{ 14, 15, 16, 16, 17 },
+{ 14, 13, 11, 15, 12 },
+{ 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;
+
+ level = who->t_stats.s_lvl;
+ need = st_matrix[who->t_ctype][which];
+ switch (who->t_ctype) {
+ case C_FIGHTER:
+ need -= (level-1) / 2;
+ when C_MAGICIAN:
+ need -= 2 * (level-1) / 5;
+ when C_CLERIC:
+ need -= (level-1) / 3;
+ when C_THIEF:
+ need -= 2 * (level-1) / 4;
+ when C_MONSTER:
+ need -= level / 2;
+ }
+ /*
+ * 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;
+ /*
+ * does the player have a ring of protection on?
+ */
+ if (who == &player)
+ need -= (min(ring_value(R_PROTECT),3)); /* no more than +3 bonus */
+ /*
+ * does the player have a cloak of protection on?
+ */
+ if (who == &player && cur_misc[WEAR_CLOAK])
+ need -= (min(cur_misc[WEAR_CLOAK]->o_ac,3)); /* no more than +3 bonus */
+ need -= adj;
+ 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');
+}
+
+/*
+ * 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);
+ s2++;
+ }
+ *s1 = '\0';
+}
+
+/*
+ * tr_name:
+ * print the name of a trap
+ */
+
+char *
+tr_name(ch)
+char ch;
+{
+ register char *s = NULL;
+
+ 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 "";
+ }
+}
+
+/*
+ * 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 0ef99244acb8 -r 0ed67132cf10 arogue5/vers.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/vers.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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.
+ */
+
+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 5.8 (Bell Labs) 1/03/85";
+char *release = "5.8.2";
diff -r 0ef99244acb8 -r 0ed67132cf10 arogue5/weapons.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/weapons.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,310 @@
+/*
+ * Functions for dealing with problems brought about by weapons
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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"
+
+
+
+/*
+ * do the actual motion on the screen done by an object traveling
+ * across the room
+ */
+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;
+ }
+ 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;
+ coord *fpos = NULL;
+
+ 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) {
+ 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) {
+ if (obj->o_type == WEAPON) /* BUGFIX: Identification trick */
+ msg("The %s vanishes as it hits the ground.",
+ weaps[obj->o_which].w_name);
+ else
+ msg("%s vanishes as it hits the ground.", inv_name(obj,TRUE));
+ }
+ 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);
+ }
+ return(fight(&mp, obj, TRUE));
+ } else {
+ if (!ce(mp, hero)) {
+ return(FALSE);
+ }
+ 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];
+ strcpy(weap->o_damage,iwp->w_dam);
+ strcpy(weap->o_hurldmg,iwp->w_hrl);
+ weap->o_launch = iwp->w_launch;
+ weap->o_flags = iwp->w_flags;
+ weap->o_weight = iwp->w_wght;
+ if (weap->o_flags & ISMANY) {
+ weap->o_count = rnd(8) + 8;
+ weap->o_group = 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 0 /* Do we really want to make this check */
+ if (is_current(obj)) { /* Are we holding it? */
+ msg(terse ? "Holding it." : "You are already holding it.");
+ return;
+ }
+#endif
+
+ if (!dropcheck(obj)) return; /* Can we get rid of it? */
+
+ if(!(obj->o_flags & ISMISL)) {
+ for(;;) {
+ 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);
+ 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;
+
+ if ((oweapon = cur_weapon) != NULL) {
+ if (!dropcheck(cur_weapon)) {
+ cur_weapon = oweapon;
+ return;
+ }
+ if (terse)
+ addmsg("Was ");
+ else
+ addmsg("You were ");
+ msg("wielding %s", inv_name(oweapon, TRUE));
+ }
+ if ((item = get_item(pack, "wield", WIELDABLE)) == NULL) {
+ after = FALSE;
+ return;
+ }
+ obj = OBJPTR(item);
+ if (is_current(obj)) {
+ msg("Item in use.");
+ after = FALSE;
+ return;
+ }
+ if (player.t_ctype != C_FIGHTER &&
+ obj->o_type == WEAPON &&
+ (obj->o_which == TWOSWORD || obj->o_which == BASWORD)) {
+ msg("Only fighters 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 0ef99244acb8 -r 0ed67132cf10 arogue5/wear.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/wear.c Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,259 @@
+/*
+ * This file contains misc functions for dealing with armor
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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"
+
+
+/*
+ * take_off:
+ * Get the armor off of the players back
+ */
+
+take_off()
+{
+ register struct object *obj;
+ register struct linked_list *item;
+
+ /* What does player want to take off? */
+ if ((item = get_item(pack, "take off", REMOVABLE)) == NULL)
+ return;
+
+ obj = OBJPTR(item);
+ if (!is_current(obj)) {
+ sprintf(outstring,"Not wearing %c) %s", pack_char(pack, obj),inv_name(obj, TRUE));
+ msg(outstring);
+ return;
+ }
+
+ /* Can the player remove the item? */
+ if (!dropcheck(obj)) return;
+ updpack(TRUE);
+
+ sprintf(outstring,"Was wearing %c) %s", pack_char(pack, obj),inv_name(obj,TRUE));
+ msg(outstring);
+}
+
+/*
+ * 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;
+ char buf[LINELEN];
+
+
+ /* What does player want to wear? */
+ if ((item = get_item(pack, "wear", WEARABLE)) == 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 (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;
+ }
+ waste_time();
+ 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:
+ if (cur_misc[WEAR_BOOTS] != NULL)
+ msg("already wearing a pair of boots");
+ else {
+ 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:
+ if (cur_misc[WEAR_BOOTS] != NULL)
+ msg("already wearing a pair of boots");
+ else {
+ 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:
+ if (cur_misc[WEAR_BRACERS] != NULL)
+ msg("already wearing bracers");
+ else {
+ if (cur_armor != NULL) {
+ msg("You can't wear bracers of defense with armor.");
+ }
+ else {
+ 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:
+ if (cur_misc[WEAR_CLOAK] != NULL || cur_relic[EMORI_CLOAK])
+ msg("%slready wearing a cloak.", terse ? "A"
+ : "You are a");
+ else {
+ if (cur_armor != NULL) {
+ msg("You can't wear a cloak with armor.");
+ }
+ else {
+ 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:
+ if (cur_misc[WEAR_GAUNTLET] != NULL)
+ msg("Already wearing a pair of gauntlets.");
+ else {
+ 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:
+ if (cur_misc[WEAR_JEWEL] != NULL || cur_relic[YENDOR_AMULET])
+ msg("Already wearing an amulet.");
+ else {
+ msg("wearing %s",inv_name(obj,TRUE));
+ cur_misc[WEAR_JEWEL] = obj;
+ aggravate();
+ }
+ /*
+ * 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");
+ else {
+ 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:
+ if (cur_misc[WEAR_NECKLACE] != NULL)
+ msg("already wearing a necklace");
+ else {
+ 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) {
+ msg(terse ? "Call it: " : "What do you want to call it? ");
+ if (get_str(buf, cw) == NORM) {
+ m_guess[obj->o_which] = new((unsigned int) strlen(buf) + 1);
+ strcpy(m_guess[obj->o_which], buf);
+ }
+ }
+
+ when RING:
+ if (cur_misc[WEAR_GAUNTLET] != NULL) {
+ msg ("You have to remove your gauntlets first!");
+ return;
+ }
+
+ /* If there is room, put on the ring */
+ for (i=0; i
+#include "rogue.h"
+
+
+/*
+ * 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 = 0, 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') {
+ makemonster(TRUE); /* make monster and be done with it */
+ 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;
+ if (thiswin == hw)
+ restscr(cw);
+ mpos = 0;
+ 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 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(9)) {
+ 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 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(4);
+ 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;
+ p_know[wh] = TRUE;
+ when RELIC:
+ obj->o_weight = things[TYP_RELIC].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 = readchar();
+ 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);
+}
+
+/*
+ * make a monster for the wizard
+ */
+makemonster(create)
+bool create;
+{
+ register int i;
+ register short which_monst;
+ register int num_monst = NUMMONST, pres_monst=1, num_lines=2*(LINES-3);
+ char monst_name[40];
+
+ /* 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(hw,' ');
+ }
+
+ else {
+ mvwaddstr(hw, 0, 0, "Which monster");
+ if (!terse && create) waddstr(hw, " do you wish to create");
+ waddstr(hw, "? ");
+ draw(hw);
+ }
+ }
+
+get_monst:
+ get_str(monst_name, hw);
+ which_monst = atoi(monst_name);
+ if ((which_monst < 1 || which_monst > NUMMONST)) {
+ mvwaddstr(hw, 0, 0, "Please enter a number in the displayed range -- ");
+ draw(hw);
+ goto get_monst;
+ }
+ restscr(cw);
+ if (create) {
+ creat_mons (&player, which_monst, TRUE);
+ light(&hero);
+ }
+ touchwin(cw);
+ return(which_monst);
+}
+
+/*
+ * passwd:
+ * see if user knows password
+ */
+
+passwd()
+{
+ register char *sp, c;
+ char buf[LINELEN];
+
+ 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, "Si")) == 0);
+}
+
+
+/*
+ * teleport:
+ * Bamf the hero someplace else
+ */
+
+teleport()
+{
+ register struct room *new_rp, *old_rp = roomin(&hero);
+ register int rm;
+ coord c;
+
+ c = hero;
+ mvwaddch(cw, hero.y, hero.x, mvwinch(stdscr, hero.y, hero.x));
+ do
+ {
+ rm = rnd_room();
+ rnd_pos(&rooms[rm], &hero);
+ } until(winat(hero.y, hero.x) == FLOOR);
+ player.t_oldpos = c; /* Save last position */
+
+ /* If hero gets moved, darken old room */
+ new_rp = &rooms[rm];
+ if (old_rp && old_rp != new_rp) {
+ old_rp->r_flags |= FORCEDARK; /* Fake darkness */
+ light(&c);
+ old_rp->r_flags &= ~FORCEDARK; /* Restore light state */
+ }
+
+ /* Darken where we just came from */
+ else if (levtype == MAZELEV) light(&c);
+
+ light(&hero);
+ mvwaddch(cw, hero.y, hero.x, PLAYER);
+
+ /* Reset current room and position */
+ oldrp = new_rp; /* Used in look() */
+ player.t_oldpos = hero;
+
+ /*
+ * 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)) == 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 0ef99244acb8 -r 0ed67132cf10 arogue5/xcrypt.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/xcrypt.c Thu Aug 09 22:58:48 2012 +0000
@@ -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 DEBUG
+# 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);
+}