Import Advanced Rogue 5.8 from the Roguelike Restoration Project (r1490)

This commit is contained in:
John "Elwin" Edwards 2012-08-09 22:58:48 +00:00
parent 9ed6e5e369
commit 14fad3b319
47 changed files with 29836 additions and 0 deletions

178
arogue5/LICENSE.TXT Normal file
View file

@ -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.

203
arogue5/Makefile Normal file
View file

@ -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

1025
arogue5/arogue58.doc Normal file

File diff suppressed because it is too large Load diff

953
arogue5/arogue58.html Normal file
View file

@ -0,0 +1,953 @@
<!-- Advanced Rogue -->
<!-- Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T -->
<!-- All rights reserved. -->
<!-- -->
<!-- Based on "Rogue: Exploring the Dungeons of Doom" -->
<!-- Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman -->
<!-- All rights reserved. -->
<!-- -->
<!-- See the file LICENSE.TXT for full copyright and licensing information. -->
<!-- Creator : groff version 1.18.1 -->
<!-- CreationDate: Sat Jan 21 09:55:23 2006 -->
<h1 align="center"><a href="http://roguelike.sourceforge.net/arogue77">The Dungeons of
Doom</a></h1>
<br>
<h2 align="center">AT&amp;T Bell Laboratories</h2>
<h3 align="center"><A href="http://roguelike.sourceforge.net/arogue58">http://roguelike.sourceforge.net/arogue58</A></h3>
<br>
<table border="0" cellpadding="3" cellspacing="3" style="BORDER-COLLAPSE: collapse" id="table1" align="center">
<tr>
<td nowrap>
Advanced Rogue<br>
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&amp;T<br>
All rights reserved.
</td>
</tr>
<tr>
<td nowrap>
Based on "Rogue: Exploring the Dungeons of Doom"<br>
Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman<br>
All rights reserved.
</td>
</tr>
</table>
<p align="center">See the file LICENSE.TXT for full copyright and licensing
information.</p>
<p align="center">&nbsp;</p>
<p align="center"><b>ABSTRACT</b></p>
<blockquote>
<blockquote>
<p align="justify">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.</p>
<p align="justify">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.</p>
</blockquote>
</blockquote>
<h2 align="justify">&nbsp;</h2>
<h3 align="justify">1. INTRODUCTION</h3>
<p align="justify">
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.</p>
<p align="justify">
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.</p>
<p align="justify">
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.</p>
<h3 align="justify">2. CHARACTER CLASSES AND ATTRIBUTES</h3>
<p align="justify">
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.</p>
<p align="justify"><span style="FONT-VARIANT: small-caps"><strong>2.1 The Fighter</strong></span></p>
<p align="justify">
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.</p>
<p align="justify"><span style="FONT-VARIANT: small-caps"><strong>2.2 The Magician</strong></span></p>
<p align="justify">
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.</p>
<p align="justify"><strong><span style="FONT-VARIANT: small-caps">2.3 The Cleric</span></strong></p>
<p align="justify">
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.</p>
<p align="justify">
Because of their religious nature, clerics can also affect the &quot;undead&quot;
beings, like zombies and ghouls, which became monsters after they died. If
an &quot;undead&quot; creature is next to a cleric, the cleric may try to turn it and
cause it to flee. If the cleric is sufficiently powerful relative to the
monster, the cleric will destroy it. This ability increases as the character
gains experience levels.</p>
<p align="justify">
Clerics can gain from 1 to 8 extra hit points on reaching a new experience
level.</p>
<p align="justify"><strong><span style="FONT-VARIANT: small-caps">2.4 The Thief</span></strong></p>
<p align="justify">
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.
</p>
<p align="justify">
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.</p>
<p align="justify">
Thieves gain from 1 to 6 extra hit points from a new experience level.
</p>
<p align="justify"><strong><span style="FONT-VARIANT: small-caps">2.5
CONSTITUTION</span></strong></p>
<p align="justify">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.</p>
<p align="justify"><strong><span style="FONT-VARIANT: small-caps">2.6 Experience Levels</span></strong></p>
<p align="justify">
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.</p>
<p align="justify">
Thieves have the lowest threshold for gaining experience levels, followed by
clerics. Fighters are next, and magicians have the highest threshold.</p>
<h3 align="justify">
3. THE SCREEN</h3>
<p align="justify">
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.</p>
<p align="justify"><strong><span style="FONT-VARIANT: small-caps">3.1 The Top Line</span></strong>
<p align="justify">
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.</p>
<p align="justify">
<strong>
<span style="FONT-VARIANT: small-caps">3.2 The Dungeon Section</span></strong>
<p align="justify">
The large middle section of the screen displays the player's surroundings using
the following symbols:
</p>
<p>
<table border="0" cellpadding="3" style="BORDER-COLLAPSE: collapse" id="table3" cellspacing="3">
<tr>
<td align="middle">|</td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;
</td>
<td>A wall of a room.</td>
</tr>
<tr>
<td align="middle">-</td>
<td>&nbsp;</td>
<td>A wall of a room.</td>
</tr>
<tr>
<td align="middle">*</td>
<td>&nbsp;</td>
<td>A pile of gold.</td>
</tr>
<tr>
<td align="middle">%</td>
<td>&nbsp;</td>
<td>A way to the next level.</td>
</tr>
<tr>
<td align="middle">+</td>
<td>&nbsp;</td>
<td>A doorway.</td>
</tr>
<tr>
<td align="middle">.</td>
<td>&nbsp;</td>
<td>The floor in a room.</td>
</tr>
<tr>
<td align="middle">@</td>
<td>&nbsp;</td>
<td>The player.</td>
</tr>
<tr>
<td align="middle">_</td>
<td>&nbsp;</td>
<td>The player, when invisible.</td>
</tr>
<tr>
<td align="middle">#</td>
<td>&nbsp;</td>
<td>The floor in a passageway.</td>
</tr>
<tr>
<td align="middle">!</td>
<td>&nbsp;</td>
<td>A flask containing a potion.</td>
</tr>
<tr>
<td align="middle">?</td>
<td>&nbsp;</td>
<td>A sealed scroll.</td>
</tr>
<tr>
<td align="middle">:</td>
<td>&nbsp;</td>
<td>Some food.</td>
</tr>
<tr>
<td align="middle">)</td>
<td>&nbsp;</td>
<td>A weapon.</td>
</tr>
<tr>
<td align="middle">&nbsp;</td>
<td nowrap>&nbsp;</td>
<td nowrap>Solid rock (denoted by a space).</td>
</tr>
<tr>
<td align="middle">]</td>
<td>&nbsp;</td>
<td>Some armor.</td>
</tr>
<tr>
<td align="middle">;</td>
<td>&nbsp;</td>
<td>A miscellaneous magic item.</td>
</tr>
<tr>
<td align="middle">,</td>
<td>&nbsp;</td>
<td>An artifact.</td>
</tr>
<tr>
<td align="middle">=</td>
<td>&nbsp;</td>
<td>A ring.</td>
</tr>
<tr>
<td align="middle">/</td>
<td>&nbsp;</td>
<td>A wand or a staff.</td>
</tr>
<tr>
<td align="middle">^</td>
<td>&nbsp;</td>
<td>The entrance to a trading post.</td>
</tr>
<tr>
<td align="middle">&gt;</td>
<td>&nbsp;</td>
<td>A trapdoor leading to the next level</td>
</tr>
<tr>
<td align="middle">{</td>
<td>&nbsp;</td>
<td>An arrow trap</td>
</tr>
<tr>
<td align="middle">$</td>
<td>&nbsp;</td>
<td>A sleeping gas trap</td>
</tr>
<tr>
<td align="middle">}</td>
<td>&nbsp;</td>
<td>A beartrap</td>
</tr>
<tr>
<td align="middle">~</td>
<td>&nbsp;</td>
<td>A trap that teleports you somewhere else</td>
</tr>
<tr>
<td align="middle">`</td>
<td>&nbsp;</td>
<td>A poison dart trap</td>
</tr>
<tr>
<td align="middle">"</td>
<td>&nbsp;</td>
<td>a shimmering magic pool</td>
</tr>
<tr>
<td align="middle">'</td>
<td>&nbsp;</td>
<td>An entrance to a maze</td>
</tr>
<tr>
<td align="middle">$</td>
<td>&nbsp;</td>
<td>Any magical item. (During magic detection)</td>
</tr>
<tr>
<td align="middle">&gt;</td>
<td nowrap>&nbsp;</td>
<td nowrap>A blessed magical item. (During magic detection)</td>
</tr>
<tr>
<td align="middle">&lt;</td>
<td>&nbsp;</td>
<td>A cursed magical item. (During magic detection)</td>
</tr>
<tr>
<td align="middle">A letter</td>
<td>&nbsp;</td>
<td>A monster. Note that a given letter may signify<br>
multiple monsters, depending on the level of the<br>
dungeon. The player can always identify a current<br>
monster by using the identify command ('/').</td>
</tr>
</table>
</p>
<p align="justify"><strong><span style="FONT-VARIANT: small-caps">3.3 The Status Section</span></strong></p>
<p align="justify">
The bottom two lines of the screen describe the player's current status. The
first line gives the player's characteristics:
</p>
<ul>
<li>
<p align="justify">Intelligence (Int)</p>
<li>
<p align="justify">Strength (Str)</p>
<li>
<p align="justify">Wisdom (Wis)</p>
<li>
<p align="justify">Dexterity (Dxt)</p>
<li>
<p align="justify">Constitution (Const)</p>
<li>
<p align="justify">Charisma (Char)</p>
<li>
<p align="justify">Encumbrance (Carry)</p>
</li>
</ul>
<p align="justify">
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.</p>
<p align="justify">
The second status line provides the following information:
</p>
<ul>
<li>
<p align="justify">The current level (Lvl) in the dungeon. This number
increases as the player goes further down.</p>
<li>
<p align="justify">How much gold (Au) the player is carrying.</p>
<li>
<p align="justify">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.</p>
<li>
<p align="justify">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.</p>
<li>
<p align="justify">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.</p>
<li>
<p align="justify">A description of the player's character. This description
depends on the player's character type and experience level.</p>
</li>
</ul>
<h3 align="justify">4. COMMANDS</h3>
<p align="justify">
A player can invoke most Rogue commands by typing a single character. Some
commands, however, require a direction, in which case the player types the
command character followed by a directional command. Many commands can be
prefaced by a number, indicating how many times the command should be
executed.</p>
<p align="justify">
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.</p>
<p align="center"><b><i>Rogue understands the following commands:</i></b></p>
<p>
<table border="0" cellpadding="3" style="BORDER-COLLAPSE: collapse" id="table4" cellspacing="3">
<tr>
<td align="middle" valign="top">?</td>
<td>&nbsp;&nbsp;&nbsp;</td>
<td>Preceding a command by a '?' produces a brief explanation of the command. The
command '?*' gives an explanation of all the commands.</td>
</tr>
<tr>
<td align="middle" valign="top">/</td>
<td>&nbsp;</td>
<td>Preceding a symbol by a '/' identifies the symbol.</td>
</tr>
<tr>
<td align="middle" valign="top">h</td>
<td>&nbsp;</td>
<td>Move one position to the left.</td>
</tr>
<tr>
<td align="middle" valign="top">j</td>
<td>&nbsp;</td>
<td>Move one position down.</td>
</tr>
<tr>
<td align="middle" valign="top">k</td>
<td>&nbsp;</td>
<td>Move one position up.</td>
</tr>
<tr>
<td align="middle" valign="top">l</td>
<td>&nbsp;</td>
<td>Move one position to the right.</td>
</tr>
<tr>
<td align="middle" valign="top">y</td>
<td height="21">&nbsp;</td>
<td height="21">Move one position to the top left.</td>
</tr>
<tr>
<td align="middle" valign="top">u</td>
<td>&nbsp;</td>
<td>Move one position to the top right.</td>
</tr>
<tr>
<td align="middle" valign="top">b</td>
<td>&nbsp;</td>
<td>Move one position to the bottom left.</td>
</tr>
<tr>
<td align="middle" valign="top">n</td>
<td>&nbsp;</td>
<td>Move one position to the bottom right</td>
</tr>
<tr>
<td align="middle" valign="top">H</td>
<td>&nbsp;</td>
<td>Run to the left until reaching something interesting.</td>
</tr>
<tr>
<td align="middle" valign="top">J</td>
<td>&nbsp;</td>
<td>Run down until reaching something interesting.</td>
</tr>
<tr>
<td align="middle" valign="top">K</td>
<td>&nbsp;</td>
<td>Run up until reaching something interesting.</td>
</tr>
<tr>
<td align="middle" valign="top">L</td>
<td>&nbsp;</td>
<td>Run to the right until reaching something interesting.</td>
</tr>
<tr>
<td align="middle" valign="top">Y</td>
<td>&nbsp;</td>
<td>Run to the top left until reaching something interesting.</td>
</tr>
<tr>
<td align="middle" valign="top">U</td>
<td>&nbsp;</td>
<td>Run to the top right until reaching something interesting.</td>
</tr>
<tr>
<td align="middle" valign="top">B</td>
<td>&nbsp;</td>
<td>Run to the bottom left until reaching something interesting.</td>
</tr>
<tr>
<td align="middle" valign="top">N</td>
<td>&nbsp;</td>
<td>Run to the bottom right until reaching something interesting</td>
</tr>
<tr>
<td align="middle" valign="top">t</td>
<td>&nbsp;</td>
<td>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.</td>
</tr>
<tr>
<td align="middle" valign="top">f</td>
<td>&nbsp;</td>
<td>When this command precedes a directional command, the player moves
in the specified direction until passing something interesting.</td>
</tr>
<tr>
<td align="middle" valign="top">z</td>
<td>&nbsp;</td>
<td>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.</td>
</tr>
<tr>
<td align="middle" valign="top">&gt;</td>
<td>&nbsp;</td>
<td>Go down to the next level.</td>
</tr>
<tr>
<td align="middle" valign="top">&lt;</td>
<td>&nbsp;</td>
<td>Go up to the next level.</td>
</tr>
<tr>
<td align="middle" valign="top">s</td>
<td>&nbsp;</td>
<td>Search for a secret door or a trap in the circle surrounding the player.</td>
</tr>
<tr>
<td align="middle" valign="top">.</td>
<td>&nbsp;</td>
<td>This command (a dot) causes the player to rest a turn.</td>
</tr>
<tr>
<td align="middle" valign="top">i</td>
<td>&nbsp;</td>
<td>Display an inventory of the player's pack.</td>
</tr>
<tr>
<td align="middle" valign="top">I</td>
<td>&nbsp;</td>
<td>This command prompts for an item from the player's pack and displays
the inventory information for that item.</td>
</tr>
<tr>
<td align="middle" valign="top">q</td>
<td>&nbsp;</td>
<td>Quaff a potion from the player's pack.</td>
</tr>
<tr>
<td align="middle" valign="top">r</td>
<td>&nbsp;</td>
<td>Read a scroll from the player's pack.</td>
</tr>
<tr>
<td align="middle" valign="top">e</td>
<td>&nbsp;</td>
<td>Eat some food from the player's pack.</td>
</tr>
<tr>
<td align="middle" valign="top">w</td>
<td>&nbsp;</td>
<td>Wield a weapon from the player's pack.</td>
</tr>
<tr>
<td align="middle" valign="top">W</td>
<td>&nbsp;</td>
<td>Wear some armor or miscellaneous magic item from the player's pack.</td>
</tr>
<tr>
<td align="middle" valign="top">T</td>
<td>&nbsp;</td>
<td>Take off whatever the player is wearing.</td>
</tr>
<tr>
<td align="middle" valign="top">P</td>
<td>&nbsp;</td>
<td>Put on a ring from the player's pack. The player can wear a maximum
of eight rings.</td>
</tr>
<tr>
<td align="middle" valign="top">R</td>
<td>&nbsp;</td>
<td>Remove a ring from the player's hand.</td>
</tr>
<tr>
<td align="middle" valign="top">^U</td>
<td>&nbsp;</td>
<td>Use a miscellaneous magic item in the player's pack.</td>
</tr>
<tr>
<td align="middle" valign="top">d</td>
<td>&nbsp;</td>
<td>Drop an item from the player's pack.</td>
</tr>
<tr>
<td align="middle" valign="top">c</td>
<td>&nbsp;</td>
<td>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.</td>
</tr>
<tr>
<td align="middle" valign="top">m</td>
<td>&nbsp;</td>
<td>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.</td>
</tr>
<tr>
<td align="middle" valign="top">o</td>
<td>&nbsp;</td>
<td>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.</td>
</tr>
<tr>
<td align="middle" valign="top">C</td>
<td>&nbsp;</td>
<td>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.</td>
</tr>
<tr>
<td align="middle" valign="top">p</td>
<td>&nbsp;</td>
<td>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
&quot;ambitious&quot; prayers.</td>
</tr>
<tr>
<td align="middle" valign="top">a</td>
<td>&nbsp;</td>
<td>This command is restricted to clerics and characters with
exceptionally high wisdom and must be followed by a directional command.
If there is an &quot;undead&quot; 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.</td>
</tr>
<tr>
<td align="middle" valign="top">^</td>
<td>&nbsp;</td>
<td>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.</td>
</tr>
<tr>
<td align="middle" valign="top">G</td>
<td>&nbsp;</td>
<td>This command is restricted to thieves. It causes Rogue to display
all the gold on the current level.</td>
</tr>
<tr>
<td align="middle" valign="top">D</td>
<td>&nbsp;</td>
<td>Dip something into a magic pool.</td>
</tr>
<tr>
<td align="middle" valign="top">^T</td>
<td height="22">&nbsp;</td>
<td height="22">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.</td>
</tr>
<tr>
<td align="middle" valign="top">^L</td>
<td>&nbsp;</td>
<td>Redraw the screen.</td>
</tr>
<tr>
<td align="middle" valign="top">^R</td>
<td>&nbsp;</td>
<td>Repeat the last message that was displayed on the top line of the screen.</td>
</tr>
<tr>
<td align="middle" valign="top">Escape (^[)</td>
<td>&nbsp;</td>
<td>Typing an escape will usually cause Rogue to cancel the current command.</td>
</tr>
<tr>
<td align="middle" valign="top">v</td>
<td>&nbsp;</td>
<td>Print the current Rogue version number.</td>
</tr>
<tr>
<td align="middle" valign="top">!</td>
<td>&nbsp;</td>
<td>Escape to the shell level.</td>
</tr>
<tr>
<td align="middle" valign="top">S</td>
<td>&nbsp;</td>
<td>Quit and save the game for resumption at a later time.</td>
</tr>
<tr>
<td align="middle" valign="top">Q</td>
<td>&nbsp;</td>
<td>Quit without saving the game.</td>
</tr>
</table>
</p>
<h3 align="justify">5. IMPLICIT COMMANDS</h3>
<p align="justify">
There is no &quot;attack&quot; command. If a player wishes to attack a monster, the
player simply tries to move onto the spot where the monster is standing. The
game then assumes that the player wishes to attack the monster with whatever
weapon the player is wielding.</p>
<p align="justify">
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.</p>
<h3 align="justify">6. LIGHT</h3>
<p align="justify">
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.</p>
<h3 align="justify">7. WEAPONS AND ARMOR</h3>
<p align="justify">
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 &quot;throw&quot; the bolt or arrow at the
monster.</p>
<p align="justify">
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 &quot;to hit&quot; and &quot;to damage&quot;
bonuses appear in that order before the weapon's name in an inventory
listing. A positive bonus indicates a blessed weapon, and a negative bonus
usually indicates a cursed weapon. The player cannot release a cursed
weapon.</p>
<p align="justify">
Without any armor the player has an armor class of 10. The lower the
player's armor class, the harder it is for a monster to hit the player, so
wearing armor can improve the player's armor class. A cursed suit of armor,
however, offers poor protection and may sometimes be worse than no armor at
all.</p>
<p align="justify">
After the player has identified a suit of armor, the protection bonus
appears before the armor's name in an inventory listing. If the bonus is
positive the armor is blessed, and if it is negative, the armor is usually
cursed. The player cannot remove a cursed suit of armor.</p>
<p align="justify">
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.</p>
<h3 align="justify">8. POTIONS AND SCROLLS</h3>
<p align="justify">
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.</p>
<h3 align="justify">9. RINGS</h3>
<p align="justify">
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.</p>
<h3 align="justify">10. WANDS AND STAVES</h3>
<p align="justify">
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.</p>
<h3 align="justify">11. FOOD</h3>
<p>The player must be careful not to run out of food since moving through the
dungeon fighting monsters consumes a lot of energy. Starving results in the
player's fainting for increasingly longer periods of time, during which any
nearby monster can attack the player freely. </p>
<h3 align="justify">12. GOLD</h3>
<p>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
&quot;between levels&quot; of the dungeon and can be entered by stepping on the entrance.
A quartermaster is a person who will sometimes appear and will try to sell the
player some of his wares. These wares are never cursed and frequently blessed,
though blessed goods cost more than normal goods. If the player chooses to buy
one of the quartermaster's items, the quartermaster trades the item for the
specified amount of gold and disappears. Attacking a quartermaster causes him to
vanish without offering a trade. </p>
<h3 align="justify">13. MISCELLANEOUS MAGIC ITEMS</h3>
<p align="justify">
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.</p>
<h3 align="justify">14. ARTIFACTS</h3>
<p align="justify">
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.</p>
<h3 align="justify">15. TRAPS</h3>
<p align="justify">
&nbsp;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.</p>
<h3 align="justify">16. THE MONSTERS</h3>
<p align="justify">
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.</p>
<p align="justify">
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.</p>
<p align="justify">
Some monsters are more intelligent than others, and the more intelligent a
monster, the more likely that the monster will run away if it is about to
die. A fleeing monster will not attack the player unless cornered.</p>
<p align="justify">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 &quot;unique monster&quot; is killed,
the player will not find another in the current dungeon.</p>
<h3 align="justify">17. OPTIONS</h3>
<p align="justify">
Rogue has several options which may be set by the player:
</p>
<p>
<table border="0" cellpadding="3" style="BORDER-COLLAPSE: collapse" id="table5" cellspacing="3">
<tr>
<td valign="top">terse</td>
<td>&nbsp;&nbsp;</td>
<td>Setting this Boolean option results in shorter messages appearing on
the top line of the screen.</td>
</tr>
<tr>
<td valign="top">jump</td>
<td>&nbsp;</td>
<td>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.</td>
</tr>
<tr>
<td valign="top">step</td>
<td>&nbsp;</td>
<td>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.</td>
</tr>
<tr>
<td valign="top">flush</td>
<td>&nbsp;</td>
<td>Setting this Boolean option results in flushing all type ahead
(pending) commands when the player encounters a monster.</td>
</tr>
<tr>
<td valign="top">askme</td>
<td nowrap>&nbsp;</td>
<td>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.</td>
</tr>
<tr>
<td valign="top">name</td>
<td>&nbsp;</td>
<td>This string is the player's name and defaults to the player's
account name.</td>
</tr>
<tr>
<td valign="top">fruit</td>
<td>&nbsp;</td>
<td>This string identifies the player's favorite fruit, sometimes
encountered in the dungeon. It defaults to slime-mold.</td>
</tr>
<tr>
<td valign="top">file</td>
<td>&nbsp;</td>
<td>This string, which defaults to rogue.save, specifies the file to use
for saving the game.</td>
</tr>
<tr>
<td valign="top">score</td>
<td>&nbsp;</td>
<td>This string identifies the top-ten score file to use for the game.</td>
</tr>
<tr>
<td valign="top">class</td>
<td>&nbsp;</td>
<td>This option specifies the character class of the rogue. It can be
set only in the ROGUEOPTS environment variable.</td>
</tr>
</table>
</p>
<p align="justify">
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 &quot;no&quot; clears it. The syntax &quot;stringoption=name&quot; sets a
string option to &quot;name.&quot; So setting ROGUEOPTS to &quot;terse, jump, nostep,
flush, askme, name=Ivan the Terrible, fruit=pomegranate&quot; would set the
terse, jump, flush, and askme Boolean options, clear the step Boolean
option, set the player's name to &quot;Ivan the Terrible,&quot; set the player's
favorite fruit to a pomegranate, and use the defaults for the save file and
the score file.</p>
<p align="justify">
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.</p>
<h3 align="justify">18. SCORING</h3>
<p>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.</p>
<h3 align="justify">19. ACKNOWLEDGEMENTS</h3>
<p align="justify">
This version of Rogue is based on a version developed at the University of
California at Berkeley by Michael Toy and Ken Arnold.</p>

24
arogue5/arogue58.sln Normal file
View file

@ -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

305
arogue5/arogue58.vcproj Normal file
View file

@ -0,0 +1,305 @@
<?xml version="1.0" encoding = "Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.00"
Name="arogue58"
ProjectGUID="{2EEE53AB-A85A-4D4D-8DB2-B5F23513F415}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/I.. /wd4033 /wd4716"
Optimization="0"
OptimizeForWindowsApplication="TRUE"
AdditionalIncludeDirectories="../pdcurses"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
MinimalRebuild="FALSE"
ExceptionHandling="FALSE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
BufferSecurityCheck="TRUE"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"
CompileAs="1"
DisableSpecificWarnings="4013;4033;4716"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalOptions="pdcurses.lib Ws2_32.lib"
AdditionalDependencies="shfolder.lib pdcurses.lib"
OutputFile="$(OutDir)/arogue58.exe"
LinkIncremental="0"
AdditionalLibraryDirectories="..\pdcurses"
IgnoreDefaultLibraryNames="LIBC.LIB"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/arogue58.pdb"
SubSystem="1"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
OmitFramePointers="TRUE"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
StringPooling="TRUE"
RuntimeLibrary="4"
EnableFunctionLevelLinking="TRUE"
UsePrecompiledHeader="3"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/arogue58.exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
</Configuration>
<Configuration
Name="test|Win32"
OutputDirectory="test"
IntermediateDirectory="test"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/arogue58.exe"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/arogue58.pdb"
SubSystem="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
</Configuration>
</Configurations>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
<File
RelativePath="chase.c">
</File>
<File
RelativePath="command.c">
</File>
<File
RelativePath="daemon.c">
</File>
<File
RelativePath="daemons.c">
</File>
<File
RelativePath="encumb.c">
</File>
<File
RelativePath="fight.c">
</File>
<File
RelativePath="init.c">
</File>
<File
RelativePath="io.c">
</File>
<File
RelativePath="list.c">
</File>
<File
RelativePath="main.c">
</File>
<File
RelativePath="maze.c">
</File>
<File
RelativePath="mdport.c">
</File>
<File
RelativePath="misc.c">
</File>
<File
RelativePath="monsters.c">
</File>
<File
RelativePath="move.c">
</File>
<File
RelativePath="new_level.c">
</File>
<File
RelativePath="options.c">
</File>
<File
RelativePath="outside.c">
</File>
<File
RelativePath="pack.c">
</File>
<File
RelativePath="passages.c">
</File>
<File
RelativePath="player.c">
</File>
<File
RelativePath="potions.c">
</File>
<File
RelativePath="rings.c">
</File>
<File
RelativePath="rip.c">
</File>
<File
RelativePath="rogue.c">
</File>
<File
RelativePath="rooms.c">
</File>
<File
RelativePath="save.c">
</File>
<File
RelativePath="scrolls.c">
</File>
<File
RelativePath="state.c">
</File>
<File
RelativePath="sticks.c">
</File>
<File
RelativePath="things.c">
</File>
<File
RelativePath="trader.c">
</File>
<File
RelativePath="util.c">
</File>
<File
RelativePath="vers.c">
</File>
<File
RelativePath="weapons.c">
</File>
<File
RelativePath="wear.c">
</File>
<File
RelativePath="wizard.c">
</File>
<File
RelativePath="xcrypt.c">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc">
<File
RelativePath="mach_dep.h">
</File>
<File
RelativePath="network.h">
</File>
<File
RelativePath="rogue.h">
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
</Filter>
<File
RelativePath="LICENSE.TXT">
</File>
<File
RelativePath="Makefile">
</File>
<File
RelativePath="arogue58.doc">
</File>
<File
RelativePath="arogue58.html">
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

1008
arogue5/chase.c Normal file

File diff suppressed because it is too large Load diff

938
arogue5/command.c Normal file
View file

@ -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 <limits.h>
#include <ctype.h>
#include <signal.h>
#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);
}
}
}

244
arogue5/daemon.c Normal file
View file

@ -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);
}

487
arogue5/daemons.c Normal file
View file

@ -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<MAXRELIC; i++) { /* each relic eats an additional food */
if (cur_relic[i])
food_use++;
}
food_use += (ring_eat(LEFT_1) + ring_eat(LEFT_2) +
ring_eat(LEFT_3) + ring_eat(LEFT_4) +
ring_eat(RIGHT_1) + ring_eat(RIGHT_2) +
ring_eat(RIGHT_3) + ring_eat(RIGHT_4) +
foodlev);
if (food_use < 1)
food_use = 1;
food_left -= food_use;
if (food_left < MORETIME && oldfood >= MORETIME) {
msg("You are starting to feel weak");
running = FALSE;
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();
}

175
arogue5/encumb.c Normal file
View file

@ -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);
}

1579
arogue5/fight.c Normal file

File diff suppressed because it is too large Load diff

497
arogue5/init.c Normal file
View file

@ -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 <ctype.h>
#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);
}

489
arogue5/io.c Normal file
View file

@ -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 <ctype.h>
#include <stdarg.h>
#include "rogue.h"
/*
* msg:
* Display a message at the top of the screen.
*/
static char msgbuf[BUFSIZ];
static int newpos = 0;
/*VARARGS1*/
msg(char *fmt, ...)
{
va_list ap;
/*
* if the string is "", just clear the line
*/
if (*fmt == '\0')
{
overwrite(cw,msgw);
wmove(msgw, 0, 0);
clearok(msgw, FALSE);
draw(msgw);
mpos = 0;
return;
}
/*
* otherwise add to the message and flush it out
*/
va_start(ap,fmt);
doadd(fmt, ap);
va_end(ap);
endmsg();
}
/*
* add things to the current message
*/
addmsg(char *fmt, ...)
{
va_list ap;
va_start(ap,fmt);
doadd(fmt, ap);
va_end(ap);
}
/*
* Display a new msg (giving him a chance to see the previous one if it
* is up there with the --More--)
*/
endmsg()
{
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<size; i++) {
nextc = getc(stream);
if (nextc == EOF) {
*error = 1;
return(0L);
}
else {
partial = (unsigned long) (nextc & 0xff);
partial <<= 8*i;
result |= partial;
}
}
*error = 0;
return(result);
}
/*
* netwrite:
* Write out a byte, short, or long machine independently.
*/
netwrite(value, size, stream)
unsigned long value; /* What to write */
int size; /* How much to write out */
FILE *stream; /* Where to write it */
{
int i; /* Goes through value one byte at a time */
char outc; /* The next character to be written */
/* Be sure we have a right sized chunk */
if (size < 1 || size > 4) return(0);
for (i=0; i<size; i++) {
outc = (char) ((value >> (8 * i)) & 0xff);
putc(outc, stream);
}
return(size);
}

185
arogue5/list.c Normal file
View file

@ -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 <stdlib.h>
#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;
}

64
arogue5/mach_dep.h Normal file
View file

@ -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

530
arogue5/main.c Normal file
View file

@ -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 <fcntl.h>
#include <sys/stat.h>
#include <limits.h>
#include <signal.h>
#include <time.h>
#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 <nlist.h>
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 <sys/types.h>
#include <utmp.h>
struct utmp buf;
ucount()
{
reg struct utmp *up;
reg FILE *utmp;
reg int count;
if ((utmp = fopen(UTMP, "r")) == NULL)
return 0;
up = &buf;
count = 0;
while (fread(up, 1, sizeof (*up), utmp) > 0)
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 */
}

369
arogue5/maze.c Normal file
View file

@ -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 <stdlib.h>
#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);
}

1194
arogue5/mdport.c Normal file

File diff suppressed because it is too large Load diff

736
arogue5/misc.c Normal file
View file

@ -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 <ctype.h>
#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);
}

1034
arogue5/monsters.c Normal file

File diff suppressed because it is too large Load diff

1386
arogue5/move.c Normal file

File diff suppressed because it is too large Load diff

21
arogue5/network.h Normal file
View file

@ -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 */

579
arogue5/new_level.c Normal file
View file

@ -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; i<TERRASAVE; i++) {
if (vert)
for (j=1; j<COLS-1; j++) {
if (top) {
cch = CCHAR( mvinch(i+2, j) );
mvaddch(LINES-6+i, j, cch);
}
else {
cch = CCHAR( mvinch(LINES-4-i, j) );
mvaddch(4-i, j, cch);
}
}
else
for (j=2; j<LINES-3; j++) {
if (top) {
cch = CCHAR( mvinch(j, i+1) );
mvaddch(j, COLS-4+i, cch);
}
else {
cch = CCHAR( mvinch(j, COLS-2-i) );
mvaddch(j, 3-i, cch);
}
}
}
if (vert) {
startx = deltax = 1;
if (top) {
starty = LINES-4-TERRASAVE;
deltay = -1;
}
else {
starty = TERRASAVE + 2;
deltay = 1;
}
}
else {
starty = 2;
deltay = 1;
if (top) {
startx = COLS-2-TERRASAVE;
deltax = -1;
}
else {
deltax = 1;
startx = TERRASAVE + 1;
}
}
/* Check if any monsters should be saved */
for (item = mlist; item != NULL; item = nitem) {
nitem = next(item);
tp = THINGPTR(item);
if (vert) {
if (top) {
if (tp->t_pos.y < TERRASAVE + 2)
tp->t_pos.y += LINES - 5 - TERRASAVE;
else continue;
}
else {
if (tp->t_pos.y > LINES - 4 - TERRASAVE)
tp->t_pos.y += 5 + TERRASAVE - LINES;
else continue;
}
}
else {
if (top) {
if (tp->t_pos.x < TERRASAVE + 1)
tp->t_pos.x += COLS - 2 - TERRASAVE;
else continue;
}
else {
if (tp->t_pos.x > COLS - 2 - TERRASAVE)
tp->t_pos.x += 2 + TERRASAVE - COLS;
else continue;
}
}
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; j<rp->r_max.y-1; j++)
for (i=1; i<rp->r_max.x-1; i++) {
coord trp;
trp.y = rp->r_pos.y+j;
trp.x = rp->r_pos.x+i;
/* Monsters */
if ((rnd(100) < (MAXTREAS*100)/(width*length)) &&
(mvwinch(mw, rp->r_pos.y+j, rp->r_pos.x+i) == ' ')) {
register struct thing *tp;
/* 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;
}
}

469
arogue5/options.c Normal file
View file

@ -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 <ctype.h>
#include "rogue.h"
#define NUM_OPTS (sizeof optlist / sizeof (OPTION))
/*
* description of an option and what to do with it
*/
struct optstruct {
char *o_name; /* option name */
char *o_prompt; /* prompt for interactive entry */
int *o_opt; /* pointer to thing to set */
int (*o_putfunc)(); /* function to print value */
int (*o_getfunc)(); /* function to get value interactively */
};
typedef struct optstruct OPTION;
int put_bool(),
get_bool(),
put_str(),
get_str(),
put_abil(),
get_abil(),
get_quest(),
put_quest();
OPTION optlist[] = {
{"terse", "Terse output: ",
(int *) &terse, put_bool, get_bool },
{"flush", "Flush typeahead during battle: ",
(int *) &fight_flush, put_bool, get_bool },
{"jump", "Show position only at end of run: ",
(int *) &jump, put_bool, get_bool },
{"step", "Do inventories one line at a time: ",
(int *) &slow_invent, put_bool, get_bool },
{"askme", "Ask me about unidentified things: ",
(int *) &askme, put_bool, get_bool },
{"pickup", "Pick things up automatically: ",
(int *) &auto_pickup, put_bool, get_bool },
{"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);
}

210
arogue5/outside.c Normal file
View file

@ -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<LINES-2; cury++) { /* Vertical "walls" */
mvaddch(cury, 0, '|');
mvaddch(cury, COLS-1, '|');
}
for (curx=0; curx<COLS; curx++) { /* Horizontal "walls" */
mvaddch(1, curx, '-');
mvaddch(LINES-3, curx, '-');
}
/* If we are not continuing, let's start out with a line of terrain */
if (fresh) {
char ch; /* Next char to add */
/* Move to the starting point (should be (1, 0)) */
move(basey, basex);
curx = basex;
/* Start with some random terrain */
if (basex == 0) {
ch = rnd_terrain();
addch(ch);
}
else ch = CCHAR( mvinch(basey, basex) );
curx += deltax;
/* Fill in the rest of the line */
while (curx > 0 && curx < COLS-1) {
/* Put in the next piece */
ch = get_terrain(ch, '\0', '\0', '\0');
mvaddch(basey, curx, ch);
curx += deltax;
}
basey++; /* Advance to next line */
}
/* Fill in the rest of the lines */
cury = basey;
while (cury > 1 && cury < LINES - 3) {
curx = basex;
while (curx > 0 && curx < COLS-1) {
register char left, top_left, top, top_right;
register int left_pos, top_pos;
/* Get the surrounding terrain */
left_pos = curx - deltax;
top_pos = cury - deltay;
left = CCHAR( mvinch(cury, left_pos) );
top_left = CCHAR( mvinch(top_pos, left_pos) );
top = CCHAR( mvinch(top_pos, curx) );
top_right = CCHAR( mvinch(top_pos, curx + deltax) );
/* Put the piece of terrain on the map */
mvaddch(cury, curx, get_terrain(left, top_left, top, top_right));
/* Get the next x coordinate */
curx += deltax;
}
/* Get the next y coordinate */
cury += deltay;
}
genmonsters(5, (bool) 0);
}
/*
* do_paths:
* draw at least a single path-way through the terrain
*/
/*
* rnd_terrain:
* return a weighted, random type of outside terrain
*/
char
rnd_terrain()
{
int chance = rnd(100);
/* Forest is most likely */
if (chance < 60) return(FOREST);
/* Next comes meadow */
if (chance < 90) return(FLOOR);
/* Then comes lakes */
if (chance < 97) return(POOL);
/* Finally, mountains */
return(WALL);
}
/*
* get_terrain:
* return a terrain weighted by what is surrounding
*/
char
get_terrain(one, two, three, four)
char one, two, three, four;
{
register int i;
int forest = 0, mountain = 0, lake = 0, meadow = 0, total = 0;
char surrounding[4];
surrounding[0] = one;
surrounding[1] = two;
surrounding[2] = three;
surrounding[3] = four;
for (i=0; i<4; i++)
switch (surrounding[i]) {
case FOREST:
forest++;
total++;
when WALL:
mountain++;
total++;
when POOL:
lake++;
total++;
when FLOOR:
meadow++;
total++;
}
/* Should we continue mountain? */
if (rnd(total+1) < mountain) return(WALL);
/* Should we continue lakes? */
if (rnd(total+1) < lake) return(POOL);
/* Should we continue meadow? */
if (rnd(total+1) < meadow) return(FLOOR);
/* Should we continue forest? */
if (rnd(total+2) < forest) return(FOREST);
/* Return something random */
return(rnd_terrain());
}
/*
* lake_check:
* Determine if the player would drown
*/
void
lake_check(place)
coord *place;
{
NOOP(place);
}

1143
arogue5/pack.c Normal file

File diff suppressed because it is too large Load diff

284
arogue5/passages.c Normal file
View file

@ -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);
}

587
arogue5/player.c Normal file
View file

@ -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; i++) {
msg("");
mvwaddch(cw, 0, 0, '[');
waddch(cw, (char) ((int) 'a' + i));
waddstr(cw, "] A spell of ");
if (magic_spells[i].s_type == TYP_POTION)
waddstr(cw, p_magic[magic_spells[i].s_which].mi_name);
else if (magic_spells[i].s_type == TYP_SCROLL)
waddstr(cw, s_magic[magic_spells[i].s_which].mi_name);
else if (magic_spells[i].s_type == TYP_STICK)
waddstr(cw, ws_magic[magic_spells[i].s_which].mi_name);
waddstr(cw, morestr);
draw(cw);
do {
c = readchar();
} while (c != ' ' && c != ESCAPE);
if (c == ESCAPE)
break;
}
msg("");
mvwaddstr(cw, 0, 0, "Which spell are you casting? ");
draw(cw);
}
else {
/* Set up for redraw */
msg("");
clearok(cw, TRUE);
touchwin(cw);
/* Now display the possible spells */
wclear(hw);
touchwin(hw);
mvwaddstr(hw, 2, 0, " Cost Spell");
mvwaddstr(hw, 3, 0, "-----------------------------------------------");
for (i=0; i<num_spells; i++) {
mvwaddch(hw, i+4, 0, '[');
waddch(hw, (char) ((int) 'a' + i));
waddch(hw, ']');
sprintf(prbuf, " %3d", magic_spells[i].s_cost);
waddstr(hw, prbuf);
waddstr(hw, " A spell of ");
if (magic_spells[i].s_type == TYP_POTION)
waddstr(hw, p_magic[magic_spells[i].s_which].mi_name);
else if (magic_spells[i].s_type == TYP_SCROLL)
waddstr(hw, s_magic[magic_spells[i].s_which].mi_name);
else if (magic_spells[i].s_type == TYP_STICK)
waddstr(hw, ws_magic[magic_spells[i].s_which].mi_name);
}
sprintf(prbuf,"[Current spell power = %d]",spell_ability - spell_power);
mvwaddstr(hw, 0, 0, prbuf);
waddstr(hw, " Which spell are you casting? ");
draw(hw);
}
if (!nohw) {
which_spell = (int) (wgetch(hw) - 'a');
while (which_spell < 0 || which_spell >= 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; i++) {
msg("");
mvwaddch(cw, 0, 0, '[');
waddch(cw, (char) ((int) 'a' + i));
waddstr(cw, "] A prayer for ");
if (cleric_spells[i].s_type == TYP_POTION)
waddstr(cw, p_magic[cleric_spells[i].s_which].mi_name);
else if (cleric_spells[i].s_type == TYP_SCROLL)
waddstr(cw, s_magic[cleric_spells[i].s_which].mi_name);
else if (cleric_spells[i].s_type == TYP_STICK)
waddstr(cw, ws_magic[cleric_spells[i].s_which].mi_name);
waddstr(cw, morestr);
draw(cw);
do {
c = readchar();
} while (c != ' ' && c != ESCAPE);
if (c == ESCAPE)
break;
}
msg("");
mvwaddstr(cw, 0, 0, "Which prayer are you offering? ");
draw(cw);
}
else {
/* Set up for redraw */
msg("");
clearok(cw, TRUE);
touchwin(cw);
/* Now display the possible prayers */
wclear(hw);
touchwin(hw);
mvwaddstr(hw, 2, 0, " Cost Prayer");
mvwaddstr(hw, 3, 0, "-----------------------------------------------");
for (i=0; i<num_prayers; i++) {
mvwaddch(hw, i+4, 0, '[');
waddch(hw, (char) ((int) 'a' + i));
waddch(hw, ']');
sprintf(prbuf, " %3d", cleric_spells[i].s_cost);
waddstr(hw, prbuf);
waddstr(hw, " A prayer for ");
if (cleric_spells[i].s_type == TYP_POTION)
waddstr(hw, p_magic[cleric_spells[i].s_which].mi_name);
else if (cleric_spells[i].s_type == TYP_SCROLL)
waddstr(hw, s_magic[cleric_spells[i].s_which].mi_name);
else if (cleric_spells[i].s_type == TYP_STICK)
waddstr(hw, ws_magic[cleric_spells[i].s_which].mi_name);
}
sprintf(prbuf,"[Current prayer ability = %d]",prayer_ability-pray_time);
mvwaddstr(hw, 0, 0, prbuf);
waddstr(hw, " Which prayer are you offering? ");
draw(hw);
}
if (!nohw) {
which_prayer = (int) (wgetch(hw) - 'a');
while (which_prayer < 0 || which_prayer >= 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);
}
}
}

698
arogue5/potions.c Normal file
View file

@ -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; i<lost_dext; i++)
extinguish(un_itch);
lost_dext = 0;
res_strength();
res_wisdom();
res_dexterity(0);
res_intelligence();
pstats.s_const = max_stats.s_const;
}
when P_INVIS:
if (off(player, ISINVIS)) {
turn_on(player, ISINVIS);
msg("You have a tingling feeling all over your body");
fuse(appear, 0, blessed ? GONETIME*3 : GONETIME, AFTER);
PLAYER = IPLAYER;
light(&hero);
}
else {
if (find_slot(appear)) {
msg("Your tingling feeling surges.");
lengthen(appear, blessed ? GONETIME*3 : GONETIME);
}
else msg("Nothing happens."); /* Using cloak */
}
otherwise:
msg("What an odd tasting potion!");
return;
}
status(FALSE);
if (is_potion && p_know[which] && p_guess[which])
{
free(p_guess[which]);
p_guess[which] = NULL;
}
else if (is_potion &&
!p_know[which] &&
askme &&
(obj->o_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;
}
}

161
arogue5/rings.c Normal file
View file

@ -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);
}

768
arogue5/rip.c Normal file
View file

@ -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 <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include "curses.h"
#include <time.h>
#include <signal.h>
#include <ctype.h>
#include <sys/types.h>
#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<NUMNET; i++)
if (Network[i].system[0] != '!' &&
strcmp(Network[i].system, thissys)) {
sprintf(cmd,
"usend -s -d%s -uNoLogin -!'%s -u' - 2>/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); j<LINELEN; j++)
putc('\0', rmf);
(void) netwrite((unsigned long) flags,
sizeof(short), rmf);
temp = (unsigned long)
(flags==WINNER ? max_level : level);
(void) netwrite(temp, sizeof(short), rmf);
(void) netwrite((unsigned long) player.t_ctype,
sizeof(short), rmf);
(void) fwrite(thissys, 1,
strlen(thissys), rmf);
for (j=strlen(thissys); j<SYSLEN; j++)
putc('\0', rmf);
(void) fwrite(login, 1, strlen(login), rmf);
for (j=strlen(login); j<LOGLEN; j++)
putc('\0', rmf);
/* Close off the command */
(void) pclose(rmf);
}
}
_exit(0); /* Exit network process */
#endif
}
}
}
/*
* SCOREIT -- rogue -s option. Never started curses if this option.
* UPDATE -- network scoring update. Never started curses if this option.
* EDITSCORE -- want to delete or change a score.
*/
/* if (flags != SCOREIT && flags != UPDATE && prflags != EDITSCORE)
endwin(); */
if (flags != UPDATE) {
if (flags != SCOREIT) {
clear();
refresh();
endwin();
}
/*
* Print the list
*/
printf("\nTop %d Adventurers:\nRank Score\tName\n",
NUMSCORE);
for (scp = top_ten; scp <= &top_ten[NUMSCORE-1]; scp++) {
char *class;
if (scp->sc_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);
}

1432
arogue5/rogue.c Normal file

File diff suppressed because it is too large Load diff

1117
arogue5/rogue.h Normal file

File diff suppressed because it is too large Load diff

239
arogue5/rooms.c Normal file
View file

@ -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('|');
}
}

289
arogue5/save.c Normal file
View file

@ -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 <fcntl.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#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;
}

709
arogue5/scrolls.c Normal file
View file

@ -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 <ctype.h>
#include "rogue.h"
/*
* let the hero get rid of some type of monster (but not a UNIQUE!)
*/
genocide()
{
register struct linked_list *ip;
register struct thing *mp;
register 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<left_limit; i++) {
sprintf(monst_name,
"[%d] %c%s\n",
pres_monst,
monsters[pres_monst].m_normal ? ' ' : '*',
monsters[pres_monst].m_name);
waddstr(hw, monst_name);
pres_monst++;
}
/* Print right column */
for (i=0; i<left_limit && pres_monst<=NUMMONST-NUMUNIQUE-1; i++) {
sprintf(monst_name,
"[%d] %c%s\n",
pres_monst,
monsters[pres_monst].m_normal ? ' ' : '*',
monsters[pres_monst].m_name);
wmove(hw, i+2, COLS/2);
waddstr(hw, monst_name);
pres_monst++;
}
if ((num_monst -= num_lines) > 0) {
mvwaddstr(hw, LINES-1, 0, morestr);
draw(hw);
wait_for(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; i<ntraps && !ce(traps[i].tr_pos, hero); i++);
ntraps--;
if (!ce(traps[i].tr_pos, hero))
msg("What a strange trap!");
else {
while (i < ntraps) {
traps[i] = traps[i + 1];
i++;
}
}
}
goto pet_message;
case DOOR:
case SECRETDOOR:
case FLOOR:
case PASSAGE:
pet_message: msg("The dungeon begins to rumble and shake!");
addch(WALL);
/* If the player is phased, unphase him */
if (on(player, CANINWALL)) {
extinguish(unphase);
turn_off(player, CANINWALL);
msg("Your dizzy feeling leaves you.");
}
/* Mark the player as in a wall */
turn_on(player, ISINWALL);
break;
default:
msg(nothing);
}
when S_GENOCIDE:
msg("You have been granted the boon of genocide!--More--");
wait_for(cw,' ');
msg("");
genocide();
if (is_scroll) s_know[S_GENOCIDE] = TRUE;
when S_PROTECT: {
struct linked_list *ll;
struct object *lb;
bool did_it = FALSE;
msg("You are granted the power of protection.");
if ((ll = get_item(pack, "protect", PROTECTABLE)) != NULL) {
lb = OBJPTR(ll);
mpos = 0;
if (cursed) {
switch(lb->o_type) { /* ruin it completely */
case RING: if (lb->o_ac > 0) {
if (is_current(lb)) {
switch (lb->o_which) {
case R_ADDWISDOM:
pstats.s_wisdom -= lb->o_ac;
when R_ADDINTEL:
pstats.s_intel -= lb->o_ac;
when R_ADDSTR:
pstats.s_str -= lb->o_ac;
when R_ADDHIT:
pstats.s_dext -= lb->o_ac;
}
}
did_it = TRUE;
lb->o_ac = 0;
}
when ARMOR: if (lb->o_ac > 10) {
did_it = TRUE;
lb->o_ac = 10;
}
when STICK: if (lb->o_charges > 0) {
did_it = TRUE;
lb->o_charges = 0;
}
when WEAPON:if (lb->o_hplus > 0) {
did_it = TRUE;
lb->o_hplus = 0;
}
if (lb->o_dplus > 0) {
did_it = TRUE;
lb->o_dplus = 0;
}
}
if (lb->o_flags & ISPROT) {
did_it = TRUE;
lb->o_flags &= ~ISPROT;
}
if (lb->o_flags & ISBLESSED) {
did_it = TRUE;
lb->o_flags &= ~ISBLESSED;
}
if (did_it)
msg("Your %s glows red for a moment",inv_name(lb,TRUE));
else {
msg(nothing);
break;
}
}
else {
lb->o_flags |= ISPROT;
msg("Protected %s.",inv_name(lb,TRUE));
}
}
if (is_scroll) s_know[S_PROTECT] = TRUE;
}
when S_MAKEIT:
msg("You have been endowed with the power of creation.");
if (is_scroll) s_know[S_MAKEIT] = TRUE;
create_obj(TRUE, 0, 0);
when S_ALLENCH: {
struct linked_list *ll;
struct object *lb;
int howmuch, flags;
if (is_scroll && s_know[S_ALLENCH] == FALSE) {
msg("You are granted the power of enchantment.");
msg("You may enchant anything(weapon,ring,armor,scroll,potion)");
}
if ((ll = get_item(pack, "enchant",ALL)) != 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);
}

2477
arogue5/state.c Normal file

File diff suppressed because it is too large Load diff

1076
arogue5/sticks.c Normal file

File diff suppressed because it is too large Load diff

849
arogue5/things.c Normal file
View file

@ -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 <ctype.h>
#include "rogue.h"
/*
* print out the number of charges on a stick
*/
char *
charge_str(obj)
register struct object *obj;
{
static char buf[20];
if (!(obj->o_flags & ISKNOW))
buf[0] = '\0';
else if (terse)
sprintf(buf, " [%d]", obj->o_charges);
else
sprintf(buf, " [%d charges]", obj->o_charges);
return buf;
}
/*
* inv_name:
* return the name of something as it would appear in an
* inventory.
*/
char *
inv_name(obj, drop)
register struct object *obj;
bool drop;
{
register char *pb;
pb = prbuf;
pb[0] = '\0';
switch(obj->o_type) {
case SCROLL:
if (obj->o_count == 1)
sprintf(pb, "A %sscroll ", blesscurse(obj->o_flags));
else
sprintf(pb, "%d %sscrolls ",
obj->o_count, blesscurse(obj->o_flags));
pb = &pb[strlen(pb)];
if (s_know[obj->o_which] || (obj->o_flags & ISPOST))
sprintf(pb, "of %s", s_magic[obj->o_which].mi_name);
else if (s_guess[obj->o_which])
sprintf(pb, "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);
}

336
arogue5/trader.c Normal file
View file

@ -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);
}

921
arogue5/util.c Normal file
View file

@ -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 <ctype.h>
/*
* 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);
}

20
arogue5/vers.c Normal file
View file

@ -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";

310
arogue5/weapons.c Normal file
View file

@ -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 <ctype.h>
#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;
}

259
arogue5/wear.c Normal file
View file

@ -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<NUM_FINGERS; i++)
if (cur_ring[i] == NULL) {
cur_ring[i] = obj;
break;
}
if (i == NUM_FINGERS) { /* No room */
if (terse) msg("Wearing enough rings");
else msg("You already have on eight rings");
return;
}
/* Calculate the effect of the ring */
ring_on(obj);
}
updpack(TRUE);
}

585
arogue5/wizard.c Normal file
View file

@ -0,0 +1,585 @@
/*
* Special wizard commands (some of which are also non-wizard commands
* under strange circumstances)
*
* 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 <ctype.h>
#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; i++) {
sprintf(label, "[%d] %s", i+1, deaths[i].name);
mvaddstr(i+2, 0, label);
}
mvaddstr(0, 0, "Which death? ");
refresh();
/* Get the death */
for (;;) {
get_str(label, stdscr);
which_death = atoi(label);
if ((which_death < 1 || which_death > DEATHNUM)) {
mvaddstr(0, 0, "Please enter a number in the displayed range -- ");
refresh();
}
else break;
}
return(deaths[which_death-1].reason);
}
/*
* 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<left_limit; i++) {
sprintf(monst_name, "[%d] %s\n",
pres_monst, monsters[pres_monst].m_name);
waddstr(hw, monst_name);
pres_monst++;
}
/* Print right column */
for (i=0; i<left_limit && pres_monst<=NUMMONST; i++) {
sprintf(monst_name, "[%d] %s",
pres_monst, monsters[pres_monst].m_name);
wmove(hw, i+2, COLS/2);
waddstr(hw, monst_name);
pres_monst++;
}
if ((num_monst -= num_lines) > 0) {
mvwaddstr(hw, LINES-1, 0, morestr);
draw(hw);
wait_for(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));
}

694
arogue5/xcrypt.c Normal file
View file

@ -0,0 +1,694 @@
/*
* FreeSec: libcrypt
*
* Copyright (C) 1994 David Burren
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name(s) of the author(s) nor the names of other contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
* This is an original implementation of the DES and the crypt(3) interfaces
* by David Burren <davidb@werj.com.au>.
*
* An excellent reference on the underlying algorithm (and related
* algorithms) is:
*
* B. Schneier, Applied Cryptography: protocols, algorithms,
* and source code in C, John Wiley & Sons, 1994.
*
* Note that in that book's description of DES the lookups for the initial,
* pbox, and final permutations are inverted (this has been brought to the
* attention of the author). A list of errata for this book has been
* posted to the sci.crypt newsgroup by the author and is available for FTP.
*
* NOTE:
* This file has a static version of des_setkey() so that crypt.o exports
* only the crypt() interface. This is required to make binaries linked
* against crypt.o exportable or re-exportable from the USA.
*/
#include <sys/types.h>
#include <string.h>
#ifdef DEBUG
# include <stdio.h>
#endif
#define _PASSWORD_EFMT1 '_'
static unsigned char IP[64] = {
58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7
};
static unsigned char inv_key_perm[64];
static unsigned char key_perm[56] = {
57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36,
63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4
};
static unsigned char key_shifts[16] = {
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
};
static unsigned char inv_comp_perm[56];
static unsigned char comp_perm[48] = {
14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10,
23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
};
/*
* No E box is used, as it's replaced by some ANDs, shifts, and ORs.
*/
static unsigned char u_sbox[8][64];
static unsigned char sbox[8][64] = {
{
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
},
{
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
},
{
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
},
{
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
},
{
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
},
{
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
},
{
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
},
{
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
}
};
static unsigned char un_pbox[32];
static unsigned char pbox[32] = {
16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,
2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25
};
static unsigned int bits32[32] =
{
0x80000000, 0x40000000, 0x20000000, 0x10000000,
0x08000000, 0x04000000, 0x02000000, 0x01000000,
0x00800000, 0x00400000, 0x00200000, 0x00100000,
0x00080000, 0x00040000, 0x00020000, 0x00010000,
0x00008000, 0x00004000, 0x00002000, 0x00001000,
0x00000800, 0x00000400, 0x00000200, 0x00000100,
0x00000080, 0x00000040, 0x00000020, 0x00000010,
0x00000008, 0x00000004, 0x00000002, 0x00000001
};
static unsigned char bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
static unsigned int saltbits;
static int old_salt;
static unsigned int *bits28, *bits24;
static unsigned char init_perm[64], final_perm[64];
static unsigned int en_keysl[16], en_keysr[16];
static unsigned int de_keysl[16], de_keysr[16];
static int des_initialised = 0;
static unsigned char m_sbox[4][4096];
static unsigned int psbox[4][256];
static unsigned int ip_maskl[8][256], ip_maskr[8][256];
static unsigned int fp_maskl[8][256], fp_maskr[8][256];
static unsigned int key_perm_maskl[8][128], key_perm_maskr[8][128];
static unsigned int comp_maskl[8][128], comp_maskr[8][128];
static unsigned int old_rawkey0, old_rawkey1;
static unsigned char ascii64[] =
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
/* 0000000000111111111122222222223333333333444444444455555555556666 */
/* 0123456789012345678901234567890123456789012345678901234567890123 */
static __inline int
ascii_to_bin(ch)
char ch;
{
if (ch > 'z')
return(0);
if (ch >= 'a')
return(ch - 'a' + 38);
if (ch > 'Z')
return(0);
if (ch >= 'A')
return(ch - 'A' + 12);
if (ch > '9')
return(0);
if (ch >= '.')
return(ch - '.');
return(0);
}
static void
des_init()
{
int i, j, b, k, inbit, obit;
unsigned int *p, *il, *ir, *fl, *fr;
old_rawkey0 = old_rawkey1 = 0;
saltbits = 0;
old_salt = 0;
bits24 = (bits28 = bits32 + 4) + 4;
/*
* Invert the S-boxes, reordering the input bits.
*/
for (i = 0; i < 8; i++)
for (j = 0; j < 64; j++) {
b = (j & 0x20) | ((j & 1) << 4) | ((j >> 1) & 0xf);
u_sbox[i][j] = sbox[i][b];
}
/*
* Convert the inverted S-boxes into 4 arrays of 8 bits.
* Each will handle 12 bits of the S-box input.
*/
for (b = 0; b < 4; b++)
for (i = 0; i < 64; i++)
for (j = 0; j < 64; j++)
m_sbox[b][(i << 6) | j] =
(u_sbox[(b << 1)][i] << 4) |
u_sbox[(b << 1) + 1][j];
/*
* Set up the initial & final permutations into a useful form, and
* initialise the inverted key permutation.
*/
for (i = 0; i < 64; i++) {
init_perm[final_perm[i] = IP[i] - 1] = i;
inv_key_perm[i] = 255;
}
/*
* Invert the key permutation and initialise the inverted key
* compression permutation.
*/
for (i = 0; i < 56; i++) {
inv_key_perm[key_perm[i] - 1] = i;
inv_comp_perm[i] = 255;
}
/*
* Invert the key compression permutation.
*/
for (i = 0; i < 48; i++) {
inv_comp_perm[comp_perm[i] - 1] = i;
}
/*
* Set up the OR-mask arrays for the initial and final permutations,
* and for the key initial and compression permutations.
*/
for (k = 0; k < 8; k++) {
for (i = 0; i < 256; i++) {
*(il = &ip_maskl[k][i]) = 0;
*(ir = &ip_maskr[k][i]) = 0;
*(fl = &fp_maskl[k][i]) = 0;
*(fr = &fp_maskr[k][i]) = 0;
for (j = 0; j < 8; j++) {
inbit = 8 * k + j;
if (i & bits8[j]) {
if ((obit = init_perm[inbit]) < 32)
*il |= bits32[obit];
else
*ir |= bits32[obit-32];
if ((obit = final_perm[inbit]) < 32)
*fl |= bits32[obit];
else
*fr |= bits32[obit - 32];
}
}
}
for (i = 0; i < 128; i++) {
*(il = &key_perm_maskl[k][i]) = 0;
*(ir = &key_perm_maskr[k][i]) = 0;
for (j = 0; j < 7; j++) {
inbit = 8 * k + j;
if (i & bits8[j + 1]) {
if ((obit = inv_key_perm[inbit]) == 255)
continue;
if (obit < 28)
*il |= bits28[obit];
else
*ir |= bits28[obit - 28];
}
}
*(il = &comp_maskl[k][i]) = 0;
*(ir = &comp_maskr[k][i]) = 0;
for (j = 0; j < 7; j++) {
inbit = 7 * k + j;
if (i & bits8[j + 1]) {
if ((obit=inv_comp_perm[inbit]) == 255)
continue;
if (obit < 24)
*il |= bits24[obit];
else
*ir |= bits24[obit - 24];
}
}
}
}
/*
* Invert the P-box permutation, and convert into OR-masks for
* handling the output of the S-box arrays setup above.
*/
for (i = 0; i < 32; i++)
un_pbox[pbox[i] - 1] = i;
for (b = 0; b < 4; b++)
for (i = 0; i < 256; i++) {
*(p = &psbox[b][i]) = 0;
for (j = 0; j < 8; j++) {
if (i & bits8[j])
*p |= bits32[un_pbox[8 * b + j]];
}
}
des_initialised = 1;
}
static void
setup_salt(salt)
int salt;
{
unsigned int obit, saltbit;
int i;
if (salt == old_salt)
return;
old_salt = salt;
saltbits = 0;
saltbit = 1;
obit = 0x800000;
for (i = 0; i < 24; i++) {
if (salt & saltbit)
saltbits |= obit;
saltbit <<= 1;
obit >>= 1;
}
}
static int
des_setkey(key)
const char *key;
{
unsigned int k0, k1, rawkey0, rawkey1;
int shifts, round;
if (!des_initialised)
des_init();
rawkey0 = md_ntohl(*(unsigned int *) key);
rawkey1 = md_ntohl(*(unsigned int *) (key + 4));
if ((rawkey0 | rawkey1)
&& rawkey0 == old_rawkey0
&& rawkey1 == old_rawkey1) {
/*
* Already setup for this key.
* This optimisation fails on a zero key (which is weak and
* has bad parity anyway) in order to simplify the starting
* conditions.
*/
return(0);
}
old_rawkey0 = rawkey0;
old_rawkey1 = rawkey1;
/*
* Do key permutation and split into two 28-bit subkeys.
*/
k0 = key_perm_maskl[0][rawkey0 >> 25]
| key_perm_maskl[1][(rawkey0 >> 17) & 0x7f]
| key_perm_maskl[2][(rawkey0 >> 9) & 0x7f]
| key_perm_maskl[3][(rawkey0 >> 1) & 0x7f]
| key_perm_maskl[4][rawkey1 >> 25]
| key_perm_maskl[5][(rawkey1 >> 17) & 0x7f]
| key_perm_maskl[6][(rawkey1 >> 9) & 0x7f]
| key_perm_maskl[7][(rawkey1 >> 1) & 0x7f];
k1 = key_perm_maskr[0][rawkey0 >> 25]
| key_perm_maskr[1][(rawkey0 >> 17) & 0x7f]
| key_perm_maskr[2][(rawkey0 >> 9) & 0x7f]
| key_perm_maskr[3][(rawkey0 >> 1) & 0x7f]
| key_perm_maskr[4][rawkey1 >> 25]
| key_perm_maskr[5][(rawkey1 >> 17) & 0x7f]
| key_perm_maskr[6][(rawkey1 >> 9) & 0x7f]
| key_perm_maskr[7][(rawkey1 >> 1) & 0x7f];
/*
* Rotate subkeys and do compression permutation.
*/
shifts = 0;
for (round = 0; round < 16; round++) {
unsigned int t0, t1;
shifts += key_shifts[round];
t0 = (k0 << shifts) | (k0 >> (28 - shifts));
t1 = (k1 << shifts) | (k1 >> (28 - shifts));
de_keysl[15 - round] =
en_keysl[round] = comp_maskl[0][(t0 >> 21) & 0x7f]
| comp_maskl[1][(t0 >> 14) & 0x7f]
| comp_maskl[2][(t0 >> 7) & 0x7f]
| comp_maskl[3][t0 & 0x7f]
| comp_maskl[4][(t1 >> 21) & 0x7f]
| comp_maskl[5][(t1 >> 14) & 0x7f]
| comp_maskl[6][(t1 >> 7) & 0x7f]
| comp_maskl[7][t1 & 0x7f];
de_keysr[15 - round] =
en_keysr[round] = comp_maskr[0][(t0 >> 21) & 0x7f]
| comp_maskr[1][(t0 >> 14) & 0x7f]
| comp_maskr[2][(t0 >> 7) & 0x7f]
| comp_maskr[3][t0 & 0x7f]
| comp_maskr[4][(t1 >> 21) & 0x7f]
| comp_maskr[5][(t1 >> 14) & 0x7f]
| comp_maskr[6][(t1 >> 7) & 0x7f]
| comp_maskr[7][t1 & 0x7f];
}
return(0);
}
static int
do_des(l_in, r_in, l_out, r_out, count)
unsigned int l_in, r_in, *l_out, *r_out;
int count;
{
/*
* l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format.
*/
unsigned int l, r, *kl, *kr, *kl1, *kr1;
unsigned int f = 0, r48l, r48r;
int round;
if (count == 0) {
return(1);
} else if (count > 0) {
/*
* Encrypting
*/
kl1 = en_keysl;
kr1 = en_keysr;
} else {
/*
* Decrypting
*/
count = -count;
kl1 = de_keysl;
kr1 = de_keysr;
}
/*
* Do initial permutation (IP).
*/
l = ip_maskl[0][l_in >> 24]
| ip_maskl[1][(l_in >> 16) & 0xff]
| ip_maskl[2][(l_in >> 8) & 0xff]
| ip_maskl[3][l_in & 0xff]
| ip_maskl[4][r_in >> 24]
| ip_maskl[5][(r_in >> 16) & 0xff]
| ip_maskl[6][(r_in >> 8) & 0xff]
| ip_maskl[7][r_in & 0xff];
r = ip_maskr[0][l_in >> 24]
| ip_maskr[1][(l_in >> 16) & 0xff]
| ip_maskr[2][(l_in >> 8) & 0xff]
| ip_maskr[3][l_in & 0xff]
| ip_maskr[4][r_in >> 24]
| ip_maskr[5][(r_in >> 16) & 0xff]
| ip_maskr[6][(r_in >> 8) & 0xff]
| ip_maskr[7][r_in & 0xff];
while (count--) {
/*
* Do each round.
*/
kl = kl1;
kr = kr1;
round = 16;
while (round--) {
/*
* Expand R to 48 bits (simulate the E-box).
*/
r48l = ((r & 0x00000001) << 23)
| ((r & 0xf8000000) >> 9)
| ((r & 0x1f800000) >> 11)
| ((r & 0x01f80000) >> 13)
| ((r & 0x001f8000) >> 15);
r48r = ((r & 0x0001f800) << 7)
| ((r & 0x00001f80) << 5)
| ((r & 0x000001f8) << 3)
| ((r & 0x0000001f) << 1)
| ((r & 0x80000000) >> 31);
/*
* Do salting for crypt() and friends, and
* XOR with the permuted key.
*/
f = (r48l ^ r48r) & saltbits;
r48l ^= f ^ *kl++;
r48r ^= f ^ *kr++;
/*
* Do sbox lookups (which shrink it back to 32 bits)
* and do the pbox permutation at the same time.
*/
f = psbox[0][m_sbox[0][r48l >> 12]]
| psbox[1][m_sbox[1][r48l & 0xfff]]
| psbox[2][m_sbox[2][r48r >> 12]]
| psbox[3][m_sbox[3][r48r & 0xfff]];
/*
* Now that we've permuted things, complete f().
*/
f ^= l;
l = r;
r = f;
}
r = l;
l = f;
}
/*
* Do final permutation (inverse of IP).
*/
*l_out = fp_maskl[0][l >> 24]
| fp_maskl[1][(l >> 16) & 0xff]
| fp_maskl[2][(l >> 8) & 0xff]
| fp_maskl[3][l & 0xff]
| fp_maskl[4][r >> 24]
| fp_maskl[5][(r >> 16) & 0xff]
| fp_maskl[6][(r >> 8) & 0xff]
| fp_maskl[7][r & 0xff];
*r_out = fp_maskr[0][l >> 24]
| fp_maskr[1][(l >> 16) & 0xff]
| fp_maskr[2][(l >> 8) & 0xff]
| fp_maskr[3][l & 0xff]
| fp_maskr[4][r >> 24]
| fp_maskr[5][(r >> 16) & 0xff]
| fp_maskr[6][(r >> 8) & 0xff]
| fp_maskr[7][r & 0xff];
return(0);
}
static int
des_cipher(in, out, salt, count)
const char *in;
char *out;
int salt;
int count;
{
unsigned int l_out, r_out, rawl, rawr;
unsigned int x[2];
int retval;
if (!des_initialised)
des_init();
setup_salt(salt);
memcpy(x, in, sizeof x);
rawl = md_ntohl(x[0]);
rawr = md_ntohl(x[1]);
retval = do_des(rawl, rawr, &l_out, &r_out, count);
x[0] = md_htonl(l_out);
x[1] = md_htonl(r_out);
memcpy(out, x, sizeof x);
return(retval);
}
char *
xcrypt(key, setting)
const char *key;
const char *setting;
{
int i;
unsigned int count, salt, l, r0, r1, keybuf[2];
unsigned char *p, *q;
static unsigned char output[21];
if (!des_initialised)
des_init();
/*
* Copy the key, shifting each character up by one bit
* and padding with zeros.
*/
q = (unsigned char *) keybuf;
while ((q - (unsigned char *) keybuf) < sizeof(keybuf)) {
if ((*q++ = *key << 1))
key++;
}
if (des_setkey((unsigned char *) keybuf))
return(NULL);
if (*setting == _PASSWORD_EFMT1) {
/*
* "new"-style:
* setting - underscore, 4 bytes of count, 4 bytes of salt
* key - unlimited characters
*/
for (i = 1, count = 0; i < 5; i++)
count |= ascii_to_bin(setting[i]) << (i - 1) * 6;
for (i = 5, salt = 0; i < 9; i++)
salt |= ascii_to_bin(setting[i]) << (i - 5) * 6;
while (*key) {
/*
* Encrypt the key with itself.
*/
if (des_cipher((unsigned char*)keybuf, (unsigned char*)keybuf, 0, 1))
return(NULL);
/*
* And XOR with the next 8 characters of the key.
*/
q = (unsigned char *) keybuf;
while (((q - (unsigned char *) keybuf) < sizeof(keybuf)) &&
*key)
*q++ ^= *key++ << 1;
if (des_setkey((unsigned char *) keybuf))
return(NULL);
}
strncpy((char *)output, setting, 9);
/*
* Double check that we weren't given a short setting.
* If we were, the above code will probably have created
* wierd values for count and salt, but we don't really care.
* Just make sure the output string doesn't have an extra
* NUL in it.
*/
output[9] = '\0';
p = output + strlen((const char *)output);
} else {
/*
* "old"-style:
* setting - 2 bytes of salt
* key - up to 8 characters
*/
count = 25;
salt = (ascii_to_bin(setting[1]) << 6)
| ascii_to_bin(setting[0]);
output[0] = setting[0];
/*
* If the encrypted password that the salt was extracted from
* is only 1 character long, the salt will be corrupted. We
* need to ensure that the output string doesn't have an extra
* NUL in it!
*/
output[1] = setting[1] ? setting[1] : output[0];
p = output + 2;
}
setup_salt(salt);
/*
* Do it.
*/
if (do_des(0, 0, &r0, &r1, count))
return(NULL);
/*
* Now encode the result...
*/
l = (r0 >> 8);
*p++ = ascii64[(l >> 18) & 0x3f];
*p++ = ascii64[(l >> 12) & 0x3f];
*p++ = ascii64[(l >> 6) & 0x3f];
*p++ = ascii64[l & 0x3f];
l = (r0 << 16) | ((r1 >> 16) & 0xffff);
*p++ = ascii64[(l >> 18) & 0x3f];
*p++ = ascii64[(l >> 12) & 0x3f];
*p++ = ascii64[(l >> 6) & 0x3f];
*p++ = ascii64[l & 0x3f];
l = r1 << 2;
*p++ = ascii64[(l >> 12) & 0x3f];
*p++ = ascii64[(l >> 6) & 0x3f];
*p++ = ascii64[l & 0x3f];
*p = 0;
return((char *)output);
}