Import XRogue 8.0 from the Roguelike Restoration Project (r1490)
This commit is contained in:
parent
6af92da76a
commit
034d8d6484
51 changed files with 37250 additions and 0 deletions
178
xrogue/LICENSE.TXT
Normal file
178
xrogue/LICENSE.TXT
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
Copyright (C) 1991 Robert Pietkivitch
|
||||
Portions Copyright (C) 1985 Michael Morgan, Ken Dalka and AT&T
|
||||
Portions Copyright (C) 1981 Michael Toy, Ken Arnold and Glenn Wichman
|
||||
Portions Copyright (C) 2000 Nicholas J. Kisseberth
|
||||
Portions Copyright (C) 1994 David Burren
|
||||
All rights reserved.
|
||||
|
||||
===========================================================================
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
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 "XRogue" 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 "XRogue",
|
||||
nor may "XRogue" appear in their name, without prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
===========================================================================
|
||||
|
||||
Portions of this software are based on the work of Michael Morgan and
|
||||
Ken Dalka. Used under license:
|
||||
|
||||
Advanced Rogue
|
||||
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka 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 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) 2000 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.
|
||||
115
xrogue/Makefile
Normal file
115
xrogue/Makefile
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
# XRogue: Expeditions into the Dungeons of Doom
|
||||
# Copyright (C) 1991 Robert Pietkivitch
|
||||
# All rights reserved.
|
||||
#
|
||||
# Based on "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=xrogue8.0.3
|
||||
PROGRAM=xrogue
|
||||
|
||||
O=o
|
||||
|
||||
HDRS = rogue.h mach_dep.h network.h
|
||||
|
||||
OBJS1 = vers.$(O) actions.$(O) bolt.$(O) chase.$(O) command.$(O) daemon.$(O) \
|
||||
daemons.$(O) eat.$(O) effects.$(O) fight.$(O) encumb.$(O) help.$(O) \
|
||||
init.$(O) io.$(O) list.$(O) main.$(O) maze.$(O) misc.$(O) monsters.$(O)
|
||||
OBJS2 = mons_def.$(O) move.$(O) n_level.$(O) options.$(O) outside.$(O) pack.$(O) \
|
||||
passages.$(O) player.$(O) potions.$(O) rings.$(O) rip.$(O) rooms.$(O) \
|
||||
save.$(O) scrolls.$(O) sticks.$(O) things.$(O) trader.$(O) util.$(O) \
|
||||
weapons.$(O) wear.$(O) wizard.$(O) rogue.$(O) state.$(O) xcrypt.$(O)
|
||||
OBJS = $(OBJS1) $(OBJS2)
|
||||
|
||||
CFILES= vers.c actions.c bolt.c chase.c command.c daemon.c daemons.c eat.c \
|
||||
effects.c fight.c encumb.c help.c init.c io.c list.c main.c maze.c \
|
||||
misc.c monsters.c mons_def.c move.c n_level.c options.c outside.c \
|
||||
pack.c passages.c player.c potions.c rings.c rip.c rooms.c save.c \
|
||||
scrolls.c sticks.c things.c trader.c util.c weapons.c wear.c wizard.c \
|
||||
rogue.c state.c xcrypt.c
|
||||
|
||||
MISC = Makefile README.TXT LICENSE.TXT $(PROGRAM).sln $(PROGRAM).vcproj
|
||||
|
||||
CC = gcc
|
||||
CFLAGS= -O3
|
||||
CRLIB = -lcurses
|
||||
RM = rm -f
|
||||
TAR = tar
|
||||
.SUFFIXES: .obj
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) /c $*.c
|
||||
|
||||
$(PROGRAM): $(HDRS) $(OBJS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(CRLIB) -o $@
|
||||
|
||||
clean:
|
||||
$(RM) $(OBJS1)
|
||||
$(RM) $(OBJS2)
|
||||
$(RM) core a.exe a.out a.exe.stackdump $(PROGRAM) $(PROGRAM).exe $(PROGRAM).tar $(PROGRAM).tar.gz $(PROGRAM).zip
|
||||
|
||||
dist.src:
|
||||
make clean
|
||||
tar cf $(DISTNAME)-src.tar $(CFILES) $(HDRS) $(MISC)
|
||||
gzip -f $(DISTNAME)-src.tar
|
||||
|
||||
dist.irix:
|
||||
make clean
|
||||
make CC=cc CFLAGS="-woff 1116 -O3" $(PROGRAM)
|
||||
tar cf $(DISTNAME)-irix.tar $(PROGRAM) README.TXT LICENSE.TXT
|
||||
gzip -f $(DISTNAME)-irix.tar
|
||||
|
||||
dist.aix:
|
||||
make clean
|
||||
make CC=xlc CFLAGS="-qmaxmem=16768 -O3 -qstrict" $(PROGRAM)
|
||||
tar cf $(DISTNAME)-aix.tar $(PROGRAM) README.TXT LICENSE.TXT
|
||||
gzip -f $(DISTNAME)-aix.tar
|
||||
|
||||
dist.linux:
|
||||
make clean
|
||||
make $(PROGRAM)
|
||||
tar cf $(DISTNAME)-linux.tar $(PROGRAM) README.TXT LICENSE.TXT
|
||||
gzip -f $(DISTNAME)-linux.tar
|
||||
|
||||
dist.interix:
|
||||
make clean
|
||||
make $(PROGRAM)
|
||||
tar cf $(DISTNAME)-interix.tar $(PROGRAM) README.TXT LICENSE.TXT
|
||||
gzip -f $(DISTNAME)-interix.tar
|
||||
|
||||
dist.cygwin:
|
||||
make clean
|
||||
make $(PROGRAM)
|
||||
tar cf $(DISTNAME)-cygwin.tar $(PROGRAM).exe README.TXT LICENSE.TXT
|
||||
gzip -f $(DISTNAME)-cygwin.tar
|
||||
|
||||
dist.mingw32:
|
||||
$(MAKE) RM="cmd /c del" clean
|
||||
$(MAKE) CRLIB="-lpdcurses -lWs2_32" $(PROGRAM)
|
||||
cmd /c del $(DISTNAME)-mingw32.zip
|
||||
zip $(DISTNAME)-mingw32.zip $(PROGRAM).exe README.TXT LICENSE.TXT
|
||||
|
||||
dist.msys:
|
||||
$(MAKE) clean
|
||||
$(MAKE) CRLIB="-lcurses -lWs2_32" $(PROGRAM)
|
||||
tar cf $(DISTNAME)-msys.tar $(PROGRAM).exe README.TXT LICENSE.TXT
|
||||
gzip -f $(DISTNAME)-msys.tar
|
||||
|
||||
dist.djgpp:
|
||||
make clean
|
||||
make LDFLAGS="-L$(DJDIR)/LIB" CRLIB="-lpdcurses" $(PROGRAM)
|
||||
rm -f $(DISTNAME)-djgpp.zip
|
||||
zip $(DISTNAME)-djgpp.zip $(PROGRAM) README.TXT LICENSE.TXT
|
||||
|
||||
dist.win32:
|
||||
nmake O="obj" RM="-del" clean
|
||||
nmake O="obj" CC="CL" CRLIB="..\pdcurses.lib shell32.lib user32.lib Advapi32.lib Ws2_32.lib" CFLAGS="-DPDC_STATIC_BUILD -nologo -I.. -Ox -wd4033 -wd4716" $(PROGRAM)
|
||||
-del $(DISTNAME)-win32.zip
|
||||
zip $(DISTNAME)-win32.zip $(PROGRAM).exe README.TXT LICENSE.TXT
|
||||
646
xrogue/README.TXT
Normal file
646
xrogue/README.TXT
Normal file
|
|
@ -0,0 +1,646 @@
|
|||
Welcome to XRogue
|
||||
http://roguelike.sourceforge.net/xrogue
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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.
|
||||
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
---------------------------------------------
|
||||
|
||||
Introduction:
|
||||
|
||||
Rogue was introduced at the University of California at Berkeley as a
|
||||
screen-oriented fantasy game. The game had 26 types of monsters that
|
||||
the player could meet while exploring a Dungeon generated by the computer.
|
||||
Scrolls, potions, rings, wands, staves, armor, and weapons helped the
|
||||
player to battle these monsters and to gain gold, the basis for scoring.
|
||||
|
||||
The version of rogue described in this guide has been expanded to include
|
||||
over 200 monsters with many new capabilities and has been renamed xrogue.
|
||||
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. There are also a
|
||||
number of new commands in this version not found in previous versions.
|
||||
|
||||
The game contains monsters, spells, weapons, armor, potions, and other
|
||||
magical items that you will discover during your quest. The Dungeon's
|
||||
geography changes with every game and although many magical items have
|
||||
certain identifiable properties, such as turning the player invisible,
|
||||
the physical manifestation of the magic changes each game. A red potion,
|
||||
for example, will cause the same reaction throughout a given game but
|
||||
it may be a completely different potion in a new game.
|
||||
|
||||
Entering the Dungeon with only a little food, armor, and a weapon, the
|
||||
player must develop a good strategy of when to fight, when to run, and
|
||||
how to best use any magical item found in the Dungeon. To make things
|
||||
interesting the player has a quest to return one of several unique and
|
||||
magical artifacts which are rumored to lie deep within the Dungeon.
|
||||
Returning with this artifact to the surface brings great honor.
|
||||
|
||||
However, after finding the artifact, the player may wish to continue
|
||||
his quest deeper into the Dungeon to match wits with an arch-devil, a
|
||||
demon-prince, or perhaps Charon the Boatman. Defeating such a creature
|
||||
will gain the player many experience points which is the basis for
|
||||
scoring in xrogue. It is very difficult to return from the Dungeons
|
||||
of Doom alive. Very few players have won this game.
|
||||
|
||||
Character Classes:
|
||||
|
||||
Before placing the player in the Dungeon, the game requests that you
|
||||
select what type of character they would like to be: Fighter, Paladin,
|
||||
Ranger, Magic-User, Cleric, Thief, Assassin, Druid, or Monk.
|
||||
|
||||
The Fighter
|
||||
|
||||
A Fighter has the best odds at winning battles with monsters. At high
|
||||
experience levels, the Fighter is able to attack his opponent multiple
|
||||
times in a single turn. Strength is the main attribute of the Fighter.
|
||||
|
||||
The Magic-User
|
||||
|
||||
A Magic-User is able to cast spells. Intelligence is the main attribute.
|
||||
The number of spells a Magic-User can cast increases as he gains in
|
||||
experience points and in intelligence. His spell casting ability allows
|
||||
him to identify any item in the Dungeon. 16 spells.
|
||||
|
||||
The Cleric
|
||||
|
||||
A Cleric is able to pray for assistance in battle. Wisdom is the main
|
||||
attribute. The number of prayers granted to the Cleric increases as he
|
||||
gains in experience points and in wisdom. Clerics can affect (turn) the
|
||||
undead monsters to avoid battle. Ie., zombies, ghouls, etc. If the
|
||||
Cleric is very powerful relative to the undead monster, turning it will
|
||||
utterly destroy it. 16 prayers.
|
||||
|
||||
The Paladin
|
||||
|
||||
A Paladin is a type of holy warrior, being a cross between a Cleric
|
||||
and a Fighter. He is able to pray and affect the undead like the Cleric
|
||||
and fight like the Fighter, but both to a lesser extent. He is on the
|
||||
side of all that is righteous and good and would never attack a monster
|
||||
that has not attacked him first. If he happens to kill such a monster,
|
||||
inadvertantly or otherwise, he will begin to feel increasingly uneasy.
|
||||
If he kills too many such monsters, he will face karmic retaliation and
|
||||
be reduced to a mere Fighter, minus all of the Cleric's ability.
|
||||
Charisma is the main attribute with Wisdom second.
|
||||
|
||||
The Ranger
|
||||
|
||||
A Ranger is a type of mystical warrior, being a cross between the
|
||||
Magic-User and Fighter. Like the Paladin, he is on the side of all
|
||||
that is righteous and good and would never attack a monster that
|
||||
has not attacked him first. A Ranger is able to cast spells like the
|
||||
Magic-User and fight like the Fighter, but both to a lesser extent.
|
||||
Charisma is the main attribute with Intelligence second.
|
||||
|
||||
The Thief
|
||||
|
||||
A Thief is exceptionally dexterous and has great skill at being able
|
||||
to set a traps for and/or rob (steal) items from monsters. Thieves have
|
||||
the ability to detect all the gold and hidden traps on each level of
|
||||
the Dungeon. Their dexterous nature gives Thieves the ability to move
|
||||
very quietly, so they are not as likely as to wake up sleeping monsters
|
||||
as are the other character types. If a Thief manages to sneak up on a
|
||||
creature without waking it he may be able to backstab the monster. The
|
||||
damage from a backstab is greatly increased based upon the experience
|
||||
level. Dexterity is the main attribute.
|
||||
|
||||
The Assassin
|
||||
|
||||
An Assassin is a person trained in the art of killing monsters by
|
||||
surprise. He has some of the abilities of the Thief, but he cannot
|
||||
sense traps or backstab. Instead, the Assassin has the chance to kill
|
||||
an opponent outright with one deadly blow. He can recognize and use
|
||||
poison found in the Dungeon on his weapon, thereby, making his next
|
||||
attack exceptionally lethal. Dexterity is the main attribute.
|
||||
|
||||
The Druid
|
||||
|
||||
A Druid is a type of magical warrior, being a cross between the Cleric
|
||||
and the Magic-User. A Druid can chant both spells and prayers plus a
|
||||
few of his own. The number of chants available to the Druid increases
|
||||
as he gains in experience points and in Wisdom. Wisdom is the main
|
||||
attribute. 16 chants.
|
||||
|
||||
The Monk
|
||||
|
||||
A Monk is trained in the martial arts. He wears no armor and does not
|
||||
need a weapon (although using them is not forbidden). As the Monk gains
|
||||
in experience points his natural defense or ability to dodge attackers
|
||||
increases. The Mong is a cross between the Druid and Fighter, so he
|
||||
can chant and also fight like the Fighter, but both to a lesser extent.
|
||||
Constitution is the main attribute, with wisdom second.
|
||||
|
||||
Attributes Of The Charaters:
|
||||
|
||||
Strength - The primary attribute for encumberance.
|
||||
|
||||
Intelligence - The primary attribute for casting spells.
|
||||
|
||||
Wisdom - The primary attribute for prayers and chanting.
|
||||
|
||||
Dexterity - The primary attribute for stealthiness.
|
||||
|
||||
Charisma - The primary attribute for good will. High Charisma also
|
||||
affects the cost of objects when making transactions.
|
||||
|
||||
Constitution - The primary attribute for health. High Constitution
|
||||
affects the amount of hit points you receive when
|
||||
moving up in experience levels.
|
||||
|
||||
Note: The Ranger, Paladin, and Monk do not receive their "special"
|
||||
magical abilities until they have advanced a few experience levels.
|
||||
|
||||
Experience Levels:
|
||||
|
||||
Characters gain experience points mostly from killing monsters. Other
|
||||
actions, such as stealing items from monsters, backstabbing, and turning
|
||||
monsters, also add extra experience points. Each character type gains
|
||||
experience points and moves up in experience levels at different rates.
|
||||
Moving up in experience levels adds extra hit points to the character
|
||||
which determines how many "hits" he can take before being killed.
|
||||
|
||||
Allocating Attribute Points To The Characters:
|
||||
|
||||
A player starts with 75 attribute points to distribute in to the character
|
||||
he has chosen to play. When you are prompted to distribute the attribute
|
||||
points, the screen displays the minimum and maximum allowable values for
|
||||
that particular attribute. The player can type a backspace (Ctrl-H) to go
|
||||
back and change a previous value and typing an escape (ESC) sets all the
|
||||
remaining attributes to the maximum value possible, given the number of
|
||||
remaining attribute points to be distributed.
|
||||
|
||||
THE SCREEN
|
||||
|
||||
During the normal course of play, the screen consists of three separate
|
||||
sections: the top line, the bottom two lines, and the remaining screen
|
||||
in the middle. The top line reports actions which occur during the game,
|
||||
the middle section depicts the Dungeon, and the bottom two lines describe
|
||||
the player's current condition.
|
||||
|
||||
Whenever anything happens to the player, such as finding a scroll, hitting
|
||||
a monster, or being hit by a monster, a short report appears on the top
|
||||
line of the screen. When you see the word 'More' on the top line, that
|
||||
means you must press the space key to continue.
|
||||
|
||||
The following items may be found within the Dungeon. Some of them have
|
||||
more than one interpretation, depending upon whether your character
|
||||
recognizes them or not.
|
||||
|
||||
| A wall of a room.
|
||||
- A wall of a room.
|
||||
* A pile of gold.
|
||||
% A way to another level.
|
||||
+ A doorway.
|
||||
. The floor in a room.
|
||||
# The floor in a passageway.
|
||||
Solid rock (denoted by a space).
|
||||
^ The entrance to a Trading Post
|
||||
@ The player.
|
||||
_ The player, when invisible.
|
||||
: Some food.
|
||||
! A flask containing a potion.
|
||||
? A sealed scroll.
|
||||
= A ring.
|
||||
) A weapon.
|
||||
] Some armor.
|
||||
; A miscellaneous magic item
|
||||
, An artifact
|
||||
/ A wand or a staff.
|
||||
> A trapdoor leading to the next level
|
||||
{ An arrow trap
|
||||
$ A sleeping gas trap
|
||||
} A beartrap
|
||||
~ A trap that teleports you somewhere else
|
||||
` A poison dart trap
|
||||
" A shimmering magic pool
|
||||
' An entrance to a maze
|
||||
$ Any magical item. (During magic detection)
|
||||
> A blessed magical item. (During magic detection)
|
||||
< A cursed magical item. (During magic detection)
|
||||
|
||||
Monsters are depicted as letters of the alphabet. Note that all letters
|
||||
denote multiple monsters, depending on which level of the Dungeon you are
|
||||
on. The player may identify a current monster by using the identify
|
||||
command ('/') or the clarify command ('=').
|
||||
|
||||
The bottom two lines of the screen describe the player's current status.
|
||||
The first line gives the player's characteristics:
|
||||
|
||||
Intelligence, Strength, Wisdom, Dexterity, Charisma, and Constitution
|
||||
all have a normal maximum value of 50 points, but they can go higher if
|
||||
augmented by a ring. Encumberance is a measurement of how much the player
|
||||
can carry versus how much he is currently carrying. The more you carry
|
||||
relative to your maximum encumberance causes you to use more food. The
|
||||
attribute of Strength fortifies one's encumberance.
|
||||
|
||||
The player's current number of hit points are denoted as (Hp) and it is
|
||||
followed in parentheses by the player's current maximum hit points. Hit
|
||||
points express the player's survivability. As a player heals by resting,
|
||||
using potions, or spells, the player's current hit points gradually increase
|
||||
until they reach the current maximum. This maximum number will be increased
|
||||
each time a player goes up an experience level. If the player's current hit
|
||||
points reach 0, the player becomes "metabolically challenged".
|
||||
|
||||
The player's armor class is denoted as (Ac). This number describes the
|
||||
amount of protection provided by the armor, cloaks, and/or rings currently
|
||||
worn by the player. It is also affected by high or low dexterity. Wearing
|
||||
no armor is equivalent to an armor class of 10 (Monk excepted). The lower
|
||||
the armor class number, the better.
|
||||
|
||||
The player's current experience level is denoted as (Exp), followed by
|
||||
the player's experience points. A new experience level brings extra hit
|
||||
points and possibly added abilities, such as new spells for a Magic-user,
|
||||
new prayers for a Cleric, and new chants for a Druid. There are a total
|
||||
of 26 experience levels per character.
|
||||
|
||||
Commands:
|
||||
|
||||
A player can invoke most commands by typing in a single character.
|
||||
Some commands, however, require a direction, in which case the player
|
||||
types the command character followed by a directional letter. Many
|
||||
commands can be prefaced by a number, indicating how many times the
|
||||
command should be executed.
|
||||
|
||||
When the player invokes a command referring to an item in the player's
|
||||
pack (such as reading a scroll), the game prompts for the item. The
|
||||
player can then type the letter associated with the item. Typing a '*'
|
||||
will produce a list of eligible items.
|
||||
|
||||
A list of basic games commands:
|
||||
|
||||
? Preceding a command by a '?' produces a brief explanation of the
|
||||
command. The command '?*' gives an explanation of all the commands.
|
||||
A '?@' gives information on things you encounter (rock, forest, etc).
|
||||
/ Preceding a symbol by a '/' identifies the symbol.
|
||||
= Clarify. After typing an '=' sign, the player can use the movement
|
||||
keys to position the cursor anywhere on the current level. As long
|
||||
as the player can normally see the selected position, the game will
|
||||
identify whatever is there.
|
||||
h Move one position to the left.
|
||||
j Move one position down.
|
||||
k Move one position up.
|
||||
l Move one position to the right.
|
||||
y Move one position to the top left.
|
||||
u Move one position to the top right.
|
||||
b Move one position to the bottom left.
|
||||
n Move one position to the bottom right.
|
||||
H Run to the left until reaching something interesting.
|
||||
J Run down until reaching something interesting.
|
||||
K Run up until reaching something interesting.
|
||||
L Run to the right until reaching something interesting.
|
||||
Y Run to the top left until reaching something interesting.
|
||||
U Run to the top right until reaching something interesting.
|
||||
B Run to the bottom left until reaching something interesting.
|
||||
N Run to the bottom right until reaching something interesting.
|
||||
|
||||
> Go down the stairs to the next level or enter the outer region if you
|
||||
are standing upon the wormhole trap (must be "flying" for this to work).
|
||||
< Go up the stairs to the next level or enter the outer region if you are
|
||||
standing upon the wormhole trap (must be "flying" for this to work).
|
||||
|
||||
* Count the gold in the player's pack.
|
||||
! Escape to the shell level.
|
||||
$ Price an item at the Trading Post.
|
||||
# Buy an item at the Trading Post.
|
||||
% Sell an item at the Trading Post.
|
||||
. This command (a period) causes the player to rest one turn.
|
||||
^ This command sets traps and is limited to Thieves and Assassins. If the
|
||||
command is successful the game will ask the player for the trap type and
|
||||
sets it where the player is standing.
|
||||
a Affect the undead. This command is restricted to Clerics and Paladins
|
||||
and must be followed by a directional letter.
|
||||
A Choose your quest item (at game startup only!).
|
||||
c This command is restricted to Druids and Monks and it produces a list of
|
||||
available chants. The player can select one of the displayed chants and
|
||||
if the player's energy level is sufficiently high, "chant" it. The more
|
||||
complicated the spell, the more energy it will take.
|
||||
C This command is restricted to Magic-Users and Rangers and it produces a
|
||||
list of available 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 will take.
|
||||
d Drop an item from the player's pack.
|
||||
D Dip something into a magic pool.
|
||||
e Eat some food from the player's pack.
|
||||
f When this command is preceded with a directional command, the player will
|
||||
move in the specified direction until he crosses something interesting.
|
||||
F Frighten a monster. Not available to all characters. This command
|
||||
loses it's power at around level 10.
|
||||
g Give away or trade a slime-mold for food with a monster.
|
||||
G This command is restricted to Thieves and Assassins. It causes the game
|
||||
to display all of the gold on the current level.
|
||||
i Display an inventory of the player's pack.
|
||||
I This command prompts for an item from the player's pack and displays
|
||||
the inventory information for that item.
|
||||
m When the player types this command, you are prompted to mark an item
|
||||
with a one-line name.
|
||||
o Typing this command causes the game to display all the settable options.
|
||||
The player can then examine them or change (some of) them
|
||||
O Display your current character type and quest item.
|
||||
p This command is restricted to Clerics and Paladins and it produces a
|
||||
list of available prayers. The player can then select one of the
|
||||
displayed prayers and if the player's energy level is sufficiently high,
|
||||
"pray" it. The more complicated the prayer, the more energy it will
|
||||
take.
|
||||
P Pick up the items currently under the player.
|
||||
q Quaff a potion from the player's pack.
|
||||
Q Quit without saving the game.
|
||||
r Read a scroll from the player's pack.
|
||||
s Search for a secret door or a trap in the circle surrounding the player.
|
||||
S Save your game to play at a later time.
|
||||
t This command prompts for an object from the players pack. The player
|
||||
then can throw the object in the specified direction.
|
||||
T Take off whatever the player is wearing.
|
||||
v Print the current xrogue version number.
|
||||
w Wield a weapon from the player's pack.
|
||||
W Wear some armor, ring, or a miscellaneous magic item from the player's
|
||||
pack. The player can wear a maximum of 8 rings.
|
||||
X This command is restricted to Thieves only. It causes the game to
|
||||
display
|
||||
all of the hidden traps on the current level.
|
||||
z This command prompts for a wand or staff from the player's pack and zaps
|
||||
it in the specified direction.
|
||||
+ Fortune cookie! (Note: if you play xrogue over a modem, typing three
|
||||
consecutive '+' will tell your modem to enter "command" mode. See your
|
||||
modem manual on how to return from this mode).
|
||||
|
||||
Escape Pressing the Escape key will cancel the current command.
|
||||
Ctrl-B Check your current score. Scoring is based on experience points
|
||||
and gold. However, gold is not that important and 10% is hacked
|
||||
off if a player is killed.
|
||||
Ctrl-E Check your current food level. This command is used when you want
|
||||
to see just how much food you have remaining in your stomach. A
|
||||
full stomach is measured to be about 2000(2100). As you play the
|
||||
game, this level drops until you become hungry at about 200(2100).
|
||||
A food level over 2000(2100) makes the character satiated, and a
|
||||
level under 200(2100) makes the character hungry, then weak, and
|
||||
finally fainting. A level of 2000(2100) is the most the character
|
||||
can eat, a full, satisfied stomach!
|
||||
Ctrl-L Redraw the screen.
|
||||
Ctrl-N When the player types this command, the game prompts you to type a
|
||||
one-line name for a monster or for an item in the player's pack
|
||||
To name a monster, position the cursor over the desired monster and
|
||||
rename it.
|
||||
Ctrl-O Display the current "affects" on the player (such as slow, phased,
|
||||
confused, extra sight, flying, dancing, etc.).
|
||||
Ctrl-R Repeat last message displayed on the top line of the screen.
|
||||
Ctrl-T This command is restricted to Thieves and Assassins. It must be
|
||||
followed by a directional letter. If a monster is standing next to
|
||||
the player in the specified direction, the effect is to steal an
|
||||
item from the monster's pack. If successful, the monster does not
|
||||
notice anything, but if the player is unsuccessful, there is a
|
||||
chance
|
||||
the monster will suddenly wake up and attack.
|
||||
Ctrl-U Use a magic item in the player's pack.
|
||||
|
||||
There is no explicit attack command. If a player wishes to do battle with a
|
||||
monster, the player simply moves onto the spot where the monster is
|
||||
standing.
|
||||
Whatever the player is wielding will be used as the player's weapon.
|
||||
|
||||
As the player moves across items, the game automatically picks them up and
|
||||
places them into the player's pack. If there is no room left in the pack,
|
||||
the item is left on the floor. Setting the "pickup" option to "NO" will
|
||||
allow the player to pick up items at will using the 'P' command.
|
||||
|
||||
All actions except for bookkeeping commands, such as taking an inventory,
|
||||
take time. The amount of time varies with the command. Swinging a weapon,
|
||||
for example, takes more time than simply moving; so a monster could move
|
||||
several spaces in the time it takes the player to make one attack. The
|
||||
time it takes to swing a weapon also varies based on the bulk of the weapon,
|
||||
and the time it takes to simply move one space varies with the type of armor
|
||||
worn and the player's level of encumberance. Movement is always faster when
|
||||
the player is "flying".
|
||||
|
||||
Actions also take time and some of them can be disrupted. If the player is
|
||||
casting a spell for example, and gets hit before finishing it, the spell is
|
||||
lost. Similarly, the player might choke if hit while trying to eat. These
|
||||
same rules apply to monsters as well.
|
||||
|
||||
Some of the rooms in the Dungeon possess a natural light source. In most
|
||||
other rooms and in corridors, the player can see only those things within
|
||||
a one-space radius around the player. Dark rooms can be lit with magical
|
||||
light or by fire beetles and other monsters.
|
||||
|
||||
The player can wield only one weapon at a time. When a player attacks
|
||||
a monster, the amount of damage depends on the particular weapon he is
|
||||
wielding. To fire a projectile weapon, such as a crossbow or a short bow,
|
||||
the player should wield the bow and throw the bolt or arrow at the monster.
|
||||
|
||||
A weapon may be cursed or blessed which will affect the likelihood of you
|
||||
hitting a monster with it and the damage that it will inflict on the
|
||||
monster.
|
||||
If the player has identified the weapon he is using, the "to hit" and the
|
||||
"to damage" bonuses appear (in that order) before the weapons name in the
|
||||
inventory listing. A positive bonus indicates a blessed weapon, and a
|
||||
negative bonus usually indicates a cursed or misguided weapon. A player
|
||||
cannot release a cursed weapon until a remove curse scroll is read or cast
|
||||
by magical means.
|
||||
|
||||
After the player has identified a suit of armor, the protection bonus
|
||||
appears
|
||||
before the armors name in the inventory listing. If the bonus is positive
|
||||
the armor is blessed but if it is negative, the armor is probably cursed.
|
||||
The player cannot remove a cursed suit of armor until a remove curse scroll
|
||||
is read or cast by magical means.
|
||||
|
||||
Some monsters can corrode your armor! If such a monster hits a player
|
||||
when the player is wearing metal armor, the armor will lose some of its
|
||||
protective value. This same corrosive property also applies to weapons
|
||||
when a player hits a monster with this ability. Search for a scroll of
|
||||
"protection" to guard against corrosion of your armor and weapon.
|
||||
|
||||
A player will find many potions and scrolls in the Dungeon. Reading a
|
||||
scroll or quaffing a potion will usually cause some magical occurrence.
|
||||
Potions and scrolls may be either cursed or blessed. In this version of
|
||||
xrogue, Monster Confusion scrolls will turn your hands a variety of colors.
|
||||
A blessed Magic Mapping scroll shows very detailed maps. A scroll of
|
||||
Genocide works within the dungeon as well as in the outer region. A
|
||||
scroll of blessed Teleportation will teleport you "upward" a few levels.
|
||||
Blessed Remove Curse will cause certain monsters to panic if the scroll
|
||||
is read near them. Charm Monster will let you charm several monsters.
|
||||
|
||||
The player can wear a maximum of eight rings. Some of them 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. Rings
|
||||
can be cursed or blessed and the player cannot remove a cursed ring until
|
||||
a remove curse scroll is read or cast.
|
||||
|
||||
Wands, rods, and staves help a player in battle and affect the Dungeon.
|
||||
A player uses the "z" (zap) command to use a wand either to shoot at a
|
||||
monster, teleport, or to light up a dark room. Wands can be cursed or
|
||||
blessed.
|
||||
|
||||
A player must be frugal with his food. Both moving and searching through
|
||||
the Dungeon, and fighting monsters, consumes energy. Starving results in
|
||||
the player's fainting for increasingly longer periods of time, during which
|
||||
any nearby monster can attack the player at will. Food comes in the form
|
||||
of standard rations and as a variety of berries. Some berries have side
|
||||
effects in addition to satisfying one's hunger. Slime-Molds are monster
|
||||
food and if you have one, you may be able to trade it for a regular food
|
||||
ration, if the monster is of "friendly" persuasion.
|
||||
|
||||
Gold has a couple of uses in the Dungeon. The first use of gold is to buy
|
||||
things, either at a Trading Post or from a Quartermaster. The Trading Post
|
||||
when found, is entered via the '>' command, like going down a stairway.
|
||||
A Quartermaster ('q') is a Dungeon vendor who appears at certain times and
|
||||
will try to sell the player some of his wares. The Quartermaster's wares
|
||||
are never cursed but they can be blessed, though blessed goods do cost more
|
||||
than normal goods. If the player chooses to buy something offered by a
|
||||
Quartermaster, he will make the transaction for the specified amount of gold
|
||||
and then disappear. Attacking a Quartermaster causes him to vanish in
|
||||
haste! You can sometimes find gold at the bottom of "magic pools". Use
|
||||
the ">" command to dive for the gold, but be careful you don't drown!
|
||||
|
||||
When beginning a new game, a player is placed in the Trading Post with
|
||||
an allotment of gold based upon the type of character chosen to play.
|
||||
There are some restrictions on the use of certain items by character.
|
||||
For example, only Fighters, Paladins, and Rangers can wield two-handed
|
||||
swords while Thieves and Assassins can not wear certain types of armor.
|
||||
However, the Trading Post (and Quartermaster) will happily sell a player
|
||||
anything that he can afford, whether you need it or not.
|
||||
|
||||
Miscellaneous magical items such as a Pair of Boots or a Book are numerous
|
||||
within the Dungeon. These items are usually used to a 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, Beaker, or Ointment.
|
||||
The Medicine Crystal will heal you, remove all curses, heal you, and may
|
||||
cause panic in some monsters.
|
||||
|
||||
There are a number of unique monsters deep within the depths of the Dungeon
|
||||
that carry very special magical items or artifacts. When you begin the
|
||||
game,
|
||||
you are asked to choose a "quest item" to retrieve from the Dungeon. Most
|
||||
of these items can be used to the player's advantage, even if they are not
|
||||
one's own personal quest item during the game. However, care must be taken
|
||||
when handling some of them for they have intelligence and some will reject
|
||||
mishandling or abuse. These items consume your food (and your gold) so
|
||||
carrying them around results in increased food use. Some of these items
|
||||
will
|
||||
kill you outright if you happen to pick them up while wielding another
|
||||
artifact as your weapon. Don't be too greedy with the artifacts! Quest
|
||||
items begin appearing in xrogue between levels 40-50. The less traumatic
|
||||
quest items appear earlier while the more severe ones appear later. Once
|
||||
a unique monster is killed, you will not encounter another one like it in
|
||||
the Dungeon.
|
||||
|
||||
A variety of traps exist within the Dungeon, including trap doors, bear
|
||||
traps, and sleeping traps. Sometimes they are hidden from sight until
|
||||
sprung by a monster or by the player. A sprung trap continues to function,
|
||||
but since it is visible, an intelligent monster is not likely to tread on
|
||||
it.
|
||||
A trap called the Wormhole trap, will transport you to the "outer region"
|
||||
of the dungeon. There you will fight strange dinosaurs until you can make
|
||||
your way back to a starwell, and promptly return from whence you came.
|
||||
|
||||
Each monster except for the 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 will
|
||||
vary however, in strength and intelligence. For example, one kobold may
|
||||
be much more difficult to kill off than another. In general, the more
|
||||
difficult it is to kill a monster, the more experience points the monster
|
||||
is worth.
|
||||
|
||||
Most monsters attack by biting and clawing, but some monsters carry weapons
|
||||
and can use their breath as a weapon. Some monsters can even use magical
|
||||
items, such as wands and artifacts. Monsters with distance weapons or magic
|
||||
can sometimes attack a player from across a room or from down a corridor.
|
||||
|
||||
Some monsters are more intelligent than others, and the more intelligent
|
||||
a monster is, the more likely it will run away if it is about to die.
|
||||
A fleeing monster will not attack the player unless it is cornered.
|
||||
|
||||
It is sometimes possible to enlist a monster's aid. Reading a charm monster
|
||||
scroll, for example, or singing a charm monster chants can make a monster
|
||||
believe that the player is its friend. A charmed monster will fight hostile
|
||||
monsters for the player as long as they are not of its own race. Be sure
|
||||
your charmed monsters are in the same room with you when you enter the next
|
||||
level, or they will be lost.
|
||||
|
||||
Options:
|
||||
|
||||
The game has several options, some of which can only be set by the player
|
||||
at the beginning of the game and others during the course of play.
|
||||
|
||||
default - Play the character with "default" attribute settings.
|
||||
terse - Shorten messages at top of screen.
|
||||
jump - Speed up the display of the player's movement
|
||||
step - Lists all inventories one line at a time.
|
||||
overlay - Allows listings of inventories to overlay the currnt screen.
|
||||
flush - Supposed to flush all typed-ahead characters.
|
||||
askme - Prompt the player to name new types of scrolls, potions,
|
||||
etc.
|
||||
pickup - Pick up items automatically as you move across them
|
||||
name - The player's name.
|
||||
file - Saved game filename. Defaults to xrogue.sav.
|
||||
score - Identifies the location of the game scorefile.
|
||||
type - Specifies the character type (unchangable).
|
||||
quested item - Set at start up (unchangeable).
|
||||
|
||||
A player can set the game options at the beginning of a game via the
|
||||
ROGUEOPTS environment variable.
|
||||
|
||||
Some examples:
|
||||
|
||||
ROGUEOPTS="default nopickup, nooverlay, name=Corwin, class=magician"
|
||||
ROGUEOPTS="pickup, overlay, file=xrg.sav, score=/home/games/scorefile"
|
||||
|
||||
The player may change an option at any time during the game via the 'o'
|
||||
(option) command. On the options menu, typing a new value changes the
|
||||
option and a RETURN moves to the next option in the list. Typing an '-'
|
||||
moves you to the previous option and an ESCAPE returns you to the Dungeon.
|
||||
|
||||
A new option called "default" was added in xrogue. When you put the word
|
||||
"default" into your ROGUEOPTS environment variable your character will be
|
||||
created with "default" attribute settings, armor, weapon, quest item, and
|
||||
some food.
|
||||
|
||||
Setting "default" will force the game to skip over the beginning screen
|
||||
where you can choose/distribute your attribute points and it also skips
|
||||
over the beginning "equippage screen" where you can choose your armor,
|
||||
weapon, quest item, and etc.
|
||||
|
||||
If you use the "class" option with "default" in ROGUEOPTS, you will
|
||||
start the game immediately at level 1 with the default selections
|
||||
for your character.
|
||||
|
||||
Here is a list of the main and secondary attributes, special ability,
|
||||
and quest item ("default" settings) for each character type:
|
||||
|
||||
Character Main Attr. Secondary Specialties Def. Quest Item
|
||||
-------------------------------------------------------------------------
|
||||
Fighter strength constitution sense gold Axe of Aklad
|
||||
Ranger charisma intelligence cast spells Mandolin of Brian
|
||||
Paladin charisma wisdom affect undead Ankh of Heil
|
||||
Cleric wisdom dexterity prayer spells Horn of Geryon
|
||||
Magician intelligence dexterity cast spells Stonebones Amulet
|
||||
Thief dexterity strength sense traps Musty Daggers
|
||||
Assassin dexterity strength steal/use poison Eye of Vecna
|
||||
Druid wisdom dexterity chant spells Quill of Nagrom
|
||||
Monk constitution dexterity chant spells Emori Cloak
|
||||
|
||||
A different quest item may be chosen ONLY while you are in the beginning
|
||||
Trading Post (if you have NOT set the "default" option via ROGUEOPTS).
|
||||
|
||||
When a player is killed, his score will be equal to the amount of his
|
||||
experience points gained, plus his gold (minus 10%). A player that
|
||||
quits the game will not lose 10% of his gold. If a player makes it back
|
||||
up and out of the Dungeon alive, his score will be equal to the amount
|
||||
of experience points, plus the gold, plus additional gold received from
|
||||
selling all of the items in his pack.
|
||||
|
||||
The game maintains a top-twenty player scorefile. As an installation
|
||||
option, the game may be compiled so as to record only three entries per
|
||||
character type and name.
|
||||
1074
xrogue/actions.c
Normal file
1074
xrogue/actions.c
Normal file
File diff suppressed because it is too large
Load diff
401
xrogue/bolt.c
Normal file
401
xrogue/bolt.c
Normal file
|
|
@ -0,0 +1,401 @@
|
|||
/*
|
||||
bolt.c - functions shooting an object across the room
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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"
|
||||
|
||||
/*
|
||||
* shoot_bolt fires a bolt from the given starting point in the
|
||||
* given direction
|
||||
*/
|
||||
|
||||
shoot_bolt(shooter, start, dir, get_points, reason, name, damage)
|
||||
struct thing *shooter;
|
||||
coord start, dir;
|
||||
bool get_points;
|
||||
short reason;
|
||||
char *name;
|
||||
int damage;
|
||||
{
|
||||
unsigned char dirch = 0, ch;
|
||||
bool used, change, see_him;
|
||||
short y, x, bounces;
|
||||
coord pos;
|
||||
struct linked_list *target=NULL;
|
||||
struct {
|
||||
coord place;
|
||||
char oldch;
|
||||
} spotpos[BOLT_LENGTH];
|
||||
|
||||
switch (dir.y + dir.x) {
|
||||
case 0: dirch = '/';
|
||||
when 1: case -1: dirch = (dir.y == 0 ? '-' : '|');
|
||||
when 2: case -2: dirch = '\\';
|
||||
}
|
||||
pos.y = start.y + dir.y;
|
||||
pos.x = start.x + dir.x;
|
||||
used = FALSE;
|
||||
change = FALSE;
|
||||
|
||||
bounces = 0; /* No bounces yet */
|
||||
nofont(cw);
|
||||
for (y = 0; y < BOLT_LENGTH && !used; y++) {
|
||||
ch = winat(pos.y, pos.x);
|
||||
spotpos[y].place = pos;
|
||||
spotpos[y].oldch = mvwinch(cw, pos.y, pos.x);
|
||||
|
||||
/* Are we at hero? */
|
||||
if (ce(pos, hero)) goto at_hero;
|
||||
|
||||
switch (ch) {
|
||||
case SECRETDOOR:
|
||||
case VERTWALL:
|
||||
case HORZWALL:
|
||||
case ' ':
|
||||
if (dirch == '-' || dirch == '|') {
|
||||
dir.y = -dir.y;
|
||||
dir.x = -dir.x;
|
||||
}
|
||||
else {
|
||||
unsigned char chx = mvinch(pos.y-dir.y, pos.x),
|
||||
chy = mvinch(pos.y, pos.x-dir.x);
|
||||
bool anychange = FALSE; /* Did we change anthing */
|
||||
|
||||
if (chy == WALL || chy == SECRETDOOR ||
|
||||
chy == HORZWALL || chy == VERTWALL) {
|
||||
dir.y = -dir.y;
|
||||
change ^= TRUE; /* Change at least one direction */
|
||||
anychange = TRUE;
|
||||
}
|
||||
if (chx == WALL || chx == SECRETDOOR ||
|
||||
chx == HORZWALL || chx == VERTWALL) {
|
||||
dir.x = -dir.x;
|
||||
change ^= TRUE; /* Change at least one direction */
|
||||
anychange = TRUE;
|
||||
}
|
||||
|
||||
/* If we didn't make any change, make both changes */
|
||||
if (!anychange) {
|
||||
dir.x = -dir.x;
|
||||
dir.y = -dir.y;
|
||||
}
|
||||
}
|
||||
|
||||
/* Do we change how the bolt looks? */
|
||||
if (change) {
|
||||
change = FALSE;
|
||||
if (dirch == '\\') dirch = '/';
|
||||
else if (dirch == '/') dirch = '\\';
|
||||
}
|
||||
|
||||
y--; /* The bounce doesn't count as using up the bolt */
|
||||
|
||||
/* Make sure we aren't in an infinite bounce */
|
||||
if (++bounces > BOLT_LENGTH) used = TRUE;
|
||||
msg("The %s bounces", name);
|
||||
break;
|
||||
default:
|
||||
if (isalpha(ch)) {
|
||||
register struct linked_list *item;
|
||||
struct thing *tp;
|
||||
register char *mname;
|
||||
bool see_monster = cansee(pos.y, pos.x);
|
||||
|
||||
item = find_mons(unc(pos));
|
||||
assert(item != NULL);
|
||||
tp = THINGPTR(item);
|
||||
mname = monster_name(tp);
|
||||
|
||||
/*
|
||||
* If our prey shot this, let's record the fact that
|
||||
* he can shoot, regardless of whether he hits us.
|
||||
*/
|
||||
if (tp->t_dest != NULL && ce(*tp->t_dest, shooter->t_pos))
|
||||
tp->t_wasshot = TRUE;
|
||||
|
||||
if (!save(VS_BREATH, tp, -(shooter->t_stats.s_lvl/10))) {
|
||||
if (see_monster) {
|
||||
if (on(*tp, ISDISGUISE) &&
|
||||
(tp->t_type != tp->t_disguise)) {
|
||||
msg("Wait! That's a %s!", mname);
|
||||
turn_off(*tp, ISDISGUISE);
|
||||
}
|
||||
|
||||
turn_off(*tp, CANSURPRISE);
|
||||
msg("The %s hits %s", name, prname(mname, FALSE));
|
||||
}
|
||||
|
||||
/* Should we start to chase the shooter? */
|
||||
if (shooter != &player &&
|
||||
shooter != tp &&
|
||||
shooter->t_index != tp->t_index &&
|
||||
(tp->t_dest == NULL || rnd(100) < 25)) {
|
||||
/*
|
||||
* If we're intelligent enough to realize that this
|
||||
* is a friendly monster, we will attack the hero
|
||||
* instead.
|
||||
*/
|
||||
if (on(*shooter, ISFRIENDLY) &&
|
||||
roll(3,6) < tp->t_stats.s_intel)
|
||||
runto(tp, &hero);
|
||||
|
||||
/* Otherwise, let's chase the monster */
|
||||
else runto(tp, &shooter->t_pos);
|
||||
}
|
||||
else if (shooter == &player) {
|
||||
runto(tp, &hero);
|
||||
|
||||
/*
|
||||
* If the player shot a charmed monster, it may
|
||||
* not like being shot at.
|
||||
*/
|
||||
if (on(*tp, ISCHARMED) && save(VS_MAGIC, tp, 0)) {
|
||||
msg("The eyes of %s turn clear.",
|
||||
prname(mname, FALSE));
|
||||
turn_off(*tp, ISCHARMED);
|
||||
mname = monster_name(tp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Let the defender know that the attacker has
|
||||
* missiles!
|
||||
*/
|
||||
if (ce(*tp->t_dest, shooter->t_pos))
|
||||
tp->t_wasshot = TRUE;
|
||||
|
||||
used = TRUE;
|
||||
|
||||
/* Hit the monster -- does it do anything? */
|
||||
if ((EQUAL(name,"ice") && on(*tp, NOCOLD)) ||
|
||||
(EQUAL(name,"flame") && on(*tp, NOFIRE)) ||
|
||||
(EQUAL(name,"acid") && on(*tp, NOACID)) ||
|
||||
(EQUAL(name,"lightning bolt")&& on(*tp,NOBOLT)) ||
|
||||
(EQUAL(name,"nerve gas") &&on(*tp,NOPARALYZE))||
|
||||
(EQUAL(name,"sleeping gas") &&
|
||||
(on(*tp, NOSLEEP) || on(*tp, ISUNDEAD))) ||
|
||||
(EQUAL(name,"slow gas") && on(*tp,NOSLOW)) ||
|
||||
(EQUAL(name,"fear gas") && on(*tp,NOFEAR)) ||
|
||||
(EQUAL(name,"confusion gas") && on(*tp,ISCLEAR)) ||
|
||||
(EQUAL(name,"chlorine gas") && on(*tp,NOGAS))) {
|
||||
if (see_monster)
|
||||
msg("The %s has no effect on %s.",
|
||||
name, prname(mname, FALSE));
|
||||
}
|
||||
|
||||
else {
|
||||
see_him = !invisible(tp);
|
||||
|
||||
/* Did a spell get disrupted? */
|
||||
dsrpt_monster(tp, FALSE, see_him);
|
||||
|
||||
/*
|
||||
* Check for gas with special effects
|
||||
*/
|
||||
if (EQUAL(name, "nerve gas")) {
|
||||
tp->t_no_move = movement(tp) * FREEZETIME;
|
||||
tp->t_action = A_FREEZE;
|
||||
}
|
||||
else if (EQUAL(name, "sleeping gas")) {
|
||||
tp->t_no_move = movement(tp) * SLEEPTIME;
|
||||
tp->t_action = A_FREEZE;
|
||||
}
|
||||
else if (EQUAL(name, "slow gas")) {
|
||||
if (on(*tp, ISHASTE))
|
||||
turn_off(*tp, ISHASTE);
|
||||
else
|
||||
turn_on(*tp, ISSLOW);
|
||||
}
|
||||
else if (EQUAL(name, "fear gas")) {
|
||||
turn_on(*tp, ISFLEE);
|
||||
tp->t_dest = &hero;
|
||||
|
||||
/* It is okay to turn tail */
|
||||
tp->t_oldpos = tp->t_pos;
|
||||
}
|
||||
else if (EQUAL(name, "confusion gas")) {
|
||||
turn_on(*tp, ISHUH);
|
||||
tp->t_dest = &hero;
|
||||
}
|
||||
else if ((EQUAL(name, "lightning bolt")) &&
|
||||
on(*tp, BOLTDIVIDE)) {
|
||||
if (creat_mons(tp, tp->t_index, FALSE)) {
|
||||
if (see_monster)
|
||||
msg("The %s divides %s.",
|
||||
name,prname(mname, FALSE));
|
||||
light(&hero);
|
||||
}
|
||||
else if (see_monster)
|
||||
msg("The %s has no effect on %s.",
|
||||
name, prname(mname, FALSE));
|
||||
}
|
||||
else {
|
||||
if (save(VS_BREATH, tp,
|
||||
-(shooter->t_stats.s_lvl/10)))
|
||||
damage /= 2;
|
||||
|
||||
/* The poor fellow got killed! */
|
||||
if ((tp->t_stats.s_hpt -= damage) <= 0) {
|
||||
if (see_monster)
|
||||
msg("The %s kills %s",
|
||||
name, prname(mname, FALSE));
|
||||
else
|
||||
msg("You hear a faint groan in the distance");
|
||||
/*
|
||||
* Instead of calling killed() here, we
|
||||
* will record that the monster was killed
|
||||
* and call it at the end of the routine,
|
||||
* after we restore what was under the bolt.
|
||||
* We have to do this because in the case
|
||||
* of a bolt that first misses the monster
|
||||
* and then gets it on the bounce. If we
|
||||
* call killed here, the 'missed' space in
|
||||
* spotpos puts the monster back on the
|
||||
* screen
|
||||
*/
|
||||
target = item;
|
||||
}
|
||||
else { /* Not dead, so just scream */
|
||||
if (!see_monster)
|
||||
msg("You hear a scream in the distance");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (isalpha(show(pos.y, pos.x))) {
|
||||
if (see_monster) {
|
||||
if (terse)
|
||||
msg("%s misses", name);
|
||||
else
|
||||
msg("The %s whizzes past %s",
|
||||
name, prname(mname, FALSE));
|
||||
}
|
||||
if (get_points) runto(tp, &hero);
|
||||
}
|
||||
}
|
||||
else if (pos.y == hero.y && pos.x == hero.x) {
|
||||
at_hero: if (!save(VS_BREATH, &player,
|
||||
-(shooter->t_stats.s_lvl/10))){
|
||||
if (terse)
|
||||
msg("The %s hits you", name);
|
||||
else
|
||||
msg("You are hit by the %s", name);
|
||||
used = TRUE;
|
||||
|
||||
/*
|
||||
* The Amulet of Yendor protects against all "breath"
|
||||
*
|
||||
* The following two if statements could be combined
|
||||
* into one, but it makes the compiler barf, so split
|
||||
* it up
|
||||
*/
|
||||
if (cur_relic[YENDOR_AMULET] ||
|
||||
(EQUAL(name,"chlorine gas")&&on(player, NOGAS)) ||
|
||||
(EQUAL(name,"acid")&&on(player, NOACID)) ||
|
||||
(EQUAL(name,"sleeping gas")&&ISWEARING(R_ALERT))){
|
||||
msg("The %s has no effect", name);
|
||||
}
|
||||
else if((EQUAL(name, "flame") && on(player, NOFIRE)) ||
|
||||
(EQUAL(name, "ice") && on(player, NOCOLD)) ||
|
||||
(EQUAL(name,"lightning bolt")&&
|
||||
on(player,NOBOLT)) ||
|
||||
(EQUAL(name,"fear gas")&&ISWEARING(R_HEROISM))){
|
||||
msg("The %s has no effect", name);
|
||||
}
|
||||
|
||||
else {
|
||||
dsrpt_player();
|
||||
|
||||
/*
|
||||
* Check for gas with special effects
|
||||
*/
|
||||
if (EQUAL(name, "nerve gas")) {
|
||||
msg("The nerve gas paralyzes you.");
|
||||
player.t_no_move +=
|
||||
movement(&player) * FREEZETIME;
|
||||
player.t_action = A_FREEZE;
|
||||
}
|
||||
else if (EQUAL(name, "sleeping gas")) {
|
||||
msg("The sleeping gas puts you to sleep.");
|
||||
player.t_no_move +=
|
||||
movement(&player) * SLEEPTIME;
|
||||
player.t_action = A_FREEZE;
|
||||
}
|
||||
else if (EQUAL(name, "confusion gas")) {
|
||||
if (off(player, ISCLEAR)) {
|
||||
if (on(player, ISHUH))
|
||||
lengthen(unconfuse,
|
||||
rnd(20)+HUHDURATION);
|
||||
else {
|
||||
turn_on(player, ISHUH);
|
||||
fuse(unconfuse, (VOID *)NULL,
|
||||
rnd(20)+HUHDURATION, AFTER);
|
||||
msg("The confusion gas has confused you.");
|
||||
}
|
||||
}
|
||||
else msg("You feel dizzy for a moment, but it quickly passes.");
|
||||
}
|
||||
else if (EQUAL(name, "slow gas")) {
|
||||
add_slow();
|
||||
}
|
||||
else if (EQUAL(name, "fear gas")) {
|
||||
turn_on(player, ISFLEE);
|
||||
player.t_dest = &shooter->t_pos;
|
||||
msg("The fear gas terrifies you.");
|
||||
}
|
||||
else {
|
||||
if (EQUAL(name, "acid") &&
|
||||
cur_armor != NULL &&
|
||||
!(cur_armor->o_flags & ISPROT) &&
|
||||
!save(VS_BREATH, &player, -2) &&
|
||||
cur_armor->o_ac < pstats.s_arm+1) {
|
||||
msg("Your armor corrodes from the acid");
|
||||
cur_armor->o_ac++;
|
||||
}
|
||||
if (save(VS_BREATH, &player,
|
||||
-(shooter->t_stats.s_lvl/10)) &&
|
||||
off(player, NOACID))
|
||||
damage /= 2;
|
||||
if ((pstats.s_hpt -= damage) <= 0)
|
||||
death(reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
msg("The %s whizzes by you", name);
|
||||
}
|
||||
|
||||
mvwaddch(cw, pos.y, pos.x, dirch);
|
||||
draw(cw);
|
||||
}
|
||||
|
||||
pos.y += dir.y;
|
||||
pos.x += dir.x;
|
||||
}
|
||||
|
||||
/* Restore what was under the bolt */
|
||||
newfont(cw);
|
||||
for (x = y - 1; x >= 0; x--)
|
||||
mvwaddch(cw, spotpos[x].place.y, spotpos[x].place.x, spotpos[x].oldch);
|
||||
|
||||
/* If we killed something, do so now. This will also blank the monster. */
|
||||
if (target) killed(target, FALSE, get_points, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
936
xrogue/chase.c
Normal file
936
xrogue/chase.c
Normal file
|
|
@ -0,0 +1,936 @@
|
|||
/*
|
||||
chase.c - Code for one object to chase another
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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 <ctype.h>
|
||||
#include <curses.h>
|
||||
#include <limits.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* Canblink checks if the monster can teleport (blink). If so, it will
|
||||
* try to blink the monster next to the player.
|
||||
*/
|
||||
|
||||
bool
|
||||
can_blink(tp)
|
||||
register struct thing *tp;
|
||||
{
|
||||
register int y, x, index=9;
|
||||
coord tryp; /* To hold the coordinates for use in diag_ok */
|
||||
bool spots[9], found_one=FALSE;
|
||||
|
||||
/*
|
||||
* First, can the monster even blink? And if so, there is only a 50%
|
||||
* chance that it will do so. And it won't blink if it is running or
|
||||
* held.
|
||||
*/
|
||||
if (off(*tp, CANBLINK) || (on(*tp, ISHELD)) ||
|
||||
on(*tp, ISFLEE) ||
|
||||
tp->t_action == A_FREEZE ||
|
||||
(rnd(12) < 6)) return(FALSE);
|
||||
|
||||
|
||||
/* Initialize the spots as illegal */
|
||||
do {
|
||||
spots[--index] = FALSE;
|
||||
} while (index > 0);
|
||||
|
||||
/* Find a suitable spot next to the player */
|
||||
for (y=hero.y-1; y<hero.y+2; y++)
|
||||
for (x=hero.x-1; x<hero.x+2; x++, index++) {
|
||||
/* Make sure x coordinate is in range and that we are
|
||||
* not at the player's position
|
||||
*/
|
||||
if (x<0 || x >= cols || index == 4) continue;
|
||||
|
||||
/* Is it OK to move there? */
|
||||
if (step_ok(y, x, NOMONST, tp) &&
|
||||
(!isatrap(mvwinch(cw, y, x)) ||
|
||||
rnd(10) >= tp->t_stats.s_intel ||
|
||||
on(*tp, ISFLY))) {
|
||||
/* OK, we can go here. But don't go there if
|
||||
* monster can't get at player from there
|
||||
*/
|
||||
tryp.y = y;
|
||||
tryp.x = x;
|
||||
if (diag_ok(&tryp, &hero, tp)) {
|
||||
spots[index] = TRUE;
|
||||
found_one = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we found one, go to it */
|
||||
if (found_one) {
|
||||
unsigned char rch; /* What's really where the creatures moves to */
|
||||
|
||||
/* Find a legal spot */
|
||||
while (spots[index=rnd(9)] == FALSE) continue;
|
||||
|
||||
/* Get the coordinates */
|
||||
y = hero.y + (index/3) - 1;
|
||||
x = hero.x + (index % 3) - 1;
|
||||
|
||||
/* Move the monster from the old space */
|
||||
mvwaddch(cw, tp->t_pos.y, tp->t_pos.x, tp->t_oldch);
|
||||
|
||||
/* Move it to the new space */
|
||||
tp->t_oldch = mvwinch(cw, y, x);
|
||||
|
||||
/* Display the creature if our hero can see it */
|
||||
if (cansee(y, x) &&
|
||||
off(*tp, ISINWALL) &&
|
||||
!invisible(tp))
|
||||
mvwaddch(cw, y, x, tp->t_type);
|
||||
|
||||
/* Fix the monster window */
|
||||
mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, ' '); /* Clear old position */
|
||||
mvwaddch(mw, y, x, tp->t_type);
|
||||
|
||||
/* Record the new position */
|
||||
tp->t_pos.y = y;
|
||||
tp->t_pos.x = x;
|
||||
|
||||
/* If the monster is on a trap, trap it */
|
||||
rch = mvinch(y, x);
|
||||
if (isatrap(rch)) {
|
||||
if (cansee(y, x)) tp->t_oldch = rch;
|
||||
be_trapped(tp, &(tp->t_pos));
|
||||
}
|
||||
}
|
||||
|
||||
return(found_one);
|
||||
}
|
||||
|
||||
/*
|
||||
* Can_shoot determines if the monster (er) has a direct line of shot
|
||||
* at the prey (ee). If so, it returns the direction in which to shoot.
|
||||
*/
|
||||
|
||||
int
|
||||
can_shoot(er, ee, shoot_dir)
|
||||
register coord *er, *ee, *shoot_dir;
|
||||
{
|
||||
/*
|
||||
* They must be in the same room or very close (at door)
|
||||
*/
|
||||
if (roomin(er) != roomin(ee) && DISTANCE(er->y,er->x,ee->y,ee->x) > 1)
|
||||
{
|
||||
shoot_dir->x = shoot_dir->y = 0;
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* Do we have a straight shot? */
|
||||
if (!straight_shot(er->y, er->x, ee->y, ee->x, shoot_dir))
|
||||
{
|
||||
shoot_dir->x = shoot_dir->y = 0;
|
||||
return(-2);
|
||||
}
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* chase:
|
||||
* Find the spot for the chaser(er) to move closer to the
|
||||
* chasee(ee). Rer is the room of the chaser, and ree is the
|
||||
* room of the creature being chased (chasee).
|
||||
*/
|
||||
|
||||
chase(tp, ee, rer, ree, flee)
|
||||
register struct thing *tp;
|
||||
register coord *ee;
|
||||
register struct room *rer, *ree;
|
||||
bool flee; /* True if destination (ee) is player and monster is running away
|
||||
* or the player is in a wall and the monster can't get to it
|
||||
*/
|
||||
{
|
||||
int dist, thisdist, monst_dist = INT_MAX;
|
||||
register coord *er = &tp->t_pos;
|
||||
struct thing *prey; /* What we are chasing */
|
||||
coord ch_ret; /* Where chasing takes you */
|
||||
unsigned char ch, mch;
|
||||
bool next_player = FALSE;
|
||||
|
||||
/*
|
||||
* set the distance from the chas(er) to the chas(ee) here and then
|
||||
* we won't have to reset it unless the chas(er) moves (instead of shoots)
|
||||
*/
|
||||
dist = DISTANCE(er->y, er->x, ee->y, ee->x);
|
||||
|
||||
/*
|
||||
* See if our destination is a monster or player. If so, make "prey" point
|
||||
* to it.
|
||||
*/
|
||||
if (ce(hero, *ee)) prey = &player; /* Is it the player? */
|
||||
else if (tp->t_dest && ce(*(tp->t_dest), *ee)) { /* Is it a monster? */
|
||||
struct linked_list *item;
|
||||
|
||||
/* What is the monster we're chasing? */
|
||||
item = find_mons(ee->y, ee->x);
|
||||
if (item != NULL) prey = THINGPTR(item);
|
||||
else prey = NULL;
|
||||
}
|
||||
else prey = NULL;
|
||||
|
||||
/* We will use at least one movement period */
|
||||
tp->t_no_move = movement(tp);
|
||||
if (on(*tp, ISFLY)) /* If the creature is flying, speed it up */
|
||||
tp->t_no_move /= 2;
|
||||
|
||||
/*
|
||||
* If the thing is confused or it can't see the player,
|
||||
* let it move randomly.
|
||||
*/
|
||||
if ((on(*tp, ISHUH) && rnd(10) < 8) ||
|
||||
(prey && on(*prey, ISINVIS) && off(*tp, CANSEE))) { /* invisible prey */
|
||||
/*
|
||||
* get a valid random move
|
||||
*/
|
||||
tp->t_newpos = rndmove(tp);
|
||||
dist = DISTANCE(tp->t_newpos.y, tp->t_newpos.x, ee->y, ee->x);
|
||||
}
|
||||
|
||||
/*
|
||||
* Otherwise, find the empty spot next to the chaser that is
|
||||
* closest to the chasee.
|
||||
*/
|
||||
else {
|
||||
register int ey, ex, x, y;
|
||||
int dist_to_old = INT_MIN; /* Dist from goal to old position */
|
||||
|
||||
/*
|
||||
* This will eventually hold where we move to get closer
|
||||
* If we can't find an empty spot, we stay where we are.
|
||||
*/
|
||||
dist = flee ? 0 : INT_MAX;
|
||||
ch_ret = *er;
|
||||
|
||||
/* Are we at our goal already? */
|
||||
if (!flee && ce(ch_ret, *ee)) {
|
||||
turn_off(*tp, ISRUN); /* So stop running! */
|
||||
return;
|
||||
}
|
||||
|
||||
ey = er->y + 1;
|
||||
ex = er->x + 1;
|
||||
|
||||
/* Check all possible moves */
|
||||
for (x = er->x - 1; x <= ex; x++) {
|
||||
if (x < 0 || x >= cols) /* Don't try off the board */
|
||||
continue;
|
||||
for (y = er->y - 1; y <= ey; y++) {
|
||||
coord tryp;
|
||||
|
||||
if ((y < 1) || (y >= lines - 2)) /* Don't try off the board */
|
||||
continue;
|
||||
|
||||
/* Don't try the player if not going after the player */
|
||||
if ((flee || !ce(hero, *ee) || on(*tp, ISFRIENDLY)) &&
|
||||
x == hero.x && y == hero.y) {
|
||||
next_player = TRUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
tryp.x = x;
|
||||
tryp.y = y;
|
||||
|
||||
/* Is there a monster on this spot closer to our goal?
|
||||
* Don't look in our spot or where we were.
|
||||
*/
|
||||
if (!ce(tryp, *er) && !ce(tryp, tp->t_oldpos) &&
|
||||
isalpha(mch = mvwinch(mw, y, x))) {
|
||||
int test_dist;
|
||||
|
||||
test_dist = DISTANCE(y, x, ee->y, ee->x);
|
||||
if (test_dist <= 25 && /* Let's be fairly close */
|
||||
test_dist < monst_dist) {
|
||||
/* Could we really move there? */
|
||||
mvwaddch(mw, y, x, ' '); /* Temporarily blank monst */
|
||||
if (diag_ok(er, &tryp, tp)) monst_dist = test_dist;
|
||||
mvwaddch(mw, y, x, mch); /* Restore monster */
|
||||
}
|
||||
}
|
||||
|
||||
/* Can we move onto the spot? */
|
||||
if (!diag_ok(er, &tryp, tp)) continue;
|
||||
|
||||
ch = mvwinch(cw, y, x); /* Screen character */
|
||||
|
||||
/*
|
||||
* Stepping on player is NOT okay if we are fleeing.
|
||||
* If we are friendly to the player and there is a monster
|
||||
* in the way that is not of our race, it is okay to move
|
||||
* there.
|
||||
*/
|
||||
if (step_ok(y, x, FIGHTOK, tp) &&
|
||||
(off(*tp, ISFLEE) || ch != PLAYER))
|
||||
{
|
||||
/*
|
||||
* If it is a trap, an intelligent monster may not
|
||||
* step on it (unless our hero is on top!)
|
||||
*/
|
||||
if ((isatrap(ch)) &&
|
||||
(rnd(10) < tp->t_stats.s_intel) &&
|
||||
(!on(*tp, ISFLY)) &&
|
||||
(y != hero.y || x != hero.x))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* OK -- this place counts
|
||||
*/
|
||||
thisdist = DISTANCE(y, x, ee->y, ee->x);
|
||||
|
||||
/* Adjust distance if we are being shot at */
|
||||
if (tp->t_wasshot && tp->t_stats.s_intel > 5 &&
|
||||
prey != NULL) {
|
||||
/* Move out of line of sight */
|
||||
if (straight_shot(tryp.y, tryp.x, ee->y, ee->x, (coord *)NULL)) {
|
||||
if (flee) thisdist -= SHOTPENALTY;
|
||||
else thisdist += SHOTPENALTY;
|
||||
}
|
||||
|
||||
/* But do we want to leave the room? */
|
||||
else if (rer && rer == ree && ch == DOOR)
|
||||
thisdist += DOORPENALTY;
|
||||
}
|
||||
|
||||
/* Don't move to the last position if we can help it
|
||||
* (unless out prey just moved there)
|
||||
*/
|
||||
if (ce(tryp, tp->t_oldpos) && (flee || !ce(tryp, hero)))
|
||||
dist_to_old = thisdist;
|
||||
|
||||
else if ((flee && (thisdist > dist)) ||
|
||||
(!flee && (thisdist < dist)))
|
||||
{
|
||||
ch_ret = tryp;
|
||||
dist = thisdist;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we aren't trying to get the player, but he is in our way,
|
||||
* hit him (unless we have been turned or are friendly). next_player
|
||||
* being TRUE -> we are next to the player but don't want to hit him.
|
||||
*
|
||||
* If we are friendly to the player, following him, and standing next
|
||||
* to him, we will try to help him out in battle.
|
||||
*/
|
||||
if (next_player && off(*tp, WASTURNED)) {
|
||||
if (off(*tp, ISFRIENDLY) &&
|
||||
((flee && ce(ch_ret, *er)) ||
|
||||
(!flee && DISTANCE(er->y, er->x, ee->y, ee->x) < dist)) &&
|
||||
step_ok(tp->t_dest->y, tp->t_dest->x, NOMONST, tp)) {
|
||||
/* Okay to hit player */
|
||||
debug("Switching to hero.");
|
||||
tp->t_newpos = hero;
|
||||
tp->t_action = A_MOVE;
|
||||
return;
|
||||
}
|
||||
else if (on(*tp, ISFRIENDLY) && !flee && ce(*ee, hero)) {
|
||||
/*
|
||||
* Look all around the player. If there is a fightable
|
||||
* creature next to both of us, hit it. Otherwise, if
|
||||
* there is a fightable creature next to the player, try
|
||||
* to move next to it.
|
||||
*/
|
||||
dist = INT_MAX;
|
||||
for (x = hero.x - 1; x <= hero.x + 1; x++) {
|
||||
if (x < 0 || x >= cols) /* Don't try off the board */
|
||||
continue;
|
||||
for (y = hero.y - 1; y <= hero.y + 1; y++) {
|
||||
if ((y < 1) || (y >= lines - 2)) /* Stay on the board */
|
||||
continue;
|
||||
|
||||
/* Is there a fightable monster here? */
|
||||
if (isalpha(mvwinch(mw, y, x)) &&
|
||||
step_ok(y, x, FIGHTOK, tp) &&
|
||||
off(*tp, ISSTONE)) {
|
||||
thisdist = DISTANCE(er->y, er->x, y, x);
|
||||
if (thisdist < dist) {
|
||||
dist = thisdist;
|
||||
ch_ret.y = y;
|
||||
ch_ret.x = x;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Are we next to a bad guy? */
|
||||
if (dist <= 2) { /* Get him! */
|
||||
tp->t_newpos = ch_ret;
|
||||
tp->t_action = A_MOVE;
|
||||
}
|
||||
|
||||
/* Try to move to the bad guy */
|
||||
else if (dist < INT_MAX)
|
||||
chase(tp, &ch_ret,
|
||||
roomin(&tp->t_pos), roomin(&ch_ret), FALSE);
|
||||
|
||||
else tp->t_action = A_NIL;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have decided that we can move onto a monster (we are
|
||||
* friendly to the player, go to it.
|
||||
*/
|
||||
if (!ce(ch_ret, *er) && isalpha(mvwinch(mw, ch_ret.y, ch_ret.x))) {
|
||||
debug("Attack monster");
|
||||
tp->t_newpos = ch_ret;
|
||||
tp->t_action = A_MOVE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we can't get closer to the player (if that's our goal)
|
||||
* because other monsters are in the way, just stay put
|
||||
*/
|
||||
if (!flee && ce(hero, *ee) && monst_dist < INT_MAX &&
|
||||
DISTANCE(er->y, er->x, hero.y, hero.x) < dist) {
|
||||
tp->t_action = A_NIL; /* do nothing for awhile */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Do we want to go back to the last position? */
|
||||
else if (dist_to_old != INT_MIN && /* It is possible to move back */
|
||||
((flee && dist == 0) || /* No other possible moves */
|
||||
(!flee && dist == INT_MAX))) {
|
||||
/* Do we move back or just stay put (default)? */
|
||||
dist = DISTANCE(er->y, er->x, ee->y, ee->x); /* Current distance */
|
||||
if (!flee || (flee && (dist_to_old > dist))) ch_ret = tp->t_oldpos;
|
||||
}
|
||||
|
||||
/* Record the new destination */
|
||||
tp->t_newpos = ch_ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do we want to fight or move? If our selected destination (ch_ret)
|
||||
* is our hero, then we want to fight. Otherwise, we want to move.
|
||||
*/
|
||||
if (ce(tp->t_newpos, hero)) {
|
||||
/* Fight! (or sell) */
|
||||
if (on(*tp, CANSELL)) {
|
||||
tp->t_action = A_SELL;
|
||||
tp->t_no_move += movement(tp); /* takes a little time to sell */
|
||||
}
|
||||
else {
|
||||
tp->t_action = A_ATTACK;
|
||||
|
||||
/*
|
||||
* Try to find a weapon to wield. Wield_weap will return a
|
||||
* projector if weapon is a projectile (eg. bow for arrow).
|
||||
* If weapon is NULL (the case here), it will try to find
|
||||
* a suitable weapon.
|
||||
*
|
||||
* Add in rest of time. Fight is
|
||||
* movement() + weap_move() + FIGHTBASE
|
||||
*/
|
||||
tp->t_using = wield_weap((struct object *)NULL, tp);
|
||||
if (tp->t_using == NULL)
|
||||
tp->t_no_move += weap_move(tp, (struct object *)NULL);
|
||||
else
|
||||
tp->t_no_move += weap_move(tp, OBJPTR(tp->t_using));
|
||||
|
||||
if (on(*tp, ISHASTE))
|
||||
tp->t_no_move += FIGHTBASE/2;
|
||||
else if (on(*tp, ISSLOW))
|
||||
tp->t_no_move += FIGHTBASE*2;
|
||||
else
|
||||
tp->t_no_move += FIGHTBASE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Move */
|
||||
tp->t_action = A_MOVE;
|
||||
|
||||
/*
|
||||
* Check if the creature is not next to the player. If it
|
||||
* is not and has held or suffocated the player, then stop it!
|
||||
* Note that this code should more appropriately appear in
|
||||
* the area that actually moves the monster, but for now it
|
||||
* is okay here because the player can't move while held or
|
||||
* suffocating.
|
||||
*/
|
||||
if (dist > 2) {
|
||||
if (on(*tp, DIDHOLD)) {
|
||||
turn_off(*tp, DIDHOLD);
|
||||
turn_on(*tp, CANHOLD);
|
||||
if (--hold_count == 0)
|
||||
turn_off(player, ISHELD);
|
||||
}
|
||||
|
||||
/* If monster was suffocating, stop it */
|
||||
if (on(*tp, DIDSUFFOCATE)) {
|
||||
turn_off(*tp, DIDSUFFOCATE);
|
||||
turn_on(*tp, CANSUFFOCATE);
|
||||
extinguish(suffocate);
|
||||
msg("You can breathe again.....Whew!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* do_chase:
|
||||
* Make one thing chase another.
|
||||
*/
|
||||
|
||||
do_chase(th)
|
||||
register struct thing *th;
|
||||
{
|
||||
register struct room *orig_rer, /* Original room of chaser */
|
||||
*new_room; /* new room of monster */
|
||||
unsigned char floor, rch, sch;
|
||||
coord old_pos, /* Old position of monster */
|
||||
ch_ret; /* Where we want to go */
|
||||
|
||||
if (on(*th, NOMOVE)) return;
|
||||
|
||||
ch_ret = th->t_newpos; /* Record our desired new position */
|
||||
|
||||
/*
|
||||
* Make sure we have an open spot (no other monster's gotten in our way,
|
||||
* someone didn't just drop a scare monster there, our prey didn't just
|
||||
* get there, etc.)
|
||||
*/
|
||||
if (!step_ok(th->t_newpos.y, th->t_newpos.x, FIGHTOK, th)) {
|
||||
/*
|
||||
* Most monsters get upset now. Guardians are all friends,
|
||||
* and we don't want to see 50 messages in a row!
|
||||
*/
|
||||
if (th->t_stats.s_intel > 4 &&
|
||||
off(*th, ISUNDEAD) &&
|
||||
off(*th, ISGUARDIAN) &&
|
||||
off(*th, AREMANY) &&
|
||||
off(*th, ISHUH) &&
|
||||
off(*th, ISCHARMED) &&
|
||||
off(player, ISBLIND) &&
|
||||
cansee(unc(th->t_pos)) &&
|
||||
!invisible(th) && (rnd(15) < 5)) {
|
||||
switch (rnd(10)) {
|
||||
case 0: case 1:
|
||||
msg("%s lashes out at you! ",prname(monster_name(th),TRUE));
|
||||
when 2: case 3:
|
||||
msg("%s scrambles around. ",prname(monster_name(th), TRUE));
|
||||
otherwise:
|
||||
msg("%s motions angrily. ", prname(monster_name(th), TRUE));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (ce(th->t_newpos, hero) || /* Player just got in our way */
|
||||
isalpha(mvwinch(mw, th->t_newpos.y, th->t_newpos.x))) {
|
||||
bool fightplayer = ce(th->t_newpos, hero);
|
||||
|
||||
/* If we were turned or are friendly, we just have to sit here! */
|
||||
if (fightplayer && (on(*th, WASTURNED) || on(*th, ISFRIENDLY))) return;
|
||||
|
||||
/* Do we want to sell something? */
|
||||
if (fightplayer && on(*th, CANSELL)) {
|
||||
th->t_action = A_SELL;
|
||||
th->t_no_move += movement(th); /* takes a little time to sell */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Let's hit him */
|
||||
th->t_action = A_ATTACK;
|
||||
|
||||
/*
|
||||
* Try to find a weapon to wield. Wield_weap will return a
|
||||
* projector if weapon is a projectile (eg. bow for arrow).
|
||||
* If weapon is NULL (the case here), it will try to find
|
||||
* a suitable weapon.
|
||||
*/
|
||||
th->t_using = wield_weap((struct object *)NULL, th);
|
||||
/*
|
||||
* add in rest of time
|
||||
*/
|
||||
if (th->t_using == NULL)
|
||||
th->t_no_move += weap_move(th, (struct object *)NULL);
|
||||
else
|
||||
th->t_no_move += weap_move(th, OBJPTR(th->t_using));
|
||||
if (on(*th, ISHASTE))
|
||||
th->t_no_move += FIGHTBASE/2;
|
||||
else if (on(*th, ISSLOW))
|
||||
th->t_no_move += FIGHTBASE*2;
|
||||
else
|
||||
th->t_no_move += FIGHTBASE;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Blank out the old position and record the new position --
|
||||
* the blanking must be done first in case the positions are the same.
|
||||
*/
|
||||
mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
|
||||
mvwaddch(mw, ch_ret.y, ch_ret.x, th->t_type);
|
||||
|
||||
/* Get new and old rooms of monster */
|
||||
new_room = roomin(&ch_ret);
|
||||
orig_rer = roomin(&th->t_pos);
|
||||
|
||||
/* Store the critter's old position and update the current one */
|
||||
old_pos = th->t_pos;
|
||||
th->t_pos = ch_ret;
|
||||
floor = (roomin(&ch_ret) == NULL) ? PASSAGE : FLOOR;
|
||||
|
||||
/* If we have a scavenger, it can pick something up */
|
||||
if (off(*th, ISGUARDIAN)) {
|
||||
register struct linked_list *n_item, *o_item;
|
||||
register int item_count = 0;
|
||||
bool want_something = FALSE;
|
||||
|
||||
while ((n_item = find_obj(ch_ret.y, ch_ret.x)) != NULL) {
|
||||
register struct object *n_obj, *o_obj;
|
||||
bool wants_it;
|
||||
|
||||
/* Does this monster want anything? */
|
||||
if (want_something == FALSE) {
|
||||
if (on(*th, ISSCAVENGE) || on(*th, CARRYFOOD) ||
|
||||
on(*th, CARRYGOLD) || on(*th, CARRYSCROLL) ||
|
||||
on(*th, CARRYPOTION) || on(*th, CARRYRING) ||
|
||||
on(*th, CARRYSTICK) || on(*th, CARRYMISC) ||
|
||||
on(*th, CARRYWEAPON) || on(*th, CARRYARMOR) ||
|
||||
on(*th, CARRYDAGGER)) {
|
||||
want_something = TRUE;
|
||||
|
||||
/*
|
||||
* Blank the area. We have to do it only before the
|
||||
* first item in case an item gets dropped in same
|
||||
* place. We don't want to blank it out after it get
|
||||
* dropped.
|
||||
*/
|
||||
mvaddch(ch_ret.y, ch_ret.x, floor);
|
||||
|
||||
/* Were we specifically after something here? */
|
||||
if (ce(*th->t_dest, ch_ret)) {
|
||||
/* If we're mean, we go after the hero */
|
||||
if (on(*th, ISMEAN)) runto(th, &hero);
|
||||
|
||||
/* Otherwise just go back to sleep */
|
||||
else {
|
||||
turn_off(*th, ISRUN);
|
||||
th->t_dest = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
item_count++; /* Count the number of items */
|
||||
|
||||
/*
|
||||
* see if he's got one of this group already
|
||||
*/
|
||||
o_item = NULL;
|
||||
n_obj = OBJPTR(n_item);
|
||||
detach(lvl_obj, n_item);
|
||||
|
||||
/* See if he wants it */
|
||||
if (n_obj->o_type == SCROLL && n_obj->o_which == S_SCARE &&
|
||||
th->t_stats.s_intel < 16)
|
||||
wants_it = FALSE; /* Most monsters don't want a scare monster */
|
||||
else if (on(*th, ISSCAVENGE)) wants_it = TRUE;
|
||||
else {
|
||||
wants_it = FALSE; /* Default case */
|
||||
switch (n_obj->o_type) {
|
||||
case FOOD: if(on(*th, CARRYFOOD)) wants_it = TRUE;
|
||||
when GOLD: if(on(*th, CARRYGOLD)) wants_it = TRUE;
|
||||
when SCROLL:if(on(*th, CARRYSCROLL)) wants_it = TRUE;
|
||||
when POTION:if(on(*th, CARRYPOTION)) wants_it = TRUE;
|
||||
when RING: if(on(*th, CARRYRING)) wants_it = TRUE;
|
||||
when STICK: if(on(*th, CARRYSTICK)) wants_it = TRUE;
|
||||
when MM: if(on(*th, CARRYMISC)) wants_it = TRUE;
|
||||
when ARMOR: if(on(*th, CARRYARMOR)) wants_it = TRUE;
|
||||
when WEAPON:if(on(*th, CARRYWEAPON) ||
|
||||
(on(*th,CARRYDAGGER)&&n_obj->o_which==DAGGER))
|
||||
wants_it = TRUE;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* The quartermaster doesn't sell cursed stuff so he won't
|
||||
* pick it up
|
||||
*/
|
||||
if (on(*th, CANSELL) && (n_obj->o_flags & ISCURSED))
|
||||
wants_it = FALSE;
|
||||
|
||||
/* If he doesn't want it, throw it away */
|
||||
if (wants_it == FALSE) {
|
||||
fall(n_item, FALSE);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Otherwise, let's pick it up */
|
||||
if (n_obj->o_group) {
|
||||
for(o_item = th->t_pack; o_item != NULL; o_item = next(o_item)){
|
||||
o_obj = OBJPTR(o_item);
|
||||
if (o_obj->o_group == n_obj->o_group) {
|
||||
o_obj->o_count += n_obj->o_count;
|
||||
o_discard(n_item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (o_item == NULL) { /* didn't find it */
|
||||
attach(th->t_pack, n_item);
|
||||
}
|
||||
}
|
||||
|
||||
/* If there was anything here, we may have to update the screen */
|
||||
if (item_count) {
|
||||
if (cansee(ch_ret.y, ch_ret.x))
|
||||
mvwaddch(cw, ch_ret.y, ch_ret.x, mvinch(ch_ret.y, ch_ret.x));
|
||||
updpack(TRUE, th); /* Update the monster's encumberance, too */
|
||||
}
|
||||
}
|
||||
|
||||
rch = mvwinch(stdscr, old_pos.y, old_pos.x);
|
||||
if (th->t_oldch == floor && rch != floor && !isatrap(rch))
|
||||
mvwaddch(cw, old_pos.y, old_pos.x, rch);
|
||||
else
|
||||
mvwaddch(cw, old_pos.y, old_pos.x, th->t_oldch);
|
||||
sch = mvwinch(cw, ch_ret.y, ch_ret.x); /* What player sees */
|
||||
rch = mvwinch(stdscr, ch_ret.y, ch_ret.x); /* What's really there */
|
||||
|
||||
/* If we have a tunneling monster, it may be making a tunnel */
|
||||
if (on(*th, CANTUNNEL) &&
|
||||
(rch==SECRETDOOR || rch==WALL || rch==VERTWALL || rch==HORZWALL)) {
|
||||
unsigned char nch; /* The new look to the tunnel */
|
||||
|
||||
if (rch == WALL && levtype == OUTSIDE) nch = FLOOR;
|
||||
else if (rch == WALL) nch = PASSAGE;
|
||||
else if (levtype == MAZELEV || levtype == OUTSIDE) nch = FLOOR;
|
||||
else nch = DOOR;
|
||||
addch(nch);
|
||||
|
||||
if (cansee(ch_ret.y, ch_ret.x)) sch = nch; /* Can player see this? */
|
||||
|
||||
/* Does this make a new exit? */
|
||||
if (rch == VERTWALL || rch == HORZWALL) {
|
||||
struct linked_list *newroom;
|
||||
coord *exit;
|
||||
|
||||
newroom = new_item(sizeof(coord));
|
||||
exit = DOORPTR(newroom);
|
||||
*exit = ch_ret;
|
||||
attach(new_room->r_exit, newroom);
|
||||
}
|
||||
}
|
||||
|
||||
/* Mark if the monster is inside a wall */
|
||||
if (isrock(mvinch(ch_ret.y, ch_ret.x))) turn_on(*th, ISINWALL);
|
||||
else turn_off(*th, ISINWALL);
|
||||
|
||||
/* If the monster can illuminate rooms, check for a change */
|
||||
if (on(*th, HASFIRE)) {
|
||||
register struct linked_list *fire_item;
|
||||
|
||||
/* Is monster entering a room? */
|
||||
if (orig_rer != new_room && new_room != NULL) {
|
||||
fire_item = creat_item(); /* Get an item-only structure */
|
||||
ldata(fire_item) = (char *) th;
|
||||
|
||||
attach(new_room->r_fires, fire_item);
|
||||
new_room->r_flags |= HASFIRE;
|
||||
|
||||
if (cansee(ch_ret.y, ch_ret.x) && next(new_room->r_fires) == NULL)
|
||||
light(&hero);
|
||||
}
|
||||
|
||||
/* Is monster leaving a room? */
|
||||
if (orig_rer != new_room && orig_rer != NULL) {
|
||||
/* Find the bugger in the list and delete him */
|
||||
for (fire_item = orig_rer->r_fires; fire_item != NULL;
|
||||
fire_item = next(fire_item)) {
|
||||
if (THINGPTR(fire_item) == th) { /* Found him! */
|
||||
detach(orig_rer->r_fires, fire_item);
|
||||
destroy_item(fire_item);
|
||||
if (orig_rer->r_fires == NULL) {
|
||||
orig_rer->r_flags &= ~HASFIRE;
|
||||
if (cansee(old_pos.y, old_pos.x))
|
||||
light(&old_pos);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If monster is entering player's room and player can see it,
|
||||
* stop the player's running.
|
||||
*/
|
||||
if (new_room != orig_rer && new_room != NULL &&
|
||||
new_room == roomin(th->t_dest) && cansee(unc(ch_ret)) &&
|
||||
(off(*th, ISINVIS) || on(player, CANSEE)) &&
|
||||
(off(*th, ISSHADOW) || on(player, CANSEE)) &&
|
||||
(off(*th, CANSURPRISE) || ISWEARING(R_ALERT))) {
|
||||
running = FALSE;
|
||||
if (fight_flush) flushinp();
|
||||
}
|
||||
|
||||
th->t_oldch = sch;
|
||||
|
||||
/* Let's display those creatures that we can see. */
|
||||
if (cansee(unc(ch_ret)) &&
|
||||
off(*th, ISINWALL) &&
|
||||
!invisible(th))
|
||||
mvwaddch(cw, ch_ret.y, ch_ret.x, th->t_type);
|
||||
|
||||
/* Record monster's last position (if new one is different) */
|
||||
if (!ce(ch_ret, old_pos)) th->t_oldpos = old_pos;
|
||||
|
||||
/* If the monster is on a trap, trap it */
|
||||
sch = mvinch(ch_ret.y, ch_ret.x);
|
||||
if (isatrap(sch)) {
|
||||
if (cansee(ch_ret.y, ch_ret.x)) th->t_oldch = sch;
|
||||
be_trapped(th, &ch_ret);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get_hurl returns the weapon that the monster will "throw" if he has one
|
||||
*/
|
||||
|
||||
struct linked_list *
|
||||
get_hurl(tp)
|
||||
register struct thing *tp;
|
||||
{
|
||||
struct linked_list *arrow=NULL, *bolt=NULL, *rock=NULL,
|
||||
*spear = NULL, *dagger=NULL, *dart=NULL, *aklad=NULL;
|
||||
register struct linked_list *pitem;
|
||||
register struct object *obj;
|
||||
bool bow=FALSE, crossbow=FALSE, sling=FALSE;
|
||||
|
||||
for (pitem=tp->t_pack; pitem; pitem=next(pitem)) {
|
||||
obj = OBJPTR(pitem);
|
||||
if (obj->o_type == WEAPON)
|
||||
switch (obj->o_which) {
|
||||
case BOW: bow = TRUE;
|
||||
when CROSSBOW: crossbow = TRUE;
|
||||
when SLING: sling = TRUE;
|
||||
when ROCK: rock = pitem;
|
||||
when ARROW: arrow = pitem;
|
||||
when BOLT: bolt = pitem;
|
||||
when SPEAR: spear = pitem;
|
||||
when DAGGER:
|
||||
/* Don't throw the dagger if it's our last one */
|
||||
if (obj->o_count > 1) dagger = pitem;
|
||||
when DART: dart = pitem;
|
||||
}
|
||||
else if (obj->o_type == RELIC &&
|
||||
obj->o_which == AXE_AKLAD)
|
||||
aklad = pitem;
|
||||
}
|
||||
|
||||
/* Do we have that all-powerful Aklad Axe? */
|
||||
if (aklad) return(aklad);
|
||||
|
||||
/* Use crossbow bolt if possible */
|
||||
if (crossbow && bolt) return(bolt);
|
||||
if (bow && arrow) return(arrow);
|
||||
if (spear) return(spear);
|
||||
if (dagger) return(dagger);
|
||||
if (sling && rock) return(rock);
|
||||
if (dart) return(dart);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* runto:
|
||||
* Set a monster running after something
|
||||
*/
|
||||
|
||||
runto(runner, spot)
|
||||
register struct thing *runner;
|
||||
coord *spot;
|
||||
{
|
||||
if (on(*runner, ISSTONE))
|
||||
return;
|
||||
|
||||
/* If we are chasing a new creature, forget about thrown weapons */
|
||||
if (runner->t_dest && !ce(*runner->t_dest, *spot)) runner->t_wasshot=FALSE;
|
||||
|
||||
/*
|
||||
* Start the beastie running
|
||||
*/
|
||||
runner->t_dest = spot;
|
||||
turn_on(*runner, ISRUN);
|
||||
turn_off(*runner, ISDISGUISE);
|
||||
}
|
||||
|
||||
/*
|
||||
* straight_shot:
|
||||
* See if there is a straight line of sight between the two
|
||||
* given coordinates. If shooting is not NULL, it is a pointer
|
||||
* to a structure which should be filled with the direction
|
||||
* to shoot (if there is a line of sight). If shooting, monsters
|
||||
* get in the way. Otherwise, they do not.
|
||||
*/
|
||||
|
||||
bool
|
||||
straight_shot(ery, erx, eey, eex, shooting)
|
||||
register int ery, erx, eey, eex;
|
||||
register coord *shooting;
|
||||
{
|
||||
register int dy, dx; /* Deltas */
|
||||
unsigned char ch;
|
||||
|
||||
/* Does the monster have a straight shot at prey */
|
||||
if ((ery != eey) && (erx != eex) &&
|
||||
(abs(ery - eey) != abs(erx - eex))) return(FALSE);
|
||||
|
||||
/* Get the direction to shoot */
|
||||
if (eey > ery) dy = 1;
|
||||
else if (eey == ery) dy = 0;
|
||||
else dy = -1;
|
||||
|
||||
if (eex > erx) dx = 1;
|
||||
else if (eex == erx) dx = 0;
|
||||
else dx = -1;
|
||||
|
||||
/* Make sure we have free area all the way to the player */
|
||||
ery += dy;
|
||||
erx += dx;
|
||||
while ((ery != eey) || (erx != eex)) {
|
||||
switch (ch = winat(ery, erx)) {
|
||||
case VERTWALL:
|
||||
case HORZWALL:
|
||||
case WALL:
|
||||
case DOOR:
|
||||
case SECRETDOOR:
|
||||
case FOREST:
|
||||
return(FALSE);
|
||||
default:
|
||||
if (shooting && isalpha(ch)) return(FALSE);
|
||||
}
|
||||
ery += dy;
|
||||
erx += dx;
|
||||
}
|
||||
|
||||
if (shooting) { /* If we are shooting -- put in the directions */
|
||||
shooting->y = dy;
|
||||
shooting->x = dx;
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
1305
xrogue/command.c
Normal file
1305
xrogue/command.c
Normal file
File diff suppressed because it is too large
Load diff
264
xrogue/daemon.c
Normal file
264
xrogue/daemon.c
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
/*
|
||||
daemon.c - functions for dealing with things that happen in the future
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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 {
|
||||
int d_type;
|
||||
int (*d_func)();
|
||||
VOID *d_arg;
|
||||
int d_time;
|
||||
} ;
|
||||
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(dfunc, arg, type)
|
||||
reg VOID *arg;
|
||||
reg int type, (*dfunc)();
|
||||
{
|
||||
reg struct delayed_action *dev;
|
||||
|
||||
dev = d_slot();
|
||||
if (dev != NULL) {
|
||||
dev->d_type = type;
|
||||
dev->d_func = dfunc;
|
||||
dev->d_arg = arg;
|
||||
dev->d_time = DAEMON;
|
||||
demoncnt += 1; /* update count */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* kill_daemon:
|
||||
* Remove a daemon from the list
|
||||
*/
|
||||
|
||||
kill_daemon(dfunc)
|
||||
reg int (*dfunc)();
|
||||
{
|
||||
reg struct delayed_action *dev;
|
||||
reg int i;
|
||||
|
||||
for (i = 0, dev = d_list; i < MAXDAEMONS; i++, dev++) {
|
||||
if (dev->d_type != EMPTY && dfunc == 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 = NULL;
|
||||
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;
|
||||
{
|
||||
struct delayed_action *dev;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Loop through the devil list
|
||||
*/
|
||||
for (i = 0; i < MAXDAEMONS; i++)
|
||||
{
|
||||
dev = &d_list[i];
|
||||
/*
|
||||
* Executing each one, giving it the proper arguments
|
||||
*/
|
||||
if ((dev->d_type == flag) && (dev->d_time == DAEMON) && (dev->d_func != NULL))
|
||||
(*dev->d_func)(dev->d_arg);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* fuse:
|
||||
* Start a fuse to go off in a certain number of turns
|
||||
*/
|
||||
|
||||
fuse(dfunc, arg, time, type)
|
||||
VOID *arg;
|
||||
reg int (*dfunc)(), time, type;
|
||||
{
|
||||
reg struct delayed_action *wire;
|
||||
|
||||
wire = f_slot();
|
||||
if (wire != NULL) {
|
||||
wire->d_type = type;
|
||||
wire->d_func = dfunc;
|
||||
wire->d_arg = arg;
|
||||
wire->d_time = time;
|
||||
fusecnt += 1; /* update count */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* lengthen:
|
||||
* Increase the time until a fuse goes off
|
||||
*/
|
||||
|
||||
lengthen(dfunc, xtime)
|
||||
reg int (*dfunc)(), xtime;
|
||||
{
|
||||
reg struct delayed_action *wire;
|
||||
|
||||
if ((wire = find_slot(dfunc)) == NULL)
|
||||
return;
|
||||
wire->d_time += xtime;
|
||||
}
|
||||
|
||||
/*
|
||||
* extinguish:
|
||||
* Put out a fuse
|
||||
*/
|
||||
|
||||
extinguish(dfunc)
|
||||
reg int (*dfunc)();
|
||||
{
|
||||
reg struct delayed_action *wire;
|
||||
|
||||
if ((wire = find_slot(dfunc)) == NULL)
|
||||
return;
|
||||
wire->d_type = EMPTY;
|
||||
wire->d_func = NULL;
|
||||
wire->d_arg = NULL;
|
||||
wire->d_time = 0;
|
||||
fusecnt -= 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* do_fuses:
|
||||
* Decrement counters and start needed fuses
|
||||
*/
|
||||
|
||||
do_fuses(flag)
|
||||
reg int flag;
|
||||
{
|
||||
struct delayed_action *wire;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Step though the list
|
||||
*/
|
||||
for (i = 0; i < MAXFUSES; i++) {
|
||||
wire = &f_list[i];
|
||||
/*
|
||||
* Decrementing counters and starting things we want. We also need
|
||||
* to remove the fuse from the list once it has gone off.
|
||||
*/
|
||||
if(flag == wire->d_type && wire->d_time > 0 &&
|
||||
--wire->d_time == 0) {
|
||||
wire->d_type = EMPTY;
|
||||
if (wire->d_func != NULL)
|
||||
(*wire->d_func)(wire->d_arg);
|
||||
fusecnt -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* activity:
|
||||
* Show wizard number of demaons and memory blocks used
|
||||
*/
|
||||
|
||||
activity()
|
||||
{
|
||||
msg("Daemons = %d : Fuses = %d : Memory Items = %d : Memory Used = %d",
|
||||
demoncnt,fusecnt,total,md_memused());
|
||||
}
|
||||
|
||||
731
xrogue/daemons.c
Normal file
731
xrogue/daemons.c
Normal file
|
|
@ -0,0 +1,731 @@
|
|||
/*
|
||||
daemons.c - All the daemon and fuse functions are in here
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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"
|
||||
|
||||
/*
|
||||
* 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 = 10 - curp->s_lvl;
|
||||
new_points = curp->s_lvl - 2;
|
||||
when C_CLERIC:
|
||||
case C_DRUID:
|
||||
limit = 12 - curp->s_lvl;
|
||||
new_points = curp->s_lvl - 3;
|
||||
when C_THIEF:
|
||||
case C_ASSASSIN:
|
||||
limit = 14 - curp->s_lvl;
|
||||
new_points = curp->s_lvl - 4;
|
||||
when C_MONK:
|
||||
limit = 16 - curp->s_lvl;
|
||||
new_points = curp->s_lvl - 5;
|
||||
when C_RANGER:
|
||||
case C_PALADIN:
|
||||
limit = 18 - curp->s_lvl;
|
||||
new_points = curp->s_lvl - 6;
|
||||
when C_FIGHTER:
|
||||
limit = 20 - curp->s_lvl;
|
||||
new_points = curp->s_lvl - 7;
|
||||
when C_MONSTER:
|
||||
limit = 15 - curp->s_lvl;
|
||||
new_points = curp->s_lvl - 5;
|
||||
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, (VOID *)NULL, BEFORE);
|
||||
}
|
||||
|
||||
/*
|
||||
* rollwand:
|
||||
* Called to roll to see if a wandering monster starts up
|
||||
*/
|
||||
|
||||
int between = 0;
|
||||
|
||||
rollwand()
|
||||
{
|
||||
|
||||
if (++between >= 4)
|
||||
{
|
||||
/* Theives may not awaken a monster */
|
||||
if ((roll(1, 6) == 4) &&
|
||||
((player.t_ctype != C_THIEF && player.t_ctype != C_ASSASSIN) ||
|
||||
(rnd(30) >= dex_compute()))) {
|
||||
if (levtype != POSTLEV)
|
||||
wanderer();
|
||||
kill_daemon(rollwand);
|
||||
fuse(swander, (VOID *)NULL, 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))
|
||||
msg("You begin to feel weird.. ");
|
||||
}
|
||||
|
||||
/*
|
||||
* land:
|
||||
* Player can no longer fly
|
||||
*/
|
||||
|
||||
int
|
||||
land()
|
||||
{
|
||||
turn_off(player, ISFLY);
|
||||
msg("You regain your normal weight");
|
||||
running = FALSE;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
int
|
||||
res_strength(howmuch)
|
||||
long howmuch;
|
||||
{
|
||||
|
||||
/* If lost_str is non-zero, restore that amount of strength,
|
||||
* else all of it
|
||||
*/
|
||||
if (lost_str) {
|
||||
chg_str(lost_str);
|
||||
lost_str = 0;
|
||||
}
|
||||
|
||||
/* Now, add in the restoral, but no greater than maximum strength */
|
||||
if (howmuch > 0)
|
||||
pstats.s_str =
|
||||
min(pstats.s_str + howmuch, max_stats.s_str + ring_value(R_ADDSTR));
|
||||
|
||||
updpack(TRUE, &player);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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()
|
||||
{
|
||||
pstats.s_hpt = -1;
|
||||
death(D_SUFFOCATION);
|
||||
}
|
||||
|
||||
/*
|
||||
* digest the hero's food
|
||||
*/
|
||||
|
||||
stomach()
|
||||
{
|
||||
register int oldfood, old_hunger, food_use, i;
|
||||
|
||||
/*
|
||||
* avoid problems of fainting while eating by just not saying it
|
||||
* takes food to eat food
|
||||
*/
|
||||
if (player.t_action == C_EAT)
|
||||
return;
|
||||
|
||||
old_hunger = hungry_state;
|
||||
if (food_left <= 0)
|
||||
{
|
||||
/*
|
||||
* the hero is fainting
|
||||
*/
|
||||
if (player.t_action == A_FREEZE)
|
||||
return;
|
||||
if (rnd(100) > 12)
|
||||
return;
|
||||
if (hungry_state == F_FAINT && rnd(28) == 7) /*must have fainted once*/
|
||||
{
|
||||
pstats.s_hpt = -1;
|
||||
msg("You starve to death!! --More-- ");
|
||||
wait_for(' ');
|
||||
death(D_STARVATION);
|
||||
}
|
||||
player.t_action = A_FREEZE;
|
||||
player.t_no_move = movement(&player) * (rnd(8) + 3);
|
||||
if (!terse)
|
||||
addmsg("You feel too weak from the lack of food. ");
|
||||
msg("You faint");
|
||||
running = FALSE;
|
||||
if (fight_flush) flushinp();
|
||||
count = 0;
|
||||
hungry_state = F_FAINT;
|
||||
}
|
||||
else
|
||||
{
|
||||
oldfood = food_left;
|
||||
food_use = 0;
|
||||
for (i=0; i<MAXRELIC; i++) { /* each relic eats an additional food */
|
||||
if (cur_relic[i])
|
||||
food_use++;
|
||||
}
|
||||
/* Charge for wearing rings */
|
||||
food_use += (ring_eat(LEFT_1) + ring_eat(LEFT_2) +
|
||||
ring_eat(LEFT_3) + ring_eat(LEFT_4) +
|
||||
ring_eat(RIGHT_1) + ring_eat(RIGHT_2) +
|
||||
ring_eat(RIGHT_3) + ring_eat(RIGHT_4) +
|
||||
foodlev);
|
||||
if (food_use < 1)
|
||||
food_use = 1;
|
||||
food_left -= food_use;
|
||||
if (food_left < MORETIME && oldfood >= MORETIME) {
|
||||
msg("You are starting to feel weak");
|
||||
running = FALSE;
|
||||
if (fight_flush) flushinp();
|
||||
count = 0;
|
||||
hungry_state = F_WEAK;
|
||||
}
|
||||
else if (food_left < 2 * MORETIME && oldfood >= 2 * MORETIME)
|
||||
{
|
||||
msg(terse ? "Getting hungry" : "You are starting to get hungry");
|
||||
running = FALSE;
|
||||
hungry_state = F_HUNGRY;
|
||||
}
|
||||
else if(food_left<STOMACHSIZE-MORETIME && oldfood>=STOMACHSIZE-MORETIME)
|
||||
{
|
||||
hungry_state = F_OKAY;
|
||||
}
|
||||
}
|
||||
if (old_hunger != hungry_state) {
|
||||
updpack(TRUE, &player);
|
||||
status(TRUE);
|
||||
}
|
||||
wghtchk();
|
||||
}
|
||||
|
||||
/*
|
||||
* daemon for curing the diseased
|
||||
*/
|
||||
|
||||
cure_disease()
|
||||
{
|
||||
turn_off(player, HASDISEASE);
|
||||
if (off (player, HASINFEST))
|
||||
msg(terse ? "You feel yourself improving"
|
||||
: "You begin to feel yourself improving again");
|
||||
}
|
||||
|
||||
/*
|
||||
* appear:
|
||||
* Become visible again
|
||||
*/
|
||||
|
||||
appear()
|
||||
{
|
||||
turn_off(player, ISINVIS);
|
||||
PLAYER = VPLAYER;
|
||||
msg("The tingling feeling leaves your body");
|
||||
light(&hero);
|
||||
}
|
||||
|
||||
/*
|
||||
* dust_appear:
|
||||
* dust of disappearance wears off
|
||||
*/
|
||||
|
||||
dust_appear()
|
||||
{
|
||||
turn_off(player, ISINVIS);
|
||||
PLAYER = VPLAYER;
|
||||
msg("You become visible again");
|
||||
light(&hero);
|
||||
}
|
||||
|
||||
/*
|
||||
* unchoke:
|
||||
* the effects of "dust of choking and sneezing" wear off
|
||||
*/
|
||||
|
||||
unchoke()
|
||||
{
|
||||
if (!find_slot(unconfuse))
|
||||
turn_off(player, ISHUH);
|
||||
if (!find_slot(sight))
|
||||
turn_off(player, ISBLIND);
|
||||
light(&hero);
|
||||
msg("Your throat and eyes return to normal");
|
||||
}
|
||||
|
||||
/*
|
||||
* make some potion for the guy in the Alchemy jug
|
||||
*/
|
||||
|
||||
alchemy(obj)
|
||||
register struct object *obj;
|
||||
{
|
||||
register struct object *tobj = 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(11)) {
|
||||
case 0: tobj->o_ac = P_PHASE;
|
||||
when 1: tobj->o_ac = P_CLEAR;
|
||||
when 2: tobj->o_ac = P_SEEINVIS;
|
||||
when 3: tobj->o_ac = P_HEALING;
|
||||
when 4: tobj->o_ac = P_MFIND;
|
||||
when 5: tobj->o_ac = P_TFIND;
|
||||
when 6: tobj->o_ac = P_HASTE;
|
||||
when 7: tobj->o_ac = P_RESTORE;
|
||||
when 8: tobj->o_ac = P_FLY;
|
||||
when 9: tobj->o_ac = P_SKILL;
|
||||
when 10:tobj->o_ac = P_FFIND;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* otto's irresistable dance wears off
|
||||
*/
|
||||
|
||||
int
|
||||
undance()
|
||||
{
|
||||
turn_off(player, ISDANCE);
|
||||
msg ("Your feet take a break.....whew!");
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* if he has our favorite necklace of strangulation then take damage every turn
|
||||
*/
|
||||
|
||||
strangle()
|
||||
{
|
||||
if ((pstats.s_hpt -= 6) <= 0) {
|
||||
pstats.s_hpt = -1;
|
||||
death(D_STRANGLE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* if he has on the gauntlets of fumbling he might drop his weapon each turn
|
||||
*/
|
||||
|
||||
fumble()
|
||||
{
|
||||
register struct linked_list *item;
|
||||
|
||||
if (cur_weapon!=NULL &&
|
||||
!(cur_weapon->o_flags & ISCURSED) &&
|
||||
cur_weapon->o_type != RELIC &&
|
||||
rnd(100)<3) {
|
||||
for (item = pack; item != NULL; item = next(item)) {
|
||||
if (OBJPTR(item) == cur_weapon)
|
||||
break;
|
||||
}
|
||||
if (item != NULL) {
|
||||
switch(mvwinch(stdscr, hero.y, hero.x)) {
|
||||
case PASSAGE:
|
||||
case SCROLL:
|
||||
case POTION:
|
||||
case WEAPON:
|
||||
case FLOOR:
|
||||
case STICK:
|
||||
case ARMOR:
|
||||
case POOL:
|
||||
case RELIC:
|
||||
case GOLD:
|
||||
case FOOD:
|
||||
case RING:
|
||||
case MM:
|
||||
drop(item);
|
||||
running = FALSE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called each turn the hero has the ring of searching on
|
||||
* it's a lot like trap_look()
|
||||
*/
|
||||
|
||||
ring_search()
|
||||
{
|
||||
if (rnd(75) < (2*dex_compute() + 5*pstats.s_lvl)) search(TRUE, FALSE);
|
||||
else search(FALSE, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* this is called each turn the hero has the ring of teleportation on
|
||||
*/
|
||||
|
||||
ring_teleport()
|
||||
{
|
||||
if (rnd(100) < 3) teleport();
|
||||
}
|
||||
|
||||
/*
|
||||
* this is called to charge up the quill of Nagrom
|
||||
*/
|
||||
|
||||
quill_charge()
|
||||
{
|
||||
register struct object *tobj = NULL;
|
||||
register struct linked_list *item;
|
||||
|
||||
/*
|
||||
* find the Quill of Nagrom in the hero's pack. It should still be there
|
||||
* because it can't be dropped. If its not then don't do anything.
|
||||
*/
|
||||
for (item = pack; item != NULL; item = next(item)) {
|
||||
tobj = OBJPTR(item);
|
||||
if (tobj->o_type == RELIC && tobj->o_which == QUILL_NAGROM)
|
||||
break;
|
||||
}
|
||||
if (item == NULL)
|
||||
return;
|
||||
if (tobj->o_charges < QUILLCHARGES)
|
||||
tobj->o_charges++;
|
||||
fuse (quill_charge, (VOID *)NULL, player.t_ctype == C_MAGICIAN ? 4 : 8, AFTER);
|
||||
}
|
||||
|
||||
/*
|
||||
* take the skills away gained (or lost) by the potion of skills
|
||||
*/
|
||||
|
||||
unskill()
|
||||
{
|
||||
if (pstats.s_lvladj != 0) {
|
||||
pstats.s_lvl -= pstats.s_lvladj;
|
||||
pstats.s_lvladj = 0;
|
||||
msg("You feel your normal skill level return.");
|
||||
status(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* charge up the cloak of Emori
|
||||
*/
|
||||
|
||||
int
|
||||
cloak_charge(obj)
|
||||
register struct object *obj;
|
||||
{
|
||||
if (obj->o_charges < 1)
|
||||
obj->o_charges = 1;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* nofire:
|
||||
* He lost his fire resistance
|
||||
*/
|
||||
|
||||
nofire()
|
||||
{
|
||||
if (!ISWEARING(R_FIRE)) {
|
||||
turn_off(player, NOFIRE);
|
||||
msg("Your feeling of fire resistance leaves you");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* nocold:
|
||||
* He lost his cold resistance
|
||||
*/
|
||||
|
||||
nocold()
|
||||
{
|
||||
if (!ISWEARING(R_WARMTH)) {
|
||||
turn_off(player, NOCOLD);
|
||||
msg("Your feeling of warmth leaves you");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* nobolt:
|
||||
* He lost his protection from lightning
|
||||
*/
|
||||
|
||||
nobolt()
|
||||
{
|
||||
turn_off(player, NOBOLT);
|
||||
msg("Your skin loses its bluish tint");
|
||||
}
|
||||
|
||||
/*
|
||||
* eat_gold:
|
||||
* an artifact eats gold
|
||||
*/
|
||||
|
||||
eat_gold(obj)
|
||||
register struct object *obj;
|
||||
{
|
||||
if (purse == 250)
|
||||
msg("%s.. Bids you to find some more gold. ", inv_name(obj, FALSE));
|
||||
if (purse == 100)
|
||||
msg("%s.. Demands that you find more gold! ", inv_name(obj, FALSE));
|
||||
if (purse == 50)
|
||||
msg("%s.. Commands you to find more gold!! ", inv_name(obj, FALSE));
|
||||
if (purse == 0) {
|
||||
if (rnd(10) >= 7)
|
||||
msg("You feel the artifact gnawing away... ");
|
||||
if (--pstats.s_hpt < 1) {
|
||||
pstats.s_hpt = -1;
|
||||
death(D_RELIC);
|
||||
}
|
||||
}
|
||||
else
|
||||
purse--;
|
||||
}
|
||||
|
||||
/*
|
||||
* give the hero back some spell points
|
||||
*/
|
||||
|
||||
spell_recovery()
|
||||
{
|
||||
int time;
|
||||
|
||||
time = SPELLTIME - max(17-pstats.s_intel, 0);
|
||||
time = max(time, 5);
|
||||
if (spell_power > 0) spell_power--;
|
||||
fuse(spell_recovery, (VOID *)NULL, time, AFTER);
|
||||
}
|
||||
|
||||
/*
|
||||
* give the hero back some prayer points
|
||||
*/
|
||||
|
||||
prayer_recovery()
|
||||
{
|
||||
int time;
|
||||
|
||||
time = SPELLTIME - max(17-pstats.s_wisdom, 0);
|
||||
time = max(time, 5);
|
||||
if (pray_time > 0) pray_time--;
|
||||
fuse(prayer_recovery, (VOID *)NULL, time, AFTER);
|
||||
}
|
||||
|
||||
/*
|
||||
* give the hero back some chant points
|
||||
*/
|
||||
|
||||
chant_recovery()
|
||||
{
|
||||
int time;
|
||||
|
||||
time = SPELLTIME - max(17-pstats.s_wisdom, 0);
|
||||
time = max(time, 5);
|
||||
if (chant_time > 0) chant_time--;
|
||||
fuse(chant_recovery, (VOID *)NULL, time, AFTER);
|
||||
}
|
||||
|
||||
166
xrogue/eat.c
Normal file
166
xrogue/eat.c
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
eat.c - Functions for dealing with digestion
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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"
|
||||
|
||||
/*
|
||||
* eat:
|
||||
* He wants to eat something, so let him try
|
||||
*/
|
||||
|
||||
eat()
|
||||
{
|
||||
register struct linked_list *item;
|
||||
int which;
|
||||
unsigned long temp;
|
||||
|
||||
if (player.t_action != C_EAT) {
|
||||
if ((item = get_item(pack, "eat", FOOD, FALSE, FALSE)) == NULL)
|
||||
return;
|
||||
|
||||
player.t_using = item; /* Remember what it is */
|
||||
player.t_action = C_EAT; /* We are eating */
|
||||
which = (OBJPTR(item))->o_which;
|
||||
player.t_no_move = max(foods[which].mi_food/100, 1) * movement(&player);
|
||||
return;
|
||||
}
|
||||
|
||||
/* We have waited our time, let's eat the food */
|
||||
item = player.t_using;
|
||||
player.t_using = NULL;
|
||||
player.t_action = A_NIL;
|
||||
|
||||
which = (OBJPTR(item))->o_which;
|
||||
if ((food_left += foods[which].mi_food) > STOMACHSIZE)
|
||||
food_left = STOMACHSIZE;
|
||||
del_pack(item);
|
||||
if (hungry_state == F_SATIATED && food_left == STOMACHSIZE && rnd(4) == 1) {
|
||||
pstats.s_hpt = -1;
|
||||
msg ("Cough! Ack! You choke on all that food and die! --More--");
|
||||
wait_for(' ');
|
||||
death(D_FOOD_CHOKE);
|
||||
}
|
||||
if (food_left >= STOMACHSIZE-MORETIME) {
|
||||
hungry_state = F_SATIATED;
|
||||
msg ("You have trouble getting that food down!");
|
||||
msg ("Your stomach feels like it's about to burst!");
|
||||
}
|
||||
else if (which != E_SLIMEMOLD) {
|
||||
hungry_state = F_OKAY;
|
||||
switch (rnd(10)) {
|
||||
case 0: msg("Yuck, what a foul tasting %s! ", foods[which].mi_name);
|
||||
when 1: msg("Mmmm, what a tasty %s. ", foods[which].mi_name);
|
||||
when 2: msg("Wow, what a scrumptious %s! ", foods[which].mi_name);
|
||||
when 3: msg("Hmmm, %s heaven! ", foods[which].mi_name);
|
||||
when 4: msg("You've eaten better %s. ", foods[which].mi_name);
|
||||
when 5: msg("You smack your lips ");
|
||||
when 6: msg("Yum-yum-yum ");
|
||||
when 7: msg("Gulp! ");
|
||||
when 8: msg("Your tongue flips out! ");
|
||||
when 9: msg("You lick your chin ");
|
||||
}
|
||||
}
|
||||
updpack(TRUE, &player);
|
||||
switch(which) {
|
||||
case E_WHORTLEBERRY: /* add 1 to intelligence */
|
||||
(*add_abil[A_INTELLIGENCE])(1);
|
||||
when E_SWEETSOP: /* add 1 to strength */
|
||||
case E_SOURSOP: /* add 1 to strength */
|
||||
(*add_abil[A_STRENGTH])(1);
|
||||
when E_SAPODILLA: /* add 1 to wisdom */
|
||||
(*add_abil[A_WISDOM])(1);
|
||||
when E_APPLE: /* add 1 to dexterity */
|
||||
(*add_abil[A_DEXTERITY])(1);
|
||||
when E_PRICKLEY: /* add 1 to constitution */
|
||||
(*add_abil[A_CONSTITUTION])(1);
|
||||
when E_PEACH: /* add 1 to charisma */
|
||||
(*add_abil[A_CHARISMA])(1);
|
||||
when E_PITANGA: /* add 1 hit point */
|
||||
max_stats.s_hpt++;
|
||||
pstats.s_hpt = max_stats.s_hpt;
|
||||
msg("You feel a bit tougher now. ");
|
||||
when E_HAGBERRY: /* armor class */
|
||||
case E_JABOTICABA: /* armor class */
|
||||
pstats.s_arm--;
|
||||
msg("Your skin feels more resilient now. ");
|
||||
when E_STRAWBERRY: /* add 10% experience points */
|
||||
case E_RAMBUTAN: /* add 10% experience points */
|
||||
temp = pstats.s_exp/100 + 10;
|
||||
pstats.s_exp += temp;
|
||||
msg("You feel slightly more experienced now. ");
|
||||
check_level();
|
||||
when E_DEWBERRY: /* encourage him to do more magic */
|
||||
if (chant_time > 0) {
|
||||
chant_time -= 80;
|
||||
if (chant_time < 0)
|
||||
chant_time = 0;
|
||||
msg("You feel you have more chant ability. ");
|
||||
}
|
||||
if (pray_time > 0) {
|
||||
pray_time -= 80;
|
||||
if (pray_time < 0)
|
||||
pray_time = 0;
|
||||
msg("You feel you have more prayer ability. ");
|
||||
}
|
||||
if (spell_power > 0) {
|
||||
spell_power -= 80;
|
||||
if (spell_power < 0)
|
||||
spell_power = 0;
|
||||
msg("You feel you have more spell casting ability. ");
|
||||
}
|
||||
when E_CANDLEBERRY: /* cure him */
|
||||
if (on(player, HASINFEST) ||
|
||||
on(player, HASDISEASE)||
|
||||
on(player, DOROT)) {
|
||||
if (on(player, HASDISEASE)) {
|
||||
extinguish(cure_disease);
|
||||
cure_disease();
|
||||
}
|
||||
if (on(player, HASINFEST)) {
|
||||
msg("You feel yourself improving. ");
|
||||
turn_off(player, HASINFEST);
|
||||
infest_dam = 0;
|
||||
}
|
||||
if (on(player, DOROT)) {
|
||||
msg("You feel your skin returning to normal. ");
|
||||
turn_off(player, DOROT);
|
||||
}
|
||||
}
|
||||
when E_SLIMEMOLD: /* monster food */
|
||||
msg("The slime-mold quivers around in your mouth. ");
|
||||
player.t_no_move = 3*movement(&player);
|
||||
if (off(player, HASDISEASE)) {
|
||||
if (ISWEARING(R_HEALTH) || player.t_ctype == C_PALADIN ||
|
||||
player.t_ctype == C_RANGER) {
|
||||
msg("You feel lousy. ");
|
||||
}
|
||||
else {
|
||||
turn_on(player, HASDISEASE);
|
||||
fuse(cure_disease, (VOID *)NULL, roll(HEALTIME,SICKTIME),AFTER);
|
||||
msg("You become ill. ");
|
||||
}
|
||||
}
|
||||
pstats.s_const -= rnd(2)+1;
|
||||
if (pstats.s_const <= 3) pstats.s_const = 3;
|
||||
|
||||
otherwise: /* not all the foods have to do something */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
721
xrogue/effects.c
Normal file
721
xrogue/effects.c
Normal file
|
|
@ -0,0 +1,721 @@
|
|||
/*
|
||||
effects.c - functions for dealing with appllying effects to monsters
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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"
|
||||
|
||||
/*
|
||||
* effect:
|
||||
* Check for effects of one thing hitting another thing. Return
|
||||
* the reason code if the defender is killed. Otherwise return 0.
|
||||
*/
|
||||
|
||||
effect(att, def, weap, thrown, see_att, see_def)
|
||||
register struct thing *att, *def;
|
||||
struct object *weap;
|
||||
bool thrown;
|
||||
register bool see_att, see_def;
|
||||
{
|
||||
register bool att_player, def_player;
|
||||
char attname[LINELEN+1], defname[LINELEN+1];
|
||||
|
||||
/* See if the attacker or defender is the player */
|
||||
att_player = (att == &player);
|
||||
def_player = (def == &player);
|
||||
|
||||
/*
|
||||
* If the player could see the attacker or defender, they can't
|
||||
* surprise anymore (don't bother checking if they could).
|
||||
*/
|
||||
if (see_att) turn_off(*att, CANSURPRISE);
|
||||
if (see_def) turn_off(*def, CANSURPRISE);
|
||||
|
||||
/* What are the attacker and defender names? */
|
||||
if (att_player) strcpy(attname, "you");
|
||||
else {
|
||||
if (see_att) strcpy(attname, monster_name(att));
|
||||
else strcpy(attname, "something");
|
||||
}
|
||||
|
||||
if (def_player) strcpy(defname, "you");
|
||||
else {
|
||||
if (see_def) strcpy(defname, monster_name(def));
|
||||
else strcpy(defname, "something");
|
||||
}
|
||||
|
||||
/*
|
||||
* See what happens to the attacker first. We can skip this
|
||||
* whole section, however, if the defender is the player.
|
||||
* Nothing happens (yet) to anyone just for hitting the player.
|
||||
*/
|
||||
if (!def_player) {
|
||||
if (!thrown) { /* Some things require a direct hit. */
|
||||
/*
|
||||
* If the attacker hits a rusting monster, The weapon
|
||||
* may be damaged
|
||||
*/
|
||||
if (on(*def, CANRUST) && weap &&
|
||||
weap->o_type != RELIC && (weap->o_flags & ISMETAL) &&
|
||||
!(weap->o_flags & ISPROT)) {
|
||||
if ((weap->o_hplus < 1 && weap->o_dplus < 1) ||
|
||||
roll(1,20) < weap->o_hplus+weap->o_dplus+10) {
|
||||
if (rnd(100) < 50) weap->o_hplus--;
|
||||
else weap->o_dplus--;
|
||||
if (att_player)
|
||||
msg(terse ? "Your %s weakens!"
|
||||
: "Your %s gets weaker!",
|
||||
weaps[weap->o_which].w_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If the attacker hit something that shrieks, wake the dungeon */
|
||||
if (on(*def, CANSHRIEK)) {
|
||||
if (see_def)
|
||||
msg("%s emits an ear piercing shriek! ", prname(defname, TRUE));
|
||||
else
|
||||
msg("You hear an ear piercing shriek!");
|
||||
|
||||
/* Friendly charactors should be immune */
|
||||
if (player.t_ctype == C_PALADIN ||
|
||||
player.t_ctype == C_RANGER || player.t_ctype == C_MONK)
|
||||
aggravate(TRUE, FALSE);
|
||||
else
|
||||
aggravate(TRUE, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* does the creature explode when hit?
|
||||
*/
|
||||
if (on(*def, CANEXPLODE)) {
|
||||
if (see_def) msg("%s explodes!", prname(defname, TRUE));
|
||||
else msg("You hear a tremendous explosion!");
|
||||
explode(def);
|
||||
if (pstats.s_hpt < 1) {
|
||||
pstats.s_hpt = -1;
|
||||
death(def->t_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now let's see what happens to the defender. Start out with
|
||||
* the things that everyone can do. Then exit if the attacker
|
||||
* is the player.
|
||||
*/
|
||||
if (!thrown) {
|
||||
/*
|
||||
* Can the player confuse?
|
||||
*/
|
||||
if (on(*att, CANHUH) && att_player) {
|
||||
msg("Your hands return to normal. ");
|
||||
if (off(*def, ISCLEAR) &&
|
||||
(off(*def, ISUNIQUE) || !save(VS_MAGIC, def, 0))) {
|
||||
if (see_def) msg("%s appears confused!", prname(defname, TRUE));
|
||||
turn_on(*def, ISHUH);
|
||||
}
|
||||
turn_off(*att, CANHUH);
|
||||
}
|
||||
|
||||
/* Return now if the attacker is the player. */
|
||||
if (att_player) return(0);
|
||||
|
||||
/*
|
||||
* Some monsters may take half your hit points
|
||||
*/
|
||||
if (on(*att, CANSUCK) && !save(VS_MAGIC, def, 0)) {
|
||||
if (def->t_stats.s_hpt == 1) return(att->t_index); /* Killed! */
|
||||
else {
|
||||
def->t_stats.s_hpt /= 2;
|
||||
if (def_player)
|
||||
msg("Your life force is being drained out of you.");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If a hugging monster hits, it may SQUEEEEEEEZE.
|
||||
*/
|
||||
if (on(*att, CANHUG)) {
|
||||
if (roll(1,20) >= 18 || roll(1,20) >= 18) {
|
||||
if (def_player)
|
||||
msg("%s squeezes itself nastily against you!",
|
||||
prname(attname, TRUE));
|
||||
else if (see_att)
|
||||
msg("%s squeezes real hard!", prname(attname, TRUE));
|
||||
|
||||
if ((def->t_stats.s_hpt -= roll(2,8)) <= 0)
|
||||
return(att->t_index);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Some monsters have poisonous bites.
|
||||
*/
|
||||
if (on(*att, CANPOISON) && !save(VS_POISON, def, 0)) {
|
||||
if (def_player) {
|
||||
if (ISWEARING(R_SUSABILITY))
|
||||
msg(terse ? "Sting has no effect."
|
||||
: "A sting momentarily weakens your arm.");
|
||||
else {
|
||||
chg_str(-1);
|
||||
msg(terse ? "A sting has weakened you." :
|
||||
"You get stung in the arm! You feel weaker. ");
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Subtract a strength point and see if it kills it */
|
||||
if (--def->t_stats.s_str <= 0) return(D_STRENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Turning to stone:
|
||||
*/
|
||||
if (on(*att, TOUCHSTONE)) {
|
||||
if (def_player) turn_off(*att, TOUCHSTONE);
|
||||
if (on(*def, CANINWALL)) {
|
||||
if (def_player)
|
||||
msg("%s's touch has no effect.", prname(attname, TRUE));
|
||||
}
|
||||
else {
|
||||
if (!save(VS_PETRIFICATION, def, 0) && rnd(100) < 10) {
|
||||
if (def_player) {
|
||||
msg("Your body begins to solidify.. ");
|
||||
msg("You are transformed into stone!! --More--");
|
||||
wait_for(' ');
|
||||
return(D_PETRIFY);
|
||||
}
|
||||
else {
|
||||
/* The monster got stoned! */
|
||||
turn_on(*def, ISSTONE);
|
||||
turn_off(*def, ISRUN);
|
||||
turn_off(*def, ISINVIS);
|
||||
turn_off(*def, ISDISGUISE);
|
||||
if (def->t_stats.s_intel > 15)
|
||||
msg("%s staggers.. ", prname(defname, TRUE));
|
||||
else if (see_def)
|
||||
msg("%s turns to stone! ", prname(defname, TRUE));
|
||||
else if (cansee(unc(def->t_pos)))
|
||||
msg("A statue appears out of nowhere! ");
|
||||
}
|
||||
}
|
||||
else if (def->t_action != A_FREEZE) {
|
||||
if (def_player)
|
||||
msg("%s's touch stiffens your limbs.",
|
||||
prname(attname, TRUE));
|
||||
else if (see_def)
|
||||
msg("%s appears to freeze over.", prname(defname, TRUE));
|
||||
|
||||
def->t_no_move += movement(def) * STONETIME;
|
||||
def->t_action = A_FREEZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Wraiths might drain energy levels
|
||||
*/
|
||||
if ((on(*att, CANDRAIN) || on(*att, DOUBLEDRAIN)) &&
|
||||
!save(VS_POISON, def, 3-(att->t_stats.s_lvl/5))) {
|
||||
if (def_player) {
|
||||
lower_level(att->t_index);
|
||||
if (on(*att, DOUBLEDRAIN)) lower_level(att->t_index);
|
||||
turn_on(*att, DIDDRAIN);
|
||||
}
|
||||
else {
|
||||
def->t_stats.s_hpt -= roll(1, 8);
|
||||
def->t_stats.s_lvl--;
|
||||
if (on(*att, DOUBLEDRAIN)) {
|
||||
def->t_stats.s_hpt -= roll(1, 8);
|
||||
def->t_stats.s_lvl--;
|
||||
}
|
||||
if (see_def)
|
||||
msg("%s appears less skillful.", prname(defname, TRUE));
|
||||
|
||||
/* Did it kill it? */
|
||||
if (def->t_stats.s_hpt <= 0 ||
|
||||
def->t_stats.s_lvl <= 0)
|
||||
return(att->t_index);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Paralyzation:
|
||||
*/
|
||||
if (on(*att, CANPARALYZE) && def->t_action != A_FREEZE) {
|
||||
if (def_player) turn_off(*att, CANPARALYZE);
|
||||
if (!save(VS_PARALYZATION, def, 0)) {
|
||||
if (on(*def, CANINWALL)) {
|
||||
if (def_player)
|
||||
msg("%s's touch has no effect.", prname(attname, TRUE));
|
||||
}
|
||||
else {
|
||||
if (def_player)
|
||||
msg("%s's touch paralyzes you.", prname(attname, TRUE));
|
||||
else if (see_def)
|
||||
msg("%s appears to freeze over!", prname(defname, TRUE));
|
||||
|
||||
def->t_no_move += movement(def) * FREEZETIME;
|
||||
def->t_action = A_FREEZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Painful wounds make the defendant faint
|
||||
*/
|
||||
if (on(*att, CANPAIN) && def->t_action != A_FREEZE) {
|
||||
if (def_player) turn_off(*att, CANPAIN);
|
||||
if (!ISWEARING(R_ALERT) && !save(VS_POISON, def, 0)) {
|
||||
if (def_player)
|
||||
msg("You faint from the painful wound!");
|
||||
else if (see_def)
|
||||
msg("%s appears to faint!", prname(defname, TRUE));
|
||||
|
||||
def->t_no_move += movement(def) * PAINTIME;
|
||||
def->t_action = A_FREEZE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Some things currently affect only the player. Let's make
|
||||
* a check here so we don't have to check for each thing.
|
||||
*/
|
||||
if (def_player) {
|
||||
/*
|
||||
* Stinking monsters make the defender weaker (to hit). For now
|
||||
* this will only affect the player. We may later add the HASSTINK
|
||||
* effect to monsters, too.
|
||||
*/
|
||||
if (on(*att, CANSTINK)) {
|
||||
turn_off(*att, CANSTINK);
|
||||
if (!save(VS_POISON, def, 0)) {
|
||||
msg("The stench of %s sickens you. Blech!",
|
||||
prname(attname, FALSE));
|
||||
if (on(player, HASSTINK)) lengthen(unstink, STINKTIME);
|
||||
else {
|
||||
turn_on(player, HASSTINK);
|
||||
fuse(unstink, (VOID *)NULL, STINKTIME, AFTER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Chilling monster reduces strength each time. This only
|
||||
* affects the player for now because of its temporary nature.
|
||||
*/
|
||||
if (on(*att, CANCHILL)) {
|
||||
if (!ISWEARING(R_SUSABILITY) && !save(VS_POISON, def, 0)) {
|
||||
msg("You cringe at %s's chilling touch.",
|
||||
prname(attname, FALSE));
|
||||
chg_str(-1);
|
||||
if (lost_str++ == 0)
|
||||
fuse(res_strength, (VOID *)NULL, CHILLTIME, AFTER);
|
||||
else lengthen(res_strength, CHILLTIME);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Itching monsters reduce dexterity (temporarily). This only
|
||||
* affects the player for now because of its temporary nature.
|
||||
*/
|
||||
if (on(*att, CANITCH) && !save(VS_POISON, def, 0)) {
|
||||
msg("The claws of %s scratch you!", prname(attname, FALSE));
|
||||
if (ISWEARING(R_SUSABILITY)) {
|
||||
msg("The scratch has no effect.");
|
||||
}
|
||||
else {
|
||||
(*add_abil[A_DEXTERITY])(-1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If a disease-carrying monster hits, there is a chance the
|
||||
* defender will catch the disease. This only applies to the
|
||||
* player for now because of the temporary nature. Don't affect
|
||||
* the Ranger or Paladin.
|
||||
*/
|
||||
if (on(*att, CANDISEASE) &&
|
||||
(rnd(def->t_stats.s_const) < att->t_stats.s_lvl) &&
|
||||
off(*def, HASDISEASE)) {
|
||||
if (ISWEARING(R_HEALTH) ||
|
||||
player.t_ctype == C_PALADIN ||
|
||||
player.t_ctype == C_RANGER) {
|
||||
msg("The wound heals quickly.");
|
||||
}
|
||||
else {
|
||||
turn_on(*def, HASDISEASE);
|
||||
fuse(cure_disease, (VOID *)NULL, roll(HEALTIME,SICKTIME), AFTER);
|
||||
msg(terse ? "You have been diseased!"
|
||||
: "You have contracted an annoying disease!");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If a rusting monster hits, you lose armor. This only applies to
|
||||
* the player because monsters don't wear armor (for now).
|
||||
*/
|
||||
if (on(*att, CANRUST)) {
|
||||
if (cur_armor != NULL &&
|
||||
cur_armor->o_which != LEATHER &&
|
||||
cur_armor->o_which != STUDDED_LEATHER &&
|
||||
cur_armor->o_which != PADDED_ARMOR &&
|
||||
!(cur_armor->o_flags & ISPROT) &&
|
||||
cur_armor->o_ac < def->t_stats.s_arm+1) {
|
||||
msg(terse ? "Your armor weakens."
|
||||
: "Your armor becomes weaker.");
|
||||
cur_armor->o_ac++;
|
||||
}
|
||||
if (cur_misc[WEAR_BRACERS] != NULL &&
|
||||
cur_misc[WEAR_BRACERS]->o_ac > 0 &&
|
||||
!(cur_misc[WEAR_BRACERS]->o_flags & ISPROT)) {
|
||||
cur_misc[WEAR_BRACERS]->o_ac--;
|
||||
if (cur_misc[WEAR_BRACERS]->o_ac == 0) {
|
||||
register struct linked_list *item;
|
||||
|
||||
for (item=pack; item!=NULL; item=next(item)) {
|
||||
if (OBJPTR(item) == cur_misc[WEAR_BRACERS]) {
|
||||
detach(pack, item);
|
||||
o_discard(item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
msg ("Your bracers crumble apart!");
|
||||
cur_misc[WEAR_BRACERS] = NULL;
|
||||
inpack--;
|
||||
}
|
||||
else {
|
||||
msg("Your bracers weaken!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If can dissolve and hero has leather type armor. This
|
||||
* also only applies to the player for now because of the
|
||||
* armor.
|
||||
*/
|
||||
if (on(*att, CANDISSOLVE) && cur_armor != NULL &&
|
||||
(cur_armor->o_which == LEATHER ||
|
||||
cur_armor->o_which == STUDDED_LEATHER ||
|
||||
cur_armor->o_which == PADDED_ARMOR) &&
|
||||
!(cur_armor->o_flags & ISPROT) &&
|
||||
cur_armor->o_ac < def->t_stats.s_arm+1) {
|
||||
msg(terse ? "Your armor dissolves!"
|
||||
: "Your armor appears to have dissolved!");
|
||||
cur_armor->o_ac++;
|
||||
}
|
||||
|
||||
/*
|
||||
* If an infesting monster hits you, you get a parasite or rot.
|
||||
* This will only affect the player until we figure out how to
|
||||
* make it affect monsters. Don't affect the Monk.
|
||||
*/
|
||||
if (on(*att, CANINFEST) &&
|
||||
rnd(def->t_stats.s_const) < att->t_stats.s_lvl) {
|
||||
if (ISWEARING(R_HEALTH) || player.t_ctype == C_MONK) {
|
||||
msg("The wound heals quickly.");
|
||||
}
|
||||
else {
|
||||
turn_off(*att, CANINFEST);
|
||||
msg(terse ? "You have been infested."
|
||||
: "You have contracted a parasitic infestation!");
|
||||
infest_dam++;
|
||||
turn_on(*def, HASINFEST);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Does it take wisdom away? This currently affects only
|
||||
* the player because of its temporary nature.
|
||||
*/
|
||||
if (on(*att, TAKEWISDOM) &&
|
||||
!save(VS_MAGIC, def, 0) &&
|
||||
!ISWEARING(R_SUSABILITY)) {
|
||||
(*add_abil[A_WISDOM])(-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Does it take intelligence away? This currently affects
|
||||
* only the player because of its temporary nature.
|
||||
*/
|
||||
if (on(*att, TAKEINTEL) &&
|
||||
!save(VS_MAGIC, &player, 0) &&
|
||||
!ISWEARING(R_SUSABILITY)) {
|
||||
(*add_abil[A_INTELLIGENCE])(-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Cause fear by touching. This currently affects only
|
||||
* the player until we figure out how we want it to
|
||||
* affect monsters.
|
||||
*/
|
||||
if (on(*att, TOUCHFEAR)) {
|
||||
turn_off(*att, TOUCHFEAR);
|
||||
if (!ISWEARING(R_HEROISM) &&
|
||||
!save(VS_WAND, def, 0) &&
|
||||
!(on(*def, ISFLEE) && (def->t_dest == &att->t_pos))) {
|
||||
turn_on(*def, ISFLEE);
|
||||
def->t_dest = &att->t_pos;
|
||||
msg("%s's touch terrifies you!", prname(attname, TRUE));
|
||||
|
||||
/* It is okay to turn tail */
|
||||
if (!def_player) def->t_oldpos = def->t_pos;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Make the hero dance (as in otto's irresistable dance)
|
||||
* This should be fairly easy to do to monsters, but
|
||||
* we'll restrict it to players until we decide what to
|
||||
* do about the temporary nature.
|
||||
*/
|
||||
if (on(*att, CANDANCE) &&
|
||||
!on(*def, ISDANCE) &&
|
||||
def->t_action != A_FREEZE &&
|
||||
!save(VS_MAGIC, def, -4)) {
|
||||
turn_off(*att, CANDANCE);
|
||||
turn_on(*def, ISDANCE);
|
||||
msg("You begin to dance uncontrollably!");
|
||||
fuse(undance, (VOID *)NULL, roll(2,4), AFTER);
|
||||
}
|
||||
|
||||
/*
|
||||
* Suffocating our hero. Monsters don't get suffocated.
|
||||
* That's too hard for now.
|
||||
*/
|
||||
if (on(*att, CANSUFFOCATE) &&
|
||||
!ISWEARING(R_FREEDOM) &&
|
||||
rnd(100) < 30 &&
|
||||
(find_slot(suffocate) == 0)) {
|
||||
turn_on(*att, DIDSUFFOCATE);
|
||||
msg("%s is beginning to suffocate you!", prname(attname, TRUE));
|
||||
fuse(suffocate, (VOID *)NULL, roll(9,3), AFTER);
|
||||
}
|
||||
|
||||
/*
|
||||
* some creatures stops the poor guy from moving.
|
||||
* How can we do this to a monster?
|
||||
*/
|
||||
if (on(*att,CANHOLD) && off(*att,DIDHOLD) && !ISWEARING(R_FREEDOM)){
|
||||
turn_on(*def, ISHELD);
|
||||
turn_on(*att, DIDHOLD);
|
||||
hold_count++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sucker will suck blood and run. This
|
||||
* should be easy to have happen to a monster,
|
||||
* but we have to decide how to handle the fleeing.
|
||||
*/
|
||||
if (on(*att, CANDRAW)) {
|
||||
turn_off(*att, CANDRAW);
|
||||
turn_on(*att, ISFLEE);
|
||||
msg("%s sates itself with your blood!", prname(attname, TRUE));
|
||||
if ((def->t_stats.s_hpt -= 12) <= 0) return(att->t_index);
|
||||
|
||||
/* It is okay to turn tail */
|
||||
att->t_oldpos = att->t_pos;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bad smell will force a reduction in strength.
|
||||
* This will happen only to the player because of
|
||||
* the temporary nature.
|
||||
*/
|
||||
if (on(*att, CANSMELL)) {
|
||||
turn_off(*att, CANSMELL);
|
||||
if (save(VS_MAGIC, def, 0) || ISWEARING(R_SUSABILITY)) {
|
||||
if (terse)
|
||||
msg("Pheww!");
|
||||
else
|
||||
msg("You smell an unpleasant odor. Phew!");
|
||||
}
|
||||
|
||||
else {
|
||||
int odor_str = -(rnd(6)+1);
|
||||
|
||||
msg("You are overcome by a foul odor!");
|
||||
if (lost_str == 0) {
|
||||
chg_str(odor_str);
|
||||
fuse(res_strength, (VOID *)NULL, SMELLTIME, AFTER);
|
||||
lost_str -= odor_str;
|
||||
}
|
||||
else lengthen(res_strength, SMELLTIME);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The monsters touch slows the defendant down.
|
||||
*/
|
||||
if (on(*att, TOUCHSLOW)) {
|
||||
turn_off(*att, TOUCHSLOW);
|
||||
if (!save(VS_PARALYZATION, def, 0))
|
||||
add_slow();
|
||||
}
|
||||
|
||||
/*
|
||||
* Rotting only affects the player. Don't affect the Monk,
|
||||
* Paladin, or Ranger.
|
||||
*/
|
||||
if (on(*att, CANROT)) {
|
||||
if (!ISWEARING(R_HEALTH) &&
|
||||
player.t_ctype != C_MONK &&
|
||||
player.t_ctype != C_RANGER &&
|
||||
player.t_ctype != C_PALADIN &&
|
||||
!save(VS_POISON, def, 0) &&
|
||||
off(*def, DOROT)) {
|
||||
turn_on(*def, DOROT);
|
||||
msg("You feel your skin starting to rot and peel away!");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Monsters should be able to steal gold from anyone,
|
||||
* but until this is rewritten, they will only steal
|
||||
* from the player (tough break).
|
||||
*/
|
||||
if (on(*att, STEALGOLD)) {
|
||||
/*
|
||||
* steal some gold
|
||||
*/
|
||||
register long lastpurse;
|
||||
register struct linked_list *item;
|
||||
register struct object *obj;
|
||||
|
||||
lastpurse = purse;
|
||||
purse -= (GOLDCALC * 2);
|
||||
if (!save(VS_MAGIC, def, att->t_stats.s_lvl/10)) {
|
||||
if (on(*att, ISUNIQUE))
|
||||
purse -= (GOLDCALC * 5);
|
||||
else
|
||||
purse -= (GOLDCALC * 3);
|
||||
}
|
||||
if (purse < 0)
|
||||
purse = 0;
|
||||
if (purse != lastpurse) {
|
||||
msg("You lost some gold! ");
|
||||
|
||||
/* Give the gold to the thief */
|
||||
for (item=att->t_pack; item != NULL; item=next(item)) {
|
||||
obj = OBJPTR(item);
|
||||
if (obj->o_type == GOLD) {
|
||||
obj->o_count += lastpurse - purse;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Did we do it? */
|
||||
if (item == NULL) { /* Then make some */
|
||||
item = new_item(sizeof *obj);
|
||||
obj = OBJPTR(item);
|
||||
obj->o_type = GOLD;
|
||||
obj->o_count = lastpurse - purse;
|
||||
obj->o_hplus = obj->o_dplus = 0;
|
||||
strcpy(obj->o_damage,"0d0");
|
||||
strcpy(obj->o_hurldmg,"0d0");
|
||||
obj->o_ac = 11;
|
||||
obj->contents = NULL;
|
||||
obj->o_group = 0;
|
||||
obj->o_flags = 0;
|
||||
obj->o_mark[0] = '\0';
|
||||
obj->o_pos = att->t_pos;
|
||||
|
||||
attach(att->t_pack, item);
|
||||
}
|
||||
}
|
||||
|
||||
turn_on(*att, ISFLEE);
|
||||
turn_on(*att, ISINVIS);
|
||||
|
||||
/* It is okay to turn tail */
|
||||
att->t_oldpos = att->t_pos;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Stealing happens last since the monster disappears
|
||||
* after the act.
|
||||
*/
|
||||
if (on(*att, STEALMAGIC)) {
|
||||
register struct linked_list *list, *steal;
|
||||
register struct object *obj;
|
||||
register int nobj;
|
||||
|
||||
/*
|
||||
* steal a magic item, look through the pack
|
||||
* and pick out one we like.
|
||||
*/
|
||||
steal = NULL;
|
||||
for (nobj = 0, list = def->t_pack; list != NULL; list = next(list))
|
||||
{
|
||||
obj = OBJPTR(list);
|
||||
if (!is_current(obj) &&
|
||||
list != def->t_using &&
|
||||
obj->o_type != RELIC &&
|
||||
is_magic(obj) &&
|
||||
rnd(++nobj) == 0)
|
||||
steal = list;
|
||||
}
|
||||
if (steal != NULL)
|
||||
{
|
||||
register struct object *obj;
|
||||
struct linked_list *item;
|
||||
|
||||
obj = OBJPTR(steal);
|
||||
if (on(*att, ISUNIQUE))
|
||||
monsters[att->t_index].m_normal = TRUE;
|
||||
item = find_mons(att->t_pos.y, att->t_pos.x);
|
||||
|
||||
killed(item, FALSE, FALSE, FALSE); /* Remove the attacker */
|
||||
|
||||
if (obj->o_count > 1 && obj->o_group == 0) {
|
||||
register int oc;
|
||||
|
||||
oc = --(obj->o_count);
|
||||
obj->o_count = 1;
|
||||
if (def_player)
|
||||
msg("%s stole %s!", prname(attname, TRUE),
|
||||
inv_name(obj, TRUE));
|
||||
obj->o_count = oc;
|
||||
}
|
||||
else {
|
||||
if (def_player) {
|
||||
msg("%s stole %s!", prname(attname, TRUE),
|
||||
inv_name(obj, TRUE));
|
||||
|
||||
/* If this is a relic, clear its holding field */
|
||||
if (obj->o_type == RELIC)
|
||||
cur_relic[obj->o_which] = 0;
|
||||
|
||||
inpack--;
|
||||
}
|
||||
|
||||
detach(def->t_pack, steal);
|
||||
o_discard(steal);
|
||||
}
|
||||
|
||||
updpack(FALSE, def);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Didn't kill the defender */
|
||||
return(0);
|
||||
}
|
||||
|
||||
202
xrogue/encumb.c
Normal file
202
xrogue/encumb.c
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
/*
|
||||
encumb.c - Stuff to do with encumberance
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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"
|
||||
|
||||
/*
|
||||
* updpack:
|
||||
* Update his pack weight and adjust fooduse accordingly
|
||||
*/
|
||||
|
||||
updpack(getmax, tp)
|
||||
int getmax;
|
||||
struct thing *tp;
|
||||
{
|
||||
|
||||
reg int topcarry, curcarry;
|
||||
|
||||
if (getmax)
|
||||
tp->t_stats.s_carry = totalenc(tp); /* get total encumb */
|
||||
curcarry = packweight(tp); /* get pack weight */
|
||||
|
||||
/* Only update food use for the player (for now) */
|
||||
if (tp == &player) {
|
||||
topcarry = tp->t_stats.s_carry / 5; /* 20% of total carry */
|
||||
if(curcarry > 4 * topcarry) {
|
||||
if(rnd(100) < 80)
|
||||
foodlev = 3; /* > 80% of pack */
|
||||
} else if(curcarry > 3 * topcarry) {
|
||||
if(rnd(100) < 60)
|
||||
foodlev = 2; /* > 60% of pack */
|
||||
} else
|
||||
foodlev = 1; /* <= 60% of pack */
|
||||
}
|
||||
tp->t_stats.s_pack = curcarry; /* update pack weight */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* packweight:
|
||||
* Get the total weight of the hero's pack
|
||||
*/
|
||||
|
||||
packweight(tp)
|
||||
register struct thing *tp;
|
||||
{
|
||||
reg struct object *obj;
|
||||
reg struct linked_list *pc;
|
||||
reg int weight;
|
||||
|
||||
weight = 0;
|
||||
for (pc = tp->t_pack ; pc != NULL ; pc = next(pc)) {
|
||||
obj = OBJPTR(pc);
|
||||
weight += itemweight(obj);
|
||||
}
|
||||
if (weight < 0) /* in case of amulet */
|
||||
weight = 0;
|
||||
|
||||
/* If this is the player, is he wearing a ring of carrying? */
|
||||
if (tp == &player && ISWEARING(R_CARRY)) {
|
||||
register int temp, i;
|
||||
|
||||
temp = 0;
|
||||
for (i=0; i<NUM_FINGERS; i++) {
|
||||
if (cur_ring[i] != NULL && cur_ring[i]->o_which == R_CARRY) {
|
||||
if (cur_ring[i]->o_flags & ISCURSED) temp--;
|
||||
else temp += 2;
|
||||
}
|
||||
}
|
||||
weight -= (temp * weight) / 4;
|
||||
}
|
||||
|
||||
return(weight);
|
||||
}
|
||||
|
||||
/*
|
||||
* itemweight:
|
||||
* Get the weight of an object
|
||||
*/
|
||||
|
||||
itemweight(wh)
|
||||
reg struct object *wh;
|
||||
{
|
||||
reg int weight;
|
||||
reg int ac;
|
||||
|
||||
weight = wh->o_weight; /* get base weight */
|
||||
switch(wh->o_type) {
|
||||
case ARMOR:
|
||||
/*
|
||||
* subtract 10% for each enchantment
|
||||
* this will add weight for negative items
|
||||
*/
|
||||
ac = armors[wh->o_which].a_class - wh->o_ac;
|
||||
weight = ((weight*10) - (weight*ac)) / 10;
|
||||
if (weight < 0) weight = 0;
|
||||
when WEAPON:
|
||||
if ((wh->o_hplus + wh->o_dplus) > 0)
|
||||
weight /= 2;
|
||||
}
|
||||
if(wh->o_flags & ISCURSED)
|
||||
weight += weight / 5; /* 20% more for cursed */
|
||||
weight *= wh->o_count;
|
||||
return(weight);
|
||||
}
|
||||
|
||||
/*
|
||||
* playenc:
|
||||
* Get hero's carrying ability above norm
|
||||
*/
|
||||
|
||||
playenc(tp)
|
||||
register struct thing *tp;
|
||||
{
|
||||
register int strength;
|
||||
|
||||
if (tp == &player) strength = str_compute();
|
||||
else strength = tp->t_stats.s_str;
|
||||
|
||||
return ((strength-8)*50);
|
||||
}
|
||||
|
||||
/*
|
||||
* totalenc:
|
||||
* Get total weight that the hero can carry
|
||||
*/
|
||||
|
||||
totalenc(tp)
|
||||
register struct thing *tp;
|
||||
{
|
||||
reg int wtotal;
|
||||
|
||||
wtotal = NORMENCB + playenc(tp);
|
||||
if (tp == &player) switch(hungry_state) {
|
||||
case F_SATIATED:
|
||||
case F_OKAY:
|
||||
case F_HUNGRY: ; /* no change */
|
||||
when F_WEAK: wtotal -= wtotal / 10; /* 10% off weak */
|
||||
when F_FAINT: wtotal /= 2; /* 50% off faint */
|
||||
}
|
||||
return(wtotal);
|
||||
}
|
||||
|
||||
/*
|
||||
* whgtchk:
|
||||
* See if the hero can carry his pack
|
||||
*/
|
||||
|
||||
wghtchk()
|
||||
{
|
||||
reg int dropchk, err = TRUE;
|
||||
reg char ch;
|
||||
int wghtchk();
|
||||
|
||||
inwhgt = TRUE;
|
||||
if (pstats.s_pack > pstats.s_carry) {
|
||||
ch = mvwinch(stdscr, hero.y, hero.x);
|
||||
if((ch != FLOOR && ch != PASSAGE)) {
|
||||
extinguish(wghtchk);
|
||||
fuse(wghtchk, (VOID *)NULL, 1, AFTER);
|
||||
inwhgt = FALSE;
|
||||
return;
|
||||
}
|
||||
extinguish(wghtchk);
|
||||
msg("Your pack is far too heavy for you.. ");
|
||||
do {
|
||||
dropchk = drop((struct linked_list *)NULL);
|
||||
if(dropchk == 0) {
|
||||
mpos = 0;
|
||||
msg("You must drop something");
|
||||
}
|
||||
if(dropchk == TRUE)
|
||||
err = FALSE;
|
||||
} while(err);
|
||||
}
|
||||
inwhgt = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* hitweight:
|
||||
* Gets the fighting ability according to current weight
|
||||
* This returns a +1 hit for light pack weight
|
||||
* 0 hit for medium pack weight
|
||||
* -1 hit for heavy pack weight
|
||||
*/
|
||||
|
||||
hitweight()
|
||||
{
|
||||
return(2 - foodlev);
|
||||
}
|
||||
|
||||
1473
xrogue/fight.c
Normal file
1473
xrogue/fight.c
Normal file
File diff suppressed because it is too large
Load diff
651
xrogue/help.c
Normal file
651
xrogue/help.c
Normal file
|
|
@ -0,0 +1,651 @@
|
|||
/*
|
||||
help.c - Routines having to do with help
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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 "mach_dep.h"
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* Give character descripts
|
||||
*/
|
||||
|
||||
static char *game_fighter = "Strength is the main attribute of the Fighter. \
|
||||
He can wield any weapon and the two-handed sword is his weapon of choice. He \
|
||||
can also wear any type of armor. Plate armor being the best choice and \
|
||||
leather armor the worst. The Fighter is able to sense both traps and gold \
|
||||
at higher experience levels. His natural quest item is the Axe of Aklad. \
|
||||
Due to his superior form, the Fighter usually receives more hit-points per \
|
||||
new experience level than the other characters. The Fighter is neither good \
|
||||
or evil; he is a neutral character. The default attribute values of the \
|
||||
Fighter are: Int=7, Str=16, Wis=7, Dxt=16, Con=17, and Chr=11. Default gold \
|
||||
amount is 2000 pieces and default hit-points are 24.";
|
||||
|
||||
static char *game_thief = "Dexterity is the main attribute of the Thief. His \
|
||||
stealth allows him to move quietly, thus disturbing less monsters. He can \
|
||||
sense traps and gold and can take (steal) things from the monsters. The \
|
||||
Thief can not wield the two-handed sword so the bastard sword is his weapon \
|
||||
of choice. He can only wear studded leather armor. The Thief's natural \
|
||||
quest item is the Daggers of Musty Doit. With higher dexterity the Thief \
|
||||
is able to \"backstab\" monsters, thereby killing them with a single blow. \
|
||||
His character type fluctuates between that of good, neutral, and evil. The \
|
||||
default attribute values of the Thief are: Int=7, Str=14, Wis=7, Dxt=18, \
|
||||
Con=17, and Chr=11. Default gold amount is 2000 pieces and default \
|
||||
hit-points are 23.";
|
||||
|
||||
static char *game_assassin = "Dexterity is the main attribute of the \
|
||||
Assassin. Like the Thief, he moves with an extra degree of stealth. He can \
|
||||
sense gold and steal things from monsters. The ability to sense traps comes \
|
||||
at higher experience levels. The Assassin can not wield the two-handed sword \
|
||||
and he can only wear studded leather armor. The natural quest item of the \
|
||||
Assassin is the Eye of Vecna. He is also skilled in the use of poison. \
|
||||
Higher dexterity enables him to \"assassinate\" monsters with a single blow. \
|
||||
The Assassin is aligned with the powers of evil. The default attribute \
|
||||
values of the Assassin are: Int=7, Str=14, Wis=7, Dxt=18, Con=17, and \
|
||||
Chr=11. Default gold amount is 2000 pieces and default hit-points are 23.";
|
||||
|
||||
static char *game_ranger = "Charisma is the main attribute of the Ranger who \
|
||||
also has a secondary attribute of Intelligence. Like the Magician, this \
|
||||
gives him the ability to cast spells which increases as he attains higher \
|
||||
experience levels. Like the Fighter, he can wield any weapon and wear any \
|
||||
armor. The Ranger's natural quest item is the Mandolin of Brian. He is \
|
||||
aligned with the powers of good. Therefore, he can be made to suffer and \
|
||||
even become cursed by the very powers that allow him to cast spells if he \
|
||||
happens to cause the demise of a likewise good creature. The default \
|
||||
attribute values of the Ranger are: Int=11, Str=11, Wis=7, Dxt=16, Con=16, \
|
||||
and Chr=13. Default gold amount is 2000 pieces and default hit-points \
|
||||
are 22.";
|
||||
|
||||
static char *game_paladin = "Charisma is the main attribute of the Paladin \
|
||||
who has a secondary attribute of Wisdom. Like the Cleric, this gives him \
|
||||
the ability to offer prayers, receive what his heart desires, and an ability \
|
||||
to turn the undead. This ability will increase as he gains higher \
|
||||
experience levels. Like the Fighter, he can wield any weapon and wear any \
|
||||
armor. The Ankh of Heil is the Paladin's natural quest item. Like the \
|
||||
Ranger, the Paladin is aligned with the powers of good. This can cause \
|
||||
him to suffer and become cursed if he brings ruin to a likewise good \
|
||||
creature. The default attribute values of the Paladin are: Int=7, \
|
||||
Str=11, Wis=11, Dxt=16, Con=16, and Chr=13. Default gold amount is \
|
||||
2000 pieces and default hit-points are 22.";
|
||||
|
||||
static char *game_druid = "Wisdom is the main attribute of the Druid. This \
|
||||
gives him the ability to chant secret words and mantras, which is much \
|
||||
greater than that of the Monk. The Druid can not wield the two-handed or \
|
||||
bastard swords but he can wear any armor. His natural quest item is the Quill \
|
||||
of Nagrom. Like the Magician and Cleric, the Druid is aligned neutral. He \
|
||||
therefore, must rely upon his Wisdom and his chanting ability in order to \
|
||||
remain alive. Likewise, he does not receive as many new hit-points per \
|
||||
new experience level. The default attribute values of the Druid are: Int=7, \
|
||||
Str=10, Wis=14, Dxt=16, Con=15, and Chr=12. Default gold amount is 2000 \
|
||||
pieces and default hit-points are 21.";
|
||||
|
||||
static char *game_monk = "Constitution is the main attribute of the Monk who \
|
||||
has a secondary aspect of Wisdom. Like the Druid, this gives him the \
|
||||
ability to chant mantras which will increase as he gains higher experience. \
|
||||
The Monk can not wield the two-handed sword and he can not wear any armor. \
|
||||
The Cloak of Emori is the Monk's natural quest item. The Monk can also \
|
||||
sense traps, though much less than the Thief or Assassin. He is the most \
|
||||
healthy character. Like the Ranger and Paladin, he is aligned with the \
|
||||
powers of good. Therefore, he is made to suffer and can become cursed if \
|
||||
he kills a likewise good creature. The default attribute values of the \
|
||||
Monk are: Int=7, Str=11, Wis=11, Dxt=16, Con=18, and Chr=11. Default \
|
||||
gold amount is 2000 pieces and default hit-points are 22.";
|
||||
|
||||
static char *game_magician = "Intelligence is the main attribute of the \
|
||||
Magician. The Magician's ability to cast spells is much greater than that \
|
||||
of the Ranger. He can not wield the two- handed or bastard swords, but he \
|
||||
can wear any kind of armor. His natural quest item is the Amulet of \
|
||||
Stonebones. The Magician is aligned neutral. He must rely upon his \
|
||||
Intelligence and spell casting abilities to remain alive. There- fore, he \
|
||||
does not receive as many new hit-points per new experience level. The \
|
||||
default attribute values of the Magician are: Int=14, Str=10, Wis=7, \
|
||||
Dxt=16, Con=15, and Chr=12. Default gold amount is 2000 pieces and \
|
||||
default hit-points are 21.";
|
||||
|
||||
static char *game_cleric = "Wisdom is the main attribute of the Cleric. The \
|
||||
Cleric's ability to give or offer prayers, receive their due, and affect \
|
||||
the undead are much greater than that of the Paladin. Like the Magician, \
|
||||
the Cleric can not wield the two- handed or bastard swords, but he can \
|
||||
wear any armor. His natural quest item is the Horn of Geryon. The Cleric \
|
||||
is aligned neutral and he must rely upon his Wisdom and prayer ability to \
|
||||
remain alive. He therefore, does not receive as many new hit-points per \
|
||||
new experience level. The default attribute values of the Cleric are: Int=7, \
|
||||
Str=10, Wis=14, Dxt=16, Con=15, and Chr=12. The default gold amount is 2000 \
|
||||
pieces and default hit-points are 21.";
|
||||
|
||||
|
||||
static char *game_food ="There are three types of food, regular food rations, \
|
||||
various fruits, and slime- molds. Eating regular food will add 750 points to \
|
||||
your current food level [see the CTRL(E) command]. Eating fruit adds \
|
||||
300 points. Certain fruits also cure you, add an attribute point, add a \
|
||||
hit-point, increase your armor, give you additional prayer, chant, or spell \
|
||||
casting abilities, or add experience points. Eating slime-mold (monster \
|
||||
food) can make you ill, but they will add 100 points to your current food \
|
||||
level. If your food level points drop below 100 you will become weak. You \
|
||||
will faint and might die if they drop to 0 or below. At the other extreme, \
|
||||
if your food level points reach 2000 (and above) you will become satiated. \
|
||||
Risk eating more and you could choke to death.";
|
||||
|
||||
/*
|
||||
static char *game_monst ="To be updated.";
|
||||
static char *game_potion ="To be updated...";
|
||||
static char *game_scroll ="To be updated...";
|
||||
static char *game_ring ="To be updated...";
|
||||
static char *game_stick ="To be updated...";
|
||||
static char *game_weapon ="To be updated...";
|
||||
static char *game_armor ="To be updated...";
|
||||
static char *game_miscm ="To be updated...";
|
||||
static char *game_qitems ="To be updated...";
|
||||
static char *game_dungeon ="To be updated...";
|
||||
static char *game_traps ="To be updated...";
|
||||
static char *game_mazes ="To be updated...";
|
||||
static char *game_option ="To be updated...";
|
||||
static char *game_begin ="To be updated...";
|
||||
*/
|
||||
|
||||
/* help list */
|
||||
static struct h_list helpstr[] = {
|
||||
'?', " Print help",
|
||||
'/', " Identify object",
|
||||
'=', " Identify a screen character",
|
||||
' ', "",
|
||||
'h', " Move left",
|
||||
'j', " Move down",
|
||||
'k', " Move up",
|
||||
'l', " Move right",
|
||||
'y', " Move up and left",
|
||||
'u', " Move up and right",
|
||||
'b', " Move down and left",
|
||||
'n', " Move down and right",
|
||||
'H', " Run left",
|
||||
'J', " Run down",
|
||||
'K', " Run up",
|
||||
'L', " Run right",
|
||||
'Y', " Run up & left",
|
||||
'U', " Run up & right",
|
||||
'B', " Run down & left",
|
||||
'N', " Run down & right",
|
||||
' ', "",
|
||||
'>', " Go down a staircase",
|
||||
'<', " Go up a staircase",
|
||||
'\\', " Game descriptions",
|
||||
'.', " Rest for a while",
|
||||
'*', " Count gold pieces",
|
||||
'a', " Affect the undead",
|
||||
'A', " Choose artifact (equipage)",
|
||||
'c', " Chant a mantra",
|
||||
'C', " Cast a spell",
|
||||
'd', " Drop something",
|
||||
'D', " Dip something (into a pool)",
|
||||
'e', " Eat food or fruit",
|
||||
'f', "<dir> Forward until find something",
|
||||
'F', " Frighten a monster",
|
||||
'g', " Give food to monster",
|
||||
'G', " Sense for gold",
|
||||
'i', " Inventory",
|
||||
'I', " Inventory (single item)",
|
||||
'm', " Mark an object (specific)",
|
||||
'o', " Examine and/or set options",
|
||||
'O', " Character type and quest item",
|
||||
'p', " Pray to the powers that be",
|
||||
'P', " Pick up object(s)",
|
||||
'q', " Quaff a potion",
|
||||
'Q', " Quit the game",
|
||||
'r', " Read a scroll",
|
||||
's', " Search for a trap/secret door",
|
||||
'S', " Save your game",
|
||||
't', "<dir> Throw something",
|
||||
'T', " Take off something",
|
||||
'v', " Print program version",
|
||||
'w', " Wield a weapon",
|
||||
'W', " Wear something",
|
||||
'X', " Sense for traps",
|
||||
'z', "<dir> Zap a wand or staff",
|
||||
' ', "",
|
||||
'^', " Set a trap",
|
||||
'$', " Price an item (trading post)",
|
||||
'#', " Buy an item (trading post)",
|
||||
'%', " Sell an item (trading post)",
|
||||
'!', " Shell escape",
|
||||
ESC, " Cancel command (Esc)",
|
||||
' ', "",
|
||||
CTRL('B'), " Current score (if you win)",
|
||||
CTRL('E'), " Current food level",
|
||||
CTRL('L'), " Redraw the screen",
|
||||
CTRL('N'), " Name an object or a monster",
|
||||
CTRL('O'), " Character affect status",
|
||||
CTRL('R'), " Repeat last message",
|
||||
CTRL('T'), "<dir> Take (steal) from (direction)",
|
||||
CTRL('U'), " Use a magic item",
|
||||
0, 0
|
||||
} ;
|
||||
|
||||
/* wizard help list */
|
||||
static struct h_list wiz_help[] = {
|
||||
' ', "",
|
||||
'+', " Random fortunes",
|
||||
'M', " Make an object",
|
||||
'V', " Display vlevel and turns",
|
||||
CTRL('A'), " System activity",
|
||||
CTRL('C'), " Move to another dungeon level",
|
||||
CTRL('D'), " Go down 1 dungeon level",
|
||||
CTRL('F'), " Display the entire level",
|
||||
CTRL('G'), " Charge wands and staffs",
|
||||
CTRL('H'), " Jump 9 experience levels",
|
||||
CTRL('I'), " Inventory of level",
|
||||
CTRL('J'), " Teleport somewhere",
|
||||
CTRL('K'), " Identify an object",
|
||||
CTRL('M'), " Recharge wand or staff",
|
||||
CTRL('P'), " Toggle wizard status",
|
||||
CTRL('X'), " Detect monsters",
|
||||
CTRL('Y'), " Display food levels",
|
||||
0, 0
|
||||
};
|
||||
|
||||
/* item help list */
|
||||
static struct item_list item_help[] = {
|
||||
'@', " You (visible)",
|
||||
'_', " You (invisible)",
|
||||
' ', "",
|
||||
':', " Food ration or fruit (eat)",
|
||||
'!', " Potion (quaff)",
|
||||
'?', " Scroll (read)",
|
||||
'=', " Ring (wear)",
|
||||
')', " Weapon (wield)",
|
||||
']', " Armor (wear)",
|
||||
'/', " Wand or staff (zap)",
|
||||
';', " Magic item (use)",
|
||||
',', " Artifact (quest item)",
|
||||
'*', " Gold or zapped missile",
|
||||
' ', "",
|
||||
'$', " Magical item in room",
|
||||
'>', " Blessed magical item",
|
||||
'<', " Cursed magical item",
|
||||
' ', " ",
|
||||
'`', " Dart trap",
|
||||
'{', " Arrow trap",
|
||||
'}', " Bear trap",
|
||||
'~', " Teleport trap",
|
||||
'$', " Sleeping gas trap",
|
||||
'>', " Trap door",
|
||||
'<', " Outer region entrance",
|
||||
'\'', " Maze entrance",
|
||||
'^', " Trading post entrance",
|
||||
'"', " Magic pool or lake",
|
||||
' ', " Solid rock or mountain",
|
||||
'.', " Floor of a room or meadow",
|
||||
'%', " Stairs (up or down)",
|
||||
'+', " Doorway",
|
||||
'&', " Secret doorway",
|
||||
'#', " Passage between rooms",
|
||||
'\\', " Forest",
|
||||
HORZWALL, " Horizontal wall of a room",
|
||||
VERTWALL, " Vertical wall of a room",
|
||||
0, 0
|
||||
};
|
||||
|
||||
ident_hero()
|
||||
{
|
||||
bool doit = TRUE;
|
||||
|
||||
wclear(hw);
|
||||
wprintw(hw, "Characters, Items, and Game Descriptions:\n");
|
||||
wprintw(hw, "-----------------------------------------\n");
|
||||
wprintw(hw, "a) Fighter m) Scrolls\n");
|
||||
wprintw(hw, "b) Thief n) Rings\n");
|
||||
wprintw(hw, "c) Assassin o) Wands and Staffs\n");
|
||||
wprintw(hw, "d) Ranger p) Weapons\n");
|
||||
wprintw(hw, "e) Paladin q) Armors\n");
|
||||
wprintw(hw, "f) Monk r) Miscellaneous Magic Items\n");
|
||||
wprintw(hw, "g) Magician s) Quest Items (Artifacts and Relics)\n");
|
||||
wprintw(hw, "h) Cleric t) The Dungeon\n");
|
||||
wprintw(hw, "i) Druid u) Traps\n");
|
||||
wprintw(hw, "j) Monsters v) Mazes and Outer Regions\n");
|
||||
wprintw(hw, "k) Foods w) Setting game options\n");
|
||||
wprintw(hw, "l) Potions x) Starting out\n");
|
||||
wprintw(hw, "\nEnter a letter: ");
|
||||
draw(hw);
|
||||
while (doit) {
|
||||
switch (wgetch(cw)) {
|
||||
case EOF:
|
||||
case ESC:
|
||||
doit = FALSE;
|
||||
when 'a':
|
||||
wclear(hw);
|
||||
wprintw(hw, "Fighter Characteristics:");
|
||||
mvwaddstr(hw, 2, 0, game_fighter);
|
||||
draw(hw);
|
||||
doit = FALSE;
|
||||
when 'b':
|
||||
wclear(hw);
|
||||
wprintw(hw, "Thief Characteristics:");
|
||||
mvwaddstr(hw, 2, 0, game_thief);
|
||||
draw(hw);
|
||||
doit = FALSE;
|
||||
when 'c':
|
||||
wclear(hw);
|
||||
wprintw(hw, "Assassin Characteristics:");
|
||||
mvwaddstr(hw, 2, 0, game_assassin);
|
||||
draw(hw);
|
||||
doit = FALSE;
|
||||
when 'd':
|
||||
wclear(hw);
|
||||
wprintw(hw, "Ranger Characteristics:");
|
||||
mvwaddstr(hw, 2, 0, game_ranger);
|
||||
draw(hw);
|
||||
doit = FALSE;
|
||||
when 'e':
|
||||
wclear(hw);
|
||||
wprintw(hw, "Paladin Characteristics:");
|
||||
mvwaddstr(hw, 2, 0, game_paladin);
|
||||
draw(hw);
|
||||
doit = FALSE;
|
||||
when 'f':
|
||||
wclear(hw);
|
||||
wprintw(hw, "Monk Characteristics:");
|
||||
mvwaddstr(hw, 2, 0, game_monk);
|
||||
draw(hw);
|
||||
doit = FALSE;
|
||||
when 'g':
|
||||
wclear(hw);
|
||||
wprintw(hw, "Magician Characteristics:");
|
||||
mvwaddstr(hw, 2, 0, game_magician);
|
||||
draw(hw);
|
||||
doit = FALSE;
|
||||
when 'h':
|
||||
wclear(hw);
|
||||
wprintw(hw, "Cleric Characteristics:");
|
||||
mvwaddstr(hw, 2, 0, game_cleric);
|
||||
draw(hw);
|
||||
doit = FALSE;
|
||||
when 'i':
|
||||
wclear(hw);
|
||||
wprintw(hw, "Druid Characteristics:");
|
||||
mvwaddstr(hw, 2, 0, game_druid);
|
||||
draw(hw);
|
||||
doit = FALSE;
|
||||
when 'j':
|
||||
wclear(hw);
|
||||
wprintw(hw, "Monster Characteristics:");
|
||||
draw(hw);
|
||||
doit = FALSE;
|
||||
when 'k':
|
||||
wclear(hw);
|
||||
wprintw(hw, "Foods:");
|
||||
mvwaddstr(hw, 2, 0, game_food);
|
||||
draw(hw);
|
||||
doit = FALSE;
|
||||
when 'l':
|
||||
wclear(hw);
|
||||
wprintw(hw, "Potions:");
|
||||
draw(hw);
|
||||
doit = FALSE;
|
||||
when 'm':
|
||||
wclear(hw);
|
||||
wprintw(hw, "Scrolls:");
|
||||
draw(hw);
|
||||
doit = FALSE;
|
||||
when 'n':
|
||||
wclear(hw);
|
||||
wprintw(hw, "Rings:");
|
||||
draw(hw);
|
||||
doit = FALSE;
|
||||
when 'o':
|
||||
wclear(hw);
|
||||
wprintw(hw, "Wands and Staffs:");
|
||||
draw(hw);
|
||||
doit = FALSE;
|
||||
when 'p':
|
||||
wclear(hw);
|
||||
wprintw(hw, "Weapons:");
|
||||
draw(hw);
|
||||
doit = FALSE;
|
||||
when 'q':
|
||||
wclear(hw);
|
||||
wprintw(hw, "Armors:");
|
||||
draw(hw);
|
||||
doit = FALSE;
|
||||
when 'r':
|
||||
wclear(hw);
|
||||
wprintw(hw, "Miscellaneous Magic Items:");
|
||||
draw(hw);
|
||||
doit = FALSE;
|
||||
when 's':
|
||||
wclear(hw);
|
||||
wprintw(hw, "Quest Items (Artifacts and Relics):");
|
||||
draw(hw);
|
||||
doit = FALSE;
|
||||
when 't':
|
||||
wclear(hw);
|
||||
wprintw(hw, "The Dungeon:");
|
||||
draw(hw);
|
||||
doit = FALSE;
|
||||
when 'u':
|
||||
wclear(hw);
|
||||
wprintw(hw, "Traps:");
|
||||
draw(hw);
|
||||
doit = FALSE;
|
||||
when 'v':
|
||||
wclear(hw);
|
||||
wprintw(hw, "Mazes and Outer Regions:");
|
||||
draw(hw);
|
||||
doit = FALSE;
|
||||
when 'w':
|
||||
wclear(hw);
|
||||
wprintw(hw, "Setting game options:");
|
||||
draw(hw);
|
||||
doit = FALSE;
|
||||
when 'x':
|
||||
wclear(hw);
|
||||
wprintw(hw, "Starting out:");
|
||||
draw(hw);
|
||||
doit = FALSE;
|
||||
otherwise:
|
||||
doit = TRUE;
|
||||
}
|
||||
}
|
||||
wmove(hw, lines-1, 0);
|
||||
wprintw(hw, spacemsg);
|
||||
draw(hw);
|
||||
wait_for(' ');
|
||||
wclear(hw);
|
||||
draw(hw);
|
||||
wmove(cw, 0, 0);
|
||||
wclrtoeol(cw);
|
||||
status(FALSE);
|
||||
touchwin(cw);
|
||||
}
|
||||
|
||||
/*
|
||||
* Real Help
|
||||
*/
|
||||
|
||||
help()
|
||||
{
|
||||
register struct h_list *strp = helpstr;
|
||||
register struct item_list *itemp = item_help;
|
||||
struct h_list *wizp = wiz_help;
|
||||
register char helpch;
|
||||
register int cnt;
|
||||
|
||||
msg("Character you want help for (* for commands, @ for items): ");
|
||||
helpch = wgetch(cw);
|
||||
mpos = 0;
|
||||
/*
|
||||
* If it's not a *, @, or +, then just print help string
|
||||
* for the character entered.
|
||||
*/
|
||||
if (helpch != '*' && helpch != '@' && helpch != '+') {
|
||||
wmove(msgw, 0, 0);
|
||||
while (strp->h_ch) {
|
||||
if (strp->h_ch == helpch) {
|
||||
msg("%s%s", unctrl(strp->h_ch), strp->h_desc);
|
||||
return;
|
||||
}
|
||||
strp++;
|
||||
}
|
||||
if (wizard) {
|
||||
while (wizp->h_ch) {
|
||||
if (wizp->h_ch == helpch) {
|
||||
msg("%s%s", unctrl(wizp->h_ch), wizp->h_desc);
|
||||
return;
|
||||
}
|
||||
wizp++;
|
||||
}
|
||||
}
|
||||
msg("Unknown command '%s'", unctrl(helpch));
|
||||
return;
|
||||
}
|
||||
|
||||
/* fortunes - but let's not say so - explicitly */
|
||||
if (helpch == '+') {
|
||||
msg("Meaningless command '+'");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print help for everything else
|
||||
*/
|
||||
if (helpch == '*') {
|
||||
wclear(hw);
|
||||
cnt = 0;
|
||||
while (strp->h_ch) {
|
||||
mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrl(strp->h_ch));
|
||||
waddstr(hw, strp->h_desc);
|
||||
strp++;
|
||||
if (++cnt >= 46 && strp->h_ch) {
|
||||
wmove(hw, lines-1, 0);
|
||||
wprintw(hw, morestr);
|
||||
draw(hw);
|
||||
wait_for(' ');
|
||||
wclear(hw);
|
||||
cnt = 0;
|
||||
}
|
||||
}
|
||||
if (wizard) {
|
||||
while (wizp->h_ch) {
|
||||
mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrl(wizp->h_ch));
|
||||
waddstr(hw, wizp->h_desc);
|
||||
wizp++;
|
||||
if (++cnt >= 46 && wizp->h_ch) {
|
||||
wmove(hw, lines-1, 0);
|
||||
wprintw(hw, morestr);
|
||||
draw(hw);
|
||||
wait_for(' ');
|
||||
wclear(hw);
|
||||
cnt = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (helpch == '@') {
|
||||
wclear(hw);
|
||||
cnt = 0;
|
||||
while (itemp->item_ch) {
|
||||
mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrl(itemp->item_ch));
|
||||
waddstr(hw, itemp->item_desc);
|
||||
itemp++;
|
||||
if (++cnt >= 46 && itemp->item_ch) {
|
||||
wmove(hw, lines-1, 0);
|
||||
wprintw(hw, morestr);
|
||||
draw(hw);
|
||||
wait_for(' ');
|
||||
wclear(hw);
|
||||
cnt = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
wmove(hw, lines-1, 0);
|
||||
wprintw(hw, spacemsg);
|
||||
draw(hw);
|
||||
wait_for(' ');
|
||||
wclear(hw);
|
||||
draw(hw);
|
||||
wmove(cw, 0, 0);
|
||||
wclrtoeol(cw);
|
||||
status(FALSE);
|
||||
touchwin(cw);
|
||||
}
|
||||
|
||||
/*
|
||||
* identify:
|
||||
* Tell the player what a certain thing is.
|
||||
*/
|
||||
|
||||
identify(ch)
|
||||
register unsigned char ch;
|
||||
{
|
||||
register char *str = NULL;
|
||||
|
||||
if (ch == 0) {
|
||||
msg("What do you want identified? ");
|
||||
ch = wgetch(cw);
|
||||
mpos = 0;
|
||||
if (ch == ESC)
|
||||
{
|
||||
msg("");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (isalpha(ch))
|
||||
msg("Use the \"=\" command to identify monsters. ");
|
||||
else switch(ch)
|
||||
{
|
||||
case VPLAYER: str = "You (visibly)";
|
||||
when IPLAYER: str = "You (invisibly)";
|
||||
when GOLD: str = "Gold";
|
||||
when STAIRS: str = (levtype == OUTSIDE) ? "Entrance to the dungeon"
|
||||
: "Stairway";
|
||||
when DOOR: str = "Doorway";
|
||||
when SECRETDOOR:str = "Secret door";
|
||||
when FLOOR: str = (levtype == OUTSIDE) ? "Meadow" : "Room floor";
|
||||
when PASSAGE: str = "Passage";
|
||||
when VERTWALL:
|
||||
case HORZWALL:
|
||||
str = (levtype == OUTSIDE) ? "Boundary of sector"
|
||||
: "Wall of a room";
|
||||
when POST: str = "Trading post";
|
||||
when POOL: str = (levtype == OUTSIDE) ? "Lake"
|
||||
: "A shimmering pool";
|
||||
when TRAPDOOR: str = "Trap door";
|
||||
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 WORMHOLE: str = "Entrance to a worm hole";
|
||||
when FOREST: str = "Forest";
|
||||
when ' ' : str = (levtype == OUTSIDE) ? "Mountain"
|
||||
: "Solid rock";
|
||||
when FOOD: str = "Food";
|
||||
when POTION: str = "Potion";
|
||||
when SCROLL: str = "Scroll";
|
||||
when RING: str = "Ring";
|
||||
when WEAPON: str = "Weapon";
|
||||
when ARMOR: str = "Armor";
|
||||
when MM: str = "Miscellaneous magic";
|
||||
when STICK: str = "Wand or staff";
|
||||
when RELIC: str = "Artifact";
|
||||
otherwise: str = "Unknown character";
|
||||
}
|
||||
if (!isalpha(ch))
|
||||
msg("%s %s", unctrl(ch), str);
|
||||
}
|
||||
|
||||
|
||||
825
xrogue/init.c
Normal file
825
xrogue/init.c
Normal file
|
|
@ -0,0 +1,825 @@
|
|||
/*
|
||||
init.c - global variable initializaton
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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"
|
||||
|
||||
/*
|
||||
* If there is any news, put it in a character string and assign it to
|
||||
* rogue_news. Otherwise, assign NULL to rogue_news.
|
||||
*/
|
||||
|
||||
static char *rogue_news = "Enter a number within the minimum and maximum \
|
||||
range. When satisfied with your choices, enter a 'y'. For help at any \
|
||||
other time enter a '?' or a '='.";
|
||||
|
||||
/* replace the above line with this when descriptions are done */
|
||||
/* other time enter a '?' or a '='. For character and item descriptions \
|
||||
enter a '\\' on any other screen.";
|
||||
*/
|
||||
|
||||
struct words 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",
|
||||
};
|
||||
|
||||
struct words sylls[NSYLLS] = {
|
||||
"a", "ae", "ak", "an", "ax", "ach", "ano", "ars", "bha", "bar", "bre",
|
||||
"cha", "cre", "cum", "cow", "duh", "dha", "e", "ea", "em", "et", "ey",
|
||||
"eck", "etk", "egg", "exl", "fu", "fen", "fid", "gan", "gle", "h", "ha",
|
||||
"hr", "ht", "how", "hex", "hip", "hoc", "i", "ia", "ig", "it", "iz",
|
||||
"ion", "ink", "ivi", "iss", "je", "jin", "jha", "jyr", "ka", "kho", "kal",
|
||||
"kli", "lu", "lre", "lta", "lri", "m", "ma", "mh", "mi", "mr", "mar",
|
||||
"myr", "moh", "mul", "nep", "nes", "o", "oc", "om", "oq", "ox", "orn",
|
||||
"oxy", "olm", "ode", "po", "pie", "pod", "pot", "qar", "que", "ran", "rah",
|
||||
"rok", "sa", "sat", "sha", "sol", "sri", "ti", "tem", "tar", "tki", "tch",
|
||||
"tox", "u", "ub", "uh", "ur", "uv", "unk", "uwh", "ugh", "uyr", "va",
|
||||
"vil", "vit", "vom", "vux", "wah", "wex", "xu", "xed", "xen", "ya", "yep",
|
||||
"yih", "zef", "zen", "zil", "zym", "-"
|
||||
};
|
||||
|
||||
struct words 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",
|
||||
"Lapis lazuli", "Malachite", "Mocca stone",
|
||||
"Moonstone", "Obsidian", "Olivine",
|
||||
"Onyx", "Opal", "Pearl",
|
||||
"Peridot", "Quartz", "Rhodochrosite",
|
||||
"Rhodolite", "Ruby", "Sapphire",
|
||||
"Sardonyx", "Serpentine", "Spinel",
|
||||
"Tiger eye", "Topaz", "Tourmaline",
|
||||
"Turquoise", "Zircon",
|
||||
};
|
||||
|
||||
struct words wood[NWOOD] = {
|
||||
"Avocado wood", "Balsa", "Banyan", "Birch",
|
||||
"Cedar", "Cherry", "Cinnabar", "Dogwood",
|
||||
"Driftwood", "Ebony", "Eucalyptus", "Hemlock",
|
||||
"Ironwood", "Mahogany", "Manzanita", "Maple",
|
||||
"Oak", "Pine", "Redwood", "Rosewood",
|
||||
"Teak", "Walnut", "Aloe", "Sandalwood",
|
||||
};
|
||||
|
||||
struct words 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;
|
||||
register char *str;
|
||||
|
||||
for (i = 0 ; i < MAXPOTIONS ; i++)
|
||||
{
|
||||
do
|
||||
str = rainbow[rnd(NCOLORS)].w_string;
|
||||
until (isupper(*str));
|
||||
*str = tolower(*str);
|
||||
p_colors[i] = str;
|
||||
p_know[i] = FALSE;
|
||||
p_guess[i] = NULL;
|
||||
if (i > 0)
|
||||
p_magic[i].mi_prob += p_magic[i-1].mi_prob;
|
||||
}
|
||||
badcheck("potions", p_magic, MAXPOTIONS);
|
||||
}
|
||||
|
||||
/*
|
||||
* do any initialization for food
|
||||
*/
|
||||
|
||||
init_foods()
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i=0; i < MAXFOODS; i++) {
|
||||
if (i > 0)
|
||||
foods[i].mi_prob += foods[i-1].mi_prob;
|
||||
}
|
||||
badcheck("foods", foods, MAXFOODS);
|
||||
}
|
||||
|
||||
/*
|
||||
* init_materials:
|
||||
* Initialize the construction materials for wands and staffs
|
||||
*/
|
||||
|
||||
init_materials()
|
||||
{
|
||||
register int i;
|
||||
register char *str;
|
||||
|
||||
for (i = 0 ; i < MAXSTICKS ; i++)
|
||||
{
|
||||
do
|
||||
if (rnd(100) > 50)
|
||||
{
|
||||
str = metal[rnd(NMETAL)].w_string;
|
||||
if (isupper(*str))
|
||||
ws_type[i] = "wand";
|
||||
}
|
||||
else
|
||||
{
|
||||
str = wood[rnd(NWOOD)].w_string;
|
||||
if (isupper(*str))
|
||||
ws_type[i] = "staff";
|
||||
}
|
||||
until (isupper(*str));
|
||||
*str = tolower(*str);
|
||||
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(5)+1;
|
||||
while(nsyl--)
|
||||
{
|
||||
sp = sylls[rnd(NSYLLS)].w_string;
|
||||
while(*sp)
|
||||
*cp++ = *sp++;
|
||||
}
|
||||
*cp++ = ' ';
|
||||
}
|
||||
*--cp = '\0';
|
||||
s_names[i] = (char *) new(strlen(prbuf)+1);
|
||||
s_know[i] = FALSE;
|
||||
s_guess[i] = NULL;
|
||||
strcpy(s_names[i], prbuf);
|
||||
if (i > 0)
|
||||
s_magic[i].mi_prob += s_magic[i-1].mi_prob;
|
||||
}
|
||||
badcheck("scrolls", s_magic, MAXSCROLLS);
|
||||
}
|
||||
|
||||
/*
|
||||
* init_player:
|
||||
* roll up the rogue
|
||||
*/
|
||||
|
||||
init_player()
|
||||
{
|
||||
int stat_total, round = 0, minimum, maximum, ch, i, j = 0;
|
||||
short do_escape, *our_stats[NUMABILITIES-1];
|
||||
struct linked_list *weap_item, *armor_item, *food_item;
|
||||
struct object *obj;
|
||||
|
||||
weap_item = armor_item = food_item = NULL;
|
||||
|
||||
if (char_type == -1) { /* not set via options */
|
||||
/* See what type character will be */
|
||||
wclear(hw);
|
||||
touchwin(hw);
|
||||
wmove(hw,2,0);
|
||||
for(i=1; i<=NUM_CHARTYPES-1; i++) {
|
||||
wprintw(hw,"[%d] %s\n",i,char_class[i-1].name);
|
||||
}
|
||||
mvwaddstr(hw, 0, 0, "What character class do you desire? ");
|
||||
draw(hw);
|
||||
char_type = (wgetch(hw) - '0');
|
||||
while (char_type < 1 || char_type > NUM_CHARTYPES-1) {
|
||||
wmove(hw,0,0);
|
||||
wprintw(hw,"Please enter a character type between 1 and %d: ",
|
||||
NUM_CHARTYPES-1);
|
||||
draw(hw);
|
||||
char_type = (wgetch(hw) - '0');
|
||||
}
|
||||
char_type--;
|
||||
}
|
||||
player.t_ctype = char_type;
|
||||
player.t_quiet = 0;
|
||||
pack = NULL;
|
||||
|
||||
/* Select the gold */
|
||||
purse = 3000;
|
||||
switch (player.t_ctype) {
|
||||
case C_FIGHTER:
|
||||
purse += 200;
|
||||
when C_MAGICIAN:
|
||||
case C_CLERIC:
|
||||
case C_DRUID:
|
||||
purse += 100;
|
||||
when C_THIEF:
|
||||
case C_ASSASSIN:
|
||||
purse += 0;
|
||||
when C_RANGER:
|
||||
case C_PALADIN:
|
||||
purse -= 100;
|
||||
when C_MONK:
|
||||
purse -= 200;
|
||||
}
|
||||
/*
|
||||
* allow me to describe a super character
|
||||
*/
|
||||
/* let's lessen the restrictions on this okay? */
|
||||
if (wizard && strcmp(getenv("SUPER"),"YES") == 0) {
|
||||
pstats.s_str = MAXATT;
|
||||
pstats.s_intel = MAXATT;
|
||||
pstats.s_wisdom = MAXATT;
|
||||
pstats.s_dext = MAXATT;
|
||||
pstats.s_const = MAXATT;
|
||||
pstats.s_charisma = MAXATT;
|
||||
pstats.s_exp = 10000000L;
|
||||
pstats.s_lvl = 1;
|
||||
pstats.s_lvladj = 0;
|
||||
pstats.s_hpt = 500;
|
||||
pstats.s_carry = totalenc(&player);
|
||||
strcpy(pstats.s_dmg,"4d8");
|
||||
check_level();
|
||||
wmove(hw,0,0);
|
||||
wclrtoeol(hw);
|
||||
draw(hw);
|
||||
mpos = 0;
|
||||
|
||||
/* set quest item */
|
||||
if(player.t_ctype == C_FIGHTER) quest_item = AXE_AKLAD;
|
||||
if(player.t_ctype == C_RANGER) quest_item = BRIAN_MANDOLIN;
|
||||
if(player.t_ctype == C_PALADIN) quest_item = HEIL_ANKH;
|
||||
if(player.t_ctype == C_MAGICIAN) quest_item = STONEBONES_AMULET;
|
||||
if(player.t_ctype == C_CLERIC) quest_item = GERYON_HORN;
|
||||
if(player.t_ctype == C_THIEF) quest_item = MUSTY_DAGGER;
|
||||
if(player.t_ctype == C_ASSASSIN) quest_item = EYE_VECNA;
|
||||
if(player.t_ctype == C_DRUID) quest_item = QUILL_NAGROM;
|
||||
if(player.t_ctype == C_MONK) quest_item = EMORI_CLOAK;
|
||||
|
||||
/* armor */
|
||||
if (player.t_ctype == C_THIEF || player.t_ctype == C_ASSASSIN)
|
||||
j = STUDDED_LEATHER;
|
||||
else if (player.t_ctype == C_MONK) {
|
||||
armor_item = spec_item(MM, MM_BRACERS, 20, 0);
|
||||
obj = OBJPTR(armor_item);
|
||||
obj->o_weight = things[TYP_MM].mi_wght;
|
||||
whatis (armor_item); /* identify it */
|
||||
obj->o_flags |= (ISKNOW | ISPROT);
|
||||
add_pack(armor_item, TRUE);
|
||||
cur_misc[WEAR_BRACERS] = obj;
|
||||
goto w_armorjmp;
|
||||
}
|
||||
else j = PLATE_ARMOR;
|
||||
|
||||
armor_item = spec_item(ARMOR, j, 20, 0);
|
||||
obj = OBJPTR(armor_item);
|
||||
obj->o_weight = armors[j].a_wght;
|
||||
obj->o_flags |= (ISKNOW | ISPROT);
|
||||
add_pack(armor_item, TRUE);
|
||||
cur_armor = obj;
|
||||
|
||||
w_armorjmp: /* monk doesn't wear armor */
|
||||
|
||||
/* weapons */
|
||||
if (player.t_ctype == C_THIEF || player.t_ctype == C_ASSASSIN ||
|
||||
player.t_ctype == C_MONK)
|
||||
j = BASWORD;
|
||||
else if (player.t_ctype == C_FIGHTER || player.t_ctype == C_RANGER ||
|
||||
player.t_ctype == C_PALADIN)
|
||||
j = TWOSWORD;
|
||||
else j = TRIDENT;
|
||||
|
||||
weap_item = spec_item(WEAPON, j, 20, 20);
|
||||
obj = OBJPTR(weap_item);
|
||||
obj->o_flags |= (ISKNOW | ISPROT);
|
||||
obj->o_weight = weaps[j].w_wght;
|
||||
add_pack(weap_item, TRUE);
|
||||
cur_weapon = obj;
|
||||
|
||||
/* food */
|
||||
food_item = spec_item(FOOD, E_RATION, 0, 0);
|
||||
obj = OBJPTR(food_item);
|
||||
obj->o_flags |= ISKNOW;
|
||||
obj->o_weight = foods[TYP_FOOD].mi_wght;
|
||||
add_pack(food_item, TRUE); /* just one */
|
||||
|
||||
/* give wizard plenty gold */
|
||||
purse = 50000;
|
||||
}
|
||||
else
|
||||
/* default attributes checked */
|
||||
{
|
||||
if (def_attr == TRUE) { /* "default" option used in ROGUEOPTS */
|
||||
switch(player.t_ctype) {
|
||||
/* set "default attributes" option and quest items here */
|
||||
case C_FIGHTER:
|
||||
case C_MONK:
|
||||
pstats.s_intel = 7;
|
||||
pstats.s_dext = 16;
|
||||
pstats.s_charisma = 11;
|
||||
if (player.t_ctype == C_FIGHTER) {
|
||||
pstats.s_str = 16;
|
||||
pstats.s_wisdom = 7;
|
||||
pstats.s_const = 17;
|
||||
quest_item = AXE_AKLAD;
|
||||
}
|
||||
else {
|
||||
pstats.s_str = 11;
|
||||
pstats.s_wisdom = 11;
|
||||
pstats.s_const = 18;
|
||||
quest_item = EMORI_CLOAK;
|
||||
}
|
||||
when C_RANGER:
|
||||
case C_PALADIN:
|
||||
pstats.s_str = 11;
|
||||
pstats.s_dext = 16;
|
||||
pstats.s_const = 16;
|
||||
pstats.s_charisma = 13;
|
||||
/* intelligence or wisdom */
|
||||
if (player.t_ctype == C_RANGER) {
|
||||
pstats.s_intel = 11;
|
||||
pstats.s_wisdom = 7;
|
||||
quest_item = BRIAN_MANDOLIN;
|
||||
}
|
||||
else {
|
||||
pstats.s_intel = 7;
|
||||
pstats.s_wisdom = 11;
|
||||
quest_item = HEIL_ANKH;
|
||||
}
|
||||
when C_THIEF:
|
||||
case C_ASSASSIN:
|
||||
pstats.s_intel = 7;
|
||||
pstats.s_str = 14;
|
||||
pstats.s_wisdom = 7;
|
||||
pstats.s_dext = 18;
|
||||
pstats.s_const = 17;
|
||||
pstats.s_charisma = 11;
|
||||
if (player.t_ctype == C_THIEF)
|
||||
quest_item = MUSTY_DAGGER;
|
||||
else
|
||||
quest_item = EYE_VECNA;
|
||||
when C_MAGICIAN:
|
||||
case C_CLERIC:
|
||||
case C_DRUID:
|
||||
pstats.s_str = 10;
|
||||
pstats.s_dext = 16;
|
||||
pstats.s_const = 15;
|
||||
pstats.s_charisma = 12;
|
||||
/* intelligence & wisdom */
|
||||
if (player.t_ctype == C_MAGICIAN) {
|
||||
pstats.s_intel = 14;
|
||||
pstats.s_wisdom = 7;
|
||||
}
|
||||
else {
|
||||
pstats.s_intel = 7;
|
||||
pstats.s_wisdom = 14;
|
||||
}
|
||||
if (player.t_ctype == C_MAGICIAN)
|
||||
quest_item = STONEBONES_AMULET;
|
||||
else if (player.t_ctype == C_CLERIC)
|
||||
quest_item = GERYON_HORN;
|
||||
else
|
||||
quest_item = QUILL_NAGROM;
|
||||
}
|
||||
/* Intialize */
|
||||
pstats.s_exp = 0L;
|
||||
pstats.s_lvl = 1;
|
||||
pstats.s_lvladj = 0;
|
||||
pstats.s_exp = 0L;
|
||||
strcpy(pstats.s_dmg,"2d4");
|
||||
pstats.s_carry = totalenc(&player);
|
||||
check_level();
|
||||
wmove(hw,0,0);
|
||||
wclrtoeol(hw);
|
||||
draw(hw);
|
||||
mpos = 0;
|
||||
|
||||
/* Get the hit points. */
|
||||
pstats.s_hpt = 12 + const_bonus(); /* Base plus bonus */
|
||||
|
||||
/* Add in the component that varies according to class */
|
||||
pstats.s_hpt += char_class[player.t_ctype].hit_pts;
|
||||
|
||||
/* dole out some armor */
|
||||
if (player.t_ctype == C_THIEF || player.t_ctype == C_ASSASSIN)
|
||||
j = STUDDED_LEATHER;
|
||||
else if (player.t_ctype == C_FIGHTER || player.t_ctype == C_RANGER ||
|
||||
player.t_ctype == C_PALADIN) {
|
||||
switch (rnd(4)) {
|
||||
case 0: j = PLATE_ARMOR;
|
||||
when 1: j = PLATE_MAIL;
|
||||
when 2: case 3: j = BANDED_MAIL;
|
||||
}
|
||||
}
|
||||
else if (player.t_ctype == C_MONK) {
|
||||
if (rnd(3) == 0) j = MM_PROTECT;
|
||||
else j = MM_BRACERS;
|
||||
armor_item = spec_item(MM, j, rnd(125)/60+3, 0);
|
||||
obj = OBJPTR(armor_item);
|
||||
obj->o_weight = things[TYP_MM].mi_wght;
|
||||
whatis (armor_item); /* identify it */
|
||||
obj->o_flags |= ISKNOW;
|
||||
add_pack(armor_item, TRUE);
|
||||
goto p_armorjmp;
|
||||
}
|
||||
else { /* other characters */
|
||||
switch (rnd(7)) {
|
||||
case 0: j = PLATE_MAIL;
|
||||
when 1: case 2: j = BANDED_MAIL;
|
||||
when 3: case 4: j = SPLINT_MAIL;
|
||||
when 5: case 6: j = PADDED_ARMOR;
|
||||
}
|
||||
}
|
||||
armor_item = spec_item(ARMOR, j, rnd(100)/85, 0);
|
||||
obj = OBJPTR(armor_item);
|
||||
obj->o_weight = armors[j].a_wght;
|
||||
obj->o_flags |= ISKNOW;
|
||||
add_pack(armor_item, TRUE);
|
||||
|
||||
p_armorjmp: /* monk doesn't wear armor */
|
||||
|
||||
/* give him a weapon */
|
||||
if (player.t_ctype == C_THIEF || player.t_ctype == C_ASSASSIN ||
|
||||
player.t_ctype == C_MONK) {
|
||||
switch (rnd(5)) {
|
||||
case 0: j = BASWORD;
|
||||
when 1: case 2: j = TRIDENT;
|
||||
when 3: case 4: j = BARDICHE;
|
||||
}
|
||||
}
|
||||
else if (player.t_ctype == C_FIGHTER || player.t_ctype == C_RANGER ||
|
||||
player.t_ctype == C_PALADIN) {
|
||||
switch (rnd(5)) {
|
||||
case 0: j= TWOSWORD;
|
||||
when 1: case 2: j= TRIDENT;
|
||||
when 3: case 4: j= SWORD;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (rnd(7)) {
|
||||
case 0: j = TRIDENT;
|
||||
when 1: case 2: j = SWORD;
|
||||
when 3: case 4: j = BARDICHE;
|
||||
when 5: j = MACE;
|
||||
when 6: j = SPETUM;
|
||||
}
|
||||
}
|
||||
weap_item = spec_item(WEAPON, j, rnd(155)/75, rnd(165)/80);
|
||||
obj = OBJPTR(weap_item);
|
||||
obj->o_weight = weaps[j].w_wght;
|
||||
obj->o_flags |= ISKNOW;
|
||||
add_pack(weap_item, TRUE);
|
||||
|
||||
/* food rations */
|
||||
food_item = spec_item(FOOD, E_RATION, 0, 0);
|
||||
obj = OBJPTR(food_item);
|
||||
obj->o_weight = foods[TYP_FOOD].mi_wght;
|
||||
obj->o_flags |= ISKNOW;
|
||||
add_pack(food_item, TRUE);
|
||||
|
||||
/* give him some fruit - coose from those w/o special effects */
|
||||
switch (rnd(6)) {
|
||||
case 0: j = E_BANANA;
|
||||
when 1: j = E_BLUEBERRY;
|
||||
when 2: j = E_ELDERBERRY;
|
||||
when 3: j = E_GUANABANA;
|
||||
when 4: j = E_CAPRIFIG;
|
||||
when 5: j = E_GOOSEBERRY;
|
||||
}
|
||||
food_item = spec_item(FOOD, j, 0, 0);
|
||||
obj = OBJPTR(food_item);
|
||||
obj->o_weight = foods[TYP_FOOD].mi_wght;
|
||||
obj->o_flags |= ISKNOW;
|
||||
add_pack(food_item, TRUE);
|
||||
|
||||
/* adjust purse */
|
||||
purse = 2000;
|
||||
}
|
||||
else { /* select attibutes */
|
||||
switch(player.t_ctype) {
|
||||
case C_FIGHTER: round = A_STRENGTH;
|
||||
when C_RANGER: round = A_CHARISMA;
|
||||
when C_PALADIN: round = A_CHARISMA;
|
||||
when C_MAGICIAN: round = A_INTELLIGENCE;
|
||||
when C_CLERIC: round = A_WISDOM;
|
||||
when C_THIEF: round = A_DEXTERITY;
|
||||
when C_ASSASSIN: round = A_DEXTERITY;
|
||||
when C_DRUID: round = A_WISDOM;
|
||||
when C_MONK: round = A_CONSTITUTION;
|
||||
}
|
||||
|
||||
do {
|
||||
wclear(hw);
|
||||
|
||||
/* If there is any news, display it */
|
||||
if (rogue_news) {
|
||||
register int i;
|
||||
|
||||
/* Print a separator line */
|
||||
wmove(hw, 12, 0);
|
||||
for (i=0; i<cols; i++) waddch(hw, '-');
|
||||
|
||||
/* Print the news */
|
||||
mvwaddstr(hw, 14, 0, rogue_news);
|
||||
}
|
||||
|
||||
stat_total = MAXSTATS;
|
||||
do_escape = FALSE; /* No escape seen yet */
|
||||
|
||||
/* Initialize abilities */
|
||||
pstats.s_intel = 0;
|
||||
pstats.s_str = 0;
|
||||
pstats.s_wisdom = 0;
|
||||
pstats.s_dext = 0;
|
||||
pstats.s_const = 0;
|
||||
pstats.s_charisma = 0;
|
||||
|
||||
/* Initialize pointer into abilities */
|
||||
our_stats[A_INTELLIGENCE] = &pstats.s_intel;
|
||||
our_stats[A_STRENGTH] = &pstats.s_str;
|
||||
our_stats[A_WISDOM] = &pstats.s_wisdom;
|
||||
our_stats[A_DEXTERITY] = &pstats.s_dext;
|
||||
our_stats[A_CONSTITUTION] = &pstats.s_const;
|
||||
|
||||
/* Let player distribute attributes */
|
||||
for (i=0; i<NUMABILITIES-1; i++) {
|
||||
wmove(hw, 2, 0);
|
||||
wprintw(hw, "You are creating a %s with %2d attribute points.",
|
||||
char_class[player.t_ctype].name, stat_total);
|
||||
|
||||
/*
|
||||
* Player must have a minimum of 7 in any attribute and 11 in
|
||||
* the player's primary attribute.
|
||||
*/
|
||||
minimum = (round == i ? 11 : 7);
|
||||
|
||||
/* Subtract out remaining minimums */
|
||||
maximum = stat_total - (7 * (NUMABILITIES-1 - i));
|
||||
|
||||
/* Subtract out remainder of profession minimum (11 - 7) */
|
||||
if (round > i) maximum -= 4;
|
||||
|
||||
/* Maximum can't be greater than 18 */
|
||||
if (maximum > 18) maximum = 18;
|
||||
|
||||
wmove(hw, 4, 0);
|
||||
wprintw(hw,
|
||||
"Minimum: %2d; Maximum: %2d (%s corrects previous entry)",
|
||||
minimum, maximum, unctrl('\b'));
|
||||
|
||||
wmove(hw, 6, 0);
|
||||
wprintw(hw, " Int: %-2d", pstats.s_intel);
|
||||
wprintw(hw, " Str: %-2d", pstats.s_str);
|
||||
wprintw(hw, " Wis: %-2d", pstats.s_wisdom);
|
||||
wprintw(hw, " Dex: %-2d", pstats.s_dext);
|
||||
wprintw(hw, " Con: %-2d", pstats.s_const);
|
||||
wprintw(hw, " Cha: %-2d", pstats.s_charisma);
|
||||
wclrtoeol(hw);
|
||||
wmove(hw, 6, 11*i + 9);
|
||||
if (do_escape == FALSE) draw(hw);
|
||||
|
||||
/* Get player's input */
|
||||
if (do_escape || maximum == minimum) {
|
||||
*our_stats[i] = maximum;
|
||||
stat_total -= maximum;
|
||||
}
|
||||
else for (;;) {
|
||||
ch = wgetch(hw);
|
||||
if (ch == '\b') { /* Backspace */
|
||||
if (i == 0) continue; /* Can't move back */
|
||||
else {
|
||||
stat_total += *our_stats[i-1];
|
||||
*our_stats[i] = 0;
|
||||
*our_stats[i-1] = 0;
|
||||
i -= 2; /* Back out */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ch == '\033') { /* Escape */
|
||||
/*
|
||||
* Escape will result in using all maximums for
|
||||
* remaining abilities.
|
||||
*/
|
||||
do_escape = TRUE;
|
||||
*our_stats[i] = maximum;
|
||||
stat_total -= maximum;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Do we have a legal digit? */
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
ch -= '0'; /* Convert it to a number */
|
||||
*our_stats[i] = 10 * *our_stats[i] + ch;
|
||||
|
||||
/* Is the number in range? */
|
||||
if (*our_stats[i] >= minimum &&
|
||||
*our_stats[i] <= maximum) {
|
||||
stat_total -= *our_stats[i];
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If it's too small, get more - 1x is the only
|
||||
* allowable case.
|
||||
*/
|
||||
if (*our_stats[i] < minimum && *our_stats[i] == 1) {
|
||||
/* Print the player's one */
|
||||
waddch(hw, '1');
|
||||
draw(hw);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Error condition */
|
||||
putchar('\007');
|
||||
*our_stats[i] = 0;
|
||||
i--; /* Rewind */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Discard extra points over 18 */
|
||||
if (stat_total > 18) stat_total = 18;
|
||||
|
||||
/* Charisma gets what's left */
|
||||
pstats.s_charisma = stat_total;
|
||||
|
||||
/* Intialize constants */
|
||||
pstats.s_lvl = 1;
|
||||
pstats.s_lvladj = 0;
|
||||
pstats.s_exp = 0L;
|
||||
strcpy(pstats.s_dmg,"2d4");
|
||||
pstats.s_carry = totalenc(&player);
|
||||
|
||||
/* Get the hit points. */
|
||||
pstats.s_hpt = 12 + const_bonus(); /* Base plus bonus */
|
||||
|
||||
/* Add in the component that varies according to class */
|
||||
pstats.s_hpt += char_class[player.t_ctype].hit_pts;
|
||||
|
||||
/* Display the character */
|
||||
wmove(hw, 2, 0);
|
||||
wprintw(hw,"You are creating a %s.",
|
||||
char_class[player.t_ctype].name);
|
||||
wclrtoeol(hw);
|
||||
|
||||
/* Get rid of max/min line */
|
||||
wmove(hw, 4, 0);
|
||||
wclrtoeol(hw);
|
||||
|
||||
wmove(hw, 6, 0);
|
||||
wprintw(hw, " Int: %2d", pstats.s_intel);
|
||||
wprintw(hw, " Str: %2d", pstats.s_str);
|
||||
wprintw(hw, " Wis: %2d", pstats.s_wisdom);
|
||||
wprintw(hw, " Dex: %2d", pstats.s_dext);
|
||||
wprintw(hw, " Con: %2d", pstats.s_const);
|
||||
wprintw(hw, " Cha: %2d", pstats.s_charisma);
|
||||
wclrtoeol(hw);
|
||||
|
||||
wmove(hw, 8, 0);
|
||||
wprintw(hw, " Hp: %2d", pstats.s_hpt);
|
||||
wclrtoeol(hw);
|
||||
|
||||
wmove(hw, 10, 0);
|
||||
wprintw(hw, " Gold: %ld", purse);
|
||||
|
||||
mvwaddstr(hw, 0, 0, "Is this character okay? ");
|
||||
draw(hw);
|
||||
} while(wgetch(hw) != 'y');
|
||||
}
|
||||
}
|
||||
pstats.s_arm = 10;
|
||||
max_stats = pstats;
|
||||
/* Set up initial movement rate */
|
||||
player.t_action = A_NIL;
|
||||
player.t_movement = 6;
|
||||
player.t_no_move = 0;
|
||||
player.t_using = NULL;
|
||||
wclear(hw);
|
||||
}
|
||||
|
||||
/*
|
||||
* init_stones:
|
||||
* Initialize the ring stone setting scheme for this time
|
||||
*/
|
||||
|
||||
init_stones()
|
||||
{
|
||||
register int i;
|
||||
register char *str;
|
||||
|
||||
for (i = 0 ; i < MAXRINGS ; i++)
|
||||
{
|
||||
do
|
||||
str = stones[rnd(NSTONES)].w_string;
|
||||
until (isupper(*str));
|
||||
*str = tolower(*str);
|
||||
r_stones[i] = str;
|
||||
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);
|
||||
}
|
||||
|
||||
563
xrogue/io.c
Normal file
563
xrogue/io.c
Normal file
|
|
@ -0,0 +1,563 @@
|
|||
/*
|
||||
io.c - Various input/output functions
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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;
|
||||
|
||||
/* VARARGS */
|
||||
void
|
||||
msg(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
/*
|
||||
* if the string is "", just clear the line
|
||||
*/
|
||||
if (*fmt == '\0')
|
||||
{
|
||||
wclear(msgw);
|
||||
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
|
||||
*/
|
||||
|
||||
/* VARARGS */
|
||||
void
|
||||
addmsg(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
doadd(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is no current message, do nothing. Otherwise, prompt the
|
||||
* player with the --More-- string. Then erase the message.
|
||||
*/
|
||||
|
||||
rmmsg()
|
||||
{
|
||||
if (mpos) {
|
||||
wclear(msgw);
|
||||
overwrite(cw, msgw);
|
||||
mvwaddstr(msgw, 0, 0, huh);
|
||||
waddstr(msgw, morestr);
|
||||
clearok(msgw, FALSE);
|
||||
draw(msgw);
|
||||
wait_for(' ');
|
||||
msg("");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Display a new msg (giving him a chance to see the previous one if it
|
||||
* is up there with the --More--)
|
||||
*/
|
||||
|
||||
endmsg()
|
||||
{
|
||||
/* Needed to track where we are for 5.0 (PC) curses */
|
||||
register int x, y;
|
||||
|
||||
if (mpos) {
|
||||
/*
|
||||
* If this message will fit on the line (plus space for --More--)
|
||||
* then just add it (only during combat).
|
||||
*/
|
||||
if (player.t_quiet < 0 && mpos + newpos + strlen(morestr) + 5 < cols) {
|
||||
wmove(msgw, 0, mpos + 5);
|
||||
newpos += mpos + 5;
|
||||
strcat(huh, " ");
|
||||
}
|
||||
else {
|
||||
wclear(msgw);
|
||||
overwrite(cw, msgw);
|
||||
mvwaddstr(msgw, 0, 0, huh);
|
||||
waddstr(msgw, morestr);
|
||||
clearok(msgw, FALSE);
|
||||
draw(msgw);
|
||||
wait_for(' ');
|
||||
wclear(msgw);
|
||||
overwrite(cw, msgw);
|
||||
wmove(msgw, 0, 0);
|
||||
huh[0] = '\0';
|
||||
}
|
||||
}
|
||||
else {
|
||||
wclear(msgw);
|
||||
overwrite(cw, msgw);
|
||||
wmove(msgw, 0, 0);
|
||||
huh[0] = '\0';
|
||||
}
|
||||
strcat(huh, msgbuf);
|
||||
mvwaddstr(msgw, 0, 0, huh);
|
||||
getyx(msgw, y, x);
|
||||
mpos = newpos;
|
||||
newpos = 0;
|
||||
wmove(msgw, y, x);
|
||||
clearok(msgw, FALSE);
|
||||
draw(msgw);
|
||||
}
|
||||
|
||||
doadd(char *fmt, va_list ap)
|
||||
{
|
||||
vsprintf((char *) &msgbuf[newpos], fmt, ap);
|
||||
newpos = strlen(msgbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* step_ok:
|
||||
* returns true if it is ok for type to step on ch
|
||||
* flgptr will be NULL if we don't know what the monster is yet!
|
||||
*/
|
||||
|
||||
step_ok(y, x, can_on_monst, flgptr)
|
||||
register int y, x, can_on_monst;
|
||||
register struct thing *flgptr;
|
||||
{
|
||||
/* can_on_monst = MONSTOK if all we care about are physical obstacles */
|
||||
register struct linked_list *item;
|
||||
register struct thing *tp;
|
||||
unsigned char ch;
|
||||
|
||||
/* What is here? Don't check monster window if MONSTOK is set */
|
||||
if (can_on_monst == MONSTOK) ch = mvinch(y, x);
|
||||
else ch = winat(y, x);
|
||||
|
||||
if (can_on_monst == FIGHTOK && isalpha(ch) &&
|
||||
(item = find_mons(y, x)) != NULL) {
|
||||
tp = THINGPTR(item); /* What monster is here? */
|
||||
|
||||
/* We can hit it if we're after it */
|
||||
if (flgptr->t_dest == &tp->t_pos) return TRUE;
|
||||
|
||||
/*
|
||||
* Otherwise, if we're friendly we'll hit it unless it is also
|
||||
* friendly or is our race.
|
||||
*/
|
||||
if (off(*flgptr, ISFRIENDLY) ||
|
||||
on(*tp, ISFRIENDLY) ||
|
||||
flgptr->t_index == tp->t_index) return FALSE;
|
||||
else return TRUE;
|
||||
}
|
||||
else switch (ch)
|
||||
{
|
||||
case ' ':
|
||||
case VERTWALL:
|
||||
case HORZWALL:
|
||||
case SECRETDOOR:
|
||||
if (flgptr && on(*flgptr, CANINWALL)) return(TRUE);
|
||||
return FALSE;
|
||||
when SCROLL:
|
||||
if (can_on_monst == MONSTOK) { /* Not a real obstacle */
|
||||
move_free = 0; /* check free movement */
|
||||
return(TRUE);
|
||||
}
|
||||
/*
|
||||
* 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) {
|
||||
move_free = 1;
|
||||
item = find_obj(y, x);
|
||||
if (item != NULL &&
|
||||
(OBJPTR(item))->o_which==S_SCARE &&
|
||||
(flgptr == NULL || flgptr->t_stats.s_intel < 17)) {
|
||||
move_free = 2;
|
||||
return(FALSE); /* All but smart ones are scared */
|
||||
}
|
||||
}
|
||||
return(TRUE);
|
||||
otherwise:
|
||||
return (!isalpha(ch));
|
||||
}
|
||||
/* return(FALSE); */
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
* shoot_ok:
|
||||
* returns true if it is ok for type to shoot over ch
|
||||
*/
|
||||
|
||||
shoot_ok(int ch)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case ' ':
|
||||
case VERTWALL:
|
||||
case HORZWALL:
|
||||
case SECRETDOOR:
|
||||
case FOREST:
|
||||
return FALSE;
|
||||
default:
|
||||
return (!isalpha(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;
|
||||
char buf[LINELEN];
|
||||
static int hpwidth = 0, s_hungry = -1;
|
||||
static int s_lvl = -1, s_hp = -1, s_str, maxs_str,
|
||||
s_ac = 0;
|
||||
static short s_intel, s_dext, s_wisdom, s_const, s_charisma;
|
||||
static short maxs_intel, maxs_dext, maxs_wisdom, maxs_const, maxs_charisma;
|
||||
static unsigned long s_exp = 0;
|
||||
static int s_carry, s_pack;
|
||||
bool first_line=FALSE;
|
||||
|
||||
/* Go to English mode */
|
||||
nofont(cw);
|
||||
|
||||
stat_ptr = &pstats;
|
||||
max_ptr = &max_stats;
|
||||
|
||||
/*
|
||||
* If nothing has changed in the first line, then skip it
|
||||
*/
|
||||
if (!display &&
|
||||
s_lvl == level &&
|
||||
s_intel == stat_ptr->s_intel &&
|
||||
s_wisdom == stat_ptr->s_wisdom &&
|
||||
s_dext == dex_compute() &&
|
||||
s_const == stat_ptr->s_const &&
|
||||
s_charisma == stat_ptr->s_charisma &&
|
||||
s_str == str_compute() &&
|
||||
s_hungry == hungry_state &&
|
||||
maxs_intel == max_ptr->s_intel &&
|
||||
maxs_wisdom == max_ptr->s_wisdom &&
|
||||
maxs_dext == max_ptr->s_dext &&
|
||||
maxs_const == max_ptr->s_const &&
|
||||
maxs_charisma == max_ptr->s_charisma &&
|
||||
maxs_str == max_ptr->s_str ) goto line_two;
|
||||
|
||||
/* Display the first line */
|
||||
first_line = TRUE;
|
||||
getyx(cw, oy, ox);
|
||||
sprintf(buf, "Int:%d(%d) Str:%d", stat_ptr->s_intel,
|
||||
max_ptr->s_intel, str_compute());
|
||||
|
||||
/* Maximum strength */
|
||||
pb = &buf[strlen(buf)];
|
||||
sprintf(pb, "(%d)", max_ptr->s_str);
|
||||
|
||||
pb = &buf[strlen(buf)];
|
||||
sprintf(pb, " Wis:%d(%d) Dxt:%d(%d) Con:%d(%d) Cha:%d(%d)",
|
||||
stat_ptr->s_wisdom,max_ptr->s_wisdom,dex_compute(),max_ptr->s_dext,
|
||||
stat_ptr->s_const,max_ptr->s_const,stat_ptr->s_charisma,
|
||||
max_ptr->s_charisma);
|
||||
|
||||
/* Update first line status */
|
||||
s_intel = stat_ptr->s_intel;
|
||||
s_wisdom = stat_ptr->s_wisdom;
|
||||
s_dext = dex_compute();
|
||||
s_const = stat_ptr->s_const;
|
||||
s_charisma = stat_ptr->s_charisma;
|
||||
s_str = str_compute();
|
||||
maxs_intel = max_ptr->s_intel;
|
||||
maxs_wisdom = max_ptr->s_wisdom;
|
||||
maxs_dext = max_ptr->s_dext;
|
||||
maxs_const = max_ptr->s_const;
|
||||
maxs_charisma = max_ptr->s_charisma;
|
||||
maxs_str = max_ptr->s_str;
|
||||
|
||||
/* Print the line */
|
||||
mvwaddstr(cw, lines-2, 0, buf);
|
||||
switch (hungry_state) {
|
||||
case F_SATIATED:
|
||||
waddstr(cw, " Satiated");
|
||||
when F_OKAY: ;
|
||||
when F_HUNGRY:
|
||||
waddstr(cw, " Hungry");
|
||||
when F_WEAK:
|
||||
waddstr(cw, " Weak");
|
||||
when F_FAINT:
|
||||
waddstr(cw, " Fainting");
|
||||
}
|
||||
wclrtoeol(cw);
|
||||
s_hungry = hungry_state;
|
||||
|
||||
/*
|
||||
* If nothing has changed since the last status, don't
|
||||
* bother.
|
||||
*/
|
||||
line_two:
|
||||
if (!display &&
|
||||
s_lvl == level &&
|
||||
s_hp == stat_ptr->s_hpt &&
|
||||
s_ac == ac_compute(FALSE) - dext_prot(s_dext) &&
|
||||
s_pack == stat_ptr->s_pack &&
|
||||
s_carry == stat_ptr->s_carry &&
|
||||
s_exp == stat_ptr->s_exp ) {
|
||||
newfont(cw);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!first_line) getyx(cw, oy, ox);
|
||||
if (s_hp != max_ptr->s_hpt) {
|
||||
temp = s_hp = max_ptr->s_hpt;
|
||||
for (hpwidth = 0; temp; hpwidth++)
|
||||
temp /= 10;
|
||||
}
|
||||
sprintf(buf, "Lvl:%d Hp:%*d(%*d) Ac:%d Carry:%d(%d) Exp:%d/%lu %s",
|
||||
level, hpwidth, stat_ptr->s_hpt, hpwidth, max_ptr->s_hpt,
|
||||
ac_compute(FALSE) - dext_prot(s_dext),stat_ptr->s_pack/10,
|
||||
stat_ptr->s_carry/10, stat_ptr->s_lvl, stat_ptr->s_exp,
|
||||
cnames[player.t_ctype][min(stat_ptr->s_lvl-1, NUM_CNAMES-1)]);
|
||||
|
||||
/*
|
||||
* Save old status
|
||||
*/
|
||||
s_lvl = level;
|
||||
s_hp = stat_ptr->s_hpt;
|
||||
s_ac = ac_compute(FALSE) - dext_prot(s_dext);
|
||||
s_pack = stat_ptr->s_pack;
|
||||
s_carry = stat_ptr->s_carry;
|
||||
s_exp = stat_ptr->s_exp;
|
||||
mvwaddstr(cw, lines-1, 0, buf);
|
||||
wclrtoeol(cw);
|
||||
newfont(cw);
|
||||
wmove(cw, oy, ox);
|
||||
}
|
||||
|
||||
/*
|
||||
* wait_for
|
||||
* Sit around until the guy types the right key
|
||||
*/
|
||||
|
||||
wait_for(ch)
|
||||
register char ch;
|
||||
{
|
||||
register char c;
|
||||
|
||||
clearok(msgw, FALSE);
|
||||
if (ch == '\n') {
|
||||
while ((c = wgetch(msgw)) != '\n' && c != '\r') {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (wgetch(msgw) != ch) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* over_win:
|
||||
* Given a current window, a new window, and the max y and x of the
|
||||
* new window, paint the new window on top of the old window without
|
||||
* destroying any of the old window. Current window and new window
|
||||
* are assumed to have lines lines and cols columns (max y and max x
|
||||
* pertain only the the useful information to be displayed.
|
||||
* If redraw is non-zero, we wait for the character "redraw" to be
|
||||
* typed and then redraw the starting screen.
|
||||
*/
|
||||
|
||||
over_win(oldwin, newin, maxy, maxx, cursory, cursorx, redraw)
|
||||
WINDOW *oldwin, *newin;
|
||||
int maxy, maxx, cursory, cursorx;
|
||||
char redraw;
|
||||
{
|
||||
char blanks[LINELEN+1];
|
||||
register int line, i;
|
||||
WINDOW *ow; /* Overlay window */
|
||||
|
||||
/* Create a blanking line */
|
||||
for (i=0; i<maxx && i<cols && i<LINELEN; i++) blanks[i] = ' ';
|
||||
blanks[i] = '\0';
|
||||
|
||||
/* Create the window we will display */
|
||||
ow = newwin(lines, cols, 0, 0);
|
||||
|
||||
/* Blank out the area we want to use */
|
||||
if (oldwin == cw) {
|
||||
msg("");
|
||||
line = 1;
|
||||
}
|
||||
else line = 0;
|
||||
|
||||
overwrite(oldwin, ow); /* Get a copy of the old window */
|
||||
|
||||
/* Do the remaining blanking */
|
||||
for (; line < maxy; line++) mvwaddstr(ow, line, 0, blanks);
|
||||
|
||||
overlay(newin, ow); /* Overlay our new window */
|
||||
|
||||
/* Move the cursor to the specified location */
|
||||
wmove(ow, cursory, cursorx);
|
||||
|
||||
clearok(ow, FALSE); /* Draw inventory without clearing */
|
||||
draw(ow);
|
||||
|
||||
if (redraw) {
|
||||
wait_for(redraw);
|
||||
|
||||
clearok(oldwin, FALSE); /* Setup to redraw current screen */
|
||||
touchwin(oldwin); /* clearing first */
|
||||
draw(oldwin);
|
||||
}
|
||||
|
||||
delwin(ow);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* show_win:
|
||||
* function used to display a window and wait before returning
|
||||
*/
|
||||
|
||||
show_win(scr, message)
|
||||
register WINDOW *scr;
|
||||
char *message;
|
||||
{
|
||||
mvwaddstr(scr, 0, 0, message);
|
||||
touchwin(scr);
|
||||
wmove(scr, hero.y, hero.x);
|
||||
draw(scr);
|
||||
wait_for(' ');
|
||||
restscr(cw);
|
||||
}
|
||||
|
||||
/*
|
||||
* dbotline:
|
||||
* Displays message on bottom line and waits for a space to return
|
||||
*/
|
||||
|
||||
dbotline(scr,message)
|
||||
WINDOW *scr;
|
||||
char *message;
|
||||
{
|
||||
mvwaddstr(scr,lines-1,0,message);
|
||||
draw(scr);
|
||||
wait_for(' ');
|
||||
}
|
||||
|
||||
/*
|
||||
* restscr:
|
||||
* Restores the screen to the terminal
|
||||
*/
|
||||
|
||||
restscr(scr)
|
||||
WINDOW *scr;
|
||||
{
|
||||
clearok(scr,TRUE);
|
||||
touchwin(scr);
|
||||
draw(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);
|
||||
}
|
||||
|
||||
246
xrogue/list.c
Normal file
246
xrogue/list.c
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
list.c - Functions for dealing with linked lists of goodies
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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(obj);
|
||||
FREE(item);
|
||||
}
|
||||
|
||||
/*
|
||||
r_free_fire_list
|
||||
Throw the whole list of fire monsters away. But don't
|
||||
discard the item (monster) itself as that belong to mlist.
|
||||
*/
|
||||
|
||||
_r_free_fire_list(ptr)
|
||||
register struct linked_list **ptr;
|
||||
{
|
||||
register struct linked_list *item;
|
||||
|
||||
while (*ptr != NULL)
|
||||
{
|
||||
item = *ptr;
|
||||
*ptr = next(item);
|
||||
free(item);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* r_free_list:
|
||||
* Throw the whole list of room exits away
|
||||
*/
|
||||
|
||||
_r_free_list(ptr)
|
||||
register struct linked_list **ptr;
|
||||
{
|
||||
register struct linked_list *item;
|
||||
|
||||
while (*ptr != NULL)
|
||||
{
|
||||
item = *ptr;
|
||||
*ptr = next(item);
|
||||
r_discard(item);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* r_discard:
|
||||
* free up an item and its room
|
||||
*/
|
||||
|
||||
r_discard(item)
|
||||
register struct linked_list *item;
|
||||
{
|
||||
total -= 2;
|
||||
FREE(DOORPTR(item));
|
||||
FREE(item);
|
||||
}
|
||||
|
||||
/*
|
||||
* t_free_list:
|
||||
* Throw the whole thing list away
|
||||
*/
|
||||
|
||||
_t_free_list(ptr)
|
||||
register struct linked_list **ptr;
|
||||
{
|
||||
register struct linked_list *item;
|
||||
|
||||
while (*ptr != NULL)
|
||||
{
|
||||
item = *ptr;
|
||||
*ptr = next(item);
|
||||
t_discard(item);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* t_discard:
|
||||
* free up an item and its thing
|
||||
*/
|
||||
|
||||
t_discard(item)
|
||||
register struct linked_list *item;
|
||||
{
|
||||
register struct thing *tp;
|
||||
|
||||
total -= 2;
|
||||
tp = THINGPTR(item);
|
||||
if (tp->t_name != NULL) FREE(tp->t_name);
|
||||
if (tp->t_pack != NULL)
|
||||
o_free_list(tp->t_pack);
|
||||
FREE(tp);
|
||||
FREE(item);
|
||||
}
|
||||
|
||||
/*
|
||||
* destroy_item:
|
||||
* get rid of an item structure -- don't worry about contents
|
||||
*/
|
||||
|
||||
destroy_item(item)
|
||||
register struct linked_list *item;
|
||||
{
|
||||
total--;
|
||||
FREE(item);
|
||||
}
|
||||
|
||||
/*
|
||||
* new_item
|
||||
* get a new item with a specified size
|
||||
*/
|
||||
|
||||
struct linked_list *
|
||||
new_item(size)
|
||||
int size;
|
||||
{
|
||||
register struct linked_list *item;
|
||||
|
||||
if ((item = (struct linked_list *) new(sizeof *item)) == NULL)
|
||||
msg("Ran out of memory for header after %d items", total);
|
||||
if ((item->l_data = new(size)) == NULL)
|
||||
msg("Ran out of memory for data after %d items", total);
|
||||
item->l_next = item->l_prev = NULL;
|
||||
memset(item->l_data,0,size);
|
||||
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);
|
||||
|
||||
if (space == NULL) {
|
||||
sprintf(prbuf,"Rogue ran out of memory (used = %d, wanted = %d).",
|
||||
md_memused(), size);
|
||||
fatal(prbuf);
|
||||
}
|
||||
total++;
|
||||
return space;
|
||||
}
|
||||
|
||||
58
xrogue/mach_dep.h
Normal file
58
xrogue/mach_dep.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
mach_dep.h - machine dependents
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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/undefine that the wizard commands exist
|
||||
*/
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define fstat _fstat
|
||||
#define stat _stat
|
||||
#define open _open
|
||||
#define popen _popen
|
||||
#define pclose _pclose
|
||||
#if !defined(__MINGW32__)
|
||||
#define PATH_MAX _MAX_PATH
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define NOOP(x) (x += 0)
|
||||
|
||||
extern char *md_getusername();
|
||||
extern char *md_gethomedir();
|
||||
extern char *md_getroguedir();
|
||||
extern void md_flushinp();
|
||||
extern char *md_getshell();
|
||||
extern char *md_gethostname();
|
||||
extern void md_dobinaryio();
|
||||
extern char *md_getpass();
|
||||
extern void md_init();
|
||||
extern char *xcrypt();
|
||||
|
||||
/*
|
||||
* define if you want to limit scores to one per class per userid
|
||||
*/
|
||||
|
||||
/* #define LIMITSCORE 1*/
|
||||
#undef LIMITSCORE
|
||||
|
||||
/*
|
||||
* fudge factor allowed in time for saved game
|
||||
*/
|
||||
|
||||
#define FUDGE_TIME 200
|
||||
438
xrogue/main.c
Normal file
438
xrogue/main.c
Normal file
|
|
@ -0,0 +1,438 @@
|
|||
/*
|
||||
main.c - setup code
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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 <signal.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "mach_dep.h"
|
||||
#include "network.h"
|
||||
#include "rogue.h"
|
||||
|
||||
main(argc, argv, envp)
|
||||
char **argv;
|
||||
char **envp;
|
||||
{
|
||||
register char *env;
|
||||
time_t now;
|
||||
|
||||
md_init();
|
||||
|
||||
/*
|
||||
* get home and options from environment
|
||||
*/
|
||||
|
||||
strncpy(home, md_gethomedir(), LINELEN);
|
||||
|
||||
/* Get default save file */
|
||||
strcpy(file_name, home);
|
||||
strcat(file_name, "xrogue.sav");
|
||||
|
||||
/* Get default score file */
|
||||
strcpy(score_file, md_getroguedir());
|
||||
|
||||
if (*score_file)
|
||||
strcat(score_file,"/");
|
||||
|
||||
strcat(score_file, "xrogue.scr");
|
||||
|
||||
if ((env = getenv("ROGUEOPTS")) != NULL)
|
||||
parse_opts(env);
|
||||
|
||||
if (whoami[0] == '\0')
|
||||
strucpy(whoami, md_getusername(), strlen(md_getusername()));
|
||||
|
||||
/*
|
||||
* check for print-score option
|
||||
*/
|
||||
if (argc == 2 && strcmp(argv[1], "-s") == 0)
|
||||
{
|
||||
waswizard = TRUE;
|
||||
score((long)0, SCOREIT, (short)0);
|
||||
exit_game(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for a network update
|
||||
*/
|
||||
if (argc == 2 && strcmp(argv[1], "-u") == 0) {
|
||||
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_game(0);
|
||||
else {
|
||||
score((long)amount, UPDATE, (short)monster);
|
||||
exit_game(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if he is a wizard
|
||||
*/
|
||||
if (argc >= 2 && argv[1][0] == '\0')
|
||||
if (strcmp(PASSWD, xcrypt(md_getpass("Wizard's password: "), "mT")) == 0)
|
||||
{
|
||||
wizard = TRUE;
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
|
||||
if (betaover())
|
||||
{
|
||||
printf("Sorry, %s, but the test period of this prerelease version\n",whoami);
|
||||
printf("of xrogue is over. Please acquire a new version. Sorry.\n");
|
||||
exit_game(0);
|
||||
}
|
||||
|
||||
if (!wizard && !author() && !playtime()) {
|
||||
printf("Sorry, %s, but you can't play during working hours.\n", whoami);
|
||||
printf("Try again later.\n");
|
||||
exit_game(0);
|
||||
}
|
||||
if (!wizard && !author() && too_much()) {
|
||||
printf("Sorry, %s, but the system is too loaded now.\n", whoami);
|
||||
printf("Try again later.\n");
|
||||
exit_game(0);
|
||||
}
|
||||
|
||||
if (argc == 2)
|
||||
if (!restore(argv[1], envp)) /* Note: restore will never return */
|
||||
exit_game(0);
|
||||
|
||||
if (wizard && getenv("SEED") != NULL) {
|
||||
seed = atoi(getenv("SEED"));
|
||||
}
|
||||
else {
|
||||
seed = (int) time(&now) + getpid();
|
||||
}
|
||||
if (wizard)
|
||||
printf("Hello %s, welcome to dungeon #%d", whoami, seed);
|
||||
else
|
||||
printf("Hello %s, just a moment while I dig the dungeon...", whoami);
|
||||
fflush(stdout);
|
||||
|
||||
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 */
|
||||
init_names(); /* Set up names of scrolls */
|
||||
init_misc(); /* Set up miscellaneous magic */
|
||||
init_foods(); /* set up the food table */
|
||||
|
||||
initscr(); /* Start up cursor package */
|
||||
|
||||
typeahead(-1); /* turn off 3.2/4.0 curses feature */
|
||||
|
||||
if (COLS < MINCOLS)
|
||||
{
|
||||
printf("\n\nSorry, %s, but your terminal window has too few columns.\n", whoami);
|
||||
printf("Your terminal has %d columns, needs 70.\n",COLS);
|
||||
byebye(0);
|
||||
}
|
||||
if (LINES < MINLINES)
|
||||
{
|
||||
printf("\n\nSorry, %s, but your terminal window has too few lines.\n", whoami);
|
||||
printf("Your terminal has %d lines, needs 22.\n",LINES);
|
||||
byebye(0);
|
||||
}
|
||||
|
||||
cols = COLS;
|
||||
lines = LINES;
|
||||
|
||||
if ( cols % 2 != 0) cols -=1; /* must be even for maze code */
|
||||
if (lines % 2 != 0) lines -=1; /* must be even for maze code */
|
||||
|
||||
/*
|
||||
* Now that we have cols and lines, we can update our window
|
||||
* structure for non-hardware windows.
|
||||
*/
|
||||
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);
|
||||
if (cw == NULL || hw == NULL || mw == NULL || msgw == NULL) {
|
||||
exit_game(EXIT_CLS | EXIT_ENDWIN);
|
||||
}
|
||||
|
||||
keypad(cw, TRUE);
|
||||
keypad(hw, TRUE);
|
||||
|
||||
init_player(); /* Roll up the rogue */
|
||||
waswizard = wizard;
|
||||
|
||||
draw(cw);
|
||||
/* A super wizard doesn't have to get equipped */
|
||||
/* Check if "" option is TRUE and get environment flag */
|
||||
if (wizard && strcmp(getenv("SUPER"),"YES") == 0 ||
|
||||
def_attr == TRUE) {
|
||||
level = 1;
|
||||
new_level(NORMLEV);
|
||||
}
|
||||
else
|
||||
new_level(STARTLEV); /* Draw current level */
|
||||
|
||||
/*
|
||||
* Start up daemons and fuses
|
||||
*/
|
||||
daemon(doctor, &player, AFTER);
|
||||
fuse(swander, (VOID *)NULL, WANDERTIME, AFTER);
|
||||
/* Give characters their innate abilities */
|
||||
if (player.t_ctype == C_MAGICIAN || player.t_ctype == C_RANGER)
|
||||
fuse(spell_recovery, (VOID *)NULL, SPELLTIME, AFTER);
|
||||
if (player.t_ctype == C_DRUID || player.t_ctype == C_MONK)
|
||||
fuse(chant_recovery, (VOID *)NULL, SPELLTIME, AFTER);
|
||||
if (player.t_ctype == C_CLERIC || player.t_ctype == C_PALADIN)
|
||||
fuse(prayer_recovery, (VOID *)NULL, SPELLTIME, AFTER);
|
||||
daemon(stomach, (VOID *)NULL, AFTER);
|
||||
if (player.t_ctype == C_THIEF ||
|
||||
player.t_ctype == C_ASSASSIN ||
|
||||
player.t_ctype == C_MONK)
|
||||
daemon(trap_look, (VOID *)NULL, AFTER);
|
||||
|
||||
/* Does this character have any special knowledge? */
|
||||
switch (player.t_ctype) {
|
||||
case C_ASSASSIN:
|
||||
/* Assassins automatically recognize poison */
|
||||
p_know[P_POISON] = TRUE;
|
||||
when C_FIGHTER:
|
||||
/* Fighters automatically recognize skill */
|
||||
p_know[P_SKILL] = TRUE;
|
||||
}
|
||||
|
||||
/* Choose an initial quest item */
|
||||
if (!wizard) {
|
||||
if (def_attr == FALSE)
|
||||
quest_item = rnd(MAXRELIC);
|
||||
}
|
||||
mpos = 0;
|
||||
draw(cw);
|
||||
msg("You have been quested to retrieve the %s....",
|
||||
rel_magic[quest_item].mi_name);
|
||||
mpos = 0;
|
||||
playit();
|
||||
}
|
||||
|
||||
/*
|
||||
* endit:
|
||||
* Exit the program abnormally.
|
||||
*/
|
||||
|
||||
/*UNUSED*/
|
||||
void
|
||||
endit(sig)
|
||||
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);
|
||||
printf("\n"); /* So the curser doesn't stop at the end of the line */
|
||||
exit_game(EXIT_ENDWIN);
|
||||
}
|
||||
|
||||
/*
|
||||
* rnd:
|
||||
* Pick a very random number.
|
||||
*/
|
||||
|
||||
rnd(range)
|
||||
register int range;
|
||||
{
|
||||
return( 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;
|
||||
}
|
||||
|
||||
setup()
|
||||
{
|
||||
md_setup();
|
||||
}
|
||||
|
||||
/*
|
||||
* playit:
|
||||
* The main loop of the program. Loop until the game is over,
|
||||
* refreshing things and looking at the proper times.
|
||||
*/
|
||||
|
||||
playit()
|
||||
{
|
||||
register char *opts;
|
||||
|
||||
/*
|
||||
* parse environment declaration of options
|
||||
*/
|
||||
if ((opts = getenv("ROGUEOPTS")) != NULL)
|
||||
parse_opts(opts);
|
||||
|
||||
player.t_oldpos = hero;
|
||||
oldrp = roomin(&hero);
|
||||
after = TRUE;
|
||||
command(); /* Command execution */
|
||||
endit(-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* see if the system is being used too much for this game
|
||||
*/
|
||||
|
||||
too_much()
|
||||
{
|
||||
/* we no longer do load checking or user counts */
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* author:
|
||||
* See if a user is an author of the program
|
||||
*/
|
||||
|
||||
author()
|
||||
{
|
||||
switch (md_getuid()) {
|
||||
case 0: /* always OK for root to play */
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* playtime:
|
||||
* Returns TRUE when it is a good time to play rogue
|
||||
*/
|
||||
|
||||
playtime()
|
||||
{
|
||||
/* we no longer do playtime checking */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* betaover:
|
||||
* Returns TRUE if the test period of this version of the game is over
|
||||
*/
|
||||
|
||||
betaover()
|
||||
{
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
|
||||
exit_game(flag)
|
||||
int flag;
|
||||
{
|
||||
int i;
|
||||
|
||||
if (flag & EXIT_CLS) /* Clear Screen */
|
||||
{
|
||||
wclear(cw);
|
||||
draw(cw);
|
||||
}
|
||||
|
||||
if (flag & EXIT_ENDWIN) /* Shutdown Curses */
|
||||
{
|
||||
keypad(cw,FALSE);
|
||||
keypad(hw,FALSE);
|
||||
delwin(cw);
|
||||
delwin(mw);
|
||||
delwin(hw);
|
||||
delwin(msgw);
|
||||
if (!isendwin())
|
||||
endwin();
|
||||
}
|
||||
o_free_list(player.t_pack);
|
||||
t_free_list(mlist);
|
||||
t_free_list(rlist);
|
||||
t_free_list(tlist);
|
||||
o_free_list(lvl_obj); /* Free up previous objects (if any) */
|
||||
for (i = 0; i < MAXROOMS; i++)
|
||||
{
|
||||
r_free_list(rooms[i].r_exit); /* Free up the exit lists */
|
||||
_r_free_fire_list(&rooms[i].r_fires);
|
||||
}
|
||||
|
||||
for(i=0; i<MAXSCROLLS; i++)
|
||||
{
|
||||
if (s_names[i] != NULL)
|
||||
free( s_names[i] );
|
||||
if (s_guess[i] != NULL)
|
||||
free( s_guess[i] );
|
||||
}
|
||||
|
||||
for(i=0; i<MAXPOTIONS; i++)
|
||||
{
|
||||
if (p_guess[i] != NULL)
|
||||
free( p_guess[i] );
|
||||
}
|
||||
|
||||
for(i=0; i<MAXRINGS; i++)
|
||||
{
|
||||
if (r_guess[i] != NULL)
|
||||
free( r_guess[i] );
|
||||
}
|
||||
|
||||
for(i=0; i<MAXSTICKS; i++)
|
||||
{
|
||||
if (ws_guess[i] != NULL)
|
||||
free( ws_guess[i] );
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
385
xrogue/maze.c
Normal file
385
xrogue/maze.c
Normal file
|
|
@ -0,0 +1,385 @@
|
|||
/*
|
||||
maze.c - functions for dealing with mazes
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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 <stdlib.h>
|
||||
#include <curses.h>
|
||||
#include "rogue.h"
|
||||
|
||||
struct cell {
|
||||
char y_pos;
|
||||
char x_pos;
|
||||
};
|
||||
struct b_cellscells {
|
||||
char num_pos; /* number of frontier cells next to you */
|
||||
struct cell conn[4]; /* the y,x position of above cell */
|
||||
} b_cells;
|
||||
|
||||
static char *maze_frontier, *maze_bits;
|
||||
static int maze_lines, maze_cols;
|
||||
static char *moffset(), *foffset();
|
||||
static int rmwall(),findcells(),crankout(),draw_maze();
|
||||
|
||||
/*
|
||||
* crankout:
|
||||
* Does actual drawing of maze to window
|
||||
*/
|
||||
|
||||
static
|
||||
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(HORZWALL);
|
||||
else if(x==0 || x==cols-2) /* left | right side */
|
||||
addch(VERTWALL);
|
||||
else if (y % 2 == 0 && x % 2 == 0) {
|
||||
if(*moffset(y, x-1) || *moffset(y, x+1))
|
||||
addch(HORZWALL);
|
||||
else
|
||||
addch(VERTWALL);
|
||||
}
|
||||
else if (y % 2 == 0)
|
||||
addch(HORZWALL);
|
||||
else
|
||||
addch(VERTWALL);
|
||||
}
|
||||
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(50) + 50); /* add in one large hunk */
|
||||
attach(lvl_obj, item);
|
||||
cnt = 0;
|
||||
do {
|
||||
rnd_pos(rp, &tp);
|
||||
} until (mvinch(tp.y, tp.x) == FLOOR || cnt++ > 2500);
|
||||
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++ > 2500);
|
||||
mvaddch(tp.y, tp.x, FOOD);
|
||||
obj->o_pos = tp;
|
||||
|
||||
/* it doesn't mater if it's a treasure maze or a normal maze,
|
||||
* more than enough monsters will be genned.
|
||||
*/
|
||||
least = rnd(11)+5;
|
||||
if (least < 6) {
|
||||
least = 7;
|
||||
treas = FALSE;
|
||||
}
|
||||
else treas = TRUE;
|
||||
genmonsters(least, treas);
|
||||
|
||||
/* sometimes they're real angry */
|
||||
if (rnd(100) < 65) {
|
||||
/* protect the good charactors */
|
||||
if (player.t_ctype == C_PALADIN ||
|
||||
player.t_ctype == C_RANGER || player.t_ctype == C_MONK) {
|
||||
aggravate(TRUE, FALSE);
|
||||
}
|
||||
else {
|
||||
aggravate(TRUE, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* draw_maze:
|
||||
* Generate and draw the maze on the screen
|
||||
*/
|
||||
|
||||
static
|
||||
draw_maze()
|
||||
{
|
||||
reg int i, j, more;
|
||||
reg char *ptr;
|
||||
|
||||
maze_lines = (lines - 3) / 2;
|
||||
maze_cols = (cols - 1) / 2;
|
||||
maze_bits = ALLOC((lines - 3) * (cols - 1));
|
||||
maze_frontier = ALLOC(maze_lines * maze_cols);
|
||||
ptr = maze_frontier;
|
||||
while (ptr < (maze_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(maze_frontier);
|
||||
FREE(maze_bits);
|
||||
}
|
||||
|
||||
/*
|
||||
* findcells:
|
||||
* Figure out cells to open up
|
||||
*/
|
||||
|
||||
static findcells(y,x)
|
||||
reg int x, y;
|
||||
{
|
||||
reg int rtpos, i;
|
||||
|
||||
*foffset(y, x) = FALSE;
|
||||
b_cells.num_pos = 0;
|
||||
if (y < maze_lines - 1) { /* look below */
|
||||
if (*foffset(y + 1, x)) {
|
||||
b_cells.conn[b_cells.num_pos].y_pos = y + 1;
|
||||
b_cells.conn[b_cells.num_pos].x_pos = x;
|
||||
b_cells.num_pos += 1;
|
||||
}
|
||||
}
|
||||
if (y > 0) { /* look above */
|
||||
if (*foffset(y - 1, x)) {
|
||||
b_cells.conn[b_cells.num_pos].y_pos = y - 1;
|
||||
b_cells.conn[b_cells.num_pos].x_pos = x;
|
||||
b_cells.num_pos += 1;
|
||||
|
||||
}
|
||||
}
|
||||
if (x < maze_cols - 1) { /* look right */
|
||||
if (*foffset(y, x + 1)) {
|
||||
b_cells.conn[b_cells.num_pos].y_pos = y;
|
||||
b_cells.conn[b_cells.num_pos].x_pos = x + 1;
|
||||
b_cells.num_pos += 1;
|
||||
}
|
||||
}
|
||||
if (x > 0) { /* look left */
|
||||
if (*foffset(y, x - 1)) {
|
||||
b_cells.conn[b_cells.num_pos].y_pos = y;
|
||||
b_cells.conn[b_cells.num_pos].x_pos = x - 1;
|
||||
b_cells.num_pos += 1;
|
||||
|
||||
}
|
||||
}
|
||||
if (b_cells.num_pos == 0) /* no neighbors available */
|
||||
return 0;
|
||||
else {
|
||||
i = rnd(b_cells.num_pos);
|
||||
rtpos = b_cells.num_pos - 1;
|
||||
rmwall(b_cells.conn[i].y_pos, b_cells.conn[i].x_pos, y, x);
|
||||
return rtpos;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* foffset:
|
||||
* Calculate memory address for frontier
|
||||
*/
|
||||
|
||||
static char *
|
||||
foffset(y, x)
|
||||
int y, x;
|
||||
{
|
||||
|
||||
return (maze_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;
|
||||
|
||||
/* Get the absolute value of y and x differences */
|
||||
absy = hero.y - y;
|
||||
absx = hero.x - x;
|
||||
if (absy < 0) absy = -absy;
|
||||
if (absx < 0) absx = -absx;
|
||||
|
||||
/* If we are standing in a wall, we can see a bit more */
|
||||
switch (winat(hero.y, hero.x)) {
|
||||
case VERTWALL:
|
||||
case HORZWALL:
|
||||
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 VERTWALL:
|
||||
case HORZWALL:
|
||||
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 VERTWALL:
|
||||
case HORZWALL:
|
||||
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;
|
||||
|
||||
if (xcheck < 0 || ycheck < 0)
|
||||
return FALSE;
|
||||
switch (winat(ycheck, xcheck)) {
|
||||
case VERTWALL:
|
||||
case HORZWALL:
|
||||
case WALL:
|
||||
case DOOR:
|
||||
case SECRETDOOR:
|
||||
return(FALSE);
|
||||
}
|
||||
start += delta;
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* moffset:
|
||||
* Calculate memory address for bits
|
||||
*/
|
||||
|
||||
static char *
|
||||
moffset(y, x)
|
||||
int y, x;
|
||||
{
|
||||
return (maze_bits + (y * (cols - 1)) + x);
|
||||
}
|
||||
|
||||
/*
|
||||
* rmwall:
|
||||
* Removes appropriate walls from the maze
|
||||
*/
|
||||
static
|
||||
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);
|
||||
}
|
||||
|
||||
1296
xrogue/misc.c
Normal file
1296
xrogue/misc.c
Normal file
File diff suppressed because it is too large
Load diff
1660
xrogue/mons_def.c
Normal file
1660
xrogue/mons_def.c
Normal file
File diff suppressed because it is too large
Load diff
865
xrogue/monsters.c
Normal file
865
xrogue/monsters.c
Normal file
|
|
@ -0,0 +1,865 @@
|
|||
/*
|
||||
monsters.c - File with various monster functions in it
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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 <string.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* Check_residue takes care of any effect of the monster
|
||||
*/
|
||||
|
||||
check_residue(tp)
|
||||
register struct thing *tp;
|
||||
{
|
||||
/*
|
||||
* Take care of special abilities
|
||||
*/
|
||||
if (on(*tp, DIDHOLD) && (--hold_count == 0)) {
|
||||
turn_off(player, ISHELD);
|
||||
turn_off(*tp, DIDHOLD);
|
||||
}
|
||||
|
||||
/* If frightened of this monster, stop */
|
||||
if (on(player, ISFLEE) &&
|
||||
player.t_dest == &tp->t_pos) turn_off(player, ISFLEE);
|
||||
|
||||
/* If monster was suffocating player, stop it */
|
||||
if (on(*tp, DIDSUFFOCATE)) {
|
||||
extinguish(suffocate);
|
||||
turn_off(*tp, DIDSUFFOCATE);
|
||||
}
|
||||
|
||||
/* If something with fire, may darken */
|
||||
if (on(*tp, HASFIRE)) {
|
||||
register struct room *rp=roomin(&tp->t_pos);
|
||||
register struct linked_list *fire_item;
|
||||
|
||||
if (rp) {
|
||||
for (fire_item = rp->r_fires; fire_item != NULL;
|
||||
fire_item = next(fire_item)) {
|
||||
if (THINGPTR(fire_item) == tp) {
|
||||
detach(rp->r_fires, fire_item);
|
||||
destroy_item(fire_item);
|
||||
if (rp->r_fires == NULL) {
|
||||
rp->r_flags &= ~HASFIRE;
|
||||
if (cansee(tp->t_pos.y, tp->t_pos.x)) light(&hero);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Creat_mons creates the specified monster -- any if 0
|
||||
*/
|
||||
|
||||
bool
|
||||
creat_mons(person, monster, report)
|
||||
struct thing *person; /* Where to create next to */
|
||||
short monster;
|
||||
bool report;
|
||||
{
|
||||
struct linked_list *nitem;
|
||||
register struct thing *tp;
|
||||
struct room *rp;
|
||||
coord *mp;
|
||||
|
||||
if (levtype == POSTLEV)
|
||||
return(FALSE);
|
||||
if ((mp = fallpos(&(person->t_pos), FALSE, 2)) != NULL) {
|
||||
nitem = new_item(sizeof (struct thing));
|
||||
new_monster(nitem,
|
||||
monster == 0 ? randmonster(FALSE, FALSE)
|
||||
: monster,
|
||||
mp,
|
||||
TRUE);
|
||||
tp = THINGPTR(nitem);
|
||||
runto(tp, &hero);
|
||||
carry_obj(tp, monsters[tp->t_index].m_carry/2); /* only half chance */
|
||||
|
||||
/* since it just got here, it is disoriented */
|
||||
tp->t_no_move = 2 * movement(tp);
|
||||
|
||||
if (on(*tp, HASFIRE)) {
|
||||
rp = roomin(&tp->t_pos);
|
||||
if (rp) {
|
||||
register struct linked_list *fire_item;
|
||||
|
||||
/* Put the new fellow in the room list */
|
||||
fire_item = creat_item();
|
||||
ldata(fire_item) = (char *) tp;
|
||||
attach(rp->r_fires, fire_item);
|
||||
|
||||
rp->r_flags |= HASFIRE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we can see this monster, set oldch to ' ' to make light()
|
||||
* think the creature used to be invisible (ie. not seen here)
|
||||
*/
|
||||
if (cansee(tp->t_pos.y, tp->t_pos.x)) tp->t_oldch = ' ';
|
||||
return(TRUE);
|
||||
}
|
||||
if (report) msg("You hear a faint cry of anguish in the distance.. ");
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Genmonsters:
|
||||
* Generate at least 'least' monsters for this single room level.
|
||||
* 'Treas' indicates whether this is a "treasure" level.
|
||||
*/
|
||||
|
||||
void
|
||||
genmonsters(least, treas)
|
||||
register int least;
|
||||
bool treas;
|
||||
{
|
||||
reg int i;
|
||||
reg struct room *rp = &rooms[0];
|
||||
reg struct linked_list *item;
|
||||
reg struct thing *mp;
|
||||
coord tp;
|
||||
|
||||
for (i = 0; i < (max(50, level) + least); i++) {
|
||||
if (!treas && rnd(100) < 65) /* put in some little buggers */
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Put the monster in
|
||||
*/
|
||||
item = new_item(sizeof *mp);
|
||||
mp = THINGPTR(item);
|
||||
do {
|
||||
rnd_pos(rp, &tp);
|
||||
} until(mvwinch(stdscr, tp.y, tp.x) == FLOOR);
|
||||
|
||||
new_monster(item, randmonster(FALSE, FALSE), &tp, FALSE);
|
||||
/*
|
||||
* See if we want to give it a treasure to carry around.
|
||||
*/
|
||||
carry_obj(mp, monsters[mp->t_index].m_carry);
|
||||
|
||||
/* Calculate a movement rate */
|
||||
mp->t_no_move = movement(mp);
|
||||
|
||||
/* Is it going to give us some light? */
|
||||
if (on(*mp, HASFIRE)) {
|
||||
register struct linked_list *fire_item;
|
||||
|
||||
fire_item = creat_item();
|
||||
ldata(fire_item) = (char *) mp;
|
||||
attach(rp->r_fires, fire_item);
|
||||
rp->r_flags |= HASFIRE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* id_monst returns the index of the monster given its letter
|
||||
*/
|
||||
|
||||
short
|
||||
id_monst(monster)
|
||||
register char monster;
|
||||
{
|
||||
register short result;
|
||||
|
||||
if (levtype == OUTSIDE) {
|
||||
result = NLEVMONS*vlevel + (NUMMONST-NUMDINOS-1);
|
||||
if (result > NUMMONST) result = NUMMONST;
|
||||
}
|
||||
else {
|
||||
result = NLEVMONS*vlevel;
|
||||
if (result > NUMMONST-NUMDINOS) result = NUMMONST-NUMDINOS;
|
||||
}
|
||||
|
||||
if (levtype == OUTSIDE) {
|
||||
for(; result>(NUMMONST-NUMDINOS-1); result--)
|
||||
if (monsters[result].m_appear == monster) return(result);
|
||||
for (result=(NLEVMONS*vlevel)+1; result <= NUMMONST-NUMDINOS; result++)
|
||||
if (monsters[result].m_appear == monster) return(result);
|
||||
}
|
||||
else {
|
||||
for(; result>0; result--)
|
||||
if (monsters[result].m_appear == monster) return(result);
|
||||
for (result=(NLEVMONS*vlevel)+1; result <= NUMMONST; result++)
|
||||
if (monsters[result].m_appear == monster) return(result);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* new_monster:
|
||||
* Pick a new monster and add it to the list
|
||||
*/
|
||||
|
||||
new_monster(item, type, cp, max_monster)
|
||||
struct linked_list *item;
|
||||
short type;
|
||||
coord *cp;
|
||||
bool max_monster;
|
||||
{
|
||||
register struct thing *tp;
|
||||
register struct monster *mp;
|
||||
register char *ip, *hitp;
|
||||
register int i, min_intel, max_intel;
|
||||
register int num_dice, num_sides=8, num_extra=0;
|
||||
|
||||
attach(mlist, item);
|
||||
tp = THINGPTR(item);
|
||||
tp->t_pack = NULL;
|
||||
tp->t_index = type;
|
||||
tp->t_wasshot = FALSE;
|
||||
tp->t_type = monsters[type].m_appear;
|
||||
tp->t_ctype = C_MONSTER;
|
||||
tp->t_action = A_NIL;
|
||||
tp->t_doorgoal.x = tp->t_doorgoal.y = -1;
|
||||
tp->t_quiet = 0;
|
||||
tp->t_dest = NULL;
|
||||
tp->t_name = NULL;
|
||||
tp->t_pos = tp->t_oldpos = *cp;
|
||||
tp->t_oldch = mvwinch(cw, cp->y, cp->x);
|
||||
mvwaddch(mw, cp->y, cp->x, tp->t_type);
|
||||
mp = &monsters[tp->t_index];
|
||||
|
||||
/* Figure out monster's hit points */
|
||||
hitp = mp->m_stats.ms_hpt;
|
||||
num_dice = atoi(hitp);
|
||||
if ((hitp = strchr(hitp, 'd')) != NULL) {
|
||||
num_sides = atoi(++hitp);
|
||||
if ((hitp = strchr(hitp, '+')) != NULL)
|
||||
num_extra = atoi(++hitp);
|
||||
}
|
||||
|
||||
tp->t_stats.s_lvladj = 0;
|
||||
tp->t_stats.s_lvl = mp->m_stats.ms_lvl;
|
||||
tp->t_stats.s_arm = mp->m_stats.ms_arm;
|
||||
strcpy(tp->t_stats.s_dmg,mp->m_stats.ms_dmg);
|
||||
tp->t_stats.s_str = mp->m_stats.ms_str;
|
||||
tp->t_stats.s_dext = mp->m_stats.ms_dex;
|
||||
tp->t_movement = mp->m_stats.ms_move;
|
||||
if (vlevel > HARDER) { /* the deeper, the meaner we get */
|
||||
tp->t_stats.s_lvl += (vlevel - HARDER);
|
||||
num_dice += (vlevel - HARDER)/2;
|
||||
tp->t_stats.s_arm -= (vlevel - HARDER) / 4;
|
||||
}
|
||||
if (max_monster)
|
||||
tp->t_stats.s_hpt = num_dice * num_sides + num_extra;
|
||||
else
|
||||
tp->t_stats.s_hpt = roll(num_dice, num_sides) + num_extra;
|
||||
tp->t_stats.s_exp = mp->m_stats.ms_exp + mp->m_add_exp*tp->t_stats.s_hpt;
|
||||
|
||||
/*
|
||||
* just initailize others values to something reasonable for now
|
||||
* maybe someday will *really* put these in monster table
|
||||
*/
|
||||
tp->t_stats.s_wisdom = 8 + rnd(7);
|
||||
tp->t_stats.s_const = 8 + rnd(7);
|
||||
tp->t_stats.s_charisma = 8 + rnd(7);
|
||||
|
||||
/* Set the initial flags */
|
||||
for (i=0; i<16; i++) tp->t_flags[i] = 0;
|
||||
for (i=0; i<MAXFLAGS; i++)
|
||||
turn_on(*tp, mp->m_flags[i]);
|
||||
|
||||
/*
|
||||
* these are the base chances that a creatures will do something
|
||||
* assuming it can. These are(or can be) modified at runtime
|
||||
* based on what the creature experiences
|
||||
*/
|
||||
tp->t_breathe = 70; /* base chance of breathing */
|
||||
tp->t_artifact = 90; /* base chance of using artifact */
|
||||
tp->t_summon = 50; /* base chance of summoning */
|
||||
tp->t_cast = 70; /* base chance of casting a spell */
|
||||
tp->t_wand = on(*tp, ISUNIQUE) ? 35 : 50; /* base chance of using wands */
|
||||
|
||||
/* suprising monsters don't always surprise you */
|
||||
if (!max_monster && on(*tp, CANSURPRISE) &&
|
||||
off(*tp, ISUNIQUE) && rnd(100) < 25)
|
||||
turn_off(*tp, CANSURPRISE);
|
||||
|
||||
/* If this monster is unique, gen it */
|
||||
if (on(*tp, ISUNIQUE)) mp->m_normal = FALSE;
|
||||
|
||||
/*
|
||||
* If it is the quartermaster, then compute his level and exp pts
|
||||
* based on the level. This will make it fair when thieves try to
|
||||
* steal and give them reasonable experience if they succeed.
|
||||
* Then fill his pack with his wares.
|
||||
*/
|
||||
if (on(*tp, CANSELL)) {
|
||||
tp->t_stats.s_exp = vlevel * 100;
|
||||
tp->t_stats.s_lvl = vlevel/2 + 1;
|
||||
make_sell_pack(tp);
|
||||
}
|
||||
|
||||
/* Normally scared monsters have a chance to not be scared */
|
||||
if (on(*tp, ISFLEE) && (rnd(4) == 0)) turn_off(*tp, ISFLEE);
|
||||
|
||||
/* Figure intelligence */
|
||||
min_intel = atoi(mp->m_intel);
|
||||
if ((ip = (char *) strchr(mp->m_intel, '-')) == NULL)
|
||||
tp->t_stats.s_intel = min_intel;
|
||||
else {
|
||||
max_intel = atoi(++ip);
|
||||
if (max_monster)
|
||||
tp->t_stats.s_intel = max_intel;
|
||||
else
|
||||
tp->t_stats.s_intel = min_intel + rnd(max_intel - min_intel);
|
||||
}
|
||||
if (vlevel > HARDER)
|
||||
tp->t_stats.s_intel += ((vlevel - HARDER)/2);
|
||||
tp->maxstats = tp->t_stats;
|
||||
|
||||
/* If the monster can shoot, it may have a weapon */
|
||||
if (on(*tp, CANSHOOT) && ((rnd(100) < (20 + vlevel)) || max_monster)) {
|
||||
struct linked_list *item1;
|
||||
register struct object *cur, *cur1;
|
||||
|
||||
item = new_item(sizeof *cur);
|
||||
item1 = new_item(sizeof *cur1);
|
||||
cur = OBJPTR(item);
|
||||
cur1 = OBJPTR(item1);
|
||||
cur->o_hplus = (rnd(4) < 3) ? 0
|
||||
: (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
|
||||
cur->o_dplus = (rnd(4) < 3) ? 0
|
||||
: (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
|
||||
cur1->o_hplus = (rnd(4) < 3) ? 0
|
||||
: (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
|
||||
cur1->o_dplus = (rnd(4) < 3) ? 0
|
||||
: (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
|
||||
strcpy(cur->o_damage,"0d0");
|
||||
strcpy(cur->o_hurldmg,"0d0");
|
||||
strcpy(cur1->o_damage,"0d0");
|
||||
strcpy(cur1->o_hurldmg,"0d0");
|
||||
cur->o_ac = cur1->o_ac = 11;
|
||||
cur->o_count = cur1->o_count = 1;
|
||||
cur->o_group = cur1->o_group = 0;
|
||||
cur->contents = cur1->contents = NULL;
|
||||
if ((cur->o_hplus <= 0) && (cur->o_dplus <= 0)) cur->o_flags = ISCURSED;
|
||||
if ((cur1->o_hplus <= 0) && (cur1->o_dplus <= 0))
|
||||
cur1->o_flags = ISCURSED;
|
||||
cur->o_flags = cur1->o_flags = 0;
|
||||
cur->o_type = cur1->o_type = WEAPON;
|
||||
cur->o_mark[0] = cur1->o_mark[0] = '\0';
|
||||
|
||||
/* The monster may use a crossbow, sling, or an arrow */
|
||||
i = rnd(100);
|
||||
if (i < 35) {
|
||||
cur->o_which = CROSSBOW;
|
||||
cur1->o_which = BOLT;
|
||||
init_weapon(cur, CROSSBOW);
|
||||
init_weapon(cur1, BOLT);
|
||||
}
|
||||
else if (i < 70) {
|
||||
cur->o_which = BOW;
|
||||
cur1->o_which = ARROW;
|
||||
init_weapon(cur, BOW);
|
||||
init_weapon(cur1, ARROW);
|
||||
}
|
||||
else {
|
||||
cur->o_which = SLING;
|
||||
cur1->o_which = ROCK;
|
||||
init_weapon(cur, SLING);
|
||||
init_weapon(cur1, ROCK);
|
||||
}
|
||||
|
||||
attach(tp->t_pack, item);
|
||||
attach(tp->t_pack, item1);
|
||||
}
|
||||
|
||||
|
||||
/* Calculate the initial movement rate */
|
||||
updpack(TRUE, tp);
|
||||
tp->t_no_move = movement(tp);
|
||||
|
||||
if (ISWEARING(R_AGGR))
|
||||
runto(tp, &hero);
|
||||
|
||||
if (on(*tp, ISDISGUISE))
|
||||
{
|
||||
char mch = 0;
|
||||
|
||||
if (tp->t_pack != NULL)
|
||||
mch = (OBJPTR(tp->t_pack))->o_type;
|
||||
else
|
||||
switch (rnd(10)) {
|
||||
case 0: mch = GOLD;
|
||||
when 1: mch = POTION;
|
||||
when 2: mch = SCROLL;
|
||||
when 3: mch = FOOD;
|
||||
when 4: mch = WEAPON;
|
||||
when 5: mch = ARMOR;
|
||||
when 6: mch = RING;
|
||||
when 7: mch = STICK;
|
||||
when 8: mch = monsters[randmonster(FALSE, FALSE)].m_appear;
|
||||
when 9: mch = MM;
|
||||
}
|
||||
tp->t_disguise = mch;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* randmonster:
|
||||
* Pick a monster to show up. The lower the level,
|
||||
* the meaner the monster.
|
||||
*/
|
||||
|
||||
short
|
||||
randmonster(wander, no_unique)
|
||||
register bool wander, no_unique;
|
||||
{
|
||||
register int d, cur_level, range, i;
|
||||
|
||||
/*
|
||||
* Do we want a merchant? Merchant is always in place 'NUMMONST'
|
||||
*/
|
||||
if (wander && monsters[NUMMONST].m_wander && rnd(100) < pstats.s_charisma/3)
|
||||
return NUMMONST;
|
||||
|
||||
cur_level = vlevel;
|
||||
range = (4*NLEVMONS)+1; /* range is 0 thru 12 */
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
if (i++ > NUMMONST-1) { /* in case all have be genocided */
|
||||
i = 0;
|
||||
if (--cur_level <= 0)
|
||||
fatal("rogue: Could not find a monster to make! ");
|
||||
}
|
||||
if (levtype == OUTSIDE) { /* create DINOSUARS */
|
||||
d = (cur_level - rnd(range/2)) + (NUMMONST-NUMDINOS-1);
|
||||
if (d < NUMMONST-NUMDINOS)
|
||||
d = (NUMMONST-NUMDINOS) + rnd(range/2);
|
||||
if (d > NUMMONST-1)
|
||||
d = (NUMMONST-NUMDINOS) + rnd(NUMDINOS);
|
||||
}
|
||||
else { /* Create NORMALs and UNIQs here */
|
||||
d = (NLEVMONS*(cur_level-1) + rnd(range) - (range-NLEVMONS-1));
|
||||
if (d < 1) d = rnd(6)+1;
|
||||
|
||||
if (d > NUMMONST-NUMDINOS-1) { /* Entire range NORMs + UNIQs */
|
||||
if (no_unique) /* Choose from last 12 NORMAL monsters */
|
||||
d = (NUMMONST-NUMDINOS-NUMUNIQUE-1) - rnd(NUMUNIQUE/5);
|
||||
else /* Choose from entire UNIQ monsters + range */
|
||||
d = (NUMMONST-NUMDINOS-1) - rnd(NUMUNIQUE+range);
|
||||
}
|
||||
/* Half-way into the UNIQs now */
|
||||
else if (d > (NUMMONST-NUMDINOS-(NUMUNIQUE/2)-1)) {
|
||||
if (no_unique) /* Choose from last 15 NORMAL monsters */
|
||||
d = (NUMMONST-NUMDINOS-NUMUNIQUE-1) - rnd(NUMUNIQUE/4);
|
||||
else /* Choose from entire UNIQ monsters + range */
|
||||
d = (NUMMONST-NUMDINOS-1) - rnd(NUMUNIQUE+range);
|
||||
}
|
||||
/* End NORMALs and begin relic bearing UNIQs */
|
||||
else if (d > (NUMMONST-NUMDINOS-NUMUNIQUE-1)) {
|
||||
if (no_unique) /* Choose from last 20 NORMAL monsters */
|
||||
d = (NUMMONST-NUMDINOS-NUMUNIQUE-1) - rnd(NUMUNIQUE/3);
|
||||
else /* Choose from first 20 UNIQ monsters */
|
||||
d = (NUMMONST-NUMDINOS-NUMUNIQUE-1) + rnd(NUMUNIQUE/3);
|
||||
}
|
||||
}
|
||||
}
|
||||
while (wander ? !monsters[d].m_wander || !monsters[d].m_normal
|
||||
: !monsters[d].m_normal);
|
||||
return d;
|
||||
}
|
||||
|
||||
/* Sell displays a menu of goods from which the player may choose
|
||||
* to purchase something.
|
||||
*/
|
||||
|
||||
sell(tp)
|
||||
register struct thing *tp;
|
||||
{
|
||||
register struct linked_list *item, *seller;
|
||||
register struct linked_list *sellpack;
|
||||
register struct object *obj;
|
||||
register long worth, min_worth;
|
||||
char buffer[LINELEN];
|
||||
|
||||
/*
|
||||
* Get a linked_list pointer to the seller. We need this in case
|
||||
* he disappears so we can set him ISDEAD.
|
||||
*/
|
||||
seller = find_mons(tp->t_pos.y, tp->t_pos.x);
|
||||
|
||||
sellpack = tp->t_pack;
|
||||
if (sellpack == NULL) {
|
||||
msg("%s looks puzzled and departs.", prname(monster_name(tp), TRUE));
|
||||
|
||||
/* Get rid of the monster */
|
||||
killed(seller, FALSE, FALSE, FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* See how much the minimum pack item is worth */
|
||||
min_worth = 100000;
|
||||
for (item = sellpack; item != NULL; item = next(item)) {
|
||||
obj = OBJPTR(item);
|
||||
obj->o_flags |= ISPOST; /* Force a long description of the item */
|
||||
worth = get_worth(obj);
|
||||
if (worth < min_worth) min_worth = worth;
|
||||
}
|
||||
|
||||
/* See if player can afford an item */
|
||||
if (min_worth > purse) {
|
||||
msg("%s eyes your small purse and departs.",
|
||||
prname(monster_name(tp), TRUE));
|
||||
|
||||
/* Get rid of the monster */
|
||||
killed(seller, FALSE, FALSE, FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Announce our intentions */
|
||||
msg("%s opens his pack. --More--", prname(monster_name(tp), TRUE));
|
||||
wait_for(' ');
|
||||
|
||||
/* Try to sell something */
|
||||
sprintf(buffer, "You got %ld gold pieces. Buy", purse);
|
||||
item = get_item(sellpack, buffer, ALL, TRUE, TRUE);
|
||||
|
||||
/* Get rid of the monster */
|
||||
if (item != NULL) detach(tp->t_pack, item); /* Take it out of the pack */
|
||||
killed(seller, FALSE, FALSE, FALSE);
|
||||
|
||||
if (item == NULL) return;
|
||||
|
||||
/* Can he afford the selected item? */
|
||||
obj = OBJPTR(item);
|
||||
|
||||
worth = get_worth(obj);
|
||||
if (worth > purse) {
|
||||
msg("You cannot afford it.");
|
||||
o_discard(item);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Charge him through the nose */
|
||||
purse -= worth;
|
||||
|
||||
/* If a stick or ring, let player know the type */
|
||||
switch (obj->o_type) {
|
||||
case RING: r_know[obj->o_which] = TRUE;
|
||||
when POTION: p_know[obj->o_which] = TRUE;
|
||||
when SCROLL: s_know[obj->o_which] = TRUE;
|
||||
when STICK: ws_know[obj->o_which] = TRUE;
|
||||
when MM: m_know[obj->o_which] = TRUE;
|
||||
|
||||
}
|
||||
|
||||
/* identify it */
|
||||
whatis (item);
|
||||
|
||||
/* Remove the POST flag that we used for get_item() */
|
||||
obj->o_flags &= ~ISPOST;
|
||||
|
||||
if (add_pack(item, FALSE) == FALSE) {
|
||||
obj->o_pos = hero;
|
||||
fall(item, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* what to do when the hero steps next to a monster
|
||||
*/
|
||||
|
||||
struct linked_list *
|
||||
wake_monster(y, x)
|
||||
int y, x;
|
||||
{
|
||||
register struct thing *tp;
|
||||
register struct linked_list *it;
|
||||
register struct room *trp;
|
||||
register char *mname;
|
||||
bool nasty; /* Will the monster "attack"? */
|
||||
|
||||
if ((it = find_mons(y, x)) == NULL) {
|
||||
msg("Wake: can't find monster in show (%d, %d)", y, x);
|
||||
return (NULL);
|
||||
}
|
||||
tp = THINGPTR(it);
|
||||
if (on(*tp, ISSTONE)) /* if stoned, don't do anything */
|
||||
return it;
|
||||
|
||||
/*
|
||||
* For now, if we are a friendly monster, we won't do any of
|
||||
* our special effects.
|
||||
*/
|
||||
if (on(*tp, ISFRIENDLY)) return it;
|
||||
|
||||
trp = roomin(&tp->t_pos); /* Current room for monster */
|
||||
|
||||
/*
|
||||
* Let greedy ones in a room guard gold
|
||||
* (except in a maze where lots of creatures would all go for the
|
||||
* same piece of gold)
|
||||
*/
|
||||
if (on(*tp, ISGREED) && off(*tp, ISRUN) && levtype != MAZELEV &&
|
||||
trp != NULL && lvl_obj != NULL) {
|
||||
register struct linked_list *item;
|
||||
register struct object *cur;
|
||||
|
||||
for (item = lvl_obj; item != NULL; item = next(item)) {
|
||||
cur = OBJPTR(item);
|
||||
if ((cur->o_type == GOLD) && (roomin(&cur->o_pos) == trp)) {
|
||||
/* Run to the gold */
|
||||
runto(tp, &cur->o_pos);
|
||||
|
||||
/* Make it worth protecting */
|
||||
cur->o_count += GOLDCALC + GOLDCALC;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Every time he sees mean monster, it might start chasing him
|
||||
*/
|
||||
if (on(*tp, ISMEAN) &&
|
||||
off(*tp, ISHELD) &&
|
||||
off(*tp, ISRUN) &&
|
||||
rnd(100) > 35 &&
|
||||
(!is_stealth(&player) || (on(*tp, ISUNIQUE) && rnd(100) > 35)) &&
|
||||
(off(player, ISINVIS) || on(*tp, CANSEE)) ||
|
||||
(trp != NULL && (trp->r_flags & ISTREAS))) {
|
||||
runto(tp, &hero);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the name; we don't want to do it until here because we need to
|
||||
* know whether the monster is still sleeping or not.
|
||||
*/
|
||||
mname = monster_name(tp);
|
||||
|
||||
/* See if the monster will bother the player */
|
||||
nasty = (on(*tp, ISRUN) && cansee(tp->t_pos.y, tp->t_pos.x));
|
||||
|
||||
/*
|
||||
* if the creature is awake and can see the player and the
|
||||
* player has the dreaded "eye of vecna" then see if the
|
||||
* creature is turned to stone
|
||||
*/
|
||||
if (cur_relic[EYE_VECNA] && nasty && off(*tp, NOSTONE) &&
|
||||
(off(player, ISINVIS) || on(*tp, CANSEE))) {
|
||||
turn_on(*tp, NOSTONE); /* only have to save once */
|
||||
if (!save(VS_PETRIFICATION, tp, -2)) {
|
||||
turn_on(*tp, ISSTONE);
|
||||
turn_off(*tp, ISRUN);
|
||||
turn_off(*tp, ISINVIS);
|
||||
turn_off(*tp, CANSURPRISE);
|
||||
turn_off(*tp, ISDISGUISE);
|
||||
msg("%s is turned to stone!", prname(mname, TRUE));
|
||||
return it;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle monsters that can gaze and do things while running
|
||||
* Player must be able to see the monster and the monster must
|
||||
* not be asleep
|
||||
*/
|
||||
if (nasty && !invisible(tp)) {
|
||||
/*
|
||||
* Confusion
|
||||
*/
|
||||
if (on(*tp, CANHUH) &&
|
||||
(off(*tp, ISINVIS) || on(player, CANSEE)) &&
|
||||
(off(*tp, CANSURPRISE) || ISWEARING(R_ALERT))) {
|
||||
if (!save(VS_MAGIC, &player, 0)) {
|
||||
if (off(player, ISCLEAR)) {
|
||||
if (find_slot(unconfuse))
|
||||
lengthen(unconfuse, HUHDURATION);
|
||||
else {
|
||||
fuse(unconfuse, (VOID *)NULL, HUHDURATION, AFTER);
|
||||
msg("%s's gaze has confused you.",prname(mname, TRUE));
|
||||
turn_on(player, ISHUH);
|
||||
}
|
||||
}
|
||||
else msg("You feel dizzy for a moment, but it quickly passes.");
|
||||
}
|
||||
else if (rnd(100) < 67)
|
||||
turn_off(*tp, CANHUH); /* Once you save, maybe that's it */
|
||||
}
|
||||
|
||||
/* Sleep */
|
||||
if(on(*tp, CANSNORE) &&
|
||||
player.t_action != A_FREEZE &&
|
||||
!save(VS_PARALYZATION, &player, 0)) {
|
||||
if (ISWEARING(R_ALERT))
|
||||
msg("You feel drowsy for a moment.. ");
|
||||
else {
|
||||
msg("%s's gaze puts you to sleep! ", prname(mname, TRUE));
|
||||
player.t_no_move += movement(&player) * SLEEPTIME;
|
||||
player.t_action = A_FREEZE;
|
||||
if (rnd(100) < 50) turn_off(*tp, CANSNORE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fear */
|
||||
if (on(*tp, CANFRIGHTEN) && !on(player, ISFLEE)) {
|
||||
turn_off(*tp, CANFRIGHTEN);
|
||||
if (!ISWEARING(R_HEROISM) &&
|
||||
!save(VS_WAND, &player, -(tp->t_stats.s_lvl/10))) {
|
||||
turn_on(player, ISFLEE);
|
||||
player.t_dest = &tp->t_pos;
|
||||
msg("The sight of %s terrifies you!", prname(mname, FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/* blinding creatures */
|
||||
if(on(*tp, CANBLIND) && !find_slot(sight)) {
|
||||
turn_off(*tp, CANBLIND);
|
||||
if (!save(VS_WAND, &player, 0)) {
|
||||
msg("The gaze of %s blinds you! ", prname(mname, FALSE));
|
||||
turn_on(player, ISBLIND);
|
||||
fuse(sight, (VOID *)NULL, rnd(30)+20, AFTER);
|
||||
light(&hero);
|
||||
}
|
||||
}
|
||||
|
||||
/* the sight of the ghost can age you! */
|
||||
if (on(*tp, CANAGE)) {
|
||||
turn_off (*tp, CANAGE);
|
||||
if (!save(VS_MAGIC, &player, 0)) {
|
||||
msg ("The sight of %s ages you!", prname(mname, FALSE));
|
||||
pstats.s_const--;
|
||||
/* max_stats.s_const--; */
|
||||
if (pstats.s_const < 1) {
|
||||
pstats.s_hpt = -1;
|
||||
death (D_CONSTITUTION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Turning to stone */
|
||||
if (on(*tp, LOOKSTONE)) {
|
||||
turn_off(*tp, LOOKSTONE);
|
||||
|
||||
if (on(player, CANINWALL))
|
||||
msg("The gaze of %s has no effect.", prname(mname, FALSE));
|
||||
else {
|
||||
if (!save(VS_PETRIFICATION, &player, 0) && rnd(100) < 5) {
|
||||
pstats.s_hpt = -1;
|
||||
msg("The gaze of %s petrifies you!", prname(mname, FALSE));
|
||||
msg("You are turned to stone!!! --More--");
|
||||
wait_for(' ');
|
||||
death(D_PETRIFY);
|
||||
}
|
||||
else {
|
||||
msg("The gaze of %s stiffens your limbs.",
|
||||
prname(mname, FALSE));
|
||||
player.t_no_move += movement(&player) * STONETIME;
|
||||
player.t_action = A_FREEZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return it;
|
||||
}
|
||||
/*
|
||||
* wanderer:
|
||||
* A wandering monster has awakened and is headed for the player
|
||||
*/
|
||||
|
||||
wanderer()
|
||||
{
|
||||
register int i;
|
||||
register struct room *hr = roomin(&hero);
|
||||
register struct linked_list *item;
|
||||
register struct thing *tp;
|
||||
register long *attr; /* Points to monsters' attributes */
|
||||
int carry; /* Chance of wanderer carrying anything */
|
||||
short rmonst; /* Our random wanderer */
|
||||
bool canteleport = FALSE, /* Can the monster teleport? */
|
||||
seehim; /* Is monster within sight? */
|
||||
coord cp;
|
||||
|
||||
rmonst = randmonster(TRUE, FALSE); /* Choose a random wanderer */
|
||||
attr = &monsters[rmonst].m_flags[0]; /* Start of attributes */
|
||||
for (i=0; i<MAXFLAGS; i++)
|
||||
if (*attr++ == CANTELEPORT) {
|
||||
canteleport = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Find a place for it -- avoid the player's room if can't teleport */
|
||||
do {
|
||||
do {
|
||||
i = rnd_room();
|
||||
} until (canteleport || hr != &rooms[i] || levtype == MAZELEV ||
|
||||
levtype == OUTSIDE);
|
||||
|
||||
/* Make sure the monster does not teleport on top of the player */
|
||||
do {
|
||||
rnd_pos(&rooms[i], &cp);
|
||||
} while (hr == &rooms[i] && ce(cp, hero));
|
||||
} until (step_ok(cp.y, cp.x, NOMONST, (struct thing *)NULL));
|
||||
|
||||
/* Create a new wandering monster */
|
||||
item = new_item(sizeof *tp);
|
||||
new_monster(item, rmonst, &cp, FALSE);
|
||||
tp = THINGPTR(item);
|
||||
runto(tp, &hero);
|
||||
tp->t_pos = cp; /* Assign the position to the monster */
|
||||
seehim = cansee(tp->t_pos.y, tp->t_pos.x);
|
||||
if (on(*tp, HASFIRE)) {
|
||||
register struct room *rp;
|
||||
|
||||
rp = roomin(&tp->t_pos);
|
||||
if (rp) {
|
||||
register struct linked_list *fire_item;
|
||||
|
||||
fire_item = creat_item();
|
||||
ldata(fire_item) = (char *) tp;
|
||||
attach(rp->r_fires, fire_item);
|
||||
|
||||
rp->r_flags |= HASFIRE;
|
||||
if (seehim && next(rp->r_fires) == NULL)
|
||||
light(&hero);
|
||||
}
|
||||
}
|
||||
|
||||
/* See if we give the monster anything */
|
||||
carry = monsters[tp->t_index].m_carry;
|
||||
if (off(*tp, ISUNIQUE)) carry /= 2; /* Non-unique has only a half chance */
|
||||
carry_obj(tp, carry);
|
||||
|
||||
/* Calculate its movement rate */
|
||||
tp->t_no_move = movement(tp);
|
||||
|
||||
/* Alert the player if a monster just teleported in */
|
||||
if (hr == &rooms[i] && canteleport && seehim && !invisible(tp)) {
|
||||
msg("A %s just teleported in", monster_name(tp));
|
||||
light(&hero);
|
||||
running = FALSE;
|
||||
}
|
||||
|
||||
if (wizard)
|
||||
msg("Started a wandering %s", monster_name(tp));
|
||||
}
|
||||
|
||||
1910
xrogue/move.c
Normal file
1910
xrogue/move.c
Normal file
File diff suppressed because it is too large
Load diff
672
xrogue/n_level.c
Normal file
672
xrogue/n_level.c
Normal file
|
|
@ -0,0 +1,672 @@
|
|||
/*
|
||||
n_level.c - Dig and draw a new level
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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:
|
||||
* Dig and draw a new level
|
||||
*/
|
||||
|
||||
new_level(ltype)
|
||||
LEVTYPE ltype; /* designates type of level to create */
|
||||
{
|
||||
register int rm = 0, i, cnt;
|
||||
register unsigned 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: %ld", 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+20 + rnd(51);
|
||||
|
||||
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) == HORZWALL) vert = TRUE;
|
||||
else vert = FALSE;
|
||||
|
||||
if (level < 1) {
|
||||
fresh = TRUE;
|
||||
starty = 2;
|
||||
startx = 1;
|
||||
deltay = deltax = 1;
|
||||
level = max_level; /* Restore level to deepest attempt */
|
||||
prev_max = level; /* reset for boundary crossings below */
|
||||
}
|
||||
else if (level >= 1 && prev_max == 1000) {
|
||||
fresh = TRUE;
|
||||
starty = 2;
|
||||
startx = 1;
|
||||
deltay = deltax = 1;
|
||||
prev_max = level; /* reset for boundary crossings below */
|
||||
}
|
||||
else { /* Copy several lines of the terrain to the other end */
|
||||
|
||||
unsigned char cch; /* Copy character */
|
||||
|
||||
if (wizard) msg("Crossing sector boundary ");
|
||||
|
||||
/* 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 = mvinch(i+2, j);
|
||||
mvaddch(lines-6+i, j, cch);
|
||||
}
|
||||
else {
|
||||
cch = mvinch(lines-4-i, j);
|
||||
mvaddch(4-i, j, cch);
|
||||
}
|
||||
}
|
||||
else
|
||||
for (j=2; j<lines-3; j++) {
|
||||
if (top) {
|
||||
cch = mvinch(j, i+1);
|
||||
mvaddch(j, cols-4+i, cch);
|
||||
}
|
||||
else {
|
||||
cch = mvinch(j, cols-2-i);
|
||||
mvaddch(j, 3-i, cch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vert) {
|
||||
startx = deltax = 1;
|
||||
if (top) {
|
||||
starty = lines-4-TERRASAVE;
|
||||
deltay = -1;
|
||||
}
|
||||
else {
|
||||
starty = TERRASAVE + 2;
|
||||
deltay = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
starty = 2;
|
||||
deltay = 1;
|
||||
if (top) {
|
||||
startx = cols-2-TERRASAVE;
|
||||
deltax = -1;
|
||||
}
|
||||
else {
|
||||
deltax = 1;
|
||||
startx = TERRASAVE + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if any monsters should be saved */
|
||||
for (item = mlist; item != NULL; item = nitem) {
|
||||
nitem = next(item);
|
||||
tp = THINGPTR(item);
|
||||
if (vert) {
|
||||
if (top) {
|
||||
if (tp->t_pos.y < TERRASAVE + 2)
|
||||
tp->t_pos.y += lines - 5 - TERRASAVE;
|
||||
else continue;
|
||||
}
|
||||
else {
|
||||
if (tp->t_pos.y > lines - 4 - TERRASAVE)
|
||||
tp->t_pos.y += 5 + TERRASAVE - lines;
|
||||
else continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (top) {
|
||||
if (tp->t_pos.x < TERRASAVE + 1)
|
||||
tp->t_pos.x += cols - 2 - TERRASAVE;
|
||||
else continue;
|
||||
}
|
||||
else {
|
||||
if (tp->t_pos.x > cols - 2 - TERRASAVE)
|
||||
tp->t_pos.x += 2 + TERRASAVE - cols;
|
||||
else continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the monster is busy chasing another monster, don't save
|
||||
* it
|
||||
*/
|
||||
if (tp->t_dest && tp->t_dest != &hero) continue;
|
||||
|
||||
/* Outside has plenty of monsters, don't need these.
|
||||
* 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 || levtype != OUTSIDE) 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(mlist);
|
||||
o_free_list(lvl_obj); /* Free up previous objects (if any) */
|
||||
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
|
||||
r_free_list(rp->r_exit); /* Free up the exit lists */
|
||||
|
||||
levtype = ltype;
|
||||
foods_this_level = 0; /* food for hero this level */
|
||||
|
||||
/* What kind of level are we on? */
|
||||
if (ltype == POSTLEV || ltype == STARTLEV) {
|
||||
if (ltype == POSTLEV)
|
||||
do_post(FALSE); /* Trading post */
|
||||
else
|
||||
do_post(TRUE); /* Equipage */
|
||||
|
||||
levtype = ltype = POSTLEV;
|
||||
}
|
||||
else if (ltype == MAZELEV) {
|
||||
do_maze();
|
||||
no_food++;
|
||||
put_things(ltype); /* Place objects (if any) */
|
||||
}
|
||||
else if (ltype == OUTSIDE) {
|
||||
/* Move the cursor back onto the hero */
|
||||
wmove(cw, hero.y, hero.x);
|
||||
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, 5) == 5) {
|
||||
cnt = 0;
|
||||
do {
|
||||
rm = rnd_room();
|
||||
rnd_pos(&rooms[rm], &stairs);
|
||||
} until (mvinch(stairs.y, stairs.x) == FLOOR || cnt++ > 2500);
|
||||
addch(STAIRS);
|
||||
}
|
||||
/*
|
||||
* maybe add a trading post
|
||||
*/
|
||||
if (level > 5 && rnd(10) == 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++ > 2500);
|
||||
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++ > 2500 || 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 = 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(tlist, item);
|
||||
turn_off(*tp,ISELSEWHERE);
|
||||
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 = 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)+2;
|
||||
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++ > 2500);
|
||||
|
||||
traps[i].tr_flags = 0;
|
||||
|
||||
/* If we are at the bottom, we can't set a trap door */
|
||||
if (level >= nfloors) ch = (unsigned char) rnd(8) + 1;
|
||||
else ch = (unsigned char) rnd(9);
|
||||
|
||||
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;
|
||||
when 8: ch = WORMHOLE;
|
||||
}
|
||||
addch(ch);
|
||||
traps[i].tr_type = ch;
|
||||
traps[i].tr_show = FLOOR;
|
||||
traps[i].tr_pos = stairs;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fresh) { /* A whole new picture */
|
||||
/*
|
||||
* try to find a room for the hero. The objective here is to:
|
||||
* --> don't put him in a treasure room
|
||||
* --> don't put him on an object
|
||||
* --> try not to put him next to the stairs
|
||||
*/
|
||||
cnt = 2500;
|
||||
do {
|
||||
if (ltype != OUTSIDE) rm = rnd_room();
|
||||
else continue;
|
||||
|
||||
if (rooms[rm].r_flags & ISTREAS)
|
||||
continue;
|
||||
|
||||
rnd_pos(&rooms[rm], &hero);
|
||||
} until( cnt-- == 0 ||
|
||||
(winat(hero.y, hero.x) == FLOOR &&
|
||||
DISTANCE(hero.y, hero.x, stairs.y, stairs.x) > cnt/10));
|
||||
}
|
||||
else { /* We're extending into an adjacent outside plane */
|
||||
rm = 0;
|
||||
if (vert) {
|
||||
if (hero.y == 1) hero.y = lines - 3 - TERRASAVE; /* Top to bottom */
|
||||
else hero.y = TERRASAVE + 1; /* Bottom to top */
|
||||
}
|
||||
else {
|
||||
if (hero.x == 0) hero.x = cols - 1 - TERRASAVE; /* Right to left */
|
||||
else hero.x = TERRASAVE; /* Left to right */
|
||||
}
|
||||
}
|
||||
oldrp = &rooms[rm]; /* Set the current room */
|
||||
player.t_oldpos = player.t_pos; /* Set the current position */
|
||||
|
||||
if (ISWEARING(R_AGGR) ||
|
||||
(cur_misc[WEAR_JEWEL] != NULL &&
|
||||
cur_misc[WEAR_JEWEL]->o_which == MM_JEWEL))
|
||||
aggravate(TRUE, TRUE); /* affect all charactors */
|
||||
|
||||
/*
|
||||
* If player is moving up or above his deepest point, wake up any
|
||||
* non-uniques
|
||||
*/
|
||||
else if (level < cur_max) {
|
||||
aggravate(FALSE, FALSE);
|
||||
}
|
||||
|
||||
light(&hero);
|
||||
wmove(cw, hero.y, hero.x);
|
||||
waddch(cw, PLAYER);
|
||||
|
||||
if (level > cur_max)
|
||||
cur_max = level;
|
||||
|
||||
draw(cw);
|
||||
|
||||
status(TRUE);
|
||||
|
||||
/* Do we sense any food on this level? */
|
||||
if (cur_relic[SURTUR_RING])
|
||||
quaff(P_FFIND, NULL, NULL, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pick a room that is really there
|
||||
*/
|
||||
|
||||
rnd_room()
|
||||
{
|
||||
register int rm;
|
||||
|
||||
if (levtype != NORMLEV)
|
||||
rm = 0;
|
||||
else do
|
||||
{
|
||||
rm = rnd(MAXROOMS);
|
||||
} while (rooms[rm].r_flags & ISGONE);
|
||||
return rm;
|
||||
}
|
||||
|
||||
/*
|
||||
* put_things:
|
||||
* put potions and scrolls on this level
|
||||
*/
|
||||
|
||||
put_things(ltype)
|
||||
LEVTYPE ltype; /* designates type of level to create */
|
||||
{
|
||||
register int i, rm, cnt;
|
||||
register struct object *cur;
|
||||
register struct linked_list *item, *nextitem, *exitptr;
|
||||
int length, width;
|
||||
int ITEMS = 0; /* number of items to place */
|
||||
coord tp, *exit;
|
||||
|
||||
/*
|
||||
* The only way to get new stuff is to go down into the dungeon.
|
||||
*/
|
||||
if (level < cur_max) {
|
||||
if (ltype == NORMLEV)
|
||||
return;
|
||||
}
|
||||
|
||||
if (ltype == OUTSIDE) goto jmp_here; /* a jump for outside */
|
||||
|
||||
/*
|
||||
* There is a chance that there is a Treasure Room on this level
|
||||
*/
|
||||
if (ltype == NORMLEV && rnd(150) < level) {
|
||||
register int j;
|
||||
register struct room *rp;
|
||||
|
||||
/* Count the number of free spaces */
|
||||
i = 0; /* 0 tries */
|
||||
do {
|
||||
rp = &rooms[rnd_room()];
|
||||
width = rp->r_max.y - 2;
|
||||
length = rp->r_max.x - 2;
|
||||
} until ((width*length >= MAXTREAS) || (i++ > MAXROOMS*4));
|
||||
|
||||
/* Mark the room as a treasure room */
|
||||
rp->r_flags |= ISTREAS;
|
||||
|
||||
/* Make all the doors secret doors */
|
||||
for (exitptr = rp->r_exit; exitptr; exitptr = next(exitptr)) {
|
||||
exit = DOORPTR(exitptr);
|
||||
move(exit->y, exit->x);
|
||||
addch(SECRETDOOR);
|
||||
}
|
||||
|
||||
/*
|
||||
* check to see if there are any monsters in room already
|
||||
*/
|
||||
for (item = mlist; item != NULL; item = nextitem) {
|
||||
register struct thing *tp;
|
||||
|
||||
tp = THINGPTR(item);
|
||||
nextitem = next(item);
|
||||
if (rp == roomin(&tp->t_pos)) {
|
||||
/*
|
||||
* Don't let nice creatures be generated in a treasure
|
||||
* room.
|
||||
*/
|
||||
if ((player.t_ctype==C_PALADIN || player.t_ctype==C_RANGER ||
|
||||
player.t_ctype==C_MONK) && off(*tp, ISMEAN)) {
|
||||
int index;
|
||||
|
||||
if (on(*tp, ISUNIQUE)) index = tp->t_index;
|
||||
else index = -1;
|
||||
|
||||
/* Get rid of the monster */
|
||||
killed(item, FALSE, FALSE, FALSE);
|
||||
|
||||
/* Restore uniques back in the table */
|
||||
if (index != -1) monsters[index].m_normal = TRUE;
|
||||
|
||||
continue;
|
||||
}
|
||||
turn_on(*tp, ISMEAN);
|
||||
turn_on(*tp, ISGUARDIAN);
|
||||
}
|
||||
}
|
||||
|
||||
/* Put in the monsters and treasures */
|
||||
for (j=1; j<rp->r_max.y-1; j++)
|
||||
for (i=1; i<rp->r_max.x-1; i++) {
|
||||
coord trp;
|
||||
|
||||
trp.y = rp->r_pos.y+j;
|
||||
trp.x = rp->r_pos.x+i;
|
||||
|
||||
/* Monsters */
|
||||
if ((rnd(100) < (MAXTREAS*100)/(width*length)) &&
|
||||
(mvwinch(mw, rp->r_pos.y+j, rp->r_pos.x+i) == ' ')) {
|
||||
register struct thing *tp;
|
||||
|
||||
/*
|
||||
* Put it there and leave it asleep. Wake the monsters
|
||||
* when the player enters the room. Hopefully, all bases
|
||||
* are covered as far as the ways to get in. This way
|
||||
* cpu time is not wasted on the awake monsters that
|
||||
* can't get to the player anyway.
|
||||
* try not to put any UNIQUEs in a treasure room.
|
||||
* note that they may have put put in already by the
|
||||
* non-treasure room code.
|
||||
* also, try not to put ISMEAN monsters in a treasure
|
||||
* room as these are supposed to be non-hostile until
|
||||
* attacked. It also makes life simpler for the ranger,
|
||||
* paladin, and monk.
|
||||
*/
|
||||
for(;;) {
|
||||
item = new_item(sizeof *tp); /* Make a monster */
|
||||
tp = THINGPTR(item);
|
||||
new_monster(item,randmonster(FALSE, TRUE),&trp,TRUE);
|
||||
if (on(*tp, HASFIRE)) {
|
||||
register struct linked_list *fire_item;
|
||||
|
||||
fire_item = creat_item();
|
||||
ldata(fire_item) = (char *) tp;
|
||||
attach(rp->r_fires, fire_item);
|
||||
rp->r_flags |= HASFIRE;
|
||||
}
|
||||
/*
|
||||
* only picky for these classes
|
||||
*/
|
||||
if (player.t_ctype != C_RANGER &&
|
||||
player.t_ctype != C_PALADIN &&
|
||||
player.t_ctype != C_MONK)
|
||||
break;
|
||||
if (on(*tp, ISMEAN))
|
||||
break;
|
||||
killed (item, FALSE, FALSE, FALSE);
|
||||
}
|
||||
if (on(*tp, ISUNIQUE)) { /* just in case */
|
||||
carry_obj(tp, monsters[tp->t_index].m_carry);
|
||||
tp->t_no_move = movement(tp);
|
||||
}
|
||||
turn_on(*tp, ISGUARDIAN);
|
||||
|
||||
}
|
||||
|
||||
/* Treasures */
|
||||
if ((rnd(100) < (MAXTREAS*100)/(width*length)) &&
|
||||
(mvinch(rp->r_pos.y+j, rp->r_pos.x+i) == FLOOR)) {
|
||||
item = new_thing(ALL, TRUE);
|
||||
attach(lvl_obj, item);
|
||||
cur = OBJPTR(item);
|
||||
|
||||
mvaddch(trp.y, trp.x, cur->o_type);
|
||||
cur->o_pos = trp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jmp_here: /* outside jumper for equippage */
|
||||
|
||||
/*
|
||||
* Do ITEMS attempts to put things in dungeon, maze, or outside
|
||||
*/
|
||||
|
||||
if (ltype == OUTSIDE) ITEMS = rnd(15)+1;
|
||||
else if (ltype == MAZELEV) ITEMS = rnd(20)+1;
|
||||
else ITEMS = MAXOBJ + rnd(4);
|
||||
|
||||
for (i = 0; i < ITEMS; i++)
|
||||
if (rnd(100) < 65) {
|
||||
/*
|
||||
* Pick a new object and link it in the list
|
||||
*/
|
||||
item = new_thing(ALL, TRUE);
|
||||
attach(lvl_obj, item);
|
||||
cur = OBJPTR(item);
|
||||
/*
|
||||
* Put it somewhere
|
||||
*/
|
||||
cnt = 0;
|
||||
do {
|
||||
if (ltype == OUTSIDE) rm = 0;
|
||||
else rm = rnd_room();
|
||||
rnd_pos(&rooms[rm], &tp);
|
||||
} until (winat(tp.y, tp.x) == FLOOR || cnt++ > 2500);
|
||||
mvaddch(tp.y, tp.x, cur->o_type);
|
||||
cur->o_pos = tp;
|
||||
}
|
||||
}
|
||||
|
||||
35
xrogue/network.h
Normal file
35
xrogue/network.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
network.h - networking setup
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Note that networking is set up for machines that can communicate
|
||||
* via some system such as uucp. The mechanism listed here uses uux
|
||||
* and assumes that the target machine allows access to the game via
|
||||
* the uux command. NETCOMMAND must be defined if networking is desired.
|
||||
*/
|
||||
|
||||
/* #undef NETCOMMAND "uux - -n '%s!%s -u' >/dev/null 2>&1" */
|
||||
/* #define NETCOMMAND "usend -s -d%s -uNoLogin -!'%s -u' - 2>/dev/null" */
|
||||
#define NETCOMMAND ""
|
||||
|
||||
/* Networking information -- should not vary among networking machines */
|
||||
|
||||
struct network {
|
||||
char *system;
|
||||
char *rogue;
|
||||
};
|
||||
extern struct network Network[];
|
||||
extern unsigned long netread();
|
||||
extern unsigned long netwrite();
|
||||
|
||||
501
xrogue/options.c
Normal file
501
xrogue/options.c
Normal file
|
|
@ -0,0 +1,501 @@
|
|||
/*
|
||||
options.c - This file has all the code for the option command
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* I would rather this command were not necessary, but
|
||||
* it is the only way to keep the wolves off of my back.
|
||||
*/
|
||||
|
||||
#include <curses.h>
|
||||
#include <ctype.h>
|
||||
#include "rogue.h"
|
||||
|
||||
#define NUM_OPTS (sizeof optlist / sizeof (OPTION))
|
||||
|
||||
/*
|
||||
* description of an option and what to do with it
|
||||
*/
|
||||
struct optstruct {
|
||||
char *o_name; /* option name */
|
||||
char *o_prompt; /* prompt for interactive entry */
|
||||
int *o_opt; /* pointer to thing to set */
|
||||
int (*o_putfunc)(); /* function to print value */
|
||||
int (*o_getfunc)(); /* function to get value interactively */
|
||||
};
|
||||
|
||||
typedef struct optstruct OPTION;
|
||||
|
||||
int put_bool(),
|
||||
get_bool(),
|
||||
put_str(),
|
||||
get_str(),
|
||||
put_abil(),
|
||||
get_abil(),
|
||||
get_quest(),
|
||||
put_quest(),
|
||||
get_default();
|
||||
|
||||
OPTION optlist[] = {
|
||||
{"terse", "Terse output: ",
|
||||
(int *) &terse, put_bool, get_bool },
|
||||
{"flush", "Flush typeahead during battle: ",
|
||||
(int *) &fight_flush, put_bool, get_bool },
|
||||
{"jump", "Show position only at end of run: ",
|
||||
(int *) &jump, put_bool, get_bool },
|
||||
{"step", "Do inventories one line at a time: ",
|
||||
(int *) &slow_invent, put_bool, get_bool },
|
||||
{"askme", "Ask me about unidentified things: ",
|
||||
(int *) &askme, put_bool, get_bool },
|
||||
{"pickup", "Pick things up automatically: ",
|
||||
(int *) &auto_pickup, put_bool, get_bool },
|
||||
{"overlay", "Overlay menu: ",
|
||||
(int *) &menu_overlay, put_bool, get_bool },
|
||||
{"name", "Name: ",
|
||||
(int *) whoami, put_str, get_str },
|
||||
{"file", "Save file: ",
|
||||
(int *) file_name, put_str, get_str },
|
||||
{"score", "Score file: ",
|
||||
(int *) score_file, put_str, get_str },
|
||||
{"class", "Character type: ",
|
||||
(int *) &char_type, put_abil, get_abil },
|
||||
{"quest", "Quest item: ",
|
||||
(int *) &quest_item, put_quest, get_quest },
|
||||
{"default", "Default Attributes: ",
|
||||
(int *) &def_attr, put_bool, get_default }
|
||||
};
|
||||
|
||||
/*
|
||||
* The default attribute field is read-only
|
||||
*/
|
||||
|
||||
get_default(bp, win)
|
||||
bool *bp;
|
||||
WINDOW *win;
|
||||
{
|
||||
register int oy, ox;
|
||||
|
||||
getyx(win, oy, ox);
|
||||
put_bool(bp, win);
|
||||
get_ro(win, oy, ox);
|
||||
}
|
||||
|
||||
/*
|
||||
* The ability (class) 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 == 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 == killchar()) /* process kill character */
|
||||
{
|
||||
sp = buf;
|
||||
wmove(win, oy, ox);
|
||||
continue;
|
||||
}
|
||||
else if (sp == buf)
|
||||
if (c == '-' && win == hw) /* To move back a line in hw */
|
||||
break;
|
||||
else if (c == '~')
|
||||
{
|
||||
strcpy(buf, home);
|
||||
waddstr(win, home);
|
||||
sp += strlen(home);
|
||||
continue;
|
||||
}
|
||||
*sp++ = c;
|
||||
waddstr(win, unctrl(c));
|
||||
}
|
||||
*sp = '\0';
|
||||
if (sp > buf) /* only change option if something has been typed */
|
||||
strucpy(opt, buf, strlen(buf));
|
||||
wmove(win, oy, ox);
|
||||
waddstr(win, opt);
|
||||
waddch(win, '\n');
|
||||
draw(win);
|
||||
if (win == msgw)
|
||||
mpos += 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]; op++)
|
||||
{
|
||||
waddstr(hw, op->o_prompt);
|
||||
(*op->o_putfunc)(op->o_opt, hw);
|
||||
waddch(hw, '\n');
|
||||
}
|
||||
/*
|
||||
* Set values
|
||||
*/
|
||||
wmove(hw, 0, 0);
|
||||
for (op = optlist; op < &optlist[NUM_OPTS]; op++)
|
||||
{
|
||||
waddstr(hw, op->o_prompt);
|
||||
|
||||
retval = (*op->o_getfunc)(op->o_opt, hw);
|
||||
|
||||
if (retval)
|
||||
if (retval == QUIT)
|
||||
break;
|
||||
else if (op > optlist) { /* MINUS */
|
||||
wmove(hw, (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(' ');
|
||||
restscr(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;
|
||||
|
||||
if (*str == '\"')
|
||||
str++;
|
||||
|
||||
while (*str)
|
||||
{
|
||||
/*
|
||||
* Get option name
|
||||
*/
|
||||
|
||||
for (sp = str; isalpha(*sp); sp++)
|
||||
continue;
|
||||
len = (char *)sp - str;
|
||||
/*
|
||||
* Look it up and deal with it
|
||||
*/
|
||||
for (op = optlist; op < &optlist[NUM_OPTS]; op++)
|
||||
if (EQSTR(str, op->o_name, len))
|
||||
{
|
||||
if (op->o_putfunc == put_bool) /* if option is a boolean */
|
||||
*(bool *)op->o_opt = TRUE;
|
||||
else /* string option */
|
||||
{
|
||||
register char *start;
|
||||
char value[LINELEN];
|
||||
|
||||
/*
|
||||
* Skip to start of string value
|
||||
*/
|
||||
for (str = sp + 1; *str == '=' || *str == ':'; 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 != '\"'; sp++)
|
||||
continue;
|
||||
strucpy(start, str, (char *) 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);
|
||||
register int i;
|
||||
|
||||
for (i=0; i<NUM_CHARTYPES-1; i++) {
|
||||
if (EQSTR(value, char_class[i].name, len)) {
|
||||
*op->o_opt = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* check for "noname" for booleans
|
||||
*/
|
||||
else if (op->o_putfunc == put_bool
|
||||
&& EQSTR(str, "no", 2) && EQSTR(str + 2, op->o_name, len - 2))
|
||||
{
|
||||
*(bool *)op->o_opt = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* skip to start of next option name
|
||||
*/
|
||||
while (*sp && !isalpha(*sp))
|
||||
sp++;
|
||||
str = sp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* print the default attributes
|
||||
*/
|
||||
|
||||
/* put_default(b, win)
|
||||
* bool *b;
|
||||
* WINDOW *win;
|
||||
* {
|
||||
* waddstr(win, *b ? "True" : "False");
|
||||
* }
|
||||
*/
|
||||
|
||||
/*
|
||||
* print the character type
|
||||
*/
|
||||
|
||||
put_abil(ability, win)
|
||||
int *ability;
|
||||
WINDOW *win;
|
||||
{
|
||||
waddstr(win, char_class[*ability].name);
|
||||
}
|
||||
|
||||
/*
|
||||
* print out the quest
|
||||
*/
|
||||
|
||||
put_quest(quest, win)
|
||||
int *quest;
|
||||
WINDOW *win;
|
||||
{
|
||||
waddstr(win, rel_magic[*quest].mi_name);
|
||||
}
|
||||
|
||||
/*
|
||||
* put out a boolean
|
||||
*/
|
||||
|
||||
put_bool(b, win)
|
||||
bool *b;
|
||||
WINDOW *win;
|
||||
{
|
||||
waddstr(win, *b ? "True" : "False");
|
||||
}
|
||||
|
||||
/*
|
||||
* put out a string
|
||||
*/
|
||||
|
||||
put_str(str, win)
|
||||
char *str;
|
||||
WINDOW *win;
|
||||
{
|
||||
waddstr(win, str);
|
||||
}
|
||||
|
||||
226
xrogue/outside.c
Normal file
226
xrogue/outside.c
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
outside.c - functions for dealing with the "outside" level
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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 int cury, curx; /* Current y and x positions */
|
||||
|
||||
/* Lay out the boundary */
|
||||
for (cury=1; cury<lines-2; cury++) { /* Vertical "walls" */
|
||||
mvaddch(cury, 0, VERTWALL);
|
||||
mvaddch(cury, cols-1, VERTWALL);
|
||||
}
|
||||
for (curx=0; curx<cols; curx++) { /* Horizontal "walls" */
|
||||
mvaddch(1, curx, HORZWALL);
|
||||
mvaddch(lines-3, curx, HORZWALL);
|
||||
}
|
||||
|
||||
/* 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 = 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 = mvinch(cury, left_pos);
|
||||
top_left = mvinch(top_pos, left_pos);
|
||||
top = mvinch(top_pos, curx);
|
||||
top_right = 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;
|
||||
}
|
||||
/* The deeper we go.. */
|
||||
if (level > 40) genmonsters(20, (bool) 0);
|
||||
else if (level > 10) genmonsters(15, (bool) 0);
|
||||
else genmonsters(10, (bool) 0);
|
||||
|
||||
/* sometimes they're real angry */
|
||||
if (rnd(100) < 65) {
|
||||
/* protect good guys */
|
||||
if (player.t_ctype == C_PALADIN ||
|
||||
player.t_ctype == C_RANGER || player.t_ctype == C_MONK) {
|
||||
aggravate(TRUE, FALSE);
|
||||
}
|
||||
else {
|
||||
aggravate(TRUE, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
/* Meadow is most likely */
|
||||
if (chance < 40) return(FLOOR);
|
||||
|
||||
/* Next comes forest */
|
||||
if (chance < 65) return(FOREST);
|
||||
|
||||
/* Then comes lakes */
|
||||
if (chance < 85) 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
|
||||
*/
|
||||
|
||||
/*UNUSED*/
|
||||
/* void
|
||||
* lake_check(place)
|
||||
* register coord *place;
|
||||
* {
|
||||
* }
|
||||
*/
|
||||
|
||||
1582
xrogue/pack.c
Normal file
1582
xrogue/pack.c
Normal file
File diff suppressed because it is too large
Load diff
370
xrogue/passages.c
Normal file
370
xrogue/passages.c
Normal file
|
|
@ -0,0 +1,370 @@
|
|||
/*
|
||||
passages.c - Draw the connecting passages
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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 (i = 0; i < MAXROOMS; i++)
|
||||
{
|
||||
r1 = &rdes[i];
|
||||
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 = r1 - rdes;
|
||||
j = 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 = r1 - rdes;
|
||||
j = 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, max_diag, offset = 0, i;
|
||||
register int rm;
|
||||
int turns[3], turn_dist[3];
|
||||
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);
|
||||
offset = abs(spos.x - epos.x); /* how far to turn */
|
||||
}
|
||||
else if (direc == 'r') /* setup for moving right */
|
||||
{
|
||||
rmt = rm + 1;
|
||||
rpt = &rooms[rmt];
|
||||
delta.x = 1;
|
||||
delta.y = 0;
|
||||
spos.x = rpf->r_pos.x;
|
||||
spos.y = rpf->r_pos.y;
|
||||
epos.x = rpt->r_pos.x;
|
||||
epos.y = rpt->r_pos.y;
|
||||
if (!(rpf->r_flags & ISGONE))
|
||||
{
|
||||
spos.x += rpf->r_max.x-1;
|
||||
spos.y += rnd(rpf->r_max.y-2)+1;
|
||||
}
|
||||
if (!(rpt->r_flags & ISGONE))
|
||||
epos.y += rnd(rpt->r_max.y-2)+1;
|
||||
distance = abs(spos.x - epos.x) - 1;
|
||||
turn_delta.y = (spos.y < epos.y ? 1 : -1);
|
||||
turn_delta.x = 0;
|
||||
offset = abs(spos.y - epos.y);
|
||||
}
|
||||
else
|
||||
debug("error in connection tables");
|
||||
|
||||
/*
|
||||
* Draw in the doors on either side of the passage or just put #'s
|
||||
* if the rooms are gone.
|
||||
*/
|
||||
if (!(rpf->r_flags & ISGONE)) door(rpf, &spos);
|
||||
else
|
||||
{
|
||||
cmov(spos);
|
||||
addch('#');
|
||||
}
|
||||
if (!(rpt->r_flags & ISGONE)) door(rpt, &epos);
|
||||
else
|
||||
{
|
||||
cmov(epos);
|
||||
addch('#');
|
||||
}
|
||||
|
||||
/* How far can we move diagonally? */
|
||||
max_diag = min(distance, offset);
|
||||
|
||||
/*
|
||||
* Decide how many turns we will have.
|
||||
*/
|
||||
for (i=0; i<3; i++) turn_dist[i] = 0; /* Init distances */
|
||||
if (max_diag > 0) {
|
||||
int nturns;
|
||||
|
||||
for (i=0, nturns=0; i<3; i++) {
|
||||
if (rnd(3 - i + nturns) == 0) {
|
||||
nturns++;
|
||||
turns[i] = 0;
|
||||
}
|
||||
else turns[i] = -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Just use a straight line (middle turn) */
|
||||
turns[0] = turns[2] = -1;
|
||||
turns[1] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now decide how long each turn will be (for those selected above).
|
||||
*/
|
||||
while (max_diag > 0) {
|
||||
for (i=0; i<3; i++) {
|
||||
if (turns[i] >= 0 && max_diag > 0 && rnd(2) == 0) {
|
||||
turn_dist[i]++;
|
||||
max_diag--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have extra offset space, add it to the straight turn.
|
||||
*/
|
||||
if (offset > distance) turn_dist[1] += offset - distance;
|
||||
|
||||
/*
|
||||
* Decide where we want to make our turns.
|
||||
* First calculate the offsets, then use those offsets to calculate
|
||||
* the exact position relative to "distance."
|
||||
*/
|
||||
turns[0] = rnd(distance - turn_dist[0] - turn_dist[2]);
|
||||
turns[2] = rnd(distance - turn_dist[0] - turn_dist[2] - turns[0]);
|
||||
turns[1] = rnd(distance - turn_dist[0] - turn_dist[2] -
|
||||
turns[0] - turns[2]);
|
||||
|
||||
turns[0] = distance - turns[0];
|
||||
turns[1] = turns[0] - turn_dist[0] - turns[1];
|
||||
turns[2] = turns[1] - turns[2];
|
||||
|
||||
/*
|
||||
* Get ready to move...
|
||||
*/
|
||||
curr.x = spos.x;
|
||||
curr.y = spos.y;
|
||||
while (distance > 0) {
|
||||
/*
|
||||
* Move to next row/column
|
||||
*/
|
||||
curr.x += delta.x;
|
||||
curr.y += delta.y;
|
||||
|
||||
/*
|
||||
* Check if we are at a turn place; if so make a turn
|
||||
*/
|
||||
for (i=0; i<3; i++) {
|
||||
if (distance == turns[i] && turn_dist[i] > 0) {
|
||||
/*
|
||||
* If this is the start of a straight path,
|
||||
* we might put in a right-angle turn (33% chance).
|
||||
*/
|
||||
if (i == 1 && rnd(3) == 0) {
|
||||
cmov(curr);
|
||||
addch(PASSAGE);
|
||||
}
|
||||
|
||||
/* Now dig the turn */
|
||||
while (turn_dist[i]--) {
|
||||
curr.x += turn_delta.x;
|
||||
curr.y += turn_delta.y;
|
||||
cmov(curr);
|
||||
addch(PASSAGE);
|
||||
if (i != 1) { /* A diagonal */
|
||||
if (--distance > 0) {
|
||||
curr.x += delta.x;
|
||||
curr.y += delta.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (distance > 0) {
|
||||
/*
|
||||
* Dig the passage.
|
||||
*/
|
||||
cmov(curr);
|
||||
addch(PASSAGE);
|
||||
distance--;
|
||||
}
|
||||
}
|
||||
curr.x += delta.x;
|
||||
curr.y += delta.y;
|
||||
if (!ce(curr, epos))
|
||||
msg("Warning, connectivity problem (%d, %d) to (%d, %d).",
|
||||
curr.y, curr.x, epos.y, epos.x);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a door or possibly a secret door
|
||||
* also enters the door in the exits array of the room.
|
||||
*/
|
||||
|
||||
door(rm, cp)
|
||||
register struct room *rm;
|
||||
register coord *cp;
|
||||
{
|
||||
struct linked_list *newroom;
|
||||
coord *exit;
|
||||
|
||||
cmov(*cp);
|
||||
|
||||
if (rnd(10) < (level - 1) && rnd(100) < 20)
|
||||
addch(SECRETDOOR);
|
||||
else
|
||||
addch(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);
|
||||
}
|
||||
|
||||
1478
xrogue/player.c
Normal file
1478
xrogue/player.c
Normal file
File diff suppressed because it is too large
Load diff
1058
xrogue/potions.c
Normal file
1058
xrogue/potions.c
Normal file
File diff suppressed because it is too large
Load diff
173
xrogue/rings.c
Normal file
173
xrogue/rings.c
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
rings.c - Routines dealing specificaly with rings
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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"
|
||||
|
||||
/*
|
||||
* routines dealing specifically with rings
|
||||
*/
|
||||
|
||||
/*
|
||||
* how much food does this ring use up?
|
||||
*/
|
||||
|
||||
ring_eat(hand)
|
||||
register int hand;
|
||||
{
|
||||
if (cur_ring[hand] == NULL)
|
||||
return 0;
|
||||
switch (cur_ring[hand]->o_which) {
|
||||
case R_VAMPREGEN:
|
||||
return 3;
|
||||
case R_REGEN:
|
||||
case R_SUSABILITY:
|
||||
return 2;
|
||||
case R_HEALTH:
|
||||
return 1;
|
||||
case R_SEARCH:
|
||||
case R_SEEINVIS:
|
||||
return (rnd(100) < 50); /* 0 or 1 */
|
||||
case R_DIGEST:
|
||||
if (cur_ring[hand]->o_ac >= 0)
|
||||
return (-(cur_ring[hand]->o_ac)-1);
|
||||
else
|
||||
return (-(cur_ring[hand]->o_ac));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ring_on(item)
|
||||
register struct linked_list *item;
|
||||
{
|
||||
register struct object *obj;
|
||||
register int save_max;
|
||||
|
||||
obj = OBJPTR(item);
|
||||
|
||||
/*
|
||||
* Calculate the effect it has on the poor guy.
|
||||
*/
|
||||
switch (obj->o_which)
|
||||
{
|
||||
case R_ADDSTR:
|
||||
save_max = max_stats.s_str;
|
||||
chg_str(obj->o_ac);
|
||||
max_stats.s_str = save_max;
|
||||
when R_ADDHIT:
|
||||
pstats.s_dext += obj->o_ac;
|
||||
when R_ADDINTEL:
|
||||
pstats.s_intel += obj->o_ac;
|
||||
when R_ADDWISDOM:
|
||||
pstats.s_wisdom += obj->o_ac;
|
||||
when R_SEEINVIS:
|
||||
if (on(player, CANSEE)) msg("Your eyes sparkle.");
|
||||
else msg("Your eyes begin to tingle.");
|
||||
turn_on(player, CANSEE);
|
||||
light(&hero);
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
when R_AGGR:
|
||||
aggravate(TRUE, TRUE); /* all charactors are affected*/
|
||||
when R_WARMTH:
|
||||
if (on(player, NOCOLD)) msg("You feel warm all over.");
|
||||
else msg("You begin to feel warm.");
|
||||
turn_on(player, NOCOLD);
|
||||
when R_FIRE:
|
||||
if (on(player, NOFIRE)) msg("You feel quite fire proof now.");
|
||||
else msg("You begin to feel fire proof.");
|
||||
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, (VOID *)NULL, AFTER);
|
||||
when R_TELEPORT:
|
||||
daemon(ring_teleport, (VOID *)NULL, AFTER);
|
||||
}
|
||||
status(FALSE);
|
||||
if (r_know[obj->o_which] && r_guess[obj->o_which]) {
|
||||
free(r_guess[obj->o_which]);
|
||||
r_guess[obj->o_which] = NULL;
|
||||
}
|
||||
else if (!r_know[obj->o_which] &&
|
||||
askme &&
|
||||
(obj->o_flags & ISKNOW) == 0 &&
|
||||
r_guess[obj->o_which] == NULL) {
|
||||
nameitem(item, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* print ring bonuses
|
||||
*/
|
||||
|
||||
char *
|
||||
ring_num(obj)
|
||||
register struct object *obj;
|
||||
{
|
||||
static char buf[5];
|
||||
|
||||
if (!(obj->o_flags & ISKNOW))
|
||||
return "";
|
||||
switch (obj->o_which)
|
||||
{
|
||||
case R_PROTECT:
|
||||
case R_ADDSTR:
|
||||
case R_ADDDAM:
|
||||
case R_ADDHIT:
|
||||
case R_ADDINTEL:
|
||||
case R_ADDWISDOM:
|
||||
case R_DIGEST:
|
||||
buf[0] = ' ';
|
||||
strcpy(&buf[1], num(obj->o_ac, 0));
|
||||
when R_AGGR:
|
||||
case R_LIGHT:
|
||||
case R_CARRY:
|
||||
case R_TELEPORT:
|
||||
if (obj->o_flags & ISCURSED)
|
||||
return " cursed";
|
||||
else
|
||||
return "";
|
||||
otherwise:
|
||||
return "";
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the effect of the specified ring
|
||||
*/
|
||||
|
||||
ring_value(type)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (ISRING(LEFT_1, type)) result += cur_ring[LEFT_1]->o_ac;
|
||||
if (ISRING(LEFT_2, type)) result += cur_ring[LEFT_2]->o_ac;
|
||||
if (ISRING(LEFT_3, type)) result += cur_ring[LEFT_3]->o_ac;
|
||||
if (ISRING(LEFT_4, type)) result += cur_ring[LEFT_4]->o_ac;
|
||||
if (ISRING(RIGHT_1, type)) result += cur_ring[RIGHT_1]->o_ac;
|
||||
if (ISRING(RIGHT_2, type)) result += cur_ring[RIGHT_2]->o_ac;
|
||||
if (ISRING(RIGHT_3, type)) result += cur_ring[RIGHT_3]->o_ac;
|
||||
if (ISRING(RIGHT_4, type)) result += cur_ring[RIGHT_4]->o_ac;
|
||||
return(result);
|
||||
}
|
||||
|
||||
763
xrogue/rip.c
Normal file
763
xrogue/rip.c
Normal file
|
|
@ -0,0 +1,763 @@
|
|||
/*
|
||||
rip.c - File for the fun ends Death or a total win
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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 REALLIFE 1 /* Print out machine and logname */
|
||||
#define EDITSCORE 2 /* Edit the current score file */
|
||||
#define ADDSCORE 3 /* Add a new score */
|
||||
|
||||
#include <curses.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include "mach_dep.h"
|
||||
#include "network.h"
|
||||
#include "rogue.h"
|
||||
|
||||
/* Network machines (for mutual score keeping) */
|
||||
struct network Network[] = {
|
||||
{ "", "" },
|
||||
};
|
||||
|
||||
static char *rip[] = {
|
||||
" ___________",
|
||||
" / \\",
|
||||
" / \\",
|
||||
" / R. I. P. \\",
|
||||
" / \\",
|
||||
" / \\",
|
||||
" | |",
|
||||
" | |",
|
||||
" | killed by |",
|
||||
" | |",
|
||||
" | |",
|
||||
" | |",
|
||||
" *| * * * |*",
|
||||
" _________)|//\\\\///\\///\\//\\//\\/|(_________",
|
||||
NULL
|
||||
};
|
||||
|
||||
char *killname();
|
||||
|
||||
/*UNUSED*/
|
||||
void
|
||||
byebye(sig)
|
||||
int sig;
|
||||
{
|
||||
NOOP(sig);
|
||||
exit_game(EXIT_ENDWIN);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* death:
|
||||
* Do something really fun when he dies
|
||||
*/
|
||||
|
||||
death(monst)
|
||||
register short monst;
|
||||
{
|
||||
register char **dp = rip, *killer;
|
||||
register struct tm *lt;
|
||||
time_t date;
|
||||
char buf[LINELEN];
|
||||
struct tm *localtime();
|
||||
|
||||
time(&date);
|
||||
lt = localtime(&date);
|
||||
clear();
|
||||
move(8, 0);
|
||||
while (*dp)
|
||||
printw("%s\n", *dp++);
|
||||
mvaddstr(14, 28-((strlen(whoami)+1)/2), whoami);
|
||||
sprintf(buf, "%lu Points", pstats.s_exp );
|
||||
mvaddstr(15, 28-((strlen(buf)+1)/2), buf);
|
||||
killer = killname(monst);
|
||||
mvaddstr(17, 28-((strlen(killer)+1)/2), killer);
|
||||
mvaddstr(18, 25, (sprintf(prbuf, "%4d", 1900+lt->tm_year), prbuf));
|
||||
move(lines-1, 0);
|
||||
refresh();
|
||||
score(pstats.s_exp, KILLED, monst);
|
||||
exit_game(EXIT_ENDWIN);
|
||||
}
|
||||
|
||||
char *
|
||||
killname(monst)
|
||||
register short monst;
|
||||
{
|
||||
static char mons_name[LINELEN/2];
|
||||
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;
|
||||
int flags;
|
||||
short monst;
|
||||
{
|
||||
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;
|
||||
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 */
|
||||
|
||||
#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 (level == 0 && max_level == 0)
|
||||
amount = 0; /*don't count if quit early */
|
||||
if (flags != WINNER && flags != SCOREIT && flags != UPDATE) {
|
||||
if (flags == CHICKEN) {
|
||||
packend = "when you quit";
|
||||
amount = amount / 100;
|
||||
}
|
||||
else
|
||||
packend = "at your untimely demise";
|
||||
mvaddstr(lines - 1, 0, retstr);
|
||||
refresh();
|
||||
getstr(prbuf);
|
||||
showpack(packend);
|
||||
}
|
||||
purse = 0; /* Steal all the gold */
|
||||
|
||||
/*
|
||||
* Open file and read list
|
||||
*/
|
||||
|
||||
if ((outf = fopen(score_file, "rb+")) == NULL)
|
||||
{
|
||||
if ((outf = fopen(score_file, "wb+")) == NULL)
|
||||
{
|
||||
mvprintw(lines - 1, 0, "Unable to open or create score file: %s",score_file);
|
||||
refresh();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
thissys = md_gethostname();
|
||||
|
||||
/*
|
||||
* If this is a SCOREIT optin (rogue -s), don't call byebye. The
|
||||
* endwin() calls in byebye() will and this results in a core dump.
|
||||
*/
|
||||
if (flags == SCOREIT) signal(SIGINT, SIG_DFL);
|
||||
else signal(SIGINT, byebye);
|
||||
|
||||
if (flags != SCOREIT && flags != UPDATE)
|
||||
{
|
||||
mvaddstr(lines - 1, 0, retstr);
|
||||
refresh();
|
||||
fflush(stdout);
|
||||
getstr(prbuf);
|
||||
}
|
||||
|
||||
/* Check for special options */
|
||||
if (strcmp(prbuf, "names") == 0)
|
||||
prflags = REALLIFE;
|
||||
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 */
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the score and convert it to a compatible format */
|
||||
|
||||
fseek(outf, 0, SEEK_SET);
|
||||
rs_read_scorefile(outf, top_ten, NUMSCORE);
|
||||
|
||||
/* 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, NAMELEN, stdin) != NAMELEN) errors++;
|
||||
|
||||
wintype = (short) netread(&errcheck, sizeof(short), stdin);
|
||||
if (errcheck) errors++;
|
||||
|
||||
uplevel = (short) netread(&errcheck, sizeof(short), stdin);
|
||||
if (errcheck) errors++;
|
||||
|
||||
uptype = (short) netread(&errcheck, sizeof(short), stdin);
|
||||
if (errcheck) errors++;
|
||||
|
||||
if (fread(upsystem, 1, SYSLEN, stdin) != SYSLEN)
|
||||
errors++;
|
||||
if (fread(uplogin, 1, LOGLEN, stdin) != LOGLEN)
|
||||
errors++;
|
||||
|
||||
if (errors) {
|
||||
fclose(outf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert player in list if need be
|
||||
*/
|
||||
if (!waswizard) {
|
||||
char *login= NULL;
|
||||
|
||||
if (flags != UPDATE) {
|
||||
login = md_getusername();
|
||||
|
||||
if ((login == NULL) || (*login == 0))
|
||||
login = "another rogue fiend";
|
||||
}
|
||||
|
||||
if (flags == UPDATE)
|
||||
(void) update(top_ten, amount, upquest, whoami, wintype,
|
||||
uplevel, monst, uptype, upsystem, uplogin);
|
||||
else {
|
||||
if (prflags == ADDSCORE) { /* Overlay characteristic by new ones */
|
||||
char buffer[LINELEN];
|
||||
|
||||
clear();
|
||||
mvaddstr(1, 0, "Score: ");
|
||||
mvaddstr(2, 0, "Quest (number): ");
|
||||
mvaddstr(3, 0, "Name: ");
|
||||
mvaddstr(4, 0, "System: ");
|
||||
mvaddstr(5, 0, "Login: ");
|
||||
mvaddstr(6, 0, "Level: ");
|
||||
mvaddstr(7, 0, "Char type: ");
|
||||
mvaddstr(8, 0, "Result: ");
|
||||
|
||||
/* Get the score */
|
||||
move(1, 7);
|
||||
get_str(buffer, stdscr);
|
||||
amount = atol(buffer);
|
||||
|
||||
/* Get the character's quest -- must be a number */
|
||||
move(2, 16);
|
||||
get_str(buffer, stdscr);
|
||||
quest_item = atoi(buffer);
|
||||
|
||||
/* Get the character's name */
|
||||
move(3, 6);
|
||||
get_str(buffer, stdscr);
|
||||
strncpy(whoami, buffer, NAMELEN);
|
||||
|
||||
/* Get the system */
|
||||
move(4, 8);
|
||||
get_str(buffer, stdscr);
|
||||
strncpy(thissys, buffer, SYSLEN);
|
||||
|
||||
/* Get the login */
|
||||
move(5, 7);
|
||||
get_str(buffer, stdscr);
|
||||
strncpy(login, buffer, LOGLEN);
|
||||
|
||||
/* Get the level */
|
||||
move(6, 7);
|
||||
get_str(buffer, stdscr);
|
||||
level = max_level = (short) atoi(buffer);
|
||||
|
||||
/* Get the character type */
|
||||
move(7, 11);
|
||||
get_str(buffer, stdscr);
|
||||
for (i=0; i<NUM_CHARTYPES; i++) {
|
||||
if (EQSTR(buffer, char_class[i].name, strlen(buffer)))
|
||||
break;
|
||||
}
|
||||
player.t_ctype = i;
|
||||
|
||||
/* Get the win type */
|
||||
move(8, 8);
|
||||
get_str(buffer, stdscr);
|
||||
switch (buffer[0]) {
|
||||
case 'W':
|
||||
case 'w':
|
||||
case 'T':
|
||||
case 't':
|
||||
flags = WINNER;
|
||||
break;
|
||||
|
||||
case 'Q':
|
||||
case 'q':
|
||||
flags = CHICKEN;
|
||||
break;
|
||||
|
||||
case 'k':
|
||||
case 'K':
|
||||
default:
|
||||
flags = KILLED;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get the monster if player was killed */
|
||||
if (flags == KILLED) {
|
||||
mvaddstr(9, 0, "Death type: ");
|
||||
get_str(buffer, stdscr);
|
||||
if (buffer[0] == 'M' || buffer[0] == 'm')
|
||||
do {
|
||||
monst = makemonster(TRUE, "choose");
|
||||
} while (monst < 0); /* Force a choice */
|
||||
else monst = getdeath();
|
||||
}
|
||||
}
|
||||
|
||||
if (update(top_ten, amount, (short) quest_item, whoami, flags,
|
||||
(flags == WINNER) ? (short) max_level : (short) level,
|
||||
monst, player.t_ctype, thissys, login)
|
||||
) {
|
||||
/* 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; Network[i].system[0] != 0; i++)
|
||||
if (Network[i].system[0] != '!' &&
|
||||
strcmp(Network[i].system, thissys)) {
|
||||
sprintf(cmd, NETCOMMAND,
|
||||
Network[i].system, Network[i].rogue);
|
||||
|
||||
/* Execute the command */
|
||||
if ((rmf=popen(cmd, "w")) != NULL) {
|
||||
unsigned long temp; /* Temporary value */
|
||||
|
||||
/* Write out the parameters */
|
||||
(void) netwrite((unsigned long) amount,
|
||||
sizeof(unsigned long), rmf);
|
||||
|
||||
(void) netwrite((unsigned long) monst,
|
||||
sizeof(short), rmf);
|
||||
|
||||
(void) netwrite((unsigned long) quest_item,
|
||||
sizeof(short), rmf);
|
||||
|
||||
(void) fwrite(whoami, 1, strlen(whoami), rmf);
|
||||
for (j=strlen(whoami); j<NAMELEN; j++)
|
||||
putc('\0', rmf);
|
||||
|
||||
(void) netwrite((unsigned long) flags,
|
||||
sizeof(short), rmf);
|
||||
|
||||
temp = (unsigned long)
|
||||
(flags==WINNER ? max_level : level);
|
||||
(void) netwrite(temp, sizeof(short), rmf);
|
||||
|
||||
(void) netwrite((unsigned long) player.t_ctype,
|
||||
sizeof(short), rmf);
|
||||
|
||||
(void) fwrite(thissys, 1,
|
||||
strlen(thissys), rmf);
|
||||
for (j=strlen(thissys); j<SYSLEN; j++)
|
||||
putc('\0', rmf);
|
||||
|
||||
(void) fwrite(login, 1, strlen(login), rmf);
|
||||
for (j=strlen(login); j<LOGLEN; j++)
|
||||
putc('\0', rmf);
|
||||
|
||||
/* Close off the command */
|
||||
(void) pclose(rmf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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]; scp++) {
|
||||
char *class;
|
||||
|
||||
if (scp->sc_score != 0) {
|
||||
class = char_class[scp->sc_ctype].name;
|
||||
|
||||
/* Make sure we have an in-bound reason */
|
||||
if (scp->sc_flags > REASONLEN) scp->sc_flags = REASONLEN;
|
||||
|
||||
printf("%3d %10lu\t%s (%s)", scp - top_ten + 1,
|
||||
scp->sc_score, scp->sc_name, class);
|
||||
|
||||
if (prflags == REALLIFE) printf(" [in real life %.*s!%.*s]",
|
||||
SYSLEN, scp->sc_system, LOGLEN, scp->sc_login);
|
||||
|
||||
printf(":\n\t\t%s on level %d", reason[scp->sc_flags],
|
||||
scp->sc_level);
|
||||
|
||||
switch (scp->sc_flags) {
|
||||
case KILLED:
|
||||
printf(" by");
|
||||
killer = killname(scp->sc_monster);
|
||||
printf(" %s", killer);
|
||||
break;
|
||||
|
||||
case WINNER:
|
||||
printf(" with the %s",
|
||||
rel_magic[scp->sc_quest].mi_name);
|
||||
break;
|
||||
}
|
||||
|
||||
if (prflags == EDITSCORE)
|
||||
{
|
||||
fflush(stdout);
|
||||
getstr(prbuf);
|
||||
printf("\n");
|
||||
if (prbuf[0] == 'd') {
|
||||
for (sc2 = scp; sc2 < &top_ten[NUMSCORE-1]; sc2++)
|
||||
*sc2 = *(sc2 + 1);
|
||||
top_ten[NUMSCORE-1].sc_score = 0;
|
||||
for (i = 0; i < NAMELEN; i++)
|
||||
top_ten[NUMSCORE-1].sc_name[i] = rnd(255);
|
||||
top_ten[NUMSCORE-1].sc_flags = RN;
|
||||
top_ten[NUMSCORE-1].sc_level = RN;
|
||||
top_ten[NUMSCORE-1].sc_monster = RN;
|
||||
scp--;
|
||||
}
|
||||
else if (prbuf[0] == 'e') {
|
||||
printf("Death type: ");
|
||||
getstr(prbuf);
|
||||
if (prbuf[0] == 'M' || prbuf[0] == 'm')
|
||||
do {
|
||||
scp->sc_monster =
|
||||
makemonster(TRUE, "choose");
|
||||
} while (scp->sc_monster < 0); /* Force a choice */
|
||||
else scp->sc_monster = getdeath();
|
||||
clear();
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
else printf("\n");
|
||||
}
|
||||
}
|
||||
/* if (prflags == EDITSCORE) endwin();*/ /* End editing windowing */
|
||||
}
|
||||
fseek(outf, 0L, SEEK_SET);
|
||||
|
||||
if (flags != SCOREIT)
|
||||
rs_write_scorefile(outf,top_ten,NUMSCORE);
|
||||
fclose(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(' ');
|
||||
clear();
|
||||
}
|
||||
}
|
||||
mvprintw(cnt + 1,0,"--- %ld Gold Pieces ---",purse);
|
||||
refresh();
|
||||
}
|
||||
|
||||
total_winner()
|
||||
{
|
||||
register struct linked_list *item;
|
||||
register struct object *obj;
|
||||
register long worth;
|
||||
register char c;
|
||||
register long 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 ");
|
||||
switch (player.t_ctype) {
|
||||
case C_FIGHTER: addstr("Leader of the Fighter's Guild.\n");
|
||||
when C_RANGER: addstr("King of the Northern Land.\n");
|
||||
when C_PALADIN: addstr("King of the Southern Land.\n");
|
||||
when C_MAGICIAN:addstr("High Wizard of the Sorcerer's Guild.\n");
|
||||
when C_CLERIC: addstr("Bishop of the Monastery.\n");
|
||||
when C_THIEF: addstr("Leader of the Thief's Guild.\n");
|
||||
when C_MONK: addstr("Master of the Temple.\n");
|
||||
when C_ASSASSIN: addstr("Leader of the Assassin's Guild.\n");
|
||||
when C_DRUID: addstr("High Priest of the Monastery.\n");
|
||||
otherwise: addstr("Town Drunk in the Tavern.\n");
|
||||
}
|
||||
mvaddstr(lines - 1, 0, spacemsg);
|
||||
refresh();
|
||||
wait_for(' ');
|
||||
clear();
|
||||
mvaddstr(0, 0, " Worth Item");
|
||||
oldpurse = purse;
|
||||
for (c = 'a', item = pack; item != NULL; c++, item = next(item))
|
||||
{
|
||||
obj = OBJPTR(item);
|
||||
worth = get_worth(obj);
|
||||
if (obj->o_group == 0)
|
||||
worth *= obj->o_count;
|
||||
whatis(item);
|
||||
mvprintw(c-'a'+1, 0, "%c) %6ld %s", c, worth, inv_name(obj, FALSE));
|
||||
purse += worth;
|
||||
}
|
||||
mvprintw(c - 'a' + 1, 0," %5ld Gold Pieces ", oldpurse);
|
||||
refresh();
|
||||
score(pstats.s_exp + (long) purse, WINNER, '\0');
|
||||
exit_game(EXIT_ENDWIN);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
delete_score(top_ten, idx)
|
||||
struct sc_ent top_ten[NUMSCORE];
|
||||
int idx;
|
||||
{
|
||||
for(;idx < NUMSCORE-1;idx++)
|
||||
top_ten[idx] = top_ten[idx+1];
|
||||
|
||||
top_ten[NUMSCORE-1].sc_score = 0L;
|
||||
}
|
||||
|
||||
int
|
||||
insert_score(top_ten, sc)
|
||||
struct sc_ent top_ten[NUMSCORE];
|
||||
struct sc_ent *sc;
|
||||
{
|
||||
int i,j;
|
||||
|
||||
if (top_ten[NUMSCORE-1].sc_score > 0)
|
||||
return(-1); /* no room */
|
||||
|
||||
for(i = 0; i < NUMSCORE; i++) {
|
||||
if (sc->sc_score > top_ten[i].sc_score) {
|
||||
for(j = NUMSCORE-1; j > i; j--)
|
||||
top_ten[j] = top_ten[j-1];
|
||||
top_ten[i] = *sc;
|
||||
return(i);
|
||||
}
|
||||
}
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* PCS = player-class-system (used to determines uniqueness of player) */
|
||||
|
||||
int
|
||||
is_pcs_match(sc1,sc2)
|
||||
struct sc_ent *sc1;
|
||||
struct sc_ent *sc2;
|
||||
{
|
||||
return( (strcmp(sc1->sc_name,sc2->sc_name) == 0) &&
|
||||
(sc1->sc_ctype == sc2->sc_ctype) &&
|
||||
(strcmp(sc1->sc_system, sc2->sc_system)==0) );
|
||||
}
|
||||
|
||||
int
|
||||
count_pcs_matches(top_ten,sc,lowest)
|
||||
struct sc_ent top_ten[NUMSCORE];
|
||||
struct sc_ent *sc;
|
||||
int *lowest;
|
||||
{
|
||||
int i, matches = 0;
|
||||
|
||||
*lowest = -1;
|
||||
|
||||
for(i = 0; i < NUMSCORE; i++) {
|
||||
if (is_pcs_match(sc,&top_ten[i])) {
|
||||
matches++;
|
||||
*lowest = i;
|
||||
}
|
||||
}
|
||||
return(matches);
|
||||
}
|
||||
|
||||
int
|
||||
find_most_pcs_matches(top_ten,sc,num,idx)
|
||||
struct sc_ent top_ten[NUMSCORE];
|
||||
struct sc_ent *sc;
|
||||
int *num, *idx;
|
||||
{
|
||||
int i, matches, max_match=0, max_match_idx=-1, lowest;
|
||||
|
||||
for(i = NUMSCORE-1; i > 0; i--) {
|
||||
matches = count_pcs_matches(top_ten,&top_ten[i],&lowest);
|
||||
|
||||
if (matches > max_match) {
|
||||
max_match = matches;
|
||||
max_match_idx = lowest;
|
||||
}
|
||||
}
|
||||
|
||||
matches = count_pcs_matches(top_ten,sc,&lowest) + 1;
|
||||
|
||||
if (matches > max_match) {
|
||||
*num = matches;
|
||||
*idx = lowest;
|
||||
}
|
||||
else {
|
||||
*num = max_match;
|
||||
*idx = max_match_idx;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
add_score(top_ten,sc)
|
||||
struct sc_ent top_ten[NUMSCORE];
|
||||
struct sc_ent *sc;
|
||||
{
|
||||
int idx, count;
|
||||
|
||||
if (insert_score(top_ten,sc) == -1) {
|
||||
/* Simple insert if space available in table */
|
||||
|
||||
find_most_pcs_matches(top_ten,sc,&count,&idx);
|
||||
|
||||
/* EVERY ENTRY UNIQUE, */
|
||||
/* INSERT IF SCORE > LOWEST MATCH SCORE */
|
||||
if (count == 1) {
|
||||
if (sc->sc_score > top_ten[idx].sc_score) {
|
||||
delete_score(top_ten,idx);
|
||||
insert_score(top_ten,sc);
|
||||
}
|
||||
}
|
||||
/* CURRENT PCS HAS HIGHEST DUPE COUNT */
|
||||
/* INSERT IF SCORE > LOWEST MATCH SCORE */
|
||||
else if (is_pcs_match(sc,&top_ten[idx])) {
|
||||
if (sc->sc_score > top_ten[idx].sc_score) {
|
||||
delete_score(top_ten,idx);
|
||||
insert_score(top_ten,sc);
|
||||
}
|
||||
}
|
||||
/* UNRELATED PCS HAS HIGHEST DUPE COUNT */
|
||||
/* DELETE LOWEST DUPE TO MAKE ROOM AND INSERT */
|
||||
else {
|
||||
delete_score(top_ten,idx);
|
||||
insert_score(top_ten,sc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
{
|
||||
struct sc_ent sc;
|
||||
|
||||
sc.sc_score = amount;
|
||||
sc.sc_quest = quest;
|
||||
strncpy(sc.sc_name, whoami, NAMELEN);
|
||||
sc.sc_name[NAMELEN-1] = 0;
|
||||
sc.sc_flags = flags;
|
||||
sc.sc_level = level;
|
||||
sc.sc_monster = monst;
|
||||
sc.sc_ctype = ctype;
|
||||
strncpy(sc.sc_system, system, SYSLEN);
|
||||
sc.sc_system[SYSLEN - 1] = 0;
|
||||
strncpy(sc.sc_login, login, LOGLEN);
|
||||
sc.sc_login[LOGLEN-1] = 0;
|
||||
|
||||
add_score(top_ten, &sc);
|
||||
return(1);
|
||||
}
|
||||
|
||||
658
xrogue/rogue.c
Normal file
658
xrogue/rogue.c
Normal file
|
|
@ -0,0 +1,658 @@
|
|||
/*
|
||||
rogue.c - Global game variables
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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 <ctype.h>
|
||||
#include <curses.h>
|
||||
#include "rogue.h"
|
||||
|
||||
/*
|
||||
* Now all the global variables
|
||||
*/
|
||||
|
||||
struct trap traps[MAXTRAPS];
|
||||
struct room rooms[MAXROOMS]; /* One for each room -- A level */
|
||||
struct room *oldrp; /* Roomin(&player.t_oldpos) */
|
||||
struct thing player; /* The rogue */
|
||||
struct object *cur_armor; /* What a well dresssed rogue wears */
|
||||
struct object *cur_ring[NUM_FINGERS]; /* Which rings are being worn */
|
||||
struct object *cur_misc[NUM_MM]; /* which MM's are in use */
|
||||
int cur_relic[MAXRELIC]; /* Currently used relics */
|
||||
struct linked_list *lvl_obj = NULL;
|
||||
struct linked_list *mlist = NULL;
|
||||
struct linked_list *rlist = NULL; /* list of dead monsters to be reaped */
|
||||
struct linked_list *tlist = NULL; /* list of monsters fallen down traps */
|
||||
struct linked_list *monst_dead = NULL; /* monster killed by monster */
|
||||
struct object *cur_weapon = NULL;
|
||||
int char_type = -1; /* what type of character is player */
|
||||
int foodlev = 1; /* how fast he eats food */
|
||||
int ntraps; /* Number of traps on this level */
|
||||
int trader = 0; /* no. of purchases */
|
||||
int curprice = -1; /* current price of item */
|
||||
int seed; /* Random number seed */
|
||||
int max_level; /* Deepest player has gone ever */
|
||||
int cur_max; /* Deepest player has gone currently */
|
||||
int prev_max; /* A flag indicating worm hole */
|
||||
int move_free = 0; /* Movement check (io.c & actions.c) */
|
||||
int mpos = 0;
|
||||
int level = 0;
|
||||
long purse = 0;
|
||||
int inpack = 0;
|
||||
int total = 0;
|
||||
int no_food = 0; /* how long has he gone with no food */
|
||||
int foods_this_level = 0; /* foods made per level */
|
||||
int count = 0;
|
||||
int food_left = STOMACHSIZE-MORETIME-1;
|
||||
int group = 1;
|
||||
int hungry_state = F_OKAY;
|
||||
int infest_dam=0;
|
||||
int lost_str=0;
|
||||
int lastscore = -1;
|
||||
int hold_count = 0;
|
||||
int trap_tries = 0;
|
||||
int chant_time = 0;
|
||||
int pray_time = 0;
|
||||
int spell_power = 0;
|
||||
long turns = 0; /* Number of turns player has taken */
|
||||
int quest_item = 0; /* Item player is looking for */
|
||||
int cols = 0; /* number of columns in terminal */
|
||||
int lines = 0; /* number of lines on the terminal */
|
||||
int nfloors = -1; /* Number of floors in this dungeon */
|
||||
char curpurch[LINELEN]; /* name of item ready to buy */
|
||||
char PLAYER = VPLAYER; /* what the player looks like */
|
||||
char take; /* Thing the rogue is taking */
|
||||
char prbuf[LINELEN*2]; /* Buffer for sprintfs */
|
||||
char runch; /* Direction player is running */
|
||||
char *s_names[MAXSCROLLS]; /* Names of the scrolls */
|
||||
char *p_colors[MAXPOTIONS]; /* Colors of the potions */
|
||||
char *r_stones[MAXRINGS]; /* Stone settings of the rings */
|
||||
char *ws_made[MAXSTICKS]; /* What sticks are made of */
|
||||
char whoami[LINELEN]; /* Name of player */
|
||||
char huh[LINELEN]; /* The last message printed */
|
||||
char *s_guess[MAXSCROLLS]; /* Players guess at what scroll is */
|
||||
char *p_guess[MAXPOTIONS]; /* Players guess at what potion is */
|
||||
char *r_guess[MAXRINGS]; /* Players guess at what ring is */
|
||||
char *ws_guess[MAXSTICKS]; /* Players guess at what wand is */
|
||||
char *m_guess[MAXMM]; /* Players guess at what MM is */
|
||||
char *ws_type[MAXSTICKS]; /* Is it a wand or a staff */
|
||||
char file_name[LINELEN]; /* Save file name */
|
||||
char score_file[LINELEN]; /* Score file name */
|
||||
char home[LINELEN]; /* User's home directory */
|
||||
WINDOW *cw; /* Window that the player sees */
|
||||
WINDOW *hw; /* Used for the help command */
|
||||
WINDOW *mw; /* Used to store monsters */
|
||||
WINDOW *msgw; /* Used to display messages */
|
||||
bool pool_teleport = FALSE; /* just teleported from a pool */
|
||||
bool inwhgt = FALSE; /* true if from wghtchk() */
|
||||
bool after; /* True if we want after daemons */
|
||||
bool waswizard; /* Was a wizard sometime */
|
||||
bool s_know[MAXSCROLLS]; /* Does he know what a scroll does */
|
||||
bool p_know[MAXPOTIONS]; /* Does he know what a potion does */
|
||||
bool r_know[MAXRINGS]; /* Does he know what a ring does */
|
||||
bool ws_know[MAXSTICKS]; /* Does he know what a stick does */
|
||||
bool m_know[MAXMM]; /* Does he know what a MM does */
|
||||
|
||||
/* options */
|
||||
bool playing = TRUE; /* Defaults */
|
||||
bool running = FALSE;
|
||||
bool wizard = FALSE;
|
||||
bool notify = TRUE;
|
||||
bool fight_flush = FALSE;
|
||||
bool terse = FALSE;
|
||||
bool auto_pickup = FALSE;
|
||||
bool def_attr = FALSE; /* default attributes */
|
||||
bool menu_overlay = TRUE;
|
||||
bool door_stop = TRUE;
|
||||
bool jump = TRUE;
|
||||
bool slow_invent = FALSE;
|
||||
bool firstmove = FALSE;
|
||||
bool askme = TRUE;
|
||||
bool in_shell = FALSE;
|
||||
bool daytime = TRUE;
|
||||
bool funfont = FALSE;
|
||||
|
||||
LEVTYPE levtype; /* what type of level am i'm on? */
|
||||
|
||||
char *nothing = "Nothing seems to happen. ";
|
||||
char *spacemsg = "--Press space to continue--";
|
||||
char *morestr = " --More--";
|
||||
char *retstr = "[Press return to continue]";
|
||||
|
||||
/*
|
||||
* This lays out all the class specific details
|
||||
*
|
||||
* Here are the beginning experience levels for all players.
|
||||
* All further experience levels are computed by muliplying by 2
|
||||
* up through MAXDOUBLE. Then exp pts are calculated by adding
|
||||
* in the cap figure. You must change MAXDOUBLE if you change the
|
||||
* cap figure.
|
||||
*/
|
||||
|
||||
struct character_types char_class[NUM_CHARTYPES] = {
|
||||
/* name exppts cap hitpts Base Maxlvl, Factor, Offset, Range */
|
||||
{ "fighter", 90, 1310720, 13, 10, 30, 2, 1, 3 },
|
||||
{ "ranger", 110, 2293760, 10, 10, 22, 2, 1, 2 },
|
||||
{ "paladin", 110, 1966080, 10, 10, 23, 2, 1, 2 },
|
||||
{ "magician", 105, 2129920, 9, 10, 24, 2, 1, 2 },
|
||||
{ "cleric", 105, 1802240, 9, 10, 24, 2, 1, 2 },
|
||||
{ "thief", 95, 1228800, 11, 10, 28, 2, 1, 3 },
|
||||
{ "assassin", 95, 1392640, 11, 10, 26, 2, 1, 3 },
|
||||
{ "druid", 105, 1638400, 9, 10, 24, 2, 1, 2 },
|
||||
{ "monk", 100, 1556480, 10, 10, 25, 2, 1, 2 },
|
||||
{ "monster", 0, 0, 8, 10, 20, 1, 0, 2 },
|
||||
};
|
||||
|
||||
/*
|
||||
* This array lists the names of the character's abilities. It must be ordered
|
||||
* according to the ability definitions in rogue.h.
|
||||
*/
|
||||
|
||||
struct words abilities[NUMABILITIES] = {
|
||||
"Intelligence", "Strength", "Wisdom", "Dexterity", "Constitution", "Charisma"
|
||||
};
|
||||
|
||||
/*
|
||||
* NOTE: the ordering of the points in this array is critical. They MUST
|
||||
* be listed in the following sequence:
|
||||
*
|
||||
* 7 4 6
|
||||
* 1 0 2
|
||||
* 5 3 8
|
||||
*/
|
||||
|
||||
coord grid[9] = {{0,0},
|
||||
{ 0,-1}, { 0, 1}, {-1, 0}, { 1, 0},
|
||||
{-1,-1}, { 1, 1}, { 1,-1}, {-1, 1}
|
||||
};
|
||||
|
||||
struct death_type deaths[DEATHNUM] = {
|
||||
{ D_ARROW, "an arrow"},
|
||||
{ D_DART, "a dart"},
|
||||
{ D_BOLT, "a bolt"},
|
||||
{ D_POISON, "poison"},
|
||||
{ D_POTION, "a cursed potion"},
|
||||
{ D_PETRIFY, "petrification"},
|
||||
{ D_SUFFOCATION, "suffocation"},
|
||||
{ D_INFESTATION, "a parasite"},
|
||||
{ D_DROWN, "drowning"},
|
||||
{ D_ROT, "body rot"},
|
||||
{ D_CONSTITUTION, "poor health"},
|
||||
{ D_STRENGTH, "being too weak"},
|
||||
{ D_SIGNAL, "a bug"},
|
||||
{ D_CHOKE, "dust of choking"},
|
||||
{ D_STRANGLE, "strangulation"},
|
||||
{ D_FALL, "a fall"},
|
||||
{ D_RELIC, "an artifact's wrath"},
|
||||
{ D_STARVATION, "starvation"},
|
||||
{ D_FOOD_CHOKE, "choking on food"},
|
||||
{ D_SCROLL, "reading a scroll"},
|
||||
{ D_FRIGHT, "being too frightened"},
|
||||
{ D_CRYSTAL, "being absorbed"},
|
||||
{ D_CARD, "the face of death"},
|
||||
};
|
||||
|
||||
/*
|
||||
* weapons and their attributes
|
||||
*/
|
||||
|
||||
struct init_weps weaps[MAXWEAPONS] = {
|
||||
{ "mace", "2d10","2d10", NONE, ISMETAL, 6, 150, 15 },
|
||||
{ "long sword", "3d4", "2d8", NONE, ISMETAL, 5, 200, 25 },
|
||||
{ "short bow", "1d1", "1d1", NONE, 0, 8, 50, 4 },
|
||||
{ "arrow", "2d4", "1d6", BOW, ISMANY|ISMISL, 1, 5, 4 },
|
||||
{ "dagger", "2d8", "1d6", NONE, ISMETAL|ISMISL|ISMANY, 2,10,7},
|
||||
{ "rock", "2d4", "1d6", SLING, ISMANY|ISMISL, 1, 20, 3 },
|
||||
{ "two-handed sword","3d10","3d8", NONE, ISMETAL, 4, 250, 40 },
|
||||
{ "sling", "1d1", "1d1", NONE, 0, 8, 25, 3 },
|
||||
{ "dart", "2d4", "2d6", NONE, ISMANY|ISMISL, 2, 15, 7 },
|
||||
{ "crossbow", "1d1", "1d1", NONE, 0, 8, 75, 5 },
|
||||
{ "crossbow bolt", "2d4", "2d4", CROSSBOW, ISMANY|ISMISL, 1, 10, 5 },
|
||||
{ "spear", "2d6", "3d10", NONE, ISMISL, 7, 100, 15 },
|
||||
{ "trident", "3d6", "3d4", NONE, ISMETAL, 4, 200, 30 },
|
||||
{ "spetum", "2d6", "2d8", NONE, ISMETAL, 6, 150, 20 },
|
||||
{ "bardiche", "3d4", "2d10", NONE, ISMETAL, 5, 150, 25 },
|
||||
{ "pike", "2d8", "2d8", NONE, ISMETAL, 7, 100, 15 },
|
||||
{ "bastard sword", "3d8", "3d6", NONE, ISMETAL, 4, 175, 30 },
|
||||
{ "halberd", "2d8", "2d4", NONE, ISMETAL, 6, 100, 10 },
|
||||
{ "battle axe", "2d8", "3d8", NONE, ISMETAL, 5, 150, 15 },
|
||||
} ;
|
||||
|
||||
struct init_armor armors[MAXARMORS] = {
|
||||
{ "leather armor", 10, 8, 200, 100 },
|
||||
{ "ring mail", 20, 7, 250, 200 },
|
||||
{ "studded leather armor", 30, 5, 320, 250 },
|
||||
{ "scale mail", 40, 7, 280, 250 },
|
||||
{ "padded armor", 50, 6, 350, 300 },
|
||||
{ "chain mail", 60, 6, 350, 600 },
|
||||
{ "splint mail", 70, 5, 370, 400 },
|
||||
{ "banded mail", 80, 5, 370, 350 },
|
||||
{ "plate mail", 90, 4, 400, 400 },
|
||||
{ "plate armor", 100, 3, 500, 450 },
|
||||
};
|
||||
|
||||
struct magic_item things[NUMTHINGS] = {
|
||||
{ "potion", 220, 10 }, /* potion */
|
||||
{ "scroll", 220, 30 }, /* scroll */
|
||||
{ "food", 190, 20 }, /* food */
|
||||
{ "weapon", 90, 0 }, /* weapon */
|
||||
{ "armor", 90, 0 }, /* armor */
|
||||
{ "ring", 70, 5 }, /* ring */
|
||||
{ "stick", 70, 0 }, /* stick */
|
||||
{ "miscellaneous magic", 50, 50 }, /* miscellaneous magic */
|
||||
{ "artifact", 0, 10 }, /* artifact */
|
||||
};
|
||||
|
||||
struct magic_item s_magic[MAXSCROLLS] = {
|
||||
{ "monster confusion", 40, 125, 0, 0 },
|
||||
{ "magic mapping", 60, 150, 0, 5 },
|
||||
{ "light", 60, 100, 15, 15 },
|
||||
{ "hold monster", 30, 200, 20, 20 },
|
||||
{ "sleep", 20, 150, 25, 0 },
|
||||
{ "enchantment", 130, 200, 15, 15 },
|
||||
{ "identify", 170, 100, 0, 20 },
|
||||
{ "scare monster", 40, 250, 20, 30 },
|
||||
{ "gold detection", 30, 110, 0, 0 },
|
||||
{ "teleportation", 60, 165, 20, 20 },
|
||||
{ "create monster", 20, 75, 0, 0 },
|
||||
{ "remove curse", 80, 120, 15, 15 },
|
||||
{ "petrification", 30, 185, 0, 0 },
|
||||
{ "genocide", 10, 300, 0, 0 },
|
||||
{ "cure disease", 80, 160, 0, 0 },
|
||||
{ "acquirement", 10, 700, 0, 5 },
|
||||
{ "protection", 30, 190, 10, 0 },
|
||||
{ "trap finding", 50, 180, 0, 0 },
|
||||
{ "runes", 20, 50, 0, 0 },
|
||||
{ "charm monster", 30, 275, 0, 20 },
|
||||
};
|
||||
|
||||
struct magic_item p_magic[MAXPOTIONS] = {
|
||||
{ "clear thought", 50, 180, 10, 5 },
|
||||
{ "gain ability", 160, 210, 10, 10 },
|
||||
{ "see invisible", 40, 150, 20, 20 },
|
||||
{ "healing", 140, 130, 15, 15 },
|
||||
{ "monster detection", 40, 120, 0, 0 },
|
||||
{ "magic detection", 70, 105, 0, 0 },
|
||||
{ "raise level", 10, 450, 10, 5 },
|
||||
{ "haste self", 50, 180, 20, 5 },
|
||||
{ "restore abilities", 130, 140, 0, 15 },
|
||||
{ "phasing", 60, 210, 10, 10 },
|
||||
{ "invisibility", 20, 230, 0, 10 },
|
||||
{ "flying", 50, 130, 0, 15 },
|
||||
{ "food detection", 20, 150, 0, 0 },
|
||||
{ "skill", 10, 200, 20, 5 },
|
||||
{ "fire resistance", 40, 250, 10, 5 },
|
||||
{ "cold resistance", 40, 250, 10, 5 },
|
||||
{ "lightning protection", 40, 250, 20, 5 },
|
||||
{ "poison", 30, 205, 25, 0 },
|
||||
};
|
||||
|
||||
struct magic_item r_magic[MAXRINGS] = {
|
||||
{ "protection", 60, 200, 25, 25 },
|
||||
{ "add strength", 50, 200, 25, 25 },
|
||||
{ "sustain ability", 50, 500, 0, 0 },
|
||||
{ "searching", 40, 400, 0, 0 },
|
||||
{ "extra sight", 60, 350, 0, 0 },
|
||||
{ "alertness", 40, 380, 0, 0 },
|
||||
{ "aggravate monster", 30, 100, 100, 0 },
|
||||
{ "dexterity", 50, 220, 25, 25 },
|
||||
{ "increase damage", 60, 220, 25, 25 },
|
||||
{ "regeneration", 40, 600, 0, 0 },
|
||||
{ "slow digestion", 50, 240, 20, 20 },
|
||||
{ "teleportation", 20, 100, 90, 0 },
|
||||
{ "stealth", 20, 300, 0, 0 },
|
||||
{ "add intelligence", 50, 240, 25, 25 },
|
||||
{ "increase wisdom", 40, 220, 25, 25 },
|
||||
{ "sustain health", 80, 500, 0, 0 },
|
||||
{ "carrying", 10, 100, 90, 0 },
|
||||
{ "illumination", 30, 520, 0, 0 },
|
||||
{ "delusion", 10, 100, 100, 0 },
|
||||
{ "fear", 20, 100, 75, 0 },
|
||||
{ "heroism", 50, 390, 0, 0 },
|
||||
{ "fire resistance", 40, 400, 0, 0 },
|
||||
{ "warmth", 40, 400, 0, 0 },
|
||||
{ "vampiric regeneration", 10,1000, 0, 0 },
|
||||
{ "free action", 40, 370, 0, 0 },
|
||||
{ "teleport control", 10, 700, 0, 0 },
|
||||
};
|
||||
|
||||
struct magic_item ws_magic[MAXSTICKS] = {
|
||||
{ "light", 80, 120, 15, 15 },
|
||||
{ "striking", 50, 115, 0, 0 },
|
||||
{ "lightning", 40, 200, 0, 0 },
|
||||
{ "fire", 30, 200, 0, 0 },
|
||||
{ "cold", 30, 200, 0, 0 },
|
||||
{ "polymorph", 80, 150, 0, 0 },
|
||||
{ "magic missile", 90, 170, 0, 0 },
|
||||
{ "slow", 70, 220, 20, 10 },
|
||||
{ "drain life", 50, 210, 20, 0 },
|
||||
{ "charging", 70, 400, 0, 0 },
|
||||
{ "teleport", 90, 140, 20, 10 },
|
||||
{ "cancellation", 50, 130, 0, 0 },
|
||||
{ "confusion", 30, 100, 20, 0 },
|
||||
{ "disintegration", 20, 300, 25, 0 },
|
||||
{ "petrification", 30, 240, 0, 0 },
|
||||
{ "paralyzation", 30, 180, 10, 0 },
|
||||
{ "degeneration", 30, 250, 20, 0 },
|
||||
{ "curing", 50, 250, 20, 5 },
|
||||
{ "wonder", 40, 110, 20, 20 },
|
||||
{ "fear", 40, 180, 0, 0 },
|
||||
};
|
||||
|
||||
/*
|
||||
* WARNING: unique miscellaneous magic items must be put at the end
|
||||
* of this list. They MUST be the last items. The function
|
||||
* create_obj() in wizard.c depends on it.
|
||||
*/
|
||||
|
||||
struct magic_item m_magic[MAXMM] = {
|
||||
{ "alchemy jug", 40, 240, 0, 0 },
|
||||
{ "beaker of potions", 60, 300, 0, 0 },
|
||||
{ "book of spells", 60, 300, 0, 0 },
|
||||
{ "boots of elvenkind", 50, 500, 0, 0 },
|
||||
{ "bracers of defense", 80, 400, 20, 10 },
|
||||
{ "chime of opening", 30, 250, 0, 0 },
|
||||
{ "chime of hunger", 20, 100, 100, 0 },
|
||||
{ "cloak of displacement", 60, 500, 0, 0 },
|
||||
{ "cloak of protection", 80, 400, 20, 10 },
|
||||
{ "drums of panic", 60, 350, 0, 0 },
|
||||
{ "dust of disappearance", 30, 300, 0, 0 },
|
||||
{ "dust of choking", 30, 100, 100, 0 },
|
||||
{ "gauntlets of dexterity", 40, 600, 25, 0 },
|
||||
{ "gauntlets of ogre power", 40, 600, 25, 0 },
|
||||
{ "jewel of attacks", 50, 150, 100, 0 },
|
||||
{ "keoghtoms ointment", 60, 350, 0, 0 },
|
||||
{ "robe of powerlessness", 20, 100, 100, 0 },
|
||||
{ "gauntlets of fumbling", 30, 100, 100, 0 },
|
||||
{ "necklace of adaptation", 50, 500, 0, 0 },
|
||||
{ "necklace of strangulation", 30, 110, 100, 0 },
|
||||
{ "boots of dancing", 40, 120, 100, 0 },
|
||||
{ "book of skills", 30, 650, 0, 0 },
|
||||
{ "medicine crystal", 10, 800, 25, 5 },
|
||||
};
|
||||
|
||||
struct magic_item rel_magic[MAXRELIC] = {
|
||||
{ "Daggers of Musty Doit", 0, 50000, 0, 0},
|
||||
{ "Cloak of Emori", 0, 50000, 0, 0},
|
||||
{ "Ankh of Heil", 0, 50000, 0, 0},
|
||||
{ "Staff of Ming", 0, 50000, 0, 0},
|
||||
{ "Wand of Orcus", 0, 50000, 0, 0},
|
||||
{ "Rod of Asmodeus", 0, 50000, 0, 0},
|
||||
{ "Amulet of Yendor", 0, 50000, 0, 0},
|
||||
{ "Mandolin of Brian", 0, 50000, 0, 0},
|
||||
{ "Horn of Geryon", 0, 50000, 0, 0},
|
||||
{ "Morning Star of Hruggek", 0, 50000, 0, 0},
|
||||
{ "Flail of Yeenoghu", 0, 50000, 0, 0},
|
||||
{ "Eye of Vecna", 0, 50000, 0, 0},
|
||||
{ "Axe of Aklad", 0, 50000, 0, 0},
|
||||
{ "Quill of Nagrom", 0, 50000, 0, 0},
|
||||
{ "Amulet of Stonebones", 0, 50000, 0, 0},
|
||||
{ "Ring of Surtur", 0, 50000, 0, 0},
|
||||
{ "Card of Alteran", 0, 50000, 0, 0},
|
||||
};
|
||||
|
||||
/*
|
||||
* food and fruits that you get
|
||||
*/
|
||||
struct magic_item foods[MAXFOODS] = {
|
||||
|
||||
{ "food ration", 690, 50, 750, 0},
|
||||
{ "apple", 10, 20, 300, 0},
|
||||
{ "banana", 30, 20, 300, 0},
|
||||
{ "blueberry", 30, 20, 300, 0},
|
||||
{ "candleberry", 10, 20, 300, 0},
|
||||
{ "caprifig", 20, 20, 300, 0},
|
||||
{ "dewberry", 10, 20, 300, 0},
|
||||
{ "elderberry", 30, 20, 300, 0},
|
||||
{ "gooseberry", 20, 20, 300, 0},
|
||||
{ "guanabana", 30, 20, 300, 0},
|
||||
{ "hagberry", 10, 20, 300, 0},
|
||||
{ "jaboticaba", 10, 20, 300, 0},
|
||||
{ "peach", 10, 20, 300, 0},
|
||||
{ "pitanga", 10, 20, 300, 0},
|
||||
{ "prickly pear", 10, 20, 300, 0},
|
||||
{ "rambutan", 10, 20, 300, 0},
|
||||
{ "sapodilla", 10, 20, 300, 0},
|
||||
{ "soursop", 10, 20, 300, 0},
|
||||
{ "strawberry", 10, 20, 300, 0},
|
||||
{ "sweetsop", 10, 20, 300, 0},
|
||||
{ "whortleberry", 10, 20, 300, 0},
|
||||
{ "slime-mold", 10, 10, 100, 0},
|
||||
};
|
||||
|
||||
/*
|
||||
* these are the spells that a magician can cast
|
||||
*/
|
||||
|
||||
struct spells magic_spells[MAXSPELLS] = {
|
||||
{ P_TFIND, 3, TYP_POTION, 0 },
|
||||
{ S_IDENT, 5, TYP_SCROLL, 0 },
|
||||
{ S_LIGHT, 7, TYP_SCROLL, ISBLESSED },
|
||||
{ S_REMOVE, 10, TYP_SCROLL, 0 },
|
||||
{ S_FINDTRAPS, 15, TYP_SCROLL, 0 },
|
||||
{ P_FLY, 20, TYP_POTION, 0 },
|
||||
{ S_TELEP, 25, TYP_SCROLL, 0 },
|
||||
{ S_SLEEP, 30, TYP_SCROLL, 0 },
|
||||
{ P_SEEINVIS, 35, TYP_POTION, ISBLESSED },
|
||||
{ P_CLEAR, 40, TYP_POTION, 0 },
|
||||
{ WS_COLD, 45, TYP_STICK, 0 },
|
||||
{ P_PHASE, 50, TYP_POTION, 0 },
|
||||
{ WS_FIRE, 55, TYP_STICK, 0 },
|
||||
{ P_HASTE, 60, TYP_POTION, ISBLESSED },
|
||||
{ WS_ELECT, 65, TYP_STICK, 0 },
|
||||
{ S_HOLD, 70, TYP_SCROLL, ISBLESSED },
|
||||
};
|
||||
|
||||
/*
|
||||
* these are the spells that a cleric can cast
|
||||
*/
|
||||
|
||||
struct spells cleric_spells[MAXPRAYERS] = {
|
||||
{ P_MFIND, 3, TYP_POTION, 0 },
|
||||
{ P_TFIND, 5, TYP_POTION, 0 },
|
||||
{ S_LIGHT, 7, TYP_SCROLL, ISBLESSED },
|
||||
{ S_REMOVE, 10, TYP_SCROLL, 0 },
|
||||
{ P_FFIND, 15, TYP_POTION, 0 },
|
||||
{ P_FLY, 20, TYP_POTION, 0 },
|
||||
{ P_HEALING, 25, TYP_POTION, 0 },
|
||||
{ S_CURING, 30, TYP_SCROLL, 0 },
|
||||
{ P_RESTORE, 35, TYP_POTION, 0 },
|
||||
{ S_MAP, 40, TYP_SCROLL, 0 },
|
||||
{ P_SEEINVIS, 45, TYP_POTION, ISBLESSED },
|
||||
{ P_CLEAR, 50, TYP_POTION, 0 },
|
||||
{ P_PHASE, 55, TYP_POTION, 0 },
|
||||
{ WS_CURING, 60, TYP_STICK, ISBLESSED },
|
||||
{ WS_PARALYZE, 65, TYP_STICK, 0 },
|
||||
{ S_ALLENCH, 70, TYP_SCROLL, 0 },
|
||||
};
|
||||
|
||||
/*
|
||||
* these are the spells that a druid can chant
|
||||
*/
|
||||
|
||||
struct spells druid_spells[MAXCHANTS] = {
|
||||
{ P_MFIND, 3, TYP_POTION, 0 },
|
||||
{ P_TFIND, 5, TYP_POTION, 0 },
|
||||
{ S_LIGHT, 7, TYP_SCROLL, ISBLESSED },
|
||||
{ S_REMOVE, 10, TYP_SCROLL, 0 },
|
||||
{ S_FINDTRAPS, 15, TYP_SCROLL, 0 },
|
||||
{ S_CONFUSE, 20, TYP_SCROLL, 0 },
|
||||
{ P_FFIND, 25, TYP_POTION, 0 },
|
||||
{ P_HEALING, 30, TYP_POTION, 0 },
|
||||
{ S_MAP, 35, TYP_SCROLL, 0 },
|
||||
{ P_CLEAR, 40, TYP_POTION, 0 },
|
||||
{ P_COLD, 45, TYP_POTION, 0 },
|
||||
{ P_FIRE, 50, TYP_POTION, 0 },
|
||||
{ P_PHASE, 55, TYP_POTION, 0 },
|
||||
{ P_LIGHTNING, 60, TYP_POTION, 0 },
|
||||
{ S_CHARM, 65, TYP_SCROLL, ISBLESSED },
|
||||
{ S_HOLD, 70, TYP_SCROLL, ISBLESSED },
|
||||
};
|
||||
|
||||
/*
|
||||
* these are the scrolls that a quill can write
|
||||
*/
|
||||
|
||||
struct spells quill_scrolls[MAXQUILL] = {
|
||||
{ S_GFIND, 5, },
|
||||
{ S_IDENT, 10, },
|
||||
{ S_LIGHT, 10, },
|
||||
{ S_REMOVE, 15, },
|
||||
{ S_MAP, 20, },
|
||||
{ S_CONFUSE, 25, },
|
||||
{ S_SLEEP, 30, },
|
||||
{ S_CURING, 40, },
|
||||
{ S_TELEP, 50, },
|
||||
{ S_SCARE, 60, },
|
||||
{ S_HOLD, 70, },
|
||||
{ S_PETRIFY, 80, },
|
||||
{ S_PROTECT, 90, },
|
||||
{ S_ALLENCH, 100, },
|
||||
};
|
||||
|
||||
/*
|
||||
* Experience-level names of each character (see NUM_CNAMES in rogue.h)
|
||||
*/
|
||||
|
||||
const char *cnames[NUM_CHARTYPES-1][NUM_CNAMES] = {
|
||||
{ "Veteran", "Fighter", /* Fighter */
|
||||
"Ruffian", "Tussler",
|
||||
"Swordsman", "Hero",
|
||||
"Bravo", "Picador",
|
||||
"Stalwart", "Bashar",
|
||||
"Swashbuckler", "Myrmidon",
|
||||
"Fusileer", "Pugilist",
|
||||
"Champion", "Superhero",
|
||||
"Warrior", "Lord",
|
||||
"Lord I", "Lord II",
|
||||
"Lord III", "Lord IV",
|
||||
"Lord V", "Lord VI",
|
||||
"Lord VII", "Warrior Lord"
|
||||
},
|
||||
{ "Runner", "Strider", /* Ranger */
|
||||
"Warden", "Steward",
|
||||
"Scout", "Courser",
|
||||
"Tracker", "Guide",
|
||||
"Protector", "Bartizan",
|
||||
"Gendarme", "Sentinel",
|
||||
"Vigilant", "Pathfinder",
|
||||
"Guardian", "Overseer",
|
||||
"Castellan", "Ranger",
|
||||
"Lord Ranger I", "Lord Ranger II",
|
||||
"Lord Ranger III", "Lord Ranger IV",
|
||||
"Lord Ranger V", "Lord Ranger VI",
|
||||
"Lord Ranger VII", "Master Ranger"
|
||||
},
|
||||
{ "Gallant", "Keeper", /* Paladin */
|
||||
"Bravado", "Brazen",
|
||||
"Protector", "Defender",
|
||||
"Warder", "Guardian",
|
||||
"Champion", "Bulwark",
|
||||
"Venturist", "Inspirator",
|
||||
"Chevalier", "Justiciar",
|
||||
"Undaunteer", "Plautus",
|
||||
"Knight", "Paladin",
|
||||
"Paladin I", "Paladin II",
|
||||
"Paladin III", "Paladin IV",
|
||||
"Paladin V", "Paladin VI",
|
||||
"Paladin VII", "Lord Paladin"
|
||||
},
|
||||
{ "Prestidigitator", "Evoker", /* Magic User */
|
||||
"Summoner", "Invoker",
|
||||
"Conjurer", "Theurgist",
|
||||
"Illusionist", "Diviner",
|
||||
"Thaumaturgist", "Magician",
|
||||
"Thelemist", "Magus",
|
||||
"Enchanter", "Warlock",
|
||||
"Witch", "Shaman",
|
||||
"Sorcerer", "Wizard",
|
||||
"Wizard I", "Wizard II",
|
||||
"Wizard III", "Wizard IV",
|
||||
"Wizard V", "Wizard VI",
|
||||
"Wizard VII", "Lord Magus"
|
||||
},
|
||||
{ "Acolyte", "Adept", /* Cleric */
|
||||
"Charmer", "Friar",
|
||||
"Priest", "Curate",
|
||||
"Vicar", "Deacon",
|
||||
"Sabiast", "Cabalist",
|
||||
"Prefect", "Canon",
|
||||
"Minister", "Cardinal",
|
||||
"Bishop", "Patriarch",
|
||||
"Exorcist", "Archdeacon",
|
||||
"High Priest I", "High Priest II",
|
||||
"High Priest III", "High Priest IV",
|
||||
"High Priest V", "High Priest VI",
|
||||
"High Priest VII", "Reverend Lord"
|
||||
},
|
||||
{ "Rogue", "Footpad", /* Thief */
|
||||
"Cutpurse", "Robber",
|
||||
"Vagrant", "Truant",
|
||||
"Burglar", "Filcher",
|
||||
"Sharper", "Magsman",
|
||||
"Racketeer", "Prowler",
|
||||
"Crook", "Bounder",
|
||||
"Quisling", "Malfeasor",
|
||||
"Swindler", "Thief",
|
||||
"Master Thief I", "Master Thief II",
|
||||
"Master Thief III", "Master Thief IV",
|
||||
"Master Thief V", "Master Thief VI",
|
||||
"Master Thief VII", "Master Rogue"
|
||||
},
|
||||
{ "Bravo", "Rutterkin", /* Assassin */
|
||||
"Waghalter", "Murderer",
|
||||
"Butcher", "Desperado",
|
||||
"Thug", "Killer",
|
||||
"Cutthroat", "Executioner",
|
||||
"Eradicator", "Obliterator",
|
||||
"Mechanic", "Wiseguy",
|
||||
"Nihilist", "Berserker",
|
||||
"Assassin", "Expert Assassin",
|
||||
"Prime Assassin I", "Prime Assassin II",
|
||||
"Prime Assassin III", "Prime Assassin IV",
|
||||
"Prime Assassin V", "Prime Assassin VI",
|
||||
"Prime Assassin VII", "Master Assassin"
|
||||
},
|
||||
{ "Aspirant", "Ovate", /* Druid */
|
||||
"Practitioner", "Devoutist",
|
||||
"Initiate 1st Circle", "Initiate 2nd Circle",
|
||||
"Initiate 3rd Circle", "Initiate 4th Circle",
|
||||
"Initiate 5th Circle", "Initiate 6th Circle",
|
||||
"Initiate 7th Circle", "Initiate 8th Circle",
|
||||
"Initiate 9th Circle", "Illuminati",
|
||||
"Lesser Druid", "Arch Druid",
|
||||
"Druid", "Master Druid",
|
||||
"Master Druid I", "Master Druid II",
|
||||
"Master Druid III", "Master Druid IV",
|
||||
"Master Druid V", "Master Druid VI",
|
||||
"Master Druid VII", "Lord Druid"
|
||||
},
|
||||
{ "Novice", "Initiate", /* Monk */
|
||||
"Brother", "Disciple",
|
||||
"Canon", "Elder",
|
||||
"Precept", "Lama",
|
||||
"Immaculate", "Wizard",
|
||||
"Shaman", "Master",
|
||||
"Superior Master", "Master of Dragons",
|
||||
"Master of North Wind", "Master of West Wind",
|
||||
"Master of South Wind", "Master of East Wind",
|
||||
"Grand Master I", "Grand Master II",
|
||||
"Grand Master III", "Grand Master IV",
|
||||
"Grand Master V", "Grand Master VI",
|
||||
"Grand Master VII", "Lord Monk"
|
||||
}
|
||||
};
|
||||
|
||||
1405
xrogue/rogue.h
Normal file
1405
xrogue/rogue.h
Normal file
File diff suppressed because it is too large
Load diff
295
xrogue/rooms.c
Normal file
295
xrogue/rooms.c
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
/*
|
||||
rooms.c - Draw the nine rooms on the screen
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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;
|
||||
int left_out;
|
||||
int num_monsters;
|
||||
int which_monster;
|
||||
int j;
|
||||
coord top;
|
||||
coord bsze;
|
||||
coord mp;
|
||||
coord *np;
|
||||
|
||||
/*
|
||||
* bsze is the maximum room size
|
||||
*/
|
||||
bsze.x = cols/3;
|
||||
bsze.y = (lines-2)/3;
|
||||
/*
|
||||
* Clear things for a new level
|
||||
*/
|
||||
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) {
|
||||
rp->r_flags = 0;
|
||||
_r_free_fire_list(&rp->r_fires);
|
||||
}
|
||||
/*
|
||||
* 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.y = -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) < 55 && level >= cur_max)
|
||||
{
|
||||
register struct linked_list *item;
|
||||
register struct object *cur;
|
||||
coord tp;
|
||||
|
||||
has_gold = TRUE; /* This room has gold in it */
|
||||
|
||||
item = spec_item(GOLD, NULL, NULL, NULL);
|
||||
cur = OBJPTR(item);
|
||||
|
||||
/* Put the gold into the level list of items */
|
||||
attach(lvl_obj, item);
|
||||
|
||||
/* Put it somewhere */
|
||||
rnd_pos(rp, &tp);
|
||||
mvaddch(tp.y, tp.x, GOLD);
|
||||
cur->o_pos = tp;
|
||||
if (roomin(&tp) != rp) {
|
||||
endwin();
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Put the monster in
|
||||
*/
|
||||
if (rnd(100) < (has_gold ? 80 : 25) + vlevel/2)
|
||||
{
|
||||
do
|
||||
{
|
||||
rnd_pos(rp, &mp);
|
||||
} until(mvwinch(stdscr, mp.y, mp.x) == FLOOR);
|
||||
which_monster = randmonster(FALSE, FALSE);
|
||||
num_monsters = 1;
|
||||
/*
|
||||
* see if we should make a whole bunch
|
||||
*/
|
||||
for (j=0; j<MAXFLAGS; j++) {
|
||||
if (monsters[which_monster].m_flags[j] == AREMANY)
|
||||
num_monsters = roll(7,2);
|
||||
}
|
||||
for (j=0; j<num_monsters; j++) {
|
||||
if ((np = fallpos(&mp, FALSE, 2)) != NULL &&
|
||||
mvwinch(stdscr, np->y, np->x) == FLOOR) {
|
||||
item = new_item(sizeof *tp);
|
||||
tp = THINGPTR(item);
|
||||
new_monster(item, which_monster, np, FALSE);
|
||||
/*
|
||||
* See if we want to give it a treasure to
|
||||
* carry around.
|
||||
*/
|
||||
carry_obj(tp, monsters[tp->t_index].m_carry);
|
||||
tp->t_no_move = movement(tp);
|
||||
|
||||
/*
|
||||
* If it has a fire, mark it
|
||||
*/
|
||||
if (on(*tp, HASFIRE)) {
|
||||
register struct linked_list *fire_item;
|
||||
|
||||
fire_item = creat_item();
|
||||
ldata(fire_item) = (char *) tp;
|
||||
attach(rp->r_fires, fire_item);
|
||||
rp->r_flags |= HASFIRE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a room pointer and a pointer to a door, supposedly in that room,
|
||||
* return the coordinates of the entrance to the doorway.
|
||||
*/
|
||||
|
||||
coord *
|
||||
doorway(rp, door)
|
||||
register struct room *rp;
|
||||
register coord *door;
|
||||
{
|
||||
register int misses = 0;
|
||||
static coord answer;
|
||||
|
||||
/* Do we have decent parameters? */
|
||||
if (rp == NULL || door == NULL) return(NULL);
|
||||
|
||||
/* Initialize the answer to be the door, then calculate the offset */
|
||||
answer = *door;
|
||||
|
||||
/* Calculate the x-offset */
|
||||
if (door->x == rp->r_pos.x) answer.x++;
|
||||
else if (door->x == rp->r_pos.x + rp->r_max.x - 1) answer.x--;
|
||||
else misses++;
|
||||
|
||||
/* Calculate the y-offset */
|
||||
if (door->y == rp->r_pos.y) answer.y++;
|
||||
else if (door->y == rp->r_pos.y + rp->r_max.y - 1) answer.y--;
|
||||
else misses++;
|
||||
|
||||
if (misses <= 1) return(&answer);
|
||||
else return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Draw a box around a room
|
||||
*/
|
||||
|
||||
draw_room(rp)
|
||||
register struct room *rp;
|
||||
{
|
||||
register int j, k;
|
||||
|
||||
move(rp->r_pos.y, rp->r_pos.x+1);
|
||||
vert(rp->r_max.y-2); /* Draw left side */
|
||||
move(rp->r_pos.y+rp->r_max.y-1, rp->r_pos.x);
|
||||
horiz(rp->r_max.x); /* Draw bottom */
|
||||
move(rp->r_pos.y, rp->r_pos.x);
|
||||
horiz(rp->r_max.x); /* Draw top */
|
||||
vert(rp->r_max.y-2); /* Draw right side */
|
||||
/*
|
||||
* Put the floor down
|
||||
*/
|
||||
for (j = 1; j < rp->r_max.y-1; j++)
|
||||
{
|
||||
move(rp->r_pos.y + j, rp->r_pos.x+1);
|
||||
for (k = 1; k < rp->r_max.x-1; k++)
|
||||
addch(FLOOR);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* horiz:
|
||||
* draw a horizontal line
|
||||
*/
|
||||
|
||||
horiz(cnt)
|
||||
register int cnt;
|
||||
{
|
||||
while (cnt--)
|
||||
addch(HORZWALL);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(VERTWALL);
|
||||
}
|
||||
}
|
||||
|
||||
304
xrogue/save.c
Normal file
304
xrogue/save.c
Normal file
|
|
@ -0,0 +1,304 @@
|
|||
/*
|
||||
save.c - save and restore routines
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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 <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include "rogue.h"
|
||||
#include "mach_dep.h"
|
||||
|
||||
extern char version[];
|
||||
extern unsigned char encstr[];
|
||||
extern int big_endian;
|
||||
|
||||
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 = wgetch(cw);
|
||||
if (c == ESC) 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;
|
||||
}
|
||||
}
|
||||
else
|
||||
goto gotfile; /* must save to file restored from */
|
||||
|
||||
do
|
||||
{
|
||||
msg("File name: ");
|
||||
mpos = 0;
|
||||
buf[0] = '\0';
|
||||
if (get_str(buf, msgw) == QUIT)
|
||||
{
|
||||
msg("");
|
||||
return FALSE;
|
||||
}
|
||||
strcpy(file_name, buf);
|
||||
gotfile:
|
||||
|
||||
if ((savef = fopen(file_name, "wb")) == NULL)
|
||||
msg(strerror(errno));
|
||||
} while (savef == NULL);
|
||||
|
||||
msg("");
|
||||
/*
|
||||
* write out encrpyted file
|
||||
*/
|
||||
if (save_file(savef) == FALSE) {
|
||||
fclose(savef);
|
||||
msg("Cannot create save file.");
|
||||
unlink(file_name);
|
||||
return(FALSE);
|
||||
}
|
||||
fclose(savef);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* automatically save a file. This is used if a HUP signal is recieved
|
||||
*/
|
||||
|
||||
void
|
||||
auto_save(int sig)
|
||||
{
|
||||
register FILE *savef = NULL;
|
||||
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, "wb")) != NULL))
|
||||
save_file(savef);
|
||||
fclose(savef);
|
||||
exit_game(EXIT_ENDWIN);
|
||||
}
|
||||
|
||||
/*
|
||||
* write the saved game on the file
|
||||
*/
|
||||
|
||||
bool
|
||||
save_file(savef)
|
||||
register FILE *savef;
|
||||
{
|
||||
int slines = LINES;
|
||||
int scols = COLS;
|
||||
int ret = FALSE;
|
||||
int endian = 0x01020304;
|
||||
big_endian = ( *((char *)&endian) == 0x01 );
|
||||
|
||||
wmove(cw, LINES-1, 0);
|
||||
draw(cw);
|
||||
|
||||
encwrite(version,strlen(version)+1,savef);
|
||||
rs_write_int(savef,slines);
|
||||
rs_write_int(savef,scols);
|
||||
|
||||
ret = rs_save_file(savef);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
restore(file, envp)
|
||||
register char *file;
|
||||
char **envp;
|
||||
{
|
||||
register int inf;
|
||||
extern char **environ;
|
||||
char buf[LINELEN];
|
||||
int endian = 0x01020304;
|
||||
big_endian = ( *((char *)&endian) == 0x01 );
|
||||
|
||||
if (strcmp(file, "-r") == 0)
|
||||
file = file_name;
|
||||
|
||||
if ((inf = open(file, O_RDONLY)) < 0)
|
||||
{
|
||||
perror(file);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
encread(buf, strlen(version) + 1, inf);
|
||||
|
||||
if (strcmp(buf, version) != 0)
|
||||
{
|
||||
printf("Sorry, saved game is out of date.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
rs_read_int(inf,&lines);
|
||||
rs_read_int(inf,&cols);
|
||||
|
||||
initscr();
|
||||
|
||||
if (lines > LINES)
|
||||
{
|
||||
endwin();
|
||||
printf("Sorry, original game was played on a screen with %d lines.\n",lines);
|
||||
printf("Current screen only has %d lines. Unable to restore game\n",LINES);
|
||||
return(FALSE);
|
||||
}
|
||||
if (cols > COLS)
|
||||
{
|
||||
endwin();
|
||||
printf("Sorry, original game was played on a screen with %d columns.\n",cols);
|
||||
printf("Current screen only has %d columns. Unable to restore game\n",COLS);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
typeahead(-1);
|
||||
setup();
|
||||
cw = newwin(LINES, COLS, 0, 0);
|
||||
mw = newwin(LINES, COLS, 0, 0);
|
||||
hw = newwin(LINES, COLS, 0, 0);
|
||||
msgw = newwin(4, cols, 0, 0);
|
||||
|
||||
keypad(cw, TRUE);
|
||||
keypad(hw, TRUE);
|
||||
|
||||
if (rs_restore_file(inf) == FALSE)
|
||||
{
|
||||
endwin();
|
||||
printf("Cannot restore file\n");
|
||||
close(inf);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
close(inf);
|
||||
|
||||
if (!wizard)
|
||||
unlink(file);
|
||||
|
||||
mpos = 0;
|
||||
environ = envp;
|
||||
strcpy(file_name, file);
|
||||
clearok(curscr, TRUE);
|
||||
touchwin(cw);
|
||||
wrefresh(cw);
|
||||
msg("Welcome back! --More-- ");
|
||||
wait_for(' ');
|
||||
msg("");
|
||||
playit();
|
||||
|
||||
/*NOTREACHED*/
|
||||
return(1);
|
||||
}
|
||||
|
||||
#define ENCWBSIZ 1024
|
||||
|
||||
/*
|
||||
* perform an encrypted write
|
||||
*/
|
||||
|
||||
long
|
||||
encwrite(start, size, outf)
|
||||
register char *start;
|
||||
register unsigned long size;
|
||||
register FILE *outf;
|
||||
{
|
||||
register unsigned char *ep;
|
||||
register int i = 0;
|
||||
unsigned long num_written = 0;
|
||||
char buf[ENCWBSIZ];
|
||||
int ret;
|
||||
|
||||
ep = encstr;
|
||||
|
||||
while (size--)
|
||||
{
|
||||
buf[i++] = *start++ ^ *ep++;
|
||||
if (*ep == '\0')
|
||||
ep = encstr;
|
||||
|
||||
if (i == ENCWBSIZ || size == 0)
|
||||
{
|
||||
ret = (unsigned int) fwrite(buf, 1, i, outf);
|
||||
if (ret > 0)
|
||||
num_written += ret;
|
||||
|
||||
if (ret < i)
|
||||
return(num_written);
|
||||
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
return(num_written);
|
||||
}
|
||||
|
||||
#define ENCRBSIZ 32768
|
||||
|
||||
/*
|
||||
* perform an encrypted read
|
||||
*/
|
||||
|
||||
long
|
||||
encread(start, size, inf)
|
||||
register char *start;
|
||||
register unsigned long size;
|
||||
int inf;
|
||||
{
|
||||
register unsigned char *ep;
|
||||
register int rd_siz;
|
||||
register unsigned long total_read;
|
||||
|
||||
total_read = 0;
|
||||
while (total_read < size) {
|
||||
rd_siz = ENCRBSIZ;
|
||||
rd_siz = ((size-total_read) > ENCRBSIZ) ? ENCRBSIZ : (size-total_read);
|
||||
rd_siz = read(inf,&start[total_read],rd_siz);
|
||||
if(rd_siz==-1 || rd_siz==0)
|
||||
break;
|
||||
total_read += rd_siz;
|
||||
}
|
||||
ep = encstr;
|
||||
|
||||
size = total_read;
|
||||
while (size--)
|
||||
{
|
||||
*start++ ^= *ep++;
|
||||
if (*ep == '\0')
|
||||
ep = encstr;
|
||||
}
|
||||
return total_read;
|
||||
}
|
||||
|
||||
901
xrogue/scrolls.c
Normal file
901
xrogue/scrolls.c
Normal file
|
|
@ -0,0 +1,901 @@
|
|||
/*
|
||||
scrolls.c - Functions for dealing with scrolls
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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
|
||||
*/
|
||||
|
||||
genocide()
|
||||
{
|
||||
register struct linked_list *ip;
|
||||
register struct thing *mp;
|
||||
register struct linked_list *nip;
|
||||
/* cannot genocide any uniques */
|
||||
register int num_monst = NUMMONST-NUMUNIQUE-NUMDINOS;
|
||||
register int which_monst;
|
||||
|
||||
which_monst = makemonster(FALSE, "wipe out");
|
||||
if (which_monst <= 0 || which_monst >= num_monst) {
|
||||
msg("");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Remove this monster from the present level */
|
||||
for (ip = mlist; ip; ip = nip) {
|
||||
mp = THINGPTR(ip);
|
||||
nip = next(ip);
|
||||
if (mp->t_index == which_monst) {
|
||||
killed(ip, FALSE, FALSE, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove from available monsters */
|
||||
monsters[which_monst].m_normal = FALSE;
|
||||
monsters[which_monst].m_wander = FALSE;
|
||||
mpos = 0;
|
||||
msg("You have wiped out the %s.", monsters[which_monst].m_name);
|
||||
}
|
||||
|
||||
read_scroll(which, flag, is_scroll)
|
||||
register int which;
|
||||
int flag;
|
||||
bool is_scroll;
|
||||
{
|
||||
register struct object *obj = NULL, *nobj;
|
||||
register struct linked_list *item, *nitem;
|
||||
register int i,j;
|
||||
register unsigned char ch, nch;
|
||||
bool cursed, blessed;
|
||||
|
||||
blessed = FALSE;
|
||||
cursed = FALSE;
|
||||
item = NULL;
|
||||
|
||||
if (which < 0) {
|
||||
if (on(player, ISBLIND)) {
|
||||
msg("You can't see to read anything!");
|
||||
return;
|
||||
}
|
||||
if (on(player, ISINWALL)) {
|
||||
msg("You can't see the scroll while inside rock!");
|
||||
return;
|
||||
}
|
||||
|
||||
/* This is a scroll or book. */
|
||||
if (player.t_action != C_READ) {
|
||||
int units;
|
||||
|
||||
item = get_item(pack, "read", READABLE, FALSE, FALSE);
|
||||
|
||||
/*
|
||||
* Make certain that it is somethings that we want to read
|
||||
*/
|
||||
if (item == NULL)
|
||||
return;
|
||||
|
||||
/* How long does it take to read? */
|
||||
units = usage_time(item);
|
||||
if (units < 0) return;
|
||||
|
||||
player.t_using = item; /* Remember what it is */
|
||||
player.t_no_move = units * movement(&player);
|
||||
if ((OBJPTR(item))->o_type == SCROLL) player.t_action = C_READ;
|
||||
else player.t_action = C_USE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* We have waited our time, let's quaff the potion */
|
||||
item = player.t_using;
|
||||
player.t_using = NULL;
|
||||
player.t_action = A_NIL;
|
||||
|
||||
obj = OBJPTR(item);
|
||||
/* remove it from the pack */
|
||||
inpack--;
|
||||
detach(pack, item);
|
||||
|
||||
msg("As you read the scroll, it vanishes.");
|
||||
cursed = obj->o_flags & ISCURSED;
|
||||
blessed = obj->o_flags & ISBLESSED;
|
||||
|
||||
which = obj->o_which;
|
||||
}
|
||||
else {
|
||||
cursed = flag & ISCURSED;
|
||||
blessed = flag & ISBLESSED;
|
||||
}
|
||||
|
||||
switch (which) {
|
||||
case S_CONFUSE: /* Scroll of monster confusion. Give him that power. */
|
||||
{
|
||||
register char *str;
|
||||
|
||||
switch (rnd(5)) {
|
||||
case 0:
|
||||
str = "glow red";
|
||||
when 1:
|
||||
str = "vibrate";
|
||||
when 2:
|
||||
str = "glow blue";
|
||||
when 3:
|
||||
str = "radiate green";
|
||||
otherwise:
|
||||
str = "itch with a strange desire";
|
||||
}
|
||||
msg("Your hands begin to %s. ", str);
|
||||
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.");
|
||||
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
|
||||
*/
|
||||
msg("You hear a high-pitched humming noise.");
|
||||
/* protect good charactors */
|
||||
if (player.t_ctype == C_PALADIN ||
|
||||
player.t_ctype == C_RANGER || player.t_ctype == C_MONK) {
|
||||
msg("A chill runs up your spine! ");
|
||||
aggravate(TRUE, FALSE);
|
||||
}
|
||||
else {
|
||||
aggravate(TRUE, TRUE);
|
||||
}
|
||||
}
|
||||
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);
|
||||
turn_off(*th, ISCHARMED);
|
||||
}
|
||||
if (levtype == OUTSIDE)
|
||||
msg("A sudden peace comes over the land.. ");
|
||||
else
|
||||
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);
|
||||
turn_off(*th, ISCHARMED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (gotone) msg("A sudden peace surrounds you.");
|
||||
else msg(nothing);
|
||||
}
|
||||
when S_SLEEP:
|
||||
/*
|
||||
* if cursed, you fall asleep
|
||||
*/
|
||||
if (is_scroll) s_know[S_SLEEP] = TRUE;
|
||||
if (cursed) {
|
||||
if (ISWEARING(R_ALERT))
|
||||
msg("You feel drowsy for a moment.");
|
||||
else {
|
||||
msg("You fall asleep.");
|
||||
player.t_no_move += movement(&player)*(4 + rnd(SLEEPTIME));
|
||||
player.t_action = A_FREEZE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* sleep monster scroll.
|
||||
* puts all monsters within 2 spaces asleep
|
||||
*/
|
||||
register int x,y;
|
||||
register struct linked_list *mon;
|
||||
bool gotone=FALSE;
|
||||
|
||||
for (x = hero.x-2; x <= hero.x+2; x++) {
|
||||
for (y = hero.y-2; y <= hero.y+2; y++) {
|
||||
if (y < 1 || x < 0 || y > lines - 3 || x > cols - 1)
|
||||
continue;
|
||||
if (isalpha(mvwinch(mw, y, x))) {
|
||||
if ((mon = find_mons(y, x)) != NULL) {
|
||||
register struct thing *th;
|
||||
|
||||
th = THINGPTR(mon);
|
||||
if (on(*th, ISUNDEAD))
|
||||
continue;
|
||||
th->t_no_move += movement(th)*(SLEEPTIME+4);
|
||||
th->t_action = A_FREEZE;
|
||||
gotone = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (gotone)
|
||||
msg("The monster(s) around you seem to have fallen asleep!");
|
||||
else
|
||||
msg(nothing);
|
||||
}
|
||||
when S_CREATE:
|
||||
/*
|
||||
* Create a monster
|
||||
* First look in a circle around him, next try his room
|
||||
* otherwise give up
|
||||
*/
|
||||
creat_mons(&player, (short) 0, TRUE);
|
||||
light(&hero);
|
||||
when S_IDENT:
|
||||
/*
|
||||
* if its blessed then identify everything in the pack
|
||||
*/
|
||||
if (blessed) {
|
||||
msg("You feel more Knowledgeable!");
|
||||
idenpack();
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Identify, let the rogue figure something out
|
||||
*/
|
||||
if (is_scroll && s_know[S_IDENT] != TRUE) {
|
||||
msg("This scroll is an identify scroll");
|
||||
}
|
||||
whatis((struct linked_list *)NULL);
|
||||
}
|
||||
if (is_scroll) s_know[S_IDENT] = TRUE;
|
||||
when S_MAP:
|
||||
/*
|
||||
* Scroll of magic mapping.
|
||||
*/
|
||||
if (blessed) {
|
||||
register int i;
|
||||
|
||||
if (is_scroll && s_know[S_MAP] != TRUE)
|
||||
s_know[S_MAP] = TRUE;
|
||||
/* light rooms */
|
||||
for (i=0; i<MAXROOMS; i++){
|
||||
rooms[i].r_flags &= ~ISDARK;
|
||||
}
|
||||
|
||||
msg("This scroll has a very detailed map on it! --More--");
|
||||
wait_for(' ');
|
||||
overwrite(stdscr, hw);
|
||||
overlay(stdscr, cw); /* wizard CTRL(F) */
|
||||
overlay(mw, cw); /* wizard CTRL(X) */
|
||||
draw(cw);
|
||||
goto map_jump; /* skip over regular mapping routine */
|
||||
}
|
||||
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 = mvwinch(hw, i, j))
|
||||
{
|
||||
case SECRETDOOR:
|
||||
nch = secretdoor (i, j);
|
||||
break;
|
||||
case HORZWALL:
|
||||
case VERTWALL:
|
||||
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);
|
||||
map_jump: /* blessed map jump from above */
|
||||
when S_GFIND:
|
||||
/*
|
||||
* Scroll of gold detection
|
||||
*/
|
||||
{
|
||||
int gtotal = 0;
|
||||
|
||||
if (is_scroll) s_know[S_GFIND] = TRUE;
|
||||
wclear(hw);
|
||||
for (nitem = lvl_obj; nitem != NULL; nitem = next(nitem)) {
|
||||
nobj = OBJPTR(nitem);
|
||||
if (nobj->o_type == GOLD) {
|
||||
gtotal += nobj->o_count;
|
||||
mvwaddch(hw, nobj->o_pos.y, nobj->o_pos.x, GOLD);
|
||||
}
|
||||
}
|
||||
for (nitem = mlist; nitem != NULL; nitem = next(nitem)) {
|
||||
register struct linked_list *gitem;
|
||||
register struct thing *th;
|
||||
|
||||
th = THINGPTR(nitem);
|
||||
if (on(*th, NODETECT)) continue;
|
||||
for(gitem = th->t_pack; gitem != NULL; gitem = next(gitem)){
|
||||
nobj = OBJPTR(gitem);
|
||||
if (nobj->o_type == GOLD) {
|
||||
gtotal += nobj->o_count;
|
||||
mvwaddch(hw, th->t_pos.y, th->t_pos.x, GOLD);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (gtotal) {
|
||||
rmmsg();
|
||||
overlay(hw,cw);
|
||||
draw(cw);
|
||||
msg("You begin to feel greedy. You sense gold!");
|
||||
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 * NLEVMONS) * LEVEL;
|
||||
/* if (turns > 42000) turns = 42000; limit turns */
|
||||
debug ("vlevel = %d turns = %d", vlevel, turns);
|
||||
|
||||
level = rnd(201)+80; /* cursed teleport range */
|
||||
|
||||
msg("You are banished to the lower regions! ");
|
||||
new_level(NORMLEV);
|
||||
|
||||
status(TRUE);
|
||||
mpos = 0;
|
||||
if (old_max == cur_max) { /* if he's been here make it harder */
|
||||
/* protect good charactors */
|
||||
if (player.t_ctype == C_PALADIN ||
|
||||
player.t_ctype == C_RANGER || player.t_ctype == C_MONK) {
|
||||
aggravate(TRUE, FALSE);
|
||||
}
|
||||
else {
|
||||
aggravate(TRUE, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (blessed) {
|
||||
int old_level,
|
||||
much = rnd(6) - 7;
|
||||
|
||||
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!");
|
||||
/* return; leaks item, go through end of function */
|
||||
}
|
||||
else if (blessed) {
|
||||
for (nitem = pack; nitem != NULL; nitem = next(nitem)) {
|
||||
nobj = OBJPTR(nitem);
|
||||
nobj->o_flags &= ~ISCURSED;
|
||||
}
|
||||
msg("Your pack glistens brightly!");
|
||||
do_panic(NULL); /* this startles them */
|
||||
/* return; leaks item, go through end of function */
|
||||
}
|
||||
else {
|
||||
nitem = get_item(pack, "remove the curse on",ALL,FALSE,FALSE);
|
||||
if (nitem != NULL) {
|
||||
nobj = OBJPTR(nitem);
|
||||
nobj->o_flags &= ~ISCURSED;
|
||||
msg("Removed the curse from %s",inv_name(nobj,TRUE));
|
||||
}
|
||||
}
|
||||
if (is_scroll) s_know[S_REMOVE] = TRUE;
|
||||
when S_PETRIFY:
|
||||
switch (mvinch(hero.y, hero.x)) {
|
||||
case WORMHOLE:
|
||||
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("The dizzy feeling leaves you.");
|
||||
}
|
||||
|
||||
/* Mark the player as in a wall */
|
||||
turn_on(player, ISINWALL);
|
||||
break;
|
||||
default:
|
||||
msg(nothing);
|
||||
}
|
||||
when S_GENOCIDE:
|
||||
msg("You have been granted the boon of genocide! --More--");
|
||||
wait_for(' ');
|
||||
msg("");
|
||||
genocide();
|
||||
if (is_scroll) s_know[S_GENOCIDE] = TRUE;
|
||||
when S_PROTECT: {
|
||||
struct linked_list *ll;
|
||||
struct object *lb;
|
||||
bool did_it = FALSE;
|
||||
msg("You are granted the power of protection.");
|
||||
if ((ll=get_item(pack,"protect",PROTECTABLE,FALSE,FALSE)) != NULL) {
|
||||
lb = OBJPTR(ll);
|
||||
mpos = 0;
|
||||
if (cursed) {
|
||||
switch(lb->o_type) { /* ruin it completely */
|
||||
case RING: if (lb->o_ac > 0) {
|
||||
if (is_current(lb)) {
|
||||
switch (lb->o_which) {
|
||||
case R_ADDWISDOM:
|
||||
pstats.s_wisdom -= lb->o_ac;
|
||||
when R_ADDINTEL:
|
||||
pstats.s_intel -= lb->o_ac;
|
||||
when R_ADDSTR:
|
||||
pstats.s_str -= lb->o_ac;
|
||||
when R_ADDHIT:
|
||||
pstats.s_dext -= lb->o_ac;
|
||||
}
|
||||
}
|
||||
did_it = TRUE;
|
||||
lb->o_ac = 0;
|
||||
}
|
||||
when ARMOR: if (lb->o_ac > 10) {
|
||||
did_it = TRUE;
|
||||
lb->o_ac = 10;
|
||||
}
|
||||
when STICK: if (lb->o_charges > 0) {
|
||||
did_it = TRUE;
|
||||
lb->o_charges = 0;
|
||||
}
|
||||
when WEAPON:if (lb->o_hplus > 0) {
|
||||
did_it = TRUE;
|
||||
lb->o_hplus = 0;
|
||||
}
|
||||
if (lb->o_dplus > 0) {
|
||||
did_it = TRUE;
|
||||
lb->o_dplus = 0;
|
||||
}
|
||||
}
|
||||
if (lb->o_flags & ISPROT) {
|
||||
did_it = TRUE;
|
||||
lb->o_flags &= ~ISPROT;
|
||||
}
|
||||
if (lb->o_flags & ISBLESSED) {
|
||||
did_it = TRUE;
|
||||
lb->o_flags &= ~ISBLESSED;
|
||||
}
|
||||
if (did_it)
|
||||
msg("Your %s glows red for a moment",inv_name(lb,TRUE));
|
||||
else {
|
||||
msg(nothing);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
lb->o_flags |= ISPROT;
|
||||
msg("Protected %s.",inv_name(lb,TRUE));
|
||||
}
|
||||
}
|
||||
if (is_scroll) s_know[S_PROTECT] = TRUE;
|
||||
}
|
||||
when S_MAKEIT:
|
||||
msg("You have been endowed with the power of creation!");
|
||||
if (is_scroll) s_know[S_MAKEIT] = TRUE;
|
||||
create_obj(TRUE, 0, 0);
|
||||
when S_ALLENCH: {
|
||||
struct linked_list *ll;
|
||||
struct object *lb;
|
||||
int howmuch, flags;
|
||||
if (is_scroll && s_know[S_ALLENCH] == FALSE) {
|
||||
msg("You are granted the power of enchantment.");
|
||||
msg("You may enchant anything (weapon, ring, armor, scroll, potion)");
|
||||
}
|
||||
if ((ll = get_item(pack, "enchant", ALL, FALSE, FALSE)) != NULL) {
|
||||
lb = OBJPTR(ll);
|
||||
lb->o_flags &= ~ISCURSED;
|
||||
if (blessed) {
|
||||
howmuch = 2;
|
||||
flags = ISBLESSED;
|
||||
}
|
||||
else if (cursed) {
|
||||
howmuch = -1;
|
||||
flags = ISCURSED;
|
||||
}
|
||||
else {
|
||||
howmuch = 1;
|
||||
flags = ISBLESSED;
|
||||
}
|
||||
switch(lb->o_type) {
|
||||
case RING:
|
||||
if (lb->o_ac + howmuch > MAXENCHANT) {
|
||||
msg("The enchantment doesn't seem to work!");
|
||||
break;
|
||||
}
|
||||
lb->o_ac += howmuch;
|
||||
if (lb==cur_ring[LEFT_1] || lb==cur_ring[LEFT_2] ||
|
||||
lb==cur_ring[LEFT_3] || lb==cur_ring[LEFT_4] ||
|
||||
lb==cur_ring[RIGHT_1] || lb==cur_ring[RIGHT_2] ||
|
||||
lb==cur_ring[RIGHT_3] || lb==cur_ring[RIGHT_4]) {
|
||||
switch (lb->o_which) {
|
||||
case R_ADDWISDOM: pstats.s_wisdom += howmuch;
|
||||
when R_ADDINTEL: pstats.s_intel += howmuch;
|
||||
when R_ADDSTR: pstats.s_str += howmuch;
|
||||
when R_ADDHIT: pstats.s_dext += howmuch;
|
||||
}
|
||||
}
|
||||
msg("Enchanted %s.",inv_name(lb,TRUE));
|
||||
when ARMOR:
|
||||
if ((armors[lb->o_which].a_class - lb->o_ac) +
|
||||
howmuch > MAXENCHANT) {
|
||||
msg("The enchantment doesn't seem to work!");
|
||||
break;
|
||||
}
|
||||
else
|
||||
lb->o_ac -= howmuch;
|
||||
msg("Enchanted %s.",inv_name(lb,TRUE));
|
||||
when STICK:
|
||||
lb->o_charges += rnd(16)+10;
|
||||
if (lb->o_charges < 0)
|
||||
lb->o_charges = 0;
|
||||
if (EQUAL(ws_type[lb->o_which], "staff")) {
|
||||
if (lb->o_charges > 200)
|
||||
lb->o_charges = 200;
|
||||
}
|
||||
else {
|
||||
if (lb->o_charges > 200) /* make em the same */
|
||||
lb->o_charges = 200;
|
||||
}
|
||||
msg("Enchanted %s.",inv_name(lb,TRUE));
|
||||
when WEAPON:
|
||||
if(lb->o_hplus+lb->o_dplus+howmuch > MAXENCHANT * 2){
|
||||
msg("The enchantment doesn't seem to work!");
|
||||
break;
|
||||
}
|
||||
if (rnd(100) < 50)
|
||||
lb->o_hplus += howmuch;
|
||||
else
|
||||
lb->o_dplus += howmuch;
|
||||
msg("Enchanted %s.",inv_name(lb,TRUE));
|
||||
when MM:
|
||||
switch (lb->o_which) {
|
||||
case MM_BRACERS:
|
||||
if (lb->o_ac + howmuch > MAXENCHANT) {
|
||||
msg("The enchantment doesn't seem to work!");
|
||||
break;
|
||||
}
|
||||
else lb->o_ac += howmuch;
|
||||
msg("Enchanted %s.",inv_name(lb,TRUE));
|
||||
when MM_PROTECT:
|
||||
if (lb->o_ac + howmuch > MAXENCHANT) {
|
||||
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 gotten here via prayer or Ankh, dock his wisdom. */
|
||||
if (!is_scroll) {
|
||||
pstats.s_wisdom--;
|
||||
if (pstats.s_wisdom < 3) pstats.s_wisdom = 3;
|
||||
msg("You feel a drain on your system. ");
|
||||
}
|
||||
}
|
||||
when S_FINDTRAPS:
|
||||
for (i=0; i<ntraps; i++) {
|
||||
if (!(traps[i].tr_flags & ISFOUND)) {
|
||||
traps[i].tr_flags |= ISFOUND;
|
||||
if (cansee(traps[i].tr_pos.y, traps[i].tr_pos.x))
|
||||
mvwaddch(cw,traps[i].tr_pos.y,traps[i].tr_pos.x,
|
||||
traps[i].tr_type);
|
||||
}
|
||||
}
|
||||
if (ntraps > 0) {
|
||||
msg("You sense the presence of traps.");
|
||||
if (is_scroll) s_know[S_FINDTRAPS] = TRUE;
|
||||
}
|
||||
else
|
||||
msg(nothing);
|
||||
|
||||
when S_RUNES:
|
||||
{
|
||||
register struct linked_list *sitem;
|
||||
|
||||
msg("The scroll explodes in a ball of fire!");
|
||||
if (on(player, NOFIRE)) {
|
||||
msg("The fire does not seem to affect you.");
|
||||
break;
|
||||
}
|
||||
explode(&player);
|
||||
if (pstats.s_hpt <= 0) {
|
||||
pstats.s_hpt = -1;
|
||||
death(D_SCROLL);
|
||||
}
|
||||
for (sitem = pack; sitem != NULL; sitem = nitem) {
|
||||
nitem = next(sitem); /* in case we delete it */
|
||||
nobj = OBJPTR(sitem);
|
||||
/*
|
||||
* check for loss of all scrolls and give them
|
||||
* a save versus fire
|
||||
*/
|
||||
if (nobj->o_type == SCROLL && roll(1,20) < 17) {
|
||||
msg("%s burns up!", inv_name(nobj, TRUE));
|
||||
inpack--;
|
||||
detach(pack, sitem);
|
||||
o_discard(sitem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when S_CHARM:
|
||||
{
|
||||
bool spots[9];
|
||||
int x, y, spot, count, numcharmed, something, bonus;
|
||||
struct linked_list *item;
|
||||
register struct thing *tp;
|
||||
|
||||
/* Initialize the places where we look around us */
|
||||
for (i=0; i<9; i++) spots[i] = FALSE;
|
||||
count = 0; /* No spots tried yet */
|
||||
numcharmed = 0; /* Nobody charmed yet */
|
||||
something = 0; /* Nothing has been seen yet */
|
||||
bonus = 0; /* no bonus yet */
|
||||
|
||||
/* Now look around us randomly for a charmee */
|
||||
while (count < 9) {
|
||||
do {
|
||||
spot = rnd(9);
|
||||
} while (spots[spot] == TRUE);
|
||||
|
||||
/* We found a place */
|
||||
count++;
|
||||
spots[spot] = TRUE;
|
||||
y = hero.y - 1 + (spot / 3);
|
||||
x = hero.x - 1 + (spot % 3);
|
||||
|
||||
/* Be sure to stay on the board! */
|
||||
if (x < 0 || x >= cols || (y < 1) || (y >= lines - 2))
|
||||
continue;
|
||||
|
||||
/* Is there a monster here? */
|
||||
if (!isalpha(mvwinch(mw, y, x))) continue;
|
||||
|
||||
/* What kind is it? */
|
||||
item = find_mons(y, x);
|
||||
if (item == NULL) continue;
|
||||
|
||||
tp = THINGPTR(item);
|
||||
if (on(*tp,ISCHARMED) || on(*tp,ISUNIQUE) || on(*tp,ISUNDEAD))
|
||||
continue;
|
||||
|
||||
/* Will the monster be charmed? */
|
||||
if (blessed) bonus -= 3;
|
||||
bonus -= (pstats.s_charisma - 12) / 3;
|
||||
if ((player.t_ctype==C_PALADIN || player.t_ctype==C_RANGER) &&
|
||||
off(*tp, ISMEAN))
|
||||
bonus -= 3;
|
||||
if (save(VS_MAGIC, tp, bonus)) continue;
|
||||
|
||||
/* We got him! */
|
||||
numcharmed++;
|
||||
|
||||
/* Let the player know (maybe) */
|
||||
if ((off(*tp, ISINVIS) || on(player, CANSEE)) &&
|
||||
(off(*tp, ISSHADOW) || on(player, CANSEE)) &&
|
||||
cansee(y, x)) {
|
||||
if (on(*tp, CANSURPRISE)) {
|
||||
turn_off(*tp, CANSURPRISE);
|
||||
msg("What the !? ");
|
||||
}
|
||||
msg("The eyes of %s glaze over!",
|
||||
prname(monster_name(tp), FALSE));
|
||||
something++;
|
||||
}
|
||||
|
||||
/* Charm him and turn off any side effects */
|
||||
turn_on(*tp, ISCHARMED);
|
||||
runto(tp, &hero);
|
||||
tp->t_action = A_NIL;
|
||||
|
||||
/* If monster was suffocating us, stop it */
|
||||
if (on(*tp, DIDSUFFOCATE)) {
|
||||
turn_off(*tp, DIDSUFFOCATE);
|
||||
extinguish(suffocate);
|
||||
}
|
||||
|
||||
/* If monster held us, stop it */
|
||||
if (on(*tp, DIDHOLD) && (--hold_count == 0))
|
||||
turn_off(player, ISHELD);
|
||||
turn_off(*tp, DIDHOLD);
|
||||
|
||||
/* If frightened of this monster, stop */
|
||||
if (on(player, ISFLEE) &&
|
||||
player.t_dest == &tp->t_pos) turn_off(player, ISFLEE);
|
||||
|
||||
if ((blessed && numcharmed >= 5) || numcharmed > 0) break;
|
||||
}
|
||||
|
||||
if (something == 0) msg(nothing);
|
||||
}
|
||||
|
||||
otherwise:
|
||||
msg("What a puzzling scroll!");
|
||||
if (item != NULL) o_discard(item);
|
||||
return;
|
||||
}
|
||||
look(TRUE, FALSE); /* put the result of the scroll on the screen */
|
||||
status(FALSE);
|
||||
if (is_scroll && item && s_know[which] && s_guess[which])
|
||||
{
|
||||
free(s_guess[which]);
|
||||
s_guess[which] = NULL;
|
||||
}
|
||||
else if (is_scroll &&
|
||||
!s_know[which] &&
|
||||
item &&
|
||||
askme &&
|
||||
(obj->o_flags & ISKNOW) == 0 &&
|
||||
(obj->o_flags & ISPOST) == 0 &&
|
||||
s_guess[which] == NULL) {
|
||||
nameitem(item, FALSE);
|
||||
}
|
||||
if (item != NULL) o_discard(item);
|
||||
updpack(TRUE, &player);
|
||||
}
|
||||
|
||||
3366
xrogue/state.c
Normal file
3366
xrogue/state.c
Normal file
File diff suppressed because it is too large
Load diff
896
xrogue/sticks.c
Normal file
896
xrogue/sticks.c
Normal file
|
|
@ -0,0 +1,896 @@
|
|||
/*
|
||||
sticks.c - Functions to implement the various sticks one might find
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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"
|
||||
|
||||
/*
|
||||
* zap a stick and see what happens
|
||||
*/
|
||||
|
||||
do_zap(zapper, obj, direction, which, flags)
|
||||
struct thing *zapper;
|
||||
struct object *obj;
|
||||
coord *direction;
|
||||
int which;
|
||||
int flags;
|
||||
{
|
||||
register struct linked_list *item = NULL;
|
||||
register struct thing *tp;
|
||||
register int y = 0, x = 0, bonus;
|
||||
struct linked_list *nitem;
|
||||
struct object *nobj;
|
||||
bool cursed, blessed, is_player = FALSE;
|
||||
char *mname = NULL;
|
||||
|
||||
cursed = flags & ISCURSED;
|
||||
blessed = flags & ISBLESSED;
|
||||
|
||||
if (obj && obj->o_type != RELIC) { /* all relics are chargeless */
|
||||
if (obj->o_charges < 1) {
|
||||
msg(nothing);
|
||||
return;
|
||||
}
|
||||
obj->o_charges--;
|
||||
}
|
||||
if (which == WS_WONDER) {
|
||||
switch (rnd(19)) {
|
||||
case 0: which = WS_ELECT;
|
||||
when 1: which = WS_FIRE;
|
||||
when 2: which = WS_COLD;
|
||||
when 3: which = WS_POLYMORPH;
|
||||
when 4: which = WS_MISSILE;
|
||||
when 5: which = WS_SLOW_M;
|
||||
when 6: which = WS_TELMON;
|
||||
when 7: which = WS_CANCEL;
|
||||
when 8: which = WS_CONFMON;
|
||||
when 9: which = WS_DISINTEGRATE;
|
||||
when 10: which = WS_PETRIFY;
|
||||
when 11: which = WS_PARALYZE;
|
||||
when 12: which = WS_MDEG;
|
||||
when 13: which = WS_FEAR;
|
||||
when 14: which = WS_CURING;
|
||||
when 15: which = WS_LIGHT;
|
||||
when 16: which = WS_HIT;
|
||||
when 17: which = WS_DRAIN;
|
||||
when 18: which = WS_CHARGE;
|
||||
}
|
||||
if(ws_magic[which].mi_curse>0 && rnd(100)<=ws_magic[which].mi_curse){
|
||||
cursed = TRUE;
|
||||
blessed = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
tp = NULL;
|
||||
switch (which) {
|
||||
case WS_POLYMORPH:
|
||||
case WS_SLOW_M:
|
||||
case WS_TELMON:
|
||||
case WS_CANCEL:
|
||||
case WS_CONFMON:
|
||||
case WS_DISINTEGRATE:
|
||||
case WS_PETRIFY:
|
||||
case WS_PARALYZE:
|
||||
case WS_MDEG:
|
||||
case WS_FEAR:
|
||||
y = zapper->t_pos.y;
|
||||
x = zapper->t_pos.x;
|
||||
|
||||
do {
|
||||
y += direction->y;
|
||||
x += direction->x;
|
||||
}
|
||||
while (shoot_ok(winat(y, x)) && !(y == hero.y && x == hero.x));
|
||||
|
||||
if (y == hero.y && x == hero.x)
|
||||
is_player = TRUE;
|
||||
else if (isalpha(mvwinch(mw, y, x))) {
|
||||
item = find_mons(y, x);
|
||||
tp = THINGPTR(item);
|
||||
runto(tp, &hero);
|
||||
turn_off(*tp, CANSURPRISE);
|
||||
mname = monster_name(tp);
|
||||
is_player = FALSE;
|
||||
|
||||
/* The monster may not like being shot at */
|
||||
if ((zapper == &player) &&
|
||||
on(*tp, ISCHARMED) &&
|
||||
save(VS_MAGIC, tp, 0)) {
|
||||
msg("The eyes of %s turn clear.", prname(mname, FALSE));
|
||||
turn_off(*tp, ISCHARMED);
|
||||
mname = monster_name(tp);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* if monster misses player because the player dodged then lessen
|
||||
* the chances he will use the wand again since the player appears
|
||||
* to be rather dextrous
|
||||
*/
|
||||
if (zapper != &player)
|
||||
zapper->t_wand = zapper->t_wand * 3 / 5;
|
||||
}
|
||||
}
|
||||
switch (which) {
|
||||
case WS_LIGHT:
|
||||
/*
|
||||
* Reddy Kilowat wand. Light up the room
|
||||
*/
|
||||
blue_light(blessed, cursed);
|
||||
when WS_DRAIN:
|
||||
/*
|
||||
* Take away 1/2 of hero's hit points, then take it away
|
||||
* evenly from the monsters in the room or next to hero
|
||||
* if he is in a passage (but leave the monsters alone
|
||||
* if the stick is cursed)
|
||||
*/
|
||||
if (pstats.s_hpt < 2) {
|
||||
msg("You are too weak to use it.");
|
||||
}
|
||||
else if (cursed)
|
||||
pstats.s_hpt /= 2;
|
||||
if (pstats.s_hpt <= 0) {
|
||||
pstats.s_hpt = -1;
|
||||
msg("You drain your own life away. --More--");
|
||||
death(D_STRENGTH);
|
||||
}
|
||||
else
|
||||
drain(hero.y-1, hero.y+1, hero.x-1, hero.x+1);
|
||||
|
||||
when WS_POLYMORPH:
|
||||
{
|
||||
register char oldch;
|
||||
register struct room *rp;
|
||||
register struct linked_list *pitem;
|
||||
coord delta;
|
||||
|
||||
if (tp == NULL)
|
||||
break;
|
||||
if (save(VS_MAGIC, tp, 0)) {
|
||||
msg(nothing);
|
||||
break;
|
||||
}
|
||||
rp = roomin(&tp->t_pos);
|
||||
check_residue(tp);
|
||||
delta.x = x;
|
||||
delta.y = y;
|
||||
detach(mlist, item);
|
||||
oldch = tp->t_oldch;
|
||||
pitem = tp->t_pack; /* save his pack */
|
||||
tp->t_pack = NULL;
|
||||
|
||||
if (levtype == OUTSIDE)
|
||||
new_monster(item,rnd(NUMDINOS)+NUMMONST-NUMDINOS,&delta,FALSE);
|
||||
else
|
||||
new_monster(item,rnd(NUMMONST-NUMUNIQUE-NUMDINOS-1)+1,&delta,FALSE);
|
||||
|
||||
if (tp->t_pack != NULL)
|
||||
o_free_list (tp->t_pack);
|
||||
tp->t_pack = pitem;
|
||||
if (isalpha(mvwinch(cw, y, x)))
|
||||
mvwaddch(cw, y, x, tp->t_type);
|
||||
tp->t_oldch = oldch;
|
||||
/*
|
||||
* should the room light up?
|
||||
*/
|
||||
if (on(*tp, HASFIRE)) {
|
||||
if (rp) {
|
||||
register struct linked_list *fire_item;
|
||||
|
||||
fire_item = creat_item();
|
||||
ldata(fire_item) = (char *) tp;
|
||||
attach(rp->r_fires, fire_item);
|
||||
rp->r_flags |= HASFIRE;
|
||||
if (cansee(tp->t_pos.y,tp->t_pos.x) &&
|
||||
next(rp->r_fires) == NULL) light(&hero);
|
||||
}
|
||||
}
|
||||
runto(tp, &hero);
|
||||
msg(terse ? "A new %s!"
|
||||
: "You have created a new %s!",
|
||||
monster_name(tp));
|
||||
}
|
||||
|
||||
when WS_PETRIFY:
|
||||
if (tp == NULL)
|
||||
break;
|
||||
if (save(VS_MAGIC, tp, 0)) {
|
||||
msg(nothing);
|
||||
break;
|
||||
}
|
||||
check_residue(tp);
|
||||
turn_on(*tp, ISSTONE);
|
||||
turn_on(*tp, NOSTONE);
|
||||
turn_off(*tp, ISRUN);
|
||||
turn_off(*tp, ISINVIS);
|
||||
turn_off(*tp, CANSURPRISE);
|
||||
turn_off(*tp, ISDISGUISE);
|
||||
tp->t_action = A_NIL;
|
||||
tp->t_no_move = 0;
|
||||
msg("%s is turned to stone!",prname(mname, TRUE));
|
||||
|
||||
when WS_TELMON:
|
||||
{
|
||||
register int rm;
|
||||
register struct room *rp;
|
||||
|
||||
if (tp == NULL)
|
||||
break;
|
||||
if (save(VS_MAGIC, tp, 0)) {
|
||||
msg(nothing);
|
||||
break;
|
||||
}
|
||||
rp = NULL;
|
||||
check_residue(tp);
|
||||
tp->t_action = A_FREEZE; /* creature is disoriented */
|
||||
tp->t_no_move = 2;
|
||||
if (cursed) { /* Teleport monster to player */
|
||||
if ((y == (hero.y + direction->y)) &&
|
||||
(x == (hero.x + direction->x)))
|
||||
msg(nothing);
|
||||
else {
|
||||
tp->t_pos.y = hero.y + direction->y;
|
||||
tp->t_pos.x = hero.x + direction->x;
|
||||
}
|
||||
}
|
||||
else if (blessed) { /* Get rid of monster */
|
||||
killed(item, FALSE, TRUE, TRUE);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
register int i=0;
|
||||
|
||||
do { /* Move monster to another room */
|
||||
rm = rnd_room();
|
||||
rnd_pos(&rooms[rm], &tp->t_pos);
|
||||
}until(winat(tp->t_pos.y,tp->t_pos.x)==FLOOR ||i++>500);
|
||||
rp = &rooms[rm];
|
||||
}
|
||||
|
||||
/* Now move the monster */
|
||||
if (isalpha(mvwinch(cw, y, x)))
|
||||
mvwaddch(cw, y, x, tp->t_oldch);
|
||||
mvwaddch(mw, y, x, ' ');
|
||||
mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, tp->t_type);
|
||||
if (tp->t_pos.y != y || tp->t_pos.x != x)
|
||||
tp->t_oldch = mvwinch(cw, tp->t_pos.y, tp->t_pos.x);
|
||||
/*
|
||||
* check to see if room that creature appears in should
|
||||
* light up
|
||||
*/
|
||||
if (on(*tp, HASFIRE)) {
|
||||
if (rp) {
|
||||
register struct linked_list *fire_item;
|
||||
|
||||
fire_item = creat_item();
|
||||
ldata(fire_item) = (char *) tp;
|
||||
attach(rp->r_fires, fire_item);
|
||||
rp->r_flags |= HASFIRE;
|
||||
if(cansee(tp->t_pos.y, tp->t_pos.x) &&
|
||||
next(rp->r_fires) == NULL)
|
||||
light(&hero);
|
||||
}
|
||||
}
|
||||
}
|
||||
when WS_CANCEL:
|
||||
if (tp == NULL)
|
||||
break;
|
||||
if (save(VS_MAGIC, tp, 0)) {
|
||||
msg(nothing);
|
||||
break;
|
||||
}
|
||||
check_residue(tp);
|
||||
tp->t_flags[0] &= CANC0MASK;
|
||||
tp->t_flags[1] &= CANC1MASK;
|
||||
tp->t_flags[2] &= CANC2MASK;
|
||||
tp->t_flags[3] &= CANC3MASK;
|
||||
tp->t_flags[4] &= CANC4MASK;
|
||||
tp->t_flags[5] &= CANC5MASK;
|
||||
tp->t_flags[6] &= CANC6MASK;
|
||||
tp->t_flags[7] &= CANC7MASK;
|
||||
tp->t_flags[8] &= CANC8MASK;
|
||||
tp->t_flags[9] &= CANC9MASK;
|
||||
tp->t_flags[10] &= CANCAMASK;
|
||||
tp->t_flags[11] &= CANCBMASK;
|
||||
tp->t_flags[12] &= CANCCMASK;
|
||||
tp->t_flags[13] &= CANCDMASK;
|
||||
tp->t_flags[14] &= CANCEMASK;
|
||||
tp->t_flags[15] &= CANCFMASK;
|
||||
|
||||
when WS_MISSILE:
|
||||
{
|
||||
int dice;
|
||||
static struct object bolt =
|
||||
{
|
||||
MISSILE , {0, 0}, 0, "", "1d4 " , NULL, 0, WS_MISSILE, 50, 1
|
||||
};
|
||||
|
||||
if (!obj)
|
||||
dice = zapper->t_stats.s_lvl;
|
||||
if (obj->o_type == RELIC)
|
||||
dice = 15;
|
||||
else if (EQUAL(ws_type[which], "staff"))
|
||||
dice = 10;
|
||||
else
|
||||
dice = 6;
|
||||
sprintf(bolt.o_hurldmg, "%dd4", dice);
|
||||
do_motion(&bolt, direction->y, direction->x, zapper);
|
||||
if (!hit_monster(unc(bolt.o_pos), &bolt, zapper))
|
||||
msg("The missile vanishes with a puff of smoke");
|
||||
}
|
||||
when WS_HIT:
|
||||
{
|
||||
register unsigned char ch;
|
||||
struct object strike; /* don't want to change sticks attributes */
|
||||
|
||||
direction->y += hero.y;
|
||||
direction->x += hero.x;
|
||||
ch = winat(direction->y, direction->x);
|
||||
if (isalpha(ch))
|
||||
{
|
||||
strike = *obj;
|
||||
strike.o_hplus = 7;
|
||||
if (EQUAL(ws_type[which], "staff"))
|
||||
strcpy(strike.o_damage,"3d8");
|
||||
else
|
||||
strcpy(strike.o_damage,"2d8");
|
||||
fight(direction, &strike, FALSE);
|
||||
}
|
||||
}
|
||||
when WS_SLOW_M:
|
||||
if (is_player) {
|
||||
add_slow();
|
||||
break;
|
||||
}
|
||||
if (tp == NULL)
|
||||
break;
|
||||
if (cursed) {
|
||||
if (on(*tp, ISSLOW))
|
||||
turn_off(*tp, ISSLOW);
|
||||
else
|
||||
turn_on(*tp, ISHASTE);
|
||||
break;
|
||||
}
|
||||
if ((on(*tp,ISUNIQUE) && save(VS_MAGIC,tp,0)) || on(*tp,NOSLOW)) {
|
||||
msg(nothing);
|
||||
break;
|
||||
}
|
||||
else if (blessed) {
|
||||
turn_off(*tp, ISRUN);
|
||||
turn_on(*tp, ISHELD);
|
||||
}
|
||||
/*
|
||||
* always slow in case he breaks free of HOLD
|
||||
*/
|
||||
if (on(*tp, ISHASTE))
|
||||
turn_off(*tp, ISHASTE);
|
||||
else
|
||||
turn_on(*tp, ISSLOW);
|
||||
|
||||
when WS_CHARGE:
|
||||
if (ws_know[WS_CHARGE] != TRUE && obj)
|
||||
msg("This is a wand of charging.");
|
||||
nitem = get_item(pack, "charge", STICK, FALSE, FALSE);
|
||||
if (nitem != NULL) {
|
||||
nobj = OBJPTR(nitem);
|
||||
if ((++(nobj->o_charges) == 1) && (nobj->o_which == WS_HIT))
|
||||
fix_stick(nobj);
|
||||
if (blessed) ++(nobj->o_charges);
|
||||
if (EQUAL(ws_type[nobj->o_which], "staff")) {
|
||||
if (nobj->o_charges > 200)
|
||||
nobj->o_charges = 200;
|
||||
}
|
||||
else {
|
||||
if (nobj->o_charges > 200)
|
||||
nobj->o_charges = 200;
|
||||
}
|
||||
}
|
||||
when WS_ELECT:
|
||||
shoot_bolt( zapper, zapper->t_pos, *direction, TRUE, D_BOLT,
|
||||
"lightning bolt", roll(zapper->t_stats.s_lvl,6));
|
||||
|
||||
when WS_FIRE:
|
||||
shoot_bolt( zapper, zapper->t_pos, *direction, TRUE, D_BOLT,
|
||||
"flame", roll(zapper->t_stats.s_lvl,6));
|
||||
|
||||
when WS_COLD:
|
||||
shoot_bolt( zapper, zapper->t_pos, *direction, TRUE, D_BOLT,
|
||||
"ice", roll(zapper->t_stats.s_lvl,6));
|
||||
|
||||
when WS_CONFMON:
|
||||
if (cursed || is_player) {
|
||||
if (!save(VS_WAND, &player, 0)) {
|
||||
dsrpt_player();
|
||||
confus_player();
|
||||
}
|
||||
else {
|
||||
if (zapper != &player) zapper->t_wand /= 2;
|
||||
msg(nothing);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (tp == NULL)
|
||||
break;
|
||||
if (save(VS_MAGIC, tp, 0) || on(*tp, ISCLEAR))
|
||||
msg(nothing);
|
||||
else
|
||||
turn_on (*tp, ISHUH);
|
||||
}
|
||||
when WS_PARALYZE:
|
||||
if (is_player || cursed) {
|
||||
if ((obj && obj->o_type==RELIC) || !save(VS_WAND, &player, 0)){
|
||||
player.t_no_move += 2 * movement(&player) * FREEZETIME;
|
||||
player.t_action = A_FREEZE;
|
||||
msg("You can't move.");
|
||||
}
|
||||
else {
|
||||
if (zapper != &player) zapper->t_wand /= 2;
|
||||
msg(nothing);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (tp == NULL)
|
||||
break;
|
||||
bonus = 0;
|
||||
if (blessed) bonus = -3;
|
||||
if (((obj && obj->o_type==RELIC) || !save(VS_WAND,tp,bonus)) &&
|
||||
off(*tp, NOPARALYZE)) {
|
||||
tp->t_no_move += 2 * movement(tp) * FREEZETIME;
|
||||
tp->t_action = A_FREEZE;
|
||||
}
|
||||
else {
|
||||
msg(nothing);
|
||||
}
|
||||
}
|
||||
when WS_FEAR:
|
||||
if (is_player) {
|
||||
if (!on(player, ISFLEE) ||
|
||||
ISWEARING(R_HEROISM) ||
|
||||
save(VS_WAND, &player, 0)) {
|
||||
msg(nothing);
|
||||
zapper->t_wand /= 2;
|
||||
}
|
||||
else {
|
||||
turn_on(player, ISFLEE);
|
||||
player.t_dest = &zapper->t_pos;
|
||||
msg("The sight of %s terrifies you.", prname(mname, FALSE));
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (tp == NULL)
|
||||
break;
|
||||
bonus = 0;
|
||||
if (blessed) bonus = -3;
|
||||
if(save(VS_WAND, tp,bonus) || on(*tp,ISUNDEAD) || on(*tp,NOFEAR)){
|
||||
msg(nothing);
|
||||
break;
|
||||
}
|
||||
turn_on(*tp, ISFLEE);
|
||||
turn_on(*tp, WASTURNED);
|
||||
|
||||
/* Stop it from attacking us */
|
||||
dsrpt_monster(tp, TRUE, cansee(tp->t_pos.y, tp->t_pos.x));
|
||||
|
||||
/* If monster was suffocating, stop it */
|
||||
if (on(*tp, DIDSUFFOCATE)) {
|
||||
turn_off(*tp, DIDSUFFOCATE);
|
||||
extinguish(suffocate);
|
||||
}
|
||||
|
||||
/* If monster held us, stop it */
|
||||
if (on(*tp, DIDHOLD) && (--hold_count == 0))
|
||||
turn_off(player, ISHELD);
|
||||
turn_off(*tp, DIDHOLD);
|
||||
|
||||
/* It is okay to turn tail */
|
||||
tp->t_oldpos = tp->t_pos;
|
||||
|
||||
when WS_MDEG:
|
||||
if (is_player) {
|
||||
if (save(VS_WAND, &player, 0)) {
|
||||
msg (nothing);
|
||||
zapper->t_wand /= 2;
|
||||
break;
|
||||
}
|
||||
pstats.s_hpt /= 2;
|
||||
if (pstats.s_hpt <= 0) {
|
||||
pstats.s_hpt = -1;
|
||||
msg("Your life has been sucked out from you! --More--");
|
||||
wait_for(' ');
|
||||
death(zapper);
|
||||
}
|
||||
else
|
||||
msg("You feel a great drain on your system.");
|
||||
}
|
||||
if (tp == NULL)
|
||||
break;
|
||||
if (cursed) {
|
||||
tp->t_stats.s_hpt *= 2;
|
||||
msg("%s appears to be stronger now!", prname(mname, TRUE));
|
||||
}
|
||||
else if (on(*tp, ISUNIQUE) && save(VS_WAND, tp, 0))
|
||||
msg (nothing);
|
||||
else {
|
||||
tp->t_stats.s_hpt /= 2;
|
||||
msg("%s appears to be weaker now", prname(mname, TRUE));
|
||||
}
|
||||
if (tp->t_stats.s_hpt < 1)
|
||||
killed(item, TRUE, TRUE, TRUE);
|
||||
when WS_DISINTEGRATE:
|
||||
if (tp == NULL)
|
||||
break;
|
||||
if (cursed) {
|
||||
register int m1, m2;
|
||||
coord mp;
|
||||
struct linked_list *titem;
|
||||
char ch;
|
||||
struct thing *th;
|
||||
|
||||
if (on(*tp, ISUNIQUE) || on(*tp, CANSELL)) {
|
||||
msg (nothing);
|
||||
break;
|
||||
}
|
||||
for (m1=tp->t_pos.x-1 ; m1 <= tp->t_pos.x+1 ; m1++) {
|
||||
for(m2=tp->t_pos.y-1 ; m2<=tp->t_pos.y+1 ; m2++) {
|
||||
if (m1 == hero.x && m2 == hero.y)
|
||||
continue;
|
||||
ch = winat(m2,m1);
|
||||
if (shoot_ok(ch)) {
|
||||
mp.x = m1; /* create it */
|
||||
mp.y = m2;
|
||||
titem = new_item(sizeof(struct thing));
|
||||
new_monster(titem,(short)tp->t_index,&mp,FALSE);
|
||||
th = THINGPTR(titem);
|
||||
turn_on (*th, ISMEAN);
|
||||
runto(th,&hero);
|
||||
if (on(*th, HASFIRE)) {
|
||||
register struct room *rp;
|
||||
|
||||
rp = roomin(&th->t_pos);
|
||||
if (rp) {
|
||||
register struct linked_list *fire_item;
|
||||
|
||||
fire_item = creat_item();
|
||||
ldata(fire_item) = (char *) th;
|
||||
attach(rp->r_fires, fire_item);
|
||||
rp->r_flags |= HASFIRE;
|
||||
if (cansee(th->t_pos.y, th->t_pos.x) &&
|
||||
next(rp->r_fires) == NULL)
|
||||
light(&hero);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else { /* if its a UNIQUE it might still live */
|
||||
if (on(*tp, ISUNIQUE) && save(VS_MAGIC, tp, 0)) {
|
||||
tp->t_stats.s_hpt /= 2;
|
||||
if (tp->t_stats.s_hpt < 1) {
|
||||
killed(item, FALSE, TRUE, TRUE);
|
||||
msg("You have disintegrated %s", prname(mname, FALSE));
|
||||
}
|
||||
else {
|
||||
msg("%s appears wounded", prname(mname, TRUE));
|
||||
}
|
||||
}
|
||||
else {
|
||||
msg("You have disintegrated %s", prname(mname, FALSE));
|
||||
killed (item, FALSE, TRUE, TRUE);
|
||||
}
|
||||
}
|
||||
when WS_CURING:
|
||||
if (cursed) {
|
||||
bool sick = FALSE;
|
||||
if (!save(VS_POISON, &player, 0)) {
|
||||
msg("You feel extremely sick. ");
|
||||
sick = TRUE;
|
||||
pstats.s_hpt -= (pstats.s_hpt/3)+1;
|
||||
if (pstats.s_hpt == 0) {
|
||||
pstats.s_hpt = -1;
|
||||
msg("You die! --More--");
|
||||
wait_for(' ');
|
||||
death (D_POISON);
|
||||
}
|
||||
}
|
||||
if (!save(VS_WAND, &player, 0) && !ISWEARING(R_HEALTH)) {
|
||||
turn_on(player, HASDISEASE);
|
||||
turn_on(player, HASINFEST);
|
||||
turn_on(player, DOROT);
|
||||
fuse(cure_disease, (VOID *)NULL, roll(HEALTIME,SICKTIME), AFTER);
|
||||
infest_dam++;
|
||||
}
|
||||
else if (sick == FALSE) msg("You feel momentarily sick");
|
||||
}
|
||||
else {
|
||||
if (on(player, HASDISEASE) || on(player, HASINFEST)) {
|
||||
extinguish(cure_disease);
|
||||
turn_off(player, HASINFEST);
|
||||
infest_dam = 0;
|
||||
cure_disease(); /* this prints message */
|
||||
}
|
||||
if (on(player, DOROT)) {
|
||||
msg("You feel your skin returning to normal.");
|
||||
turn_off(player, DOROT);
|
||||
}
|
||||
pstats.s_hpt += roll(pstats.s_lvl, blessed ? 9 : 6);
|
||||
if (pstats.s_hpt > max_stats.s_hpt)
|
||||
pstats.s_hpt = max_stats.s_hpt;
|
||||
msg("You begin to feel %sbetter.", blessed ? "much " : "");
|
||||
|
||||
}
|
||||
otherwise:
|
||||
msg("What a bizarre schtick!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* drain:
|
||||
* Do drain hit points from player shtick
|
||||
*/
|
||||
|
||||
drain(ymin, ymax, xmin, xmax)
|
||||
int ymin, ymax, xmin, xmax;
|
||||
{
|
||||
register int i, j, count;
|
||||
register struct thing *ick;
|
||||
register struct linked_list *item;
|
||||
|
||||
/*
|
||||
* First count how many things we need to spread the hit points among
|
||||
*/
|
||||
count = 0;
|
||||
for (i = ymin; i <= ymax; i++) {
|
||||
if (i < 1 || i > lines - 3)
|
||||
continue;
|
||||
for (j = xmin; j <= xmax; j++) {
|
||||
if (j < 0 || j > cols - 1)
|
||||
continue;
|
||||
if (isalpha(mvwinch(mw, i, j)))
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count == 0)
|
||||
{
|
||||
msg("You have a tingling feeling.");
|
||||
return;
|
||||
}
|
||||
count = pstats.s_hpt / count;
|
||||
pstats.s_hpt /= 2;
|
||||
if (pstats.s_hpt <= 0) {
|
||||
pstats.s_hpt = -1;
|
||||
msg("Aarrgghhh!! --More--");
|
||||
wait_for(' ');
|
||||
death(D_STRENGTH);
|
||||
}
|
||||
/*
|
||||
* Now zot all of the monsters
|
||||
*/
|
||||
for (i = ymin; i <= ymax; i++) {
|
||||
if (i < 1 || i > lines - 3)
|
||||
continue;
|
||||
for (j = xmin; j <= xmax; j++) {
|
||||
if (j < 0 || j > cols - 1)
|
||||
continue;
|
||||
if (isalpha(mvwinch(mw, i, j)) &&
|
||||
((item = find_mons(i, j)) != NULL)) {
|
||||
ick = THINGPTR(item);
|
||||
if (on(*ick, ISUNIQUE) && save(VS_MAGIC, ick, 0))
|
||||
ick->t_stats.s_hpt -= count / 2;
|
||||
else
|
||||
ick->t_stats.s_hpt -= count;
|
||||
if (ick->t_stats.s_hpt < 1)
|
||||
killed(item,
|
||||
cansee(i,j)&&(!on(*ick,ISINVIS)||on(player,CANSEE)),
|
||||
TRUE, TRUE);
|
||||
else {
|
||||
runto(ick, &hero);
|
||||
|
||||
/*
|
||||
* The monster may not like being shot at. Since the
|
||||
* shot is not aimed directly at the monster, we will
|
||||
* give him a poorer save.
|
||||
*/
|
||||
if (on(*ick, ISCHARMED) && save(VS_MAGIC, ick, -2)) {
|
||||
msg("The eyes of %s turn clear.",
|
||||
prname(monster_name(ick), FALSE));
|
||||
turn_off(*ick, ISCHARMED);
|
||||
}
|
||||
if (cansee(i,j) && (!on(*ick,ISINVIS)||on(player,CANSEE)))
|
||||
msg("%s appears wounded",
|
||||
prname(monster_name(ick), TRUE));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* initialize a stick
|
||||
*/
|
||||
|
||||
fix_stick(cur)
|
||||
register struct object *cur;
|
||||
{
|
||||
if (EQUAL(ws_type[cur->o_which], "staff")) {
|
||||
cur->o_weight = 100;
|
||||
cur->o_charges = 5 + rnd(11);
|
||||
strcpy(cur->o_damage,"3d4");
|
||||
cur->o_hplus = 1;
|
||||
cur->o_dplus = 0;
|
||||
switch (cur->o_which) {
|
||||
case WS_HIT:
|
||||
cur->o_hplus = 3;
|
||||
cur->o_dplus = 3;
|
||||
strcpy(cur->o_damage,"2d8");
|
||||
when WS_LIGHT:
|
||||
cur->o_charges = 15 + rnd(11);
|
||||
}
|
||||
}
|
||||
else {
|
||||
strcpy(cur->o_damage,"2d3");
|
||||
cur->o_weight = 75;
|
||||
cur->o_hplus = 1;
|
||||
cur->o_dplus = 0;
|
||||
cur->o_charges = 5 + rnd(11);
|
||||
switch (cur->o_which) {
|
||||
case WS_HIT:
|
||||
cur->o_hplus = 3;
|
||||
cur->o_dplus = 3;
|
||||
strcpy(cur->o_damage,"2d8");
|
||||
when WS_LIGHT:
|
||||
cur->o_charges = 15 + rnd(11);
|
||||
}
|
||||
}
|
||||
strcpy(cur->o_hurldmg,"3d3");
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Use the wand that our monster is wielding.
|
||||
*/
|
||||
|
||||
m_use_wand(monster)
|
||||
register struct thing *monster;
|
||||
{
|
||||
register struct object *obj;
|
||||
|
||||
/* Make sure we really have it */
|
||||
if (monster->t_using)
|
||||
obj = OBJPTR(monster->t_using);
|
||||
else {
|
||||
debug("Stick not set!");
|
||||
monster->t_action = A_NIL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj->o_type != STICK) {
|
||||
debug("Stick not selected!");
|
||||
monster->t_action = A_NIL;
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* shoot the stick!
|
||||
* assume all blessed sticks are normal for now.
|
||||
* Note that we don't get here if the wand is cursed.
|
||||
*/
|
||||
msg("%s points a %s at you!", prname(monster_name(monster), TRUE),
|
||||
ws_type[obj->o_which]);
|
||||
do_zap(monster, obj, &monster->t_newpos, obj->o_which, NULL);
|
||||
monster->t_wand /= 2; /* chance lowers with each use */
|
||||
}
|
||||
|
||||
bool
|
||||
need_dir(type, which)
|
||||
int type, /* type of item, NULL means stick */
|
||||
which; /* which item */
|
||||
{
|
||||
if (type == STICK || type == 0) {
|
||||
switch (which) {
|
||||
case WS_LIGHT:
|
||||
case WS_DRAIN:
|
||||
case WS_CHARGE:
|
||||
case WS_CURING:
|
||||
return(FALSE);
|
||||
default:
|
||||
return(TRUE);
|
||||
}
|
||||
}
|
||||
else if (type == RELIC) {
|
||||
switch (which) {
|
||||
case MING_STAFF:
|
||||
case ASMO_ROD:
|
||||
case EMORI_CLOAK:
|
||||
return(TRUE);
|
||||
default:
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
return (FALSE); /* hope we don't get here */
|
||||
}
|
||||
|
||||
/*
|
||||
* let the player zap a stick and see what happens
|
||||
*/
|
||||
|
||||
player_zap(which, flag)
|
||||
int which;
|
||||
int flag;
|
||||
{
|
||||
register struct linked_list *item;
|
||||
register struct object *obj;
|
||||
|
||||
obj = NULL;
|
||||
if (which == 0) {
|
||||
/* This is a stick. It takes 2 movement periods to zap it */
|
||||
if (player.t_action != C_ZAP) {
|
||||
if ((item = get_item(pack,"zap with",ZAPPABLE,FALSE,FALSE)) == NULL)
|
||||
return(FALSE);
|
||||
|
||||
obj = OBJPTR(item);
|
||||
|
||||
if (need_dir(obj->o_type, obj->o_which)) {
|
||||
if (!get_dir(&player.t_newpos))
|
||||
return(FALSE);
|
||||
}
|
||||
player.t_using = item; /* Remember what it is */
|
||||
player.t_action = C_ZAP; /* We are quaffing */
|
||||
player.t_no_move = 2 * movement(&player);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
item = player.t_using;
|
||||
/* We've waited our time, let's shoot 'em up! */
|
||||
player.t_using = NULL;
|
||||
player.t_action = A_NIL;
|
||||
|
||||
obj = OBJPTR(item);
|
||||
|
||||
/* Handle relics specially here */
|
||||
if (obj->o_type == RELIC) {
|
||||
switch (obj->o_which) {
|
||||
case ORCUS_WAND:
|
||||
/* msg(nothing); */
|
||||
read_scroll(S_PETRIFY, NULL, FALSE);
|
||||
return(TRUE);
|
||||
when MING_STAFF:
|
||||
which = WS_MISSILE;
|
||||
when EMORI_CLOAK:
|
||||
which = WS_PARALYZE;
|
||||
obj->o_charges = 0; /* one zap/day (whatever that is) */
|
||||
fuse(cloak_charge, obj, CLOAK_TIME, AFTER);
|
||||
when ASMO_ROD:
|
||||
switch (rnd(3)) {
|
||||
case 0: which = WS_ELECT;
|
||||
when 1: which = WS_COLD;
|
||||
otherwise: which = WS_FIRE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
which = obj->o_which;
|
||||
ws_know[which] = TRUE;
|
||||
flag = obj->o_flags;
|
||||
}
|
||||
}
|
||||
do_zap(&player, obj, &player.t_newpos, which, flag);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
951
xrogue/things.c
Normal file
951
xrogue/things.c
Normal file
|
|
@ -0,0 +1,951 @@
|
|||
/*
|
||||
things.c - functions for dealing with things like potions and scrolls
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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, "named %s", s_guess[obj->o_which]);
|
||||
else
|
||||
sprintf(pb, "titled '%s'", s_names[obj->o_which]);
|
||||
when POTION:
|
||||
if (obj->o_count == 1)
|
||||
sprintf(pb, "A %spotion ", blesscurse(obj->o_flags));
|
||||
else
|
||||
sprintf(pb, "%d %spotions ",
|
||||
obj->o_count, blesscurse(obj->o_flags));
|
||||
pb = &pb[strlen(pb)];
|
||||
if (p_know[obj->o_which])
|
||||
sprintf(pb, "of %s (%s)", p_magic[obj->o_which].mi_name,
|
||||
p_kind(obj));
|
||||
else if (obj->o_flags & ISPOST)
|
||||
sprintf(pb, "of %s", p_magic[obj->o_which].mi_name);
|
||||
else if (p_guess[obj->o_which])
|
||||
sprintf(pb, "named %s (%s)", p_guess[obj->o_which],
|
||||
p_colors[obj->o_which]);
|
||||
else {
|
||||
pb = prbuf;
|
||||
if (obj->o_count == 1)
|
||||
sprintf(pb, "A%s %s potion",
|
||||
vowelstr(p_colors[obj->o_which]),
|
||||
p_colors[obj->o_which]);
|
||||
else
|
||||
sprintf(pb, "%d %s potions",
|
||||
obj->o_count, p_colors[obj->o_which]);
|
||||
}
|
||||
when FOOD:
|
||||
if (obj->o_count == 1)
|
||||
sprintf(pb, "A%s %s", vowelstr(foods[obj->o_which].mi_name),
|
||||
foods[obj->o_which].mi_name);
|
||||
else
|
||||
sprintf(pb, "%d %ss", obj->o_count,foods[obj->o_which].mi_name);
|
||||
when WEAPON:
|
||||
if (obj->o_count > 1)
|
||||
sprintf(pb, "%d ", obj->o_count);
|
||||
else
|
||||
strcpy(pb, "A ");
|
||||
pb = &pb[strlen(pb)];
|
||||
if (obj->o_flags & ISKNOW) {
|
||||
strcat(pb, num(obj->o_hplus, obj->o_dplus));
|
||||
strcat (pb, " ");
|
||||
}
|
||||
strcat(pb, weaps[obj->o_which].w_name);
|
||||
if (obj->o_count > 1)
|
||||
strcat(pb, "s");
|
||||
if (obj == cur_weapon)
|
||||
strcat(pb, " (weapon in hand)");
|
||||
if (obj->o_flags & ISPOISON)
|
||||
strcat(pb, " {Poisoned}");
|
||||
when ARMOR:
|
||||
if (obj->o_flags & ISKNOW) {
|
||||
strcat(pb, num(armors[obj->o_which].a_class - obj->o_ac, 0));
|
||||
strcat(pb, " ");
|
||||
}
|
||||
strcat(pb, armors[obj->o_which].a_name);
|
||||
if (obj == cur_armor)
|
||||
strcat(pb, " (being worn)");
|
||||
when STICK:
|
||||
sprintf(pb, "A %s%s ",
|
||||
blesscurse(obj->o_flags), ws_type[obj->o_which]);
|
||||
pb = &pb[strlen(pb)];
|
||||
if (ws_know[obj->o_which] || obj->o_flags & ISKNOW)
|
||||
sprintf(pb, "of %s%s (%s)", ws_magic[obj->o_which].mi_name,
|
||||
charge_str(obj), ws_made[obj->o_which]);
|
||||
else if (obj->o_flags & ISPOST)
|
||||
sprintf(pb, "of %s", ws_magic[obj->o_which].mi_name);
|
||||
else if (ws_guess[obj->o_which])
|
||||
sprintf(pb, "named %s (%s)", ws_guess[obj->o_which],
|
||||
ws_made[obj->o_which]);
|
||||
else {
|
||||
pb = prbuf;
|
||||
sprintf(pb, "A %s %s", ws_made[obj->o_which],
|
||||
ws_type[obj->o_which]);
|
||||
}
|
||||
if (obj == cur_weapon)
|
||||
strcat(prbuf, " (weapon in hand)");
|
||||
when RING:
|
||||
if (r_know[obj->o_which] || obj->o_flags & ISKNOW)
|
||||
sprintf(pb, "A%s ring of %s (%s)", ring_num(obj),
|
||||
r_magic[obj->o_which].mi_name, r_stones[obj->o_which]);
|
||||
else if (obj->o_flags & ISPOST)
|
||||
sprintf(pb, "A ring of %s", r_magic[obj->o_which].mi_name);
|
||||
else if (r_guess[obj->o_which])
|
||||
sprintf(pb, "A ring named %s (%s)",
|
||||
r_guess[obj->o_which], r_stones[obj->o_which]);
|
||||
else
|
||||
sprintf(pb, "A%s %s ring", vowelstr(r_stones[obj->o_which]),
|
||||
r_stones[obj->o_which]);
|
||||
if (obj == cur_ring[LEFT_1] || obj == cur_ring[LEFT_2] ||
|
||||
obj == cur_ring[LEFT_3] || obj == cur_ring[LEFT_4])
|
||||
strcat(pb, " (on left hand)");
|
||||
if (obj == cur_ring[RIGHT_1] || obj == cur_ring[RIGHT_2] ||
|
||||
obj == cur_ring[RIGHT_3] || obj == cur_ring[RIGHT_4])
|
||||
strcat(pb, " (on right hand)");
|
||||
when RELIC:
|
||||
if (obj->o_flags & ISKNOW)
|
||||
switch(obj->o_which) {
|
||||
case QUILL_NAGROM:
|
||||
sprintf(pb, "%s%s", rel_magic[obj->o_which].mi_name,
|
||||
charge_str(obj));
|
||||
otherwise:
|
||||
strcpy(pb, rel_magic[obj->o_which].mi_name);
|
||||
}
|
||||
else switch(obj->o_which) {
|
||||
case MUSTY_DAGGER:
|
||||
strcpy(pb, "Two very fine daggers marked MDDE");
|
||||
when EMORI_CLOAK:
|
||||
strcpy(pb, "A silk cloak");
|
||||
when HEIL_ANKH:
|
||||
strcpy(pb, "A golden ankh");
|
||||
when MING_STAFF:
|
||||
strcpy(pb, "A finely carved staff");
|
||||
when ORCUS_WAND:
|
||||
strcpy(pb, "A sparkling ivory wand");
|
||||
when ASMO_ROD:
|
||||
strcpy(pb, "A glistening ebony rod");
|
||||
when YENDOR_AMULET:
|
||||
strcpy(pb, "A silver amulet");
|
||||
when STONEBONES_AMULET:
|
||||
strcpy(pb, "A stone amulet");
|
||||
when BRIAN_MANDOLIN:
|
||||
strcpy(pb, "A gleaming mandolin");
|
||||
when HRUGGEK_MSTAR:
|
||||
strcpy(pb, "A silvery morning star");
|
||||
when AXE_AKLAD:
|
||||
strcpy(pb, "A jewel encrusted axe");
|
||||
when QUILL_NAGROM:
|
||||
strcpy(pb, "A bright white feather");
|
||||
when GERYON_HORN:
|
||||
strcpy(pb, "A jet black horn");
|
||||
when YEENOGHU_FLAIL:
|
||||
strcpy(pb, "A shimmering flail");
|
||||
when SURTUR_RING:
|
||||
strcpy(pb, "A fiery red ring");
|
||||
when ALTERAN_CARD:
|
||||
strcpy(pb, "A rectangular piece of wood");
|
||||
otherwise:
|
||||
strcpy(pb, "A wholly magical item");
|
||||
}
|
||||
|
||||
/* Take care of wielding and wearing */
|
||||
switch (obj->o_which) {
|
||||
case EMORI_CLOAK:
|
||||
if (cur_armor == NULL && cur_misc[WEAR_CLOAK] == NULL)
|
||||
strcat(pb, " (being worn)");
|
||||
if (obj->o_charges)
|
||||
strcat(pb, " [charged]");
|
||||
else
|
||||
strcat(pb, " [discharged]");
|
||||
when HEIL_ANKH:
|
||||
if (cur_relic[HEIL_ANKH]) strcat(pb, " (in palm)");
|
||||
when EYE_VECNA:
|
||||
if (cur_relic[EYE_VECNA]) strcat(pb, " (in forehead)");
|
||||
when STONEBONES_AMULET:
|
||||
if (cur_relic[STONEBONES_AMULET])
|
||||
strcat(pb, " (in chest)");
|
||||
when YENDOR_AMULET:
|
||||
if (cur_relic[YENDOR_AMULET])
|
||||
strcat(pb, " (in chest)");
|
||||
when MUSTY_DAGGER:
|
||||
case HRUGGEK_MSTAR:
|
||||
case AXE_AKLAD:
|
||||
case YEENOGHU_FLAIL:
|
||||
case MING_STAFF:
|
||||
case ASMO_ROD:
|
||||
case ORCUS_WAND:
|
||||
if (cur_weapon == obj) strcat(pb, " (weapon in hand)");
|
||||
when SURTUR_RING:
|
||||
if (cur_relic[SURTUR_RING])
|
||||
strcat(pb, " (in nose)");
|
||||
}
|
||||
when MM:
|
||||
if (m_know[obj->o_which])
|
||||
{
|
||||
misc_name(pb,obj);
|
||||
}
|
||||
else {
|
||||
switch (obj->o_which) {
|
||||
case MM_JUG:
|
||||
case MM_BEAKER:
|
||||
case MM_KEOGHTOM:
|
||||
strcpy(pb, "A crystalline jar");
|
||||
when MM_BOOK:
|
||||
case MM_SKILLS:
|
||||
strcpy(pb, "A dusty book");
|
||||
when MM_ELF_BOOTS:
|
||||
case MM_DANCE:
|
||||
strcpy(pb, "A pair of old boots");
|
||||
when MM_BRACERS:
|
||||
strcpy(pb, "A set of bracers");
|
||||
when MM_OPEN:
|
||||
case MM_HUNGER:
|
||||
strcpy(pb, "A mysterious chime");
|
||||
when MM_DISP:
|
||||
case MM_R_POWERLESS:
|
||||
case MM_PROTECT:
|
||||
strcpy(pb, "A dark looking cloak");
|
||||
when MM_DRUMS:
|
||||
strcpy(pb, "A drum set");
|
||||
when MM_DISAPPEAR:
|
||||
case MM_CHOKE:
|
||||
strcpy(pb, "A small pouch of dust");
|
||||
when MM_G_DEXTERITY:
|
||||
case MM_G_OGRE:
|
||||
case MM_FUMBLE:
|
||||
strcpy(pb, "A set of gauntlets");
|
||||
when MM_ADAPTION:
|
||||
case MM_JEWEL:
|
||||
case MM_STRANGLE:
|
||||
strcpy(pb, "A little necklace");
|
||||
when MM_CRYSTAL:
|
||||
strcpy(pb, "An unusual looking rock");
|
||||
otherwise:
|
||||
strcpy(pb, "A magical item");
|
||||
}
|
||||
if (m_guess[obj->o_which]) {
|
||||
strcat(pb, " named: ");
|
||||
strcat(pb, m_guess[obj->o_which]);
|
||||
}
|
||||
}
|
||||
if (obj == cur_misc[WEAR_BOOTS] ||
|
||||
obj == cur_misc[WEAR_BRACERS] ||
|
||||
obj == cur_misc[WEAR_CLOAK] ||
|
||||
obj == cur_misc[WEAR_GAUNTLET] ||
|
||||
obj == cur_misc[WEAR_NECKLACE] ||
|
||||
obj == cur_misc[WEAR_JEWEL])
|
||||
strcat(pb, " (being worn)");
|
||||
when GOLD:
|
||||
sprintf(pb, "%d Pieces of Gold", obj->o_count);
|
||||
otherwise:
|
||||
debug("Picked up something funny");
|
||||
sprintf(pb, "Something totally bizarre %s", unctrl(obj->o_type));
|
||||
wait_for(' ');
|
||||
}
|
||||
|
||||
/* Is it marked? */
|
||||
if (obj->o_mark[0]) {
|
||||
pb = &pb[strlen(pb)];
|
||||
sprintf(pb, " <%s>", obj->o_mark);
|
||||
}
|
||||
|
||||
if (obj->o_flags & ISPROT)
|
||||
strcat(pb, " [protected]");
|
||||
if (drop && isupper(prbuf[0]))
|
||||
prbuf[0] = tolower(prbuf[0]);
|
||||
else if (!drop && islower(*prbuf))
|
||||
*prbuf = toupper(*prbuf);
|
||||
if (!drop)
|
||||
strcat(pb, ".");
|
||||
/*
|
||||
* Truncate if long. Use cols-4 to offset the "pack letter" of a normal
|
||||
* inventory listing.
|
||||
*/
|
||||
prbuf[cols-4] = '\0';
|
||||
return prbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* weap_name:
|
||||
* Return the name of a weapon.
|
||||
*/
|
||||
|
||||
char *
|
||||
weap_name(obj)
|
||||
register struct object *obj;
|
||||
{
|
||||
switch (obj->o_type) {
|
||||
case WEAPON:
|
||||
return(weaps[obj->o_which].w_name);
|
||||
when MISSILE:
|
||||
return(ws_magic[obj->o_which].mi_name);
|
||||
when RELIC:
|
||||
switch (obj->o_which) {
|
||||
case MUSTY_DAGGER:
|
||||
return("daggers");
|
||||
when YEENOGHU_FLAIL:
|
||||
return("flail");
|
||||
when AXE_AKLAD:
|
||||
return("axe");
|
||||
when HRUGGEK_MSTAR:
|
||||
return("morning star");
|
||||
when MING_STAFF:
|
||||
return("staff");
|
||||
when ORCUS_WAND:
|
||||
return("wand");
|
||||
when ASMO_ROD:
|
||||
return("rod");
|
||||
}
|
||||
}
|
||||
return("weapon");
|
||||
}
|
||||
|
||||
/*
|
||||
* drop:
|
||||
* put something down
|
||||
*/
|
||||
|
||||
drop(item)
|
||||
struct linked_list *item;
|
||||
{
|
||||
register char ch = 0;
|
||||
register struct linked_list *obj, *nobj;
|
||||
register struct object *op;
|
||||
|
||||
if (item == NULL) {
|
||||
/* We charge 2 movement times to drop something */
|
||||
if (player.t_action == C_DROP && player.t_using != NULL) {
|
||||
obj = player.t_using;
|
||||
player.t_using = NULL;
|
||||
player.t_action = A_NIL;
|
||||
}
|
||||
|
||||
/* t_action == C_DROP always when called from command() */
|
||||
else {
|
||||
if ((obj = get_item(pack, "drop", ALL, FALSE, FALSE)) == NULL) {
|
||||
player.t_action = A_NIL;
|
||||
player.t_using = NULL;
|
||||
return(FALSE);
|
||||
}
|
||||
if (player.t_action == C_DROP) {
|
||||
player.t_using = obj;
|
||||
player.t_no_move = 2 * movement(&player);
|
||||
return(FALSE); /* We'll come back after we've waited */
|
||||
}
|
||||
}
|
||||
|
||||
switch(ch = 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("You can't leave it here");
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
else {
|
||||
obj = item;
|
||||
}
|
||||
op = OBJPTR(obj);
|
||||
if (!dropcheck(op))
|
||||
return(FALSE);
|
||||
|
||||
/*
|
||||
* If it is a scare monster scroll, curse it
|
||||
*/
|
||||
if (op->o_type == SCROLL && op->o_which == S_SCARE) {
|
||||
if (op->o_flags & ISBLESSED)
|
||||
op->o_flags &= ~ISBLESSED;
|
||||
else op->o_flags |= ISCURSED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Take it out of the pack
|
||||
*/
|
||||
if (op->o_count >= 2 && op->o_group == 0)
|
||||
{
|
||||
nobj = new_item(sizeof *op);
|
||||
op->o_count--;
|
||||
op = OBJPTR(nobj);
|
||||
*op = *(OBJPTR(obj));
|
||||
op->o_count = 1;
|
||||
obj = nobj;
|
||||
}
|
||||
else {
|
||||
detach(pack, obj);
|
||||
inpack--;
|
||||
}
|
||||
if(ch == POOL) {
|
||||
msg("Gloop... Your %s sinks out of sight. ",inv_name(op,TRUE));
|
||||
o_discard(obj);
|
||||
}
|
||||
else if (levtype == POSTLEV) {
|
||||
op->o_pos = hero; /* same place as hero */
|
||||
fall(obj,FALSE);
|
||||
if (item == NULL) /* if item wasn't sold */
|
||||
msg("Thanks for your donation to the Fiend's flea market.");
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Link it into the level object list
|
||||
*/
|
||||
attach(lvl_obj, obj);
|
||||
mvaddch(hero.y, hero.x, op->o_type);
|
||||
op->o_pos = hero;
|
||||
msg("Dropped %s", inv_name(op, TRUE));
|
||||
}
|
||||
updpack(FALSE, &player);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* do special checks for dropping or unweilding|unwearing|unringing
|
||||
*/
|
||||
|
||||
dropcheck(op)
|
||||
register struct object *op;
|
||||
{
|
||||
int save_max;
|
||||
|
||||
if (op == NULL)
|
||||
return TRUE;
|
||||
if (levtype == POSTLEV) {
|
||||
if ((op->o_flags & ISCURSED) && (op->o_flags & ISKNOW)) {
|
||||
msg("The trader does not accept 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(150) < cur_relic[op->o_which]++) {
|
||||
msg("The artifact turns on you! ");
|
||||
msg("It crushes your mind!!! --More--");
|
||||
pstats.s_hpt = -1;
|
||||
wait_for (' ');
|
||||
death(D_RELIC);
|
||||
}
|
||||
else {
|
||||
if (terse) msg("You can't release it.");
|
||||
else msg("You cannot bring yourself to release it.");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we aren't wearing it, we can drop it */
|
||||
if (!is_current(op)) return TRUE;
|
||||
|
||||
/* At this point, we know we are wearing the item */
|
||||
if (op->o_flags & ISCURSED) {
|
||||
msg("You can't. It appears to be cursed.");
|
||||
return FALSE;
|
||||
}
|
||||
if (op->o_type == RING && cur_misc[WEAR_GAUNTLET] != NULL) {
|
||||
msg ("You have to remove your gauntlets first!");
|
||||
return FALSE;
|
||||
}
|
||||
cur_null(op); /* set current to NULL */
|
||||
if (op->o_type == RING) {
|
||||
switch (op->o_which) {
|
||||
case R_ADDSTR: save_max = max_stats.s_str;
|
||||
chg_str(-op->o_ac);
|
||||
max_stats.s_str = save_max;
|
||||
when R_ADDHIT: pstats.s_dext -= op->o_ac;
|
||||
when R_ADDINTEL: pstats.s_intel -= op->o_ac;
|
||||
when R_ADDWISDOM: pstats.s_wisdom -= op->o_ac;
|
||||
when R_SEEINVIS: if (!ISWEARING(R_SEEINVIS) &&
|
||||
find_slot(unsee) == 0) {
|
||||
turn_off(player, CANSEE);
|
||||
msg("The tingling feeling leaves your eyes. ");
|
||||
}
|
||||
light(&hero);
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
when R_WARMTH: if (!ISWEARING(R_WARMTH) && !find_slot(nocold))
|
||||
turn_off(player, NOCOLD);
|
||||
when R_FIRE: if (!ISWEARING(R_FIRE) &&
|
||||
!cur_relic[SURTUR_RING] &&
|
||||
!find_slot(nofire))
|
||||
turn_off(player, NOFIRE);
|
||||
when R_LIGHT: {
|
||||
if(roomin(&hero) != NULL) {
|
||||
light(&hero);
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
}
|
||||
}
|
||||
when R_SEARCH: kill_daemon(ring_search);
|
||||
when R_TELEPORT: kill_daemon(ring_teleport);
|
||||
}
|
||||
}
|
||||
else if (op->o_type == MM) {
|
||||
switch (op->o_which) {
|
||||
case MM_ADAPTION:
|
||||
turn_off(player, NOGAS);
|
||||
turn_off(player, NOACID);
|
||||
|
||||
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);
|
||||
|
||||
when MM_G_OGRE:
|
||||
case MM_G_DEXTERITY:
|
||||
save_max = max_stats.s_str;
|
||||
chg_str(-op->o_ac);
|
||||
max_stats.s_str = save_max;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* return a new thing
|
||||
*/
|
||||
|
||||
struct linked_list *
|
||||
new_thing(thing_type, allow_curse)
|
||||
int thing_type;
|
||||
bool allow_curse;
|
||||
{
|
||||
register struct linked_list *item;
|
||||
register struct object *cur;
|
||||
register int j;
|
||||
register int blesschance, cursechance;
|
||||
|
||||
item = new_item(sizeof *cur);
|
||||
cur = OBJPTR(item);
|
||||
cur->o_hplus = cur->o_dplus = 0;
|
||||
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);
|
||||
if (allow_curse) cursechance = rnd(100);
|
||||
else cursechance = 100; /* No chance of curse */
|
||||
|
||||
/* Get the type of item (pick one if 'any' is specified) */
|
||||
if (thing_type == ALL) j = pick_one(things, NUMTHINGS);
|
||||
else j = thing_type;
|
||||
|
||||
/*
|
||||
* make sure he gets his vitamins
|
||||
*/
|
||||
if (thing_type == ALL && no_food > 4)
|
||||
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 > 1 &&
|
||||
j == 2)
|
||||
j = pick_one(things, NUMTHINGS); /* not too many.... */
|
||||
switch (j)
|
||||
{
|
||||
case TYP_POTION:
|
||||
cur->o_type = POTION;
|
||||
do {
|
||||
cur->o_which = pick_one(p_magic, MAXPOTIONS);
|
||||
} while (!allow_curse && p_magic[cur->o_which].mi_curse == 100);
|
||||
cur->o_weight = things[TYP_POTION].mi_wght;
|
||||
if (cursechance < p_magic[cur->o_which].mi_curse)
|
||||
cur->o_flags |= ISCURSED;
|
||||
else if (blesschance < p_magic[cur->o_which].mi_bless)
|
||||
cur->o_flags |= ISBLESSED;
|
||||
|
||||
/* If we made a gain ability potion, see what kind it is */
|
||||
if (cur->o_which == P_ABIL) cur->o_kind = rnd(NUMABILITIES);
|
||||
|
||||
when TYP_SCROLL:
|
||||
cur->o_type = SCROLL;
|
||||
do {
|
||||
cur->o_which = pick_one(s_magic, MAXSCROLLS);
|
||||
} while (!allow_curse && s_magic[cur->o_which].mi_curse == 100);
|
||||
cur->o_weight = things[TYP_SCROLL].mi_wght;
|
||||
if (cursechance < s_magic[cur->o_which].mi_curse)
|
||||
cur->o_flags |= ISCURSED;
|
||||
else if (blesschance < s_magic[cur->o_which].mi_bless)
|
||||
cur->o_flags |= ISBLESSED;
|
||||
when TYP_FOOD:
|
||||
no_food = 0;
|
||||
cur->o_type = FOOD;
|
||||
cur->o_weight = things[TYP_FOOD].mi_wght;
|
||||
cur->o_count += extras();
|
||||
foods_this_level += cur->o_count;
|
||||
cur->o_which = pick_one(foods, MAXFOODS);
|
||||
when TYP_WEAPON:
|
||||
cur->o_type = WEAPON;
|
||||
cur->o_which = rnd(MAXWEAPONS);
|
||||
init_weapon(cur, cur->o_which);
|
||||
if (cursechance < 20)
|
||||
{
|
||||
|
||||
cur->o_flags |= ISCURSED;
|
||||
cur->o_hplus -= rnd(3) + 1;
|
||||
cur->o_dplus -= rnd(3) + 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);
|
||||
wait_for(' ');
|
||||
j = 0;
|
||||
}
|
||||
cur->o_which = j;
|
||||
cur->o_ac = armors[j].a_class;
|
||||
cur->o_weight = armors[j].a_wght;
|
||||
if (cursechance < 20)
|
||||
{
|
||||
cur->o_flags |= ISCURSED;
|
||||
cur->o_ac += rnd(4)+1;
|
||||
}
|
||||
else if (blesschance < 40)
|
||||
cur->o_ac -= rnd(3)+1;
|
||||
when TYP_RING:
|
||||
cur->o_type = RING;
|
||||
do {
|
||||
cur->o_which = pick_one(r_magic, MAXRINGS);
|
||||
} while (!allow_curse && r_magic[cur->o_which].mi_curse == 100);
|
||||
cur->o_weight = things[TYP_RING].mi_wght;
|
||||
if (cursechance < r_magic[cur->o_which].mi_curse)
|
||||
cur->o_flags |= ISCURSED;
|
||||
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;
|
||||
if (cur->o_flags & ISCURSED)
|
||||
cur->o_ac = -cur->o_ac;
|
||||
if (blesschance < r_magic[cur->o_which].mi_bless)
|
||||
cur->o_ac+=rnd(vlevel/10)+1;
|
||||
when R_DIGEST:
|
||||
if (cur->o_flags & ISCURSED)
|
||||
cur->o_ac = -1;
|
||||
else if (blesschance < r_magic[cur->o_which].mi_bless)
|
||||
cur->o_ac = 2;
|
||||
else cur->o_ac = 1;
|
||||
}
|
||||
when TYP_STICK:
|
||||
cur->o_type = STICK;
|
||||
do {
|
||||
cur->o_which = pick_one(ws_magic, MAXSTICKS);
|
||||
} while (!allow_curse && ws_magic[cur->o_which].mi_curse == 100);
|
||||
fix_stick(cur);
|
||||
if (cursechance < ws_magic[cur->o_which].mi_curse)
|
||||
cur->o_flags |= ISCURSED;
|
||||
else if (blesschance < ws_magic[cur->o_which].mi_bless)
|
||||
cur->o_flags |= ISBLESSED;
|
||||
when TYP_MM:
|
||||
cur->o_type = MM;
|
||||
do {
|
||||
cur->o_which = pick_one(m_magic, MAXMM);
|
||||
} while (!allow_curse && m_magic[cur->o_which].mi_curse == 100);
|
||||
cur->o_weight = things[TYP_MM].mi_wght;
|
||||
if (cursechance < m_magic[cur->o_which].mi_curse)
|
||||
cur->o_flags |= ISCURSED;
|
||||
else if (blesschance < m_magic[cur->o_which].mi_bless)
|
||||
cur->o_flags |= ISBLESSED;
|
||||
switch (cur->o_which) {
|
||||
case MM_JUG:
|
||||
switch(rnd(11)) {
|
||||
case 0: cur->o_ac = P_PHASE;
|
||||
when 1: cur->o_ac = P_CLEAR;
|
||||
when 2: cur->o_ac = P_SEEINVIS;
|
||||
when 3: cur->o_ac = P_HEALING;
|
||||
when 4: cur->o_ac = P_MFIND;
|
||||
when 5: cur->o_ac = P_TFIND;
|
||||
when 6: cur->o_ac = P_HASTE;
|
||||
when 7: cur->o_ac = P_RESTORE;
|
||||
when 8: cur->o_ac = P_FLY;
|
||||
when 9: cur->o_ac = P_SKILL;
|
||||
when 10:cur->o_ac = P_FFIND;
|
||||
}
|
||||
when MM_HUNGER:
|
||||
case MM_CHOKE:
|
||||
cur->o_ac = (2 + rnd(2)) * 3;
|
||||
when MM_OPEN:
|
||||
case MM_DRUMS:
|
||||
case MM_DISAPPEAR:
|
||||
case MM_KEOGHTOM:
|
||||
cur->o_ac = (5 + rnd(6)) * 3;
|
||||
when MM_BRACERS:
|
||||
if (cur->o_flags & ISCURSED)
|
||||
cur->o_ac = -(rnd(5)+1);
|
||||
else
|
||||
cur->o_ac = rnd(5)+1;
|
||||
when MM_PROTECT:
|
||||
if (cur->o_flags & ISCURSED)
|
||||
cur->o_ac = -(rnd(5)+1);
|
||||
else
|
||||
cur->o_ac = rnd(5)+1;
|
||||
when MM_DISP:
|
||||
cur->o_ac = 3;
|
||||
when MM_SKILLS: /* set it to a character class */
|
||||
cur->o_ac = rnd(NUM_CHARTYPES-1);
|
||||
when MM_CRYSTAL:
|
||||
cur->o_ac = 1; /* Use it just once */
|
||||
otherwise:
|
||||
cur->o_ac = 0;
|
||||
}
|
||||
otherwise:
|
||||
debug("Picked a bad kind of object");
|
||||
wait_for(' ');
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
/*
|
||||
* provide a new item tailored to specification
|
||||
*/
|
||||
|
||||
struct linked_list *
|
||||
spec_item(type, which, hit, damage)
|
||||
int type, which, hit, damage;
|
||||
{
|
||||
register struct linked_list *item;
|
||||
register struct object *obj;
|
||||
|
||||
item = new_item(sizeof *obj);
|
||||
obj = OBJPTR(item);
|
||||
obj->o_count = 1;
|
||||
obj->o_group = 0;
|
||||
obj->contents = NULL;
|
||||
obj->o_type = type;
|
||||
obj->o_which = which;
|
||||
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_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 |= ISCURSED;
|
||||
|
||||
when ARMOR:
|
||||
obj->o_ac = armors[which].a_class - hit;
|
||||
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 < 0) obj->o_flags |= ISCURSED;
|
||||
}
|
||||
|
||||
when STICK:
|
||||
fix_stick(obj);
|
||||
obj->o_charges = hit;
|
||||
|
||||
when GOLD:
|
||||
obj->o_type = GOLD;
|
||||
obj->o_count = GOLDCALC;
|
||||
obj->o_ac = 11;
|
||||
|
||||
when MM:
|
||||
obj->o_type = MM;
|
||||
obj->o_ac = hit;
|
||||
|
||||
when RELIC:
|
||||
/* Handle weight here since these are all created uniquely */
|
||||
obj->o_weight = things[TYP_RELIC].mi_wght;
|
||||
if (obj->o_which == EMORI_CLOAK)
|
||||
obj->o_charges = 1;
|
||||
|
||||
}
|
||||
return(item);
|
||||
}
|
||||
|
||||
/*
|
||||
* pick an item out of a list of nitems possible magic items
|
||||
*/
|
||||
|
||||
pick_one(magic, nitems)
|
||||
register struct magic_item *magic;
|
||||
int nitems;
|
||||
{
|
||||
register struct magic_item *end;
|
||||
register int i;
|
||||
register struct magic_item *start;
|
||||
|
||||
start = magic;
|
||||
for (end = &magic[nitems], i = rnd(1000); magic < end; magic++)
|
||||
if (i < magic->mi_prob)
|
||||
break;
|
||||
if (magic == end)
|
||||
{
|
||||
if (wizard)
|
||||
{
|
||||
msg("bad pick_one: %d from %d items", i, nitems);
|
||||
for (magic = start; magic < end; magic++)
|
||||
msg("%s: %d%%", magic->mi_name, magic->mi_prob);
|
||||
}
|
||||
magic = start;
|
||||
}
|
||||
return magic - start;
|
||||
}
|
||||
|
||||
|
||||
/* blesscurse returns whether, according to the flag, the object is
|
||||
* blessed, cursed, or neither
|
||||
*/
|
||||
|
||||
char *
|
||||
blesscurse(flags)
|
||||
int flags;
|
||||
{
|
||||
if (flags & ISKNOW) {
|
||||
if (flags & ISCURSED) return("cursed ");
|
||||
if (flags & ISBLESSED) return("blessed ");
|
||||
return("normal ");
|
||||
}
|
||||
return("");
|
||||
}
|
||||
|
||||
/*
|
||||
* p_kind returns the type of potion for some types of identified potions;
|
||||
* otherwise, it returns the color.
|
||||
*/
|
||||
|
||||
char *
|
||||
p_kind(obj)
|
||||
struct object *obj; /* We assume that obj points to a potion */
|
||||
{
|
||||
if (obj->o_which == P_ABIL) return(abilities[obj->o_kind].w_string);
|
||||
else return(p_colors[obj->o_which]);
|
||||
}
|
||||
|
||||
/*
|
||||
* extras:
|
||||
* Return the number of extra items to be created
|
||||
*/
|
||||
|
||||
extras()
|
||||
{
|
||||
reg int i;
|
||||
|
||||
i = rnd(100);
|
||||
if (i < 3) /* 3% for 2 more */
|
||||
return (2);
|
||||
else if (i < 6) /* 6% for 1 more */
|
||||
return (1);
|
||||
else /* otherwise no more */
|
||||
return (0);
|
||||
}
|
||||
|
||||
498
xrogue/trader.c
Normal file
498
xrogue/trader.c
Normal file
|
|
@ -0,0 +1,498 @@
|
|||
/*
|
||||
trader.c - Anything to do with trading posts
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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"
|
||||
|
||||
/*
|
||||
* buy_it:
|
||||
* Buy the item on which the hero stands
|
||||
*/
|
||||
|
||||
buy_it()
|
||||
{
|
||||
reg int wh;
|
||||
struct linked_list *item = NULL;
|
||||
struct object *obj = NULL;
|
||||
int wasfood = FALSE;
|
||||
|
||||
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 = wgetch(cw);
|
||||
if (wh == ESC || wh == 'n') {
|
||||
msg("");
|
||||
return;
|
||||
}
|
||||
} until(wh == 'y');
|
||||
}
|
||||
mpos = 0;
|
||||
if (curprice > purse) {
|
||||
msg("You can't afford it!");
|
||||
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);
|
||||
obj = OBJPTR(item);
|
||||
mpos = 0;
|
||||
wasfood = ISMULT(obj->o_type);
|
||||
if (add_pack((struct linked_list *)NULL,TRUE)) {/* 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;
|
||||
if (!wasfood) /* if it was food then the object has been deleted */
|
||||
{
|
||||
whatis (item); /* identify it */
|
||||
obj = OBJPTR(item);
|
||||
obj->o_flags &= ~ISPOST; /* turn off ISPOST */
|
||||
obj->o_flags |= ISKNOW; /* he knows the item */
|
||||
msg("%s", inv_name(obj, TRUE));
|
||||
}
|
||||
else
|
||||
msg("a food ration.");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* do_post:
|
||||
* Put a trading post room and stuff on the screen
|
||||
*/
|
||||
|
||||
do_post(startup)
|
||||
bool startup; /* True if equipping the player at the beginning of the game */
|
||||
{
|
||||
coord tp;
|
||||
reg int i, j = 0, k;
|
||||
reg struct room *rp;
|
||||
reg struct object *op;
|
||||
reg struct linked_list *ll;
|
||||
|
||||
o_free_list(lvl_obj); /* throw old items away */
|
||||
|
||||
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
|
||||
rp->r_flags = ISGONE; /* kill all rooms */
|
||||
|
||||
rp = &rooms[0]; /* point to only room */
|
||||
rp->r_flags = 0; /* this room NOT gone */
|
||||
rp->r_max.x = 40;
|
||||
rp->r_max.y = 10; /* 10 * 40 room */
|
||||
rp->r_pos.x = (cols - rp->r_max.x) / 2; /* center horizontal */
|
||||
rp->r_pos.y = 1; /* 2nd line */
|
||||
draw_room(rp); /* draw the only room */
|
||||
|
||||
/* Are we equipping the player? */
|
||||
if (startup) {
|
||||
int wpt;
|
||||
|
||||
/*
|
||||
* Give the rogue some weaponry.
|
||||
* Create every kind of weapon there is.
|
||||
*/
|
||||
for (wpt=0; wpt<MAXWEAPONS; wpt++) {
|
||||
ll = spec_item(WEAPON, wpt, rnd(100)/80+1, rnd(121)/60);
|
||||
attach(lvl_obj, ll);
|
||||
op = OBJPTR(ll);
|
||||
op->o_flags |= (ISPOST | ISKNOW);
|
||||
do {
|
||||
rnd_pos(rp,&tp);
|
||||
} until (mvinch(tp.y, tp.x) == FLOOR);
|
||||
op->o_pos = tp;
|
||||
mvaddch(tp.y,tp.x,op->o_type);
|
||||
}
|
||||
|
||||
/*
|
||||
* Suit of armor.
|
||||
* Create every kind of armor there is.
|
||||
*/
|
||||
for (i=0; i<MAXARMORS; i++) {
|
||||
ll = spec_item(ARMOR, i, rnd(100)/75, 0);
|
||||
attach(lvl_obj, ll);
|
||||
op = OBJPTR(ll);
|
||||
op->o_flags |= (ISPOST | ISKNOW);
|
||||
op->o_weight = armors[i].a_wght;
|
||||
do {
|
||||
rnd_pos(rp,&tp);
|
||||
} until (mvinch(tp.y, tp.x) == FLOOR);
|
||||
op->o_pos = tp;
|
||||
mvaddch(tp.y,tp.x,op->o_type);
|
||||
}
|
||||
|
||||
/* Now create some rods/wands/staffs */
|
||||
for (i=rnd(4)+2; i>0; i--) {
|
||||
if (i == 1 && player.t_ctype != C_FIGHTER) j = WS_HIT;
|
||||
else if (i == 5 && (player.t_ctype == C_RANGER ||
|
||||
player.t_ctype == C_PALADIN ||
|
||||
player.t_ctype == C_MONK)) j = WS_FEAR;
|
||||
else switch (rnd(8)) {
|
||||
case 0: j = WS_SLOW_M;
|
||||
when 1: j = WS_TELMON;
|
||||
when 2: j = WS_CONFMON;
|
||||
when 3: j = WS_PARALYZE;
|
||||
when 4: j = WS_MDEG;
|
||||
when 5: j = WS_WONDER;
|
||||
when 6: j = WS_LIGHT;
|
||||
when 7: j = WS_CANCEL;
|
||||
}
|
||||
ll = spec_item(STICK, j, 0, 0);
|
||||
attach(lvl_obj, ll);
|
||||
op = OBJPTR(ll);
|
||||
|
||||
/* Let clerics and MU'S know what kind they are */
|
||||
switch (player.t_ctype) {
|
||||
case C_MAGICIAN:
|
||||
case C_CLERIC:
|
||||
case C_DRUID:
|
||||
op->o_flags |= (ISPOST | ISKNOW);
|
||||
otherwise:
|
||||
op->o_flags |= ISPOST;
|
||||
}
|
||||
fix_stick(op);
|
||||
do {
|
||||
rnd_pos(rp,&tp);
|
||||
} until (mvinch(tp.y, tp.x) == FLOOR);
|
||||
op->o_pos = tp;
|
||||
mvaddch(tp.y,tp.x,op->o_type);
|
||||
}
|
||||
|
||||
/* Now let's make some rings */
|
||||
for (i=rnd(5)+3; i>0; i--) {
|
||||
k = 0;
|
||||
if (i == 6 && player.t_ctype != C_MONK) j = R_HEALTH;
|
||||
else if (i == 7) j = R_HEROISM;
|
||||
else switch (rnd(21)) {
|
||||
case 0: j = R_ADDINTEL; k = roll(1,3);
|
||||
when 1: j = R_ADDSTR; k = roll(1,3);
|
||||
when 2: j = R_ADDWISDOM; k = roll(1,3);
|
||||
when 3: j = R_ADDHIT; k = roll(1,3);
|
||||
when 4: j = R_ADDDAM; k = roll(1,3);
|
||||
when 5: j = R_PROTECT; k = roll(1,3);
|
||||
when 6: j = R_DIGEST; k = 1;
|
||||
when 7: j = R_SUSABILITY;
|
||||
when 8: j = R_SEEINVIS;
|
||||
when 9: j = R_ALERT;
|
||||
when 10: j = R_FIRE;
|
||||
when 11: j = R_WARMTH;
|
||||
when 12: j = R_FREEDOM;
|
||||
when 13: j = R_STEALTH;
|
||||
when 14: j = R_CARRY;
|
||||
when 15: j = R_LIGHT;
|
||||
when 16: j = R_TELCONTROL;
|
||||
when 17: j = R_DELUSION;
|
||||
when 18: j = R_FEAR;
|
||||
when 19: j = R_AGGR;
|
||||
when 20: j = R_SEARCH;
|
||||
}
|
||||
ll = spec_item(RING, j, k, 0);
|
||||
attach(lvl_obj, ll);
|
||||
op = OBJPTR(ll);
|
||||
|
||||
/*
|
||||
* Let fighters, thieves, and monks know what kind
|
||||
* of rings these are.
|
||||
*/
|
||||
switch (player.t_ctype) {
|
||||
case C_FIGHTER:
|
||||
case C_THIEF:
|
||||
case C_MONK:
|
||||
op->o_flags |= (ISPOST | ISKNOW);
|
||||
otherwise:
|
||||
op->o_flags |= ISPOST;
|
||||
}
|
||||
do {
|
||||
rnd_pos(rp,&tp);
|
||||
} until (mvinch(tp.y, tp.x) == FLOOR);
|
||||
op->o_pos = tp;
|
||||
mvaddch(tp.y,tp.x,op->o_type);
|
||||
}
|
||||
|
||||
/* Let's offer some potions */
|
||||
for (i=rnd(4)+3; i>0; i--) {
|
||||
if (i == 1 && player.t_ctype == C_ASSASSIN) j = P_POISON;
|
||||
else if (i == 6) j = P_PHASE;
|
||||
else switch (rnd(11)) {
|
||||
case 0: j = P_CLEAR;
|
||||
when 1: j = P_HEALING;
|
||||
when 2: j = P_MFIND;
|
||||
when 3: j = P_HASTE;
|
||||
when 4: j = P_RESTORE;
|
||||
when 5: j = P_FLY;
|
||||
when 6: j = P_FFIND;
|
||||
when 7: j = P_SEEINVIS;
|
||||
when 8: j = P_TFIND;
|
||||
when 9: j = P_INVIS;
|
||||
when 10: j = P_SKILL;
|
||||
}
|
||||
|
||||
/* Make the potion */
|
||||
ll = spec_item(POTION, j, 0, 0);
|
||||
attach(lvl_obj, ll);
|
||||
op = OBJPTR(ll);
|
||||
op->o_flags |= ISPOST;
|
||||
|
||||
/* Place the potion */
|
||||
do {
|
||||
rnd_pos(rp,&tp);
|
||||
} until (mvinch(tp.y, tp.x) == FLOOR);
|
||||
op->o_pos = tp;
|
||||
mvaddch(tp.y,tp.x,op->o_type);
|
||||
}
|
||||
|
||||
/* Let's offer some scrolls */
|
||||
for (i=rnd(4)+3; i>0; i--) {
|
||||
if (i == 1 && player.t_ctype != C_MONK) j = S_CURING;
|
||||
else if (i == 6 && player.t_ctype != C_THIEF) j = S_FINDTRAPS;
|
||||
else switch (rnd(11)) {
|
||||
case 0: j = S_CONFUSE;
|
||||
when 1: j = S_MAP;
|
||||
when 2: j = S_LIGHT;
|
||||
when 3: j = S_SLEEP;
|
||||
when 4: j = S_IDENT;
|
||||
when 5: j = S_GFIND;
|
||||
when 6: j = S_REMOVE;
|
||||
when 7: j = S_HOLD;
|
||||
when 8: j = S_PETRIFY;
|
||||
when 9: j = S_SCARE;
|
||||
when 10: j = S_TELEP;
|
||||
}
|
||||
|
||||
/* Make the scroll */
|
||||
ll = spec_item(SCROLL, j, 0, 0);
|
||||
attach(lvl_obj, ll);
|
||||
op = OBJPTR(ll);
|
||||
op->o_flags |= ISPOST;
|
||||
|
||||
/* Place the scroll */
|
||||
do {
|
||||
rnd_pos(rp,&tp);
|
||||
} until (mvinch(tp.y, tp.x) == FLOOR);
|
||||
op->o_pos = tp;
|
||||
mvaddch(tp.y,tp.x,op->o_type);
|
||||
}
|
||||
|
||||
/* And finally, let's get some food */
|
||||
for (i=rnd(3)+2; i>0; i--) {
|
||||
ll = spec_item(FOOD, 0, 0, 0);
|
||||
attach(lvl_obj, ll);
|
||||
op = OBJPTR(ll);
|
||||
op->o_weight = things[TYP_FOOD].mi_wght;
|
||||
op->o_flags |= ISPOST;
|
||||
do {
|
||||
rnd_pos(rp,&tp);
|
||||
} until (mvinch(tp.y, tp.x) == FLOOR);
|
||||
op->o_pos = tp;
|
||||
mvaddch(tp.y,tp.x,op->o_type);
|
||||
}
|
||||
}
|
||||
else { /* in trading post itself */
|
||||
i = roll(10, 4); /* 10 to 40 items */
|
||||
for (; i > 0 ; i--) { /* place all the items */
|
||||
ll = new_thing(ALL, TRUE); /* get something */
|
||||
attach(lvl_obj, ll);
|
||||
op = OBJPTR(ll);
|
||||
op->o_flags |= ISPOST; /* object in trading post */
|
||||
do {
|
||||
rnd_pos(rp,&tp);
|
||||
} until (mvinch(tp.y, tp.x) == FLOOR);
|
||||
op->o_pos = tp;
|
||||
mvaddch(tp.y,tp.x,op->o_type);
|
||||
}
|
||||
}
|
||||
wmove(cw,12,0);
|
||||
nofont(cw);
|
||||
trader = 0;
|
||||
if (startup) {
|
||||
waddstr(cw,"Welcome to Friendly Fiend's Equipage\n\r");
|
||||
waddstr(cw,"====================================\n\r");
|
||||
}
|
||||
else {
|
||||
waddstr(cw,"Welcome to Friendly Fiend's Flea Market\n\r");
|
||||
waddstr(cw,"=======================================\n\r");
|
||||
}
|
||||
waddstr(cw,"$: Prices object that you stand upon.\n\r");
|
||||
waddstr(cw,"#: Buys the object that you stand upon.\n\r");
|
||||
waddstr(cw,"%: Trades in something in your pack for gold.\n\r");
|
||||
newfont(cw);
|
||||
trans_line();
|
||||
}
|
||||
|
||||
/*
|
||||
* open_market:
|
||||
* Retruns TRUE when ok do to transacting
|
||||
*/
|
||||
|
||||
open_market()
|
||||
{
|
||||
if (trader >= MAXPURCH && !wizard && level != 0) {
|
||||
msg("The market is closed. The stairs are that-a-way! ");
|
||||
return FALSE;
|
||||
}
|
||||
else {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* price_it:
|
||||
* Price the object that the hero stands on
|
||||
*/
|
||||
|
||||
price_it()
|
||||
{
|
||||
reg struct linked_list *item;
|
||||
reg struct object *obj;
|
||||
reg int worth;
|
||||
reg char *str;
|
||||
|
||||
if (!open_market()) /* after buying hours */
|
||||
return FALSE;
|
||||
if ((item = find_obj(hero.y,hero.x)) == NULL) {
|
||||
debug("Can't find the item");
|
||||
return FALSE;
|
||||
}
|
||||
obj = OBJPTR(item);
|
||||
worth = get_worth(obj);
|
||||
if (worth < 0) {
|
||||
msg("That's not for sale.");
|
||||
return FALSE;
|
||||
}
|
||||
if (worth < 25)
|
||||
worth = 25;
|
||||
|
||||
/* Our shopkeeper is affected by the person's charisma */
|
||||
if (pstats.s_charisma > 24) /* but don't give it away! */
|
||||
worth = (int) ((float) worth * (18. / (float)24));
|
||||
else
|
||||
worth = (int) ((float) worth * (18. / (float)pstats.s_charisma));
|
||||
|
||||
str = inv_name(obj, TRUE);
|
||||
msg("%s for only %d pieces of gold", str, worth);
|
||||
curprice = worth; /* save price */
|
||||
strcpy(curpurch,str); /* save item */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* sell_it:
|
||||
* Sell an item to the trading post
|
||||
*/
|
||||
|
||||
sell_it()
|
||||
{
|
||||
reg struct linked_list *item;
|
||||
reg struct object *obj;
|
||||
reg int wo, ch;
|
||||
|
||||
if (!open_market()) /* after selling hours */
|
||||
return;
|
||||
|
||||
if ((item = get_item(pack, "sell", ALL, FALSE, FALSE)) == NULL)
|
||||
return;
|
||||
obj = OBJPTR(item);
|
||||
wo = get_worth(obj);
|
||||
if (wo <= 0) {
|
||||
mpos = 0;
|
||||
msg("We don't buy those.");
|
||||
return;
|
||||
}
|
||||
if (wo < 25)
|
||||
wo = 25;
|
||||
msg("Your %s is worth %d pieces of gold.",typ_name(obj),wo);
|
||||
msg("Do you want to sell it? ");
|
||||
do {
|
||||
ch = wgetch(cw);
|
||||
if (ch == ESC || ch == 'n') {
|
||||
msg("");
|
||||
return;
|
||||
}
|
||||
} until (ch == 'y');
|
||||
mpos = 0;
|
||||
if (drop(item) == TRUE) { /* drop this item */
|
||||
purse += wo; /* give him his money */
|
||||
++trader; /* another transaction */
|
||||
wo = obj->o_count;
|
||||
if (obj->o_group == 0) /* dropped one at a time */
|
||||
obj->o_count = 1;
|
||||
msg("Sold %s",inv_name(obj,TRUE));
|
||||
obj->o_count = wo;
|
||||
trans_line(); /* show remaining deals */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* trans_line:
|
||||
* Show how many transactions the hero has left
|
||||
*/
|
||||
|
||||
trans_line()
|
||||
{
|
||||
if (level == 0)
|
||||
sprintf(prbuf, "You are welcome to spend whatever gold you have.");
|
||||
else if (!wizard)
|
||||
sprintf(prbuf,"You have %d transactions remaining.",
|
||||
MAXPURCH - trader);
|
||||
else
|
||||
sprintf(prbuf,
|
||||
"You have infinite transactions remaining oh great wizard.");
|
||||
nofont(cw);
|
||||
mvwaddstr(cw,lines - 4,0,prbuf);
|
||||
newfont(cw);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
1313
xrogue/util.c
Normal file
1313
xrogue/util.c
Normal file
File diff suppressed because it is too large
Load diff
21
xrogue/vers.c
Normal file
21
xrogue/vers.c
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
vers.c - version number
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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.
|
||||
*/
|
||||
|
||||
unsigned 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";
|
||||
char version[] = "@(#)vers.c 8.0.3 - 12/10/2005";
|
||||
char *release = "8.0.3";
|
||||
428
xrogue/weapons.c
Normal file
428
xrogue/weapons.c
Normal file
|
|
@ -0,0 +1,428 @@
|
|||
/*
|
||||
weapons.c - Functions for dealing with problems brought about by weapons
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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"
|
||||
|
||||
boomerang(ydelta, xdelta, item, tp)
|
||||
int ydelta, xdelta;
|
||||
register struct linked_list *item;
|
||||
register struct thing *tp;
|
||||
{
|
||||
register struct object *obj;
|
||||
struct thing midpoint;
|
||||
coord oldpos;
|
||||
|
||||
obj = OBJPTR(item);
|
||||
oldpos = obj->o_pos;
|
||||
|
||||
/*
|
||||
* make it appear to fly at the target
|
||||
*/
|
||||
do_motion(obj, ydelta, xdelta, tp);
|
||||
hit_monster(unc(obj->o_pos), obj, tp);
|
||||
|
||||
/*
|
||||
* Now let's make it fly back to the wielder. We need to
|
||||
* use midpoint to fool do_motion into thinking the action
|
||||
* starts there. Do_motion only looks at the t_pos field.
|
||||
*/
|
||||
midpoint.t_pos = obj->o_pos; /* Simulate a new start position */
|
||||
do_motion(obj, -ydelta, -xdelta, &midpoint);
|
||||
|
||||
obj->o_pos = oldpos;
|
||||
}
|
||||
|
||||
/*
|
||||
* do the actual motion on the screen done by an object traveling
|
||||
* across the room. Note that we should not look at any field in
|
||||
* tp other than t_pos unless we change boomerang().
|
||||
*/
|
||||
|
||||
do_motion(obj, ydelta, xdelta, tp)
|
||||
register struct object *obj;
|
||||
register int ydelta, xdelta;
|
||||
register struct thing *tp;
|
||||
{
|
||||
|
||||
/*
|
||||
* Come fly with us ...
|
||||
*/
|
||||
obj->o_pos = tp->t_pos;
|
||||
for (;;) {
|
||||
register int ch;
|
||||
/*
|
||||
* Erase the old one
|
||||
*/
|
||||
if (!ce(obj->o_pos, tp->t_pos) &&
|
||||
cansee(unc(obj->o_pos)) &&
|
||||
mvwinch(cw, obj->o_pos.y, obj->o_pos.x) != ' ') {
|
||||
mvwaddch(cw, obj->o_pos.y, obj->o_pos.x, show(obj->o_pos.y, obj->o_pos.x));
|
||||
}
|
||||
/*
|
||||
* Get the new position
|
||||
*/
|
||||
obj->o_pos.y += ydelta;
|
||||
obj->o_pos.x += xdelta;
|
||||
if (shoot_ok(ch = winat(obj->o_pos.y, obj->o_pos.x)) && ch != DOOR && !ce(obj->o_pos, hero)) {
|
||||
/*
|
||||
* It hasn't hit anything yet, so display it
|
||||
* If it alright.
|
||||
*/
|
||||
if (cansee(unc(obj->o_pos)) &&
|
||||
mvwinch(cw, obj->o_pos.y, obj->o_pos.x) != ' ') {
|
||||
if (obj->o_type == MISSILE) nofont(cw);
|
||||
mvwaddch(cw, obj->o_pos.y, obj->o_pos.x, obj->o_type);
|
||||
newfont(cw);
|
||||
draw(cw);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Did we stop because of a monster or the hero? If we did
|
||||
* not, we want to move our position back one because we could
|
||||
* not actually make it this far.
|
||||
*/
|
||||
if (!isalpha(ch) &&
|
||||
!(obj->o_pos.y == hero.y && obj->o_pos.x == hero.x)) {
|
||||
obj->o_pos.y -= ydelta;
|
||||
obj->o_pos.x -= xdelta;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fall:
|
||||
* Drop an item someplace around here.
|
||||
*/
|
||||
|
||||
fall(item, pr)
|
||||
register struct linked_list *item;
|
||||
bool pr;
|
||||
{
|
||||
register struct object *obj;
|
||||
register struct room *rp;
|
||||
register int i;
|
||||
struct object *tobj;
|
||||
struct linked_list *titem;
|
||||
coord *fpos = 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) {
|
||||
if (obj->o_group) { /* try to add groups together */
|
||||
for(titem=lvl_obj; titem!=NULL; titem=next(titem)) {
|
||||
tobj = OBJPTR(titem);
|
||||
if (tobj->o_group == obj->o_group &&
|
||||
tobj->o_pos.y == fpos->y &&
|
||||
tobj->o_pos.x == fpos->x) {
|
||||
tobj->o_count += obj->o_count;
|
||||
o_discard(item);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
mvaddch(fpos->y, fpos->x, obj->o_type);
|
||||
obj->o_pos = *fpos;
|
||||
if ((rp = roomin(&hero)) != NULL &&
|
||||
lit_room(rp)) {
|
||||
light(&hero);
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
}
|
||||
attach(lvl_obj, item);
|
||||
return;
|
||||
}
|
||||
if (pr) {
|
||||
msg("The %s vanishes as it hits the ground.",
|
||||
weaps[obj->o_which].w_name);
|
||||
}
|
||||
o_discard(item);
|
||||
}
|
||||
|
||||
/*
|
||||
* Does the missile hit the monster
|
||||
*/
|
||||
|
||||
hit_monster(y, x, obj, tp)
|
||||
register int y, x;
|
||||
struct object *obj;
|
||||
register struct thing *tp;
|
||||
{
|
||||
static coord mp;
|
||||
|
||||
mp.y = y;
|
||||
mp.x = x;
|
||||
if (tp == &player) {
|
||||
/* Make sure there is a monster where it landed */
|
||||
if (!isalpha(mvwinch(mw, y, x))) {
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/* Player hits monster */
|
||||
return(fight(&mp, obj, TRUE));
|
||||
} else {
|
||||
if (!ce(mp, hero)) {
|
||||
/* Monster hits monster */
|
||||
return(skirmish(tp, &mp, obj, TRUE));
|
||||
}
|
||||
|
||||
/* Monster hits player */
|
||||
return(attack(tp, obj, TRUE));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* init_weapon:
|
||||
* Set up the initial goodies for a weapon
|
||||
*/
|
||||
|
||||
init_weapon(weap, type)
|
||||
register struct object *weap;
|
||||
char type;
|
||||
{
|
||||
register struct init_weps *iwp;
|
||||
|
||||
iwp = &weaps[type];
|
||||
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 (obj->o_type == RELIC && obj->o_which == AXE_AKLAD) {
|
||||
boomerang(ydelta, xdelta, item, tp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dropcheck(obj)) return; /* Can we get rid of it? */
|
||||
|
||||
if(!(obj->o_flags & ISMISL)) {
|
||||
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 = wgetch(cw);
|
||||
if (ch == 'n' || ch == ESC) {
|
||||
after = FALSE;
|
||||
return;
|
||||
}
|
||||
if (ch == 'y')
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Get rid of the thing. If it is a non-multiple item object, or
|
||||
* if it is the last thing, just drop it. Otherwise, create a new
|
||||
* item with a count of one.
|
||||
*/
|
||||
if (obj->o_count < 2) {
|
||||
detach(tp->t_pack, item);
|
||||
if (tp->t_pack == pack) {
|
||||
inpack--;
|
||||
}
|
||||
}
|
||||
else {
|
||||
obj->o_count--;
|
||||
nitem = (struct linked_list *) new_item(sizeof *obj);
|
||||
obj = OBJPTR(nitem);
|
||||
*obj = *(OBJPTR(item));
|
||||
obj->o_count = 1;
|
||||
item = nitem;
|
||||
}
|
||||
updpack(FALSE, tp);
|
||||
do_motion(obj, ydelta, xdelta, tp);
|
||||
/*
|
||||
* AHA! Here it has hit something. If it is a wall or a door,
|
||||
* or if it misses (combat) the monster, put it on the floor
|
||||
*/
|
||||
if (!hit_monster(unc(obj->o_pos), obj, tp)) {
|
||||
fall(item, TRUE);
|
||||
}
|
||||
else
|
||||
o_discard(item);
|
||||
|
||||
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/2];
|
||||
|
||||
if (n1 == 0 && n2 == 0) {
|
||||
return "+0";
|
||||
}
|
||||
if (n2 == 0) {
|
||||
sprintf(numbuf, "%s%d", n1 < 0 ? "" : "+", n1);
|
||||
} else {
|
||||
sprintf(numbuf, "%s%d, %s%d", n1 < 0 ? "" : "+", n1, n2 < 0 ? "" : "+", n2);
|
||||
}
|
||||
return(numbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* wield:
|
||||
* Pull out a certain weapon
|
||||
*/
|
||||
|
||||
wield()
|
||||
{
|
||||
register struct linked_list *item;
|
||||
register struct object *obj, *oweapon;
|
||||
|
||||
/*
|
||||
* It takes 2 movement periods to unwield a weapon and 2 movement
|
||||
* periods to wield a weapon.
|
||||
*/
|
||||
if (player.t_action != C_WIELD) {
|
||||
player.t_action = C_WIELD;
|
||||
player.t_using = NULL; /* Make sure this is NULL! */
|
||||
if (cur_weapon != NULL) {
|
||||
player.t_no_move = 2 * movement(&player);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((oweapon = cur_weapon) != NULL) {
|
||||
/* At this point we have waited at least 2 units */
|
||||
if (!dropcheck(cur_weapon)) {
|
||||
cur_weapon = oweapon;
|
||||
player.t_action = A_NIL;
|
||||
return;
|
||||
}
|
||||
if (terse)
|
||||
addmsg("Was ");
|
||||
else
|
||||
addmsg("You were ");
|
||||
msg("wielding %s", inv_name(oweapon, TRUE));
|
||||
}
|
||||
|
||||
/* We we have something picked out? */
|
||||
if (player.t_using == NULL) {
|
||||
/* Now, what does he want to wield? */
|
||||
if ((item = get_item(pack, "wield", WIELDABLE, FALSE, FALSE)) == NULL) {
|
||||
player.t_action = A_NIL;
|
||||
after = FALSE;
|
||||
return;
|
||||
}
|
||||
player.t_using = item;
|
||||
player.t_no_move = 2 * movement(&player);
|
||||
return;
|
||||
}
|
||||
|
||||
/* We have waited our time, let's wield the weapon */
|
||||
item = player.t_using;
|
||||
player.t_using = NULL;
|
||||
player.t_action = A_NIL;
|
||||
|
||||
obj = OBJPTR(item);
|
||||
|
||||
if (is_current(obj)) {
|
||||
msg("Item in use.");
|
||||
after = FALSE;
|
||||
return;
|
||||
}
|
||||
if (player.t_ctype != C_FIGHTER &&
|
||||
player.t_ctype != C_RANGER &&
|
||||
player.t_ctype != C_PALADIN &&
|
||||
obj->o_type == WEAPON &&
|
||||
obj->o_which == TWOSWORD) {
|
||||
switch (rnd(3)) {
|
||||
case 0:
|
||||
msg("Only fighter types can wield the two-handed sword.");
|
||||
when 1:
|
||||
msg("Your hand does not fit the two-handed sword.");
|
||||
otherwise:
|
||||
msg("You can not wield the two-handed sword.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (player.t_ctype != C_FIGHTER &&
|
||||
player.t_ctype != C_ASSASSIN &&
|
||||
player.t_ctype != C_THIEF &&
|
||||
player.t_ctype != C_MONK &&
|
||||
obj->o_type == WEAPON &&
|
||||
obj->o_which == BASWORD) {
|
||||
switch (rnd(3)) {
|
||||
case 0:
|
||||
msg("Only thief types can wield the bastard sword.");
|
||||
when 1:
|
||||
msg("Your hand does not fit the bastard sword.");
|
||||
otherwise:
|
||||
msg("You can not wield the bastard sword.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (terse) {
|
||||
addmsg("W");
|
||||
} else {
|
||||
addmsg("You are now w");
|
||||
}
|
||||
msg("ielding %s", inv_name(obj, TRUE));
|
||||
cur_weapon = obj;
|
||||
}
|
||||
|
||||
438
xrogue/wear.c
Normal file
438
xrogue/wear.c
Normal file
|
|
@ -0,0 +1,438 @@
|
|||
/*
|
||||
wear.c - functions for dealing with armor
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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;
|
||||
|
||||
/* It takes time to take things off */
|
||||
if (player.t_action != C_TAKEOFF) {
|
||||
/* What does player want to take off? */
|
||||
if ((item = get_item(pack, "take off", REMOVABLE, FALSE, FALSE))==NULL)
|
||||
return;
|
||||
|
||||
obj = OBJPTR(item);
|
||||
if (!is_current(obj)) {
|
||||
msg("Not wearing %c) %s", pack_char(pack, obj),inv_name(obj, TRUE));
|
||||
return;
|
||||
}
|
||||
|
||||
player.t_using = item; /* Remember what it is */
|
||||
player.t_action = C_TAKEOFF; /* We are taking something off */
|
||||
|
||||
/* Cursed items take almost no time */
|
||||
if (obj->o_flags & ISCURSED) player.t_no_move = movement(&player);
|
||||
else player.t_no_move = dress_units(item) * movement(&player);
|
||||
return;
|
||||
}
|
||||
|
||||
/* We have waited our time, let's take off our item */
|
||||
item = player.t_using;
|
||||
player.t_using = NULL;
|
||||
player.t_action = A_NIL;
|
||||
|
||||
obj = OBJPTR(item);
|
||||
if (!is_current(obj)) { /* Just to be on the safe side */
|
||||
msg("Not wearing %c) %s", pack_char(pack, obj),inv_name(obj, TRUE));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Can the player remove the item? */
|
||||
if (!dropcheck(obj)) return;
|
||||
updpack(TRUE, &player);
|
||||
|
||||
msg("Was wearing %c) %s", pack_char(pack, obj),inv_name(obj,TRUE));
|
||||
}
|
||||
|
||||
/*
|
||||
* wear:
|
||||
* The player wants to wear something, so let him/her put it on.
|
||||
*/
|
||||
|
||||
wear()
|
||||
{
|
||||
register struct linked_list *item;
|
||||
register struct object *obj;
|
||||
register int i;
|
||||
|
||||
/* It takes time to put things on */
|
||||
if (player.t_action != C_WEAR) {
|
||||
/* What does player want to wear? */
|
||||
if ((item = get_item(pack, "wear", WEARABLE, FALSE, FALSE)) == NULL)
|
||||
return;
|
||||
|
||||
obj = OBJPTR(item);
|
||||
|
||||
switch (obj->o_type) {
|
||||
case ARMOR:
|
||||
if (cur_armor != NULL) {
|
||||
addmsg("You are already wearing armor");
|
||||
if (!terse) addmsg(". You'll have to take it off first.");
|
||||
endmsg();
|
||||
after = FALSE;
|
||||
return;
|
||||
}
|
||||
if (player.t_ctype == C_MONK) {
|
||||
msg("Monks can't wear armor!");
|
||||
return;
|
||||
}
|
||||
if (cur_misc[WEAR_BRACERS] != NULL) {
|
||||
msg("You can't wear armor with bracers of defense.");
|
||||
return;
|
||||
}
|
||||
if (cur_misc[WEAR_CLOAK] != NULL || cur_relic[EMORI_CLOAK]) {
|
||||
msg("You can't wear armor with a cloak.");
|
||||
return;
|
||||
}
|
||||
if (player.t_ctype == C_THIEF &&
|
||||
(obj->o_which != LEATHER &&
|
||||
obj->o_which != STUDDED_LEATHER)) {
|
||||
if (terse) msg("Thieves can't wear that type of armor.");
|
||||
else
|
||||
msg("Thieves can wear leather and studded leather armor.");
|
||||
return;
|
||||
}
|
||||
if (player.t_ctype == C_ASSASSIN &&
|
||||
(obj->o_which != LEATHER &&
|
||||
obj->o_which != STUDDED_LEATHER)) {
|
||||
if (terse) msg("Assassins can't wear that type of armor.");
|
||||
else
|
||||
msg("Assassins can wear leather and studded leather armor.");
|
||||
return;
|
||||
}
|
||||
|
||||
when MM:
|
||||
switch (obj->o_which) {
|
||||
/*
|
||||
* when wearing the boots of elvenkind the player will not
|
||||
* set off any traps
|
||||
*/
|
||||
case MM_ELF_BOOTS:
|
||||
if (cur_misc[WEAR_BOOTS] != NULL) {
|
||||
msg("Already wearing a pair of boots. ");
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* when wearing the boots of dancing the player will dance
|
||||
* uncontrollably
|
||||
*/
|
||||
when MM_DANCE:
|
||||
if (cur_misc[WEAR_BOOTS] != NULL) {
|
||||
msg("Already wearing a pair of boots.");
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* bracers give the hero protection in he same way armor does.
|
||||
* they cannot be used with armor but can be used with cloaks
|
||||
*/
|
||||
when MM_BRACERS:
|
||||
if (cur_misc[WEAR_BRACERS] != NULL) {
|
||||
msg("Already wearing bracers.");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (cur_armor != NULL) {
|
||||
msg("You can't wear bracers of defense with armor.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The robe (cloak) of powerlessness disallows any spell casting
|
||||
*/
|
||||
when MM_R_POWERLESS:
|
||||
/*
|
||||
* the cloak of displacement gives the hero an extra +2 on AC
|
||||
* and saving throws. Cloaks cannot be used with armor.
|
||||
*/
|
||||
case MM_DISP:
|
||||
/*
|
||||
* the cloak of protection gives the hero +n on AC and saving
|
||||
* throws with a max of +3 on saves
|
||||
*/
|
||||
case MM_PROTECT:
|
||||
if (cur_misc[WEAR_CLOAK] != NULL ||
|
||||
cur_relic[EMORI_CLOAK]) {
|
||||
msg("%slready wearing a cloak.", terse ? "A"
|
||||
: "You are a");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (cur_armor != NULL) {
|
||||
msg("You can't wear a cloak with armor.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* the gauntlets of dexterity and ogre power give the hero
|
||||
* a dexterity of 21, the gauntlets of fumbling cause the
|
||||
* hero to drop his weapon.
|
||||
*/
|
||||
when MM_G_DEXTERITY:
|
||||
case MM_G_OGRE:
|
||||
case MM_FUMBLE:
|
||||
if (cur_misc[WEAR_GAUNTLET] != NULL) {
|
||||
msg("Already wearing a pair of gauntlets.");
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* the jewel of attacks does an aggavate monster
|
||||
*/
|
||||
when MM_JEWEL:
|
||||
if (cur_misc[WEAR_JEWEL] != NULL ||
|
||||
cur_relic[YENDOR_AMULET] ||
|
||||
cur_relic[STONEBONES_AMULET]) {
|
||||
msg("Already wearing an amulet.");
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* the necklace of adaption makes the hero immune to
|
||||
* chlorine gas and acid breath.
|
||||
*/
|
||||
when MM_ADAPTION:
|
||||
if (cur_misc[WEAR_NECKLACE] != NULL) {
|
||||
msg("Already wearing a necklace.");
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* the necklace of stragulation will try to strangle the
|
||||
* hero to death
|
||||
*/
|
||||
when MM_STRANGLE:
|
||||
if (cur_misc[WEAR_NECKLACE] != NULL) {
|
||||
msg("Already wearing a necklace.");
|
||||
return;
|
||||
}
|
||||
otherwise:
|
||||
msg("What a strange item you have!");
|
||||
return;
|
||||
}
|
||||
|
||||
when RING:
|
||||
if (cur_misc[WEAR_GAUNTLET] != NULL) {
|
||||
msg ("You have to remove your gauntlets first!");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Is there room to put the ring on */
|
||||
for (i=0; i<NUM_FINGERS; i++)
|
||||
if (cur_ring[i] == NULL) {
|
||||
break;
|
||||
}
|
||||
if (i == NUM_FINGERS) { /* Not enough fingers */
|
||||
if (terse) msg("Wearing enough rings.");
|
||||
else msg("You are already wearing eight rings.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
player.t_using = item; /* Remember what it is */
|
||||
player.t_action = C_WEAR; /* We are taking something off */
|
||||
player.t_no_move = dress_units(item) * movement(&player);
|
||||
return;
|
||||
}
|
||||
|
||||
/* We have waited our time, let's put on our item */
|
||||
item = player.t_using;
|
||||
player.t_using = NULL;
|
||||
player.t_action = A_NIL;
|
||||
|
||||
obj = OBJPTR(item);
|
||||
|
||||
switch (obj->o_type) {
|
||||
case ARMOR:
|
||||
obj->o_flags |= ISKNOW;
|
||||
cur_armor = obj;
|
||||
addmsg(terse ? "W" : "You are now w");
|
||||
msg("earing %s.", armors[obj->o_which].a_name);
|
||||
|
||||
when MM:
|
||||
switch (obj->o_which) {
|
||||
/*
|
||||
* when wearing the boots of elvenkind the player will not
|
||||
* set off any traps
|
||||
*/
|
||||
case MM_ELF_BOOTS:
|
||||
msg("Wearing %s",inv_name(obj,TRUE));
|
||||
cur_misc[WEAR_BOOTS] = obj;
|
||||
/*
|
||||
* when wearing the boots of dancing the player will dance
|
||||
* uncontrollably
|
||||
*/
|
||||
when MM_DANCE:
|
||||
msg("Wearing %s",inv_name(obj,TRUE));
|
||||
cur_misc[WEAR_BOOTS] = obj;
|
||||
msg("You begin to dance uncontrollably!");
|
||||
turn_on(player, ISDANCE);
|
||||
/*
|
||||
* bracers give the hero protection in he same way armor does.
|
||||
* they cannot be used with armor but can be used with cloaks
|
||||
*/
|
||||
when MM_BRACERS:
|
||||
msg("wearing %s",inv_name(obj,TRUE));
|
||||
cur_misc[WEAR_BRACERS] = obj;
|
||||
|
||||
/*
|
||||
* The robe (cloak) of powerlessness disallows any spell casting
|
||||
*/
|
||||
when MM_R_POWERLESS:
|
||||
/*
|
||||
* the cloak of displacement gives the hero an extra +2 on AC
|
||||
* and saving throws. Cloaks cannot be used with armor.
|
||||
*/
|
||||
case MM_DISP:
|
||||
/*
|
||||
* the cloak of protection gives the hero +n on AC and saving
|
||||
* throws with a max of +3 on saves
|
||||
*/
|
||||
case MM_PROTECT:
|
||||
msg("wearing %s",inv_name(obj,TRUE));
|
||||
cur_misc[WEAR_CLOAK] = obj;
|
||||
/*
|
||||
* the gauntlets of dexterity and ogre power give the hero
|
||||
* a dexterity of 21, the gauntlets of fumbling cause the
|
||||
* hero to drop his weapon.
|
||||
*/
|
||||
when MM_G_DEXTERITY:
|
||||
case MM_G_OGRE:
|
||||
case MM_FUMBLE:
|
||||
msg("Wearing %s", inv_name(obj,TRUE));
|
||||
cur_misc[WEAR_GAUNTLET] = obj;
|
||||
if (obj->o_which == MM_FUMBLE)
|
||||
daemon(fumble, (VOID *)NULL, AFTER);
|
||||
/*
|
||||
* the jewel of attacks does an aggavate monster
|
||||
*/
|
||||
when MM_JEWEL:
|
||||
msg("Wearing %s",inv_name(obj,TRUE));
|
||||
cur_misc[WEAR_JEWEL] = obj;
|
||||
aggravate(TRUE, TRUE); /* affect all charactors */
|
||||
if (player.t_ctype == C_PALADIN ||
|
||||
player.t_ctype == C_RANGER || player.t_ctype == C_MONK)
|
||||
msg("A chill runs down your spine! ");
|
||||
|
||||
/*
|
||||
* the necklace of adaption makes the hero immune to
|
||||
* chlorine gas and acid
|
||||
*/
|
||||
when MM_ADAPTION:
|
||||
msg("Wearing %s",inv_name(obj,TRUE));
|
||||
cur_misc[WEAR_NECKLACE] = obj;
|
||||
turn_on(player, NOGAS);
|
||||
turn_on(player, NOACID);
|
||||
|
||||
/*
|
||||
* the necklace of stragulation will try to strangle the
|
||||
* hero to death
|
||||
*/
|
||||
when MM_STRANGLE:
|
||||
msg("Wearing %s",inv_name(obj,TRUE));
|
||||
cur_misc[WEAR_NECKLACE] = obj;
|
||||
msg("The necklace is beginning to strangle you!");
|
||||
daemon(strangle, (VOID *)NULL, AFTER);
|
||||
otherwise:
|
||||
msg("What a strange item you have!");
|
||||
}
|
||||
status(FALSE);
|
||||
if (m_know[obj->o_which] && m_guess[obj->o_which]) {
|
||||
free(m_guess[obj->o_which]);
|
||||
m_guess[obj->o_which] = NULL;
|
||||
}
|
||||
else if (!m_know[obj->o_which] &&
|
||||
askme &&
|
||||
(obj->o_flags & ISKNOW) == 0 &&
|
||||
m_guess[obj->o_which] == NULL) {
|
||||
nameitem(item, FALSE);
|
||||
}
|
||||
|
||||
when RING:
|
||||
/* If there is room, put on the ring */
|
||||
for (i=0; i<NUM_FINGERS; i++)
|
||||
if (cur_ring[i] == NULL) {
|
||||
cur_ring[i] = obj;
|
||||
break;
|
||||
}
|
||||
if (i == NUM_FINGERS) { /* Not enough fingers */
|
||||
if (terse) msg("Wearing enough rings.");
|
||||
else msg("You are already wearing eight rings.");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Calculate the effect of the ring */
|
||||
ring_on(item);
|
||||
}
|
||||
updpack(TRUE, &player);
|
||||
}
|
||||
|
||||
/*
|
||||
* dress_units:
|
||||
* How many movements periods does it take to put on or remove the
|
||||
* given item of "clothing"?
|
||||
*/
|
||||
|
||||
dress_units(item)
|
||||
struct linked_list *item;
|
||||
{
|
||||
register struct object *obj;
|
||||
|
||||
obj = OBJPTR(item);
|
||||
|
||||
switch (obj->o_type) {
|
||||
case ARMOR:
|
||||
return(10-armors[obj->o_which].a_class);
|
||||
when RING:
|
||||
return(2);
|
||||
when MM:
|
||||
switch (obj->o_which) {
|
||||
case MM_ELF_BOOTS:
|
||||
case MM_DANCE:
|
||||
/* Boots */
|
||||
return(5);
|
||||
when MM_R_POWERLESS:
|
||||
case MM_DISP:
|
||||
case MM_PROTECT:
|
||||
/* Robes */
|
||||
return(4);
|
||||
when MM_BRACERS:
|
||||
case MM_G_DEXTERITY:
|
||||
case MM_G_OGRE:
|
||||
case MM_FUMBLE:
|
||||
/* Hand garments */
|
||||
return(3);
|
||||
when MM_JEWEL:
|
||||
case MM_ADAPTION:
|
||||
case MM_STRANGLE:
|
||||
/* Jewelry */
|
||||
return(2);
|
||||
otherwise:
|
||||
return(1); /* What is it? */
|
||||
}
|
||||
otherwise:
|
||||
return(1); /* What is it? */
|
||||
}
|
||||
}
|
||||
|
||||
819
xrogue/wizard.c
Normal file
819
xrogue/wizard.c
Normal file
|
|
@ -0,0 +1,819 @@
|
|||
/*
|
||||
wizard.c - Special wizard commands
|
||||
|
||||
XRogue: Expeditions into the Dungeons of Doom
|
||||
Copyright (C) 1991 Robert Pietkivitch
|
||||
All rights reserved.
|
||||
|
||||
Based on "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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Special wizard commands (some of which are also non-wizard commands
|
||||
* under strange circumstances)
|
||||
*/
|
||||
|
||||
#include <curses.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "rogue.h"
|
||||
#include "mach_dep.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;
|
||||
char *pt;
|
||||
reg int ch, whc, newtype = 0, msz, newitem;
|
||||
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);
|
||||
wprintw(hw,"monster\t\t\tm");
|
||||
}
|
||||
wprintw(hw,"\n\nWhat do you want to create? ");
|
||||
draw(hw);
|
||||
do {
|
||||
ch = wgetch(hw);
|
||||
if (ch == ESC) {
|
||||
restscr(cw);
|
||||
return;
|
||||
}
|
||||
switch (ch) {
|
||||
case RING:
|
||||
case STICK:
|
||||
case POTION:
|
||||
case SCROLL:
|
||||
case ARMOR:
|
||||
case WEAPON:
|
||||
case FOOD:
|
||||
case MM:
|
||||
nogood = FALSE;
|
||||
break;
|
||||
case RELIC:
|
||||
case 'm':
|
||||
if (wizard)
|
||||
nogood = FALSE;
|
||||
break;
|
||||
default:
|
||||
nogood = TRUE;
|
||||
}
|
||||
} while (nogood);
|
||||
newitem = ch;
|
||||
}
|
||||
else
|
||||
newitem = which_item;
|
||||
|
||||
pt = "those";
|
||||
msz = 0;
|
||||
if(newitem == 'm') {
|
||||
/* make monster and be done with it */
|
||||
wh = makemonster(TRUE, "create");
|
||||
if (wh > 0) {
|
||||
creat_mons (&player, wh, TRUE);
|
||||
light(&hero);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(newitem == GOLD) pt = "gold";
|
||||
else if(isatrap(newitem)) pt = "traps";
|
||||
|
||||
switch(newitem) {
|
||||
case POTION: whc = TYP_POTION; msz = MAXPOTIONS;
|
||||
when SCROLL: whc = TYP_SCROLL; msz = MAXSCROLLS;
|
||||
when WEAPON: whc = TYP_WEAPON; msz = MAXWEAPONS;
|
||||
when ARMOR: whc = TYP_ARMOR; msz = MAXARMORS;
|
||||
when RING: whc = TYP_RING; msz = MAXRINGS;
|
||||
when STICK: whc = TYP_STICK; msz = MAXSTICKS;
|
||||
when MM: whc = TYP_MM; msz = MAXMM;
|
||||
when RELIC: whc = TYP_RELIC; msz = MAXRELIC;
|
||||
when FOOD: whc = TYP_FOOD; msz = MAXFOODS;
|
||||
otherwise:
|
||||
if (thiswin == hw)
|
||||
restscr(cw);
|
||||
mpos = 0;
|
||||
msg("Even wizards can't create %s !!",pt);
|
||||
return;
|
||||
}
|
||||
if(msz == 1) { /* if only one type of item */
|
||||
ch = 'a';
|
||||
}
|
||||
else if (prompt) {
|
||||
register struct magic_item *wmi;
|
||||
char wmn;
|
||||
register int ii;
|
||||
int old_prob;
|
||||
|
||||
mpos = 0;
|
||||
wmi = NULL;
|
||||
wmn = 0;
|
||||
switch(newitem) {
|
||||
case POTION: wmi = &p_magic[0];
|
||||
when SCROLL: wmi = &s_magic[0];
|
||||
when RING: wmi = &r_magic[0];
|
||||
when STICK: wmi = &ws_magic[0];
|
||||
when MM: wmi = &m_magic[0];
|
||||
when RELIC: wmi = &rel_magic[0];
|
||||
when FOOD: wmi = &foods[0];
|
||||
when WEAPON: wmn = 1;
|
||||
when ARMOR: wmn = 2;
|
||||
}
|
||||
wclear(hw);
|
||||
thiswin = hw;
|
||||
if (wmi != NULL) {
|
||||
ii = old_prob = 0;
|
||||
while (ii < msz) {
|
||||
if(wmi->mi_prob == old_prob && wizard == FALSE) {
|
||||
msz--; /* can't make a unique item */
|
||||
}
|
||||
else {
|
||||
mvwaddch(hw,ii % 13,ii > 12 ? cols/2 : 0, ii + 'a');
|
||||
waddstr(hw,") ");
|
||||
waddstr(hw,wmi->mi_name);
|
||||
ii++;
|
||||
}
|
||||
old_prob = wmi->mi_prob;
|
||||
wmi++;
|
||||
}
|
||||
}
|
||||
else if (wmn != 0) {
|
||||
for(ii = 0 ; ii < msz ; ii++) {
|
||||
mvwaddch(hw,ii % 13,ii > 12 ? cols/2 : 0, ii + 'a');
|
||||
waddstr(hw,") ");
|
||||
if(wmn == 1)
|
||||
waddstr(hw,weaps[ii].w_name);
|
||||
else
|
||||
waddstr(hw,armors[ii].a_name);
|
||||
}
|
||||
}
|
||||
sprintf(prbuf,"Which %s? ",things[whc].mi_name);
|
||||
mvwaddstr(hw,lines - 1, 0, prbuf);
|
||||
draw(hw);
|
||||
do {
|
||||
ch = wgetch(hw);
|
||||
if (ch == ESC) {
|
||||
restscr(cw);
|
||||
msg("");
|
||||
return;
|
||||
}
|
||||
} until (isalpha(ch));
|
||||
if (thiswin == hw) /* restore screen if need be */
|
||||
restscr(cw);
|
||||
newtype = 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 +5 */
|
||||
whc = rnd(6);
|
||||
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;
|
||||
if (!wizard) whc = rnd(6);
|
||||
obj->o_dplus += whc;
|
||||
}
|
||||
else { /* armor here */
|
||||
obj->o_weight = armors[wh].a_wght;
|
||||
obj->o_ac = armors[wh].a_class - whc;
|
||||
}
|
||||
when RING:
|
||||
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 + 2;
|
||||
break;
|
||||
default:
|
||||
obj->o_ac = 0;
|
||||
}
|
||||
obj->o_weight = things[TYP_RING].mi_wght;
|
||||
when MM:
|
||||
if (whc > 1 && m_magic[wh].mi_bless != 0)
|
||||
obj->o_flags |= ISBLESSED;
|
||||
m_know[wh] = TRUE;
|
||||
switch(wh) {
|
||||
case MM_JUG:
|
||||
switch(rnd(11)) {
|
||||
case 0: obj->o_ac = P_PHASE;
|
||||
when 1: obj->o_ac = P_CLEAR;
|
||||
when 2: obj->o_ac = P_SEEINVIS;
|
||||
when 3: obj->o_ac = P_HEALING;
|
||||
when 4: obj->o_ac = P_MFIND;
|
||||
when 5: obj->o_ac = P_TFIND;
|
||||
when 6: obj->o_ac = P_HASTE;
|
||||
when 7: obj->o_ac = P_RESTORE;
|
||||
when 8: obj->o_ac = P_FLY;
|
||||
when 9: obj->o_ac = P_SKILL;
|
||||
when 10:obj->o_ac = P_FFIND;
|
||||
}
|
||||
when MM_HUNGER:
|
||||
case MM_CHOKE:
|
||||
if (whc < 0 )
|
||||
whc = -whc; /* cannot be negative */
|
||||
obj->o_ac = (whc + 1) * 2;
|
||||
break;
|
||||
when MM_OPEN:
|
||||
case MM_DRUMS:
|
||||
case MM_DISAPPEAR:
|
||||
case MM_KEOGHTOM:
|
||||
if (whc < 0)
|
||||
whc = -whc; /* these cannot be negative */
|
||||
obj->o_ac = (whc + 3) * 5;
|
||||
break;
|
||||
when MM_BRACERS:
|
||||
obj->o_ac = whc + 4;
|
||||
when MM_DISP:
|
||||
obj->o_ac = 3;
|
||||
when MM_PROTECT:
|
||||
obj->o_ac = whc + 4;
|
||||
when MM_SKILLS:
|
||||
if (whc < 2)
|
||||
obj->o_ac = rnd(NUM_CHARTYPES-1);
|
||||
else
|
||||
obj->o_ac = player.t_ctype;
|
||||
when MM_CRYSTAL:
|
||||
obj->o_ac = 1;
|
||||
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 > 3 && 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 > 3 && p_magic[wh].mi_bless != 0)
|
||||
obj->o_flags |= ISBLESSED;
|
||||
obj->o_weight = things[TYP_POTION].mi_wght;
|
||||
if (wh == P_ABIL) obj->o_kind = rnd(NUMABILITIES);
|
||||
p_know[wh] = TRUE;
|
||||
when RELIC:
|
||||
obj->o_weight = things[TYP_RELIC].mi_wght;
|
||||
switch (obj->o_which) {
|
||||
case QUILL_NAGROM: obj->o_charges = QUILLCHARGES;
|
||||
when EMORI_CLOAK: obj->o_charges = 1;
|
||||
otherwise: break;
|
||||
}
|
||||
when FOOD:
|
||||
obj->o_weight = things[TYP_FOOD].mi_wght;
|
||||
}
|
||||
mpos = 0;
|
||||
obj->o_flags |= ISKNOW;
|
||||
if (add_pack(item, FALSE) == FALSE) {
|
||||
obj->o_pos = hero;
|
||||
fall(item, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* getbless:
|
||||
* Get a blessing for a wizards object
|
||||
*/
|
||||
|
||||
int
|
||||
getbless()
|
||||
{
|
||||
reg char bless;
|
||||
|
||||
msg("Blessing? (+,-,n)");
|
||||
bless = wgetch(msgw);
|
||||
if (bless == '+')
|
||||
return (15);
|
||||
else if (bless == '-')
|
||||
return (-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(showall, action)
|
||||
bool showall; /* showall -> show uniques and genocided creatures */
|
||||
char *action;
|
||||
{
|
||||
register int i;
|
||||
register short which_monst;
|
||||
register int num_monst = NUMMONST, pres_monst=1, num_lines=2*(lines-3);
|
||||
int max_monster;
|
||||
char monst_name[40];
|
||||
|
||||
/* If we're not showing all, subtract UNIQUES, DINOS, and quartermaster */
|
||||
if (!showall) num_monst -= NUMUNIQUE + NUMDINOS + 1;
|
||||
max_monster = num_monst;
|
||||
|
||||
/* Print out the monsters */
|
||||
|
||||
if (levtype == OUTSIDE) {
|
||||
num_monst = NUMDINOS;
|
||||
max_monster = NUMMONST - 1;
|
||||
pres_monst = (pres_monst + NUMMONST - NUMDINOS - 1);
|
||||
}
|
||||
|
||||
while (num_monst > 0) {
|
||||
register int left_limit;
|
||||
|
||||
if (num_monst < num_lines) left_limit = (num_monst+1)/2;
|
||||
else left_limit = num_lines/2;
|
||||
|
||||
wclear(hw);
|
||||
touchwin(hw);
|
||||
|
||||
/* Print left column */
|
||||
wmove(hw, 2, 0);
|
||||
for (i=0; i<left_limit; i++) {
|
||||
sprintf(monst_name, "[%d] %c%s\n",
|
||||
pres_monst,
|
||||
(showall || monsters[pres_monst].m_normal)
|
||||
? ' '
|
||||
: '*',
|
||||
monsters[pres_monst].m_name);
|
||||
waddstr(hw, monst_name);
|
||||
pres_monst++;
|
||||
}
|
||||
|
||||
/* Print right column */
|
||||
for (i=0; i<left_limit && pres_monst<=max_monster; i++) {
|
||||
sprintf(monst_name, "[%d] %c%s",
|
||||
pres_monst,
|
||||
(showall || monsters[pres_monst].m_normal)
|
||||
? ' '
|
||||
: '*',
|
||||
monsters[pres_monst].m_name);
|
||||
wmove(hw, i+2, cols/2);
|
||||
waddstr(hw, monst_name);
|
||||
pres_monst++;
|
||||
}
|
||||
|
||||
if ((num_monst -= num_lines) > 0) {
|
||||
mvwaddstr(hw, lines-1, 0, morestr);
|
||||
draw(hw);
|
||||
wait_for(' ');
|
||||
}
|
||||
|
||||
else {
|
||||
mvwaddstr(hw, 0, 0, "Which monster");
|
||||
if (!terse) {
|
||||
waddstr(hw, " do you wish to ");
|
||||
waddstr(hw, action);
|
||||
}
|
||||
waddstr(hw, "? ");
|
||||
draw(hw);
|
||||
}
|
||||
}
|
||||
|
||||
get_monst:
|
||||
get_str(monst_name, hw);
|
||||
which_monst = atoi(monst_name);
|
||||
if (levtype == OUTSIDE)
|
||||
if ((which_monst < NUMMONST-NUMDINOS || which_monst > max_monster)) {
|
||||
mvwaddstr(hw, 0, 0, "Please enter a number in the displayed range -- ");
|
||||
draw(hw);
|
||||
goto get_monst;
|
||||
}
|
||||
if ((which_monst < 1 || which_monst > max_monster)) {
|
||||
mvwaddstr(hw, 0, 0, "Please enter a number in the displayed range -- ");
|
||||
draw(hw);
|
||||
goto get_monst;
|
||||
}
|
||||
restscr(cw);
|
||||
return(which_monst);
|
||||
}
|
||||
|
||||
/*
|
||||
* passwd:
|
||||
* see if user knows password
|
||||
*/
|
||||
|
||||
bool
|
||||
passwd()
|
||||
{
|
||||
register char *sp, c;
|
||||
char buf[LINELEN];
|
||||
|
||||
msg("Wizard's Password:");
|
||||
mpos = 0;
|
||||
sp = buf;
|
||||
while ((c = wgetch(cw)) != '\n' && c != '\r' && c != '\033') {
|
||||
if (c == killchar())
|
||||
sp = buf;
|
||||
else if (c == erasechar() && sp > buf)
|
||||
sp--;
|
||||
else
|
||||
*sp++ = c;
|
||||
}
|
||||
if (sp == buf)
|
||||
return FALSE;
|
||||
*sp = '\0';
|
||||
return (strcmp(PASSWD, xcrypt(buf, "mT")) == 0);
|
||||
|
||||
/* don't mess with the password here or elsewhere.
|
||||
*
|
||||
* If anyone goes wizard they forfeit being placed in the scorefile.
|
||||
* So, no need to be secretive about it. Let them have it!
|
||||
*
|
||||
* Additionally, you can begin the game as wizard by starting it
|
||||
* with a null argument, as in: xrogue ""
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* teleport:
|
||||
* Bamf the hero someplace else
|
||||
*/
|
||||
|
||||
void
|
||||
teleport()
|
||||
{
|
||||
register struct room *new_rp = NULL, *old_rp = roomin(&hero);
|
||||
register int rm, which;
|
||||
coord old;
|
||||
bool got_position = FALSE;
|
||||
|
||||
/* Disrupt whatever the hero was doing */
|
||||
dsrpt_player();
|
||||
|
||||
/*
|
||||
* If the hero wasn't doing something disruptable, NULL out his
|
||||
* action anyway and let him know about it. We don't want him
|
||||
* swinging or moving into his old place.
|
||||
*/
|
||||
if (player.t_action != A_NIL) {
|
||||
player.t_action = A_NIL;
|
||||
msg("You feel momentarily disoriented.");
|
||||
}
|
||||
|
||||
old = hero;
|
||||
mvwaddch(cw, hero.y, hero.x, mvwinch(stdscr, hero.y, hero.x));
|
||||
if (ISWEARING(R_TELCONTROL) || wizard) {
|
||||
got_position = move_hero(H_TELEPORT);
|
||||
if (!got_position)
|
||||
msg("Your attempt fails.");
|
||||
else {
|
||||
new_rp = roomin(&hero);
|
||||
msg("You teleport successfully.");
|
||||
}
|
||||
}
|
||||
if (!got_position) {
|
||||
do {
|
||||
rm = rnd_room();
|
||||
rnd_pos(&rooms[rm], &hero);
|
||||
} until(winat(hero.y, hero.x) == FLOOR);
|
||||
new_rp = &rooms[rm];
|
||||
}
|
||||
player.t_oldpos = old; /* Save last position */
|
||||
|
||||
/* If hero gets moved, darken old room */
|
||||
if (old_rp && old_rp != new_rp) {
|
||||
old_rp->r_flags |= FORCEDARK; /* Fake darkness */
|
||||
light(&old);
|
||||
old_rp->r_flags &= ~FORCEDARK; /* Restore light state */
|
||||
}
|
||||
|
||||
/* Darken where we just came from */
|
||||
else if (levtype == MAZELEV) light(&old);
|
||||
|
||||
light(&hero);
|
||||
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
||||
/* if entering a treasure room, wake everyone up......Surprise! */
|
||||
if (new_rp->r_flags & ISTREAS)
|
||||
wake_room(new_rp);
|
||||
|
||||
/* Reset current room and position */
|
||||
oldrp = new_rp; /* Used in look() */
|
||||
player.t_oldpos = hero;
|
||||
/*
|
||||
* make sure we set/unset the ISINWALL on a teleport
|
||||
*/
|
||||
which = winat(hero.y, hero.x);
|
||||
if (isrock(which)) turn_on(player, ISINWALL);
|
||||
else turn_off(player, ISINWALL);
|
||||
|
||||
/*
|
||||
* turn off ISHELD in case teleportation was done while fighting
|
||||
* something that holds you
|
||||
*/
|
||||
if (on(player, ISHELD)) {
|
||||
register struct linked_list *ip, *nip;
|
||||
register struct thing *mp;
|
||||
|
||||
turn_off(player, ISHELD);
|
||||
hold_count = 0;
|
||||
for (ip = mlist; ip; ip = nip) {
|
||||
mp = THINGPTR(ip);
|
||||
nip = next(ip);
|
||||
if (on(*mp, DIDHOLD)) {
|
||||
turn_off(*mp, DIDHOLD);
|
||||
turn_on(*mp, CANHOLD);
|
||||
}
|
||||
turn_off(*mp, DIDSUFFOCATE); /* Suffocation -- see below */
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure player does not suffocate */
|
||||
extinguish(suffocate);
|
||||
|
||||
count = 0;
|
||||
running = FALSE;
|
||||
flushinp();
|
||||
}
|
||||
|
||||
/*
|
||||
* whatis:
|
||||
* What a certin object is
|
||||
*/
|
||||
|
||||
whatis(what)
|
||||
struct linked_list *what;
|
||||
{
|
||||
register struct object *obj;
|
||||
register struct linked_list *item;
|
||||
|
||||
if (what == NULL) { /* do we need to ask which one? */
|
||||
if ((item = get_item(pack, "identify", IDENTABLE, FALSE, FALSE))==NULL)
|
||||
return;
|
||||
}
|
||||
else
|
||||
item = what;
|
||||
obj = OBJPTR(item);
|
||||
switch (obj->o_type) {
|
||||
case SCROLL:
|
||||
s_know[obj->o_which] = TRUE;
|
||||
if (s_guess[obj->o_which]) {
|
||||
free(s_guess[obj->o_which]);
|
||||
s_guess[obj->o_which] = NULL;
|
||||
}
|
||||
when POTION:
|
||||
p_know[obj->o_which] = TRUE;
|
||||
if (p_guess[obj->o_which]) {
|
||||
free(p_guess[obj->o_which]);
|
||||
p_guess[obj->o_which] = NULL;
|
||||
}
|
||||
when STICK:
|
||||
ws_know[obj->o_which] = TRUE;
|
||||
if (ws_guess[obj->o_which]) {
|
||||
free(ws_guess[obj->o_which]);
|
||||
ws_guess[obj->o_which] = NULL;
|
||||
}
|
||||
when RING:
|
||||
r_know[obj->o_which] = TRUE;
|
||||
if (r_guess[obj->o_which]) {
|
||||
free(r_guess[obj->o_which]);
|
||||
r_guess[obj->o_which] = NULL;
|
||||
}
|
||||
when MM:
|
||||
/* If it's an identified jug, identify its potion */
|
||||
if (obj->o_which == MM_JUG && (obj->o_flags & ISKNOW)) {
|
||||
if (obj->o_ac != JUG_EMPTY)
|
||||
p_know[obj->o_ac] = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
m_know[obj->o_which] = TRUE;
|
||||
if (m_guess[obj->o_which]) {
|
||||
free(m_guess[obj->o_which]);
|
||||
m_guess[obj->o_which] = NULL;
|
||||
}
|
||||
otherwise:
|
||||
break;
|
||||
}
|
||||
obj->o_flags |= ISKNOW;
|
||||
if (what == NULL)
|
||||
msg(inv_name(obj, FALSE));
|
||||
}
|
||||
|
||||
/*
|
||||
* Choose a quest item
|
||||
* (if on STARTLEV equipage level = 0)
|
||||
*/
|
||||
|
||||
choose_qst()
|
||||
{
|
||||
bool doit = TRUE;
|
||||
bool escp = TRUE;
|
||||
|
||||
/* let wizard in on this too */
|
||||
if (waswizard == TRUE || (levtype == POSTLEV && level == 0)) {
|
||||
wclear(hw);
|
||||
touchwin(hw);
|
||||
wmove(hw, 2, 0);
|
||||
wprintw(hw, "a) Cloak of Emori\n");
|
||||
wprintw(hw, "b) Ankh of Heil\n");
|
||||
wprintw(hw, "c) Quill of Nagrom\n");
|
||||
wprintw(hw, "d) Eye of Vecna\n");
|
||||
wprintw(hw, "e) Ring of Surtur\n");
|
||||
wprintw(hw, "f) Staff of Ming\n");
|
||||
wprintw(hw, "g) Wand of Orcus\n");
|
||||
wprintw(hw, "h) Rod of Asmodeus\n");
|
||||
wprintw(hw, "i) Amulet of Yendor\n");
|
||||
wprintw(hw, "j) Amulet of Stonebones\n");
|
||||
wprintw(hw, "k) Mandolin of Brian\n");
|
||||
wprintw(hw, "l) Horn of Geryon\n");
|
||||
wprintw(hw, "m) Daggers of Musty Doit\n");
|
||||
wprintw(hw, "n) Axe of Aklad\n");
|
||||
wprintw(hw, "o) Morning Star of Hruggek\n");
|
||||
wprintw(hw, "p) Flail of Yeenoghu\n");
|
||||
wprintw(hw, "q) Card of Alteran\n");
|
||||
mvwaddstr(hw, 0, 0, "Select a quest item: "); /* prompt */
|
||||
|
||||
if (menu_overlay) /* Print the selections. The longest line is
|
||||
* Hruggek (26 characters). The prompt is 21.
|
||||
*/
|
||||
over_win(cw, hw, 20, 29, 0, 21, NULL);
|
||||
else
|
||||
draw(hw);
|
||||
|
||||
while (doit) {
|
||||
switch (wgetch(cw)) {
|
||||
case EOF:
|
||||
case ESC:
|
||||
escp = FALSE; /* used below */
|
||||
doit = FALSE;
|
||||
when 'a':
|
||||
quest_item = EMORI_CLOAK;
|
||||
doit = FALSE;
|
||||
when 'b':
|
||||
quest_item = HEIL_ANKH;
|
||||
doit = FALSE;
|
||||
when 'c':
|
||||
quest_item = QUILL_NAGROM;
|
||||
doit = FALSE;
|
||||
when 'd':
|
||||
quest_item = EYE_VECNA;
|
||||
doit = FALSE;
|
||||
when 'e':
|
||||
quest_item = SURTUR_RING;
|
||||
doit = FALSE;
|
||||
when 'f':
|
||||
quest_item = MING_STAFF;
|
||||
doit = FALSE;
|
||||
when 'g':
|
||||
quest_item = ORCUS_WAND;
|
||||
doit = FALSE;
|
||||
when 'h':
|
||||
quest_item = ASMO_ROD;
|
||||
doit = FALSE;
|
||||
when 'i':
|
||||
quest_item = YENDOR_AMULET;
|
||||
doit = FALSE;
|
||||
when 'j':
|
||||
quest_item = STONEBONES_AMULET;
|
||||
doit = FALSE;
|
||||
when 'k':
|
||||
quest_item = BRIAN_MANDOLIN;
|
||||
doit = FALSE;
|
||||
when 'l':
|
||||
quest_item = GERYON_HORN;
|
||||
doit = FALSE;
|
||||
when 'm':
|
||||
quest_item = MUSTY_DAGGER;
|
||||
doit = FALSE;
|
||||
when 'n':
|
||||
quest_item = AXE_AKLAD;
|
||||
doit = FALSE;
|
||||
when 'o':
|
||||
quest_item = HRUGGEK_MSTAR;
|
||||
doit = FALSE;
|
||||
when 'p':
|
||||
quest_item = YEENOGHU_FLAIL;
|
||||
doit = FALSE;
|
||||
when 'q':
|
||||
quest_item = ALTERAN_CARD;
|
||||
doit = FALSE;
|
||||
otherwise:
|
||||
doit = TRUE;
|
||||
}
|
||||
}
|
||||
if (menu_overlay) {
|
||||
status(FALSE);
|
||||
touchwin(cw);
|
||||
if (escp == TRUE) {
|
||||
msg("Your quest item is the %s. --More--",
|
||||
rel_magic[quest_item].mi_name);
|
||||
wait_for(' ');
|
||||
}
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (escp == TRUE) {
|
||||
wmove(hw, lines-4, 0);
|
||||
wprintw(hw, "Your quest item is the %s.",
|
||||
rel_magic[quest_item].mi_name);
|
||||
}
|
||||
wmove(hw, lines-1, 0);
|
||||
wprintw(hw, spacemsg);
|
||||
draw(hw);
|
||||
wait_for(' ');
|
||||
wclear(hw);
|
||||
draw(hw);
|
||||
wmove(cw, 0, 0);
|
||||
wclrtoeol(cw);
|
||||
status(FALSE);
|
||||
touchwin(cw);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
msg("You can no longer select a quest item. ");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
691
xrogue/xcrypt.c
Normal file
691
xrogue/xcrypt.c
Normal file
|
|
@ -0,0 +1,691 @@
|
|||
/*
|
||||
* 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>
|
||||
|
||||
#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);
|
||||
}
|
||||
21
xrogue/xrogue.sln
Executable file
21
xrogue/xrogue.sln
Executable file
|
|
@ -0,0 +1,21 @@
|
|||
Microsoft Visual Studio Solution File, Format Version 7.00
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xrogue", "xrogue.vcproj", "{ABD49D61-EFA9-41BA-9EA1-8DE4B4FA4FF6}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
ConfigName.0 = Debug
|
||||
ConfigName.1 = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectDependencies) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{ABD49D61-EFA9-41BA-9EA1-8DE4B4FA4FF6}.Debug.ActiveCfg = Debug|Win32
|
||||
{ABD49D61-EFA9-41BA-9EA1-8DE4B4FA4FF6}.Debug.Build.0 = Debug|Win32
|
||||
{ABD49D61-EFA9-41BA-9EA1-8DE4B4FA4FF6}.Release.ActiveCfg = Release|Win32
|
||||
{ABD49D61-EFA9-41BA-9EA1-8DE4B4FA4FF6}.Release.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
278
xrogue/xrogue.vcproj
Executable file
278
xrogue/xrogue.vcproj
Executable file
|
|
@ -0,0 +1,278 @@
|
|||
<?xml version="1.0" encoding = "Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.00"
|
||||
Name="xrogue"
|
||||
ProjectGUID="{ABD49D61-EFA9-41BA-9EA1-8DE4B4FA4FF6}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
InlineFunctionExpansion="0"
|
||||
OptimizeForWindowsApplication="TRUE"
|
||||
AdditionalIncludeDirectories=".."
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;PDC_STATIC_BUILD"
|
||||
StringPooling="TRUE"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
SmallerTypeCheck="TRUE"
|
||||
RuntimeLibrary="5"
|
||||
BufferSecurityCheck="TRUE"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
DisableLanguageExtensions="FALSE"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
CompileAs="1"
|
||||
DisableSpecificWarnings="4033;4716;4013;4131;4244;4201"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="Ws2_32.lib pdcurses.lib"
|
||||
OutputFile="$(OutDir)/xrogue.exe"
|
||||
LinkIncremental="2"
|
||||
SuppressStartupBanner="TRUE"
|
||||
AdditionalLibraryDirectories=".."
|
||||
IgnoreAllDefaultLibraries="FALSE"
|
||||
IgnoreDefaultLibraryNames="LIBC.LIB"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/xrogue.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)/xrogue.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>
|
||||
</Configurations>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
|
||||
<File
|
||||
RelativePath="actions.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="bolt.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="chase.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="command.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="daemon.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="daemons.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="eat.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="effects.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="encumb.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="fight.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="help.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="misc.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="mons_def.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="monsters.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="move.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="n_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>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
Loading…
Add table
Add a link
Reference in a new issue