home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
games
/
volume16
/
nethack31
/
part74
(
.txt
)
< prev
next >
Wrap
LaTeX Document
|
1993-02-06
|
59KB
|
1,742 lines
Path: uunet!news.tek.com!master!saab!billr
From: billr@saab.CNA.TEK.COM (Bill Randle)
Newsgroups: comp.sources.games
Subject: v16i082: nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part74/108
Message-ID: <4445@master.CNA.TEK.COM>
Date: 5 Feb 93 19:19:51 GMT
Sender: news@master.CNA.TEK.COM
Lines: 2037
Approved: billr@saab.CNA.TEK.COM
Xref: uunet comp.sources.games:1633
Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
Posting-number: Volume 16, Issue 82
Archive-name: nethack31/Part74
Supersedes: nethack3p9: Volume 10, Issue 46-102
Environment: Amiga, Atari, Mac, MS-DOS, OS2, Unix, VMS, X11
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 74 (of 108)."
# Contents: doc/Guidebook.te1 src/artifact.c
# Wrapped by billr@saab on Wed Jan 27 16:09:16 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'doc/Guidebook.te1' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'doc/Guidebook.te1'\"
echo shar: Extracting \"'doc/Guidebook.te1'\" \(25557 characters\)
sed "s/^X//" >'doc/Guidebook.te1' <<'END_OF_FILE'
X\documentstyle[titlepage]{article}
X\textheight 215mm
X\textwidth 160mm
X\oddsidemargin 0mm
X\evensidemargin 0mm
X\topmargin 0mm
X\newcommand{\nd}{\noindent}
X\newcommand{\tb}[1]{\tt #1 \hfill}
X\newcommand{\bb}[1]{\bf #1 \hfill}
X\newcommand{\ib}[1]{\it #1 \hfill}
X\newcommand{\blist}[1]
X{\begin{list}{$\bullet$}
X {\leftmargin 30mm \topsep 2mm \partopsep 0mm \parsep 0mm \itemsep 1mm
X \labelwidth 28mm \labelsep 2mm
X #1}}
X\newcommand{\elist}{\end{list}}
X% this will make \tt underscores look better, but requires that
X% math subscripts will never be used in this document
X\catcode`\_=12
X\begin{document}
X% input file: guideboo.mn
X%.ds h0 "
X%.ds h1 %.ds h2 \%
X%.ds f0 "
X%.mt
X\title{\LARGE A Guide to the Mazes of Menace:\\
X\Large Guidebook for {\it NetHack\/} 3.1}
X%.au
X\author{Eric S. Raymond\\
X(Extensively edited and expanded for 3.0 by Mike Threepoint)\\
X%.ai
XThyrsus Enterprises\\
XMalvern, PA 19355
X\date{January 9, 1993}
X\maketitle
X%.hn 1
X\section{Introduction}
X%.pg
XYou have just finished your years as a student at the local adventurer's
Xguild. After much practice and sweat you have finally completed your
Xtraining and are ready to embark upon a perilous adventure. To prove
Xyour worthiness, the local guildmasters have sent you into the Mazes of
XMenace. Your quest is to return with the Amulet of Yendor. According
Xto legend, the gods will grant immortality to the one who recovers this
Xartifact; true or not, its recovery will bring honor and full guild
Xmembership (not to mention the attentions of certain wealthy wizards).
X%.pg
XYour abilities and strengths for dealing with the hazards of adventure
Xwill vary with your background and training.
X%.pg
X\blist{}
X\item[\bb{Archeologists}]%
Xunderstand dungeons pretty well; this enables them
Xto move quickly and sneak up on dungeon nasties. They start equipped
Xwith proper tools for a scientific expedition.
X%.pg
X\item[\bb{Barbarians}]%
Xare warriors out of the hinterland, hardened to battle.
XThey begin their quests with naught but uncommon strength, a trusty hauberk,
Xand a great two-handed sword.
X%.pg
X\item[\bb{Cavemen {\rm and} Cavewomen}]
Xstart with exceptional strength and neolithic weapons.
X%.pg
X\item[\bb{Elves}]%
Xare agile, quick, and sensitive; very little of what goes
Xon will escape an Elf. The quality of Elven craftsmanship often gives
Xthem an advantage in arms and armor.
X%.pg
X\item[\bb{Healers}]%
Xare wise in medicine and the apothecary. They know the
Xherbs and simples that can restore vitality, ease pain, anesthetize,
Xand neutralize
Xpoisons; and with their instruments, they can divine a being's state
Xof health or sickness. Their medical practice earns them quite reasonable
Xamounts of money, which they enter the dungeon with.
X%.pg
X\item[\bb{Knights}]%
Xare distinguished from the common skirmisher by their
Xdevotion to the ideals of chivalry and by the surpassing excellence of
Xtheir armor.
X%.pg
X\item[\bb{Priests {\rm and} Priestesses}]%
Xare clerics militant, crusaders
Xadvancing the cause of righteousness with arms, armor, and arts
Xthaumaturgic. Their ability to commune with deities via prayer
Xoccasionally extricates them from peril---but can also put them in it.
X%.pg
X\item[\bb{Rogues}]%
Xare agile and stealthy thieves, who carry daggers, lock
Xpicks, and poisons to put on darts.
X%.pg
X\item[\bb{Samurai}]%
Xare the elite warriors of feudal Nippon. They are lightly
Xarmored and quick, and wear the %
X{\it dai-sho}, two swords of the deadliest
Xkeenness.
X%.pg
X\item[\bb{Tourists}]%
Xstart out with lots of gold (suitable for shopping with),
Xa credit card, lots of food, some maps, and an expensive camera. Most
Xmonsters don't like being photographed.
X%.pg
X\item[\bb{Valkyries}]%
Xare hardy warrior women. Their upbringing in the harsh
XNorthlands makes them strong and inures them to extremes of cold, and instills
Xin them stealth and cunning.
X%.pg
X\item[\bb{Wizards}]%
Xstart out with a fair selection of magical goodies and
Xa particular affinity for dweomercraft.
X\elist
X%.pg
X\nd You set out for the dungeon and after several days of uneventful
Xtravel, you see the ancient ruins that mark the entrance to the Mazes
Xof Menace. It is late at night, so you make camp at the entrance and
Xspend the night sleeping under the open skies. In the morning, you
Xgather your gear, eat what may be your last meal outside, and enter
Xthe dungeon.
X%.hn 1
X\section{What is going on here?}
X%.pg
XYou have just begun a game of {\it NetHack}. Your goal is to grab as much
Xtreasure as you can, retrieve the Amulet of Yendor, and escape the
XMazes of Menace alive. On the screen is kept a map of where you have
Xbeen and what you have seen on the current dungeon level; as you
Xexplore more of the level, it appears on the screen in front of you.
X%.pg
XWhen {\it NetHack\/}'s ancestor {\it rogue\/} first appeared, its screen
Xorientation was almost unique among computer fantasy games. Since
Xthen, screen orientation has become the norm rather than the
Xexception; {\it NetHack\/} continues this fine tradition. Unlike text
Xadventure games that input commands in pseudo-English sentences and
Xexplain the results in words, {\it NetHack\/} commands are all one or two
Xkeystrokes and the results are displayed graphically on the screen. A
Xminimum screen size of 24 lines by 80 columns is recommended; if the
Xscreen is larger, only a $21\times80$ section will be used for the map.
X%.pg
X{\it NetHack\/} generates a new dungeon every time you play it; even the
Xauthors still find it an entertaining and exciting game despite
Xhaving won several times.
X%.hn 1
X\section{What do all those things on the screen mean?}
X%.pg
XIn order to understand what is going on in {\it NetHack}, first you must
Xunderstand what {\it NetHack\/} is doing with the screen. The {\it NetHack\/}
Xscreen replaces the ``You see \ldots'' descriptions of text adventure games.
XFigure 1 is a sample of what a {\it NetHack\/} screen might look like.
X\vbox{
X\begin{verbatim}
X The bat bites!
X ------
X |....| ----------
X |.<..|####...@...$.|
X |....-# |...B....+
X |....| |.d......|
X ------ -------|--
X Player the Rambler St:12 Dx:7 Co:18 In:11 Wi:9 Ch:15 Neutral
X Dlvl:1 G:0 HP:9(12) Pw:3(3) AC:10 Xp:1/19 T:257 Weak
X\end{verbatim}
X\begin{center}
XFigure 1
X\end{center}
X%.hn 2
X\subsection*{The status lines (bottom)}
X%.pg
XThe bottom two lines of the screen contain several cryptic pieces of
Xinformation describing your current status. If either status line
Xbecomes longer than the width of the screen, you might not see all of
Xit. Here are explanations of what the various status items mean
X(though your configuration may not have all the status items listed
Xbelow):
X%.lp
X\blist{}
X\item[\bb{Rank}]
XYour character's name and professional ranking (based on the
Xexperience level, see below).
X%.lp
X\item[\bb{Strength}]
XA measure of your character's strength, one of your six basic
Xattributes. Your attributes can range from 3 to 18 inclusive
X(occasionally you may get super-strengths of the form 18/xx). The
Xhigher your strength, the stronger you are. Strength affects how
Xsuccessfully you perform physical tasks and how much damage you do in
Xcombat.
X%.lp
X\item[\bb{Dexterity}]
XDexterity affects your chances to hit in combat, to avoid traps, and
Xdo other tasks requiring agility or manipulation of objects.
X%.lp
X\item[\bb{Constitution}]
XConstitution affects your ability to withstand injuries and other
Xstrains on your stamina.
X%.lp
X\item[\bb{Intelligence}]
XIntelligence affects your ability to cast spells.
X%.lp
X\item[\bb{Wisdom}]
XWisdom comes from your religious affairs. It affects your magical energy.
X%.lp
X\item[\bb{Charisma}]
XCharisma affects how certain creatures react toward you. In
Xparticular, it can affect the prices shopkeepers offer you.
X%.lp
X\item[\bb{Alignment}]
X{\it Lawful}, {\it Neutral\/} or {\it Chaotic}. Basically, Lawful is
Xgood and Chaotic is evil. Your alignment influences how other
Xmonsters react toward you.
X%.lp
X\item[\bb{Dungeon Level}]
XHow deep you have gone into the dungeon. It starts at one and
Xincreases as you go deeper into the dungeon. The Amulet of Yendor is
Xreputed to be somewhere beneath the twentieth level.
X%.lp
X\item[\bb{Gold}]
XThe number of gold pieces you have.
X%.lp
X\item[\bb{Hit Points}]
XYour current and maximum hit points. Hit points indicate how much
Xdamage you can take before you die. The more you get hit in a fight,
Xthe lower they get. You can regain hit points by resting. The number
Xin parentheses is the maximum number your hit points can reach.
X%.lp
X\item[\bb{Power}]
XSpell points. This tells you how much mystic energy ({\it mana\/})
Xyou have available for spell casting. When you type `{\tt +}' to
Xlist your spells, each will have a spell point cost beside
Xit in parentheses. You will not see this if your dungeon
Xhas been set up without spells.
X%.lp
X\item[\bb{Armor Class}]
XA measure of how effectively your armor stops blows from unfriendly
Xcreatures. The lower this number is, the more effective the armor; it
Xis quite possible to have negative armor class.
X%.lp
X\item[\bb{Experience}]
XYour current experience level and experience points. As you
Xadventure, you gain experience points. At certain experience point
Xtotals, you gain an experience level. The more experienced you are,
Xthe better you fight and withstand magical attacks. Many dungeons
Xshow only your experience level here.
X%.lp
X\item[\bb{Time}]
XThe number of turns elapsed so far, displayed if you have the
X{\it time\/} option set.
X%.lp
X\item[\bb{Hunger Status}]
XYour current hunger status, ranging from %
X{\it Satiated\/} down to {\it Fainting}. If your hunger status is normal,
Xit is not displayed.
X%.pg
XAdditional status flags may appear after the hunger status:
X{\it Conf\/} when you're confused, {\it Sick\/} when sick, {\it Blind\/}
Xwhen you can't see, {\it Stun\/} when stunned, and {\it Hallu\/} when
Xhallucinating.
X\elist
X%.hn 2
X\subsection*{The message line (top)}
X%.pg
XThe top line of the screen is reserved for messages that describe
Xthings that are impossible to represent visually. If you see a
X``{\tt --More--}'' on the top line, this means that {\it NetHack\/} has
Xanother message to display on the screen, but it wants to make certain
Xthat you've read the one that is there first. To read the next message,
Xjust press the space bar.
X%.hn 2
X\subsection*{The map (rest of the screen)}
X%.pg
XThe rest of the screen is the map of the level as you have explored it
Xso far. Each symbol on the screen represents something. You can set
Xthe {\it graphics\/}
Xoption to change some of the symbols the game uses; otherwise, the
Xgame will use default symbols. Here is a list of what the default
Xsymbols mean:
X\blist{}
X%.lp
X\item[\tb{- and |}]
XThe walls of a room, or an open door.
X%.lp
X\item[\tb{.}]
XThe floor of a room, or a doorless doorway.
X%.lp
X\item[\tb{\#}]
XA corridor, or possibly a kitchen sink or drawbridge (if your dungeon
Xhas sinks).
X%.lp
X\item[\tb{<}]
XA way to the previous level.
X%.lp
X\item[\tb{>}]
XA way to the next level.
X%.lp
X\item[\tb{+}]
XA closed door, or a spell book containing a spell you can learn (if your
Xdungeon has spell books).
X%.lp
X\item[\tb{@}]
XA human (you, usually).
X%.lp
X\item[\tb{\$}]
XA pile of gold.
X%.lp
X\item[\tb{\^}]
XA trap (once you detect it).
X%.lp
X\item[\tb{)}]
XA weapon.
X%.lp
X\item[\tb{[}]
XA suit or piece of armor.
X%.lp
X\item[\tb{\%}]
XA piece of food (not necessarily healthy).
X%.lp
X\item[\tb{?}]
XA scroll.
X%.lp
X\item[\tb{/}]
XA wand.
X%.lp
X\item[\tb{=}]
XA ring.
X%.lp
X\item[\tb{!}]
XA potion.
X%.lp
X\item[\tb{(}]
XA useful item (pick-axe, key, lamp \ldots).
X%.lp
X\item[\tb{"}]
XAn amulet, or a spider web.
X%.lp
X\item[\tb{*}]
XA gem or rock (possibly valuable, possibly worthless).
X%.lp
X\item[\tb{`}]
XA boulder or statue.
X%.lp
X\item[\tb{0}]
XAn iron ball.
X%.lp
X\item[\tb{_}]
XAn altar, or an iron chain.
X%.lp
X\item[\tb{\}}]
XA pool of water or moat or a pool of lava.
X%.lp
X\item[\tb{\{}]
XA fountain (your dungeon may not have fountains).
X%.lp
X\item[\tb{$\backslash$}]
XAn opulent throne (your dungeon may not have thrones either).
X%.lp
X\item[\tb{a-zA-Z \& other symbols}]
XLetters and certain other symbols represent the various inhabitants
Xof the Mazes of Menace. Watch out, they can be nasty and vicious.
XSometimes, however, they can be helpful.
X%.pg
XYou need not memorize all these symbols; you can ask the game what any
Xsymbol represents with the `{\tt /}' command (see the Commands section for
Xmore info).
X\elist
X%.hn 1
X\section{Commands}
X%.pg
XCommands are given to {\it NetHack\/} by typing one or two characters;
X{\it NetHack\/} then asks questions to find out what it needs to know to do
Xyour bidding.
X%.pg
XFor example, a common question in the form ``{\tt What do you want to
Xuse? [a-zA-Z\ ?*]}'', asks you to choose an object you are carrying.
XHere, ``{\tt a-zA-Z}'' are the inventory letters of your possible choices.
XTyping `{\tt ?}' gives you an inventory list of these items, so you can see
Xwhat each letter refers to. In this example, there is also a `{\tt *}'
Xindicating that you may choose an object not on the list, if you
Xwanted to use something unexpected. Typing a `{\tt *}' lists your entire
Xinventory, so you can see the inventory letters of every object you're
Xcarrying. Finally, if you change your mind and decide you don't want
Xto do this command after all, you can press the `ESC' key to abort the
Xcommand.
X%.pg
XYou can put a number before most commands to repeat them that many
Xtimes; for example, ``{\tt 10s}'' will search ten times. If you have the
X{\it number\_pad\/}
Xoption set, you must type `{\tt n}' to prefix a count, so the example above
Xwould be typed ``{\tt n10s}'' instead. Commands for which counts make no
Xsense ignore them. In addition, movement commands can be prefixed for
Xgreater control (see below). To cancel a count or a prefix, press the
X`ESC' key.
X%.pg
XThe list of commands is rather long, but it can be read at any time
Xduring the game through the `{\tt ?}' command, which accesses a menu of
Xhelpful texts. Here are the commands for your reference:
X\blist{}
X%.lp
X\item[\tb{?}]
XHelp menu: display one of several help texts available.
X%.lp
X\item[\tb{/}]
XTell what a symbol represents. You may choose to specify a location
Xor type a symbol (or even a whole word) to define. If the {\it help\/}
Xoption is on, and {\it NetHack\/} has some special information about an object
Xor a monster that you looked at, you'll be asked if you want ``{\tt More
Xinfo?}''.
XIf {\it help\/} is off, then you'll only get the special information if you
Xexplicitly ask for it by typing in the name of the monster or object.
X%.lp
X\item[\tb{\&}]
XTell what a command does.
X%.lp
X\item[\tb{<}]
XGo up a staircase to the previous level (if you are on the stairs).
X%.lp
X\item[\tb{>}]
XGo down a staircase to the next level (if you are on the stairs).
X%.lp
X\item[\tb{[yuhjklbn]}]
XGo one step in the direction indicated (see Figure 2). If there is
Xa monster there, you will fight the monster instead. Only these
Xone-step movement commands cause you to fight monsters; the others
X(below) are ``safe.''
X%.sd
X\begin{center}
X\begin{tabular}{cc}
X\verb+ y k u + & \verb+ 7 8 9 +\\
X\verb+ \ | / + & \verb+ \ | / +\\
X\verb+ h- . -l + & \verb+ 4- . -6 +\\
X\verb+ / | \ + & \verb+ / | \ +\\
X\verb+ b j n + & \verb+ 1 2 3 +\\
X & (if {\it number\_pad\/} set)
X\end{tabular}
X\end{center}
X%.ed
X\begin{center}
XFigure 2
X\end{center}
X%.lp
X\item[\tb{[YUHJKLBN]}]
XGo in that direction until you hit a wall or run into something.
X%.lp
X\item[\tb{m[yuhjklbn]}]
XPrefix: Move without picking up any objects.
X%.lp
X\item[\tb{M[yuhjklbn]}]
XPrefix: Move far, no pickup.
X%.lp
X\item[\tb{g[yuhjklbn]}]
XPrefix: Move until something interesting is found.
X%.lp
X\item[\tb{G[yuhjklbn] or <CONTROL->[yuhjklbn]}]
XPrefix: Same as `{\tt g}', but forking of corridors is not considered
Xinteresting.
X%.lp
X\item[\tb{.}]
XRest, do nothing for one turn.
X%.lp
X\item[\tb{a}]
XApply (use) a tool (pick-axe, key, lamp \ldots).
X%.lp
X\item[\tb{A}]
XRemove all armor. Use `{\tt T}' (take off) to take off only one piece of
Xarmor.
X%.lp
X\item[\tb{\^{}A}]
XRedo the previous command.
X%.lp
X\item[\tb{c}]
XClose a door.
X%.lp
X\item[\tb{C}]
XCall (name) an individual monster.
X%.lp
X\item[\tb{\^{}C}]
XPanic button. Quit the game.
X%.lp
X\item[\tb{d}]
XDrop something.\\
X{\tt d7a} -- drop seven items of object
X{\it a}.
X%.lp
X\item[\tb{D}]
XDrop several things. In answer to the question
X``{\tt What kinds of things do you want to drop? [!\%= au]}''
Xyou should type zero or more object symbols possibly followed by
X`{\tt a}' and/or `{\tt u}'.\\
X%.sd
X%.si
X{\tt Da} -- drop all objects, without asking for confirmation.\\
X{\tt Du} -- drop only unpaid objects (when in a shop).\\
X{\tt D\%u} -- drop only unpaid food.
X%.ei
X%.ed
X%.lp
X\item[\tb{\^{}D}]
XKick something (usually a door).
X%.lp
X\item[\tb{e}]
XEat food.
X%.lp
X\item[\tb{E}]
XEngrave a message on the floor.
XEngraving the word ``{\tt Elbereth}'' will cause most monsters to not attack
Xyou hand-to-hand (but if you attack, you will rub it out); this is
Xoften useful to give yourself a breather. (This feature may be compiled out
Xof the game, so your version might not necessarily have it.)\\
X%.sd
X%.si
X{\tt E-} -- write in the dust with your fingers.
X%.ei
X%.ed
X%.lp
X\item[\tb{i}]
XList your inventory (everything you're carrying).
X%.lp
X\item[\tb{I}]
XList selected parts of your inventory.\\
X%.sd
X%.si
X{\tt I*} -- list all gems in inventory;\\
X{\tt Iu} -- list all unpaid items;\\
X{\tt Ix} -- list all used up items that are on your shopping bill;\\
X{\tt I\$} -- count your money.
X%.ei
X%.ed
X%.lp
X\item[\tb{o}]
XOpen a door.
X%.lp
X\item[\tb{O}]
XSet options. You will be asked to enter an option line. If you enter
Xa blank line, the current options are reported. Entering `{\tt ?}' will
Xget you explanations of the various options. Otherwise, you should
Xenter a list of options separated by commas. The available options
Xare listed later in this Guidebook. Options are usually set before
Xthe game, not with the `{\tt O}' command; see the section on options below.
X%.lp
X\item[\tb{p}]
XPay your shopping bill.
X%.lp
X\item[\tb{P}]
XPut on a ring.
X%.lp
X\item[\tb{\^{}P}]
XRepeat previous message (subsequent {\tt \^{}P}'s repeat earlier messages).
X%.lp
X\item[\tb{q}]
XQuaff (drink) a potion.
X%.lp
X\item[\tb{Q}]
XQuit the game.
X%.lp
X\item[\tb{r}]
XRead a scroll or spell book.
X%.lp
X\item[\tb{R}]
XRemove a ring.
X%.lp
X\item[\tb{\^{}R}]
XRedraw the screen.
X%.lp
X\item[\tb{s}]
XSearch for secret doors and traps around you. It usually takes several
Xtries to find something.
X%.lp
X\item[\tb{S}]
XSave the game. The game will be restored automatically the next time
Xyou play.
X%.lp
X\item[\tb{t}]
XThrow an object or shoot a projectile.
X%.lp
X\item[\tb{T}]
XTake off armor.
X%.lp
X\item[\tb{\^{}T}]
XTeleport, if you have the ability.
X%.lp
X\item[\tb{v}]
XDisplay version number.
X%.lp
X\item[\tb{V}]
XDisplay the game history.
X%.lp
X\item[\tb{w}]
XWield weapon.\\
X{\tt w-} -- wield nothing, use your bare hands.
X%.lp
X\item[\tb{W}]
XWear armor.
X%.lp
X\item[\tb{x}]
XList the spells you know (same as `{\tt +}').
X%.lp
X\item[\tb{X}]
XEnter explore (discovery) mode.
X%.lp
X\item[\tb{z}]
XZap a wand.
X%.lp
X\item[\tb{Z}]
XZap (cast) a spell.
X%.lp
X\item[\tb{\^{}Z}]
XSuspend the game (UNIX versions with job control only).
X%.lp
X\item[\tb{:}]
XLook at what is here.
X%.lp
X\item[\tb{,}]
XPick up some things.
X%.lp
X\item[\tb{@}]
XToggle the {\it pickup\/} option on and off.
X%.lp
X\item[\tb{\^{}}]
XAsk for the type of a trap you found earlier.
X%.lp
X\item[\tb{)}]
XTell what weapon you are wielding.
X%.lp
X\item[\tb{[}]
XTell what armor you are wearing.
X%.lp
X\item[\tb{=}]
XTell what rings you are wearing.
X%.lp
X\item[\tb{"}]
XTell what amulet you are wearing.
X%.lp
X\item[\tb{(}]
XTell what tools you are using.
X%.lp
X\item[\tb{\$}]
XCount your gold pieces.
X%.lp
X\item[\tb{+}]
XList the spells you know (same as `{\tt x}').
X%.lp
X\item[\tb{$\backslash$}]
XShow what types of objects have been discovered.
X%.lp
X\item[\tb{!}]
XEscape to a shell.
X%.lp
X\item[\tb{\#}]
XPerform an extended command. As you can see, the authors of {\it NetHack\/}
Xused up all the letters, so this is a way to introduce the less useful
Xcommands, or commands used under limited circumstances. You may obtain a
Xlist of them by entering `{\tt ?}'. What extended commands are available
Xdepend on what features the game was compiled with.
X\elist
X%.pg
X\nd If your keyboard has a meta key (which, when pressed in combination
Xwith another key, modifies it by setting the `meta' [8th, or `high']
Xbit), you can invoke the extended commands by meta-ing the first
Xletter of the command. In {\it OS/2, PC\/ {\rm and} ST NetHack}, the `Alt'
Xkey can be used in this fashion.
X\blist{}
X%.lp
X\item[\tb{M-a}]
XAdjust inventory letters (the {\it fixinv\/} option must be ``on'' to do this).
X%.lp
X\item[\tb{M-c}]
XTalk to someone.
X%.lp
X\item[\tb{M-d}]
XDip an object into something.
X%.lp
X\item[\tb{M-f}]
XForce a lock.
X%.lp
X\item[\tb{M-i}]
XInvoke an object's special powers.
X%.lp
X\item[\tb{M-j}]
XJump to another location.
X%.lp
X\item[\tb{M-l}]
XLoot a box on the floor.
X%.lp
X\item[\tb{M-m}]
XUse a monster's special ability.
X%.lp
X\item[\tb{M-n}]
XName an item or type of object.
X%.lp
X\item[\tb{M-o}]
XOffer a sacrifice to the gods.
X%.lp
X\item[\tb{M-p}]
XPray to the gods for help.
X%.lp
X\item[\tb{M-r}]
XRub a lamp.
X%.lp
X\item[\tb{M-s}]
XSit down.
X%.lp
X\item[\tb{M-t}]
XTurn undead.
X%.lp
X\item[\tb{M-u}]
XUntrap something (usually a trapped object).
X%.lp
X\item[\tb{M-v}]
XPrint compile time options for this version of {\it NetHack}.
X%.lp
X\item[\tb{M-w}]
XWipe off your face.
X\elist
X%.pg
X\nd If the {\it number\_pad\/} option is on, some additional letter commands
Xare available:
X\blist{}
X%.lp
X\item[\tb{j}]
XJump to another location. Same as ``{\tt \#jump}'' or ``{\tt M-j}''.
X%.lp
X\item[\tb{k}]
XKick something (usually a door). Same as `{\tt \^{}D}'.
X%.lp
X\item[\tb{l}]
XLoot a box on the floor. Same as ``{\tt \#loot}'' or ``{\tt M-l}''.
X%.lp
X\item[\tb{N}]
XName an object or type of object. Same as ``{\tt \#name}'' or ``{\tt M-N}''.
X%.lp
X\item[\tb{u}]
XUntrap a trapped object or door. Same as ``{\tt \#untrap}'' or ``{\tt M-u}''.
X\elist
X%.hn 1
X\section{Rooms and corridors}
X%.pg
XRooms and corridors in the dungeon are either lit or dark.
XAny lit areas within your line of sight will be displayed;
Xdark areas are only displayed if they are within one space of you.
XWalls and corridors remain on the map as you explore them.
X%.pg
XSecret corridors are hidden. You can find them with the `{\tt s}' (search)
Xcommand.
X%.hn 2
X\subsection*{Doorways}
X%.pg
XDoorways connect rooms and corridors. Some doorways have no doors;
Xyou can walk right through. Others have doors in them, which may be
Xopen, closed, or locked. To open a closed door, use the `{\tt o}' (open)
Xcommand; to close it again, use the `{\tt c}' (close) command.
X%.pg
XYou can get through a locked door by using a tool to pick the lock
Xwith the `{\tt a}' (apply) command, or by kicking it open with the
X`{\tt \^{}D}' (kick) command.
X%.pg
XOpen doors cannot be entered diagonally; you must approach them
Xstraight on, horizontally or vertically. Doorways without doors are
Xnot restricted.
X%.pg
XDoors can be useful for shutting out monsters. Most monsters cannot
Xopen doors, although a few don't need to (ex.\ ghosts can walk through
Xdoors).
X%.pg
XSecret doors are hidden. You can find them with the `{\tt s}' (search)
Xcommand.
X%.hn 2
X\subsection*{Traps (`{\tt \^{}}')}
X%.pg
XThere are traps throughout the dungeon to snare the unwary delver.
XFor example, you may suddenly fall into a pit and be stuck for a few
Xturns. Traps don't appear on your map until you see one triggered
Xby moving onto it, or you discover it with the `{\tt s}' (search) command.
XMonsters can fall prey to traps, too.
X%.hn 1
X\section{Monsters}
X%.pg
XMonsters you cannot see are not displayed on the screen. Beware!
XYou may suddenly come upon one in a dark place. Some magic items can
Xhelp you locate them before they locate you, which some monsters do
Xvery well.
X%.hn 2
X\subsection*{Fighting}
X%.pg
XIf you see a monster and you wish to fight it, just attempt to walk
Xinto it. Many monsters you find will mind their own business unless
Xyou attack them. Some of them are very dangerous when angered.
XRemember: Discretion is the better part of valor.
X%.hn 2
X\subsection*{Your pet}
X%.pg
XYou start the game with a little dog (`{\tt d}') or cat (`{\tt f}'),
Xwhich follows
Xyou about the dungeon and fights monsters with you. Like you, your
Xpet needs food to survive. It usually feeds itself on fresh carrion
Xand other meats. If you're worried about it or want to train it, you
Xcan feed it, too, by throwing it food.
X%.pg
XYour pet also gains experience from killing monsters, and can grow
Xover time, gaining hit points and doing more damage. Initially, your
Xpet may even be better at killing things than you, which makes pets
Xuseful for low-level characters.
X%.pg
XYour pet will follow you up and down staircases, if it is next to you
Xwhen you move. Otherwise, your pet will be stranded, and may become
Xwild.
X%.hn 2
X\subsection*{Ghost levels}
X%.pg
XYou may encounter the shades and corpses of other adventurers (or even
Xformer incarnations of yourself!) and their personal effects. Ghosts
Xare hard to kill, but easy to avoid, since they're slow and do little
Xdamage. You can plunder the deceased adventurer's possessions;
Xhowever, they are likely to be cursed. Beware of whatever killed the
Xformer player.
END_OF_FILE
if test 25557 -ne `wc -c <'doc/Guidebook.te1'`; then
echo shar: \"'doc/Guidebook.te1'\" unpacked with wrong size!
# end of 'doc/Guidebook.te1'
if test -f 'src/artifact.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/artifact.c'\"
echo shar: Extracting \"'src/artifact.c'\" \(28827 characters\)
sed "s/^X//" >'src/artifact.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)artifact.c 3.1 93/01/17 */
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X#include "hack.h"
X#include "artifact.h"
X#ifdef OVLB
X#include "artilist.h"
X#else
XSTATIC_DCL const struct artifact artilist[];
X#endif
X * Note: both artilist[] and artiexist[] have a dummy element #0,
X * so loops over them should normally start at #1. The primary
X * exception is the save & restore code, which doesn't care about
X * the contents, just the total size.
Xextern boolean notonhead; /* for long worms */
X#define get_artifact(o) \
X (((o)&&(o)->oartifact) ? &artilist[(int) (o)->oartifact] : 0)
XSTATIC_DCL int FDECL(spec_applies, (const struct artifact*,struct permonst*));
XSTATIC_DCL int FDECL(arti_invoke, (struct obj*));
X#ifndef OVLB
XSTATIC_DCL int spec_dbon_applies;
X#else /* OVLB */
X/* coordinate effects from spec_dbon() with messages in artifact_hit() */
XSTATIC_OVL int spec_dbon_applies = 0;
X/* flags including which artifacts have already been created */
Xstatic boolean artiexist[1+NROFARTIFACTS+1];
Xstatic boolean FDECL(attacks, (int,struct obj *));
X/* zero out the artifact existence list */
Xvoid
Xinit_artifacts()
X (void) memset((genericptr_t) artiexist, 0, sizeof artiexist);
Xvoid
Xsave_artifacts(fd)
Xint fd;
X bwrite(fd, (genericptr_t) artiexist, sizeof artiexist);
Xvoid
Xrestore_artifacts(fd)
Xint fd;
X mread(fd, (genericptr_t) artiexist, sizeof artiexist);
Xconst char *
Xartiname(artinum)
Xint artinum;
X if (artinum <= 0 || artinum > NROFARTIFACTS) return("");
X return(artilist[artinum].name);
X Make an artifact. If a specific alignment is specified, then an object of
X the appropriate alignment is created from scratch, or NULL is returned if
X none is available. If no alignment is given, then 'otmp' is converted
X into an artifact of matching type, or returned as-is if that's not possible.
X For the 2nd case, caller should use ``obj = mk_artifact(obj, A_NONE);''
X for the 1st, ``obj = mk_artifact(NULL, some_alignment);''.
Xstruct obj *
Xmk_artifact(otmp, alignment)
Xstruct obj *otmp; /* existing object; ignored if alignment specified */
Xaligntyp alignment; /* target alignment, or A_NONE */
X register const struct artifact *a;
X register int n = 0, m;
X register boolean by_align = (alignment != A_NONE);
X register short o_typ = (by_align || !otmp) ? 0 : otmp->otyp;
X boolean unique = !by_align && otmp && objects[o_typ].oc_unique;
X /* count eligible artifacts */
X for (a = artilist+1,m = 1; a->otyp; a++,m++)
X if ((by_align ? a->alignment == alignment : a->otyp == o_typ) &&
X (!(a->spfx & SPFX_NOGEN) || unique) && !artiexist[m]) {
X if (by_align && a->class == pl_character[0])
X goto make_artif; /* 'a' points to the desired one */
X else
X n++;
X }
X if (n) { /* found at least one candidate */
X /* select one, then find it again */
X if (n > 1) n = rnd(n); /* [1..n] */
X for (a = artilist+1,m = 1; a->otyp; a++,m++)
X if ((by_align ? a->alignment == alignment : a->otyp == o_typ)&&
X (!(a->spfx & SPFX_NOGEN) || unique) && !artiexist[m]) {
X if (!--n) break; /* stop when chosen one reached */
X /* make an appropriate object if necessary, then christen it */
Xmake_artif: if (by_align) otmp = mksobj((int)a->otyp, TRUE, FALSE);
X otmp = oname(otmp, a->name, 0);
X otmp->oartifact = m;
X artiexist[m] = TRUE;
X } else {
X /* nothing appropriate could be found; return the original object */
X if (by_align) otmp = 0; /* (there was no original object) */
X return otmp;
X * Returns the full name (with articles and correct capitalization) of an
X * artifact named "name" if one exists, or NULL, it not.
X * The given name must be rather close to the real name for it to match.
X * The object type of the artifact is returned in otyp if the return value
X * is non-NULL.
Xconst char*
Xartifact_name(name, otyp)
Xconst char *name;
Xshort *otyp;
X register const struct artifact *a;
X register const char *aname;
X if(!strncmpi(name, "the ", 4)) name += 4;
X for (a = artilist+1; a->otyp; a++) {
X aname = a->name;
X if(!strncmpi(aname, "the ", 4)) aname += 4;
X if(!strcmpi(name, aname)) {
X *otyp = a->otyp;
X return a->name;
X }
X return NULL;
Xboolean
Xexist_artifact(otyp, name)
Xregister int otyp;
Xregister const char *name;
X register const struct artifact *a;
X register boolean *arex;
X if (otyp && *name)
X for (a = artilist+1,arex = artiexist+1; a->otyp; a++,arex++)
X if ((int) a->otyp == otyp && !strcmp(a->name, name))
X return *arex;
X return FALSE;
Xvoid
Xartifact_exists(otmp, name, mod)
Xregister struct obj *otmp;
Xregister const char *name;
Xregister boolean mod;
X register const struct artifact *a;
X if (otmp && *name)
X for (a = artilist+1; a->otyp; a++)
X if (a->otyp == otmp->otyp && !strcmp(a->name, name)) {
X register int m = a - artilist;
X otmp->oartifact = (char)(mod ? m : 0);
X otmp->age = 0;
X if(otmp->otyp == RIN_INCREASE_DAMAGE)
X otmp->spe = 0;
X artiexist[m] = mod;
X break;
X return;
Xnartifact_exist()
X int a = 0;
X int n = SIZE(artiexist);
X while(n > 1)
X if(artiexist[--n]) a++;
X return a;
X#endif /* OVLB */
X#ifdef OVL0
Xboolean
Xspec_ability(otmp, abil)
Xstruct obj *otmp;
Xunsigned abil;
X const struct artifact *arti = get_artifact(otmp);
X return(arti && (arti->spfx & abil));
X#endif /* OVL0 */
X#ifdef OVLB
Xboolean
Xrestrict_name(otmp, name) /* returns 1 if name is restricted for otmp->otyp */
Xregister struct obj *otmp;
Xregister const char *name;
X register const struct artifact *a;
X if (!*name) return FALSE;
X /* Since almost every artifact is SPFX_RESTR, it doesn't cost
X us much to do the string comparison before the spfx check.
X Bug fix: don't name multiple elven daggers "Sting".
X */
X for (a = artilist+1; a->otyp; a++)
X if (a->otyp == otmp->otyp && !strcmp(a->name, name))
X return ((a->spfx & (SPFX_NOGEN|SPFX_RESTR)) != 0 ||
X otmp->quan > 1L);
X return FALSE;
Xstatic boolean
Xattacks(adtyp, otmp)
Xregister int adtyp;
Xregister struct obj *otmp;
X register const struct artifact *weap;
X if ((weap = get_artifact(otmp)) != 0)
X return(weap->attk.adtyp == adtyp);
X return(0);
Xboolean
Xdefends(adtyp, otmp)
Xregister int adtyp;
Xregister struct obj *otmp;
X register const struct artifact *weap;
X if ((weap = get_artifact(otmp)) != 0)
X return(weap->defn.adtyp == adtyp);
X return(0);
X * a potential artifact has just been worn/wielded/picked-up or
X * unworn/unwielded/dropped. Pickup/drop only set/reset the W_ART mask.
Xvoid
Xset_artifact_intrinsic(otmp,on,wp_mask)
Xregister struct obj *otmp;
Xboolean on;
Xlong wp_mask;
X long *mask = 0;
X register const struct artifact *oart = get_artifact(otmp);
X uchar dtyp;
X long spfx;
X if (!oart) return;
X /* effects from the defn field */
X dtyp = (wp_mask != W_ART) ? oart->defn.adtyp : oart->cary.adtyp;
X if (dtyp == AD_FIRE)
X mask = &HFire_resistance;
X else if (dtyp == AD_COLD)
X mask = &HCold_resistance;
X else if (dtyp == AD_ELEC)
X mask = &HShock_resistance;
X else if (dtyp == AD_MAGM)
X mask = &Antimagic;
X else if (dtyp == AD_DISN)
X mask = &HDisint_resistance;
X if(mask && wp_mask == W_ART && !on) {
X /* find out if some other artifact also confers this intrinsic */
X /* if so, leave the mask alone */
X register struct obj* obj;
X for(obj = invent; obj; obj = obj->nobj)
X if(obj != otmp && obj->oartifact) {
X register const struct artifact *art = get_artifact(obj);
X if(art->cary.adtyp == dtyp) {
X mask = (long *) 0;
X break;
X }
X if(mask) {
X if (on) *mask |= wp_mask;
X else *mask &= ~wp_mask;
X /* intrinsics from the spfx field; there could be more than one */
X spfx = (wp_mask != W_ART) ? oart->spfx : oart->cspfx;
X if(spfx && wp_mask == W_ART && !on) {
X /* don't change any spfx also conferred by other artifacts */
X register struct obj* obj;
X for(obj = invent; obj; obj = obj->nobj)
X if(obj != otmp && obj->oartifact) {
X register const struct artifact *art = get_artifact(obj);
X spfx &= ~art->cspfx;
X if (spfx & SPFX_SEARCH) {
X if(on) Searching |= wp_mask;
X else Searching &= ~wp_mask;
X if (spfx & SPFX_HALRES) {
X /* make_hallucinated must (re)set the mask itself to get
X * the display right */
X make_hallucinated((long)!on, TRUE, wp_mask);
X if (spfx & SPFX_ESP) {
X if(on) HTelepat |= wp_mask;
X else HTelepat &= ~wp_mask;
X see_monsters();
X if (spfx & SPFX_STLTH) {
X if (on) Stealth |= wp_mask;
X else Stealth &= ~wp_mask;
X if (spfx & SPFX_REGEN) {
X if (on) HRegeneration |= wp_mask;
X else HRegeneration &= ~wp_mask;
X if (spfx & SPFX_TCTRL) {
X if (on) HTeleport_control |= wp_mask;
X else HTeleport_control &= ~wp_mask;
X if (spfx & SPFX_WARN) {
X if (on) Warning |= wp_mask;
X else Warning &= ~wp_mask;
X if (spfx & SPFX_EREGEN) {
X if (on) Energy_regeneration |= wp_mask;
X else Energy_regeneration &= ~wp_mask;
X if (spfx & SPFX_HSPDAM) {
X if (on) Half_spell_damage |= wp_mask;
X else Half_spell_damage &= ~wp_mask;
X if (spfx & SPFX_HPHDAM) {
X if (on) Half_physical_damage |= wp_mask;
X else Half_physical_damage &= ~wp_mask;
X if(wp_mask == W_ART && !on && oart->inv_prop) {
X /* might have to turn off invoked power too */
X if (oart->inv_prop <= LAST_PROP &&
X (u.uprops[oart->inv_prop].p_flgs & W_ARTI))
X (void) arti_invoke(otmp);
X * creature (usually player) tries to touch (pick up or wield) an artifact obj.
X * Returns 0 if the object refuses to be touched.
X * This routine does not change any object chains.
X * Ignores such things as gauntlets, assuming the artifact is not
X * fooled by such trappings.
Xtouch_artifact(obj,mon)
X struct obj *obj;
X struct monst *mon;
X register const struct artifact *oart = get_artifact(obj);
X boolean badclass, badalign;
X boolean yours = (mon == &youmonst);
X if(!oart) return 1;
X badclass = (oart->class && (!yours || oart->class != pl_character[0]));
X badalign = (oart->spfx & SPFX_RESTR) &&
X ((oart->alignment !=
X (yours ? u.ualign.type : sgn(mon->data->maligntyp))) ||
X (yours && u.ualign.record < 0));
X /*
X * hack: Excalibur allows all lawfuls to touch it, but "class" is
X * set to 'K' to allow Knights to get it via sacrifice. This requires an
X * additional artifact field to fix, or some similar treatment. -dlc
X */
X if (obj->oartifact == ART_EXCALIBUR && !badalign) badclass = FALSE;
X if(((badclass || badalign) && (oart->spfx & SPFX_INTEL)) ||
X (badalign && (!yours || !rn2(4)))) {
X int dmg;
X char buf[BUFSZ];
X if (!yours) return 0;
X You("feel a blast of power flow from %s!", the(xname(obj)));
X dmg = d((Antimagic ? 2 : 4) , ((oart->spfx & SPFX_INTEL) ? 10 : 4));
X Sprintf(buf, "touching %s", oart->name);
X losehp(dmg, buf, KILLED_BY);
X exercise(A_WIS, FALSE);
X }
X /* can pick it up unless you're totally non-synch'd with the artifact */
X if(badclass && badalign && (oart->spfx & SPFX_INTEL)) {
X if (yours) pline("%s refuses to be held by you!", The(xname(obj)));
X return 0;
X }
X return 1;
X#endif /* OVLB */
X#ifdef OVL1
XSTATIC_OVL int
Xspec_applies(weap, ptr)
Xregister const struct artifact *weap;
Xstruct permonst *ptr;
X boolean yours = (ptr == &playermon);
X if(!(weap->spfx & (SPFX_DBONUS | SPFX_ATTK)))
X return(weap->attk.adtyp == AD_PHYS);
X if(weap->spfx & SPFX_DMONS)
X return((ptr == &mons[(int)weap->mtype]));
X else if(weap->spfx & SPFX_DCLAS)
X return((weap->mtype == ptr->mlet));
X else if(weap->spfx & SPFX_DFLAG1)
X return((ptr->mflags1 & weap->mtype) != 0L);
X else if(weap->spfx & SPFX_DFLAG2)
X return((ptr->mflags2 & weap->mtype) != 0L);
X else if(weap->spfx & SPFX_DALIGN)
X return(ptr->maligntyp == A_NONE ||
X sgn(ptr->maligntyp) != sgn(weap->alignment));
X else if(weap->spfx & SPFX_ATTK) {
X switch(weap->attk.adtyp) {
X case AD_FIRE:
X return(!(yours ? Fire_resistance : resists_fire(ptr)));
X case AD_COLD:
X return(!(yours ? Cold_resistance : resists_cold(ptr)));
X case AD_ELEC:
X return(!(yours ? Shock_resistance : resists_elec(ptr)));
X case AD_MAGM:
X case AD_STUN:
X return(!(yours ? Antimagic : (rn2(101) < ptr->mr)));
X case AD_DRLI:
X if (!yours) return(!resists_drli(ptr));
X else return(
X#ifdef POLYSELF
X resists_drli(uasmon) ||
X#endif
X defends(AD_DRLI, uwep));
X case AD_STON:
X#ifdef POLYSELF
X if (yours) return(!resists_ston(uasmon));
X else
X#endif
X return(!resists_ston(ptr));
X default: impossible("Weird weapon special attack.");
X }
X return(0);
Xspec_abon(otmp, ptr)
Xstruct obj *otmp;
Xstruct permonst *ptr;
X register const struct artifact *weap;
X if ((weap = get_artifact(otmp)) != 0)
X if(spec_applies(weap, ptr))
X return((weap->attk.damn) ? rnd((int)weap->attk.damn) : 0);
X return(0);
Xspec_dbon(otmp, ptr, tmp)
Xregister struct obj *otmp;
Xregister struct permonst *ptr;
Xregister int tmp;
X register const struct artifact *weap;
X if ((weap = get_artifact(otmp)) != 0)
X if ((spec_dbon_applies = spec_applies(weap, ptr)) != 0)
X return((weap->attk.damd) ? rnd((int)weap->attk.damd) : tmp);
X else spec_dbon_applies = 0;
X return(0);
X#endif /* OVL1 */
X#ifdef OVLB
X/* Function used when someone attacks someone else with an artifact
X * weapon. Only adds the special (artifact) damage, and returns a 1 if it
X * did something special (in which case the caller won't print the normal
X * hit message). This should be called once upon every artifact attack;
X * dmgval() no longer takes artifact bonuses into account. Possible
X * extension: change the killer so that when an orc kills you with
X * Stormbringer it's "killed by Stormbringer" instead of "killed by an orc".
Xboolean
Xartifact_hit(magr, mdef, otmp, dmgptr, dieroll)
Xstruct monst *magr, *mdef;
Xstruct obj *otmp;
Xint *dmgptr;
Xint dieroll; /* needed for Magicbane and vorpal blades */
X boolean youattack = (magr == &youmonst);
X boolean youdefend = (mdef == &youmonst);
X boolean vis = (!youattack && magr && cansee(magr->mx, magr->my))
X || (!youdefend && cansee(mdef->mx, mdef->my));
X boolean realizes_damage;
X static const char you[] = "you";
X const char *hittee = youdefend ? you : mon_nam(mdef);
X /* The following takes care of most of the damage, but not all--
X * the exception being for level draining, which is specially
X * handled. Messages are done in this function, however.
X */
X *dmgptr += spec_dbon(otmp, youdefend ? &playermon
X : mdef->data, *dmgptr);
X if (youattack && youdefend) {
X impossible("attacking yourself with weapon?");
X return FALSE;
X realizes_damage = (youdefend || vis) && spec_dbon_applies;
X /* the four basic attacks: fire, cold, shock and missiles */
X if (attacks(AD_FIRE, otmp)) {
X if (realizes_damage) {
X pline("The fiery blade burns %s!", hittee);
X return TRUE;
X if (attacks(AD_COLD, otmp)) {
X if (realizes_damage) {
X pline("The chilling blade freezes %s!", hittee);
X return TRUE;
X if (attacks(AD_ELEC, otmp)) {
X if (realizes_damage) {
X if(youattack && otmp != uwep)
X pline("%s hits %s!", The(xname(otmp)), hittee);
X pline("A bolt of lightning zaps %s!", hittee);
X return TRUE;
X if (attacks(AD_MAGM, otmp)) {
X if (realizes_damage) {
X if(youattack && otmp != uwep)
X pline("%s hits %s!", The(xname(otmp)), hittee);
X pline("A hail of magic missiles strikes %s!", hittee);
X return TRUE;
X * Magicbane's intrinsic magic is incompatible with normal
X * enchantment magic. Thus, its effects have a negative
X * dependence on spe. Against low mr victims, it typically
X * does "double athame" damage, 2d4. Occasionally, it will
X * cast unbalancing magic which effectively averages out to
X * 4d4 damage (2.5d4 against high mr victims), for spe = 0.
X */
X#define MB_MAX_DIEROLL 8 /* rolls above this aren't magical */
X#define MB_INDEX_INIT (-1)
X#define MB_INDEX_PROBE 0
X#define MB_INDEX_STUN 1
X#define MB_INDEX_SCARE 2
X#define MB_INDEX_PURGE 3
X#define MB_RESIST_ATTACK (resist_index = attack_index)
X#define MB_RESISTED_ATTACK (resist_index == attack_index)
X#define MB_UWEP_ATTACK (youattack && (otmp == uwep))
X if (attacks(AD_STUN, otmp) && (dieroll <= MB_MAX_DIEROLL)) {
X int attack_index = MB_INDEX_INIT;
X int resist_index = MB_INDEX_INIT;
X int scare_dieroll = MB_MAX_DIEROLL / 2;
X if (otmp->spe >= 3)
X scare_dieroll /= (1 << (otmp->spe / 3));
X *dmgptr += rnd(4); /* 3d4 */
X if (otmp->spe > rn2(10)) /* probe */
X attack_index = MB_INDEX_PROBE;
X else { /* stun */
X attack_index = MB_INDEX_STUN;
X *dmgptr += rnd(4); /* 4d4 */
X if (youdefend)
X make_stunned((HStun + 3), FALSE);
X else
X mdef->mstun = 1;
X if (dieroll <= scare_dieroll) { /* scare */
X attack_index = MB_INDEX_SCARE;
X *dmgptr += rnd(4); /* 5d4 */
X if (youdefend) {
X if (Antimagic)
X MB_RESIST_ATTACK;
X else {
X nomul(-3);
X nomovemsg = "";
X#ifdef POLYSELF
X if ((magr == u.ustuck)
X && sticks(uasmon)) {
X u.ustuck = (struct monst *)0;
X You("release %s!", mon_nam(magr));
X }
X#endif
X }
X } else if (youattack) {
X if (rn2(2) && resist(mdef,SPBOOK_CLASS,0,0)) {
X MB_RESIST_ATTACK;
X } else {
X if (mdef == u.ustuck) {
X if (u.uswallow)
X expels(mdef,mdef->data,TRUE);
X else {
X#ifdef POLYSELF
X if (!sticks(uasmon))
X#endif
X {
X u.ustuck = (struct monst *)0;
X You("get released!");
X }
X }
X }
X mdef->mflee = 1;
X mdef->mfleetim += 3;
X }
X }
X if (dieroll <= (scare_dieroll / 2)) { /* purge */
X struct obj *ospell;
X#ifdef POLYSELF
X struct permonst *old_uasmon = uasmon;
X#endif
X attack_index = MB_INDEX_PURGE;
X *dmgptr += rnd(4); /* 6d4 */
X /* Create a fake spell object, ala spell.c */
X ospell = mksobj(SPE_CANCELLATION, FALSE, FALSE);
X ospell->blessed = ospell->cursed = 0;
X ospell->quan = 20L;
X cancel_monst(mdef, ospell, youattack, FALSE, FALSE);
X#ifdef POLYSELF
X if (youdefend && (old_uasmon != uasmon))
X /* rehumanized, no more damage */
X *dmgptr = 0;
X#endif
X if (youdefend) {
X if (Antimagic)
X MB_RESIST_ATTACK;
X } else {
X if (!mdef->mcan)
X MB_RESIST_ATTACK;
X /* cancelled clay golems will die ... */
X else if (mdef->data == &mons[PM_CLAY_GOLEM])
X mdef->mhp = 1;
X }
X obfree(ospell, (struct obj *)0);
X if (youdefend || mdef->mhp > 0) { /* ??? -dkh- */
X static const char *mb_verb[4] =
X {"probe", "stun", "scare", "purge"};
X if (youattack || youdefend || vis) {
X pline("The magic-absorbing blade %ss %s!",
X mb_verb[attack_index], hittee);
X if (MB_RESISTED_ATTACK) {
X pline("%s resist%s!",
X youdefend ? "You" : Monnam(mdef),
X youdefend ? "" : "s");
X shieldeff(youdefend ? u.ux : mdef->mx,
X youdefend ? u.uy : mdef->my);
X }
X }
X /* Much ado about nothing. More magic fanfare! */
X if (MB_UWEP_ATTACK) {
X if (attack_index == MB_INDEX_PURGE) {
X if (!MB_RESISTED_ATTACK &&
X attacktype(mdef->data, AT_MAGC)) {
X You("absorb magical energy!");
X u.uenmax++;
X u.uen++;
X flags.botl = 1;
X }
X } else if (attack_index == MB_INDEX_PROBE) {
X if (!rn2(4 * otmp->spe)) {
X pline("The probe is insightful!");
X /* pre-damage status */
X mstatusline(mdef);
X }
X }
X } else if (youdefend && !MB_RESISTED_ATTACK
X && (attack_index == MB_INDEX_PURGE)) {
X You("lose some magical energy!");
X if (u.uenmax > 0) u.uenmax--;
X if (u.uen > 0) u.uen--;
X flags.botl = 1;
X }
X /* all this magic is confusing ... */
X if (!rn2(12)) {
X if (youdefend)
X make_confused((HConfusion + 4), FALSE);
X else
X mdef->mconf = 1;
X if (youattack || youdefend || vis)
X pline("%s %s confused.",
X youdefend ? "You" : Monnam(mdef),
X youdefend ? "are" : "is");
X }
X return TRUE;
X /* end of Magicbane code */
X /* We really want "on a natural 19 or 20" but Nethack does it in */
X /* reverse from AD&D. */
X if (spec_ability(otmp, SPFX_BEHEAD)) {
X#ifdef MULDGN
X if (otmp->oartifact == ART_TSURUGI_OF_MURAMASA && dieroll <= 2) {
X /* not really beheading, but so close, why add another SPFX */
X if (youattack && u.uswallow && mdef == u.ustuck) {
X You("slice %s wide open!", mon_nam(mdef));
X *dmgptr = mdef->mhp;
X return TRUE;
X if (!youdefend) {
X /* allow normal cutworm() call to add extra damage */
X if(notonhead)
X return FALSE;
X if (bigmonst(mdef->data)) {
X if (youattack)
X You("slice deeply into %s!",
X mon_nam(mdef));
X else if (vis)
X pline("%s cuts deeply into %s!",
X Monnam(magr), mon_nam(mdef));
X *dmgptr *= 2;
X return TRUE;
X }
X *dmgptr = mdef->mhp;
X pline("The razorsharp blade cuts %s in half!",
X mon_nam(mdef));
X otmp->dknown = TRUE;
X return TRUE;
X } else {
X#ifdef POLYSELF
X if (bigmonst(uasmon)) {
X pline("%s cuts deeply into you!",
X Monnam(magr));
X *dmgptr *= 2;
X return TRUE;
X }
X#endif
X *dmgptr = u.uhp;
X pline("The razorsharp blade cuts you in half!");
X otmp->dknown = TRUE;
X return TRUE;
X } else
X#endif /* MULDGN */
X if (otmp->oartifact == ART_VORPAL_BLADE &&
X (dieroll <= 2 || mdef->data == &mons[PM_JABBERWOCK])) {
X if (youattack && u.uswallow && mdef == u.ustuck)
X return FALSE;
X if (!youdefend) {
X if (!has_head(mdef->data) || notonhead) {
X if (youattack)
X pline("Somehow you miss %s wildly.",
X mon_nam(mdef));
X else if (vis)
X pline("Somehow %s misses wildly.",
X mon_nam(magr));
X *dmgptr = 0;
X return (youattack || vis);
X }
X *dmgptr = mdef->mhp;
X pline("%s cuts off %s head!",
X artilist[ART_VORPAL_BLADE].name,
X s_suffix(mon_nam(mdef)));
X otmp->dknown = TRUE;
X return TRUE;
X } else {
X#ifdef POLYSELF
X if (!has_head(uasmon)) {
X pline("Somehow %s misses you wildly.",
X mon_nam(magr));
X *dmgptr = 0;
X return TRUE;
X }
X#endif
X *dmgptr = u.uhp;
X pline("%s cuts off your head!",
X artilist[ART_VORPAL_BLADE].name);
X otmp->dknown = TRUE;
X /* Should amulets fall off? */
X return TRUE;
X }
X if (spec_ability(otmp, SPFX_DRLI)) {
X if (!youdefend && !resists_drli(mdef->data)) {
X if (vis) {
X if(otmp->oartifact == ART_STORMBRINGER)
X pline("The %s blade draws the life from %s!",
X Hallucination ? hcolor() : Black,
X mon_nam(mdef));
X else
X pline("%s draws the life from %s!",
X The(distant_name(otmp, xname)),
X mon_nam(mdef));
X }
X if (mdef->m_lev == 0) *dmgptr = mdef->mhp;
X else {
X int drain = rnd(8);
X *dmgptr += drain;
X mdef->mhpmax -= drain;
X mdef->m_lev--;
X drain /= 2;
X if (drain) healup(drain, 0, FALSE, FALSE);
X }
X return vis;
X } else if (youdefend
X#ifdef POLYSELF
X && !resists_drli(uasmon)
X#endif
X && !defends(AD_DRLI, uwep)) {
X if (Blind)
X You("feel an %s drain your life!",
X otmp->oartifact == ART_STORMBRINGER ?
X "unholy blade" : "object");
X else {
X if(otmp->oartifact == ART_STORMBRINGER)
X pline("The %s blade drains your life!",
X Hallucination ? hcolor() : Black);
X else
X pline("%s drains your life!",
X The(distant_name(otmp, xname)));
X }
X losexp();
X if (magr->mhp < magr->mhpmax) {
X magr->mhp += rnd(4);
X /* TODO: Should be related to # of HP you lost. */
X if (magr->mhp > magr->mhpmax) magr->mhp = magr->mhpmax;
X }
X return TRUE;
X return FALSE;
Xstatic const char recharge_type[] = { ALLOW_COUNT, ALL_CLASSES, 0 };
Xstatic const char NEARDATA invoke_types[] =
X { ALL_CLASSES, WEAPON_CLASS, ARMOR_CLASS, RING_CLASS, AMULET_CLASS,
X TOOL_CLASS, 0 };
Xdoinvoke()
X register struct obj *obj;
X obj = getobj(invoke_types, "invoke");
X if(!obj) return 0;
X return arti_invoke(obj);
XSTATIC_OVL int
Xarti_invoke(obj)
X register struct obj *obj;
X register const struct artifact *oart = get_artifact(obj);
X if(!oart || !oart->inv_prop) {
X if(obj->otyp == CRYSTAL_BALL)
X use_crystal_ball(obj);
X else
X pline("Nothing happens.");
X return 1;
X }
X if(oart->inv_prop > LAST_PROP) {
X /* It's a special power, not "just" a property */
X if(obj->age > monstermoves) {
X /* the artifact is tired :-) */
X You("feel that %s is ignoring you.", the(xname(obj)));
X return 1;
X obj->age = monstermoves + rnz(100);
X switch(oart->inv_prop) {
X case TAMING: {
X struct obj *pseudo = mksobj(SPE_CHARM_MONSTER, FALSE, FALSE);
X pseudo->blessed = pseudo->cursed = 0;
X pseudo->quan = 20L; /* do not let useup get it */
X (void) seffects(pseudo);
X obfree(pseudo, (struct obj *)0); /* now, get rid of it */
X break;
X }
X case HEALING: {
X int healamt = (u.uhpmax + 1 - u.uhp) / 2;
X if(healamt || Sick || (Blinded > 1))
X You("feel better.");
X else
X goto nothing_special;
X if(healamt) u.uhp += healamt;
X if(Sick) make_sick(0L,FALSE);
X if(Blinded > 1) make_blinded(0L,FALSE);
X flags.botl = 1;
X break;
X }
X case ENERGY_BOOST: {
X int epboost = (u.uenmax + 1 - u.uen) / 2;
X if(epboost) {
X You("feel re-energized.");
X u.uen += epboost;
X } else
X goto nothing_special;
X break;
X }
X case UNTRAP: {
X if(!untrap(TRUE)) {
X obj->age = 0; /* don't charge for changing their mind */
X return 0;
X }
X break;
X }
X case CHARGE_OBJ: {
X struct obj *otmp = getobj(recharge_type, "charge");
X if (!otmp) {
X obj->age = 0;
X return 0;
X }
X recharge(otmp, obj->blessed ? 1 : obj->cursed ? -1 : 0);
X break;
X }
X case LEV_TELE:
X level_tele();
X break;
X case CREATE_PORTAL: {
X register int i;
X d_level newlev;
X char buf[BUFSIZ];
X extern int n_dgns; /* from dungeon.c */
X winid tmpwin = create_nhwindow(NHW_MENU);
X char hc;
X start_menu(tmpwin);
X add_menu(tmpwin, 0, 0, "Dungeons:");
X add_menu(tmpwin, 0, 0, "");
X for (i = 0, hc = 'a'; i < n_dgns; i++) {
X if (!dungeons[i].dunlev_ureached) continue;
X Sprintf(buf, "%c - %s", hc, dungeons[i].dname);
X add_menu(tmpwin, hc, 0, buf);
X hc++;
X }
X add_menu(tmpwin, 0, 0, "");
X end_menu(tmpwin, '\033', "\033","Open a portal to which dungeon?");
X if (hc > 'b') {
X /* more than one entry; display menu for choices */
X hc = select_menu(tmpwin);
X } else
X hc = 'a';
X destroy_nhwindow(tmpwin);
X /* assume there won't be more than 26 dungeons */
X if (hc < 'a' || hc > 'z')
X goto nothing_special;
X /* run thru dungeon array to find the one they selected */
X for (i = 0; hc >= 'a'; i++)
X if (dungeons[i].dunlev_ureached) hc--;
X i--; /* we added one extra */
X /*
X * i is now index into dungeon structure for the new dungeon.
X * Find the closest level in the given dungeon, open
X * a use-once portal to that dungeon and go there.
X * The closest level is either the entry or dunlev_ureached.
X */
X newlev.dnum = i;
X if(dungeons[i].depth_start >= depth(&u.uz))
X newlev.dlevel = dungeons[i].entry_lev;
X else
X newlev.dlevel = dungeons[i].dunlev_ureached;
X if(u.uhave.amulet || In_endgame(&u.uz) || In_endgame(&newlev) ||
X newlev.dnum == u.uz.dnum) {
X You("feel very disoriented for a moment.");
X } else {
X if(!Blind) You("are surrounded by a shimmering sphere!");
X else You("momentarily feel weightless.");
X goto_level(&newlev, FALSE, FALSE, FALSE);
X }
X break;
X }
X } else {
X boolean on;
X unsigned long cprop;
X cprop = u.uprops[oart->inv_prop].p_flgs ^= W_ARTI;
X on = (cprop & W_ARTI) != 0; /* did we just turn on the invoked prop? */
X if(on && obj->age > monstermoves) {
X /* the artifact is tired :-) */
X u.uprops[oart->inv_prop].p_flgs ^= W_ARTI;
X You("feel that %s is ignoring you.", the(xname(obj)));
X return 1;
X } else if(!on) {
X /* when turning off property, determine downtime */
X /* arbitrary for now until we can tune this -dlc */
X obj->age = monstermoves + rnz(100);
X if(cprop & ~W_ARTI) {
X nothing_special:
X /* you had the property from some other source too */
X if (carried(obj))
X You("feel a surge of power, but notice no effect.");
X return 1;
X switch(oart->inv_prop) {
X case CONFLICT:
X if(on) You("feel like a rabble-rouser.");
X else You("feel the tension decrease in your vicinity.");
X break;
X case LEVITATION:
X if(on) float_up();
X else (void) float_down();
X break;
X case INVIS:
X if (!See_invisible && !Blind) {
X newsym(u.ux,u.uy);
X if (on) {
X Your("body takes on a %s transparency...",
X Hallucination ? "normal" : "strange");
X } else {
X Your("body seems to unfade...");
X } else goto nothing_special;
X break;
X }
X return 1;
X#endif /* OVLB */
X/*artifact.c*/
END_OF_FILE
if test 28827 -ne `wc -c <'src/artifact.c'`; then
echo shar: \"'src/artifact.c'\" unpacked with wrong size!
# end of 'src/artifact.c'
echo shar: End of archive 74 \(of 108\).
cp /dev/null ark74isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 \
101 102 103 104 105 106 107 108 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
if test "${MISSING}" = "" ; then
echo You have unpacked all 108 archives.
echo "Now execute 'rebuild.sh'"
rm -f ark10[0-8]isdone ark[1-9]isdone ark[1-9][0-9]isdone
echo You still need to unpack the following archives:
echo " " ${MISSING}
## End of shell archive.
exit 0