Merge branch 'NetHack-3.6.0'
This commit is contained in:
@@ -22,13 +22,14 @@ engrave.txt epitaph.txt
|
||||
|
||||
doc:
|
||||
(files for all versions)
|
||||
Guidebook.mn Guidebook.tex Guidebook.txt dgn_comp.6 dgn_comp.txt
|
||||
dlb.6 dlb.txt fixes22.0 fixes30.0 fixes31.1
|
||||
fixes31.2 fixes31.3 fixes32.0 fixes32.1 fixes32.2
|
||||
fixes32.3 fixes33.0 fixes33.1 fixes34.0 fixes34.1
|
||||
fixes34.2 fixes34.3 fixes35.0 fixes36.0 lev_comp.6
|
||||
lev_comp.txt makedefs.6 makedefs.txt nethack.6 nethack.txt
|
||||
recover.6 recover.txt tmac.n window.doc
|
||||
config.nh Guidebook.mn Guidebook.tex Guidebook.txt dgn_comp.6
|
||||
dgn_comp.txt dlb.6 dlb.txt fixes22.0 fixes30.0
|
||||
fixes31.1 fixes31.2 fixes31.3 fixes32.0 fixes32.1
|
||||
fixes32.2 fixes32.3 fixes33.0 fixes33.1 fixes34.0
|
||||
fixes34.1 fixes34.2 fixes34.3 fixes35.0 fixes36.0
|
||||
fixes36.1 lev_comp.6 lev_comp.txt makedefs.6 makedefs.txt
|
||||
nethack.6 nethack.txt recover.6 recover.txt tmac.n
|
||||
window.doc
|
||||
|
||||
include:
|
||||
(files for all versions)
|
||||
@@ -120,7 +121,7 @@ Install.dos Makefile.BC Makefile.GCC Makefile.MSC moveinit.pat
|
||||
msdos.c msdoshlp.txt ovlinit.c pckeys.c pctiles.c
|
||||
pctiles.h pcvideo.h portio.h schema1.BC schema2.BC
|
||||
schema3.MSC SCHEMA35.MSC setup.bat sound.c tile2bin.c
|
||||
video.c vidtxt.c vidvga.c
|
||||
video.c vidtxt.c vidvesa.c vidvga.c
|
||||
(files for running MSDOS binary under Windows)
|
||||
nhico.uu nhpif.uu
|
||||
|
||||
@@ -264,9 +265,9 @@ NetHackTerm.applescript recover.pl
|
||||
|
||||
win/share:
|
||||
(files for versions using optional tiles)
|
||||
gifread.c monsters.txt objects.txt other.txt ppmwrite.c
|
||||
renumtiles.pl thintile.c tile.doc tile.h tile2bmp.c
|
||||
tilemap.c tiletext.c
|
||||
gifread.c giftiles.c monsters.txt objects.txt other.txt
|
||||
ppmwrite.c renumtiles.pl thintile.c tile.doc tile.h
|
||||
tile2bmp.c tilemap.c tiletext.c
|
||||
|
||||
win/tty:
|
||||
(files for tty versions)
|
||||
|
||||
+16
-9
@@ -139,15 +139,22 @@ MAP
|
||||
---------------------------------------------------------------------------
|
||||
ENDMAP
|
||||
# Dungeon Description
|
||||
REGION:(01,01,23,06),lit,"ordinary"
|
||||
REGION:(01,07,23,10),unlit,"ordinary"
|
||||
REGION:(01,11,23,16),lit,"ordinary"
|
||||
REGION:(24,01,50,06),unlit,"ordinary"
|
||||
REGION:(24,07,50,10),lit,"ordinary"
|
||||
REGION:(24,11,50,16),unlit,"ordinary"
|
||||
REGION:(51,01,73,06),lit,"ordinary"
|
||||
REGION:(51,07,73,10),unlit,"ordinary"
|
||||
REGION:(51,11,73,16),lit,"ordinary"
|
||||
REGION:(01,01,73,16),lit,"ordinary"
|
||||
SWITCH [ 3 ] {
|
||||
CASE 0:
|
||||
REGION:(01,07,22,09),unlit,"ordinary"
|
||||
REGION:(24,01,50,05),unlit,"ordinary"
|
||||
REGION:(24,11,50,16),unlit,"ordinary"
|
||||
REGION:(52,07,73,09),unlit,"ordinary"
|
||||
BREAK
|
||||
CASE 1:
|
||||
REGION:(24,01,50,16),unlit,"ordinary"
|
||||
BREAK
|
||||
CASE 2:
|
||||
REGION:(01,01,22,16),unlit,"ordinary"
|
||||
REGION:(52,01,73,16),unlit,"ordinary"
|
||||
BREAK
|
||||
}
|
||||
# Stairs
|
||||
STAIR:random,up
|
||||
STAIR:random,down
|
||||
|
||||
@@ -5231,6 +5231,9 @@ unicorn horn
|
||||
warm glow stage, then I use my horn to burn off any excess and
|
||||
keep me right there."
|
||||
[ Unicorn Variations, by Roger Zelazny ]
|
||||
unreconnoitered
|
||||
Area of map which is beyond limited perception range when
|
||||
underwater or engulfed by a monster.
|
||||
valkyrie
|
||||
* valkyrie
|
||||
The Valkyries were the thirteen choosers of the slain, the
|
||||
|
||||
+5
-1
@@ -1,4 +1,4 @@
|
||||
# NetHack 3.6 dungeon.def $NHDT-Date: 1432512783 2015/05/25 00:13:03 $ $NHDT-Branch: master $:$NHDT-Revision: 1.13 $
|
||||
# NetHack 3.6 dungeon.def $NHDT-Date: 1462486876 2016/05/05 22:21:16 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.14 $
|
||||
# Copyright (c) 1990-95 by M. Stephenson
|
||||
# NetHack may be freely redistributed. See license for details.
|
||||
#
|
||||
@@ -119,6 +119,10 @@ DESCRIPTION: mazelike
|
||||
ALIGNMENT: chaotic
|
||||
ENTRY: -1
|
||||
LEVEL: "tower1" "none" @ (1, 0)
|
||||
# it isn't necessary to list these last two, but doing so makes them
|
||||
# show up in ^O output and in the level teleport menu
|
||||
LEVEL: "tower2" "none" @ (2, 0)
|
||||
LEVEL: "tower3" "none" @ (3, 0)
|
||||
|
||||
#
|
||||
# The Endgame levels
|
||||
|
||||
+20
-10
@@ -521,27 +521,37 @@ TRAP:"magic", random
|
||||
MAZE:"baalz",' '
|
||||
FLAGS: noteleport,corrmaze
|
||||
GEOMETRY:right,center
|
||||
# the two pools are fakes used to mark spots which need special wall fixups
|
||||
# the two iron bars are eyes and spots to their left will be made diggable
|
||||
MAP
|
||||
-------------------------------------------------
|
||||
| --- ----
|
||||
| ---- | ------------ |
|
||||
| ------ | --------|..........|---
|
||||
| |....| -------|...........--------------
|
||||
| ---- ----
|
||||
| ---- | ----------- |
|
||||
| ------ | ---------|.........|--P
|
||||
| F....| -------|...........--------------
|
||||
---....|--|..................S............|----
|
||||
....--....S..----------------|............S...|
|
||||
+...--....S..----------------|............S...|
|
||||
---....|--|..................|............|----
|
||||
| |....| -------|...........-----S--------
|
||||
| ------ | --------|..........|---
|
||||
| ---- | ------------ |
|
||||
| --- ----
|
||||
| F....| -------|...........-----S--------
|
||||
| ------ | ---------|.........|--P
|
||||
| ---- | ----------- |
|
||||
| ---- ----
|
||||
-------------------------------------------------
|
||||
ENDMAP
|
||||
STAIR:levregion(01,00,15,20),levregion(15,1,70,16),up
|
||||
BRANCH:levregion(01,00,15,20),levregion(15,1,70,16)
|
||||
TELEPORT_REGION:levregion(01,00,15,20),levregion(15,1,70,16)
|
||||
NON_DIGGABLE:(00,00,46,12)
|
||||
# this actually leaves the farthest right column diggable
|
||||
NON_DIGGABLE:(00,00,47,12)
|
||||
MAZEWALK:(00,06),west
|
||||
STAIR:(44,06),down
|
||||
DOOR:locked,(00,06)
|
||||
IF [50%] {
|
||||
TERRAIN:(34,08),'-'
|
||||
TERRAIN:(34,04),'S'
|
||||
TERRAIN:(29,05),'|'
|
||||
TERRAIN:(29,07),'S'
|
||||
}
|
||||
# The fellow in residence
|
||||
MONSTER:('&',"Baalzebub"),(35,06)
|
||||
# Some random weapons and armor.
|
||||
|
||||
@@ -80,7 +80,7 @@ Z Zap cast a spell (use Y instead of Z if number_pad is -1)
|
||||
$ gold count your gold
|
||||
+ spells list the spells you know; also rearrange them if desired
|
||||
` classkn display known items for one class of objects
|
||||
_ travel move via a shortest-path algorithm to a point on the map
|
||||
_ travel move via a shortest-path algorithm to a point on the map
|
||||
. rest wait a moment
|
||||
, pickup pick up all you can carry
|
||||
@ toggle "pickup" (auto pickup) option on and off
|
||||
@@ -93,7 +93,9 @@ via the meta modifier instead of the # prefix:
|
||||
M-? display extended command help (if the platform allows this)
|
||||
M-2 twoweapon toggle two-weapon combat (unless number_pad is enabled)
|
||||
M-a adjust adjust inventory letters
|
||||
M-A annotate add a one-line note to the current dungeon level (see M-O)
|
||||
M-c chat talk to someone
|
||||
M-C conduct view optional challanges
|
||||
M-d dip dip an object into something
|
||||
M-e enhance advance or check weapon and spell skills
|
||||
M-f force force a lock
|
||||
@@ -102,12 +104,16 @@ M-j jump jump to another location
|
||||
M-l loot loot a box on the floor
|
||||
M-m monster use a monster's special ability
|
||||
M-n name name a monster, an individual object, or a type of object
|
||||
M-N name synonym for M-n
|
||||
M-o offer offer a sacrifice to the gods
|
||||
M-O overview display information about visited levels and annotations
|
||||
M-p pray pray to the gods for help
|
||||
M-q quit stop playing
|
||||
M-r rub rub a lamp or a stone
|
||||
M-R ride mount or dismount saddled steed
|
||||
M-s sit sit down
|
||||
M-t turn turn undead
|
||||
M-T tip upend a container to dump out its contents
|
||||
M-u untrap untrap something
|
||||
M-v version print compile time options for this version
|
||||
M-w wipe wipe off your face
|
||||
|
||||
+19
-1
@@ -6,6 +6,8 @@
|
||||
MAZE:"knox",' '
|
||||
FLAGS: noteleport
|
||||
GEOMETRY:center,center
|
||||
# Fort's entry is via a secret door rather than a drawbridge;
|
||||
# the moat must be manually circumvented.
|
||||
MAP
|
||||
----------------------------------------------------------------------------
|
||||
| |........|...............................................................|
|
||||
@@ -37,11 +39,27 @@ TELEPORT_REGION:(06,16,09,17),(0,0,0,0),up
|
||||
TELEPORT_REGION:(06,16,09,17),(0,0,0,0),down
|
||||
# Throne room, with Croesus on the throne
|
||||
REGION:(37,08,46,11),lit,"throne"
|
||||
MONSTER:('@',"Croesus"),(43,10),hostile
|
||||
# 50% chance each to move throne and/or fort's entry secret door up one row
|
||||
IF [50%] {
|
||||
MONSTER:('@',"Croesus"),(43,10),hostile
|
||||
} ELSE {
|
||||
MONSTER:('@',"Croesus"),(43,09),hostile
|
||||
TERRAIN:(43,09), '\'
|
||||
TERRAIN:(43,10), '.'
|
||||
}
|
||||
IF [50%] {
|
||||
TERRAIN:(47,09), 'S'
|
||||
TERRAIN:(47,10), '|'
|
||||
}
|
||||
# The Vault
|
||||
# Using unfilled morgue for
|
||||
# identification in mkmaze.c
|
||||
REGION:(21,08,35,11),lit,"morgue",unfilled
|
||||
# Vault entrance also varies
|
||||
IF [50%] {
|
||||
TERRAIN:(36,09), '|'
|
||||
TERRAIN:(36,10), 'S'
|
||||
}
|
||||
# Corner towers
|
||||
REGION:(19,06,21,06),lit,"ordinary"
|
||||
REGION:(46,06,48,06),lit,"ordinary"
|
||||
|
||||
+13
-1
@@ -198,7 +198,7 @@ start: RogueEpyx
|
||||
S_armor: \x0a # Vert rect with o
|
||||
S_ring: \x09 # circle with arrow
|
||||
S_amulet: \x0c # "female" symbol
|
||||
S_food: \x05 # club (as in cards)
|
||||
S_food: \x05 # club (as in cards)
|
||||
S_potion: \xad # upside down '!'
|
||||
S_scroll: \x0e # musical note
|
||||
S_wand: \xe7 # greek tau
|
||||
@@ -394,3 +394,15 @@ start: NHAccess
|
||||
S_explode9: \047
|
||||
finish
|
||||
|
||||
start: plain
|
||||
Description: Same as Default symbols, except '+' for corner walls
|
||||
S_tlcorn: '+'
|
||||
S_trcorn: '+'
|
||||
S_blcorn: '+'
|
||||
S_brcorn: '+'
|
||||
S_crwall: '+'
|
||||
S_tuwall: '+'
|
||||
S_tdwall: '+'
|
||||
S_tlwall: '+'
|
||||
S_trwall: '+'
|
||||
finish #plain -- other symbols implicitly retain their default values
|
||||
|
||||
+1
-1
@@ -5797,7 +5797,7 @@ the list 'the man who arrived just before you'.
|
||||
# second paragraph is a bit "on the nose" but is too good to leave out
|
||||
%passage 2
|
||||
The reason for the story was a mix of many things. There was humanity's
|
||||
desire to do forebidden deeds merely because they were forbidden.
|
||||
desire to do forbidden deeds merely because they were forbidden.
|
||||
There was its desire to find new horizons and kill the people who live
|
||||
beyond them. There were the mysterious scrolls. There was the cucumber.
|
||||
But mostly there was the knowledge that one day, it would all be over.
|
||||
|
||||
+20
-3
@@ -345,7 +345,7 @@ show only your experience level here.
|
||||
The number of turns elapsed so far, displayed if you have the
|
||||
.op time
|
||||
option set.
|
||||
.lp Status
|
||||
.lp "Status "
|
||||
Hunger:
|
||||
your current hunger status.
|
||||
Values are \fBSatiated\fP, \fBNot Hungry\fP (or \fBNormal\fP),
|
||||
@@ -354,7 +354,7 @@ Values are \fBSatiated\fP, \fBNot Hungry\fP (or \fBNormal\fP),
|
||||
Not shown when \fBNormal\fP.
|
||||
.lp ""
|
||||
Encumbrance:
|
||||
an indication of how what your are carrying affects your ability to move.
|
||||
an indication of how what you are carrying affects your ability to move.
|
||||
Values are \fBUnencumbered\fP, \fBEncumbered\fP, \fBStressed\fP,
|
||||
\fBStrained\fP, \fBOvertaxed\fP, and \fBOverloaded\fP.
|
||||
Not shown when \fBUnencumbered\fP.
|
||||
@@ -368,7 +368,7 @@ Fatal conditions:
|
||||
.lp ""
|
||||
Non-fatal conditions:
|
||||
\fBBlind\fP (can't see), \fBDeaf\fP (can't hear),
|
||||
\fBStun\fB (stunned), \fBConf\fP (confused), \fBHallu\fP (hallucinating).
|
||||
\fBStun\fP (stunned), \fBConf\fP (confused), \fBHallu\fP (hallucinating).
|
||||
.lp ""
|
||||
Movement modifiers:
|
||||
\fBLev\fP (levitating), \fBFly\fP (flying), \fBRide\fP (riding).
|
||||
@@ -876,6 +876,7 @@ Escape to a shell.
|
||||
.lp #
|
||||
Perform an extended command.
|
||||
.lp ""
|
||||
.pg
|
||||
As you can see, the authors of NetHack
|
||||
used up all the letters, so this is a way to introduce the less frequently
|
||||
used commands.
|
||||
@@ -982,6 +983,7 @@ Print compile time options for this version of NetHack.
|
||||
Wipe off your face.
|
||||
.lp "#? "
|
||||
Help menu: get the list of available extended commands.
|
||||
.lp ""
|
||||
.pg
|
||||
If your keyboard has a meta key (which, when pressed in combination
|
||||
with another key, modifies it by setting the `meta' [8th, or `high']
|
||||
@@ -1049,6 +1051,7 @@ option to have nethack combine them into meta+key.
|
||||
#version
|
||||
.lp M-w
|
||||
#wipe
|
||||
.lp ""
|
||||
.pg
|
||||
If the
|
||||
.op number_pad
|
||||
@@ -2140,6 +2143,20 @@ lets you refine how it behaves. Here are the valid prefixes:
|
||||
.CC - "do not disclose it and do not prompt."
|
||||
.ei
|
||||
.ed
|
||||
The listing of vanquished monsters can be sorted,
|
||||
so there are two additional choices for `v':
|
||||
.sd
|
||||
.si
|
||||
.CC ? "prompt you and default to ask on the prompt;"
|
||||
.CC # "disclose it without prompting, ask for sort order."
|
||||
.ei
|
||||
.ed
|
||||
Asking refers to picking one of the orderings from a menu.
|
||||
The `+' disclose without prompting choice,
|
||||
or being prompted and answering `y' rather than `a',
|
||||
will default to showing monsters in the traditional order,
|
||||
from high level to low level.
|
||||
.lp ""
|
||||
Omitted categories are implicitly added with `n' prefix.
|
||||
Specified categories with omitted prefix implicitly use `+' prefix.
|
||||
Order of the disclosure categories does not matter, program display for
|
||||
|
||||
+27
-10
@@ -418,7 +418,7 @@ Not shown when {\it Normal}.
|
||||
|
||||
%.lp ""
|
||||
Encumbrance:
|
||||
an indication of how what your are carrying affects your ability to move.
|
||||
an indication of how what you are carrying affects your ability to move.
|
||||
Values are {\it Unencumbered}, {\it Encumbered}, {\it Stressed},
|
||||
{\it Strained}, {\it Overtaxed}, and {\it Overloaded}.
|
||||
Not shown when {\it Unencumbered}.
|
||||
@@ -636,7 +636,7 @@ will give a brief reminder about how it works.
|
||||
If the
|
||||
{\it autodescribe\/}
|
||||
option is on, a short description of what you see at each location is
|
||||
shown as you move the cursor. Typing `{\tt #}' while picking a location will
|
||||
shown as you move the cursor. Typing `{\tt \#}' while picking a location will
|
||||
toggle that option on or off.
|
||||
The
|
||||
{\it whatis\verb+_+coord\/}
|
||||
@@ -953,10 +953,11 @@ the exchange still takes place.
|
||||
\item[\tb{X}]
|
||||
Toggle two-weapon combat, if your character can do it. Also available
|
||||
via the ``{\tt \#twoweapon}'' extended command.\\
|
||||
+.lp ""
|
||||
+(In versions prior to 3.6 this was the command to switch from normal
|
||||
+play to ``explore mode'', also known as ``discovery mode'', which has now
|
||||
+been moved to ``{\tt \#explore}''.)
|
||||
%.lp ""
|
||||
|
||||
(In versions prior to 3.6 this was the command to switch from normal
|
||||
play to ``explore mode'', also known as ``discovery mode'', which has now
|
||||
been moved to ``{\tt \#explore}''.)
|
||||
%.lp
|
||||
\item[\tb{\^{}X}]
|
||||
Display basic information about your character.\\
|
||||
@@ -2569,6 +2570,22 @@ lets you refine how it behaves. Here are the valid prefixes:
|
||||
%.ei
|
||||
%.ed
|
||||
|
||||
The listing of vanquished monsters can be sorted,
|
||||
so there are two additional choices for `{\tt v}':
|
||||
%.sd
|
||||
%.si
|
||||
{\tt ?} --- prompt you and default to ask on the prompt;\\
|
||||
{\tt\#} --- disclose it without prompting, ask for sort order.
|
||||
%.ei
|
||||
%.ed
|
||||
|
||||
Asking refers to picking one of the orderings from a menu.
|
||||
The `{\tt +}' disclose without prompting choice,
|
||||
or being prompted and answering `{\tt y}' rather than `{\tt a}',
|
||||
will default to showing monsters in the traditional order,
|
||||
from high level to low level.
|
||||
.lp ""
|
||||
|
||||
%.lp ""
|
||||
(ex.\ ``{\tt disclose:yi na +v -g o}'')
|
||||
The example sets
|
||||
@@ -3083,15 +3100,15 @@ The possibile settings are:
|
||||
|
||||
%.sd
|
||||
%.si
|
||||
{\tt c} --- \verb#compass ('east' or '3s' or '2n,4w')#;
|
||||
{\tt m} --- \verb#map <x,y> (map column x=0 is not used)#;
|
||||
{\tt s} --- \verb#screen [row,column] (row is offset to match tty usage)#;
|
||||
{\tt c} --- \verb#compass ('east' or '3s' or '2n,4w')#;\\
|
||||
{\tt m} --- \verb#map <x,y> (map column x=0 is not used)#;\\
|
||||
{\tt s} --- \verb#screen [row,column] (row is offset to match tty usage)#;\\
|
||||
{\tt n} --- \verb#none (no coordinates shown) [default]#.
|
||||
%.ei
|
||||
%.ed
|
||||
|
||||
%.lp ""
|
||||
+The
|
||||
The
|
||||
{\it whatis\verb+_+coord\/}
|
||||
option is also used with
|
||||
the `{\tt /m}', `{\tt /M}', `{\tt /o}', and `{\tt /O}' sub-commands
|
||||
|
||||
+527
@@ -0,0 +1,527 @@
|
||||
# Sample config file for NetHack 3.6
|
||||
#
|
||||
# A '#' at the beginning of a line means the rest of the line is a comment.
|
||||
#
|
||||
# Some options must be set in this file, other options can be toggled while
|
||||
# playing.
|
||||
#
|
||||
# Copy the contents of this file into
|
||||
# * defaults.nh, same folder as nethack.exe or nethackW.exe (DOS, Windows)
|
||||
# * ~/.nethackrc (Unix, linux, Mac OS X)
|
||||
# * "NetHack Defaults" on pre-OSX Mac and BeOS
|
||||
# * NetHack.cnf on Amiga, Atari, OS/2, and VMS
|
||||
#
|
||||
# To change the configuration, comment out the unwanted lines, and
|
||||
# uncomment the configuration you want.
|
||||
#
|
||||
# There are two types of options, boolean and compound options.
|
||||
# Boolean options toggle a setting on or off, while compound options
|
||||
# take more diverse values.
|
||||
# Prefix a boolean option with 'no' or '!' to turn it off.
|
||||
# For compound options, the option name and value are separated by a colon.
|
||||
#
|
||||
# Some options are persistent, and apply only to new games.
|
||||
#
|
||||
# For more information about the options, see the Guidebook.
|
||||
|
||||
|
||||
# Set your character's name.
|
||||
#OPTIONS=name:Janet
|
||||
|
||||
# Set your character's role, race, gender, and alignment
|
||||
#OPTIONS=role:Valkyrie, race:Human, gender:female, align:lawful
|
||||
|
||||
# Set the default dog, cat, and horse names, and your fruit
|
||||
#OPTIONS=dogname:Fido
|
||||
#OPTIONS=catname:Morris
|
||||
#OPTIONS=horsename:Silver
|
||||
#OPTIONS=fruit:guava
|
||||
|
||||
# Turn on autopickup, and set object types which are picked up automatically
|
||||
# Both are persistent.
|
||||
#OPTIONS=autopickup,pickup_types:$"=/!?+
|
||||
# Automatically pick up items you threw. Persistent.
|
||||
#OPTIONS=pickup_thrown
|
||||
# When you pick up an item that would exceed this encumbrance
|
||||
# level (Unencumbered, Burdened, streSsed, straiNed, overTaxed,
|
||||
# or overLoaded), you will be asked if you want to continue. Persistent.
|
||||
#OPTIONS=pickup_burden:u
|
||||
|
||||
|
||||
# Enable messages about what your character hears
|
||||
#OPTIONS=acoustics
|
||||
|
||||
# Causes NetHack's top level command loop to treat two character sequence
|
||||
# "ESC c" as M-c, for terminals or emulators which send "ESC c" when Alt+c
|
||||
# is pressed.
|
||||
#OPTIONS=altmeta
|
||||
|
||||
# NetHack should display an ascii character map if it can.
|
||||
#OPTIONS=ascii_map
|
||||
|
||||
# Automatically describe the terrain under cursor when asked to
|
||||
# get a location on the map.
|
||||
#OPTIONS=autodescribe
|
||||
|
||||
# Automatically dig if walking into a wall and you're wielding a digging
|
||||
# implement or can otherwise dig through the wall.
|
||||
#OPTIONS=autodig
|
||||
|
||||
# Automatically try to open doors when walking into them
|
||||
#OPTIONS=autoopen
|
||||
|
||||
# Let NetHack fill your quiver or make ready some suitable weapon,
|
||||
# when firing with empty quiver or nothing at the ready.
|
||||
#OPTIONS=autoquiver
|
||||
|
||||
# Conduct/Role-playing: blind from birth or "zen"
|
||||
#OPTIONS=blind
|
||||
# Conduct/Role-playing: starts with no worn armor.
|
||||
# Wearing any armor will make you lose this conduct
|
||||
#OPTIONS=nudist
|
||||
|
||||
# Disable loading and saving of bones files
|
||||
#OPTIONS=!bones
|
||||
|
||||
# Save game state after each level change, for possible recovery
|
||||
# after program crash
|
||||
#OPTIONS=checkpoint
|
||||
|
||||
# Allows looking at things on the screen by navigating the mouse
|
||||
# over them and clicking the right mouse button
|
||||
#OPTIONS=clicklook
|
||||
|
||||
# Show assistance when you mistype a command
|
||||
#OPTIONS=cmdassist
|
||||
|
||||
# Display color if possible for different monsters, objects,
|
||||
# and dungeon features
|
||||
#OPTIONS=color
|
||||
|
||||
# Have user confirm attacks on pets, shopkeepers, and other
|
||||
# peaceable creatures (default on).
|
||||
#OPTIONS=confirm
|
||||
|
||||
# Highlight out-of-sight room floors with different color or glyph
|
||||
#OPTIONS=dark_room
|
||||
|
||||
# Controls what information the program reveals when the game ends.
|
||||
#OPTIONS=disclose:+i +a +v +g +c +o
|
||||
|
||||
# NetHack should pass eight-bit character values straight through
|
||||
# to your terminal (default off).
|
||||
#OPTIONS=eight_bit_tty
|
||||
|
||||
# Change the extended commands interface to pop-up a menu of
|
||||
# available commands.
|
||||
#OPTIONS=extmenu
|
||||
|
||||
# Objects will try to keep their inventory letters
|
||||
#OPTIONS=fixinv
|
||||
|
||||
# Try and display on the entire screen rather than in a window.
|
||||
#OPTIONS=fullscreen
|
||||
|
||||
# If more information is available for an object looked at with
|
||||
# the '/' command, ask if you want to see it (default on).
|
||||
#OPTIONS=help
|
||||
|
||||
# Hilight pets with a heart symbol (Windows, X11), or inverse attribute (TTY)
|
||||
#OPTIONS=hilite_pet
|
||||
|
||||
# Visually distinguish piles of objects from individual objects
|
||||
#OPTIONS=hilite_pile
|
||||
|
||||
# Always show the "uncursed" for inventory objects. Useful for MENUCOLORs
|
||||
#OPTIONS=implicit_uncursed
|
||||
|
||||
# Do not show the legacy intro text at game start
|
||||
#OPTIONS=!legacy
|
||||
|
||||
# Show lit corridors differently
|
||||
#OPTIONS=lit_corridor
|
||||
|
||||
# Use the old 'a', 'b', and 'c' keyboard shortcuts when looting,
|
||||
# rather than the mnemonics 'o', 'i', and 'b' (default off).
|
||||
#OPTIONS=lootabc
|
||||
|
||||
# Don't deliver email in-game
|
||||
#OPTIONS=!mail
|
||||
|
||||
# Mention in the message line when walking at a wall. Useful for blind players.
|
||||
#OPTIONS=mention_walls
|
||||
|
||||
# How menus are shown. Values are 'traditional', 'combination',
|
||||
# 'full', or 'partial'
|
||||
#OPTIONS=menustyle:full
|
||||
|
||||
# Set menu accelerator keys
|
||||
#OPTIONS=menu_deselect_all:-
|
||||
#OPTIONS=menu_deselect_page:\
|
||||
#OPTIONS=menu_first_page:^
|
||||
#OPTIONS=menu_invert_all:@
|
||||
#OPTIONS=menu_invert_page:~
|
||||
#OPTIONS=menu_last_page:|
|
||||
#OPTIONS=menu_next_page:>
|
||||
#OPTIONS=menu_previous_page:<
|
||||
#OPTIONS=menu_search::
|
||||
#OPTIONS=menu_select_all:.
|
||||
#OPTIONS=menu_select_page:,
|
||||
|
||||
# Controls how the headings in a menu are highlighted.
|
||||
# Values are 'none', 'bold', 'dim', 'underline', 'blink', or 'inverse'.
|
||||
# Default is 'inverse'
|
||||
#OPTIONS=menu_headings:inverse
|
||||
|
||||
# Show object symbols in menus in the item class lines where that object symbol
|
||||
# acts as an accelerator key to select items of that class.
|
||||
#OPTIONS=menu_objsyms
|
||||
|
||||
# Do not clear the screen before drawing menus, and align menus to right
|
||||
#OPTIONS=menu_overlay
|
||||
|
||||
# Set the number of messages saved into message history (^P -command)
|
||||
#OPTIONS=msghistory:50
|
||||
|
||||
# Allows you to change the way recalled messages are displayed.
|
||||
# The possible values are:
|
||||
# 's' single message (default; only choice prior to 3.4.0)
|
||||
# 'c' combination, two messages as `single', then as `full'
|
||||
# 'f' full window, oldest message first
|
||||
# 'r' full window reversed, newest message first
|
||||
# Default is 's'. TTY only.
|
||||
#OPTIONS=msg_window:s
|
||||
|
||||
# Allow use of the mouse for input and travel.
|
||||
#OPTIONS=mouse_support
|
||||
|
||||
# Read the NetHack news file, if present (default on).
|
||||
#OPTIONS=news
|
||||
|
||||
# Send padding nulls to the terminal (default on).
|
||||
#OPTIONS=null
|
||||
|
||||
# Use number pad or vi-keys for movement?
|
||||
# number_pad option can have an optional value of 0 (off), 1 (on),
|
||||
# or 2 (on,legacy-mode) which causes 5='g', alt-5='G', alt-0='I'
|
||||
# -1 (use vi-keys, but swap z and y, for qwertz keyboards)
|
||||
#OPTIONS=number_pad:2
|
||||
|
||||
# Set the order in which item classes appear in your inventory
|
||||
#OPTIONS=packorder:")[%?+/=!(*0_`
|
||||
|
||||
# A space separated list of specific situations where alternate
|
||||
# prompting is desired. The default is paranoid_confirmation:pray.
|
||||
#OPTIONS=paranoid_confirmation:confirm quit die bones attack pray remove
|
||||
|
||||
# Always show the inventory window? X11 and Windows GUI only.
|
||||
#OPTIONS=perm_invent
|
||||
|
||||
# Specify the type of your initial pet, if you are playing a character class
|
||||
# that uses multiple types of pets; or choose to have no initial pet at all.
|
||||
# Possible values are "cat", "dog", "horse", and "none".
|
||||
#OPTIONS=pettype:cat
|
||||
|
||||
# Threshold when item pile under you is shown in a popup list. Persistent.
|
||||
#OPTIONS=pile_limit:5
|
||||
|
||||
# Game mode
|
||||
# Values are 'normal', 'explore', or 'debug'.
|
||||
#OPTIONS=playmode:normal
|
||||
|
||||
# Preload tiles into memory. MSDOS only.
|
||||
#OPTIONS=preload_tiles
|
||||
|
||||
# When wielding a weapon, move your previous weapon to other hand
|
||||
#OPTIONS=pushweapon
|
||||
|
||||
# Space key acts as a wait.
|
||||
#OPTIONS=rest_on_space
|
||||
|
||||
# Controls the amount of screen updating for the map window when engaged
|
||||
# in multi-turn movement. Possible values are 'teleport', 'run', 'walk',
|
||||
# or 'crawl'. Default is 'run'.
|
||||
#OPTIONS=runmode:run
|
||||
|
||||
# Ask if you really want to hit your pet
|
||||
#OPTIONS=safe_pet
|
||||
|
||||
# Perform extra data checking. Wizard-mode only.
|
||||
#OPTIONS=sanity_check
|
||||
|
||||
# Display a menu of existing saved games for the player to choose from
|
||||
# at game startup, if it can. Not all ports support this option.
|
||||
#OPTIONS=selectsaved
|
||||
|
||||
# Which parts of the score file to show at end of game
|
||||
#OPTIONS=scores:10 top/2 around/own
|
||||
|
||||
# Do not show experience points in the status line
|
||||
#OPTIONS=!showexp
|
||||
|
||||
# Show your own symbol with the symbol of your race
|
||||
# eg. 'G' if you're a gnome, 'h' if dwarf, etc.
|
||||
#OPTIONS=showrace
|
||||
|
||||
# Show score on the status line
|
||||
#OPTIONS=showscore
|
||||
|
||||
# Suppress terminal beeps. Default on.
|
||||
#OPTIONS=silent
|
||||
|
||||
# Controls the sorting behavior of the pickup lists for inventory.
|
||||
# Possible values are 'full', 'loot', and 'none'.
|
||||
#OPTIONS=sortloot:full
|
||||
|
||||
# Sort the pack contents by type when displaying inventory (default on).
|
||||
#OPTIONS=sortpack
|
||||
|
||||
# Disable sparkly magic resistance animation effect
|
||||
#OPTIONS=!sparkle
|
||||
|
||||
# Boldface monsters and --More-- (default off).
|
||||
#OPTIONS=standout
|
||||
|
||||
# NetHack version level to suppress alert notification messages
|
||||
# about feature changes for that and prior versions.
|
||||
#OPTIONS=suppress_alert:3.6.0
|
||||
|
||||
# Show current turn in the status line
|
||||
#OPTIONS=time
|
||||
|
||||
# When pausing momentarily for display effect, such as with explosions and
|
||||
# moving objects, use a timer rather than sending extra characters to the
|
||||
# screen. TTY only.
|
||||
#OPTIONS=timed_delay
|
||||
|
||||
# Draw a tombstone graphic upon your death (default on).
|
||||
#OPTIONS=tombstone
|
||||
|
||||
# Do not show top ten list in a separate window. Windows GUI only.
|
||||
#OPTIONS=!toptenwin
|
||||
|
||||
# Enable travel (_) command.
|
||||
#OPTIONS=travel
|
||||
|
||||
# Use the dark gray color
|
||||
#OPTIONS=use_darkgray
|
||||
|
||||
# Use inverse text attribute in eg. menu titles
|
||||
#OPTIONS=use_inverse
|
||||
|
||||
# Display this number of messages at a time in the message window.
|
||||
# WinCE, Windows GUI, and GEM only.
|
||||
#OPTIONS=vary_msgcount:3
|
||||
|
||||
# Be less verbose with the messages
|
||||
#OPTIONS=!verbose
|
||||
|
||||
# Set the color palette for PC systems using NO_TERMS (MS-DOS only).
|
||||
# The order of colors is red, green, brown, blue, magenta, cyan,
|
||||
# bright.white, bright.red, bright.green, yellow, bright.blue,
|
||||
# bright.magenta, and bright.cyan.
|
||||
#OPTIONS=videocolors:4-2-6-1-5-3-15-12-10-14-9-13-11
|
||||
|
||||
# Gray shades to map to black-gray-white. possible values are 'dark',
|
||||
# 'normal', and 'light'. MS-DOS only.
|
||||
#OPTIONS=videoshades:normal-normal-normal
|
||||
|
||||
# When using '/' or ';' commands with autodescribe-option on, display
|
||||
# coordinates after the description. Possible values are 'compass',
|
||||
# 'map', 'screen', or 'none'
|
||||
#OPTIONS=whatis_coord:map
|
||||
|
||||
# Windowing system to use, such as 'tty' or 'x11'.
|
||||
#OPTIONS=windowtype:tty
|
||||
|
||||
# NetHack port should wrap long lines of text if they don't fit in
|
||||
# the visible area of the window.
|
||||
# WinCE only.
|
||||
#OPTIONS=wraptext
|
||||
|
||||
|
||||
|
||||
# How the map window is shown? Windows GUI only.
|
||||
# possible map_mode options include: tiles, ascii4x6,
|
||||
# ascii6x8, ascii8x8, ascii16x8, ascii7x12, ascii8x12, ascii16x12,
|
||||
# ascii12x16, ascii10x18, fit_to_screen
|
||||
#OPTIONS=map_mode:tiles
|
||||
|
||||
# Define alternative file for the files, and the tile size
|
||||
#OPTIONS=tile_file:C:\absurd64.bmp
|
||||
#OPTIONS=tile_width:64,tile_height:64
|
||||
|
||||
# When does the map window scroll? Windows GUI only.
|
||||
#OPTIONS=scroll_margin:5
|
||||
|
||||
# Message window settings. Windows GUI only.
|
||||
#OPTIONS=font_message:Arial,font_size_message:9,align_message:top
|
||||
|
||||
# Menu settings. Windows GUI only.
|
||||
#OPTIONS=font_menu:Arial,font_size_menu:9
|
||||
|
||||
# Text settings. Windows GUI only.
|
||||
#OPTIONS=font_text:Courier New,font_size_text:9
|
||||
|
||||
# Status window settings. Windows GUI only.
|
||||
#OPTIONS=font_status:Courier New,font_size_status:9
|
||||
|
||||
# No startup splash screen. Windows GUI only.
|
||||
#OPTIONS=!splash_screen
|
||||
|
||||
# How does NetHack prompt for character creation. Windows GUI only.
|
||||
#OPTIONS=player_selection:prompts
|
||||
|
||||
# NetHack should pop up dialog boxes for input.
|
||||
# Windows GUI only.
|
||||
#OPTIONS=popup_dialog
|
||||
|
||||
# Status/message window colors. Windows GUI only.
|
||||
# Possible color options include:
|
||||
# six digit hexadecimal RGB color value ("#8F8F8F"), black, red, green, brown,
|
||||
# blue, magenta, cyan, gray (or grey), orange, brightgreen, yellow, brightblue,
|
||||
# brightmagenta, brightcyan, white, trueblack, purple, silver, maroon, fuchsia,
|
||||
# lime, olive, navy, teal, aqua, activeborder, activecaption, appworkspace,
|
||||
# background, btnface, btnshadow, btntext, captiontext, graytext, highlight,
|
||||
# highlighttext, inactiveborder, inactivecaption, menu, menutext, scrollbar,
|
||||
# window, windowframe, windowtext.
|
||||
# windowcolors:<window> <text_color>/<background_color>
|
||||
#OPTIONS=windowcolors:status windowtext/window message windowtext/window
|
||||
|
||||
# HACKDIR is the default location for everything.
|
||||
# Note: On Windows HACKDIR defaults to the location of the NetHack.exe or
|
||||
# NetHackw.exe file so setting HACKDIR below to override that is not usually
|
||||
# necessary or recommended.
|
||||
#HACKDIR=c:\games\nethack
|
||||
|
||||
# The location that level files in progress are stored
|
||||
# (default=HACKDIR, writeable)
|
||||
#LEVELDIR=c:\nethack\levels
|
||||
|
||||
# The location where saved games are kept (default=HACKDIR, writeable)
|
||||
#SAVEDIR=c:\nethack\save
|
||||
|
||||
# The location that bones files are kept (default=HACKDIR, writeable)
|
||||
#BONESDIR=c:\nethack\save
|
||||
|
||||
# The location that file synchronization locks are stored
|
||||
# (default=HACKDIR, writeable)
|
||||
#LOCKDIR=c:\nethack\levels
|
||||
|
||||
# The location that a record of game aborts and self-diagnosed game problems
|
||||
# is kept (default=HACKDIR, writeable)
|
||||
#TROUBLEDIR=c:\nethack\trouble
|
||||
|
||||
# Finnish keyboards might need these modifications uncommented. Windows GUI.
|
||||
# For \, @, $, [, |
|
||||
#OPTIONS=subkeyvalue:171/92
|
||||
#OPTIONS=subkeyvalue:178/64
|
||||
#OPTIONS=subkeyvalue:180/36
|
||||
#OPTIONS=subkeyvalue:184/91
|
||||
#OPTIONS=subkeyvalue:188/124
|
||||
|
||||
# Some versions of Windows allow you to adjust the win32 console port
|
||||
# colors using R-G-B settings.
|
||||
#OPTIONS=palette:black-0-0-0
|
||||
#OPTIONS=palette:red-210-0-0
|
||||
#OPTIONS=palette:green-80-200-0
|
||||
#OPTIONS=palette:brown-180-100-0
|
||||
#OPTIONS=palette:blue-0-0-200
|
||||
#OPTIONS=palette:magenta-128-0-128
|
||||
#OPTIONS=palette:cyan-50-180-180
|
||||
#OPTIONS=palette:gray-192-192-192
|
||||
#OPTIONS=palette:dark gray-100-100-100
|
||||
#OPTIONS=palette:orange-255-128-0
|
||||
#OPTIONS=palette:bright green-0-255-0
|
||||
#OPTIONS=palette:yellow-255-255-0
|
||||
#OPTIONS=palette:bright blue-100-100-240
|
||||
#OPTIONS=palette:bright magenta-255-0-255
|
||||
#OPTIONS=palette:bright cyan-0-255-255
|
||||
#OPTIONS=palette:white-255-255-255
|
||||
|
||||
|
||||
|
||||
# Set exceptions to the pickup_types option. You can use multiple exceptions.
|
||||
# First character must be '<' (autopick) or '>' (don't autopick), followed
|
||||
# by a regular expression.
|
||||
# Always autopickup any type of arrow
|
||||
#AUTOPICKUP_EXCEPTION="<arrow"
|
||||
# Never autopickup any corpse
|
||||
#AUTOPICKUP_EXCEPTION=">corpse"
|
||||
# Never autopickup any known cursed items
|
||||
#AUTOPICKUP_EXCEPTION="> cursed"
|
||||
|
||||
|
||||
# Change the way messages are shown in the top status line.
|
||||
# You can use multiple MSGTYPE lines.
|
||||
# Format is MSGTYPE=type "regular expression"
|
||||
# Where type is one of 'show', 'hide', 'stop', or 'norep'
|
||||
# Always prompt for more after becoming hungry.
|
||||
#MSGTYPE=stop "You feel hungry."
|
||||
# Never show any displacing your pet messages.
|
||||
#MSGTYPE=hide "You displaced .*"
|
||||
# Don't repeat message when seeing same items on the floor
|
||||
#MSGTYPE=norep "You see here a *"
|
||||
#MSGTYPE=norep "You see here an *"
|
||||
|
||||
|
||||
# Highlight menu lines with different colors. You need to define the colors
|
||||
# with MENUCOLOR lines. Only for TTY and Windows GUI.
|
||||
# Toggle menucolor use on or off
|
||||
#OPTIONS=menucolors
|
||||
# Define color used for a certain menu line. Format is
|
||||
# MENUCOLOR="regular expression"=color
|
||||
# or
|
||||
# MENUCOLOR="regular expression"=color&attribute
|
||||
# Show all blessed items in green
|
||||
#MENUCOLOR=" blessed " = green
|
||||
# Show all holy water in green
|
||||
#MENUCOLOR=" holy " = green
|
||||
# Show all cursed items in red
|
||||
#MENUCOLOR=" cursed " = red
|
||||
# Show all unholy water in red
|
||||
#MENUCOLOR=" unholy " = red
|
||||
# Show all cursed worn items in orange and underlined
|
||||
#MENUCOLOR=" cursed .* (being worn)" = orange&underline
|
||||
|
||||
|
||||
# Use the IBM character set rather than just plain ascii characters
|
||||
# for tty window-port.
|
||||
#OPTIONS=symset:IBMGraphics_2
|
||||
# Use RogueEpyx character set for the rogue level
|
||||
#OPTIONS=roguesymset:RogueEpyx
|
||||
|
||||
# Override one or more symbols in the symbols files.
|
||||
# See the Guidebook for the symbol names.
|
||||
# Set boulder symbol to '0'
|
||||
#SYMBOLS=S_boulder:0
|
||||
# or
|
||||
#OPTIONS=S_boulder:0
|
||||
|
||||
# Load DEC text characters display symbols. Deprecated.
|
||||
#OPTIONS=DECgraphics
|
||||
# Load IBM text characters display symbols. Deprecated.
|
||||
#OPTIONS=IBMgraphics
|
||||
# Set the character symbol used for boulders. Deprecated.
|
||||
#OPTION=boulder:0
|
||||
|
||||
|
||||
# Wizard-mode extra items, in a text file containing item names,
|
||||
# one per line, up to a maximum of 128 lines. Each line is processed
|
||||
# by the function that handles wishing.
|
||||
#WIZKIT=~/wizkit.txt
|
||||
|
||||
|
||||
# User sounds
|
||||
# Define the directory that contains the sound files
|
||||
#SOUNDDIR=C:\nethack\sounds\
|
||||
# Define a sound mapping
|
||||
# SOUND=MESG "pattern" file volume
|
||||
#SOUND=MESG "KAABLAMM" explosion.wav 100
|
||||
|
||||
|
||||
# Turn on all status hilites.
|
||||
#OPTIONS=statushilites
|
||||
# Use highlighting in the status lines when it changes?
|
||||
#OPTIONS=hilite_status:hitpoints/30%/bright-magenta/normal
|
||||
|
||||
+144
@@ -177,6 +177,113 @@ a few types of monster (barrow wight, Nazgul, erinys) have weapon attacks that
|
||||
cockatrice corpse wouldn't be inflicted
|
||||
non-item-using monsters who happened to be carrying scroll or wand of fire or
|
||||
a fire horn could use it to cure themselves of being turned into slime
|
||||
when looting multiple containers, add 'n' for "loot next container", change
|
||||
'q' and ESC from "done with this container" to "done looting"
|
||||
change looting to choose ":iobrs nq" action from a menu for menustyle:Partial
|
||||
wand/spell/breath zaps that reached the edge of the level on the Plane of Air
|
||||
and "vanished into the aether" left temporary display effects on screen
|
||||
stop amulets and other items which aren't affected by erosion damage from
|
||||
being subjected to erosion damage
|
||||
grammar bit: polyself w/ gender change yielded "you turn into a Elvenking"
|
||||
some blindness cures ignored u.ucreamed
|
||||
some instances of stun or confusion timers were being overridden rather than
|
||||
incremented when new stun or confusion damage was suffered
|
||||
female gnome who gains level can grow up into male-only gnome lord; give an
|
||||
an alternate message instead of prohibiting the promotion
|
||||
kicked weapon which successfully hits monster vanishes from play
|
||||
unseen landmine explosion could result in "The <monst-type> statue crumbles."
|
||||
when using the 'O' command for regexp options (autopickup exceptions,
|
||||
menucolors, message types), provide opportunity to add more than one
|
||||
at a time [after 'add', return to add/list/remove menu]
|
||||
commands invoked by uppercase meta characters: M-A, M-C, M-N, M-O, M-R, M-T
|
||||
were missing from '? c' list of game commands (dat/hh)
|
||||
tweak Baalzebub's lair and clean up the map display for it
|
||||
symbol set definitions didn't recognize S_darkroom and S_vibrating_square
|
||||
wizard mode enlightenment was reporting "very fast innately" (which is not
|
||||
possible) for very fast hero who was innately fast
|
||||
when attacking a monster with a rust or corrosion or acid passive
|
||||
counter-attack, grease wasn't protecting the attacker's weapon
|
||||
the Bell of Opening now correctly reports when it opens a trapdoor/hole
|
||||
knocking can no longer send a monster through a trapdoor/hole and desaddle it
|
||||
game no longer gets confused when you break an unpaid shop item while inside
|
||||
a different shop
|
||||
shopkeepers now correctly handle nested containers and gold in containers
|
||||
for menustyle traditional, 'D' followed by (B|U|C|X)&m presented a menu of
|
||||
everything, not just invent subset matching specified BUCX categories
|
||||
for menustyles traditional or combination, 'A' (or object ID) followed by i
|
||||
displayed an inventory of everything rather than just worn items (or
|
||||
not fully identified items)
|
||||
exploding chest trap would destroy uchain while still worn if uball carried
|
||||
if monster shapechange message "<foo> turns into <bar>!" was given, <bar>
|
||||
could be "it" (if <foo> sensed telepathically and <bar> is mindless)
|
||||
automatic annotation for Ft.Ludios level got applied when a drawbridge became
|
||||
mapped, but entry there is a secret door rather than a drawbridge
|
||||
sortloot changed to group holy water and unholy water with water instead of
|
||||
placing them among the h- and u-named items
|
||||
sortloot changed to place diluted potion of foo after potion of foo instead
|
||||
of listing all diluted potions followed by all non-diluted ones
|
||||
digging down on a grave converted the terrain to floor but did not create a
|
||||
pit and uncover the grave's contents; digging again--on floor--did
|
||||
when feel_location removed a remembered-unseen-monster glyph from a known
|
||||
water location while hero was levitating, the map was redrawn showing
|
||||
floor instead of water at that spot
|
||||
Vlad's tower2 and tower3 didn't show up in wizard-mode ^O output or ^V? menu
|
||||
remove extra space from "All of your <stack-of-potions> boil and explode."
|
||||
(also applies to potions freezing and to scrolls burning)
|
||||
effects of cursed potion of levitation were skipped if already levitating
|
||||
when engulfed, having swallower be killed by angry deity trying to zap hero
|
||||
no longer violates pacifist conduct (other penalties--reduced luck or
|
||||
alignment--still apply if target is something you shouldn't kill)
|
||||
likewise when a monster kills inself trying to prevent turning to stone or
|
||||
into slime that's been caused by the player, pacifism is not affected
|
||||
metabolism adjustments: hero poly'd into metallivore form still needs to eat;
|
||||
being fainted or unconscious from other than sleep now consumes
|
||||
nutrition at lower rate, like being asleep already did;
|
||||
starvation threshold shortened due to slower food use while fainting
|
||||
after using detection magic or #terrain while underwater, then leaving water
|
||||
and saving while on land, save would flag you as underwater again and
|
||||
then restore would limit the map display accordingly; next move would
|
||||
notice, retify things, and report "you are on solid land again"
|
||||
change #terrain used while underwater to view the regular map rather than the
|
||||
crippled underwater one
|
||||
can see or feel adjacent lava or ice when underwater
|
||||
farlook when underwater now reports "land" for adjacent non-{water,lava,ice}
|
||||
and "unreconnoitered" for non-adjacent anything, instead of "dark part
|
||||
of a room" for the former and either dark-room or "unexplored" for the
|
||||
latter depending upon whether the spot had previously been scouted
|
||||
monster who accidentally killed itself by zapping wand of fire or fire horn
|
||||
at self to prevent turning into slime was not properly killed off;
|
||||
it wouldn't benefit from an amulet of life saving and would trigger
|
||||
impossible "dmonsfree: N removed doesn't match M pending"
|
||||
resurrecting a shopkeeper corpse caused crash (replmon -> replshk -> inhishop
|
||||
-> no eshk data for temporary monster being replaced with revived shk)
|
||||
new character with OPTIONS=role:Valk,race:!human,align:!lawful yielded
|
||||
"Shall I pick your Dwarven Valkyrie's for you?" where !human forces
|
||||
dwarf and dwarf forces lawful, contradicting align:!lawful
|
||||
new character with OPTIONS=role:Valk,race:random yielded
|
||||
"Shall I pick your Valkyrie's race and alignment for you?" instead
|
||||
of honoring race:random without asking
|
||||
while in shop, undead turning at self causing carried, hero owned corpse to
|
||||
resurrect claimed it belonged to shopkeeper
|
||||
while in shop, stone-to-flesh at self causing carried, hero owned figurine
|
||||
or statue to animate claimed it belonged to shopkeeper
|
||||
reviving one of a stack of N corpses in a shop charged a usage fee for all N;
|
||||
remaining N-1 were owned by hero if carried but by shop if on floor
|
||||
|
||||
|
||||
Fixes to Post-3.6.0 Problems that Were Exposed Via git Respository
|
||||
------------------------------------------------------------------
|
||||
fix "object lost" panic during pickup caused by sortloot revamp
|
||||
more sortloot revisions
|
||||
fix inventory menu for response of '?' to getobj (more sortloot revamp fallout)
|
||||
rings covered by non-cursed gloves not listed as 'R' candidates
|
||||
in baalz_fixup, move any monster away from the two fake pool spots
|
||||
switching farlook from xname to doname was giving away information for items
|
||||
located via object detection (quantity of detected gold)
|
||||
catch up win/Qt/qt_win.cpp on 18-Dec-2015 change to formatkiller()
|
||||
fix for long lines in config file (28-Jan-2016) made 'O' command's 'list' and
|
||||
'remove' menu choices in interactive handling for menu colorings,
|
||||
message types, and autopickup exceptions subject to buffer overflow
|
||||
|
||||
|
||||
Platform- and/or Interface-Specific Fixes
|
||||
@@ -189,11 +296,24 @@ tty: responding with <return> or <enter> during role, race, &c selection
|
||||
behaved same as <escape> to quit; now it will pick [random] instead
|
||||
tty: rename struct variable 'filter' (role.c) and function 'winch()' (wintty.c)
|
||||
to avoid conflicts with <curses.h>
|
||||
tty: skip selector letter and selection indicator (-,+,#) during menu coloring
|
||||
tty: '>' no longer closes a menu window
|
||||
tty: if color is disabled and use_inverse is enabled, display lava in inverse
|
||||
video so that it is visually distinguishable from water
|
||||
tty: if "--More--" was written to leftmost column (beginning of second line)
|
||||
while hero was swallowed, cursor would end up in wrong place (at end
|
||||
of status line instead back on map) after message line was cleared
|
||||
unix/X11: in top level Makefile, some commented out definitions of VARDATND
|
||||
misspelled pilemark.xbm (as pilemark.xpm)
|
||||
unix: options file with CR+LF line ends and an invalid option line resulted in
|
||||
"ad option line: "whatever-the-line-was
|
||||
because embedded carriage return character changed cursor's position
|
||||
unix: race condition with parallel make: src/Makefile might start building
|
||||
makedefs before finishing monst.o and objects.o; if so, util/Makefile
|
||||
can build them too, and they might be clobbered by simultaneous write
|
||||
unix: Makefile.{src,utl} ignored CPPFLAGS which is expanded by the default .c
|
||||
rule by GNU make so if user had a value for that in the environment,
|
||||
it would apply to some files but not others; explicitly override it
|
||||
win32gui: getversionstring() was overflowing the provided Help About buffer
|
||||
win32gui: guard against buffer overflow in in mswin_getlin()
|
||||
win32gui: handle menu_color attribute
|
||||
@@ -201,6 +321,9 @@ MacOSX: initial binary release was built from out of date source code that
|
||||
had 'BETA' and 'DEBUG' inappropriately enabled
|
||||
MacOSX: force TIMED_DELAY build option on so that 'runmode' run-time option
|
||||
is functional
|
||||
Qt: could issue impossible "Destroy called before we know if Menu or Text"
|
||||
followed by crash caused by deferencing a Null pointer if player quit
|
||||
immediately after creating character and declined to disclose anything
|
||||
X11: core bug for '`' (backtick) and #terrain commands was only noticed by
|
||||
X11 interface: impossible "add_menu: called before start_menu"
|
||||
X11: enable a scroll bar in menu windows
|
||||
@@ -243,6 +366,25 @@ feedback from probing of long worm now includes number of segments it has
|
||||
monk starts with 'shuriken' pre-discovered (despite language issue...)
|
||||
item-using monster on or next to a fire trap can use it to be cured of
|
||||
turning into slime
|
||||
wizard mode ^G can now specify "male" or "female" when creating a monster
|
||||
REPRODUCIBLE_BUILD is new config.h setting to fetch build date+time from
|
||||
environment instead of using current date+time, so that later rebuild
|
||||
could duplicate the original (disabled by default; tested for Unix)
|
||||
default value for vibrating square symbol changed from yellow '^' to purple '~'
|
||||
allow symbol set values to be specified via char within single quotes
|
||||
add symbols set "plain", same as default except it uses '+' for corner walls
|
||||
extend wizard-mode '#stats' command
|
||||
'Q' to ready an item for quick-throwing ('f') now allows the wielded weapon to
|
||||
be moved to quiver; if quantity is more than 1, it offers to split the
|
||||
stack and leave 1 wielded, otherwise it requires confirmation
|
||||
'Q' will accept an item count to manually split a stack as part of it being
|
||||
quivered, provided the stack isn't already in the quiver slot
|
||||
during end of game disclosure, the vanquished monsters list can be sorted in
|
||||
one of several ways by answering 'a' to "disclose vanquished monsters?"
|
||||
when #terrain is displaying a censored version of the map (no monsters, &c),
|
||||
moving the cursor will display farlook's brief autodescribe feedback
|
||||
interrupt a multi turn action if hp or pw is restored to maximum
|
||||
pressing d or D when cursor positioning targets doors and doorways
|
||||
|
||||
|
||||
Platform- and/or Interface-Specific New Features
|
||||
@@ -279,3 +421,5 @@ Ray Chason's MSDOS port support for some VESA modes
|
||||
|
||||
Code Cleanup and Reorganization
|
||||
-------------------------------
|
||||
removed some unused variables and dead code
|
||||
the level generator no longer uses the native pRNG
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
* For "UNIX" select BSD, ULTRIX, SYSV, or HPUX in unixconf.h.
|
||||
* A "VMS" option is not needed since the VMS C-compilers
|
||||
* provide it (no need to change sec#1, vmsconf.h handles it).
|
||||
* MacOSX uses the UNIX configruation, not the old MAC one.
|
||||
*/
|
||||
|
||||
#define UNIX /* delete if no fork(), exec() available */
|
||||
@@ -304,6 +305,28 @@
|
||||
*/
|
||||
/* #define DLB */ /* not supported on all platforms */
|
||||
|
||||
/*
|
||||
* Defining REPRODUCIBLE_BUILD causes 'util/makedefs -v' to construct
|
||||
* date+time in include/date.h (to be shown by nethack's 'v' command)
|
||||
* from SOURCE_DATE_EPOCH in the build environment rather than use
|
||||
* current date+time when makedefs is run.
|
||||
*
|
||||
* [The version string will show "last revision <date><time>" instead
|
||||
* of "last build <date><time>" if SOURCE_DATE_EPOCH has a value
|
||||
* which seems valid at the time date.h is generated. The person
|
||||
* building the program is responsible for setting it correctly,
|
||||
* and the value should be in UTC rather than local time. NetHack
|
||||
* normally uses local time and doesn't display timezone so toggling
|
||||
* REPRODUCIBLE_BUILD on or off might yield a date+time that appears
|
||||
* to be incorrect relative to what the other setting produced.]
|
||||
*
|
||||
* Intent is to be able to rebuild the program with the same value
|
||||
* and obtain an identical copy as was produced by a previous build.
|
||||
* Not necessary for normal game play....
|
||||
*/
|
||||
/* #define REPRODUCIBLE_BUILD */ /* use getenv("SOURCE_DATE_EPOCH") instead
|
||||
of current time when creating date.h */
|
||||
|
||||
/*
|
||||
* Defining INSURANCE slows down level changes, but allows games that
|
||||
* died due to program or system crashes to be resumed from the point
|
||||
|
||||
+4
-2
@@ -243,7 +243,8 @@ E NEARDATA struct obj *migrating_objs;
|
||||
E NEARDATA struct obj *billobjs;
|
||||
E NEARDATA struct obj *current_wand, *thrownobj, *kickedobj;
|
||||
|
||||
E NEARDATA struct obj zeroobj; /* init'd and defined in decl.c */
|
||||
E NEARDATA struct obj zeroobj; /* for init; &zeroobj used as special value */
|
||||
|
||||
E NEARDATA anything zeroany; /* init'd and defined in decl.c */
|
||||
|
||||
#include "you.h"
|
||||
@@ -256,7 +257,8 @@ E NEARDATA struct u_realtime urealtime;
|
||||
#include "pm.h"
|
||||
#endif
|
||||
|
||||
E NEARDATA struct monst youmonst; /* init'd and defined in decl.c */
|
||||
E NEARDATA struct monst zeromonst; /* for init of new or temp monsters */
|
||||
E NEARDATA struct monst youmonst; /* monster details when hero is poly'd */
|
||||
E NEARDATA struct monst *mydogs, *migrating_mons;
|
||||
|
||||
E NEARDATA struct mvitals {
|
||||
|
||||
+19
-9
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 extern.h $NHDT-Date: 1456992437 2016/03/03 08:07:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.550 $ */
|
||||
/* NetHack 3.6 extern.h $NHDT-Date: 1461967848 2016/04/29 22:10:48 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.558 $ */
|
||||
/* Copyright (c) Steve Creps, 1988. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -594,6 +594,7 @@ E void NDECL(recalc_mapseen);
|
||||
E void FDECL(mapseen_temple, (struct monst *));
|
||||
E void FDECL(room_discovered, (int));
|
||||
E void FDECL(recbranch_mapseen, (d_level *, d_level *));
|
||||
E void FDECL(overview_stats, (winid, const char *, long *, long *));
|
||||
E void FDECL(remdun_mapseen, (int));
|
||||
|
||||
/* ### eat.c ### */
|
||||
@@ -680,6 +681,7 @@ E int NDECL(doengrave);
|
||||
E void NDECL(sanitize_engravings);
|
||||
E void FDECL(save_engravings, (int, int));
|
||||
E void FDECL(rest_engravings, (int));
|
||||
E void FDECL(engr_stats, (const char *, char *, long *, long *));
|
||||
E void FDECL(del_engr, (struct engr *));
|
||||
E void FDECL(rloc_engr, (struct engr *));
|
||||
E void FDECL(make_grave, (int, int, const char *));
|
||||
@@ -891,8 +893,7 @@ E int NDECL(midnight);
|
||||
|
||||
/* ### invent.c ### */
|
||||
|
||||
E struct obj **FDECL(objarr_init, (int));
|
||||
E void FDECL(objarr_set, (struct obj *, int, struct obj **, BOOLEAN_P));
|
||||
E void FDECL(sortloot, (struct obj **, unsigned, BOOLEAN_P));
|
||||
E void FDECL(assigninvlet, (struct obj *));
|
||||
E struct obj *FDECL(merge_choice, (struct obj *, struct obj *));
|
||||
E int FDECL(merged, (struct obj **, struct obj **));
|
||||
@@ -921,6 +922,7 @@ E boolean FDECL(obj_here, (struct obj *, int, int));
|
||||
E boolean NDECL(wearing_armor);
|
||||
E boolean FDECL(is_worn, (struct obj *));
|
||||
E struct obj *FDECL(g_at, (int, int));
|
||||
E boolean FDECL(splittable, (struct obj *));
|
||||
E struct obj *FDECL(getobj, (const char *, const char *));
|
||||
E int FDECL(ggetobj, (const char *, int (*)(OBJ_P), int,
|
||||
BOOLEAN_P, unsigned *));
|
||||
@@ -985,6 +987,7 @@ E void FDECL(do_light_sources, (char **));
|
||||
E struct monst *FDECL(find_mid, (unsigned, unsigned));
|
||||
E void FDECL(save_light_sources, (int, int, int));
|
||||
E void FDECL(restore_light_sources, (int));
|
||||
E void FDECL(light_stats, (const char *, char *, long *, long *));
|
||||
E void FDECL(relink_light_sources, (BOOLEAN_P));
|
||||
E void NDECL(light_sources_sanity_check);
|
||||
E void FDECL(obj_move_light_source, (struct obj *, struct obj *));
|
||||
@@ -1067,6 +1070,7 @@ E void FDECL(nocmov, (int x, int y));
|
||||
|
||||
#ifdef MAIL
|
||||
#ifdef UNIX
|
||||
E void NDECL(free_maildata);
|
||||
E void NDECL(getmailstatus);
|
||||
E void NDECL(ck_server_admin_msg);
|
||||
#endif
|
||||
@@ -1417,6 +1421,7 @@ E boolean FDECL(onscary, (int, int, struct monst *));
|
||||
E void FDECL(monflee, (struct monst *, int, BOOLEAN_P, BOOLEAN_P));
|
||||
E void FDECL(mon_yells, (struct monst *, const char *));
|
||||
E int FDECL(dochug, (struct monst *));
|
||||
E boolean FDECL(m_digweapon_check, (struct monst *, XCHAR_P, XCHAR_P));
|
||||
E int FDECL(m_move, (struct monst *, int));
|
||||
E void FDECL(dissolve_bars, (int, int));
|
||||
E boolean FDECL(closed_door, (int, int));
|
||||
@@ -1591,6 +1596,7 @@ E char *FDECL(xname, (struct obj *));
|
||||
E char *FDECL(mshot_xname, (struct obj *));
|
||||
E boolean FDECL(the_unique_obj, (struct obj *));
|
||||
E boolean FDECL(the_unique_pm, (struct permonst *));
|
||||
E boolean FDECL(erosion_matters, (struct obj *));
|
||||
E char *FDECL(doname, (struct obj *));
|
||||
E char *FDECL(doname_with_price, (struct obj *));
|
||||
E boolean FDECL(not_fully_identified, (struct obj *));
|
||||
@@ -1661,7 +1667,7 @@ E void NDECL(free_symsets);
|
||||
E boolean FDECL(parsesymbols, (char *));
|
||||
E struct symparse *FDECL(match_sym, (char *));
|
||||
E void NDECL(set_playmode);
|
||||
E int FDECL(sym_val, (char *));
|
||||
E int FDECL(sym_val, (const char *));
|
||||
E const char *FDECL(clr2colorname, (int));
|
||||
E int FDECL(match_str2clr, (char *));
|
||||
E boolean FDECL(add_menu_coloring, (char *));
|
||||
@@ -1754,16 +1760,16 @@ E int FDECL(out_container, (struct obj *));
|
||||
#endif
|
||||
E int FDECL(pickup, (int));
|
||||
E int FDECL(pickup_object, (struct obj *, long, BOOLEAN_P));
|
||||
E int FDECL(query_category,
|
||||
(const char *, struct obj *, int, menu_item **, int));
|
||||
E int FDECL(query_objlist, (const char *, struct obj *, int, menu_item **,
|
||||
int, boolean (*)(OBJ_P)));
|
||||
E int FDECL(query_category, (const char *, struct obj *, int,
|
||||
menu_item **, int));
|
||||
E int FDECL(query_objlist, (const char *, struct obj **, int,
|
||||
menu_item **, int, boolean (*)(OBJ_P)));
|
||||
E struct obj *FDECL(pick_obj, (struct obj *));
|
||||
E int NDECL(encumber_msg);
|
||||
E int NDECL(doloot);
|
||||
E boolean FDECL(container_gone, (int (*)(OBJ_P)));
|
||||
E boolean NDECL(u_handsy);
|
||||
E int FDECL(use_container, (struct obj **, int));
|
||||
E int FDECL(use_container, (struct obj **, int, BOOLEAN_P));
|
||||
E int FDECL(loot_mon, (struct monst *, int *, boolean *));
|
||||
E int NDECL(dotip);
|
||||
E boolean FDECL(is_autopickup_exception, (struct obj *, BOOLEAN_P));
|
||||
@@ -1788,6 +1794,7 @@ E const char *FDECL(align_str, (ALIGNTYP_P));
|
||||
E void FDECL(mstatusline, (struct monst *));
|
||||
E void NDECL(ustatusline);
|
||||
E void NDECL(self_invis_message);
|
||||
E char *FDECL(piousness, (BOOLEAN_P, const char *));
|
||||
E void FDECL(pudding_merge_message, (struct obj *, struct obj *));
|
||||
|
||||
/* ### polyself.c ### */
|
||||
@@ -1963,6 +1970,7 @@ E NhRegion *FDECL(visible_region_at, (XCHAR_P, XCHAR_P));
|
||||
E void FDECL(show_region, (NhRegion *, XCHAR_P, XCHAR_P));
|
||||
E void FDECL(save_regions, (int, int));
|
||||
E void FDECL(rest_regions, (int, BOOLEAN_P));
|
||||
E void FDECL(region_stats, (const char *, char *, long *, long *));
|
||||
E NhRegion *FDECL(create_gas_cloud, (XCHAR_P, XCHAR_P, int, int));
|
||||
E boolean NDECL(region_danger);
|
||||
E void NDECL(region_safety);
|
||||
@@ -2307,6 +2315,7 @@ E long FDECL(spot_time_left, (XCHAR_P, XCHAR_P, SHORT_P));
|
||||
E boolean FDECL(obj_is_local, (struct obj *));
|
||||
E void FDECL(save_timers, (int, int, int));
|
||||
E void FDECL(restore_timers, (int, int, BOOLEAN_P, long));
|
||||
E void FDECL(timer_stats, (const char *, char *, long *, long *));
|
||||
E void FDECL(relink_timers, (BOOLEAN_P));
|
||||
E int NDECL(wiz_timeout_queue);
|
||||
E void NDECL(timer_sanity_check);
|
||||
@@ -2712,6 +2721,7 @@ E void FDECL(rest_worm, (int));
|
||||
E void FDECL(place_wsegs, (struct monst *));
|
||||
E void FDECL(remove_worm, (struct monst *));
|
||||
E void FDECL(place_worm_tail_randomly, (struct monst *, XCHAR_P, XCHAR_P));
|
||||
E int FDECL(size_wseg, (struct monst *));
|
||||
E int FDECL(count_wsegs, (struct monst *));
|
||||
E boolean FDECL(worm_known, (struct monst *));
|
||||
E boolean FDECL(worm_cross, (int, int, int, int));
|
||||
|
||||
+21
-11
@@ -1,10 +1,10 @@
|
||||
/* NetHack 3.6 flag.h $NHDT-Date: 1457207000 2016/03/05 19:43:20 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.101 $ */
|
||||
/* NetHack 3.6 flag.h $NHDT-Date: 1461102045 2016/04/19 21:40:45 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.103 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
/* If you change the flag structure make sure you increment EDITLEVEL in */
|
||||
/* patchlevel.h if needed. Changing the instance_flags structure does */
|
||||
/* not require incrementing EDITLEVEL. */
|
||||
/* patchlevel.h if needed. Changing the instance_flags structure does */
|
||||
/* not require incrementing EDITLEVEL. */
|
||||
|
||||
#ifndef FLAG_H
|
||||
#define FLAG_H
|
||||
@@ -48,7 +48,7 @@ struct flag {
|
||||
boolean showexp; /* show experience points */
|
||||
boolean showscore; /* show score */
|
||||
boolean silent; /* whether the bell rings or not */
|
||||
boolean sortloot; /* sort items alphabetically when looting */
|
||||
char sortloot; /* 'n'=none, 'l'=loot (pickup), 'f'=full ('l'+invent) */
|
||||
boolean sortpack; /* sorted inventory */
|
||||
boolean sparkle; /* show "resisting" special FX (Scott Bigham) */
|
||||
boolean standout; /* use standout for --More-- */
|
||||
@@ -76,8 +76,10 @@ struct flag {
|
||||
#define NUM_DISCLOSURE_OPTIONS 6 /* i,a,v,g,c,o (decl.c) */
|
||||
#define DISCLOSE_PROMPT_DEFAULT_YES 'y'
|
||||
#define DISCLOSE_PROMPT_DEFAULT_NO 'n'
|
||||
#define DISCLOSE_PROMPT_DEFAULT_SPECIAL '?' /* v, default a */
|
||||
#define DISCLOSE_YES_WITHOUT_PROMPT '+'
|
||||
#define DISCLOSE_NO_WITHOUT_PROMPT '-'
|
||||
#define DISCLOSE_SPECIAL_WITHOUT_PROMPT '#' /* v, use a */
|
||||
char end_disclose[NUM_DISCLOSURE_OPTIONS + 1]; /* disclose various
|
||||
info upon exit */
|
||||
char menu_style; /* User interface style setting */
|
||||
@@ -95,7 +97,7 @@ struct flag {
|
||||
* characters or letters, because that limits us to 26 roles.
|
||||
* They are not booleans, because someday someone may need a neuter
|
||||
* gender. Negative values are used to indicate that the user
|
||||
* hasn't yet specified that particular value. If you determine
|
||||
* hasn't yet specified that particular value. If you determine
|
||||
* that the user wants a random choice, then you should set an
|
||||
* appropriate random value; if you just left the negative value,
|
||||
* the user would be asked again!
|
||||
@@ -184,17 +186,24 @@ struct instance_flags {
|
||||
int purge_monsters; /* # of dead monsters still on fmon list */
|
||||
int override_ID; /* true to force full identification of objects */
|
||||
int suppress_price; /* controls doname() for unpaid objects */
|
||||
int terrainmode; /* for getpos()'s autodescribe when #terrain is active */
|
||||
#define TER_MAP 0x01
|
||||
#define TER_TRP 0x02
|
||||
#define TER_OBJ 0x04
|
||||
#define TER_MON 0x08
|
||||
coord travelcc; /* coordinates for travel_cache */
|
||||
boolean window_inited; /* true if init_nhwindows() completed */
|
||||
boolean vision_inited; /* true if vision is ready */
|
||||
boolean sanity_check; /* run sanity checks */
|
||||
boolean mon_polycontrol; /* debug: control monster polymorphs */
|
||||
/* stuff that is related to options and/or user or platform preferences */
|
||||
|
||||
/* stuff that is related to options and/or user or platform preferences
|
||||
*/
|
||||
unsigned msg_history; /* hint: # of top lines to save */
|
||||
int getpos_coords; /* show coordinates when getting cursor position */
|
||||
int menu_headings; /* ATR for menu headings */
|
||||
int *opt_booldup; /* for duplication of boolean opts in config file */
|
||||
int *opt_compdup; /* for duplication of compound opts in config file */
|
||||
int *opt_compdup; /* for duplication of compound opts in conf file */
|
||||
#ifdef ALTMETA
|
||||
boolean altmeta; /* Alt-c sends ESC c rather than M-c */
|
||||
#endif
|
||||
@@ -222,11 +231,11 @@ struct instance_flags {
|
||||
boolean hilite_pile; /* mark piles of objects with a hilite */
|
||||
boolean autodescribe; /* autodescribe mode in getpos() */
|
||||
#if 0
|
||||
boolean DECgraphics; /* use DEC VT-xxx extended character set */
|
||||
boolean IBMgraphics; /* use IBM extended character set */
|
||||
boolean DECgraphics; /* use DEC VT-xxx extended character set */
|
||||
boolean IBMgraphics; /* use IBM extended character set */
|
||||
#ifdef MAC_GRAPHICS_ENV
|
||||
boolean MACgraphics; /* use Macintosh extended character set, as
|
||||
as defined in the special font HackFont */
|
||||
boolean MACgraphics; /* use Macintosh extended character set, as
|
||||
as defined in the special font HackFont */
|
||||
#endif
|
||||
#endif
|
||||
uchar bouldersym; /* symbol for boulder display */
|
||||
@@ -273,6 +282,7 @@ struct instance_flags {
|
||||
boolean vt_tiledata; /* output console codes for tile support in TTY */
|
||||
#endif
|
||||
boolean wizweight; /* display weight of everything in wizard mode */
|
||||
|
||||
/*
|
||||
* Window capability support.
|
||||
*/
|
||||
|
||||
+14
-2
@@ -318,8 +318,20 @@ NEARDATA extern coord bhitpos; /* place where throw or zap hits or stops */
|
||||
#define BASICENLIGHTENMENT 1 /* show mundane stuff */
|
||||
#define MAGICENLIGHTENMENT 2 /* show intrinsics and such */
|
||||
#define ENL_GAMEINPROGRESS 0
|
||||
#define ENL_GAMEOVERALIVE 1 /* ascension, escape, quit, trickery */
|
||||
#define ENL_GAMEOVERDEAD 2
|
||||
#define ENL_GAMEOVERALIVE 1 /* ascension, escape, quit, trickery */
|
||||
#define ENL_GAMEOVERDEAD 2
|
||||
|
||||
/* control flags for sortloot() */
|
||||
#define SORTLOOT_PACK 0x01
|
||||
#define SORTLOOT_INVLET 0x02
|
||||
#define SORTLOOT_LOOT 0x04
|
||||
|
||||
/* flags for xkilled() [note: meaning of first bit used to be reversed,
|
||||
1 to give message and 0 to suppress] */
|
||||
#define XKILL_GIVEMSG 0
|
||||
#define XKILL_NOMSG 1
|
||||
#define XKILL_NOCORPSE 2
|
||||
#define XKILL_NOCONDUCT 4
|
||||
|
||||
/* Macros for messages referring to hands, eyes, feet, etc... */
|
||||
#define ARM 0
|
||||
|
||||
+72
-71
@@ -1,10 +1,14 @@
|
||||
/* NetHack 3.6 monst.h $NHDT-Date: 1432512777 2015/05/25 00:12:57 $ $NHDT-Branch: master $:$NHDT-Revision: 1.20 $ */
|
||||
/* NetHack 3.6 monst.h $NHDT-Date: 1461028522 2016/04/19 01:15:22 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.24 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
#ifndef MONST_H
|
||||
#define MONST_H
|
||||
|
||||
#ifndef MEXTRA_H
|
||||
#include "mextra.h"
|
||||
#endif
|
||||
|
||||
/* The weapon_check flag is used two ways:
|
||||
* 1) When calling mon_wield_item, is 2-6 depending on what is desired.
|
||||
* 2) Between calls to mon_wield_item, is 0 or 1 depending on whether or not
|
||||
@@ -15,52 +19,48 @@
|
||||
* that there are enough situations which might make a monster change its
|
||||
* weapon that this is impractical. --KAA
|
||||
*/
|
||||
#define NO_WEAPON_WANTED 0
|
||||
#define NEED_WEAPON 1
|
||||
#define NO_WEAPON_WANTED 0
|
||||
#define NEED_WEAPON 1
|
||||
#define NEED_RANGED_WEAPON 2
|
||||
#define NEED_HTH_WEAPON 3
|
||||
#define NEED_PICK_AXE 4
|
||||
#define NEED_AXE 5
|
||||
#define NEED_PICK_OR_AXE 6
|
||||
#define NEED_HTH_WEAPON 3
|
||||
#define NEED_PICK_AXE 4
|
||||
#define NEED_AXE 5
|
||||
#define NEED_PICK_OR_AXE 6
|
||||
|
||||
/* The following flags are used for the second argument to display_minventory
|
||||
* in invent.c:
|
||||
*
|
||||
* PICK_NONE, PICK_ONE, PICK_ANY (wintype.h) 0, 1, 2
|
||||
* MINV_NOLET If set, don't display inventory letters on monster's inventory.
|
||||
* MINV_ALL If set, display all items in monster's inventory, otherwise
|
||||
* just display wielded weapons and worn items.
|
||||
*/
|
||||
#define MINV_NOLET 0x01
|
||||
#define MINV_ALL 0x02
|
||||
|
||||
#ifndef MEXTRA_H
|
||||
#include "mextra.h"
|
||||
#endif
|
||||
#define MINV_PICKMASK 0x03 /* 1|2 */
|
||||
#define MINV_NOLET 0x04
|
||||
#define MINV_ALL 0x08
|
||||
|
||||
struct monst {
|
||||
struct monst *nmon;
|
||||
struct permonst *data;
|
||||
unsigned m_id;
|
||||
short mnum; /* permanent monster index number */
|
||||
short cham; /* if shapeshifter, orig mons[] idx goes here */
|
||||
short movement; /* movement points (derived from permonst definition and
|
||||
added effects */
|
||||
uchar m_lev; /* adjusted difficulty level of monster */
|
||||
aligntyp malign; /* alignment of this monster, relative to the
|
||||
player (positive = good to kill) */
|
||||
short mnum; /* permanent monster index number */
|
||||
short cham; /* if shapeshifter, orig mons[] idx goes here */
|
||||
short movement; /* movement points (derived from permonst definition
|
||||
and added effects */
|
||||
uchar m_lev; /* adjusted difficulty level of monster */
|
||||
aligntyp malign; /* alignment of this monster, relative to the
|
||||
player (positive = good to kill) */
|
||||
xchar mx, my;
|
||||
xchar mux, muy; /* where the monster thinks you are */
|
||||
xchar mux, muy; /* where the monster thinks you are */
|
||||
#define MTSZ 4
|
||||
coord mtrack[MTSZ]; /* monster track */
|
||||
coord mtrack[MTSZ]; /* monster track */
|
||||
int mhp, mhpmax;
|
||||
unsigned mappearance; /* for undetected mimics and the wiz */
|
||||
uchar m_ap_type; /* what mappearance is describing: */
|
||||
#define M_AP_NOTHING \
|
||||
0 /* mappearance is unused -- monster appears \
|
||||
as itself */
|
||||
#define M_AP_FURNITURE 1 /* stairs, a door, an altar, etc. */
|
||||
#define M_AP_OBJECT 2 /* an object */
|
||||
#define M_AP_MONSTER 3 /* a monster */
|
||||
#define M_AP_NOTHING 0 /* mappearance unused--monster appears as itself */
|
||||
#define M_AP_FURNITURE 1 /* stairs, a door, an altar, etc. */
|
||||
#define M_AP_OBJECT 2 /* an object */
|
||||
#define M_AP_MONSTER 3 /* a monster */
|
||||
|
||||
schar mtame; /* level of tameness, implies peaceful */
|
||||
unsigned short mintrinsics; /* low 8 correspond to mresists */
|
||||
@@ -72,12 +72,12 @@ struct monst {
|
||||
Bitfield(perminvis, 1); /* intrinsic minvis value */
|
||||
Bitfield(mcan, 1); /* has been cancelled */
|
||||
Bitfield(mburied, 1); /* has been buried */
|
||||
Bitfield(mundetected, 1); /* not seen in present hiding place */
|
||||
/* implies one of M1_CONCEAL or M1_HIDE,
|
||||
Bitfield(mundetected, 1); /* not seen in present hiding place;
|
||||
* implies one of M1_CONCEAL or M1_HIDE,
|
||||
* but not mimic (that is, snake, spider,
|
||||
* trapper, piercer, eel)
|
||||
*/
|
||||
Bitfield(mcansee, 1); /* cansee 1, temp.blinded 0, blind 0 */
|
||||
Bitfield(mcansee, 1); /* cansee 1, temp.blinded 0, blind 0 */
|
||||
|
||||
Bitfield(mspeed, 2); /* current speed */
|
||||
Bitfield(permspeed, 2); /* intrinsic mspeed value */
|
||||
@@ -89,11 +89,11 @@ struct monst {
|
||||
Bitfield(mfleetim, 7); /* timeout for mflee */
|
||||
Bitfield(msleeping, 1); /* asleep until woken */
|
||||
|
||||
Bitfield(mblinded, 7); /* cansee 0, temp.blinded n, blind 0 */
|
||||
Bitfield(mstun, 1); /* stunned (off balance) */
|
||||
Bitfield(mblinded, 7); /* cansee 0, temp.blinded n, blind 0 */
|
||||
Bitfield(mstun, 1); /* stunned (off balance) */
|
||||
|
||||
Bitfield(mfrozen, 7);
|
||||
Bitfield(mcanmove, 1); /* paralysis, similar to mblinded */
|
||||
Bitfield(mcanmove, 1); /* paralysis, similar to mblinded */
|
||||
|
||||
Bitfield(mconf, 1); /* confused */
|
||||
Bitfield(mpeaceful, 1); /* does not attack unprovoked */
|
||||
@@ -102,13 +102,13 @@ struct monst {
|
||||
Bitfield(isshk, 1); /* is shopkeeper */
|
||||
Bitfield(isminion, 1); /* is a minion */
|
||||
Bitfield(isgd, 1); /* is guard */
|
||||
Bitfield(ispriest, 1); /* is a priest */
|
||||
Bitfield(ispriest, 1); /* is an aligned priest or high priest */
|
||||
|
||||
Bitfield(iswiz, 1); /* is the Wizard of Yendor */
|
||||
Bitfield(wormno, 5); /* at most 31 worms on any level */
|
||||
/* 2 free bits */
|
||||
Bitfield(iswiz, 1); /* is the Wizard of Yendor */
|
||||
Bitfield(wormno, 5); /* at most 31 worms on any level */
|
||||
/* 2 free bits */
|
||||
|
||||
#define MAX_NUM_WORMS 32 /* should be 2^(wormno bitfield size) */
|
||||
#define MAX_NUM_WORMS 32 /* should be 2^(wormno bitfield size) */
|
||||
|
||||
unsigned long mstrategy; /* for monsters with mflag3: current strategy */
|
||||
#ifdef NHSTDC
|
||||
@@ -116,39 +116,39 @@ struct monst {
|
||||
#else
|
||||
#define STRAT_APPEARMSG 0x80000000L
|
||||
#endif
|
||||
#define STRAT_ARRIVE 0x40000000L /* just arrived on current level */
|
||||
#define STRAT_WAITFORU 0x20000000L
|
||||
#define STRAT_CLOSE 0x10000000L
|
||||
#define STRAT_WAITMASK (STRAT_CLOSE | STRAT_WAITFORU)
|
||||
#define STRAT_HEAL 0x08000000L
|
||||
#define STRAT_GROUND 0x04000000L
|
||||
#define STRAT_MONSTR 0x02000000L
|
||||
#define STRAT_PLAYER 0x01000000L
|
||||
#define STRAT_NONE 0x00000000L
|
||||
#define STRAT_ARRIVE 0x40000000L /* just arrived on current level */
|
||||
#define STRAT_WAITFORU 0x20000000L
|
||||
#define STRAT_CLOSE 0x10000000L
|
||||
#define STRAT_WAITMASK (STRAT_CLOSE | STRAT_WAITFORU)
|
||||
#define STRAT_HEAL 0x08000000L
|
||||
#define STRAT_GROUND 0x04000000L
|
||||
#define STRAT_MONSTR 0x02000000L
|
||||
#define STRAT_PLAYER 0x01000000L
|
||||
#define STRAT_NONE 0x00000000L
|
||||
#define STRAT_STRATMASK 0x0f000000L
|
||||
#define STRAT_XMASK 0x00ff0000L
|
||||
#define STRAT_YMASK 0x0000ff00L
|
||||
#define STRAT_GOAL 0x000000ffL
|
||||
#define STRAT_GOALX(s) ((xchar)((s & STRAT_XMASK) >> 16))
|
||||
#define STRAT_GOALY(s) ((xchar)((s & STRAT_YMASK) >> 8))
|
||||
#define STRAT_XMASK 0x00ff0000L
|
||||
#define STRAT_YMASK 0x0000ff00L
|
||||
#define STRAT_GOAL 0x000000ffL
|
||||
#define STRAT_GOALX(s) ((xchar) ((s & STRAT_XMASK) >> 16))
|
||||
#define STRAT_GOALY(s) ((xchar) ((s & STRAT_YMASK) >> 8))
|
||||
|
||||
long mtrapseen; /* bitmap of traps we've been trapped in */
|
||||
long mlstmv; /* for catching up with lost time */
|
||||
long mtrapseen; /* bitmap of traps we've been trapped in */
|
||||
long mlstmv; /* for catching up with lost time */
|
||||
long mspare1;
|
||||
struct obj *minvent;
|
||||
struct obj *minvent; /* mon's inventory */
|
||||
|
||||
struct obj *mw;
|
||||
long misc_worn_check;
|
||||
xchar weapon_check;
|
||||
struct obj *mw; /* mon's weapon */
|
||||
long misc_worn_check; /* mon's wornmask */
|
||||
xchar weapon_check; /* flag for whether to try switching weapons */
|
||||
|
||||
int meating; /* monster is eating timeout */
|
||||
struct mextra *mextra; /* point to mextra struct */
|
||||
};
|
||||
|
||||
#define newmonst() (struct monst *) alloc(sizeof(struct monst))
|
||||
#define newmonst() (struct monst *) alloc(sizeof (struct monst))
|
||||
|
||||
/* these are in mspeed */
|
||||
#define MSLOW 1 /* slow monster */
|
||||
#define MSLOW 1 /* slowed monster */
|
||||
#define MFAST 2 /* speeded monster */
|
||||
|
||||
#define MON_WEP(mon) ((mon)->mw)
|
||||
@@ -161,16 +161,17 @@ struct monst {
|
||||
|| (mon)->cham == PM_VLAD_THE_IMPALER)
|
||||
|
||||
/* mimic appearances that block vision/light */
|
||||
#define is_lightblocker_mappear(mon) \
|
||||
(is_obj_mappear(mon, BOULDER) || \
|
||||
((mon)->m_ap_type == M_AP_FURNITURE \
|
||||
&& ((mon)->mappearance == S_hcdoor \
|
||||
|| (mon)->mappearance == S_vcdoor \
|
||||
|| (mon)->mappearance < S_ndoor /* = walls */ \
|
||||
|| (mon)->mappearance == S_tree)))
|
||||
|
||||
#define is_lightblocker_mappear(mon) \
|
||||
(is_obj_mappear(mon, BOULDER) \
|
||||
|| ((mon)->m_ap_type == M_AP_FURNITURE \
|
||||
&& ((mon)->mappearance == S_hcdoor \
|
||||
|| (mon)->mappearance == S_vcdoor \
|
||||
|| (mon)->mappearance < S_ndoor /* = walls */ \
|
||||
|| (mon)->mappearance == S_tree)))
|
||||
#define is_door_mappear(mon) ((mon)->m_ap_type == M_AP_FURNITURE \
|
||||
&& ((mon)->mappearance == S_hcdoor || (mon)->mappearance == S_vcdoor))
|
||||
&& ((mon)->mappearance == S_hcdoor \
|
||||
|| (mon)->mappearance == S_vcdoor))
|
||||
#define is_obj_mappear(mon,otyp) ((mon)->m_ap_type == M_AP_OBJECT \
|
||||
&& (mon)->mappearance == (otyp))
|
||||
&& (mon)->mappearance == (otyp))
|
||||
|
||||
#endif /* MONST_H */
|
||||
|
||||
+8
-7
@@ -40,12 +40,13 @@ struct obj {
|
||||
unsigned owt;
|
||||
long quan; /* number of items */
|
||||
|
||||
schar spe; /* quality of weapon, armor or ring (+ or -)
|
||||
number of charges for wand ( >= -1 )
|
||||
marks your eggs, tin variety and spinach tins
|
||||
royal coffers for a court ( == 2)
|
||||
tells which fruit a fruit is
|
||||
special for uball and amulet
|
||||
schar spe; /* quality of weapon, armor or ring (+ or -);
|
||||
number of charges for wand or charged tool ( >= -1 );
|
||||
marks your eggs, tin variety and spinach tins;
|
||||
Schroedinger's Box (1) or royal coffers for a court (2);
|
||||
tells which fruit a fruit is;
|
||||
special for uball and amulet;
|
||||
scroll of mail (normal==0, bones or wishing==1, written==2);
|
||||
historic and gender for statues */
|
||||
#define STATUE_HISTORIC 0x01
|
||||
#define STATUE_MALE 0x02
|
||||
@@ -336,7 +337,7 @@ struct obj {
|
||||
|
||||
/* helpers, simple enough to be macros */
|
||||
#define is_plural(o) \
|
||||
((o)->quan > 1 || (o)->oartifact == ART_EYES_OF_THE_OVERWORLD)
|
||||
((o)->quan != 1L || (o)->otyp == LENSES || is_gloves(o) || is_boots(o))
|
||||
|
||||
/* Flags for get_obj_location(). */
|
||||
#define CONTAINED_TOO 0x1
|
||||
|
||||
+16
-16
@@ -1,28 +1,28 @@
|
||||
/* NetHack 3.6 objclass.h $NHDT-Date: 1447755971 2015/11/17 10:26:11 $ $NHDT-Branch: master $:$NHDT-Revision: 1.15 $ */
|
||||
/* NetHack 3.6 objclass.h $NHDT-Date: 1462067744 2016/05/01 01:55:44 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.16 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
#ifndef OBJCLASS_H
|
||||
#define OBJCLASS_H
|
||||
|
||||
/* definition of a class of objects */
|
||||
/* [misnamed] definition of a type of object */
|
||||
|
||||
struct objclass {
|
||||
short oc_name_idx; /* index of actual name */
|
||||
short oc_descr_idx; /* description when name unknown */
|
||||
char *oc_uname; /* called by user */
|
||||
short oc_name_idx; /* index of actual name */
|
||||
short oc_descr_idx; /* description when name unknown */
|
||||
char *oc_uname; /* called by user */
|
||||
Bitfield(oc_name_known, 1);
|
||||
Bitfield(oc_merge, 1); /* merge otherwise equal objects */
|
||||
Bitfield(oc_uses_known, 1); /* obj->known affects full description */
|
||||
/* otherwise, obj->dknown and obj->bknown */
|
||||
/* tell all, and obj->known should always */
|
||||
/* be set for proper merging behavior */
|
||||
Bitfield(oc_pre_discovered, 1); /* Already known at start of game; */
|
||||
/* won't be listed as a discovery. */
|
||||
Bitfield(oc_magic, 1); /* inherently magical object */
|
||||
Bitfield(oc_charged, 1); /* may have +n or (n) charges */
|
||||
Bitfield(oc_unique, 1); /* special one-of-a-kind object */
|
||||
Bitfield(oc_nowish, 1); /* cannot wish for this object */
|
||||
Bitfield(oc_merge, 1); /* merge otherwise equal objects */
|
||||
Bitfield(oc_uses_known, 1); /* obj->known affects full description;
|
||||
otherwise, obj->dknown and obj->bknown
|
||||
tell all, and obj->known should always
|
||||
be set for proper merging behavior. */
|
||||
Bitfield(oc_pre_discovered, 1); /* Already known at start of game;
|
||||
won't be listed as a discovery. */
|
||||
Bitfield(oc_magic, 1); /* inherently magical object */
|
||||
Bitfield(oc_charged, 1); /* may have +n or (n) charges */
|
||||
Bitfield(oc_unique, 1); /* special one-of-a-kind object */
|
||||
Bitfield(oc_nowish, 1); /* cannot wish for this object */
|
||||
|
||||
Bitfield(oc_big, 1);
|
||||
#define oc_bimanual oc_big /* for weapons & tools used as weapons */
|
||||
|
||||
+6
-5
@@ -218,12 +218,13 @@ enum opcode_defs {
|
||||
#define SP_COORD_IS_RANDOM 0x01000000
|
||||
/* Humidity flags for get_location() and friends, used with
|
||||
* SP_COORD_PACK_RANDOM() */
|
||||
#define DRY 0x1
|
||||
#define WET 0x2
|
||||
#define HOT 0x4
|
||||
#define SOLID 0x8
|
||||
#define ANY_LOC 0x10 /* even outside the level */
|
||||
#define DRY 0x01
|
||||
#define WET 0x02
|
||||
#define HOT 0x04
|
||||
#define SOLID 0x08
|
||||
#define ANY_LOC 0x10 /* even outside the level */
|
||||
#define NO_LOC_WARN 0x20 /* no complaints and set x & y to -1, if no loc */
|
||||
#define SPACELOC 0x40 /* like DRY, but accepts furniture too */
|
||||
|
||||
#define SP_COORD_X(l) (l & 0xff)
|
||||
#define SP_COORD_Y(l) ((l >> 16) & 0xff)
|
||||
|
||||
+2
-1
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 wintype.h $NHDT-Date: 1433207914 2015/06/02 01:18:34 $ $NHDT-Branch: master $:$NHDT-Revision: 1.15 $ */
|
||||
/* NetHack 3.6 wintype.h $NHDT-Date: 1461028538 2016/04/19 01:15:38 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.16 $ */
|
||||
/* Copyright (c) David Cohrs, 1991 */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -56,6 +56,7 @@ typedef struct mi {
|
||||
#define MENU_ITEM_P struct mi
|
||||
|
||||
/* select_menu() "how" argument types */
|
||||
/* [MINV_PICKMASK in monst.h assumes these have values of 0, 1, 2] */
|
||||
#define PICK_NONE 0 /* user picks nothing (display only) */
|
||||
#define PICK_ONE 1 /* only pick one */
|
||||
#define PICK_ANY 2 /* can pick any amount */
|
||||
|
||||
+25
-1
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 allmain.c $NHDT-Date: 1451955079 2016/01/05 00:51:19 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.70 $ */
|
||||
/* NetHack 3.6 allmain.c $NHDT-Date: 1463217182 2016/05/14 09:13:02 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.72 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#ifdef POSITIONBAR
|
||||
STATIC_DCL void NDECL(do_positionbar);
|
||||
#endif
|
||||
STATIC_DCL void FDECL(interrupt_multi, (const char *));
|
||||
|
||||
void
|
||||
moveloop(resuming)
|
||||
@@ -216,6 +217,8 @@ boolean resuming;
|
||||
|| (wtcap < MOD_ENCUMBER && !(moves % 20))) {
|
||||
context.botl = 1;
|
||||
u.mh++;
|
||||
if (u.mh >= u.mhmax)
|
||||
interrupt_multi("You are in full health.");
|
||||
}
|
||||
} else if (u.uhp < u.uhpmax
|
||||
&& (wtcap < MOD_ENCUMBER || !u.umoved
|
||||
@@ -234,6 +237,8 @@ boolean resuming;
|
||||
u.uhp += heal;
|
||||
if (u.uhp > u.uhpmax)
|
||||
u.uhp = u.uhpmax;
|
||||
if (u.uhp >= u.uhpmax)
|
||||
interrupt_multi("You are in full health.");
|
||||
} else if (Regeneration
|
||||
|| (u.ulevel <= 9
|
||||
&& !(moves
|
||||
@@ -241,6 +246,8 @@ boolean resuming;
|
||||
+ 1)))) {
|
||||
context.botl = 1;
|
||||
u.uhp++;
|
||||
if (u.uhp >= u.uhpmax)
|
||||
interrupt_multi("You are in full health.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,6 +277,8 @@ boolean resuming;
|
||||
if (u.uen > u.uenmax)
|
||||
u.uen = u.uenmax;
|
||||
context.botl = 1;
|
||||
if (u.uen >= u.uenmax)
|
||||
interrupt_multi("You feel full of energy.");
|
||||
}
|
||||
|
||||
if (!u.uinvulnerable) {
|
||||
@@ -506,6 +515,9 @@ display_gamewindows()
|
||||
#endif
|
||||
WIN_MAP = create_nhwindow(NHW_MAP);
|
||||
WIN_INVEN = create_nhwindow(NHW_MENU);
|
||||
/* in case of early quit where WIN_INVEN could be destroyed before
|
||||
ever having been used, use it here to pacify the Qt interface */
|
||||
start_menu(WIN_INVEN), end_menu(WIN_INVEN, (char *) 0);
|
||||
|
||||
#ifdef MAC
|
||||
/* This _is_ the right place for this - maybe we will
|
||||
@@ -687,4 +699,16 @@ do_positionbar()
|
||||
}
|
||||
#endif
|
||||
|
||||
STATIC_DCL void
|
||||
interrupt_multi(msg)
|
||||
const char *msg;
|
||||
{
|
||||
if (multi > 0 && !context.travel) {
|
||||
nomul(0);
|
||||
if (flags.verbose && msg)
|
||||
Norep("%s", msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*allmain.c*/
|
||||
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 apply.c $NHDT-Date: 1457207021 2016/03/05 19:43:41 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.223 $ */
|
||||
/* NetHack 3.6 apply.c $NHDT-Date: 1457397477 2016/03/08 00:37:57 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.224 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -737,7 +737,7 @@ register xchar x, y;
|
||||
that's the result of his actions; gain experience,
|
||||
lose pacifism, take alignment and luck hit, make
|
||||
corpse less likely to remain tame after revival */
|
||||
xkilled(mtmp, 0); /* no "you kill it" message */
|
||||
xkilled(mtmp, XKILL_NOMSG);
|
||||
/* life-saving doesn't ordinarily reset this */
|
||||
if (mtmp->mhp > 0)
|
||||
u.uconduct.killer = save_pacifism;
|
||||
@@ -3430,7 +3430,7 @@ doapply()
|
||||
case SACK:
|
||||
case BAG_OF_HOLDING:
|
||||
case OILSKIN_SACK:
|
||||
res = use_container(&obj, 1);
|
||||
res = use_container(&obj, 1, FALSE);
|
||||
break;
|
||||
case BAG_OF_TRICKS:
|
||||
(void) bagotricks(obj, FALSE, (int *) 0);
|
||||
|
||||
+68
-96
@@ -101,6 +101,7 @@ static const struct innate {
|
||||
|
||||
STATIC_DCL void NDECL(exerper);
|
||||
STATIC_DCL void FDECL(postadjabil, (long *));
|
||||
STATIC_DCL const struct innate *FDECL(role_abil, (int));
|
||||
STATIC_DCL const struct innate *FDECL(check_innate_abil, (long *, long));
|
||||
STATIC_DCL int FDECL(innately, (long *));
|
||||
|
||||
@@ -644,6 +645,34 @@ long *ability;
|
||||
see_monsters();
|
||||
}
|
||||
|
||||
STATIC_OVL const struct innate *
|
||||
role_abil(r)
|
||||
int r;
|
||||
{
|
||||
const struct {
|
||||
short role;
|
||||
const struct innate *abil;
|
||||
} roleabils[] = {
|
||||
{ PM_ARCHEOLOGIST, arc_abil },
|
||||
{ PM_BARBARIAN, bar_abil },
|
||||
{ PM_CAVEMAN, cav_abil },
|
||||
{ PM_HEALER, hea_abil },
|
||||
{ PM_KNIGHT, kni_abil },
|
||||
{ PM_MONK, mon_abil },
|
||||
{ PM_PRIEST, pri_abil },
|
||||
{ PM_RANGER, ran_abil },
|
||||
{ PM_ROGUE, rog_abil },
|
||||
{ PM_SAMURAI, sam_abil },
|
||||
{ PM_TOURIST, tou_abil },
|
||||
{ PM_VALKYRIE, val_abil },
|
||||
{ PM_WIZARD, wiz_abil },
|
||||
{ 0, 0 }
|
||||
};
|
||||
int i;
|
||||
for (i = 0; roleabils[i].abil && roleabils[i].role != r; i++);
|
||||
return roleabils[i].abil;
|
||||
}
|
||||
|
||||
STATIC_OVL const struct innate *
|
||||
check_innate_abil(ability, frommask)
|
||||
long *ability;
|
||||
@@ -652,49 +681,7 @@ long frommask;
|
||||
const struct innate *abil = 0;
|
||||
|
||||
if (frommask == FROMEXPER)
|
||||
switch (Role_switch) {
|
||||
case PM_ARCHEOLOGIST:
|
||||
abil = arc_abil;
|
||||
break;
|
||||
case PM_BARBARIAN:
|
||||
abil = bar_abil;
|
||||
break;
|
||||
case PM_CAVEMAN:
|
||||
abil = cav_abil;
|
||||
break;
|
||||
case PM_HEALER:
|
||||
abil = hea_abil;
|
||||
break;
|
||||
case PM_KNIGHT:
|
||||
abil = kni_abil;
|
||||
break;
|
||||
case PM_MONK:
|
||||
abil = mon_abil;
|
||||
break;
|
||||
case PM_PRIEST:
|
||||
abil = pri_abil;
|
||||
break;
|
||||
case PM_RANGER:
|
||||
abil = ran_abil;
|
||||
break;
|
||||
case PM_ROGUE:
|
||||
abil = rog_abil;
|
||||
break;
|
||||
case PM_SAMURAI:
|
||||
abil = sam_abil;
|
||||
break;
|
||||
case PM_TOURIST:
|
||||
abil = tou_abil;
|
||||
break;
|
||||
case PM_VALKYRIE:
|
||||
abil = val_abil;
|
||||
break;
|
||||
case PM_WIZARD:
|
||||
abil = wiz_abil;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
abil = role_abil(Role_switch);
|
||||
else if (frommask == FROMRACE)
|
||||
switch (Race_switch) {
|
||||
case PM_DWARF:
|
||||
@@ -728,10 +715,10 @@ long frommask;
|
||||
#define FROM_NONE 0
|
||||
#define FROM_ROLE 1 /* from experience at level 1 */
|
||||
#define FROM_RACE 2
|
||||
#define FROM_EXP 3 /* from experience for some level > 1 */
|
||||
#define FROM_FORM 4
|
||||
#define FROM_LYCN 5
|
||||
|
||||
#define FROM_INTR 3 /* intrinsically (eating some corpse or prayer reward) */
|
||||
#define FROM_EXP 4 /* from experience for some level > 1 */
|
||||
#define FROM_FORM 5
|
||||
#define FROM_LYCN 6
|
||||
|
||||
/* check whether particular ability has been obtained via innate attribute */
|
||||
STATIC_OVL int
|
||||
@@ -744,6 +731,8 @@ long *ability;
|
||||
return (iptr->ulevel == 1) ? FROM_ROLE : FROM_EXP;
|
||||
if ((iptr = check_innate_abil(ability, FROMRACE)) != 0)
|
||||
return FROM_RACE;
|
||||
if ((*ability & FROMOUTSIDE) != 0L)
|
||||
return FROM_INTR;
|
||||
if ((*ability & FROMFORM) != 0L)
|
||||
return FROM_FORM;
|
||||
return FROM_NONE;
|
||||
@@ -758,6 +747,8 @@ int propidx;
|
||||
/* innately() would report FROM_FORM for this; caller wants specificity */
|
||||
if (propidx == DRAIN_RES && u.ulycn >= LOW_PM)
|
||||
return FROM_LYCN;
|
||||
if (propidx == FAST && Very_fast)
|
||||
return FROM_NONE; /* can't become very fast innately */
|
||||
if ((innateness = innately(&u.uprops[propidx].intrinsic)) != FROM_NONE)
|
||||
return innateness;
|
||||
if (propidx == JUMPING && Role_if(PM_KNIGHT)
|
||||
@@ -788,21 +779,45 @@ int propidx; /* special cases can have negative values */
|
||||
struct obj *obj = (struct obj *) 0;
|
||||
int innateness = is_innate(propidx);
|
||||
|
||||
if (innateness == FROM_EXP)
|
||||
/*
|
||||
* Properties can be obtained from multiple sources and we
|
||||
* try to pick the most significant one. Classification
|
||||
* priority is not set in stone; current precedence is:
|
||||
* "from the start" (from role or race at level 1),
|
||||
* "from outside" (eating corpse, divine reward, blessed potion),
|
||||
* "from experience" (from role or race at level 2+),
|
||||
* "from current form" (while polymorphed),
|
||||
* "from timed effect" (potion or spell),
|
||||
* "from worn/wielded equipment" (Firebrand, elven boots, &c),
|
||||
* "from carried equipment" (mainly quest artifacts).
|
||||
* There are exceptions. Versatile jumping from spell or boots
|
||||
* takes priority over knight's innate but limited jumping.
|
||||
*/
|
||||
if (propidx == BLINDED && u.uroleplay.blind)
|
||||
Sprintf(buf, " from birth");
|
||||
else if (innateness == FROM_ROLE || innateness == FROM_RACE)
|
||||
Strcpy(buf, " innately");
|
||||
else if (innateness == FROM_INTR) /* [].intrinsic & FROMOUTSIDE */
|
||||
Strcpy(buf, " intrinsically");
|
||||
else if (innateness == FROM_EXP)
|
||||
Strcpy(buf, " because of your experience");
|
||||
else if (innateness == FROM_LYCN)
|
||||
Strcpy(buf, " due to your lycanthropy");
|
||||
else if (innateness == FROM_FORM)
|
||||
Strcpy(buf, " from current creature form");
|
||||
else if (innateness == FROM_ROLE || innateness == FROM_RACE)
|
||||
Strcpy(buf, " innately");
|
||||
else if (propidx == FAST && Very_fast)
|
||||
Sprintf(buf, because_of,
|
||||
((HFast & TIMEOUT) != 0L) ? "a potion or spell"
|
||||
: ((EFast & W_ARMF) != 0L && uarmf->dknown
|
||||
&& objects[uarmf->otyp].oc_name_known)
|
||||
? ysimple_name(uarmf) /* speed boots */
|
||||
: EFast ? "worn equipment"
|
||||
: something);
|
||||
else if (wizard
|
||||
&& (obj = what_gives(&u.uprops[propidx].extrinsic)) != 0)
|
||||
Sprintf(buf, because_of, obj->oartifact
|
||||
? bare_artifactname(obj)
|
||||
: ysimple_name(obj));
|
||||
else if (propidx == BLINDED && u.uroleplay.blind)
|
||||
Sprintf(buf, " from birth");
|
||||
else if (propidx == BLINDED && Blindfolded_only)
|
||||
Sprintf(buf, because_of, ysimple_name(ublindf));
|
||||
|
||||
@@ -846,50 +861,7 @@ int oldlevel, newlevel;
|
||||
register const struct innate *abil, *rabil;
|
||||
long prevabil, mask = FROMEXPER;
|
||||
|
||||
switch (Role_switch) {
|
||||
case PM_ARCHEOLOGIST:
|
||||
abil = arc_abil;
|
||||
break;
|
||||
case PM_BARBARIAN:
|
||||
abil = bar_abil;
|
||||
break;
|
||||
case PM_CAVEMAN:
|
||||
abil = cav_abil;
|
||||
break;
|
||||
case PM_HEALER:
|
||||
abil = hea_abil;
|
||||
break;
|
||||
case PM_KNIGHT:
|
||||
abil = kni_abil;
|
||||
break;
|
||||
case PM_MONK:
|
||||
abil = mon_abil;
|
||||
break;
|
||||
case PM_PRIEST:
|
||||
abil = pri_abil;
|
||||
break;
|
||||
case PM_RANGER:
|
||||
abil = ran_abil;
|
||||
break;
|
||||
case PM_ROGUE:
|
||||
abil = rog_abil;
|
||||
break;
|
||||
case PM_SAMURAI:
|
||||
abil = sam_abil;
|
||||
break;
|
||||
case PM_TOURIST:
|
||||
abil = tou_abil;
|
||||
break;
|
||||
case PM_VALKYRIE:
|
||||
abil = val_abil;
|
||||
break;
|
||||
case PM_WIZARD:
|
||||
abil = wiz_abil;
|
||||
break;
|
||||
default:
|
||||
abil = 0;
|
||||
break;
|
||||
}
|
||||
abil = role_abil(Role_switch);
|
||||
|
||||
switch (Race_switch) {
|
||||
case PM_ELF:
|
||||
|
||||
@@ -144,17 +144,18 @@ extern void FDECL(show_borlandc_stats, (winid));
|
||||
#ifdef DEBUG_MIGRATING_MONS
|
||||
STATIC_PTR int NDECL(wiz_migrate_mons);
|
||||
#endif
|
||||
STATIC_DCL int FDECL(size_monst, (struct monst *));
|
||||
STATIC_DCL int FDECL(size_monst, (struct monst *, BOOLEAN_P));
|
||||
STATIC_DCL int FDECL(size_obj, (struct obj *));
|
||||
STATIC_DCL void FDECL(count_obj, (struct obj *, long *, long *,
|
||||
BOOLEAN_P, BOOLEAN_P));
|
||||
STATIC_DCL void FDECL(obj_chain, (winid, const char *, struct obj *,
|
||||
long *, long *));
|
||||
BOOLEAN_P, long *, long *));
|
||||
STATIC_DCL void FDECL(mon_invent_chain, (winid, const char *, struct monst *,
|
||||
long *, long *));
|
||||
STATIC_DCL void FDECL(mon_chain, (winid, const char *, struct monst *,
|
||||
long *, long *));
|
||||
STATIC_DCL void FDECL(contained, (winid, const char *, long *, long *));
|
||||
BOOLEAN_P, long *, long *));
|
||||
STATIC_DCL void FDECL(contained_stats, (winid, const char *, long *, long *));
|
||||
STATIC_DCL void FDECL(misc_stats, (winid, long *, long *));
|
||||
STATIC_PTR int NDECL(wiz_show_stats);
|
||||
STATIC_DCL boolean FDECL(accept_menu_prefix, (int NDECL((*))));
|
||||
#ifdef PORT_DEBUG
|
||||
@@ -1124,7 +1125,8 @@ wiz_intrinsic(VOID_ARGS)
|
||||
for (i = 0; i < SIZE(intrinsics); ++i) {
|
||||
accelerator = intrinsics[i][0];
|
||||
any.a_int = i + 1;
|
||||
add_menu(win, NO_GLYPH, &any, accelerator, 0, ATR_NONE, intrinsics[i], FALSE);
|
||||
add_menu(win, NO_GLYPH, &any, accelerator, 0,
|
||||
ATR_NONE, intrinsics[i], FALSE);
|
||||
}
|
||||
end_menu(win, "Which intrinsic?");
|
||||
n = select_menu(win, PICK_ONE, &pick_list);
|
||||
@@ -1137,7 +1139,7 @@ wiz_intrinsic(VOID_ARGS)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(intrinsics[i],"deafness")) {
|
||||
if (!strcmp(intrinsics[i], "deafness")) {
|
||||
You("go deaf.");
|
||||
incr_itimeout(&HDeaf, 30);
|
||||
context.botl = TRUE;
|
||||
@@ -1224,13 +1226,26 @@ doterrain(VOID_ARGS)
|
||||
free((genericptr_t) sel);
|
||||
|
||||
switch (which) {
|
||||
case 1: reveal_terrain(0, 0); break; /* known map */
|
||||
case 2: reveal_terrain(0, 1); break; /* known map with traps */
|
||||
case 3: reveal_terrain(0, 1|2); break; /* known map w/ traps & objs */
|
||||
case 4: reveal_terrain(1, 0); break; /* full map */
|
||||
case 5: wiz_map_levltyp(); break; /* map internals */
|
||||
case 6: wiz_levltyp_legend(); break; /* internal details */
|
||||
default: break;
|
||||
case 1: /* known map */
|
||||
reveal_terrain(0, TER_MAP);
|
||||
break;
|
||||
case 2: /* known map with known traps */
|
||||
reveal_terrain(0, TER_MAP | TER_TRP);
|
||||
break;
|
||||
case 3: /* known map with known traps and objects */
|
||||
reveal_terrain(0, TER_MAP | TER_TRP | TER_OBJ);
|
||||
break;
|
||||
case 4: /* full map */
|
||||
reveal_terrain(1, TER_MAP);
|
||||
break;
|
||||
case 5: /* map internals */
|
||||
wiz_map_levltyp();
|
||||
break;
|
||||
case 6: /* internal details */
|
||||
wiz_levltyp_legend();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0; /* no time elapses */
|
||||
}
|
||||
@@ -1948,27 +1963,12 @@ int final;
|
||||
you_are(hofe_titles[u.uevent.uhand_of_elbereth - 1], "");
|
||||
}
|
||||
|
||||
/* note: piousness 20 matches MIN_QUEST_ALIGN (quest.h) */
|
||||
if (u.ualign.record >= 20)
|
||||
you_are("piously aligned", "");
|
||||
else if (u.ualign.record > 13)
|
||||
you_are("devoutly aligned", "");
|
||||
else if (u.ualign.record > 8)
|
||||
you_are("fervently aligned", "");
|
||||
else if (u.ualign.record > 3)
|
||||
you_are("stridently aligned", "");
|
||||
else if (u.ualign.record == 3)
|
||||
you_are("aligned", "");
|
||||
else if (u.ualign.record > 0)
|
||||
you_are("haltingly aligned", "");
|
||||
else if (u.ualign.record == 0)
|
||||
you_are("nominally aligned", "");
|
||||
else if (u.ualign.record >= -3)
|
||||
you_have("strayed", "");
|
||||
else if (u.ualign.record >= -8)
|
||||
you_have("sinned", "");
|
||||
Sprintf(buf, "%s", piousness(TRUE, "aligned"));
|
||||
if (u.ualign.record >= 0)
|
||||
you_are(buf, "");
|
||||
else
|
||||
you_have("transgressed", "");
|
||||
you_have(buf, "");
|
||||
|
||||
if (wizard) {
|
||||
Sprintf(buf, " %d", u.ualign.record);
|
||||
enl_msg("Your alignment ", "is", "was", buf, "");
|
||||
@@ -2904,9 +2904,9 @@ int NDECL((*fn));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char template[] = "%-18s %4ld %6ld";
|
||||
static const char count_str[] = " count bytes";
|
||||
static const char separator[] = "------------------ ----- ------";
|
||||
static const char template[] = "%-27s %4ld %6ld";
|
||||
static const char stats_hdr[] = " count bytes";
|
||||
static const char stats_sep[] = "--------------------------- ----- -------";
|
||||
|
||||
STATIC_OVL int
|
||||
size_obj(otmp)
|
||||
@@ -2954,21 +2954,25 @@ boolean recurse;
|
||||
}
|
||||
|
||||
STATIC_OVL void
|
||||
obj_chain(win, src, chain, total_count, total_size)
|
||||
obj_chain(win, src, chain, force, total_count, total_size)
|
||||
winid win;
|
||||
const char *src;
|
||||
struct obj *chain;
|
||||
boolean force;
|
||||
long *total_count;
|
||||
long *total_size;
|
||||
{
|
||||
char buf[BUFSZ];
|
||||
long count = 0, size = 0;
|
||||
long count = 0L, size = 0L;
|
||||
|
||||
count_obj(chain, &count, &size, TRUE, FALSE);
|
||||
*total_count += count;
|
||||
*total_size += size;
|
||||
Sprintf(buf, template, src, count, size);
|
||||
putstr(win, 0, buf);
|
||||
|
||||
if (count || size || force) {
|
||||
*total_count += count;
|
||||
*total_size += size;
|
||||
Sprintf(buf, template, src, count, size);
|
||||
putstr(win, 0, buf);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC_OVL void
|
||||
@@ -2985,14 +2989,17 @@ long *total_size;
|
||||
|
||||
for (mon = chain; mon; mon = mon->nmon)
|
||||
count_obj(mon->minvent, &count, &size, TRUE, FALSE);
|
||||
*total_count += count;
|
||||
*total_size += size;
|
||||
Sprintf(buf, template, src, count, size);
|
||||
putstr(win, 0, buf);
|
||||
|
||||
if (count || size) {
|
||||
*total_count += count;
|
||||
*total_size += size;
|
||||
Sprintf(buf, template, src, count, size);
|
||||
putstr(win, 0, buf);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC_OVL void
|
||||
contained(win, src, total_count, total_size)
|
||||
contained_stats(win, src, total_count, total_size)
|
||||
winid win;
|
||||
const char *src;
|
||||
long *total_count;
|
||||
@@ -3013,58 +3020,173 @@ long *total_size;
|
||||
for (mon = migrating_mons; mon; mon = mon->nmon)
|
||||
count_obj(mon->minvent, &count, &size, FALSE, TRUE);
|
||||
|
||||
*total_count += count;
|
||||
*total_size += size;
|
||||
|
||||
Sprintf(buf, template, src, count, size);
|
||||
putstr(win, 0, buf);
|
||||
if (count || size) {
|
||||
*total_count += count;
|
||||
*total_size += size;
|
||||
Sprintf(buf, template, src, count, size);
|
||||
putstr(win, 0, buf);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC_OVL int
|
||||
size_monst(mtmp)
|
||||
size_monst(mtmp, incl_wsegs)
|
||||
struct monst *mtmp;
|
||||
boolean incl_wsegs;
|
||||
{
|
||||
int sz = (int) sizeof(struct monst);
|
||||
int sz = (int) sizeof (struct monst);
|
||||
|
||||
if (mtmp->wormno && incl_wsegs)
|
||||
sz += size_wseg(mtmp);
|
||||
|
||||
if (mtmp->mextra) {
|
||||
sz += (int) sizeof(struct mextra);
|
||||
sz += (int) sizeof (struct mextra);
|
||||
if (MNAME(mtmp))
|
||||
sz += (int) strlen(MNAME(mtmp)) + 1;
|
||||
if (EGD(mtmp))
|
||||
sz += (int) sizeof(struct egd);
|
||||
sz += (int) sizeof (struct egd);
|
||||
if (EPRI(mtmp))
|
||||
sz += (int) sizeof(struct epri);
|
||||
sz += (int) sizeof (struct epri);
|
||||
if (ESHK(mtmp))
|
||||
sz += (int) sizeof(struct eshk);
|
||||
sz += (int) sizeof (struct eshk);
|
||||
if (EMIN(mtmp))
|
||||
sz += (int) sizeof(struct emin);
|
||||
sz += (int) sizeof (struct emin);
|
||||
if (EDOG(mtmp))
|
||||
sz += (int) sizeof(struct edog);
|
||||
sz += (int) sizeof (struct edog);
|
||||
/* mextra->mcorpsenm doesn't point to more memory */
|
||||
}
|
||||
return sz;
|
||||
}
|
||||
|
||||
STATIC_OVL void
|
||||
mon_chain(win, src, chain, total_count, total_size)
|
||||
mon_chain(win, src, chain, force, total_count, total_size)
|
||||
winid win;
|
||||
const char *src;
|
||||
struct monst *chain;
|
||||
boolean force;
|
||||
long *total_count;
|
||||
long *total_size;
|
||||
{
|
||||
char buf[BUFSZ];
|
||||
long count, size;
|
||||
struct monst *mon;
|
||||
/* mon->wormno means something different for migrating_mons and mydogs */
|
||||
boolean incl_wsegs = !strcmpi(src, "fmon");
|
||||
|
||||
for (count = size = 0, mon = chain; mon; mon = mon->nmon) {
|
||||
count = size = 0L;
|
||||
for (mon = chain; mon; mon = mon->nmon) {
|
||||
count++;
|
||||
size += size_monst(mon);
|
||||
size += size_monst(mon, incl_wsegs);
|
||||
}
|
||||
if (count || size || force) {
|
||||
*total_count += count;
|
||||
*total_size += size;
|
||||
Sprintf(buf, template, src, count, size);
|
||||
putstr(win, 0, buf);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC_OVL void
|
||||
misc_stats(win, total_count, total_size)
|
||||
winid win;
|
||||
long *total_count;
|
||||
long *total_size;
|
||||
{
|
||||
char buf[BUFSZ], hdrbuf[QBUFSZ];
|
||||
long count, size;
|
||||
int idx;
|
||||
struct trap *tt;
|
||||
struct damage *sd; /* shop damage */
|
||||
struct cemetery *bi; /* bones info */
|
||||
|
||||
/* traps and engravings are output unconditionally;
|
||||
* others only if nonzero
|
||||
*/
|
||||
count = size = 0L;
|
||||
for (tt = ftrap; tt; tt = tt->ntrap) {
|
||||
++count;
|
||||
size += (long) sizeof *tt;
|
||||
}
|
||||
*total_count += count;
|
||||
*total_size += size;
|
||||
Sprintf(buf, template, src, count, size);
|
||||
Sprintf(hdrbuf, "traps, size %ld", (long) sizeof (struct trap));
|
||||
Sprintf(buf, template, hdrbuf, count, size);
|
||||
putstr(win, 0, buf);
|
||||
|
||||
count = size = 0L;
|
||||
engr_stats("engravings, size %ld+text", hdrbuf, &count, &size);
|
||||
*total_count += count;
|
||||
*total_size += size;
|
||||
Sprintf(buf, template, hdrbuf, count, size);
|
||||
putstr(win, 0, buf);
|
||||
|
||||
count = size = 0L;
|
||||
light_stats("light sources, size %ld", hdrbuf, &count, &size);
|
||||
if (count || size) {
|
||||
*total_count += count;
|
||||
*total_size += size;
|
||||
Sprintf(buf, template, hdrbuf, count, size);
|
||||
putstr(win, 0, buf);
|
||||
}
|
||||
|
||||
count = size = 0L;
|
||||
timer_stats("timers, size %ld", hdrbuf, &count, &size);
|
||||
if (count || size) {
|
||||
*total_count += count;
|
||||
*total_size += size;
|
||||
Sprintf(buf, template, hdrbuf, count, size);
|
||||
putstr(win, 0, buf);
|
||||
}
|
||||
|
||||
count = size = 0L;
|
||||
for (sd = level.damagelist; sd; sd = sd->next) {
|
||||
++count;
|
||||
size += (long) sizeof *sd;
|
||||
}
|
||||
if (count || size) {
|
||||
*total_count += count;
|
||||
*total_size += size;
|
||||
Sprintf(hdrbuf, "shop damage, size %ld",
|
||||
(long) sizeof (struct damage));
|
||||
Sprintf(buf, template, hdrbuf, count, size);
|
||||
putstr(win, 0, buf);
|
||||
}
|
||||
|
||||
count = size = 0L;
|
||||
region_stats("regions, size %ld+%ld*rect+N", hdrbuf, &count, &size);
|
||||
if (count || size) {
|
||||
*total_count += count;
|
||||
*total_size += size;
|
||||
Sprintf(buf, template, hdrbuf, count, size);
|
||||
putstr(win, 0, buf);
|
||||
}
|
||||
|
||||
count = size = 0L;
|
||||
for (bi = level.bonesinfo; bi; bi = bi->next) {
|
||||
++count;
|
||||
size += (long) sizeof *bi;
|
||||
}
|
||||
if (count || size) {
|
||||
*total_count += count;
|
||||
*total_size += size;
|
||||
Sprintf(hdrbuf, "bones history, size %ld",
|
||||
(long) sizeof (struct cemetery));
|
||||
Sprintf(buf, template, hdrbuf, count, size);
|
||||
putstr(win, 0, buf);
|
||||
}
|
||||
|
||||
count = size = 0L;
|
||||
for (idx = 0; idx < NUM_OBJECTS; ++idx)
|
||||
if (objects[idx].oc_uname) {
|
||||
++count;
|
||||
size += (long) (strlen(objects[idx].oc_uname) + 1);
|
||||
}
|
||||
if (count || size) {
|
||||
*total_count += count;
|
||||
*total_size += size;
|
||||
Strcpy(hdrbuf, "object type names, text");
|
||||
Sprintf(buf, template, hdrbuf, count, size);
|
||||
putstr(win, 0, buf);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3075,45 +3197,73 @@ wiz_show_stats()
|
||||
{
|
||||
char buf[BUFSZ];
|
||||
winid win;
|
||||
long total_obj_size = 0, total_obj_count = 0;
|
||||
long total_mon_size = 0, total_mon_count = 0;
|
||||
long total_obj_size, total_obj_count,
|
||||
total_mon_size, total_mon_count,
|
||||
total_ovr_size, total_ovr_count,
|
||||
total_misc_size, total_misc_count;
|
||||
|
||||
win = create_nhwindow(NHW_TEXT);
|
||||
putstr(win, 0, "Current memory statistics:");
|
||||
putstr(win, 0, "");
|
||||
Sprintf(buf, "Objects, size %d", (int) sizeof(struct obj));
|
||||
putstr(win, 0, buf);
|
||||
putstr(win, 0, "");
|
||||
putstr(win, 0, count_str);
|
||||
|
||||
obj_chain(win, "invent", invent, &total_obj_count, &total_obj_size);
|
||||
obj_chain(win, "fobj", fobj, &total_obj_count, &total_obj_size);
|
||||
obj_chain(win, "buried", level.buriedobjlist, &total_obj_count,
|
||||
&total_obj_size);
|
||||
obj_chain(win, "migrating obj", migrating_objs, &total_obj_count,
|
||||
&total_obj_size);
|
||||
total_obj_count = total_obj_size = 0L;
|
||||
putstr(win, 0, stats_hdr);
|
||||
Sprintf(buf, " Objects, base size %ld", (long) sizeof (struct obj));
|
||||
putstr(win, 0, buf);
|
||||
obj_chain(win, "invent", invent, TRUE, &total_obj_count, &total_obj_size);
|
||||
obj_chain(win, "fobj", fobj, TRUE, &total_obj_count, &total_obj_size);
|
||||
obj_chain(win, "buried", level.buriedobjlist, FALSE,
|
||||
&total_obj_count, &total_obj_size);
|
||||
obj_chain(win, "migrating obj", migrating_objs, FALSE,
|
||||
&total_obj_count, &total_obj_size);
|
||||
obj_chain(win, "billobjs", billobjs, FALSE,
|
||||
&total_obj_count, &total_obj_size);
|
||||
mon_invent_chain(win, "minvent", fmon, &total_obj_count, &total_obj_size);
|
||||
mon_invent_chain(win, "migrating minvent", migrating_mons,
|
||||
&total_obj_count, &total_obj_size);
|
||||
contained_stats(win, "contained", &total_obj_count, &total_obj_size);
|
||||
putstr(win, 0, stats_sep);
|
||||
Sprintf(buf, template, " Obj total", total_obj_count, total_obj_size);
|
||||
putstr(win, 0, buf);
|
||||
|
||||
contained(win, "contained", &total_obj_count, &total_obj_size);
|
||||
total_mon_count = total_mon_size = 0L;
|
||||
putstr(win, 0, "");
|
||||
Sprintf(buf, " Monsters, base size %ld", (long) sizeof (struct monst));
|
||||
putstr(win, 0, buf);
|
||||
mon_chain(win, "fmon", fmon, TRUE, &total_mon_count, &total_mon_size);
|
||||
mon_chain(win, "migrating", migrating_mons, FALSE,
|
||||
&total_mon_count, &total_mon_size);
|
||||
/* 'mydogs' is only valid during level change or end of game disclosure,
|
||||
but conceivably we've been called from within debugger at such time */
|
||||
if (mydogs) /* monsters accompanying hero */
|
||||
mon_chain(win, "mydogs", mydogs, FALSE,
|
||||
&total_mon_count, &total_mon_size);
|
||||
putstr(win, 0, stats_sep);
|
||||
Sprintf(buf, template, " Mon total", total_mon_count, total_mon_size);
|
||||
putstr(win, 0, buf);
|
||||
|
||||
putstr(win, 0, separator);
|
||||
Sprintf(buf, template, "Total", total_obj_count, total_obj_size);
|
||||
total_ovr_count = total_ovr_size = 0L;
|
||||
putstr(win, 0, "");
|
||||
putstr(win, 0, " Overview");
|
||||
overview_stats(win, template, &total_ovr_count, &total_ovr_size);
|
||||
putstr(win, 0, stats_sep);
|
||||
Sprintf(buf, template, " Over total", total_ovr_count, total_ovr_size);
|
||||
putstr(win, 0, buf);
|
||||
|
||||
total_misc_count = total_misc_size = 0L;
|
||||
putstr(win, 0, "");
|
||||
putstr(win, 0, " Miscellaneous");
|
||||
misc_stats(win, &total_misc_count, &total_misc_size);
|
||||
putstr(win, 0, stats_sep);
|
||||
Sprintf(buf, template, " Misc total", total_misc_count, total_misc_size);
|
||||
putstr(win, 0, buf);
|
||||
|
||||
putstr(win, 0, "");
|
||||
putstr(win, 0, "");
|
||||
Sprintf(buf, "Monsters, size %d", (int) sizeof(struct monst));
|
||||
putstr(win, 0, buf);
|
||||
putstr(win, 0, "");
|
||||
|
||||
mon_chain(win, "fmon", fmon, &total_mon_count, &total_mon_size);
|
||||
mon_chain(win, "migrating", migrating_mons, &total_mon_count,
|
||||
&total_mon_size);
|
||||
|
||||
putstr(win, 0, separator);
|
||||
Sprintf(buf, template, "Total", total_mon_count, total_mon_size);
|
||||
putstr(win, 0, stats_sep);
|
||||
Sprintf(buf, template, " Grand total",
|
||||
(total_obj_count + total_mon_count
|
||||
+ total_ovr_count + total_misc_count),
|
||||
(total_obj_size + total_mon_size
|
||||
+ total_ovr_size + total_misc_size));
|
||||
putstr(win, 0, buf);
|
||||
|
||||
#if defined(__BORLANDC__) && !defined(_WIN32)
|
||||
|
||||
+26
-20
@@ -115,16 +115,12 @@ int mask;
|
||||
switch (mask & DB_UNDER) {
|
||||
case DB_ICE:
|
||||
return ICE;
|
||||
break;
|
||||
case DB_LAVA:
|
||||
return LAVAPOOL;
|
||||
break;
|
||||
case DB_MOAT:
|
||||
return MOAT;
|
||||
break;
|
||||
default:
|
||||
return STONE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -427,9 +423,9 @@ int x, y;
|
||||
}
|
||||
|
||||
STATIC_OVL void
|
||||
e_died(etmp, dest, how)
|
||||
e_died(etmp, xkill_flags, how)
|
||||
struct entity *etmp;
|
||||
int dest, how;
|
||||
int xkill_flags, how;
|
||||
{
|
||||
if (is_u(etmp)) {
|
||||
if (how == DROWNING) {
|
||||
@@ -466,13 +462,14 @@ int dest, how;
|
||||
|
||||
killer.name[0] = 0;
|
||||
/* fake "digested to death" damage-type suppresses corpse */
|
||||
#define mk_message(dest) ((dest & 1) ? "" : (char *) 0)
|
||||
#define mk_corpse(dest) ((dest & 2) ? AD_DGST : AD_PHYS)
|
||||
#define mk_message(dest) (((dest & XKILL_NOMSG) != 0) ? (char *) 0 : "")
|
||||
#define mk_corpse(dest) (((dest & XKILL_NOCORPSE) != 0) ? AD_DGST : AD_PHYS)
|
||||
/* if monsters are moving, one of them caused the destruction */
|
||||
if (context.mon_moving)
|
||||
monkilled(etmp->emon, mk_message(dest), mk_corpse(dest));
|
||||
monkilled(etmp->emon,
|
||||
mk_message(xkill_flags), mk_corpse(xkill_flags));
|
||||
else /* you caused it */
|
||||
xkilled(etmp->emon, dest);
|
||||
xkilled(etmp->emon, xkill_flags);
|
||||
etmp->edata = (struct permonst *) 0;
|
||||
|
||||
/* dead long worm handling */
|
||||
@@ -609,7 +606,9 @@ struct entity *etmp;
|
||||
if (crm->typ == DRAWBRIDGE_DOWN) {
|
||||
pline("%s crushed underneath the drawbridge.",
|
||||
E_phrase(etmp, "are")); /* no jump */
|
||||
e_died(etmp, e_inview ? 3 : 2, CRUSHING); /* no corpse */
|
||||
e_died(etmp,
|
||||
XKILL_NOCORPSE | (e_inview ? XKILL_GIVEMSG : XKILL_NOMSG),
|
||||
CRUSHING); /* no corpse */
|
||||
return; /* Note: Beyond this point, we know we're */
|
||||
} /* not at an opened drawbridge, since all */
|
||||
must_jump = TRUE; /* *missable* creatures survive on the */
|
||||
@@ -625,7 +624,10 @@ struct entity *etmp;
|
||||
E_phrase(etmp, "are"));
|
||||
else if (!Deaf)
|
||||
You_hear("a crushing sound.");
|
||||
e_died(etmp, e_inview ? 3 : 2, CRUSHING);
|
||||
e_died(etmp,
|
||||
XKILL_NOCORPSE | (e_inview ? XKILL_GIVEMSG
|
||||
: XKILL_NOMSG),
|
||||
CRUSHING);
|
||||
/* no corpse */
|
||||
return;
|
||||
}
|
||||
@@ -721,7 +723,7 @@ struct entity *etmp;
|
||||
if (!e_survives_at(etmp, etmp->ex, etmp->ey)) {
|
||||
killer.format = KILLED_BY_AN;
|
||||
Strcpy(killer.name, "closing drawbridge");
|
||||
e_died(etmp, 0, CRUSHING); /* no message */
|
||||
e_died(etmp, XKILL_NOMSG, CRUSHING);
|
||||
return;
|
||||
}
|
||||
debugpline1("%s in here", E_phrase(etmp, "survive"));
|
||||
@@ -752,11 +754,11 @@ struct entity *etmp;
|
||||
}
|
||||
killer.format = NO_KILLER_PREFIX;
|
||||
Strcpy(killer.name, "fell from a drawbridge");
|
||||
e_died(etmp, e_inview ? 3 : 2, /* CRUSHING is arbitrary */
|
||||
(is_pool(etmp->ex, etmp->ey))
|
||||
? DROWNING
|
||||
: (is_lava(etmp->ex, etmp->ey)) ? BURNING
|
||||
: CRUSHING); /*no corpse*/
|
||||
e_died(etmp, /* CRUSHING is arbitrary */
|
||||
XKILL_NOCORPSE | (e_inview ? XKILL_GIVEMSG : XKILL_NOMSG),
|
||||
is_pool(etmp->ex, etmp->ey) ? DROWNING
|
||||
: is_lava(etmp->ex, etmp->ey) ? BURNING
|
||||
: CRUSHING); /*no corpse*/
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -958,7 +960,9 @@ int x, y;
|
||||
E_phrase(etmp2, "are"));
|
||||
killer.format = KILLED_BY_AN;
|
||||
Strcpy(killer.name, "exploding drawbridge");
|
||||
e_died(etmp2, e_inview ? 3 : 2, CRUSHING); /*no corpse*/
|
||||
e_died(etmp2,
|
||||
XKILL_NOCORPSE | (e_inview ? XKILL_GIVEMSG : XKILL_NOMSG),
|
||||
CRUSHING); /*no corpse*/
|
||||
} /* nothing which is vulnerable can survive this */
|
||||
}
|
||||
set_entity(x, y, etmp1);
|
||||
@@ -988,7 +992,9 @@ int x, y;
|
||||
}
|
||||
killer.format = KILLED_BY_AN;
|
||||
Strcpy(killer.name, "collapsing drawbridge");
|
||||
e_died(etmp1, e_inview ? 3 : 2, CRUSHING); /*no corpse*/
|
||||
e_died(etmp1,
|
||||
XKILL_NOCORPSE | (e_inview ? XKILL_GIVEMSG : XKILL_NOMSG),
|
||||
CRUSHING); /*no corpse*/
|
||||
if (levl[etmp1->ex][etmp1->ey].typ == MOAT)
|
||||
do_entity(etmp1);
|
||||
}
|
||||
|
||||
+2
-1
@@ -194,8 +194,9 @@ NEARDATA struct obj *migrating_objs = (struct obj *) 0;
|
||||
/* objects not yet paid for */
|
||||
NEARDATA struct obj *billobjs = (struct obj *) 0;
|
||||
|
||||
/* used to zero all elements of a struct obj */
|
||||
/* used to zero all elements of a struct obj and a struct monst */
|
||||
NEARDATA struct obj zeroobj = DUMMY;
|
||||
NEARDATA struct monst zeromonst = DUMMY;
|
||||
/* used to zero out union any; initializer deliberately omitted */
|
||||
NEARDATA anything zeroany;
|
||||
|
||||
|
||||
+39
-22
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 detect.c $NHDT-Date: 1446369464 2015/11/01 09:17:44 $ $NHDT-Branch: master $:$NHDT-Revision: 1.61 $ */
|
||||
/* NetHack 3.6 detect.c $NHDT-Date: 1463191981 2016/05/14 02:13:01 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.70 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -272,6 +272,7 @@ outgoldmap:
|
||||
}
|
||||
newsym(u.ux, u.uy);
|
||||
u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied;
|
||||
iflags.save_uinwater = iflags.save_uburied = 0;
|
||||
You_feel("very greedy, and sense gold!");
|
||||
exercise(A_WIS, TRUE);
|
||||
display_nhwindow(WIN_MAP, TRUE);
|
||||
@@ -376,6 +377,7 @@ register struct obj *sobj;
|
||||
}
|
||||
newsym(u.ux, u.uy);
|
||||
u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied;
|
||||
iflags.save_uinwater = iflags.save_uburied = 0;
|
||||
if (sobj) {
|
||||
if (sobj->blessed) {
|
||||
Your("%s %s to tingle and you smell %s.", body_part(NOSE),
|
||||
@@ -575,6 +577,7 @@ int class; /* an object class, 0 for all */
|
||||
|
||||
newsym(u.ux, u.uy);
|
||||
u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied;
|
||||
iflags.save_uinwater = iflags.save_uburied = 0;
|
||||
You("detect the %s of %s.", ct ? "presence" : "absence", stuff);
|
||||
display_nhwindow(WIN_MAP, TRUE);
|
||||
/*
|
||||
@@ -826,6 +829,7 @@ outtrapmap:
|
||||
if (!(glyph_is_trap(glyph) || glyph_is_object(glyph)))
|
||||
newsym(u.ux, u.uy);
|
||||
u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied;
|
||||
iflags.save_uinwater = iflags.save_uburied = 0;
|
||||
|
||||
You_feel("%s.", cursed_src ? "very greedy" : "entrapped");
|
||||
/* wait for user to respond, then reset map display to normal */
|
||||
@@ -1090,6 +1094,7 @@ do_mapping()
|
||||
for (zy = 0; zy < ROWNO; zy++)
|
||||
show_map_spot(zx, zy);
|
||||
u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied;
|
||||
iflags.save_uinwater = iflags.save_uburied = 0;
|
||||
if (!level.flags.hero_memory || Underwater) {
|
||||
flush_screen(1); /* flush temp screen */
|
||||
display_nhwindow(WIN_MAP, TRUE); /* wait */
|
||||
@@ -1355,7 +1360,7 @@ boolean via_warning;
|
||||
Your("warning senses cause you to take a second %s.",
|
||||
Blind ? "to check nearby" : "look close by");
|
||||
display_nhwindow(WIN_MESSAGE, FALSE); /* flush messages */
|
||||
}
|
||||
}
|
||||
mtmp->mundetected = 0;
|
||||
newsym(x, y);
|
||||
goto find;
|
||||
@@ -1463,20 +1468,17 @@ dosearch()
|
||||
void
|
||||
warnreveal()
|
||||
{
|
||||
xchar x, y;
|
||||
int x, y;
|
||||
struct monst *mtmp;
|
||||
|
||||
for (x = u.ux - 1; x < u.ux + 2; x++)
|
||||
for (y = u.uy - 1; y < u.uy + 2; y++) {
|
||||
if (!isok(x, y))
|
||||
continue;
|
||||
if (x == u.ux && y == u.uy)
|
||||
continue;
|
||||
|
||||
if ((mtmp = m_at(x, y)) != 0
|
||||
&& warning_of(mtmp) && mtmp->mundetected)
|
||||
(void) mfind0(mtmp, 1); /* via_warning */
|
||||
}
|
||||
for (x = u.ux - 1; x <= u.ux + 1; x++)
|
||||
for (y = u.uy - 1; y <= u.uy + 1; y++) {
|
||||
if (!isok(x, y) || (x == u.ux && y == u.uy))
|
||||
continue;
|
||||
if ((mtmp = m_at(x, y)) != 0
|
||||
&& warning_of(mtmp) && mtmp->mundetected)
|
||||
(void) mfind0(mtmp, 1); /* via_warning */
|
||||
}
|
||||
}
|
||||
|
||||
/* Pre-map the sokoban levels */
|
||||
@@ -1522,15 +1524,19 @@ int which_subset; /* when not full, whether to suppress objs and/or traps */
|
||||
unsigned save_swallowed;
|
||||
struct monst *mtmp;
|
||||
struct trap *t;
|
||||
coord pos;
|
||||
char buf[BUFSZ];
|
||||
boolean keep_traps = (which_subset & 1) !=0,
|
||||
keep_objs = (which_subset & 2) != 0,
|
||||
keep_mons = (which_subset & 4) != 0; /* actually always 0 */
|
||||
/* there is a TER_MAP bit too; we always show map regardless of it */
|
||||
boolean keep_traps = (which_subset & TER_TRP) !=0,
|
||||
keep_objs = (which_subset & TER_OBJ) != 0,
|
||||
keep_mons = (which_subset & TER_MON) != 0; /* not used */
|
||||
|
||||
save_swallowed = u.uswallow;
|
||||
iflags.save_uinwater = u.uinwater, iflags.save_uburied = u.uburied;
|
||||
u.uinwater = u.uburied = 0;
|
||||
u.uswallow = 0;
|
||||
if (iflags.save_uinwater || iflags.save_uburied)
|
||||
docrt();
|
||||
default_glyph = cmap_to_glyph(level.flags.arboreal ? S_tree : S_stone);
|
||||
/* for 'full', show the actual terrain for the entire level,
|
||||
otherwise what the hero remembers for seen locations with
|
||||
@@ -1603,10 +1609,8 @@ int which_subset; /* when not full, whether to suppress objs and/or traps */
|
||||
show_glyph(x, y, glyph);
|
||||
}
|
||||
|
||||
/* [TODO: highlight hero's location somehow] */
|
||||
u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied;
|
||||
if (save_swallowed)
|
||||
u.uswallow = 1;
|
||||
/* hero's location is not highlighted, but getpos() starts with
|
||||
cursor there, and after moving it anywhere '@' moves it back */
|
||||
flush_screen(1);
|
||||
if (full) {
|
||||
Strcpy(buf, "underlying terrain");
|
||||
@@ -1624,7 +1628,20 @@ int which_subset; /* when not full, whether to suppress objs and/or traps */
|
||||
(keep_traps || keep_objs) ? "," : "");
|
||||
}
|
||||
pline("Showing %s only...", buf);
|
||||
display_nhwindow(WIN_MAP, TRUE); /* give "--More--" prompt */
|
||||
|
||||
/* allow player to move cursor around and get autodescribe feedback
|
||||
based on what is visible now rather than what is on 'real' map */
|
||||
pos.x = u.ux, pos.y = u.uy;
|
||||
iflags.autodescribe = TRUE;
|
||||
iflags.terrainmode = which_subset | TER_MAP; /* guaranteed non-zero */
|
||||
getpos(&pos, FALSE, "anything of interest");
|
||||
iflags.terrainmode = 0;
|
||||
/* leave iflags.autodescribe 'on' even if it was previously 'off' */
|
||||
|
||||
u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied;
|
||||
iflags.save_uinwater = iflags.save_uburied = 0;
|
||||
if (save_swallowed)
|
||||
u.uswallow = 1;
|
||||
docrt(); /* redraw the screen, restoring regular map */
|
||||
if (Underwater)
|
||||
under_water(2);
|
||||
|
||||
+30
-33
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 display.c $NHDT-Date: 1457207034 2016/03/05 19:43:54 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.82 $ */
|
||||
/* NetHack 3.6 display.c $NHDT-Date: 1463614572 2016/05/18 23:36:12 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.86 $ */
|
||||
/* Copyright (c) Dean Luick, with acknowledgements to Kevin Darcy */
|
||||
/* and Dave Cohrs, 1990. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
@@ -530,8 +530,7 @@ xchar x, y;
|
||||
if (!isok(x, y))
|
||||
return;
|
||||
lev = &(levl[x][y]);
|
||||
/* If the hero's memory of an invisible monster is accurate, we want to
|
||||
* keep
|
||||
/* If hero's memory of an invisible monster is accurate, we want to keep
|
||||
* him from detecting the same monster over and over again on each turn.
|
||||
* We must return (so we don't erase the monster). (We must also, in the
|
||||
* search function, be sure to skip over previously detected 'I's.)
|
||||
@@ -539,8 +538,10 @@ xchar x, y;
|
||||
if (glyph_is_invisible(lev->glyph) && m_at(x, y))
|
||||
return;
|
||||
|
||||
/* The hero can't feel non pool locations while under water. */
|
||||
if (Underwater && !Is_waterlevel(&u.uz) && !is_pool(x, y))
|
||||
/* The hero can't feel non pool locations while under water
|
||||
except for lava and ice. */
|
||||
if (Underwater && !Is_waterlevel(&u.uz)
|
||||
&& !is_pool_or_lava(x, y) && !is_ice(x, y))
|
||||
return;
|
||||
|
||||
/* Set the seen vector as if the hero had seen it.
|
||||
@@ -572,6 +573,8 @@ xchar x, y;
|
||||
} else if (IS_DOOR(lev->typ)) {
|
||||
map_background(x, y, 1);
|
||||
} else if (IS_ROOM(lev->typ) || IS_POOL(lev->typ)) {
|
||||
boolean do_room_glyph;
|
||||
|
||||
/*
|
||||
* An open room or water location. Normally we wouldn't touch
|
||||
* this, but we have to get rid of remembered boulder symbols.
|
||||
@@ -597,20 +600,18 @@ xchar x, y;
|
||||
* We could also just display what is currently on the top of the
|
||||
* object stack (if anything).
|
||||
*/
|
||||
if (lev->glyph == objnum_to_glyph(BOULDER)) {
|
||||
if (lev->typ != ROOM && lev->seenv) {
|
||||
do_room_glyph = FALSE;
|
||||
if (lev->glyph == objnum_to_glyph(BOULDER)
|
||||
|| glyph_is_invisible(lev->glyph)) {
|
||||
if (lev->typ != ROOM && lev->seenv)
|
||||
map_background(x, y, 1);
|
||||
} else {
|
||||
lev->glyph = (flags.dark_room && iflags.use_color
|
||||
&& !Is_rogue_level(&u.uz))
|
||||
? cmap_to_glyph(S_darkroom)
|
||||
: (lev->waslit ? cmap_to_glyph(S_room)
|
||||
: cmap_to_glyph(S_stone));
|
||||
show_glyph(x, y, lev->glyph);
|
||||
}
|
||||
} else if ((lev->glyph >= cmap_to_glyph(S_stone)
|
||||
&& lev->glyph < cmap_to_glyph(S_darkroom))
|
||||
|| glyph_is_invisible(levl[x][y].glyph)) {
|
||||
else
|
||||
do_room_glyph = TRUE;
|
||||
} else if (lev->glyph >= cmap_to_glyph(S_stone)
|
||||
&& lev->glyph < cmap_to_glyph(S_darkroom)) {
|
||||
do_room_glyph = TRUE;
|
||||
}
|
||||
if (do_room_glyph) {
|
||||
lev->glyph = (flags.dark_room && iflags.use_color
|
||||
&& !Is_rogue_level(&u.uz))
|
||||
? cmap_to_glyph(S_darkroom)
|
||||
@@ -701,18 +702,9 @@ register int x, y;
|
||||
return;
|
||||
}
|
||||
if (Underwater && !Is_waterlevel(&u.uz)) {
|
||||
/* don't do anything unless (x,y) is an adjacent underwater position
|
||||
*/
|
||||
int dx, dy;
|
||||
if (!is_pool(x, y))
|
||||
return;
|
||||
dx = x - u.ux;
|
||||
if (dx < 0)
|
||||
dx = -dx;
|
||||
dy = y - u.uy;
|
||||
if (dy < 0)
|
||||
dy = -dy;
|
||||
if (dx > 1 || dy > 1)
|
||||
/* when underwater, don't do anything unless <x,y> is an
|
||||
adjacent water or lava or ice position */
|
||||
if (!(is_pool_or_lava(x, y) || is_ice(x, y)) || distu(x, y) > 2)
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1017,9 +1009,10 @@ int first;
|
||||
static xchar lastx, lasty; /* last swallowed position */
|
||||
int swallower, left_ok, rght_ok;
|
||||
|
||||
if (first)
|
||||
if (first) {
|
||||
cls();
|
||||
else {
|
||||
bot();
|
||||
} else {
|
||||
register int x, y;
|
||||
|
||||
/* Clear old location */
|
||||
@@ -1103,9 +1096,13 @@ int mode;
|
||||
show_glyph(x, y, cmap_to_glyph(S_stone));
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO? Should this honor Xray radius rather than force radius 1?
|
||||
*/
|
||||
|
||||
for (x = u.ux - 1; x <= u.ux + 1; x++)
|
||||
for (y = u.uy - 1; y <= u.uy + 1; y++)
|
||||
if (isok(x, y) && is_pool(x, y)) {
|
||||
if (isok(x, y) && (is_pool_or_lava(x, y) || is_ice(x, y))) {
|
||||
if (Blind && !(x == u.ux && y == u.uy))
|
||||
show_glyph(x, y, cmap_to_glyph(S_stone));
|
||||
else
|
||||
|
||||
@@ -813,8 +813,8 @@ int retry;
|
||||
bypass_objlist(invent, FALSE);
|
||||
} else {
|
||||
/* should coordinate with perm invent, maybe not show worn items */
|
||||
n = query_objlist("What would you like to drop?", invent,
|
||||
USE_INVLET | INVORDER_SORT, &pick_list, PICK_ANY,
|
||||
n = query_objlist("What would you like to drop?", &invent,
|
||||
(USE_INVLET | INVORDER_SORT), &pick_list, PICK_ANY,
|
||||
all_categories ? allow_all : allow_category);
|
||||
if (n > 0) {
|
||||
/*
|
||||
@@ -1317,7 +1317,7 @@ boolean at_stairs, falling, portal;
|
||||
if (flags.verbose || great_effort)
|
||||
pline("%s %s up%s the %s.",
|
||||
great_effort ? "With great effort, you" : "You",
|
||||
Flying ? "fly" : "climb",
|
||||
Levitation ? "float" : Flying ? "fly" : "climb",
|
||||
(Flying && at_ladder) ? " along" : "",
|
||||
at_ladder ? "ladder" : "stairs");
|
||||
} else { /* down */
|
||||
|
||||
+89
-43
@@ -8,7 +8,7 @@ STATIC_DCL char *NDECL(nextmbuf);
|
||||
STATIC_DCL void FDECL(getpos_help, (BOOLEAN_P, const char *));
|
||||
STATIC_DCL int FDECL(CFDECLSPEC cmp_coord_distu, (const void *,
|
||||
const void *));
|
||||
STATIC_DCL void FDECL(gather_locs, (coord **, int *, BOOLEAN_P));
|
||||
STATIC_DCL void FDECL(gather_locs, (coord **, int *, int));
|
||||
STATIC_DCL void FDECL(auto_describe, (int, int));
|
||||
STATIC_DCL void NDECL(do_mname);
|
||||
STATIC_DCL boolean FDECL(alreadynamed, (struct monst *, char *, char *));
|
||||
@@ -59,30 +59,38 @@ const char *goal;
|
||||
putstr(tmpwin, 0, "Use [HJKL] to move the cursor 8 units at a time.");
|
||||
putstr(tmpwin, 0, "Or enter a background symbol (ex. <).");
|
||||
putstr(tmpwin, 0, "Use @ to move the cursor on yourself.");
|
||||
putstr(tmpwin, 0, "Use m or M to move the cursor to next monster.");
|
||||
putstr(tmpwin, 0, "Use o or O to move the cursor to next object.");
|
||||
if (getpos_hilitefunc)
|
||||
putstr(tmpwin, 0, "Use $ to display valid locations.");
|
||||
putstr(tmpwin, 0, "Use # to toggle automatic description.");
|
||||
if (iflags.cmdassist) /* assisting the '/' command, I suppose... */
|
||||
putstr(tmpwin, 0, (iflags.getpos_coords == GPCOORDS_NONE)
|
||||
? "(Set 'whatis_coord' option to include coordinates with '#' text.)"
|
||||
if (!iflags.terrainmode || (iflags.terrainmode & TER_MON) != 0)
|
||||
putstr(tmpwin, 0, "Use m or M to move the cursor to next monster.");
|
||||
if (!iflags.terrainmode || (iflags.terrainmode & TER_OBJ) != 0)
|
||||
putstr(tmpwin, 0, "Use o or O to move the cursor to next object.");
|
||||
if (!iflags.terrainmode) {
|
||||
putstr(tmpwin, 0, "Use d or D to move the cursor to next door or doorway.");
|
||||
if (getpos_hilitefunc)
|
||||
putstr(tmpwin, 0, "Use $ to display valid locations.");
|
||||
putstr(tmpwin, 0, "Use # to toggle automatic description.");
|
||||
if (iflags.cmdassist) /* assisting the '/' command, I suppose... */
|
||||
putstr(tmpwin, 0,
|
||||
(iflags.getpos_coords == GPCOORDS_NONE)
|
||||
? "(Set 'whatis_coord' option to include coordinates with '#' text.)"
|
||||
: "(Reset 'whatis_coord' option to omit coordinates from '#' text.)");
|
||||
/* disgusting hack; the alternate selection characters work for any
|
||||
getpos call, but they only matter for dowhatis (and doquickwhatis) */
|
||||
doing_what_is = (goal == what_is_an_unknown_object);
|
||||
Sprintf(sbuf, "Type a .%s when you are at the right place.",
|
||||
doing_what_is ? " or , or ; or :" : "");
|
||||
putstr(tmpwin, 0, sbuf);
|
||||
if (doing_what_is) {
|
||||
putstr(tmpwin, 0,
|
||||
" : describe current spot, show 'more info', move to another spot.");
|
||||
Sprintf(sbuf, " . describe current spot,%s move to another spot;",
|
||||
flags.help ? " prompt if 'more info'," : "");
|
||||
/* disgusting hack; the alternate selection characters work for any
|
||||
getpos call, but only matter for dowhatis (and doquickwhatis) */
|
||||
doing_what_is = (goal == what_is_an_unknown_object);
|
||||
Sprintf(sbuf, "Type a .%s when you are at the right place.",
|
||||
doing_what_is ? " or , or ; or :" : "");
|
||||
putstr(tmpwin, 0, sbuf);
|
||||
putstr(tmpwin, 0, " , describe current spot, move to another spot;");
|
||||
putstr(tmpwin, 0,
|
||||
" ; describe current spot, stop looking at things;");
|
||||
if (doing_what_is) {
|
||||
putstr(tmpwin, 0,
|
||||
" : describe current spot, show 'more info', move to another spot.");
|
||||
Sprintf(sbuf,
|
||||
" . describe current spot,%s move to another spot;",
|
||||
flags.help ? " prompt if 'more info'," : "");
|
||||
putstr(tmpwin, 0, sbuf);
|
||||
putstr(tmpwin, 0,
|
||||
" , describe current spot, move to another spot;");
|
||||
putstr(tmpwin, 0,
|
||||
" ; describe current spot, stop looking at things;");
|
||||
}
|
||||
}
|
||||
if (!force)
|
||||
putstr(tmpwin, 0, "Type Space or Escape when you're done.");
|
||||
@@ -113,17 +121,38 @@ const void *b;
|
||||
return dist_1 - dist_2;
|
||||
}
|
||||
|
||||
#define GLOC_MONS 0
|
||||
#define GLOC_OBJS 1
|
||||
#define GLOC_DOOR 2
|
||||
|
||||
boolean
|
||||
gather_locs_glyphmatch(glyph, gloc)
|
||||
int glyph, gloc;
|
||||
{
|
||||
switch (gloc) {
|
||||
default:
|
||||
case GLOC_MONS: return (glyph_is_monster(glyph)
|
||||
&& glyph != monnum_to_glyph(PM_LONG_WORM_TAIL));
|
||||
case GLOC_OBJS: return (glyph_is_object(glyph)
|
||||
&& glyph != objnum_to_glyph(BOULDER)
|
||||
&& glyph != objnum_to_glyph(ROCK));
|
||||
case GLOC_DOOR: return (glyph_is_cmap(glyph)
|
||||
&& ((glyph_to_cmap(glyph) == S_hcdoor)
|
||||
|| (glyph_to_cmap(glyph) == S_vcdoor)
|
||||
|| (glyph_to_cmap(glyph) == S_hodoor)
|
||||
|| (glyph_to_cmap(glyph) == S_vodoor)
|
||||
|| (glyph_to_cmap(glyph) == S_ndoor)));
|
||||
}
|
||||
}
|
||||
|
||||
/* gather locations for monsters or objects shown on the map */
|
||||
STATIC_OVL void
|
||||
gather_locs(arr_p, cnt_p, do_mons)
|
||||
gather_locs(arr_p, cnt_p, gloc)
|
||||
coord **arr_p;
|
||||
int *cnt_p;
|
||||
boolean do_mons;
|
||||
int gloc;
|
||||
{
|
||||
int x, y, pass, glyph, idx,
|
||||
tail = (do_mons ? monnum_to_glyph(PM_LONG_WORM_TAIL) : 0),
|
||||
boulder = (!do_mons ? objnum_to_glyph(BOULDER) : 0),
|
||||
rock = (!do_mons ? objnum_to_glyph(ROCK) : 0);
|
||||
int x, y, pass, glyph, idx;
|
||||
|
||||
/*
|
||||
* We always include the hero's location even if there is no monster
|
||||
@@ -147,9 +176,7 @@ boolean do_mons;
|
||||
/* unlike '/M', this skips monsters revealed by
|
||||
warning glyphs and remembered invisible ones */
|
||||
if ((x == u.ux && y == u.uy)
|
||||
|| (do_mons ? (glyph_is_monster(glyph) && glyph != tail)
|
||||
: (glyph_is_object(glyph)
|
||||
&& glyph != boulder && glyph != rock))) {
|
||||
|| gather_locs_glyphmatch(glyph, gloc)) {
|
||||
if (!pass) {
|
||||
++*cnt_p;
|
||||
} else {
|
||||
@@ -272,8 +299,10 @@ const char *goal;
|
||||
static const char pick_chars[] = ".,;:";
|
||||
const char *cp;
|
||||
boolean hilite_state = FALSE;
|
||||
coord *monarr = (coord *) 0, *objarr = (coord *) 0;
|
||||
int moncount = 0, monidx = 0, objcount = 0, objidx = 0;
|
||||
coord *monarr = (coord *) 0, *objarr = (coord *) 0,
|
||||
*doorarr = (coord *) 0;
|
||||
int moncount = 0, monidx = 0, objcount = 0, objidx = 0,
|
||||
doorcount = 0, dooridx = 0;
|
||||
|
||||
if (!goal)
|
||||
goal = "desired location";
|
||||
@@ -394,13 +423,13 @@ const char *goal;
|
||||
} else if (c == '@') { /* return to hero's spot */
|
||||
/* reset 'm','M' and 'o','O'; otherwise, there's no way for player
|
||||
to achieve that except by manually cycling through all spots */
|
||||
monidx = objidx = 0;
|
||||
monidx = objidx = dooridx = 0;
|
||||
cx = u.ux;
|
||||
cy = u.uy;
|
||||
goto nxtc;
|
||||
} else if (c == 'm' || c == 'M') { /* nearest or farthest monster */
|
||||
if (!monarr) {
|
||||
gather_locs(&monarr, &moncount, TRUE);
|
||||
gather_locs(&monarr, &moncount, GLOC_MONS);
|
||||
monidx = 0; /* monarr[0] is hero's spot */
|
||||
}
|
||||
if (c == 'm') {
|
||||
@@ -414,7 +443,7 @@ const char *goal;
|
||||
goto nxtc;
|
||||
} else if (c == 'o' || c == 'O') { /* nearest or farthest object */
|
||||
if (!objarr) {
|
||||
gather_locs(&objarr, &objcount, FALSE);
|
||||
gather_locs(&objarr, &objcount, GLOC_OBJS);
|
||||
objidx = 0; /* objarr[0] is hero's spot */
|
||||
}
|
||||
if (c == 'o') {
|
||||
@@ -426,6 +455,20 @@ const char *goal;
|
||||
cx = objarr[objidx].x;
|
||||
cy = objarr[objidx].y;
|
||||
goto nxtc;
|
||||
} else if (c == 'd' || c == 'D') { /* door/doorway */
|
||||
if (!doorarr) {
|
||||
gather_locs(&doorarr, &doorcount, GLOC_DOOR);
|
||||
dooridx = 0; /* objarr[0] is hero's spot */
|
||||
}
|
||||
if (c == 'd') {
|
||||
dooridx = (dooridx + 1) % doorcount;
|
||||
} else {
|
||||
if (--dooridx < 0)
|
||||
dooridx = doorcount - 1;
|
||||
}
|
||||
cx = doorarr[dooridx].x;
|
||||
cy = doorarr[dooridx].y;
|
||||
goto nxtc;
|
||||
} else {
|
||||
if (!index(quitchars, c)) {
|
||||
char matching[MAXPCHARS];
|
||||
@@ -446,7 +489,7 @@ const char *goal;
|
||||
hi_x = (pass == 1 && ty == hi_y) ? cx : COLNO - 1;
|
||||
for (tx = lo_x; tx <= hi_x; tx++) {
|
||||
/* look at dungeon feature, not at
|
||||
* user-visible glyph */
|
||||
user-visible glyph */
|
||||
k = back_to_glyph(tx, ty);
|
||||
/* uninteresting background glyph */
|
||||
if (glyph_is_cmap(k)
|
||||
@@ -460,9 +503,10 @@ const char *goal;
|
||||
}
|
||||
if (glyph_is_cmap(k)
|
||||
&& matching[glyph_to_cmap(k)]
|
||||
&& levl[tx][ty].seenv
|
||||
&& (!IS_WALL(levl[tx][ty].typ))
|
||||
&& (levl[tx][ty].typ != SDOOR)
|
||||
&& (levl[tx][ty].seenv
|
||||
|| iflags.terrainmode)
|
||||
&& !IS_WALL(levl[tx][ty].typ)
|
||||
&& levl[tx][ty].typ != SDOOR
|
||||
&& glyph_to_cmap(k) != S_room
|
||||
&& glyph_to_cmap(k) != S_corr
|
||||
&& glyph_to_cmap(k) != S_litcorr) {
|
||||
@@ -495,8 +539,10 @@ const char *goal;
|
||||
} /* !quitchars */
|
||||
if (force)
|
||||
goto nxtc;
|
||||
pline("Done.");
|
||||
msg_given = FALSE; /* suppress clear */
|
||||
if (!iflags.terrainmode) {
|
||||
pline("Done.");
|
||||
msg_given = FALSE; /* suppress clear */
|
||||
}
|
||||
cx = -1;
|
||||
cy = 0;
|
||||
result = 0; /* not -1 */
|
||||
|
||||
+3
-3
@@ -2520,9 +2520,9 @@ int retry;
|
||||
all_worn_categories = TRUE;
|
||||
}
|
||||
|
||||
n = query_objlist("What do you want to take off?", invent,
|
||||
SIGNAL_NOMENU | USE_INVLET | INVORDER_SORT, &pick_list,
|
||||
PICK_ANY,
|
||||
n = query_objlist("What do you want to take off?", &invent,
|
||||
(SIGNAL_NOMENU | USE_INVLET | INVORDER_SORT),
|
||||
&pick_list, PICK_ANY,
|
||||
all_worn_categories ? is_worn : is_worn_by_type);
|
||||
if (n > 0) {
|
||||
for (i = 0; i < n; i++)
|
||||
|
||||
+4
-19
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 dogmove.c $NHDT-Date: 1450061092 2015/12/14 02:44:52 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.57 $ */
|
||||
/* NetHack 3.6 dogmove.c $NHDT-Date: 1463704424 2016/05/20 00:33:44 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.60 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -874,7 +874,6 @@ int after; /* this is extra fast monster movement */
|
||||
}
|
||||
newdogpos:
|
||||
if (nix != omx || niy != omy) {
|
||||
struct obj *mw_tmp;
|
||||
boolean wasseen;
|
||||
|
||||
if (info[chi] & ALLOW_U) {
|
||||
@@ -888,23 +887,9 @@ newdogpos:
|
||||
}
|
||||
if (!m_in_out_region(mtmp, nix, niy))
|
||||
return 1;
|
||||
if (((IS_ROCK(levl[nix][niy].typ) && may_dig(nix, niy))
|
||||
|| closed_door(nix, niy))
|
||||
&& mtmp->weapon_check != NO_WEAPON_WANTED
|
||||
&& tunnels(mtmp->data) && needspick(mtmp->data)) {
|
||||
if (closed_door(nix, niy)) {
|
||||
if (!(mw_tmp = MON_WEP(mtmp)) || !is_pick(mw_tmp)
|
||||
|| !is_axe(mw_tmp))
|
||||
mtmp->weapon_check = NEED_PICK_OR_AXE;
|
||||
} else if (IS_TREE(levl[nix][niy].typ)) {
|
||||
if (!(mw_tmp = MON_WEP(mtmp)) || !is_axe(mw_tmp))
|
||||
mtmp->weapon_check = NEED_AXE;
|
||||
} else if (!(mw_tmp = MON_WEP(mtmp)) || !is_pick(mw_tmp)) {
|
||||
mtmp->weapon_check = NEED_PICK_AXE;
|
||||
}
|
||||
if (mtmp->weapon_check >= NEED_PICK_AXE && mon_wield_item(mtmp))
|
||||
return 0;
|
||||
}
|
||||
if (m_digweapon_check(mtmp, nix,niy))
|
||||
return 0;
|
||||
|
||||
/* insert a worm_move() if worms ever begin to eat things */
|
||||
wasseen = canseemon(mtmp);
|
||||
remove_monster(omx, omy);
|
||||
|
||||
+11
-5
@@ -1364,8 +1364,9 @@ register struct obj *obj; /* thrownobj or kickedobj or uwep */
|
||||
int otyp = obj->otyp, hmode;
|
||||
boolean guaranteed_hit = (u.uswallow && mon == u.ustuck);
|
||||
|
||||
hmode = (obj == uwep) ? HMON_APPLIED : (obj == kickedobj) ? HMON_KICKED
|
||||
: HMON_THROWN;
|
||||
hmode = (obj == uwep) ? HMON_APPLIED
|
||||
: (obj == kickedobj) ? HMON_KICKED
|
||||
: HMON_THROWN;
|
||||
|
||||
/* Differences from melee weapons:
|
||||
*
|
||||
@@ -1509,18 +1510,22 @@ register struct obj *obj; /* thrownobj or kickedobj or uwep */
|
||||
}
|
||||
|
||||
if (tmp >= rnd(20)) {
|
||||
boolean wasthrown = (thrownobj != 0);
|
||||
|
||||
/* attack hits mon */
|
||||
if (hmode == HMON_APPLIED)
|
||||
u.uconduct.weaphit++;
|
||||
if (hmon(mon, obj, hmode)) { /* mon still alive */
|
||||
cutworm(mon, bhitpos.x, bhitpos.y, obj);
|
||||
}
|
||||
exercise(A_DEX, TRUE);
|
||||
/* if hero is swallowed and projectile kills the engulfer,
|
||||
obj gets added to engulfer's inventory and then dropped,
|
||||
/* if hero was swallowed and projectile killed the engulfer,
|
||||
'obj' got added to engulfer's inventory and then dropped,
|
||||
so we can't safely use that pointer anymore; it escapes
|
||||
the chance to be used up here... */
|
||||
if (!thrownobj)
|
||||
if (wasthrown && !thrownobj)
|
||||
return 1;
|
||||
|
||||
/* projectiles other than magic stones
|
||||
sometimes disappear when thrown */
|
||||
if (objects[otyp].oc_skill < P_NONE
|
||||
@@ -1531,6 +1536,7 @@ register struct obj *obj; /* thrownobj or kickedobj or uwep */
|
||||
* but we need ammo to stay around longer on average.
|
||||
*/
|
||||
int broken, chance;
|
||||
|
||||
chance = 3 + greatest_erosion(obj) - obj->spe;
|
||||
if (chance > 1)
|
||||
broken = rn2(chance);
|
||||
|
||||
+11
-6
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 drawing.c $NHDT-Date: 1447124657 2015/11/10 03:04:17 $ $NHDT-Branch: master $:$NHDT-Revision: 1.49 $ */
|
||||
/* NetHack 3.6 drawing.c $NHDT-Date: 1463706747 2016/05/20 01:12:27 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.51 $ */
|
||||
/* Copyright (c) NetHack Development Team 1992. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -202,11 +202,12 @@ const struct symdef defsyms[MAXPCHARS] = {
|
||||
{ '^', "magic trap", C(HI_ZAP) }, /* trap */
|
||||
{ '^', "anti-magic field", C(HI_ZAP) }, /* trap */
|
||||
{ '^', "polymorph trap", C(CLR_BRIGHT_GREEN) }, /* trap */
|
||||
{ '^', "vibrating square", C(CLR_YELLOW) }, /* trap */
|
||||
{ '|', "wall", C(CLR_GRAY) }, /* vbeam */
|
||||
{ '-', "wall", C(CLR_GRAY) }, /* hbeam */
|
||||
{ '\\', "wall", C(CLR_GRAY) }, /* lslant */
|
||||
{ '/', "wall", C(CLR_GRAY) }, /* rslant */
|
||||
{ '~', "vibrating square", C(CLR_MAGENTA) }, /* "trap" */
|
||||
/* zap colors are changed by mapglyph() to match type of beam */
|
||||
{ '|', "", C(CLR_GRAY) }, /* vbeam */
|
||||
{ '-', "", C(CLR_GRAY) }, /* hbeam */
|
||||
{ '\\', "", C(CLR_GRAY) }, /* lslant */
|
||||
{ '/', "", C(CLR_GRAY) }, /* rslant */
|
||||
{ '*', "", C(CLR_WHITE) }, /* dig beam */
|
||||
{ '!', "", C(CLR_WHITE) }, /* camera flash beam */
|
||||
{ ')', "", C(HI_WOOD) }, /* boomerang open left */
|
||||
@@ -217,6 +218,7 @@ const struct symdef defsyms[MAXPCHARS] = {
|
||||
{ '*', "", C(HI_ZAP) },
|
||||
{ '#', "poison cloud", C(CLR_BRIGHT_GREEN) }, /* part of a cloud */
|
||||
{ '?', "valid position", C(CLR_BRIGHT_GREEN) }, /* target position */
|
||||
/* swallow colors are changed by mapglyph() to match engulfing monst */
|
||||
{ '/', "", C(CLR_GREEN) }, /* swallow top left */
|
||||
{ '-', "", C(CLR_GREEN) }, /* swallow top center */
|
||||
{ '\\', "", C(CLR_GREEN) }, /* swallow top right */
|
||||
@@ -225,6 +227,7 @@ const struct symdef defsyms[MAXPCHARS] = {
|
||||
{ '\\', "", C(CLR_GREEN) }, /* swallow bottom left */
|
||||
{ '-', "", C(CLR_GREEN) }, /* swallow bottom center */
|
||||
{ '/', "", C(CLR_GREEN) }, /* swallow bottom right */
|
||||
/* explosion colors are changed by mapglyph() to match type of expl. */
|
||||
{ '/', "", C(CLR_ORANGE) }, /* explosion top left */
|
||||
{ '-', "", C(CLR_ORANGE) }, /* explosion top center */
|
||||
{ '\\', "", C(CLR_ORANGE) }, /* explosion top right */
|
||||
@@ -592,6 +595,7 @@ struct symparse loadsyms[] = {
|
||||
{ SYM_PCHAR, S_bars, "S_bars" },
|
||||
{ SYM_PCHAR, S_tree, "S_tree" },
|
||||
{ SYM_PCHAR, S_room, "S_room" },
|
||||
{ SYM_PCHAR, S_darkroom, "S_darkroom" },
|
||||
{ SYM_PCHAR, S_corr, "S_corr" },
|
||||
{ SYM_PCHAR, S_litcorr, "S_litcorr" },
|
||||
{ SYM_PCHAR, S_upstair, "S_upstair" },
|
||||
@@ -636,6 +640,7 @@ struct symparse loadsyms[] = {
|
||||
{ SYM_PCHAR, S_magic_trap, "S_magic_trap" },
|
||||
{ SYM_PCHAR, S_anti_magic_trap, "S_anti_magic_trap" },
|
||||
{ SYM_PCHAR, S_polymorph_trap, "S_polymorph_trap" },
|
||||
{ SYM_PCHAR, S_vibrating_square, "S_vibrating_square" },
|
||||
{ SYM_PCHAR, S_vbeam, "S_vbeam" },
|
||||
{ SYM_PCHAR, S_hbeam, "S_hbeam" },
|
||||
{ SYM_PCHAR, S_lslant, "S_lslant" },
|
||||
|
||||
+91
-9
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 dungeon.c $NHDT-Date: 1450432757 2015/12/18 09:59:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.70 $ */
|
||||
/* NetHack 3.6 dungeon.c $NHDT-Date: 1462486971 2016/05/05 22:22:51 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.73 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -490,6 +490,7 @@ struct proto_dungeon *pd;
|
||||
|
||||
branch_num = find_branch(dungeons[dgn].dname, pd);
|
||||
new_branch = (branch *) alloc(sizeof(branch));
|
||||
(void) memset((genericptr_t)new_branch, 0, sizeof(branch));
|
||||
new_branch->next = (branch *) 0;
|
||||
new_branch->id = branch_id++;
|
||||
new_branch->type = correct_branch_type(&pd->tmpbranch[branch_num]);
|
||||
@@ -545,6 +546,7 @@ struct proto_dungeon *pd;
|
||||
|
||||
pd->final_lev[proto_index] = new_level =
|
||||
(s_level *) alloc(sizeof(s_level));
|
||||
(void) memset((genericptr_t)new_level, 0, sizeof(s_level));
|
||||
/* load new level with data */
|
||||
Strcpy(new_level->proto, tlevel->name);
|
||||
new_level->boneid = tlevel->boneschar;
|
||||
@@ -852,7 +854,7 @@ init_dungeons()
|
||||
* its branch. First, the depth of the entry point:
|
||||
*
|
||||
* depth of branch from "parent" dungeon
|
||||
* + -1 or 1 depending on a up or down stair or
|
||||
* + -1 or 1 depending on an up or down stair or
|
||||
* 0 if portal
|
||||
*
|
||||
* Followed by the depth of the top of the dungeon:
|
||||
@@ -1604,6 +1606,25 @@ level_difficulty()
|
||||
* The same applies to Vlad's Tower, although the increment
|
||||
* there is inconsequential compared to overall depth.
|
||||
*/
|
||||
#if 0
|
||||
/*
|
||||
* The inside of the Wizard's Tower is also effectively a
|
||||
* builds-up area, reached from a portal an arbitrary distance
|
||||
* below rather than stairs 1 level beneath the entry level.
|
||||
*/
|
||||
else if (On_W_tower_level(&u.uz) && In_W_tower(some_X, some_Y, &u.uz))
|
||||
res += (fakewiz1.dlev - u.uz.dlev);
|
||||
/*
|
||||
* Handling this properly would need more information here:
|
||||
* an inside/outside flag, or coordinates to calculate it.
|
||||
* Unfortunately level difficulty may be wanted before
|
||||
* coordinates have been chosen so simply extending this
|
||||
* routine to take extra arguments is not sufficient to cope.
|
||||
* The difference beyond naive depth-from-surface is small
|
||||
* relative to the overall depth, so just ignore complications
|
||||
* posed by W_tower.
|
||||
*/
|
||||
#endif /*0*/
|
||||
}
|
||||
return (xchar) res;
|
||||
}
|
||||
@@ -2119,6 +2140,50 @@ int fd;
|
||||
return load;
|
||||
}
|
||||
|
||||
/* to support '#stats' wizard-mode command */
|
||||
void
|
||||
overview_stats(win, statsfmt, total_count, total_size)
|
||||
winid win;
|
||||
const char *statsfmt;
|
||||
long *total_count, *total_size;
|
||||
{
|
||||
char buf[BUFSZ], hdrbuf[QBUFSZ];
|
||||
long ocount, osize, bcount, bsize, acount, asize;
|
||||
struct cemetery *ce;
|
||||
mapseen *mptr = find_mapseen(&u.uz);
|
||||
|
||||
ocount = bcount = acount = osize = bsize = asize = 0L;
|
||||
for (mptr = mapseenchn; mptr; mptr = mptr->next) {
|
||||
++ocount;
|
||||
osize += (long) sizeof *mptr;
|
||||
for (ce = mptr->final_resting_place; ce; ce = ce->next) {
|
||||
++bcount;
|
||||
bsize += (long) sizeof *ce;
|
||||
}
|
||||
if (mptr->custom_lth) {
|
||||
++acount;
|
||||
asize += (long) (mptr->custom_lth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
Sprintf(hdrbuf, "general, size %ld", (long) sizeof (mapseen));
|
||||
Sprintf(buf, statsfmt, hdrbuf, ocount, osize);
|
||||
putstr(win, 0, buf);
|
||||
if (bcount) {
|
||||
Sprintf(hdrbuf, "cemetery, size %ld",
|
||||
(long) sizeof (struct cemetery));
|
||||
Sprintf(buf, statsfmt, hdrbuf, bcount, bsize);
|
||||
putstr(win, 0, buf);
|
||||
}
|
||||
if (acount) {
|
||||
Sprintf(hdrbuf, "annotations, text");
|
||||
Sprintf(buf, statsfmt, hdrbuf, acount, asize);
|
||||
putstr(win, 0, buf);
|
||||
}
|
||||
*total_count += ocount + bcount + acount;
|
||||
*total_size += osize + bsize + asize;
|
||||
}
|
||||
|
||||
/* Remove all mapseen objects for a particular dnum.
|
||||
* Useful during quest expulsion to remove quest levels.
|
||||
* [No longer deleted, just marked as unreachable. #overview will
|
||||
@@ -2421,6 +2486,9 @@ recalc_mapseen()
|
||||
/* An automatic annotation is added to the Castle and
|
||||
* to Fort Ludios once their structure's main entrance
|
||||
* has been seen (in person or via magic mapping).
|
||||
* For the Fort, that entrance is just a secret door
|
||||
* which will be converted into a regular one when
|
||||
* located (or destroyed).
|
||||
* DOOR: possibly a lowered drawbridge's open portcullis;
|
||||
* DBWALL: a raised drawbridge's "closed door";
|
||||
* DRAWBRIDGE_DOWN: the span provided by lowered bridge,
|
||||
@@ -2430,6 +2498,26 @@ recalc_mapseen()
|
||||
* the adjacent DBWALL has been seen.
|
||||
*/
|
||||
case DOOR:
|
||||
if (Is_knox(&u.uz)) {
|
||||
int ty, tx = x - 4;
|
||||
|
||||
/* Throne is four columns left, either directly in
|
||||
* line or one row higher or lower, and doesn't have
|
||||
* to have been seen yet.
|
||||
* ......|}}}.
|
||||
* ..\...S}...
|
||||
* ..\...S}...
|
||||
* ......|}}}.
|
||||
* For 3.6.0 and earlier, it was always in direct line:
|
||||
* both throne and door on the lower of the two rows.
|
||||
*/
|
||||
for (ty = y - 1; ty <= y + 1; ++ty)
|
||||
if (isok(tx, ty) && IS_THRONE(levl[tx][ty].typ)) {
|
||||
mptr->flags.ludios = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (is_drawbridge_wall(x, y) < 0)
|
||||
break;
|
||||
/* else FALLTHRU */
|
||||
@@ -2437,8 +2525,6 @@ recalc_mapseen()
|
||||
case DRAWBRIDGE_DOWN:
|
||||
if (Is_stronghold(&u.uz))
|
||||
mptr->flags.castle = 1, mptr->flags.castletune = 1;
|
||||
else if (Is_knox(&u.uz))
|
||||
mptr->flags.ludios = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -2764,10 +2850,6 @@ boolean printdun;
|
||||
if (In_endgame(&mptr->lev))
|
||||
Sprintf(buf, "%s%s:", TAB, endgamelevelname(tmpbuf, i));
|
||||
else
|
||||
/* FIXME: when this branch has only one level (Ft.Ludios),
|
||||
* listing "Level 1:" for it might confuse inexperienced
|
||||
* players into thinking there's more than one.
|
||||
*/
|
||||
Sprintf(buf, "%sLevel %d:", TAB, i);
|
||||
|
||||
/* wizmode prints out proto dungeon names for clarity */
|
||||
@@ -2779,7 +2861,7 @@ boolean printdun;
|
||||
}
|
||||
/* [perhaps print custom annotation on its own line when it's long] */
|
||||
if (mptr->custom)
|
||||
Sprintf(eos(buf), " (%s)", mptr->custom);
|
||||
Sprintf(eos(buf), " \"%s\"", mptr->custom);
|
||||
if (on_level(&u.uz, &mptr->lev))
|
||||
Sprintf(eos(buf), " <- You %s here.",
|
||||
(!final || (final == 1 && how == ASCENDED)) ? "are" : "were");
|
||||
|
||||
@@ -1502,7 +1502,9 @@ struct obj *obj;
|
||||
make_confused(HConfusion + d(2, 4), FALSE);
|
||||
} else if (!rn2(4) && !Blind) {
|
||||
pline("Everything suddenly goes dark.");
|
||||
make_blinded((long) d(2, 10), FALSE);
|
||||
/* hero is not Blind, but Blinded timer might be nonzero if
|
||||
blindness is being overridden by the Eyes of the Overworld */
|
||||
make_blinded((Blinded & TIMEOUT) + (long) d(2, 10), FALSE);
|
||||
if (!Blind)
|
||||
Your1(vision_clears);
|
||||
} else if (!rn2(3)) {
|
||||
@@ -1785,6 +1787,9 @@ struct obj *otmp;
|
||||
#endif
|
||||
} else if (otmp->otyp == EGG && stale_egg(otmp)) {
|
||||
pline("Ugh. Rotten egg."); /* perhaps others like it */
|
||||
/* increasing existing nausea means that it will take longer
|
||||
before eventual vomit, but also means that constitution
|
||||
will be abused more times before illness completes */
|
||||
make_vomiting((Vomiting & TIMEOUT) + (long) d(10, 4), TRUE);
|
||||
} else {
|
||||
give_feedback:
|
||||
@@ -2610,7 +2615,7 @@ struct obj *obj;
|
||||
obj, doname, thesimpleoname, "that")) != 'y')
|
||||
return 0;
|
||||
}
|
||||
if (!wield_tool(obj, "use"))
|
||||
if (!wield_tool(obj, "use"))
|
||||
return 0;
|
||||
res = 1;
|
||||
}
|
||||
@@ -2652,15 +2657,21 @@ bite()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* as time goes by - called by moveloop() and domove() */
|
||||
/* as time goes by - called by moveloop(every move) & domove(melee attack) */
|
||||
void
|
||||
gethungry()
|
||||
{
|
||||
if (u.uinvulnerable)
|
||||
return; /* you don't feel hungrier */
|
||||
|
||||
if ((!u.usleep || !rn2(10)) /* slow metabolic rate while asleep */
|
||||
&& (carnivorous(youmonst.data) || herbivorous(youmonst.data))
|
||||
/* being polymorphed into a creature which doesn't eat prevents
|
||||
this first uhunger decrement, but to stay in such form the hero
|
||||
will need to wear an Amulet of Unchanging so still burn a small
|
||||
amount of nutrition in the 'moves % 20' ring/amulet check below */
|
||||
if ((!Unaware || !rn2(10)) /* slow metabolic rate while asleep */
|
||||
&& (carnivorous(youmonst.data)
|
||||
|| herbivorous(youmonst.data)
|
||||
|| metallivorous(youmonst.data))
|
||||
&& !Slow_digestion)
|
||||
u.uhunger--; /* ordinary food consumption */
|
||||
|
||||
@@ -2677,8 +2688,8 @@ gethungry()
|
||||
/* Conflict uses up food too */
|
||||
if (HConflict || (EConflict & (~W_ARTI)))
|
||||
u.uhunger--;
|
||||
/* +0 charged rings don't do anything, so don't affect hunger */
|
||||
/* Slow digestion still uses ring hunger */
|
||||
/* +0 charged rings don't do anything, so don't affect hunger.
|
||||
Slow digestion cancels move hunger but still causes ring hunger. */
|
||||
switch ((int) (moves % 20)) { /* note: use even cases only */
|
||||
case 4:
|
||||
if (uleft && (uleft->spe || !objects[uleft->otyp].oc_charged))
|
||||
@@ -2839,11 +2850,14 @@ boolean incr;
|
||||
}
|
||||
|
||||
if (newhs == FAINTING) {
|
||||
/* u,uhunger is likely to be negative at this point */
|
||||
int uhunger_div_by_10 = sgn(u.uhunger) * ((abs(u.uhunger) + 5) / 10);
|
||||
|
||||
if (is_fainted())
|
||||
newhs = FAINTED;
|
||||
if (u.uhs <= WEAK || rn2(20 - u.uhunger / 10) >= 19) {
|
||||
if (u.uhs <= WEAK || rn2(20 - uhunger_div_by_10) >= 19) {
|
||||
if (!is_fainted() && multi >= 0 /* %% */) {
|
||||
int duration = 10 - (u.uhunger / 10);
|
||||
int duration = 10 - uhunger_div_by_10;
|
||||
|
||||
/* stop what you're doing, then faint */
|
||||
stop_occupation();
|
||||
@@ -2858,7 +2872,11 @@ boolean incr;
|
||||
if (!Levitation)
|
||||
selftouch("Falling, you");
|
||||
}
|
||||
} else if (u.uhunger < -(int) (200 + 20 * ACURR(A_CON))) {
|
||||
|
||||
/* this used to be -(200 + 20 * Con) but that was when being asleep
|
||||
suppressed per-turn uhunger decrement but being fainted didn't;
|
||||
now uhunger becomes more negative at a slower rate */
|
||||
} else if (u.uhunger < -(100 + 10 * (int) ACURR(A_CON))) {
|
||||
u.uhs = STARVED;
|
||||
context.botl = 1;
|
||||
bot();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 end.c $NHDT-Date: 1454571522 2016/02/04 07:38:42 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.114 $ */
|
||||
/* NetHack 3.6 end.c $NHDT-Date: 1461919723 2016/04/29 08:48:43 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.116 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -50,6 +50,9 @@ STATIC_DCL void FDECL(artifact_score, (struct obj *, BOOLEAN_P, winid));
|
||||
STATIC_DCL void FDECL(really_done, (int)) NORETURN;
|
||||
STATIC_DCL boolean FDECL(odds_and_ends, (struct obj *, int));
|
||||
STATIC_DCL void FDECL(savelife, (int));
|
||||
STATIC_PTR int FDECL(CFDECLSPEC vanqsort_cmp, (const genericptr,
|
||||
const genericptr));
|
||||
STATIC_DCL int NDECL(set_vanq_order);
|
||||
STATIC_DCL void FDECL(list_vanquished, (CHAR_P, BOOLEAN_P));
|
||||
STATIC_DCL void FDECL(list_genocided, (CHAR_P, BOOLEAN_P));
|
||||
STATIC_DCL boolean FDECL(should_query_disclose_option, (int, char *));
|
||||
@@ -627,7 +630,7 @@ int category;
|
||||
char *defquery;
|
||||
{
|
||||
int idx;
|
||||
char *dop;
|
||||
char disclose, *dop;
|
||||
|
||||
*defquery = 'n';
|
||||
if ((dop = index(disclosure_options, category)) != 0) {
|
||||
@@ -639,15 +642,22 @@ char *defquery;
|
||||
*defquery = DISCLOSE_PROMPT_DEFAULT_YES;
|
||||
return TRUE;
|
||||
}
|
||||
if (flags.end_disclose[idx] == DISCLOSE_YES_WITHOUT_PROMPT) {
|
||||
disclose = flags.end_disclose[idx];
|
||||
if (disclose == DISCLOSE_YES_WITHOUT_PROMPT) {
|
||||
*defquery = 'y';
|
||||
return FALSE;
|
||||
} else if (flags.end_disclose[idx] == DISCLOSE_NO_WITHOUT_PROMPT) {
|
||||
} else if (disclose == DISCLOSE_SPECIAL_WITHOUT_PROMPT) {
|
||||
*defquery = 'a';
|
||||
return FALSE;
|
||||
} else if (disclose == DISCLOSE_NO_WITHOUT_PROMPT) {
|
||||
*defquery = 'n';
|
||||
return FALSE;
|
||||
} else if (flags.end_disclose[idx] == DISCLOSE_PROMPT_DEFAULT_YES) {
|
||||
} else if (disclose == DISCLOSE_PROMPT_DEFAULT_YES) {
|
||||
*defquery = 'y';
|
||||
return TRUE;
|
||||
} else if (disclose == DISCLOSE_PROMPT_DEFAULT_SPECIAL) {
|
||||
*defquery = 'a';
|
||||
return TRUE;
|
||||
} else {
|
||||
*defquery = 'n';
|
||||
return TRUE;
|
||||
@@ -942,8 +952,8 @@ int how;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ((wizard || discover) && (how <= GENOCIDED) &&
|
||||
!paranoid_query(ParanoidDie, "Die?")) {
|
||||
if ((wizard || discover) && (how <= GENOCIDED)
|
||||
&& !paranoid_query(ParanoidDie, "Die?")) {
|
||||
pline("OK, so you don't %s.", (how == CHOKING) ? "choke" : "die");
|
||||
savelife(how);
|
||||
killer.name[0] = 0;
|
||||
@@ -1329,9 +1339,6 @@ struct obj *list;
|
||||
boolean identified, all_containers, reportempty;
|
||||
{
|
||||
register struct obj *box, *obj;
|
||||
struct obj **oarray;
|
||||
int i, n;
|
||||
char *invlet;
|
||||
char buf[BUFSZ];
|
||||
boolean cat, deadcat;
|
||||
|
||||
@@ -1355,43 +1362,24 @@ boolean identified, all_containers, reportempty;
|
||||
} else if (box->cobj) {
|
||||
winid tmpwin = create_nhwindow(NHW_MENU);
|
||||
|
||||
/* count the number of items */
|
||||
for (n = 0, obj = box->cobj; obj; obj = obj->nobj)
|
||||
n++;
|
||||
/* Make a temporary array to store the objects sorted */
|
||||
oarray = objarr_init(n);
|
||||
|
||||
/* Add objects to the array */
|
||||
i = 0;
|
||||
invlet = flags.inv_order;
|
||||
nextclass:
|
||||
for (obj = box->cobj; obj; obj = obj->nobj) {
|
||||
if (!flags.sortpack || obj->oclass == *invlet) {
|
||||
objarr_set(
|
||||
obj, i++, oarray,
|
||||
(flags.sortloot == 'f' || flags.sortloot == 'l'));
|
||||
}
|
||||
} /* for loop */
|
||||
if (flags.sortpack) {
|
||||
if (*++invlet)
|
||||
goto nextclass;
|
||||
}
|
||||
|
||||
sortloot(&box->cobj,
|
||||
(((flags.sortloot == 'l' || flags.sortloot == 'f')
|
||||
? SORTLOOT_LOOT : 0)
|
||||
| (flags.sortpack ? SORTLOOT_PACK : 0)),
|
||||
FALSE);
|
||||
Sprintf(buf, "Contents of %s:", the(xname(box)));
|
||||
putstr(tmpwin, 0, buf);
|
||||
putstr(tmpwin, 0, "");
|
||||
for (i = 0; i < n; i++) {
|
||||
obj = oarray[i];
|
||||
for (obj = box->cobj; obj; obj = obj->nobj) {
|
||||
if (identified) {
|
||||
makeknown(obj->otyp);
|
||||
obj->known = obj->bknown = obj->dknown = obj->rknown =
|
||||
1;
|
||||
obj->known = obj->bknown = obj->dknown
|
||||
= obj->rknown = 1;
|
||||
if (Is_container(obj) || obj->otyp == STATUE)
|
||||
obj->cknown = obj->lknown = 1;
|
||||
}
|
||||
putstr(tmpwin, 0, doname(obj));
|
||||
}
|
||||
free(oarray);
|
||||
if (cat)
|
||||
putstr(tmpwin, 0, "Schroedinger's cat");
|
||||
else if (deadcat)
|
||||
@@ -1446,6 +1434,142 @@ int status;
|
||||
nethack_exit(status);
|
||||
}
|
||||
|
||||
extern const int monstr[];
|
||||
|
||||
static const char *vanqorders[] = {
|
||||
"traditional: by monster level, by internal monster index",
|
||||
#define VANQ_MLVL_MNDX 0
|
||||
"by monster toughness, by internal monster index",
|
||||
#define VANQ_MSTR_MNDX 1
|
||||
"alphabetically, first unique monsters, then others",
|
||||
#define VANQ_ALPHA_SEP 2
|
||||
"alphabetically, unique monsters and others intermixed",
|
||||
#define VANQ_ALPHA_MIX 3
|
||||
"by monster class, high to low level within class",
|
||||
#define VANQ_MCLS_HTOL 4
|
||||
"by monster class, low to high level within class",
|
||||
#define VANQ_MCLS_LTOH 5
|
||||
"by count, high to low, by internal index within tied count",
|
||||
#define VANQ_COUNT_H_L 6
|
||||
"by count, low to high, by internal index within tied count",
|
||||
#define VANQ_COUNT_L_H 7
|
||||
};
|
||||
static int vanq_sortmode = VANQ_MLVL_MNDX;
|
||||
|
||||
STATIC_PTR int CFDECLSPEC
|
||||
vanqsort_cmp(vptr1, vptr2)
|
||||
const genericptr vptr1;
|
||||
const genericptr vptr2;
|
||||
{
|
||||
int indx1 = *(short *) vptr1, indx2 = *(short *) vptr2,
|
||||
mlev1, mlev2, mstr1, mstr2, uniq1, uniq2, died1, died2, res;
|
||||
const char *name1, *name2, *punct;
|
||||
schar mcls1, mcls2;
|
||||
|
||||
switch (vanq_sortmode) {
|
||||
default:
|
||||
case VANQ_MLVL_MNDX:
|
||||
/* sort by monster level */
|
||||
mlev1 = mons[indx1].mlevel, mlev2 = mons[indx2].mlevel;
|
||||
res = mlev2 - mlev1; /* mlevel high to low */
|
||||
break;
|
||||
case VANQ_MSTR_MNDX:
|
||||
/* sort by monster toughness */
|
||||
mstr1 = monstr[indx1], mstr2 = monstr[indx2];
|
||||
res = mstr2 - mstr1; /* monstr high to low */
|
||||
break;
|
||||
case VANQ_ALPHA_SEP:
|
||||
uniq1 = ((mons[indx1].geno & G_UNIQ) && indx1 != PM_HIGH_PRIEST);
|
||||
uniq2 = ((mons[indx2].geno & G_UNIQ) && indx2 != PM_HIGH_PRIEST);
|
||||
if (uniq1 ^ uniq2) { /* one or other uniq, but not both */
|
||||
res = uniq2 - uniq1;
|
||||
break;
|
||||
} /* else both unique or neither unique */
|
||||
/*FALLTHRU*/
|
||||
case VANQ_ALPHA_MIX:
|
||||
name1 = mons[indx1].mname, name2 = mons[indx2].mname;
|
||||
res = strcmpi(name1, name2); /* caseblind alhpa, low to high */
|
||||
break;
|
||||
case VANQ_MCLS_HTOL:
|
||||
case VANQ_MCLS_LTOH:
|
||||
/* mons[].mlet is a small integer, 1..N, of type plain char;
|
||||
if 'char' happens to be unsigned, (mlet1 - mlet2) would yield
|
||||
an inappropriate result when mlet2 is greater than mlet1,
|
||||
so force our copies (mcls1, mcls2) to be signed */
|
||||
mcls1 = (schar) mons[indx1].mlet, mcls2 = (schar) mons[indx2].mlet;
|
||||
/* S_ANT through S_ZRUTY correspond to lowercase monster classes,
|
||||
S_ANGEL through S_ZOMBIE correspond to uppercase, and various
|
||||
punctuation characters are used for classes beyond those */
|
||||
if (mcls1 > S_ZOMBIE && mcls2 > S_ZOMBIE) {
|
||||
/* force a specific order to the punctuation classes that's
|
||||
different from the internal order;
|
||||
internal order is ok if neither or just one is punctuation
|
||||
since letters have lower values so come out before punct */
|
||||
static const char punctclasses[] = {
|
||||
S_LIZARD, S_EEL, S_GOLEM, S_GHOST, S_DEMON, S_HUMAN, '\0'
|
||||
};
|
||||
|
||||
if ((punct = index(punctclasses, mcls1)) != 0)
|
||||
mcls1 = (schar) (S_ZOMBIE + 1 + (int) (punct - punctclasses));
|
||||
if ((punct = index(punctclasses, mcls2)) != 0)
|
||||
mcls2 = (schar) (S_ZOMBIE + 1 + (int) (punct - punctclasses));
|
||||
}
|
||||
res = mcls1 - mcls2; /* class */
|
||||
if (res == 0) {
|
||||
mlev1 = mons[indx1].mlevel, mlev2 = mons[indx2].mlevel;
|
||||
res = mlev1 - mlev2; /* mlevel low to high */
|
||||
if (vanq_sortmode == VANQ_MCLS_HTOL)
|
||||
res = -res; /* mlevel high to low */
|
||||
}
|
||||
break;
|
||||
case VANQ_COUNT_H_L:
|
||||
case VANQ_COUNT_L_H:
|
||||
died1 = mvitals[indx1].died, died2 = mvitals[indx2].died;
|
||||
res = died2 - died1; /* dead count high to low */
|
||||
if (vanq_sortmode == VANQ_COUNT_L_H)
|
||||
res = -res; /* dead count low to high */
|
||||
break;
|
||||
}
|
||||
/* tiebreaker: internal mons[] index */
|
||||
if (res == 0)
|
||||
res = indx1 - indx2; /* mndx low to high */
|
||||
return res;
|
||||
}
|
||||
|
||||
/* returns -1 if cancelled via ESC */
|
||||
STATIC_OVL int
|
||||
set_vanq_order()
|
||||
{
|
||||
winid tmpwin;
|
||||
menu_item *selected;
|
||||
anything any;
|
||||
int i, n, choice;
|
||||
|
||||
tmpwin = create_nhwindow(NHW_MENU);
|
||||
start_menu(tmpwin);
|
||||
any = zeroany; /* zero out all bits */
|
||||
for (i = 0; i < SIZE(vanqorders); i++) {
|
||||
if (i == VANQ_ALPHA_MIX || i == VANQ_MCLS_HTOL) /* skip these */
|
||||
continue;
|
||||
any.a_int = i + 1;
|
||||
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, vanqorders[i],
|
||||
(i == vanq_sortmode) ? MENU_SELECTED : MENU_UNSELECTED);
|
||||
}
|
||||
end_menu(tmpwin, "Sort order for vanquished monster counts");
|
||||
|
||||
n = select_menu(tmpwin, PICK_ONE, &selected);
|
||||
destroy_nhwindow(tmpwin);
|
||||
if (n > 0) {
|
||||
choice = selected[0].item.a_int - 1;
|
||||
/* skip preselected entry if we have more than one item chosen */
|
||||
if (n > 1 && choice == vanq_sortmode)
|
||||
choice = selected[1].item.a_int - 1;
|
||||
free((genericptr_t) selected);
|
||||
vanq_sortmode = choice;
|
||||
}
|
||||
return (n < 0) ? -1 : vanq_sortmode;
|
||||
}
|
||||
|
||||
/* #vanquished command */
|
||||
int
|
||||
dovanquished()
|
||||
@@ -1454,75 +1578,112 @@ dovanquished()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* high priests aren't unique but are flagged as such to simplify something */
|
||||
#define UniqCritterIndx(mndx) ((mons[mndx].geno & G_UNIQ) \
|
||||
&& mndx != PM_HIGH_PRIEST)
|
||||
|
||||
STATIC_OVL void
|
||||
list_vanquished(defquery, ask)
|
||||
char defquery;
|
||||
boolean ask;
|
||||
{
|
||||
register int i, lev;
|
||||
int ntypes = 0, max_lev = 0, nkilled;
|
||||
register int i;
|
||||
int pfx, nkilled;
|
||||
unsigned ntypes, ni;
|
||||
long total_killed = 0L;
|
||||
char c;
|
||||
winid klwin;
|
||||
char buf[BUFSZ];
|
||||
short mindx[NUMMONS];
|
||||
char c, buf[BUFSZ], buftoo[BUFSZ];
|
||||
|
||||
/* get totals first */
|
||||
ntypes = 0;
|
||||
for (i = LOW_PM; i < NUMMONS; i++) {
|
||||
if (mvitals[i].died)
|
||||
ntypes++;
|
||||
total_killed += (long) mvitals[i].died;
|
||||
if (mons[i].mlevel > max_lev)
|
||||
max_lev = mons[i].mlevel;
|
||||
if ((nkilled = (int) mvitals[i].died) == 0)
|
||||
continue;
|
||||
mindx[ntypes++] = i;
|
||||
total_killed += (long) nkilled;
|
||||
}
|
||||
|
||||
/* vanquished creatures list;
|
||||
* includes all dead monsters, not just those killed by the player
|
||||
*/
|
||||
if (ntypes != 0) {
|
||||
char mlet, prev_mlet = 0; /* used as small integer, not character */
|
||||
boolean class_header, uniq_header, was_uniq = FALSE;
|
||||
|
||||
c = ask ? yn_function(
|
||||
"Do you want an account of creatures vanquished?",
|
||||
ynqchars, defquery)
|
||||
ynaqchars, defquery)
|
||||
: defquery;
|
||||
if (c == 'q')
|
||||
done_stopprint++;
|
||||
if (c == 'y' || c == 'a') {
|
||||
if (c == 'a') { /* ask player to choose sort order */
|
||||
/* choose value for vanq_sortmode via menu; ESC cancels list
|
||||
of vanquished monsters but does not set 'done_stopprint' */
|
||||
if (set_vanq_order() < 0)
|
||||
return;
|
||||
}
|
||||
uniq_header = (vanq_sortmode == VANQ_ALPHA_SEP);
|
||||
class_header = (vanq_sortmode == VANQ_MCLS_LTOH
|
||||
|| vanq_sortmode == VANQ_MCLS_HTOL);
|
||||
|
||||
klwin = create_nhwindow(NHW_MENU);
|
||||
putstr(klwin, 0, "Vanquished creatures:");
|
||||
putstr(klwin, 0, "");
|
||||
|
||||
/* countdown by monster "toughness" */
|
||||
for (lev = max_lev; lev >= 0; lev--)
|
||||
for (i = LOW_PM; i < NUMMONS; i++)
|
||||
if (mons[i].mlevel == lev
|
||||
&& (nkilled = mvitals[i].died) > 0) {
|
||||
if ((mons[i].geno & G_UNIQ) && i != PM_HIGH_PRIEST) {
|
||||
Sprintf(buf, "%s%s",
|
||||
!type_is_pname(&mons[i]) ? "The " : "",
|
||||
mons[i].mname);
|
||||
if (nkilled > 1) {
|
||||
switch (nkilled) {
|
||||
case 2:
|
||||
Sprintf(eos(buf), " (twice)");
|
||||
break;
|
||||
case 3:
|
||||
Sprintf(eos(buf), " (thrice)");
|
||||
break;
|
||||
default:
|
||||
Sprintf(eos(buf), " (%d times)", nkilled);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* trolls or undead might have come back,
|
||||
but we don't keep track of that */
|
||||
if (nkilled == 1)
|
||||
Strcpy(buf, an(mons[i].mname));
|
||||
else
|
||||
Sprintf(buf, "%d %s", nkilled,
|
||||
makeplural(mons[i].mname));
|
||||
qsort((genericptr_t) mindx, ntypes, sizeof *mindx, vanqsort_cmp);
|
||||
for (ni = 0; ni < ntypes; ni++) {
|
||||
i = mindx[ni];
|
||||
nkilled = mvitals[i].died;
|
||||
mlet = mons[i].mlet;
|
||||
if (class_header && mlet != prev_mlet) {
|
||||
Strcpy(buf, def_monsyms[(int) mlet].explain);
|
||||
putstr(klwin, ask ? 0 : iflags.menu_headings,
|
||||
upstart(buf));
|
||||
prev_mlet = mlet;
|
||||
}
|
||||
if (UniqCritterIndx(i)) {
|
||||
Sprintf(buf, "%s%s",
|
||||
!type_is_pname(&mons[i]) ? "the " : "",
|
||||
mons[i].mname);
|
||||
if (nkilled > 1) {
|
||||
switch (nkilled) {
|
||||
case 2:
|
||||
Sprintf(eos(buf), " (twice)");
|
||||
break;
|
||||
case 3:
|
||||
Sprintf(eos(buf), " (thrice)");
|
||||
break;
|
||||
default:
|
||||
Sprintf(eos(buf), " (%d times)", nkilled);
|
||||
break;
|
||||
}
|
||||
putstr(klwin, 0, buf);
|
||||
}
|
||||
was_uniq = TRUE;
|
||||
} else {
|
||||
if (uniq_header && was_uniq) {
|
||||
putstr(klwin, 0, "");
|
||||
was_uniq = FALSE;
|
||||
}
|
||||
/* trolls or undead might have come back,
|
||||
but we don't keep track of that */
|
||||
if (nkilled == 1)
|
||||
Strcpy(buf, an(mons[i].mname));
|
||||
else
|
||||
Sprintf(buf, "%3d %s", nkilled,
|
||||
makeplural(mons[i].mname));
|
||||
}
|
||||
/* number of leading spaces to match 3 digit prefix */
|
||||
pfx = !strncmpi(buf, "the ", 3) ? 0
|
||||
: !strncmpi(buf, "an ", 3) ? 1
|
||||
: !strncmpi(buf, "a ", 2) ? 2
|
||||
: !isdigit(buf[2]) ? 4 : 0;
|
||||
if (class_header)
|
||||
++pfx;
|
||||
Sprintf(buftoo, "%*s%s", pfx, "", buf);
|
||||
putstr(klwin, 0, buftoo);
|
||||
}
|
||||
/*
|
||||
* if (Hallucination)
|
||||
* putstr(klwin, 0, "and a partridge in a pear tree");
|
||||
@@ -1547,10 +1708,14 @@ num_genocides()
|
||||
{
|
||||
int i, n = 0;
|
||||
|
||||
for (i = LOW_PM; i < NUMMONS; ++i)
|
||||
if (mvitals[i].mvflags & G_GENOD)
|
||||
for (i = LOW_PM; i < NUMMONS; ++i) {
|
||||
if (mvitals[i].mvflags & G_GENOD) {
|
||||
++n;
|
||||
|
||||
if (UniqCritterIndx(i))
|
||||
impossible("unique creature '%d: %s' genocided?",
|
||||
i, mons[i].mname);
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -1559,11 +1724,12 @@ num_extinct()
|
||||
{
|
||||
int i, n = 0;
|
||||
|
||||
for (i = LOW_PM; i < NUMMONS; ++i)
|
||||
if (!(mvitals[i].mvflags & G_GENOD) && (mvitals[i].mvflags & G_GONE)
|
||||
&& !(mons[i].geno & G_UNIQ))
|
||||
for (i = LOW_PM; i < NUMMONS; ++i) {
|
||||
if (UniqCritterIndx(i))
|
||||
continue;
|
||||
if ((mvitals[i].mvflags & G_GONE) == G_EXTINCT)
|
||||
++n;
|
||||
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -1598,19 +1764,24 @@ boolean ask;
|
||||
putstr(klwin, 0, buf);
|
||||
putstr(klwin, 0, "");
|
||||
|
||||
for (i = LOW_PM; i < NUMMONS; i++)
|
||||
if (mvitals[i].mvflags & G_GONE && !(mons[i].geno & G_UNIQ)) {
|
||||
if ((mons[i].geno & G_UNIQ) && i != PM_HIGH_PRIEST)
|
||||
Sprintf(buf, "%s%s",
|
||||
!type_is_pname(&mons[i]) ? "" : "the ",
|
||||
mons[i].mname);
|
||||
else
|
||||
Strcpy(buf, makeplural(mons[i].mname));
|
||||
if (!(mvitals[i].mvflags & G_GENOD))
|
||||
for (i = LOW_PM; i < NUMMONS; i++) {
|
||||
/* uniques can't be genocided but can become extinct;
|
||||
however, they're never reported as extinct, so skip them */
|
||||
if (UniqCritterIndx(i))
|
||||
continue;
|
||||
if (mvitals[i].mvflags & G_GONE) {
|
||||
Strcpy(buf, makeplural(mons[i].mname));
|
||||
/*
|
||||
* "Extinct" is unfortunate terminology. A species
|
||||
* is marked extinct when its birth limit is reached,
|
||||
* but there might be members of the species still
|
||||
* alive, contradicting the meaning of the word.
|
||||
*/
|
||||
if ((mvitals[i].mvflags & G_GONE) == G_EXTINCT)
|
||||
Strcat(buf, " (extinct)");
|
||||
putstr(klwin, 0, buf);
|
||||
}
|
||||
|
||||
}
|
||||
putstr(klwin, 0, "");
|
||||
if (ngenocided > 0) {
|
||||
Sprintf(buf, "%d species genocided.", ngenocided);
|
||||
|
||||
+37
-19
@@ -388,6 +388,7 @@ xchar e_type;
|
||||
if ((ep = engr_at(x, y)) != 0)
|
||||
del_engr(ep);
|
||||
ep = newengr(strlen(s) + 1);
|
||||
(void) memset((genericptr_t)ep, 0, sizeof(struct engr));
|
||||
ep->nxt_engr = head_engr;
|
||||
head_engr = ep;
|
||||
ep->engr_x = x;
|
||||
@@ -414,7 +415,7 @@ int x, y;
|
||||
}
|
||||
|
||||
/*
|
||||
* freehand - returns true if player has a free hand
|
||||
* freehand - returns true if player has a free hand
|
||||
*/
|
||||
int
|
||||
freehand()
|
||||
@@ -429,30 +430,30 @@ static NEARDATA const char styluses[] = { ALL_CLASSES, ALLOW_NONE,
|
||||
RING_CLASS, 0 };
|
||||
|
||||
/* Mohs' Hardness Scale:
|
||||
* 1 - Talc 6 - Orthoclase
|
||||
* 2 - Gypsum 7 - Quartz
|
||||
* 3 - Calcite 8 - Topaz
|
||||
* 4 - Fluorite 9 - Corundum
|
||||
* 5 - Apatite 10 - Diamond
|
||||
* 1 - Talc 6 - Orthoclase
|
||||
* 2 - Gypsum 7 - Quartz
|
||||
* 3 - Calcite 8 - Topaz
|
||||
* 4 - Fluorite 9 - Corundum
|
||||
* 5 - Apatite 10 - Diamond
|
||||
*
|
||||
* Since granite is an igneous rock hardness ~ 7, anything >= 8 should
|
||||
* probably be able to scratch the rock.
|
||||
* Devaluation of less hard gems is not easily possible because obj struct
|
||||
* does not contain individual oc_cost currently. 7/91
|
||||
*
|
||||
* steel - 5-8.5 (usu. weapon)
|
||||
* diamond - 10 * jade - 5-6 (nephrite)
|
||||
* ruby - 9 (corundum) * turquoise - 5-6
|
||||
* sapphire - 9 (corundum) * opal - 5-6
|
||||
* topaz - 8 * glass - ~5.5
|
||||
* emerald - 7.5-8 (beryl) * dilithium - 4-5??
|
||||
* aquamarine - 7.5-8 (beryl) * iron - 4-5
|
||||
* garnet - 7.25 (var. 6.5-8) * fluorite - 4
|
||||
* agate - 7 (quartz) * brass - 3-4
|
||||
* amethyst - 7 (quartz) * gold - 2.5-3
|
||||
* jasper - 7 (quartz) * silver - 2.5-3
|
||||
* onyx - 7 (quartz) * copper - 2.5-3
|
||||
* moonstone - 6 (orthoclase) * amber - 2-2.5
|
||||
* steel - 5-8.5 (usu. weapon)
|
||||
* diamond - 10 * jade - 5-6 (nephrite)
|
||||
* ruby - 9 (corundum) * turquoise - 5-6
|
||||
* sapphire - 9 (corundum) * opal - 5-6
|
||||
* topaz - 8 * glass - ~5.5
|
||||
* emerald - 7.5-8 (beryl) * dilithium - 4-5??
|
||||
* aquamarine - 7.5-8 (beryl) * iron - 4-5
|
||||
* garnet - 7.25 (var. 6.5-8) * fluorite - 4
|
||||
* agate - 7 (quartz) * brass - 3-4
|
||||
* amethyst - 7 (quartz) * gold - 2.5-3
|
||||
* jasper - 7 (quartz) * silver - 2.5-3
|
||||
* onyx - 7 (quartz) * copper - 2.5-3
|
||||
* moonstone - 6 (orthoclase) * amber - 2-2.5
|
||||
*/
|
||||
|
||||
/* return 1 if action took 1 (or more) moves, 0 if error or aborted */
|
||||
@@ -1201,6 +1202,23 @@ int fd;
|
||||
}
|
||||
}
|
||||
|
||||
/* to support '#stats' wizard-mode command */
|
||||
void
|
||||
engr_stats(hdrfmt, hdrbuf, count, size)
|
||||
const char *hdrfmt;
|
||||
char *hdrbuf;
|
||||
long *count, *size;
|
||||
{
|
||||
struct engr *ep;
|
||||
|
||||
Sprintf(hdrbuf, hdrfmt, (long) sizeof (struct engr));
|
||||
*count = *size = 0L;
|
||||
for (ep = head_engr; ep; ep = ep->nxt_engr) {
|
||||
++*count;
|
||||
*size += (long) sizeof *ep + (long) ep->engr_lth;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
del_engr(ep)
|
||||
register struct engr *ep;
|
||||
|
||||
+27
-8
@@ -40,8 +40,7 @@ int expltype;
|
||||
int idamres, idamnonres;
|
||||
struct monst *mtmp, *mdef = 0;
|
||||
uchar adtyp;
|
||||
int explmask[3][3];
|
||||
/* 0=normal explosion, 1=do shieldeff, 2=do nothing */
|
||||
int explmask[3][3]; /* 0=normal explosion, 1=do shieldeff, 2=do nothing */
|
||||
boolean shopdamage = FALSE, generic = FALSE, physical_dmg = FALSE,
|
||||
do_hallu = FALSE, inside_engulfer;
|
||||
char hallu_buf[BUFSZ];
|
||||
@@ -414,9 +413,23 @@ int expltype;
|
||||
mtmp->mhp -= (idamres + idamnonres);
|
||||
}
|
||||
if (mtmp->mhp <= 0) {
|
||||
if (mdef ? (mtmp == mdef) : !context.mon_moving)
|
||||
if (!context.mon_moving) {
|
||||
killed(mtmp);
|
||||
else
|
||||
} else if (mdef && mtmp == mdef) {
|
||||
/* 'mdef' killed self trying to cure being turned
|
||||
* into slime due to some action by the player.
|
||||
* Hero gets the credit (experience) and most of
|
||||
* the blame (possible loss of alignment and/or
|
||||
* luck and/or telepathy depending on mtmp) but
|
||||
* doesn't break pacifism. xkilled()'s message
|
||||
* would be "you killed <mdef>" so give our own.
|
||||
*/
|
||||
if (cansee(mtmp->mx, mtmp->my) || canspotmon(mtmp))
|
||||
pline("%s is %s!", Monnam(mtmp),
|
||||
nonliving(mtmp->data) ? "destroyed"
|
||||
: "killed");
|
||||
xkilled(mtmp, XKILL_NOMSG | XKILL_NOCONDUCT);
|
||||
} else
|
||||
monkilled(mtmp, "", (int) adtyp);
|
||||
} else if (!context.mon_moving) {
|
||||
/* all affected monsters, even if mdef is set */
|
||||
@@ -576,7 +589,10 @@ struct obj *obj; /* only scatter this obj */
|
||||
&& ((otmp->otyp == BOULDER) || (otmp->otyp == STATUE))
|
||||
&& rn2(10)) {
|
||||
if (otmp->otyp == BOULDER) {
|
||||
pline("%s apart.", Tobjnam(otmp, "break"));
|
||||
if (cansee(sx, sy))
|
||||
pline("%s apart.", Tobjnam(otmp, "break"));
|
||||
else
|
||||
You_hear("stone breaking.");
|
||||
fracture_rock(otmp);
|
||||
place_object(otmp, sx, sy);
|
||||
if ((otmp = sobj_at(BOULDER, sx, sy)) != 0) {
|
||||
@@ -589,7 +605,10 @@ struct obj *obj; /* only scatter this obj */
|
||||
|
||||
if ((trap = t_at(sx, sy)) && trap->ttyp == STATUE_TRAP)
|
||||
deltrap(trap);
|
||||
pline("%s.", Tobjnam(otmp, "crumble"));
|
||||
if (cansee(sx, sy))
|
||||
pline("%s.", Tobjnam(otmp, "crumble"));
|
||||
else
|
||||
You_hear("stone crumbling.");
|
||||
(void) break_statue(otmp);
|
||||
place_object(otmp, sx, sy); /* put fragments on floor */
|
||||
}
|
||||
@@ -604,8 +623,8 @@ struct obj *obj; /* only scatter this obj */
|
||||
}
|
||||
|
||||
if (!used_up) {
|
||||
stmp =
|
||||
(struct scatter_chain *) alloc(sizeof(struct scatter_chain));
|
||||
stmp = (struct scatter_chain *)
|
||||
alloc(sizeof (struct scatter_chain));
|
||||
stmp->next = (struct scatter_chain *) 0;
|
||||
stmp->obj = otmp;
|
||||
stmp->ox = sx;
|
||||
|
||||
+8
-9
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 files.c $NHDT-Date: 1455835581 2016/02/18 22:46:21 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.204 $ */
|
||||
/* NetHack 3.6 files.c $NHDT-Date: 1459987580 2016/04/07 00:06:20 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.205 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -2820,14 +2820,13 @@ int which_set;
|
||||
mungspaces(buf);
|
||||
if (!*buf || *buf == '#' || !strcmp(buf, " "))
|
||||
return 1;
|
||||
/* remove trailing comment, if any */
|
||||
if ((commentp = rindex(buf, '#')) != 0) {
|
||||
*commentp = '\0';
|
||||
/* remove space preceding the stripped comment, if any;
|
||||
we know 'commentp > buf' because *buf=='#' was caught above */
|
||||
if (commentp[-1] == ' ')
|
||||
*--commentp = '\0';
|
||||
}
|
||||
/* remove trailing comment, if any (this isn't strictly needed for
|
||||
individual symbols, and it won't matter if "X#comment" without
|
||||
separating space slips through; for handling or set description,
|
||||
symbol set creator is responsible for preceding '#' with a space
|
||||
and that comment itself doesn't contain " #") */
|
||||
if ((commentp = rindex(buf, '#')) != 0 && commentp[-1] == ' ')
|
||||
commentp[-1] = '\0';
|
||||
|
||||
/* find the '=' or ':' */
|
||||
bufp = index(buf, '=');
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/* NetHack 3.6 fountain.c $NHDT-Date: 1455402364 2016/02/13 22:26:04 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.56 $ */
|
||||
/* Copyright Scott R. Turner, srt@ucla, 10/27/86 */
|
||||
/* Copyright Scott R. Turner, srt@ucla, 10/27/86 */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
/* Code for drinking from fountains. */
|
||||
@@ -481,7 +481,7 @@ register struct obj *obj;
|
||||
case 29: /* You see coins */
|
||||
/* We make fountains have more coins the closer you are to the
|
||||
* surface. After all, there will have been more people going
|
||||
* by. Just like a shopping mall! Chris Woodbury */
|
||||
* by. Just like a shopping mall! Chris Woodbury */
|
||||
|
||||
if (FOUNTAIN_IS_LOOTED(u.ux, u.uy))
|
||||
break;
|
||||
|
||||
+81
-74
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 hack.c $NHDT-Date: 1446604111 2015/11/04 02:28:31 $ $NHDT-Branch: master $:$NHDT-Revision: 1.155 $ */
|
||||
/* NetHack 3.6 hack.c $NHDT-Date: 1462663937 2016/05/07 23:32:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.165 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -149,9 +149,9 @@ moverock()
|
||||
|| (ttmp->ttyp == SPIKED_PIT))))) {
|
||||
if (Blind)
|
||||
feel_location(sx, sy);
|
||||
if (canspotmon(mtmp))
|
||||
if (canspotmon(mtmp)) {
|
||||
pline("There's %s on the other side.", a_monnam(mtmp));
|
||||
else {
|
||||
} else {
|
||||
You_hear("a monster behind %s.", the(xname(otmp)));
|
||||
map_invisible(rx, ry);
|
||||
}
|
||||
@@ -356,7 +356,7 @@ xchar x, y;
|
||||
|
||||
if (context.digging.down) /* not continuing previous dig (w/ pick-axe) */
|
||||
(void) memset((genericptr_t) &context.digging, 0,
|
||||
sizeof(struct dig_info));
|
||||
sizeof (struct dig_info));
|
||||
|
||||
if (!boulder && IS_ROCK(lev->typ) && !may_dig(x, y)) {
|
||||
You("hurt your teeth on the %s.",
|
||||
@@ -388,7 +388,7 @@ xchar x, y;
|
||||
? "tree"
|
||||
: IS_ROCK(lev->typ)
|
||||
? "rock"
|
||||
: lev->typ == IRONBARS
|
||||
: (lev->typ == IRONBARS)
|
||||
? "bar"
|
||||
: "door");
|
||||
watch_dig((struct monst *) 0, x, y, FALSE);
|
||||
@@ -431,7 +431,7 @@ xchar x, y;
|
||||
block_point(x, y); /* delobj will unblock the point */
|
||||
/* reset dig state */
|
||||
(void) memset((genericptr_t) &context.digging, 0,
|
||||
sizeof(struct dig_info));
|
||||
sizeof (struct dig_info));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -490,7 +490,7 @@ xchar x, y;
|
||||
if (dmgtxt)
|
||||
pay_for_damage(dmgtxt, FALSE);
|
||||
(void) memset((genericptr_t) &context.digging, 0,
|
||||
sizeof(struct dig_info));
|
||||
sizeof (struct dig_info));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -636,8 +636,8 @@ struct monst *mon;
|
||||
return 1;
|
||||
|
||||
/* lugging too much junk? */
|
||||
amt =
|
||||
(mon == &youmonst) ? inv_weight() + weight_cap() : curr_mon_load(mon);
|
||||
amt = (mon == &youmonst) ? inv_weight() + weight_cap()
|
||||
: curr_mon_load(mon);
|
||||
if (amt > 600)
|
||||
return 2;
|
||||
|
||||
@@ -717,9 +717,9 @@ int mode;
|
||||
if (closed_door(x, y)) {
|
||||
if (Blind && mode == DO_MOVE)
|
||||
feel_location(x, y);
|
||||
if (Passes_walls)
|
||||
if (Passes_walls) {
|
||||
; /* do nothing */
|
||||
else if (can_ooze(&youmonst)) {
|
||||
} else if (can_ooze(&youmonst)) {
|
||||
if (mode == DO_MOVE)
|
||||
You("ooze under the door.");
|
||||
} else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
|
||||
@@ -802,7 +802,8 @@ int mode;
|
||||
return (mode == TEST_TRAP);
|
||||
}
|
||||
|
||||
if (mode == TEST_TRAP) return FALSE; /* do not move through traps */
|
||||
if (mode == TEST_TRAP)
|
||||
return FALSE; /* do not move through traps */
|
||||
|
||||
ust = &levl[ux][uy];
|
||||
|
||||
@@ -829,7 +830,8 @@ int mode;
|
||||
struct obj *obj;
|
||||
|
||||
/* never travel through boulders in Sokoban */
|
||||
if (Sokoban) return FALSE;
|
||||
if (Sokoban)
|
||||
return FALSE;
|
||||
|
||||
/* don't pick two boulders in a row, unless there's a way thru */
|
||||
if (sobj_at(BOULDER, ux, uy) && !Sokoban) {
|
||||
@@ -1273,13 +1275,14 @@ domove()
|
||||
on_ice = !Levitation && is_ice(u.ux, u.uy);
|
||||
if (on_ice) {
|
||||
static int skates = 0;
|
||||
|
||||
if (!skates)
|
||||
skates = find_skates();
|
||||
if ((uarmf && uarmf->otyp == skates) || resists_cold(&youmonst)
|
||||
|| Flying || is_floater(youmonst.data)
|
||||
|| is_clinger(youmonst.data) || is_whirly(youmonst.data))
|
||||
|| is_clinger(youmonst.data) || is_whirly(youmonst.data)) {
|
||||
on_ice = FALSE;
|
||||
else if (!rn2(Cold_resistance ? 3 : 2)) {
|
||||
} else if (!rn2(Cold_resistance ? 3 : 2)) {
|
||||
HFumbling |= FROMOUTSIDE;
|
||||
HFumbling &= ~TIMEOUT;
|
||||
HFumbling += 1; /* slip on next move */
|
||||
@@ -1401,7 +1404,8 @@ domove()
|
||||
/* don't stop travel when displacing pets; if the
|
||||
displace fails for some reason, attack() in uhitm.c
|
||||
will stop travel rather than domove */
|
||||
if (!is_safepet(mtmp) || context.forcefight) nomul(0);
|
||||
if (!is_safepet(mtmp) || context.forcefight)
|
||||
nomul(0);
|
||||
/* only attack if we know it's there */
|
||||
/* or if we used the 'F' command to fight blindly */
|
||||
/* or if it hides_under, in which case we call attack() to print
|
||||
@@ -1440,6 +1444,7 @@ domove()
|
||||
|
||||
if (context.forcefight && levl[x][y].typ == IRONBARS && uwep) {
|
||||
struct obj *obj = uwep;
|
||||
|
||||
if (breaktest(obj)) {
|
||||
if (obj->quan > 1L)
|
||||
obj = splitobj(obj, 1L);
|
||||
@@ -1687,8 +1692,8 @@ domove()
|
||||
nomul(0);
|
||||
}
|
||||
|
||||
if (hides_under(youmonst.data) || (youmonst.data->mlet == S_EEL) || u.dx
|
||||
|| u.dy)
|
||||
if (hides_under(youmonst.data) || youmonst.data->mlet == S_EEL
|
||||
|| u.dx || u.dy)
|
||||
(void) hideunder(&youmonst);
|
||||
|
||||
/*
|
||||
@@ -1824,8 +1829,7 @@ switch_terrain()
|
||||
}
|
||||
|
||||
/* extracted from spoteffects; called by spoteffects to check for entering or
|
||||
leaving a pool of water/lava, and by moveloop to check for staying on one
|
||||
|
||||
leaving a pool of water/lava, and by moveloop to check for staying on one;
|
||||
returns true to skip rest of spoteffects */
|
||||
boolean
|
||||
pooleffects(newspot)
|
||||
@@ -1911,8 +1915,9 @@ boolean pick;
|
||||
static int spotterrain;
|
||||
static struct trap *spottrap = (struct trap *) 0;
|
||||
static unsigned spottraptyp = NO_TRAP;
|
||||
|
||||
struct monst *mtmp;
|
||||
struct trap *trap = t_at(u.ux, u.uy);
|
||||
register struct monst *mtmp;
|
||||
|
||||
/* prevent recursion from affecting the hero all over again
|
||||
[hero poly'd to iron golem enters water here, drown() inflicts
|
||||
@@ -1945,8 +1950,8 @@ boolean pick;
|
||||
turn, allowing it to do so could give the perception
|
||||
that a trap here is being triggered twice, so adjust
|
||||
the timeout to prevent that */
|
||||
if (trap && (HLevitation & TIMEOUT) == 1L && !ELevitation
|
||||
&& !(HLevitation & ~TIMEOUT)) {
|
||||
if (trap && (HLevitation & TIMEOUT) == 1L
|
||||
&& !(ELevitation || (HLevitation & ~(I_SPECIAL | TIMEOUT)))) {
|
||||
if (rn2(2)) { /* defer timeout */
|
||||
incr_itimeout(&HLevitation, 1L);
|
||||
} else { /* timeout early */
|
||||
@@ -1959,22 +1964,22 @@ boolean pick;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If not a pit, pickup before triggering trap.
|
||||
* If pit, trigger trap before pickup.
|
||||
*/
|
||||
* If not a pit, pickup before triggering trap.
|
||||
* If pit, trigger trap before pickup.
|
||||
*/
|
||||
pit = (trap && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT));
|
||||
if (pick && !pit)
|
||||
(void) pickup(1);
|
||||
|
||||
if (trap) {
|
||||
/*
|
||||
* dotrap on a fire trap calls melt_ice() which triggers
|
||||
* spoteffects() (again) which can trigger the same fire
|
||||
* trap (again). Use static spottrap to prevent that.
|
||||
* We track spottraptyp because some traps morph
|
||||
* (landmine to pit) and any new trap type
|
||||
* should get triggered.
|
||||
*/
|
||||
* dotrap on a fire trap calls melt_ice() which triggers
|
||||
* spoteffects() (again) which can trigger the same fire
|
||||
* trap (again). Use static spottrap to prevent that.
|
||||
* We track spottraptyp because some traps morph
|
||||
* (landmine to pit) and any new trap type
|
||||
* should get triggered.
|
||||
*/
|
||||
if (!spottrap || spottraptyp != trap->ttyp) {
|
||||
spottrap = trap;
|
||||
spottraptyp = trap->ttyp;
|
||||
@@ -1994,10 +1999,11 @@ boolean pick;
|
||||
"The ice, is gonna BREAK!", /* The Dead Zone */
|
||||
};
|
||||
long time_left = spot_time_left(u.ux, u.uy, MELT_ICE_AWAY);
|
||||
|
||||
if (time_left && time_left < 15L)
|
||||
pline1((time_left < 5L) ? icewarnings[2] : (time_left < 10L)
|
||||
? icewarnings[1]
|
||||
: icewarnings[0]);
|
||||
pline("%s", icewarnings[(time_left < 5L) ? 2
|
||||
: (time_left < 10L) ? 1
|
||||
: 0]);
|
||||
}
|
||||
if ((mtmp = m_at(u.ux, u.uy)) && !u.uswallow) {
|
||||
mtmp->mundetected = mtmp->msleeping = 0;
|
||||
@@ -2005,16 +2011,17 @@ boolean pick;
|
||||
case S_PIERCER:
|
||||
pline("%s suddenly drops from the %s!", Amonnam(mtmp),
|
||||
ceiling(u.ux, u.uy));
|
||||
if (mtmp->mtame) /* jumps to greet you, not attack */
|
||||
if (mtmp->mtame) { /* jumps to greet you, not attack */
|
||||
;
|
||||
else if (uarmh && is_metallic(uarmh))
|
||||
} else if (uarmh && is_metallic(uarmh)) {
|
||||
pline("Its blow glances off your %s.",
|
||||
helm_simple_name(uarmh));
|
||||
else if (u.uac + 3 <= rnd(20))
|
||||
} else if (u.uac + 3 <= rnd(20)) {
|
||||
You("are almost hit by %s!",
|
||||
x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
|
||||
else {
|
||||
} else {
|
||||
int dmg;
|
||||
|
||||
You("are hit by %s!",
|
||||
x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
|
||||
dmg = d(4, 6);
|
||||
@@ -2073,10 +2080,10 @@ register int typewanted;
|
||||
int typefound, min_x, min_y, max_x, max_y_offset, step;
|
||||
register struct rm *lev;
|
||||
|
||||
#define goodtype(rno) \
|
||||
#define goodtype(rno) \
|
||||
(!typewanted \
|
||||
|| ((typefound = rooms[rno - ROOMOFFSET].rtype) == typewanted) \
|
||||
|| ((typewanted == SHOPBASE) && (typefound > SHOPBASE)))
|
||||
|| (typefound = rooms[rno - ROOMOFFSET].rtype) == typewanted \
|
||||
|| (typewanted == SHOPBASE && typefound > SHOPBASE))
|
||||
|
||||
switch (rno = levl[x][y].roomno) {
|
||||
case NO_ROOM:
|
||||
@@ -2111,19 +2118,19 @@ register int typewanted;
|
||||
for (x = min_x; x <= max_x; x += step) {
|
||||
lev = &levl[x][min_y];
|
||||
y = 0;
|
||||
if (((rno = lev[y].roomno) >= ROOMOFFSET) && !index(ptr, rno)
|
||||
if ((rno = lev[y].roomno) >= ROOMOFFSET && !index(ptr, rno)
|
||||
&& goodtype(rno))
|
||||
*(--ptr) = rno;
|
||||
y += step;
|
||||
if (y > max_y_offset)
|
||||
continue;
|
||||
if (((rno = lev[y].roomno) >= ROOMOFFSET) && !index(ptr, rno)
|
||||
if ((rno = lev[y].roomno) >= ROOMOFFSET && !index(ptr, rno)
|
||||
&& goodtype(rno))
|
||||
*(--ptr) = rno;
|
||||
y += step;
|
||||
if (y > max_y_offset)
|
||||
continue;
|
||||
if (((rno = lev[y].roomno) >= ROOMOFFSET) && !index(ptr, rno)
|
||||
if ((rno = lev[y].roomno) >= ROOMOFFSET && !index(ptr, rno)
|
||||
&& goodtype(rno))
|
||||
*(--ptr) = rno;
|
||||
}
|
||||
@@ -2176,7 +2183,7 @@ register boolean newlev;
|
||||
Strcpy(u.urooms, in_rooms(u.ux, u.uy, 0));
|
||||
|
||||
for (ptr1 = &u.urooms[0], ptr2 = &u.uentered[0], ptr3 = &u.ushops[0],
|
||||
ptr4 = &u.ushops_entered[0];
|
||||
ptr4 = &u.ushops_entered[0];
|
||||
*ptr1; ptr1++) {
|
||||
if (!index(u.urooms0, *ptr1))
|
||||
*(ptr2++) = *ptr1;
|
||||
@@ -2197,6 +2204,7 @@ register boolean newlev;
|
||||
*ptr2 = '\0';
|
||||
}
|
||||
|
||||
/* possibly deliver a one-time room entry message */
|
||||
void
|
||||
check_special_room(newlev)
|
||||
register boolean newlev;
|
||||
@@ -2327,11 +2335,13 @@ register boolean newlev;
|
||||
return;
|
||||
}
|
||||
|
||||
/* the ',' command */
|
||||
int
|
||||
dopickup()
|
||||
{
|
||||
int count;
|
||||
int count, tmpcount;
|
||||
struct trap *traphere = t_at(u.ux, u.uy);
|
||||
|
||||
/* awful kludge to work around parse()'s pre-decrement */
|
||||
count = (multi || (save_cm && *save_cm == ',')) ? multi + 1 : 0;
|
||||
multi = 0; /* always reset */
|
||||
@@ -2346,7 +2356,7 @@ dopickup()
|
||||
Blind ? "feel" : "see");
|
||||
return 1;
|
||||
} else {
|
||||
int tmpcount = -count;
|
||||
tmpcount = -count;
|
||||
return loot_mon(u.ustuck, &tmpcount, (boolean *) 0);
|
||||
}
|
||||
}
|
||||
@@ -2372,6 +2382,7 @@ dopickup()
|
||||
}
|
||||
if (!OBJ_AT(u.ux, u.uy)) {
|
||||
register struct rm *lev = &levl[u.ux][u.uy];
|
||||
|
||||
if (IS_THRONE(lev->typ))
|
||||
pline("It must weigh%s a ton!", lev->looted ? " almost" : "");
|
||||
else if (IS_SINK(lev->typ))
|
||||
@@ -2407,10 +2418,11 @@ dopickup()
|
||||
void
|
||||
lookaround()
|
||||
{
|
||||
register int x, y, i, x0 = 0, y0 = 0, m0 = 1, i0 = 9;
|
||||
register int corrct = 0, noturn = 0;
|
||||
register struct monst *mtmp;
|
||||
register struct trap *trap;
|
||||
register int x, y;
|
||||
int i, x0 = 0, y0 = 0, m0 = 1, i0 = 9;
|
||||
int corrct = 0, noturn = 0;
|
||||
struct monst *mtmp;
|
||||
struct trap *trap;
|
||||
|
||||
/* Grid bugs stop if trying to move diagonal, even if blind. Maybe */
|
||||
/* they polymorphed while in the middle of a long move. */
|
||||
@@ -2423,20 +2435,18 @@ lookaround()
|
||||
return;
|
||||
for (x = u.ux - 1; x <= u.ux + 1; x++)
|
||||
for (y = u.uy - 1; y <= u.uy + 1; y++) {
|
||||
if (!isok(x, y))
|
||||
if (!isok(x, y) || (x == u.ux && y == u.uy))
|
||||
continue;
|
||||
if (NODIAG(u.umonnum) && x != u.ux && y != u.uy)
|
||||
continue;
|
||||
|
||||
if (u.umonnum == PM_GRID_BUG && x != u.ux && y != u.uy)
|
||||
continue;
|
||||
|
||||
if (x == u.ux && y == u.uy)
|
||||
continue;
|
||||
|
||||
if ((mtmp = m_at(x, y)) && mtmp->m_ap_type != M_AP_FURNITURE
|
||||
if ((mtmp = m_at(x, y)) != 0
|
||||
&& mtmp->m_ap_type != M_AP_FURNITURE
|
||||
&& mtmp->m_ap_type != M_AP_OBJECT
|
||||
&& (!mtmp->minvis || See_invisible) && !mtmp->mundetected) {
|
||||
if ((context.run != 1 && !mtmp->mtame)
|
||||
|| (x == u.ux + u.dx && y == u.uy + u.dy && !context.travel))
|
||||
|| (x == u.ux + u.dx && y == u.uy + u.dy
|
||||
&& !context.travel))
|
||||
goto stop;
|
||||
}
|
||||
|
||||
@@ -2445,11 +2455,10 @@ lookaround()
|
||||
if (x == u.ux - u.dx && y == u.uy - u.dy)
|
||||
continue;
|
||||
|
||||
if (IS_ROCK(levl[x][y].typ) || (levl[x][y].typ == ROOM)
|
||||
|| IS_AIR(levl[x][y].typ))
|
||||
if (IS_ROCK(levl[x][y].typ) || levl[x][y].typ == ROOM
|
||||
|| IS_AIR(levl[x][y].typ)) {
|
||||
continue;
|
||||
else if (closed_door(x, y)
|
||||
|| (mtmp && is_door_mappear(mtmp))) {
|
||||
} else if (closed_door(x, y) || (mtmp && is_door_mappear(mtmp))) {
|
||||
if (x != u.ux && y != u.uy)
|
||||
continue;
|
||||
if (context.run != 1)
|
||||
@@ -2594,9 +2603,7 @@ monster_nearby()
|
||||
/* Also see the similar check in dochugw() in monmove.c */
|
||||
for (x = u.ux - 1; x <= u.ux + 1; x++)
|
||||
for (y = u.uy - 1; y <= u.uy + 1; y++) {
|
||||
if (!isok(x, y))
|
||||
continue;
|
||||
if (x == u.ux && y == u.uy)
|
||||
if (!isok(x, y) || (x == u.ux && y == u.uy))
|
||||
continue;
|
||||
if ((mtmp = m_at(x, y)) && mtmp->m_ap_type != M_AP_FURNITURE
|
||||
&& mtmp->m_ap_type != M_AP_OBJECT
|
||||
@@ -2668,8 +2675,8 @@ maybe_wail()
|
||||
if (u.uprops[powers[i]].intrinsic & INTRINSIC)
|
||||
++powercnt;
|
||||
|
||||
pline(powercnt >= 4 ? "%s, all your powers will be lost..."
|
||||
: "%s, your life force is running out.",
|
||||
pline((powercnt >= 4) ? "%s, all your powers will be lost..."
|
||||
: "%s, your life force is running out.",
|
||||
who);
|
||||
}
|
||||
} else {
|
||||
@@ -2732,9 +2739,9 @@ weight_cap()
|
||||
}
|
||||
|
||||
if (Levitation || Is_airlevel(&u.uz) /* pugh@cornell */
|
||||
|| (u.usteed && strongmonst(u.usteed->data)))
|
||||
|| (u.usteed && strongmonst(u.usteed->data))) {
|
||||
carrcap = MAX_CARR_CAP;
|
||||
else {
|
||||
} else {
|
||||
if (carrcap > MAX_CARR_CAP)
|
||||
carrcap = MAX_CARR_CAP;
|
||||
if (!Flying) {
|
||||
@@ -2832,7 +2839,7 @@ boolean incl_gold;
|
||||
}
|
||||
|
||||
/* Counts the money in an object chain. */
|
||||
/* Intended use is for your or some monsters inventory, */
|
||||
/* Intended use is for your or some monster's inventory, */
|
||||
/* now that u.gold/m.gold is gone.*/
|
||||
/* Counting money in a container might be possible too. */
|
||||
long
|
||||
|
||||
+282
-141
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 invent.c $NHDT-Date: 1457207035 2016/03/05 19:43:55 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.197 $ */
|
||||
/* NetHack 3.6 invent.c $NHDT-Date: 1461967848 2016/04/29 22:10:48 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.208 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -8,14 +8,14 @@
|
||||
#define CONTAINED_SYM '>' /* designator for inside a container */
|
||||
#define HANDS_SYM '-'
|
||||
|
||||
STATIC_DCL int FDECL(CFDECLSPEC sortloot_cmp, (struct obj *, struct obj *));
|
||||
STATIC_DCL int FDECL(CFDECLSPEC sortloot_cmp, (const genericptr,
|
||||
const genericptr));
|
||||
STATIC_DCL void NDECL(reorder_invent);
|
||||
STATIC_DCL void FDECL(noarmor, (BOOLEAN_P));
|
||||
STATIC_DCL void FDECL(invdisp_nothing, (const char *, const char *));
|
||||
STATIC_DCL boolean FDECL(worn_wield_only, (struct obj *));
|
||||
STATIC_DCL boolean FDECL(only_here, (struct obj *));
|
||||
STATIC_DCL void FDECL(compactify, (char *));
|
||||
STATIC_DCL boolean FDECL(splittable, (struct obj *));
|
||||
STATIC_DCL boolean FDECL(taking_off, (const char *));
|
||||
STATIC_DCL boolean FDECL(putting_on, (const char *));
|
||||
STATIC_PTR int FDECL(ckunpaid, (struct obj *));
|
||||
@@ -25,8 +25,8 @@ STATIC_PTR char *FDECL(safeq_shortxprname, (struct obj *));
|
||||
STATIC_DCL char FDECL(display_pickinv, (const char *, const char *,
|
||||
BOOLEAN_P, long *));
|
||||
STATIC_DCL char FDECL(display_used_invlets, (CHAR_P));
|
||||
STATIC_DCL void FDECL(tally_BUCX,
|
||||
(struct obj *, int *, int *, int *, int *, int *));
|
||||
STATIC_DCL void FDECL(tally_BUCX, (struct obj *,
|
||||
int *, int *, int *, int *, int *));
|
||||
STATIC_DCL boolean FDECL(this_type_only, (struct obj *));
|
||||
STATIC_DCL void NDECL(dounpaid);
|
||||
STATIC_DCL struct obj *FDECL(find_unpaid, (struct obj *, struct obj **));
|
||||
@@ -47,96 +47,214 @@ static int lastinvnr = 51; /* 0 ... 51 (never saved&restored) */
|
||||
*/
|
||||
static char venom_inv[] = { VENOM_CLASS, 0 }; /* (constant) */
|
||||
|
||||
struct sortloot_item {
|
||||
struct obj *obj;
|
||||
int indx;
|
||||
};
|
||||
unsigned sortlootmode = 0;
|
||||
|
||||
/* qsort comparison routine for sortloot() */
|
||||
STATIC_OVL int CFDECLSPEC
|
||||
sortloot_cmp(obj1, obj2)
|
||||
struct obj *obj1;
|
||||
struct obj *obj2;
|
||||
sortloot_cmp(vptr1, vptr2)
|
||||
const genericptr vptr1;
|
||||
const genericptr vptr2;
|
||||
{
|
||||
int val1 = 0;
|
||||
int val2 = 0;
|
||||
struct sortloot_item *sli1 = (struct sortloot_item *) vptr1,
|
||||
*sli2 = (struct sortloot_item *) vptr2;
|
||||
struct obj *obj1 = sli1->obj,
|
||||
*obj2 = sli2->obj,
|
||||
sav1, sav2;
|
||||
char *cls1, *cls2, nam1[BUFSZ], nam2[BUFSZ];
|
||||
int val1, val2, c, namcmp;
|
||||
|
||||
/* Sort object names in lexicographical order, ignoring quantity. */
|
||||
int name_cmp = strcmpi(cxname_singular(obj1), cxname_singular(obj2));
|
||||
/* order by object class like inventory display */
|
||||
if ((sortlootmode & SORTLOOT_PACK) != 0) {
|
||||
cls1 = index(flags.inv_order, obj1->oclass);
|
||||
cls2 = index(flags.inv_order, obj2->oclass);
|
||||
if (cls1 != cls2)
|
||||
return (int) (cls1 - cls2);
|
||||
|
||||
if (name_cmp != 0) {
|
||||
return name_cmp;
|
||||
if ((sortlootmode & SORTLOOT_INVLET) != 0) {
|
||||
; /* skip sub-classes when sorting by packorder+invlet */
|
||||
|
||||
/* for armor, group by sub-category */
|
||||
} else if (obj1->oclass == ARMOR_CLASS) {
|
||||
static int armcat[7 + 1];
|
||||
|
||||
if (!armcat[7]) {
|
||||
/* one-time init; we want to control the order */
|
||||
armcat[ARM_HELM] = 1; /* [2] */
|
||||
armcat[ARM_GLOVES] = 2; /* [3] */
|
||||
armcat[ARM_BOOTS] = 3; /* [4] */
|
||||
armcat[ARM_SHIELD] = 4; /* [1] */
|
||||
armcat[ARM_CLOAK] = 5; /* [5] */
|
||||
armcat[ARM_SHIRT] = 6; /* [6] */
|
||||
armcat[ARM_SUIT] = 7; /* [0] */
|
||||
armcat[7] = 8;
|
||||
}
|
||||
val1 = armcat[objects[obj1->otyp].oc_armcat];
|
||||
val2 = armcat[objects[obj2->otyp].oc_armcat];
|
||||
if (val1 != val2)
|
||||
return val1 - val2;
|
||||
|
||||
/* for weapons, group by ammo (arrows, bolts), launcher (bows),
|
||||
missile (dart, boomerang), stackable (daggers, knives, spears),
|
||||
'other' (swords, axes, &c), polearm */
|
||||
} else if (obj1->oclass == WEAPON_CLASS) {
|
||||
val1 = objects[obj1->otyp].oc_skill;
|
||||
val1 = (val1 < 0)
|
||||
? (val1 >= -P_CROSSBOW && val1 <= -P_BOW) ? 1 : 3
|
||||
: (val1 >= P_BOW && val1 <= P_CROSSBOW) ? 2
|
||||
: (val1 == P_SPEAR || val1 == P_DAGGER
|
||||
|| val1 == P_KNIFE) ? 4 : !is_pole(obj1) ? 5 : 6;
|
||||
val2 = objects[obj2->otyp].oc_skill;
|
||||
val2 = (val2 < 0)
|
||||
? (val2 >= -P_CROSSBOW && val2 <= -P_BOW) ? 1 : 3
|
||||
: (val2 >= P_BOW && val2 <= P_CROSSBOW) ? 2
|
||||
: (val2 == P_SPEAR || val2 == P_DAGGER
|
||||
|| val2 == P_KNIFE) ? 4 : !is_pole(obj2) ? 5 : 6;
|
||||
if (val1 != val2)
|
||||
return val1 - val2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sort by BUC. Map blessed to 4, uncursed to 2, cursed to 1, and unknown
|
||||
* to 0. */
|
||||
/* order by assigned inventory letter */
|
||||
if ((sortlootmode & SORTLOOT_INVLET) != 0) {
|
||||
c = obj1->invlet;
|
||||
val1 = ('a' <= c && c <= 'z') ? (c - 'a' + 2)
|
||||
: ('A' <= c && c <= 'Z') ? (c - 'A' + 2 + 26)
|
||||
: (c == '$') ? 1
|
||||
: (c == '#') ? 1 + 52 + 1
|
||||
: 1 + 52 + 1 + 1; /* none of the above */
|
||||
c = obj2->invlet;
|
||||
val2 = ('a' <= c && c <= 'z') ? (c - 'a' + 2)
|
||||
: ('A' <= c && c <= 'Z') ? (c - 'A' + 2 + 26)
|
||||
: (c == '$') ? 1
|
||||
: (c == '#') ? 1 + 52 + 1
|
||||
: 1 + 52 + 1 + 1; /* none of the above */
|
||||
if (val1 != val2)
|
||||
return val1 - val2;
|
||||
}
|
||||
|
||||
if ((sortlootmode & SORTLOOT_LOOT) == 0)
|
||||
goto tiebreak;
|
||||
|
||||
/*
|
||||
* Sort object names in lexicographical order, ignoring quantity.
|
||||
*/
|
||||
/* Force diluted potions to come out after undiluted of same type;
|
||||
obj->odiluted overloads obj->oeroded. */
|
||||
sav1.odiluted = obj1->odiluted;
|
||||
sav2.odiluted = obj2->odiluted;
|
||||
if (obj1->oclass == POTION_CLASS)
|
||||
obj1->odiluted = 0;
|
||||
if (obj1->oclass == POTION_CLASS)
|
||||
obj2->odiluted = 0;
|
||||
/* Force holy and unholy water to sort adjacent to water rather
|
||||
than among 'h's and 'u's. BUCX order will keep them distinct. */
|
||||
Strcpy(nam1, cxname_singular(obj1));
|
||||
if (obj1->otyp == POT_WATER && obj1->bknown
|
||||
&& (obj1->blessed || obj1->cursed))
|
||||
(void) strsubst(nam1, obj1->blessed ? "holy " : "unholy ", "");
|
||||
Strcpy(nam2, cxname_singular(obj2));
|
||||
if (obj2->otyp == POT_WATER && obj2->bknown
|
||||
&& (obj2->blessed || obj2->cursed))
|
||||
(void) strsubst(nam2, obj2->blessed ? "holy " : "unholy ", "");
|
||||
obj1->odiluted = sav1.odiluted;
|
||||
obj2->odiluted = sav2.odiluted;
|
||||
|
||||
if ((namcmp = strcmpi(nam1, nam2)) != 0)
|
||||
return namcmp;
|
||||
|
||||
/* Sort by BUCX. Map blessed to 4, uncursed to 2, cursed to 1, and
|
||||
unknown to 0. */
|
||||
val1 = obj1->bknown
|
||||
? (obj1->blessed << 2)
|
||||
+ ((!obj1->blessed && !obj1->cursed) << 1) + obj1->cursed
|
||||
: 0;
|
||||
? (obj1->blessed << 2)
|
||||
+ ((!obj1->blessed && !obj1->cursed) << 1) + obj1->cursed
|
||||
: 0;
|
||||
val2 = obj2->bknown
|
||||
? (obj2->blessed << 2)
|
||||
+ ((!obj2->blessed && !obj2->cursed) << 1) + obj2->cursed
|
||||
: 0;
|
||||
if (val1 != val2) {
|
||||
return val2 - val1; /* Because bigger is better. */
|
||||
}
|
||||
? (obj2->blessed << 2)
|
||||
+ ((!obj2->blessed && !obj2->cursed) << 1) + obj2->cursed
|
||||
: 0;
|
||||
if (val1 != val2)
|
||||
return val2 - val1; /* bigger is better */
|
||||
|
||||
/* Sort by greasing. This will put the objects in degreasing order. */
|
||||
/* Sort by greasing. This will put the objects in degreasing order. */
|
||||
val1 = obj1->greased;
|
||||
val2 = obj2->greased;
|
||||
if (val1 != val2) {
|
||||
return val2 - val1; /* Because bigger is better. */
|
||||
}
|
||||
if (val1 != val2)
|
||||
return val2 - val1; /* bigger is better */
|
||||
|
||||
/* Sort by erosion. The effective amount is what matters. */
|
||||
/* Sort by erosion. The effective amount is what matters. */
|
||||
val1 = greatest_erosion(obj1);
|
||||
val2 = greatest_erosion(obj2);
|
||||
if (val1 != val2) {
|
||||
return val1 - val2; /* Because bigger is WORSE. */
|
||||
}
|
||||
if (val1 != val2)
|
||||
return val1 - val2; /* bigger is WORSE */
|
||||
|
||||
/* Sort by erodeproofing. Map known-invulnerable to 1, and both
|
||||
* known-vulnerable and unknown-vulnerability to 0, because that's how
|
||||
* they're displayed. */
|
||||
/* Sort by erodeproofing. Map known-invulnerable to 1, and both
|
||||
known-vulnerable and unknown-vulnerability to 0, because that's
|
||||
how they're displayed. */
|
||||
val1 = obj1->rknown && obj1->oerodeproof;
|
||||
val2 = obj2->rknown && obj2->oerodeproof;
|
||||
if (val1 != val2) {
|
||||
return val2 - val1; /* Because bigger is better. */
|
||||
if (val1 != val2)
|
||||
return val2 - val1; /* bigger is better */
|
||||
|
||||
/* Sort by enchantment. Map unknown to -1000, which is comfortably
|
||||
below the range of obj->spe. oc_uses_known means that obj->known
|
||||
matters, which usually indirectly means that obj->spe is relevant.
|
||||
Lots of objects use obj->spe for some other purpose (see obj.h). */
|
||||
if (objects[obj1->otyp].oc_uses_known
|
||||
/* exclude eggs (laid by you) and tins (homemade, pureed, &c) */
|
||||
&& obj1->oclass != FOOD_CLASS) {
|
||||
val1 = obj1->known ? obj1->spe : -1000;
|
||||
val2 = obj2->known ? obj2->spe : -1000;
|
||||
if (val1 != val2)
|
||||
return val2 - val1; /* bigger is better */
|
||||
}
|
||||
|
||||
/* Sort by enchantment. Map unknown to -1000, which is comfortably below
|
||||
* the range of ->spe. */
|
||||
val1 = obj1->known ? obj1->spe : -1000;
|
||||
val2 = obj2->known ? obj2->spe : -1000;
|
||||
if (val1 != val2) {
|
||||
return val2 - val1; /* Because bigger is better. */
|
||||
}
|
||||
|
||||
/* They're identical, as far as we're concerned,
|
||||
but we want to force a determistic order between them. */
|
||||
return (obj1->o_id > obj2->o_id) ? 1 : -1;
|
||||
}
|
||||
|
||||
struct obj **
|
||||
objarr_init(n)
|
||||
int n;
|
||||
{
|
||||
return (struct obj **) alloc(n * sizeof(struct obj *));
|
||||
tiebreak:
|
||||
/* They're identical, as far as we're concerned. We want
|
||||
to force a deterministic order, and do so by producing a
|
||||
stable sort: maintain the original order of equal items. */
|
||||
return (sli2->indx - sli1->indx);
|
||||
}
|
||||
|
||||
void
|
||||
objarr_set(otmp, idx, oarray, dosort)
|
||||
struct obj *otmp;
|
||||
int idx;
|
||||
struct obj **oarray;
|
||||
boolean dosort;
|
||||
sortloot(olist, mode, by_nexthere)
|
||||
struct obj **olist;
|
||||
unsigned mode; /* flags for sortloot_cmp() */
|
||||
boolean by_nexthere; /* T: traverse via obj->nexthere, F: via obj->nobj */
|
||||
{
|
||||
if (dosort) {
|
||||
int j;
|
||||
for (j = idx; j; j--) {
|
||||
if (sortloot_cmp(otmp, oarray[j - 1]) > 0)
|
||||
break;
|
||||
oarray[j] = oarray[j - 1];
|
||||
}
|
||||
oarray[j] = otmp;
|
||||
} else {
|
||||
oarray[idx] = otmp;
|
||||
struct sortloot_item *sliarray, osli, nsli;
|
||||
struct obj *o, **nxt_p;
|
||||
unsigned n, i;
|
||||
boolean already_sorted = TRUE;
|
||||
|
||||
sortlootmode = mode; /* extra input for sortloot_cmp() */
|
||||
for (n = osli.indx = 0, osli.obj = *olist; (o = osli.obj) != 0;
|
||||
osli = nsli) {
|
||||
nsli.obj = by_nexthere ? o->nexthere : o->nobj;
|
||||
nsli.indx = (int) ++n;
|
||||
if (nsli.obj && already_sorted
|
||||
&& sortloot_cmp((genericptr_t) &osli, (genericptr_t) &nsli) > 0)
|
||||
already_sorted = FALSE;
|
||||
}
|
||||
if (n > 1 && !already_sorted) {
|
||||
sliarray = (struct sortloot_item *) alloc(n * sizeof *sliarray);
|
||||
for (i = 0, o = *olist; o;
|
||||
++i, o = by_nexthere ? o->nexthere : o->nobj)
|
||||
sliarray[i].obj = o, sliarray[i].indx = (int) i;
|
||||
|
||||
qsort((genericptr_t) sliarray, n, sizeof *sliarray, sortloot_cmp);
|
||||
for (i = 0; i < n; ++i) {
|
||||
o = sliarray[i].obj;
|
||||
nxt_p = by_nexthere ? &(o->nexthere) : &(o->nobj);
|
||||
*nxt_p = (i < n - 1) ? sliarray[i + 1].obj : (struct obj *) 0;
|
||||
}
|
||||
*olist = sliarray[0].obj;
|
||||
free((genericptr_t) sliarray);
|
||||
}
|
||||
sortlootmode = 0;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -923,7 +1041,7 @@ register char *buf;
|
||||
}
|
||||
|
||||
/* some objects shouldn't be split when count given to getobj or askchain */
|
||||
STATIC_OVL boolean
|
||||
boolean
|
||||
splittable(obj)
|
||||
struct obj *obj;
|
||||
{
|
||||
@@ -966,7 +1084,6 @@ register const char *let, *word;
|
||||
register int foo = 0;
|
||||
register char *bp = buf;
|
||||
xchar allowcnt = 0; /* 0, 1 or 2 */
|
||||
struct obj *firstobj = invent;
|
||||
boolean usegold = FALSE; /* can't use gold because its illegal */
|
||||
boolean allowall = FALSE;
|
||||
boolean allownone = FALSE;
|
||||
@@ -1011,8 +1128,15 @@ register const char *let, *word;
|
||||
|
||||
if (!flags.invlet_constant)
|
||||
reassign();
|
||||
else
|
||||
/* in case invent is in packorder, force it to be in invlet
|
||||
order before collecing candidate inventory letters;
|
||||
if player responds with '?' or '*' it will be changed
|
||||
back by display_pickinv(), but by then we'll have 'lets'
|
||||
and so won't have to re-sort in the for(;;) loop below */
|
||||
sortloot(&invent, SORTLOOT_INVLET, FALSE);
|
||||
|
||||
for (otmp = firstobj; otmp; otmp = otmp->nobj) {
|
||||
for (otmp = invent; otmp; otmp = otmp->nobj) {
|
||||
if (&bp[foo] == &buf[sizeof buf - 1]
|
||||
|| ap == &altlets[sizeof altlets - 1]) {
|
||||
/* we must have a huge number of NOINVSYM items somehow */
|
||||
@@ -1024,8 +1148,8 @@ register const char *let, *word;
|
||||
|| (usegold && otmp->invlet == GOLD_SYM)
|
||||
|| (useboulder && otmp->otyp == BOULDER)) {
|
||||
register int otyp = otmp->otyp;
|
||||
bp[foo++] = otmp->invlet;
|
||||
|
||||
bp[foo++] = otmp->invlet;
|
||||
/* clang-format off */
|
||||
/* *INDENT-OFF* */
|
||||
/* ugly check: remove inappropriate things */
|
||||
@@ -1038,8 +1162,9 @@ register const char *let, *word;
|
||||
|| (!strcmp(word, "wield")
|
||||
&& (otmp->owornmask & W_WEP))
|
||||
#endif
|
||||
|| (!strcmp(word, "ready") /* exclude if wielded */
|
||||
&& (otmp == uwep || (otmp == uswapwep && u.twoweap)))
|
||||
|| (!strcmp(word, "ready") /* exclude when wielded... */
|
||||
&& ((otmp == uwep || (otmp == uswapwep && u.twoweap))
|
||||
&& otmp->quan == 1L)) /* ...unless more than one */
|
||||
|| ((!strcmp(word, "dip") || !strcmp(word, "grease"))
|
||||
&& inaccessible_equipment(otmp, (const char *) 0, FALSE))
|
||||
) {
|
||||
@@ -1134,7 +1259,8 @@ register const char *let, *word;
|
||||
/* worn armor (shirt, suit) covered by worn armor (suit, cloak)
|
||||
or accessory (ring) covered by cursed worn armor (gloves) */
|
||||
|| (taking_off(word)
|
||||
&& inaccessible_equipment(otmp, (const char *) 0, FALSE))
|
||||
&& inaccessible_equipment(otmp, (const char *) 0,
|
||||
(boolean) (otmp->oclass == RING_CLASS)))
|
||||
|| (!strcmp(word, "write on")
|
||||
&& (!(otyp == SCR_BLANK_PAPER || otyp == SPE_BLANK_PAPER)
|
||||
|| !otmp->dknown || !objects[otyp].oc_name_known))
|
||||
@@ -1232,10 +1358,12 @@ register const char *let, *word;
|
||||
else if (!strcmp(word, "write with"))
|
||||
Sprintf(qbuf, "your %s", body_part(FINGERTIP));
|
||||
else if (!strcmp(word, "wield"))
|
||||
Sprintf(qbuf, "your %s %s", uarmg ? "gloved" : "bare",
|
||||
makeplural(body_part(HAND)));
|
||||
Sprintf(qbuf, "your %s %s%s", uarmg ? "gloved" : "bare",
|
||||
makeplural(body_part(HAND)),
|
||||
!uwep ? " (wielded)" : "");
|
||||
else if (!strcmp(word, "ready"))
|
||||
Strcpy(qbuf, "empty quiver");
|
||||
Sprintf(qbuf, "empty quiver%s",
|
||||
!uquiver ? " (nothing readied)" : "");
|
||||
|
||||
if (ilet == '?' && !*lets && *altlets)
|
||||
allowed_choices = altlets;
|
||||
@@ -1426,9 +1554,9 @@ static NEARDATA const char removeables[] = { ARMOR_CLASS, WEAPON_CLASS,
|
||||
RING_CLASS, AMULET_CLASS,
|
||||
TOOL_CLASS, 0 };
|
||||
|
||||
/* interactive version of getobj - used for Drop, Identify and */
|
||||
/* Takeoff (A). Return the number of times fn was called successfully */
|
||||
/* If combo is TRUE, we just use this to get a category list */
|
||||
/* Interactive version of getobj - used for Drop, Identify, and Takeoff (A).
|
||||
Return the number of times fn was called successfully.
|
||||
If combo is TRUE, we just use this to get a category list. */
|
||||
int
|
||||
ggetobj(word, fn, mx, combo, resultflags)
|
||||
const char *word;
|
||||
@@ -1489,13 +1617,23 @@ unsigned *resultflags;
|
||||
ilets[iletct] = '\0';
|
||||
|
||||
for (;;) {
|
||||
Sprintf(qbuf, "What kinds of thing do you want to %s? [%s]", word,
|
||||
ilets);
|
||||
Sprintf(qbuf, "What kinds of thing do you want to %s? [%s]",
|
||||
word, ilets);
|
||||
getlin(qbuf, buf);
|
||||
if (buf[0] == '\033')
|
||||
return 0;
|
||||
if (index(buf, 'i')) {
|
||||
if (display_inventory((char *) 0, TRUE) == '\033')
|
||||
char ailets[1+26+26+1+5+1]; /* $ + a-z + A-Z + # + slop + \0 */
|
||||
struct obj *otmp;
|
||||
|
||||
/* applicable inventory letters; if empty, show entire invent */
|
||||
ailets[0] = '\0';
|
||||
if (ofilter)
|
||||
for (otmp = invent; otmp; otmp = otmp->nobj)
|
||||
/* index() check: limit overflow items to one '#' */
|
||||
if ((*ofilter)(otmp) && !index(ailets, otmp->invlet))
|
||||
(void) strkitten(ailets, otmp->invlet);
|
||||
if (display_inventory(ailets, TRUE) == '\033')
|
||||
return 0;
|
||||
} else
|
||||
break;
|
||||
@@ -1579,7 +1717,9 @@ unsigned *resultflags;
|
||||
}
|
||||
|
||||
if (m_seen) {
|
||||
return (allflag || (!oletct && ckfn != ckunpaid)) ? -2 : -3;
|
||||
return (allflag
|
||||
|| (!oletct && ckfn != ckunpaid && ckfn != ckvalidcat))
|
||||
? -2 : -3;
|
||||
} else if (flags.menu_style != MENU_TRADITIONAL && combo && !allflag) {
|
||||
return 0;
|
||||
#if 0
|
||||
@@ -1605,15 +1745,15 @@ unsigned *resultflags;
|
||||
* Walk through the chain starting at objchn and ask for all objects
|
||||
* with olet in olets (if nonNULL) and satisfying ckfn (if nonnull)
|
||||
* whether the action in question (i.e., fn) has to be performed.
|
||||
* If allflag then no questions are asked. Max gives the max nr of
|
||||
* objects to be treated. Return the number of objects treated.
|
||||
* If allflag then no questions are asked. Mx gives the max number
|
||||
* of objects to be treated. Return the number of objects treated.
|
||||
*/
|
||||
int
|
||||
askchain(objchn, olets, allflag, fn, ckfn, mx, word)
|
||||
struct obj **objchn;
|
||||
register int allflag, mx;
|
||||
register const char *olets, *word; /* olets is an Obj Class char array */
|
||||
register int FDECL((*fn), (OBJ_P)), FDECL((*ckfn), (OBJ_P));
|
||||
int allflag, mx;
|
||||
const char *olets, *word; /* olets is an Obj Class char array */
|
||||
int FDECL((*fn), (OBJ_P)), FDECL((*ckfn), (OBJ_P));
|
||||
{
|
||||
struct obj *otmp, *otmpo;
|
||||
register char sym, ilet;
|
||||
@@ -1628,11 +1768,17 @@ register int FDECL((*fn), (OBJ_P)), FDECL((*ckfn), (OBJ_P));
|
||||
nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") || ident
|
||||
|| takeoff || take_out || put_in);
|
||||
ininv = (*objchn == invent);
|
||||
|
||||
/* someday maybe we'll sort by 'olets' too (temporarily replace
|
||||
flags.packorder and pass SORTLOOT_PACK), but not yet... */
|
||||
sortloot(objchn, SORTLOOT_INVLET, FALSE);
|
||||
|
||||
first = TRUE;
|
||||
/* Changed so the askchain is interrogated in the order specified.
|
||||
* For example, if a person specifies =/ then first all rings will be
|
||||
* asked about followed by all wands -dgk
|
||||
*/
|
||||
/*
|
||||
* Interrogate in the object class order specified.
|
||||
* For example, if a person specifies =/ then first all rings
|
||||
* will be asked about followed by all wands. -dgk
|
||||
*/
|
||||
nextclass:
|
||||
ilet = 'a' - 1;
|
||||
if (*objchn && (*objchn)->oclass == COIN_CLASS)
|
||||
@@ -1675,9 +1821,10 @@ nextclass:
|
||||
Sprintf(qpfx, "%s: ", word), *qpfx = highc(*qpfx);
|
||||
first = FALSE;
|
||||
}
|
||||
(void) safe_qbuf(
|
||||
qbuf, qpfx, "?", otmp, ininv ? safeq_xprname : doname,
|
||||
ininv ? safeq_shortxprname : ansimpleoname, "item");
|
||||
(void) safe_qbuf(qbuf, qpfx, "?", otmp,
|
||||
ininv ? safeq_xprname : doname,
|
||||
ininv ? safeq_shortxprname : ansimpleoname,
|
||||
"item");
|
||||
sym = (takeoff || ident || otmp->quan < 2L) ? nyaq(qbuf)
|
||||
: nyNaq(qbuf);
|
||||
} else
|
||||
@@ -1689,11 +1836,10 @@ nextclass:
|
||||
to 'none' or 'all'. 2 special cases: cursed loadstones and
|
||||
welded weapons (eg, multiple daggers) will remain as merged
|
||||
unit; done to avoid splitting an object that won't be
|
||||
droppable (even if we're picking up rather than dropping).
|
||||
*/
|
||||
if (!yn_number)
|
||||
droppable (even if we're picking up rather than dropping). */
|
||||
if (!yn_number) {
|
||||
sym = 'n';
|
||||
else {
|
||||
} else {
|
||||
sym = 'y';
|
||||
if (yn_number < otmp->quan && splittable(otmp))
|
||||
otmp = splitobj(otmp, yn_number);
|
||||
@@ -1783,8 +1929,8 @@ int id_limit;
|
||||
while (id_limit) {
|
||||
Sprintf(buf, "What would you like to identify %s?",
|
||||
first ? "first" : "next");
|
||||
n = query_objlist(buf, invent, SIGNAL_NOMENU | SIGNAL_ESCAPE
|
||||
| USE_INVLET | INVORDER_SORT,
|
||||
n = query_objlist(buf, &invent, (SIGNAL_NOMENU | SIGNAL_ESCAPE
|
||||
| USE_INVLET | INVORDER_SORT),
|
||||
&pick_list, PICK_ANY, not_fully_identified);
|
||||
|
||||
if (n > 0) {
|
||||
@@ -2021,13 +2167,15 @@ long *out_cnt;
|
||||
struct obj *otmp;
|
||||
char ilet, ret;
|
||||
char *invlet = flags.inv_order;
|
||||
int i, n, classcount;
|
||||
int n, classcount;
|
||||
winid win; /* windows being used */
|
||||
anything any;
|
||||
menu_item *selected;
|
||||
struct obj **oarray;
|
||||
|
||||
if (flags.perm_invent && ((lets && *lets) || xtra_choice)) {
|
||||
if (lets && !*lets)
|
||||
lets = 0; /* simplify tests: (lets) instead of (lets && *lets) */
|
||||
|
||||
if (flags.perm_invent && (lets || xtra_choice)) {
|
||||
/* partial inventory in perm_invent setting; don't operate on
|
||||
full inventory window, use an alternate one instead; create
|
||||
the first time needed and keep it for re-use as needed later */
|
||||
@@ -2096,19 +2244,10 @@ long *out_cnt;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* count the number of items (preliminary count of 0,1,more was 'more'
|
||||
and is now obsolete); we have at least 2 items or want to behave as
|
||||
if we do (full invent and wiz_identify use this even for 1 item) */
|
||||
for (n = 0, otmp = invent; otmp; otmp = otmp->nobj)
|
||||
if (!lets || !*lets || index(lets, otmp->invlet))
|
||||
n++;
|
||||
oarray = objarr_init(n);
|
||||
/* Add objects to the array */
|
||||
i = 0;
|
||||
for (otmp = invent; otmp; otmp = otmp->nobj)
|
||||
if (!lets || !*lets || index(lets, otmp->invlet)) {
|
||||
objarr_set(otmp, i++, oarray, (flags.sortloot == 'f'));
|
||||
}
|
||||
sortloot(&invent,
|
||||
(((flags.sortloot == 'f') ? SORTLOOT_LOOT : SORTLOOT_INVLET)
|
||||
| (flags.sortpack ? SORTLOOT_PACK : 0)),
|
||||
FALSE);
|
||||
|
||||
start_menu(win);
|
||||
any = zeroany;
|
||||
@@ -2133,8 +2272,9 @@ long *out_cnt;
|
||||
}
|
||||
nextclass:
|
||||
classcount = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
otmp = oarray[i];
|
||||
for (otmp = invent; otmp; otmp = otmp->nobj) {
|
||||
if (lets && !index(lets, otmp->invlet))
|
||||
continue;
|
||||
if (!flags.sortpack || otmp->oclass == *invlet) {
|
||||
any = zeroany; /* all bits zero */
|
||||
ilet = otmp->invlet;
|
||||
@@ -2158,7 +2298,6 @@ nextclass:
|
||||
goto nextclass;
|
||||
}
|
||||
}
|
||||
free(oarray);
|
||||
end_menu(win, (char *) 0);
|
||||
|
||||
n = select_menu(win, want_reply ? PICK_ONE : PICK_NONE, &selected);
|
||||
@@ -2627,9 +2766,9 @@ dotypeinv()
|
||||
}
|
||||
this_type = oclass;
|
||||
}
|
||||
if (query_objlist((char *) 0, invent,
|
||||
(flags.invlet_constant ? USE_INVLET : 0)
|
||||
| INVORDER_SORT,
|
||||
if (query_objlist((char *) 0, &invent,
|
||||
((flags.invlet_constant ? USE_INVLET : 0)
|
||||
| INVORDER_SORT),
|
||||
&pick_list, PICK_NONE, this_type_only) > 0)
|
||||
free((genericptr_t) pick_list);
|
||||
return 0;
|
||||
@@ -2751,7 +2890,7 @@ boolean picked_some;
|
||||
if (Blind)
|
||||
Strcpy(fbuf, "You feel");
|
||||
Strcat(fbuf, ":");
|
||||
(void) display_minventory(mtmp, MINV_ALL, fbuf);
|
||||
(void) display_minventory(mtmp, MINV_ALL | PICK_NONE, fbuf);
|
||||
} else {
|
||||
You("%s no objects here.", verb);
|
||||
}
|
||||
@@ -3593,8 +3732,10 @@ struct obj *obj;
|
||||
* By default, only worn and wielded items are displayed. The caller
|
||||
* can pick one. Modifier flags are:
|
||||
*
|
||||
* MINV_NOLET - nothing selectable
|
||||
* MINV_ALL - display all inventory
|
||||
* PICK_NONE, PICK_ONE - standard menu control
|
||||
* PICK_ANY - allowed, but we only return a single object
|
||||
* MINV_NOLET - nothing selectable
|
||||
* MINV_ALL - display all inventory
|
||||
*/
|
||||
struct obj *
|
||||
display_minventory(mon, dflags, title)
|
||||
@@ -3608,7 +3749,8 @@ char *title;
|
||||
menu_item *selected = 0;
|
||||
int do_all = (dflags & MINV_ALL) != 0,
|
||||
incl_hero = (do_all && u.uswallow && mon == u.ustuck),
|
||||
have_inv = (mon->minvent != 0), have_any = (have_inv || incl_hero);
|
||||
have_inv = (mon->minvent != 0), have_any = (have_inv || incl_hero),
|
||||
pickings = (dflags & MINV_PICKMASK);
|
||||
|
||||
Sprintf(tmp, "%s %s:", s_suffix(noit_Monnam(mon)),
|
||||
do_all ? "possessions" : "armament");
|
||||
@@ -3619,12 +3761,10 @@ char *title;
|
||||
*/
|
||||
youmonst.data = mon->data;
|
||||
|
||||
n = query_objlist(title ? title : tmp, mon->minvent,
|
||||
INVORDER_SORT | (incl_hero ? INCLUDE_HERO : 0),
|
||||
&selected,
|
||||
(dflags & MINV_NOLET) ? PICK_NONE : PICK_ONE,
|
||||
n = query_objlist(title ? title : tmp, &(mon->minvent),
|
||||
(INVORDER_SORT | (incl_hero ? INCLUDE_HERO : 0)),
|
||||
&selected, pickings,
|
||||
do_all ? allow_all : worn_wield_only);
|
||||
|
||||
set_uasmon();
|
||||
} else {
|
||||
invdisp_nothing(title ? title : tmp, "(none)");
|
||||
@@ -3656,8 +3796,8 @@ register struct obj *obj;
|
||||
"that");
|
||||
|
||||
if (obj->cobj) {
|
||||
n = query_objlist(qbuf, obj->cobj, INVORDER_SORT, &selected,
|
||||
PICK_NONE, allow_all);
|
||||
n = query_objlist(qbuf, &(obj->cobj), INVORDER_SORT,
|
||||
&selected, PICK_NONE, allow_all);
|
||||
} else {
|
||||
invdisp_nothing(qbuf, "(empty)");
|
||||
n = 0;
|
||||
@@ -3707,8 +3847,9 @@ boolean as_if_seen;
|
||||
if (n) {
|
||||
only.x = x;
|
||||
only.y = y;
|
||||
if (query_objlist("Things that are buried here:", level.buriedobjlist,
|
||||
INVORDER_SORT, &selected, PICK_NONE, only_here) > 0)
|
||||
if (query_objlist("Things that are buried here:",
|
||||
&level.buriedobjlist, INVORDER_SORT,
|
||||
&selected, PICK_NONE, only_here) > 0)
|
||||
free((genericptr_t) selected);
|
||||
only.x = only.y = 0;
|
||||
}
|
||||
|
||||
+17
@@ -306,6 +306,23 @@ int fd;
|
||||
}
|
||||
}
|
||||
|
||||
/* to support '#stats' wizard-mode command */
|
||||
void
|
||||
light_stats(hdrfmt, hdrbuf, count, size)
|
||||
const char *hdrfmt;
|
||||
char *hdrbuf;
|
||||
long *count, *size;
|
||||
{
|
||||
light_source *ls;
|
||||
|
||||
Sprintf(hdrbuf, hdrfmt, (long) sizeof (light_source));
|
||||
*count = *size = 0L;
|
||||
for (ls = light_base; ls; ls = ls->next) {
|
||||
++*count;
|
||||
*size += (long) sizeof *ls;
|
||||
}
|
||||
}
|
||||
|
||||
/* Relink all lights that are so marked. */
|
||||
void
|
||||
relink_light_sources(ghostly)
|
||||
|
||||
+8
-1
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 mail.c $NHDT-Date: 1451955080 2016/01/05 00:51:20 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.25 $ */
|
||||
/* NetHack 3.6 mail.c $NHDT-Date: 1464222344 2016/05/26 00:25:44 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.27 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -80,6 +80,13 @@ static long laststattime;
|
||||
#define MAILPATH "/usr/mail/"
|
||||
#endif
|
||||
|
||||
void
|
||||
free_maildata()
|
||||
{
|
||||
if (mailbox)
|
||||
free((genericptr_t) mailbox), mailbox = (char *) 0;
|
||||
}
|
||||
|
||||
void
|
||||
getmailstatus()
|
||||
{
|
||||
|
||||
+32
-6
@@ -6,8 +6,6 @@
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
STATIC_VAR NEARDATA struct monst zeromonst;
|
||||
|
||||
/* this assumes that a human quest leader or nemesis is an archetype
|
||||
of the corresponding role; that isn't so for some roles (tourist
|
||||
for instance) but is for the priests and monks we use it for... */
|
||||
@@ -23,7 +21,8 @@ STATIC_DCL void FDECL(m_initgrp, (struct monst *, int, int, int));
|
||||
STATIC_DCL void FDECL(m_initthrow, (struct monst *, int, int));
|
||||
STATIC_DCL void FDECL(m_initweap, (struct monst *));
|
||||
STATIC_DCL void FDECL(m_initinv, (struct monst *));
|
||||
STATIC_DCL boolean FDECL(makemon_rnd_goodpos, (struct monst *, unsigned, coord *));
|
||||
STATIC_DCL boolean FDECL(makemon_rnd_goodpos, (struct monst *,
|
||||
unsigned, coord *));
|
||||
|
||||
extern const int monstr[];
|
||||
|
||||
@@ -771,6 +770,7 @@ xchar x, y; /* clone's preferred location or 0 (near mon) */
|
||||
/* Max HP the same, but current HP halved for both. The caller
|
||||
* might want to override this by halving the max HP also.
|
||||
* When current HP is odd, the original keeps the extra point.
|
||||
* We know original has more than 1 HP, so both end up with at least 1.
|
||||
*/
|
||||
m2->mhpmax = mon->mhpmax;
|
||||
m2->mhp = mon->mhp / 2;
|
||||
@@ -1327,6 +1327,11 @@ int
|
||||
mbirth_limit(mndx)
|
||||
int mndx;
|
||||
{
|
||||
/* There is an implicit limit of 4 for "high priest of <deity>",
|
||||
* but aligned priests can grow into high priests, thus they aren't
|
||||
* really limited to 4, so leave the default amount in place for them.
|
||||
*/
|
||||
|
||||
/* assert(MAXMONNO < 255); */
|
||||
return (mndx == PM_NAZGUL ? 9 : mndx == PM_ERINYS ? 3 : MAXMONNO);
|
||||
}
|
||||
@@ -1463,7 +1468,7 @@ rndmonst()
|
||||
rndmonst_state.mchoices[mndx] = 0;
|
||||
if (tooweak(mndx, minmlev) || toostrong(mndx, maxmlev))
|
||||
continue;
|
||||
if (upper && !isupper(def_monsyms[(int) (ptr->mlet)].sym))
|
||||
if (upper && !isupper((uchar) def_monsyms[(int) ptr->mlet].sym))
|
||||
continue;
|
||||
if (elemlevel && wrong_elem_type(ptr))
|
||||
continue;
|
||||
@@ -1668,6 +1673,7 @@ grow_up(mtmp, victim)
|
||||
struct monst *mtmp, *victim;
|
||||
{
|
||||
int oldtype, newtype, max_increase, cur_increase, lev_limit, hp_threshold;
|
||||
unsigned fem;
|
||||
struct permonst *ptr = mtmp->data;
|
||||
|
||||
/* monster died after killing enemy but before calling this function */
|
||||
@@ -1728,6 +1734,9 @@ struct monst *mtmp, *victim;
|
||||
else if (lev_limit > 49)
|
||||
lev_limit = (ptr->mlevel > 49 ? 50 : 49);
|
||||
|
||||
/* new form might force gender change */
|
||||
fem = is_male(ptr) ? 0 : is_female(ptr) ? 1 : mtmp->female;
|
||||
|
||||
if ((int) ++mtmp->m_lev >= mons[newtype].mlevel && newtype != oldtype) {
|
||||
ptr = &mons[newtype];
|
||||
if (mvitals[newtype].mvflags & G_GENOD) { /* allow G_EXTINCT */
|
||||
@@ -1739,14 +1748,31 @@ struct monst *mtmp, *victim;
|
||||
mondied(mtmp);
|
||||
return (struct permonst *) 0;
|
||||
} else if (canspotmon(mtmp)) {
|
||||
char buf[BUFSZ];
|
||||
|
||||
/* 3.6.1:
|
||||
* Temporary (?) hack to fix growing into opposite gender.
|
||||
*/
|
||||
Sprintf(buf, "%s%s",
|
||||
/* deal with female gnome becoming a gnome lord */
|
||||
(mtmp->female && !fem) ? "male "
|
||||
/* or a male gnome becoming a gnome lady
|
||||
(can't happen with 3.6.0 mons[], but perhaps
|
||||
slightly less sexist if prepared for it...) */
|
||||
: (fem && !mtmp->female) ? "female " : "",
|
||||
ptr->mname);
|
||||
pline("%s %s %s.", Monnam(mtmp),
|
||||
humanoid(ptr) ? "becomes" : "grows up into",
|
||||
an(ptr->mname));
|
||||
(fem != mtmp->female) ? "changes into"
|
||||
: humanoid(ptr) ? "becomes"
|
||||
: "grows up into",
|
||||
an(buf));
|
||||
}
|
||||
set_mon_data(mtmp, ptr, 1); /* preserve intrinsics */
|
||||
newsym(mtmp->mx, mtmp->my); /* color may change */
|
||||
lev_limit = (int) mtmp->m_lev; /* never undo increment */
|
||||
}
|
||||
mtmp->female = fem; /* gender might be changing */
|
||||
|
||||
/* sanity checks */
|
||||
if ((int) mtmp->m_lev > lev_limit) {
|
||||
mtmp->m_lev--; /* undo increment */
|
||||
|
||||
+9
-1
@@ -124,11 +124,19 @@ unsigned *ospecial;
|
||||
color = NO_COLOR;
|
||||
#ifdef TEXTCOLOR
|
||||
/* provide a visible difference if normal and lit corridor
|
||||
* use the same symbol */
|
||||
use the same symbol */
|
||||
} else if (iflags.use_color && offset == S_litcorr
|
||||
&& showsyms[idx] == showsyms[S_corr + SYM_OFF_P]) {
|
||||
color = CLR_WHITE;
|
||||
#endif
|
||||
/* try to provide a visible difference between water and lava
|
||||
if they use the same symbol and color is disabled */
|
||||
} else if (!iflags.use_color && offset == S_lava
|
||||
&& (showsyms[idx] == showsyms[S_pool + SYM_OFF_P]
|
||||
|| showsyms[idx] == showsyms[S_water + SYM_OFF_P])) {
|
||||
/* temporary? hack; makes tty use inverse video if the
|
||||
corresponding boolean option is enabled */
|
||||
special |= MG_DETECT;
|
||||
} else {
|
||||
cmap_color(offset);
|
||||
}
|
||||
|
||||
+2
-2
@@ -268,8 +268,8 @@ boolean foundyou;
|
||||
}
|
||||
|
||||
/*
|
||||
* As these are spells, the damage is related to the level
|
||||
* of the monster casting the spell.
|
||||
* As these are spells, the damage is related to the level
|
||||
* of the monster casting the spell.
|
||||
*/
|
||||
if (!foundyou) {
|
||||
dmg = 0;
|
||||
|
||||
+29
-15
@@ -2147,10 +2147,15 @@ register struct attack *mattk;
|
||||
/* not blind at this point implies you're wearing
|
||||
the Eyes of the Overworld; make them block this
|
||||
particular stun attack too */
|
||||
if (!Blind)
|
||||
if (!Blind) {
|
||||
Your1(vision_clears);
|
||||
else
|
||||
make_stunned((long) d(1, 3), TRUE);
|
||||
} else {
|
||||
long oldstun = (HStun & TIMEOUT), newstun = (long) rnd(3);
|
||||
|
||||
/* we don't want to increment stun duration every time
|
||||
or sighted hero will become incapacitated */
|
||||
make_stunned(max(oldstun, newstun), TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -2297,7 +2302,7 @@ register struct monst *mon;
|
||||
{
|
||||
register struct obj *ring, *nring;
|
||||
boolean fem = (mon->data == &mons[PM_SUCCUBUS]); /* otherwise incubus */
|
||||
int tried_gloves = 0;
|
||||
int attr_tot, tried_gloves = 0;
|
||||
char qbuf[QBUFSZ];
|
||||
|
||||
if (mon->mcan || mon->mspec_used) {
|
||||
@@ -2438,7 +2443,12 @@ register struct monst *mon;
|
||||
/* by this point you have discovered mon's identity, blind or not... */
|
||||
pline("Time stands still while you and %s lie in each other's arms...",
|
||||
noit_mon_nam(mon));
|
||||
if (rn2(35) > ACURR(A_CHA) + ACURR(A_INT)) {
|
||||
/* 3.6.1: a combined total for charisma plus intelligence of 35-1
|
||||
used to guarantee successful outcome; now total maxes out at 32
|
||||
as far as deciding what will happen; chance for bad outcome when
|
||||
Cha+Int is 32 or more is 2/35, a bit over 5.7% */
|
||||
attr_tot = ACURR(A_CHA) + ACURR(A_INT);
|
||||
if (rn2(35) > min(attr_tot, 32)) {
|
||||
/* Don't bother with mspec_used here... it didn't get tired! */
|
||||
pline("%s seems to have enjoyed it more than you...",
|
||||
noit_Monnam(mon));
|
||||
@@ -2470,16 +2480,20 @@ register struct monst *mon;
|
||||
} else {
|
||||
You("have a curious feeling...");
|
||||
}
|
||||
exercise(A_CON, FALSE);
|
||||
exercise(A_DEX, FALSE);
|
||||
exercise(A_WIS, FALSE);
|
||||
break;
|
||||
case 4: {
|
||||
int tmp;
|
||||
|
||||
You_feel("exhausted.");
|
||||
exercise(A_STR, FALSE);
|
||||
tmp = rn1(10, 6);
|
||||
losehp(Maybe_Half_Phys(tmp), "exhaustion", KILLED_BY);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} /* case 4 */
|
||||
} /* switch */
|
||||
} else {
|
||||
mon->mspec_used = rnd(100); /* monster is worn out */
|
||||
You("seem to have enjoyed it more than %s...", noit_mon_nam(mon));
|
||||
@@ -2517,14 +2531,14 @@ register struct monst *mon;
|
||||
}
|
||||
}
|
||||
|
||||
if (mon->mtame) /* don't charge */
|
||||
if (mon->mtame) { /* don't charge */
|
||||
;
|
||||
else if (rn2(20) < ACURR(A_CHA)) {
|
||||
} else if (rn2(20) < ACURR(A_CHA)) {
|
||||
pline("%s demands that you pay %s, but you refuse...",
|
||||
noit_Monnam(mon), Blind ? (fem ? "her" : "him") : mhim(mon));
|
||||
} else if (u.umonnum == PM_LEPRECHAUN)
|
||||
} else if (u.umonnum == PM_LEPRECHAUN) {
|
||||
pline("%s tries to take your money, but fails...", noit_Monnam(mon));
|
||||
else {
|
||||
} else {
|
||||
long cost;
|
||||
long umoney = money_cnt(invent);
|
||||
|
||||
@@ -2539,9 +2553,9 @@ register struct monst *mon;
|
||||
}
|
||||
if (cost > umoney)
|
||||
cost = umoney;
|
||||
if (!cost)
|
||||
if (!cost) {
|
||||
verbalize("It's on the house!");
|
||||
else {
|
||||
} else {
|
||||
pline("%s takes %ld %s for services rendered!", noit_Monnam(mon),
|
||||
cost, currency(cost));
|
||||
money2mon(mon, cost);
|
||||
@@ -2650,7 +2664,7 @@ register struct attack *mattk;
|
||||
}
|
||||
pline("%s turns to stone!", Monnam(mtmp));
|
||||
stoned = 1;
|
||||
xkilled(mtmp, 0);
|
||||
xkilled(mtmp, XKILL_NOMSG);
|
||||
if (mtmp->mhp > 0)
|
||||
return 1;
|
||||
return 2;
|
||||
@@ -2759,7 +2773,7 @@ register struct attack *mattk;
|
||||
assess_dmg:
|
||||
if ((mtmp->mhp -= tmp) <= 0) {
|
||||
pline("%s dies!", Monnam(mtmp));
|
||||
xkilled(mtmp, 0);
|
||||
xkilled(mtmp, XKILL_NOMSG);
|
||||
if (mtmp->mhp > 0)
|
||||
return 1;
|
||||
return 2;
|
||||
|
||||
+2
-2
@@ -247,8 +247,8 @@ boolean anyroom;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have drawn a map without walls, this allows us to
|
||||
* auto-magically wallify it. Taken from lev_main.c.
|
||||
* If we have drawn a map without walls, this allows us to
|
||||
* auto-magically wallify it. Taken from lev_main.c.
|
||||
*/
|
||||
STATIC_OVL void
|
||||
wallify_map()
|
||||
|
||||
+127
-28
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 mkmaze.c $NHDT-Date: 1449269918 2015/12/04 22:58:38 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.42 $ */
|
||||
/* NetHack 3.6 mkmaze.c $NHDT-Date: 1461571093 2016/04/25 07:58:13 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.47 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -9,9 +9,11 @@
|
||||
/* from sp_lev.c, for fixup_special() */
|
||||
extern lev_region *lregions;
|
||||
extern int num_lregions;
|
||||
/* for preserving the insect legs when wallifying baalz level */
|
||||
static lev_region bughack = { {COLNO, ROWNO, 0, 0}, {COLNO, ROWNO, 0, 0} };
|
||||
|
||||
STATIC_DCL boolean FDECL(iswall, (int, int));
|
||||
STATIC_DCL boolean FDECL(iswall_or_stone, (int, int));
|
||||
STATIC_DCL int FDECL(iswall, (int, int));
|
||||
STATIC_DCL int FDECL(iswall_or_stone, (int, int));
|
||||
STATIC_DCL boolean FDECL(is_solid, (int, int));
|
||||
STATIC_DCL int FDECL(extend_spine, (int[3][3], int, int, int));
|
||||
STATIC_DCL boolean FDECL(okay, (int, int, int));
|
||||
@@ -19,6 +21,7 @@ STATIC_DCL void FDECL(maze0xy, (coord *));
|
||||
STATIC_DCL boolean FDECL(put_lregion_here, (XCHAR_P, XCHAR_P, XCHAR_P,
|
||||
XCHAR_P, XCHAR_P, XCHAR_P,
|
||||
XCHAR_P, BOOLEAN_P, d_level *));
|
||||
STATIC_DCL void NDECL(baalz_fixup);
|
||||
STATIC_DCL void NDECL(setup_waterlevel);
|
||||
STATIC_DCL void NDECL(unsetup_waterlevel);
|
||||
|
||||
@@ -34,33 +37,28 @@ STATIC_DCL void NDECL(unsetup_waterlevel);
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
STATIC_OVL boolean
|
||||
STATIC_OVL int
|
||||
iswall(x, y)
|
||||
int x, y;
|
||||
{
|
||||
register int type;
|
||||
|
||||
if (!isok(x, y))
|
||||
return FALSE;
|
||||
return 0;
|
||||
type = levl[x][y].typ;
|
||||
return (boolean) (IS_WALL(type) || IS_DOOR(type)
|
||||
|| type == SDOOR || type == IRONBARS);
|
||||
return (IS_WALL(type) || IS_DOOR(type)
|
||||
|| type == SDOOR || type == IRONBARS);
|
||||
}
|
||||
|
||||
STATIC_OVL boolean
|
||||
STATIC_OVL int
|
||||
iswall_or_stone(x, y)
|
||||
int x, y;
|
||||
{
|
||||
register int type;
|
||||
|
||||
/* out of bounds = stone */
|
||||
if (!isok(x, y))
|
||||
return TRUE;
|
||||
return 1;
|
||||
|
||||
type = levl[x][y].typ;
|
||||
return (boolean) (type == STONE
|
||||
|| IS_WALL(type) || IS_DOOR(type)
|
||||
|| type == SDOOR || type == IRONBARS);
|
||||
return (levl[x][y].typ == STONE || iswall(x, y));
|
||||
}
|
||||
|
||||
/* return TRUE if out of bounds, wall or rock */
|
||||
@@ -138,6 +136,10 @@ int x1, y1, x2, y2;
|
||||
/* change walls surrounded by rock to rock. */
|
||||
for (x = x1; x <= x2; x++)
|
||||
for (y = y1; y <= y2; y++) {
|
||||
if (within_bounded_area(x, y,
|
||||
bughack.inarea.x1, bughack.inarea.y1,
|
||||
bughack.inarea.x2, bughack.inarea.y2))
|
||||
continue;
|
||||
lev = &levl[x][y];
|
||||
type = lev->typ;
|
||||
if (IS_WALL(type) && type != DBWALL) {
|
||||
@@ -158,8 +160,9 @@ int x1, y1, x2, y2;
|
||||
uchar type;
|
||||
register int x,y;
|
||||
struct rm *lev;
|
||||
int FDECL((*loc_f), (int, int));
|
||||
int bits;
|
||||
int locale[3][3]; /* rock or wall status surrounding positions */
|
||||
int locale[3][3]; /* rock or wall status surrounding positions */
|
||||
|
||||
/*
|
||||
* Value 0 represents a free-standing wall. It could be anything,
|
||||
@@ -172,8 +175,8 @@ int x1, y1, x2, y2;
|
||||
VWALL, TLWALL, TRWALL, CROSSWALL };
|
||||
|
||||
/* sanity check on incoming variables */
|
||||
if (x1<0 || x2>=COLNO || x1>x2 || y1<0 || y2>=ROWNO || y1>y2)
|
||||
panic("wall_extends: bad bounds (%d,%d) to (%d,%d)",x1,y1,x2,y2);
|
||||
if (x1 < 0 || x2 >= COLNO || x1 > x2 || y1 < 0 || y2 >= ROWNO || y1 > y2)
|
||||
panic("wall_extends: bad bounds (%d,%d) to (%d,%d)", x1, y1, x2, y2);
|
||||
|
||||
/* set the correct wall type. */
|
||||
for (x = x1; x <= x2; x++)
|
||||
@@ -184,16 +187,21 @@ int x1, y1, x2, y2;
|
||||
continue;
|
||||
|
||||
/* set the locations TRUE if rock or wall or out of bounds */
|
||||
locale[0][0] = iswall_or_stone(x - 1, y - 1);
|
||||
locale[1][0] = iswall_or_stone(x, y - 1);
|
||||
locale[2][0] = iswall_or_stone(x + 1, y - 1);
|
||||
loc_f = within_bounded_area(x, y, /* for baalz insect */
|
||||
bughack.inarea.x1, bughack.inarea.y1,
|
||||
bughack.inarea.x2, bughack.inarea.y2)
|
||||
? iswall
|
||||
: iswall_or_stone;
|
||||
locale[0][0] = (*loc_f)(x - 1, y - 1);
|
||||
locale[1][0] = (*loc_f)(x, y - 1);
|
||||
locale[2][0] = (*loc_f)(x + 1, y - 1);
|
||||
|
||||
locale[0][1] = iswall_or_stone(x - 1, y);
|
||||
locale[2][1] = iswall_or_stone(x + 1, y);
|
||||
locale[0][1] = (*loc_f)(x - 1, y);
|
||||
locale[2][1] = (*loc_f)(x + 1, y);
|
||||
|
||||
locale[0][2] = iswall_or_stone(x - 1, y + 1);
|
||||
locale[1][2] = iswall_or_stone(x, y + 1);
|
||||
locale[2][2] = iswall_or_stone(x + 1, y + 1);
|
||||
locale[0][2] = (*loc_f)(x - 1, y + 1);
|
||||
locale[1][2] = (*loc_f)(x, y + 1);
|
||||
locale[2][2] = (*loc_f)(x + 1, y + 1);
|
||||
|
||||
/* determine if wall should extend to each direction NSEW */
|
||||
bits = (extend_spine(locale, iswall(x, y - 1), 0, -1) << 3)
|
||||
@@ -211,8 +219,8 @@ void
|
||||
wallification(x1, y1, x2, y2)
|
||||
int x1, y1, x2, y2;
|
||||
{
|
||||
wall_cleanup(x1,y1,x2,y2);
|
||||
fix_wall_spines(x1,y1,x2,y2);
|
||||
wall_cleanup(x1, y1, x2, y2);
|
||||
fix_wall_spines(x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
STATIC_OVL boolean
|
||||
@@ -358,6 +366,94 @@ d_level *lev;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* fix up Baalzebub's lair, which depicts a level-sized beetle;
|
||||
its legs are walls within solid rock--regular wallification
|
||||
classifies them as superfluous and gets rid of them */
|
||||
STATIC_OVL void
|
||||
baalz_fixup()
|
||||
{
|
||||
struct monst *mtmp;
|
||||
int x, y, lastx, lasty;
|
||||
|
||||
/*
|
||||
* baalz level's nondiggable region surrounds the "insect" and rooms.
|
||||
* The outermost perimeter of that region is subject to wall cleanup
|
||||
* (hence 'x + 1' and 'y + 1' for starting don't-clean column and row,
|
||||
* 'lastx - 1' and 'lasty - 1' for ending don't-clean column and row)
|
||||
* and the interior is protected against that (in wall_cleanup()).
|
||||
*
|
||||
* Assumes level.flags.corrmaze is True, otherwise the bug legs will
|
||||
* have already been "cleaned" away by general wallification.
|
||||
*/
|
||||
|
||||
/* find low and high x for to-be-wallified portion of level */
|
||||
y = ROWNO / 2;
|
||||
for (lastx = x = 0; x < COLNO; ++x)
|
||||
if ((levl[x][y].wall_info & W_NONDIGGABLE) != 0) {
|
||||
if (!lastx)
|
||||
bughack.inarea.x1 = x + 1;
|
||||
lastx = x;
|
||||
}
|
||||
bughack.inarea.x2 = ((lastx > bughack.inarea.x1) ? lastx : x) - 1;
|
||||
/* find low and high y for to-be-wallified portion of level */
|
||||
x = bughack.inarea.x1;
|
||||
for (lasty = y = 0; y < ROWNO; ++y)
|
||||
if ((levl[x][y].wall_info & W_NONDIGGABLE) != 0) {
|
||||
if (!lasty)
|
||||
bughack.inarea.y1 = y + 1;
|
||||
lasty = y;
|
||||
}
|
||||
bughack.inarea.y2 = ((lasty > bughack.inarea.y1) ? lasty : y) - 1;
|
||||
/* two pools mark where special post-wallify fix-ups are needed */
|
||||
for (x = bughack.inarea.x1; x <= bughack.inarea.x2; ++x)
|
||||
for (y = bughack.inarea.y1; y <= bughack.inarea.y2; ++y)
|
||||
if (levl[x][y].typ == POOL) {
|
||||
levl[x][y].typ = HWALL;
|
||||
if (bughack.delarea.x1 == COLNO)
|
||||
bughack.delarea.x1 = x, bughack.delarea.y1 = y;
|
||||
else
|
||||
bughack.delarea.x2 = x, bughack.delarea.y2 = y;
|
||||
} else if (levl[x][y].typ == IRONBARS) {
|
||||
/* novelty effect; allowing digging in front of 'eyes' */
|
||||
levl[x - 1][y].wall_info &= ~W_NONDIGGABLE;
|
||||
if (isok(x - 2, y))
|
||||
levl[x - 2][y].wall_info &= ~W_NONDIGGABLE;
|
||||
}
|
||||
|
||||
wallification(max(bughack.inarea.x1 - 2, 1),
|
||||
max(bughack.inarea.y1 - 2, 0),
|
||||
min(bughack.inarea.x2 + 2, COLNO - 1),
|
||||
min(bughack.inarea.y2 + 2, ROWNO - 1));
|
||||
|
||||
/* bughack hack for rear-most legs on baalz level; first joint on
|
||||
both top and bottom gets a bogus extra connection to room area,
|
||||
producing unwanted rectangles; change back to separated legs */
|
||||
x = bughack.delarea.x1, y = bughack.delarea.y1;
|
||||
if (isok(x, y) && levl[x][y].typ == TLWALL
|
||||
&& isok(x, y + 1) && levl[x][y + 1].typ == TUWALL) {
|
||||
levl[x][y].typ = BRCORNER;
|
||||
levl[x][y + 1].typ = HWALL;
|
||||
if ((mtmp = m_at(x, y)) != 0) /* something at temporary pool... */
|
||||
(void) rloc(mtmp, FALSE);
|
||||
}
|
||||
x = bughack.delarea.x2, y = bughack.delarea.y2;
|
||||
if (isok(x, y) && levl[x][y].typ == TLWALL
|
||||
&& isok(x, y - 1) && levl[x][y - 1].typ == TDWALL) {
|
||||
levl[x][y].typ = TRCORNER;
|
||||
levl[x][y - 1].typ = HWALL;
|
||||
if ((mtmp = m_at(x, y)) != 0) /* something at temporary pool... */
|
||||
(void) rloc(mtmp, FALSE);
|
||||
}
|
||||
|
||||
/* reset bughack region; set low end to <COLNO,ROWNO> so that
|
||||
within_bounded_region() in fix_wall_spines() will fail
|
||||
most quickly--on its first test--when loading other levels */
|
||||
bughack.inarea.x1 = bughack.delarea.x1 = COLNO;
|
||||
bughack.inarea.y1 = bughack.delarea.y1 = ROWNO;
|
||||
bughack.inarea.x2 = bughack.delarea.x2 = 0;
|
||||
bughack.inarea.y2 = bughack.delarea.y2 = 0;
|
||||
}
|
||||
|
||||
static boolean was_waterlevel; /* ugh... this shouldn't be needed */
|
||||
|
||||
/* this is special stuff that the level compiler cannot (yet) handle */
|
||||
@@ -512,6 +608,9 @@ fixup_special()
|
||||
if (mtmp->isshk)
|
||||
mongone(mtmp);
|
||||
}
|
||||
} else if (on_level(&u.uz, &baalzebub_level)) {
|
||||
/* custom wallify the "beetle" potion of the level */
|
||||
baalz_fixup();
|
||||
}
|
||||
|
||||
if (lregions)
|
||||
|
||||
+8
-8
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 mkobj.c $NHDT-Date: 1454715975 2016/02/05 23:46:15 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.119 $ */
|
||||
/* NetHack 3.6 mkobj.c $NHDT-Date: 1462067745 2016/05/01 01:55:45 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.122 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -107,13 +107,11 @@ struct obj *otmp;
|
||||
{
|
||||
if (!otmp->oextra)
|
||||
otmp->oextra = newoextra();
|
||||
|
||||
if (!OMONST(otmp)) {
|
||||
struct monst *m = newmonst();
|
||||
|
||||
/* newmonst() allocates memory but doesn't initialize anything */
|
||||
(void) memset((genericptr_t) m, 0, sizeof (struct monst));
|
||||
m->mextra = (struct mextra *) 0;
|
||||
m->nmon = (struct monst *) 0;
|
||||
*m = zeromonst;
|
||||
OMONST(otmp) = m;
|
||||
}
|
||||
}
|
||||
@@ -736,7 +734,8 @@ boolean artif;
|
||||
otmp->where = OBJ_FREE;
|
||||
otmp->dknown = index(dknowns, let) ? 0 : 1;
|
||||
if ((otmp->otyp >= ELVEN_SHIELD && otmp->otyp <= ORCISH_SHIELD)
|
||||
|| otmp->otyp == SHIELD_OF_REFLECTION)
|
||||
|| otmp->otyp == SHIELD_OF_REFLECTION
|
||||
|| objects[otmp->otyp].oc_merge)
|
||||
otmp->dknown = 0;
|
||||
if (!objects[otmp->otyp].oc_uses_known)
|
||||
otmp->known = 1;
|
||||
@@ -2589,9 +2588,10 @@ struct obj *
|
||||
obj_nexto(otmp)
|
||||
struct obj *otmp;
|
||||
{
|
||||
if (!otmp)
|
||||
if (!otmp) {
|
||||
impossible("obj_nexto: wasn't given an object to check");
|
||||
|
||||
return (struct obj *) 0;
|
||||
}
|
||||
return obj_nexto_xy(otmp, otmp->ox, otmp->oy, TRUE);
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -684,9 +684,9 @@ coord *c;
|
||||
|
||||
/*
|
||||
* Search for a special room given its type (zoo, court, etc...)
|
||||
* Special values :
|
||||
* - ANY_SHOP
|
||||
* - ANY_TYPE
|
||||
* Special values :
|
||||
* - ANY_SHOP
|
||||
* - ANY_TYPE
|
||||
*/
|
||||
struct mkroom *
|
||||
search_special(type)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 mon.c $NHDT-Date: 1454528962 2016/02/03 19:49:22 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.210 $ */
|
||||
/* NetHack 3.6 mon.c $NHDT-Date: 1463534459 2016/05/18 01:20:59 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.221 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
|
||||
STATIC_VAR boolean vamp_rise_msg;
|
||||
|
||||
STATIC_DCL void FDECL(sanity_check_single_mon, (struct monst *, const char *));
|
||||
STATIC_DCL void FDECL(sanity_check_single_mon, (struct monst *, BOOLEAN_P,
|
||||
const char *));
|
||||
STATIC_DCL boolean FDECL(restrap, (struct monst *));
|
||||
STATIC_DCL long FDECL(mm_aggression, (struct monst *, struct monst *));
|
||||
STATIC_DCL long FDECL(mm_displacement, (struct monst *, struct monst *));
|
||||
@@ -41,35 +42,77 @@ const char *warnings[] = {
|
||||
|
||||
|
||||
void
|
||||
sanity_check_single_mon(mtmp, msg)
|
||||
sanity_check_single_mon(mtmp, chk_geno, msg)
|
||||
struct monst *mtmp;
|
||||
boolean chk_geno;
|
||||
const char *msg;
|
||||
{
|
||||
if (DEADMONSTER(mtmp))
|
||||
return;
|
||||
if (mtmp->data < &mons[LOW_PM] || mtmp->data >= &mons[NUMMONS])
|
||||
impossible("illegal mon data (%s)", msg);
|
||||
if (mtmp->data < &mons[LOW_PM] || mtmp->data >= &mons[NUMMONS]) {
|
||||
impossible("illegal mon data %s; mnum=%d (%s)",
|
||||
fmt_ptr((genericptr_t) mtmp->data), mtmp->mnum, msg);
|
||||
} else {
|
||||
int mndx = monsndx(mtmp->data);
|
||||
|
||||
if (mtmp->mnum != mndx) {
|
||||
impossible("monster mnum=%d, monsndx=%d (%s)",
|
||||
mtmp->mnum, mndx, msg);
|
||||
mtmp->mnum = mndx;
|
||||
}
|
||||
if (chk_geno && (mvitals[mndx].mvflags & G_GENOD) != 0)
|
||||
impossible("genocided %s in play (%s)", mons[mndx].mname, msg);
|
||||
}
|
||||
if (mtmp->isshk && !has_eshk(mtmp))
|
||||
impossible("shk without eshk (%s)", msg);
|
||||
if (mtmp->ispriest && !has_epri(mtmp))
|
||||
impossible("priest without epri (%s)", msg);
|
||||
if (mtmp->isgd && !has_egd(mtmp))
|
||||
impossible("guard without egd (%s)", msg);
|
||||
if (mtmp->isminion && !has_emin(mtmp))
|
||||
impossible("minion without emin (%s)", msg);
|
||||
/* guardian angel on astral level is tame but has emin rather than edog */
|
||||
if (mtmp->mtame && !has_edog(mtmp) && !mtmp->isminion)
|
||||
impossible("pet without edog (%s)", msg);
|
||||
}
|
||||
|
||||
void
|
||||
mon_sanity_check()
|
||||
{
|
||||
int x,y;
|
||||
struct monst *mtmp = fmon;
|
||||
int x, y;
|
||||
struct monst *mtmp, *m;
|
||||
|
||||
while (mtmp) {
|
||||
sanity_check_single_mon(mtmp, "fmon");
|
||||
mtmp = mtmp->nmon;
|
||||
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
|
||||
sanity_check_single_mon(mtmp, TRUE, "fmon");
|
||||
if (DEADMONSTER(mtmp))
|
||||
continue;
|
||||
x = mtmp->mx, y = mtmp->my;
|
||||
if (!isok(x, y) && !(mtmp->isgd && x == 0 && y == 0))
|
||||
impossible("mon (%s) claims to be at <%d,%d>?",
|
||||
fmt_ptr((genericptr_t) mtmp), x, y);
|
||||
else if (level.monsters[x][y] != mtmp)
|
||||
impossible("mon (%s) at <%d,%d> is not there!",
|
||||
fmt_ptr((genericptr_t) mtmp), x, y);
|
||||
}
|
||||
|
||||
for (x = 0; x < COLNO; x++)
|
||||
for (y = 0; y < ROWNO; y++)
|
||||
if ((mtmp = m_at(x,y)) != 0)
|
||||
sanity_check_single_mon(mtmp, "m_at");
|
||||
if ((mtmp = level.monsters[x][y]) != 0) {
|
||||
for (m = fmon; m; m = m->nmon)
|
||||
if (m == mtmp)
|
||||
break;
|
||||
if (!m)
|
||||
impossible("map mon (%s) at <%d,%d> not in fmon list!",
|
||||
fmt_ptr((genericptr_t) mtmp), x, y);
|
||||
else if ((mtmp->mx != x || mtmp->my != y)
|
||||
&& mtmp->data != &mons[PM_LONG_WORM])
|
||||
impossible("map mon (%s) at <%d,%d> is found at <%d,%d>?",
|
||||
fmt_ptr((genericptr_t) mtmp),
|
||||
mtmp->mx, mtmp->my, x, y);
|
||||
}
|
||||
|
||||
mtmp = migrating_mons;
|
||||
while (mtmp) {
|
||||
sanity_check_single_mon(mtmp, "migr");
|
||||
mtmp = mtmp->nmon;
|
||||
for (mtmp = migrating_mons; mtmp; mtmp = mtmp->nmon) {
|
||||
sanity_check_single_mon(mtmp, FALSE, "migr");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,7 +413,6 @@ unsigned corpseflags;
|
||||
}
|
||||
free_mname(mtmp);
|
||||
return obj;
|
||||
break;
|
||||
default_1:
|
||||
default:
|
||||
if (mvitals[mndx].mvflags & G_NOCORPSE) {
|
||||
@@ -472,14 +514,19 @@ register struct monst *mtmp;
|
||||
*/
|
||||
if (!is_clinger(mtmp->data) && !likes_lava(mtmp->data)) {
|
||||
if (!resists_fire(mtmp)) {
|
||||
if (cansee(mtmp->mx, mtmp->my))
|
||||
if (cansee(mtmp->mx, mtmp->my)) {
|
||||
struct attack *dummy = &mtmp->data->mattk[0];
|
||||
const char *how = on_fire(mtmp->data, dummy);
|
||||
|
||||
pline("%s %s.", Monnam(mtmp),
|
||||
mtmp->data == &mons[PM_WATER_ELEMENTAL]
|
||||
? "boils away"
|
||||
: "burns to a crisp");
|
||||
!strcmp(how, "boiling") ? "boils away"
|
||||
: !strcmp(how, "melting") ? "melts away"
|
||||
: "burns to a crisp");
|
||||
}
|
||||
mondead(mtmp);
|
||||
} else {
|
||||
if (--mtmp->mhp < 1) {
|
||||
mtmp->mhp -= 1;
|
||||
if (mtmp->mhp < 1) {
|
||||
if (cansee(mtmp->mx, mtmp->my))
|
||||
pline("%s surrenders to the fire.", Monnam(mtmp));
|
||||
mondead(mtmp);
|
||||
@@ -1538,7 +1585,10 @@ struct monst **monst_list; /* &migrating_mons or &mydogs or null */
|
||||
seemimic(mon);
|
||||
}
|
||||
|
||||
remove_monster(mx, my);
|
||||
if (mon->wormno)
|
||||
remove_worm(mon);
|
||||
else
|
||||
remove_monster(mx, my);
|
||||
|
||||
if (mon == fmon) {
|
||||
fmon = fmon->nmon;
|
||||
@@ -1580,32 +1630,27 @@ struct monst *mtmp2, *mtmp1;
|
||||
if (EGD(mtmp1)) {
|
||||
if (!EGD(mtmp2))
|
||||
newegd(mtmp2);
|
||||
(void) memcpy((genericptr_t) EGD(mtmp2), (genericptr_t) EGD(mtmp1),
|
||||
sizeof (struct egd));
|
||||
*EGD(mtmp2) = *EGD(mtmp1);
|
||||
}
|
||||
if (EPRI(mtmp1)) {
|
||||
if (!EPRI(mtmp2))
|
||||
newepri(mtmp2);
|
||||
(void) memcpy((genericptr_t) EPRI(mtmp2), (genericptr_t) EPRI(mtmp1),
|
||||
sizeof (struct epri));
|
||||
*EPRI(mtmp2) = *EPRI(mtmp1);
|
||||
}
|
||||
if (ESHK(mtmp1)) {
|
||||
if (!ESHK(mtmp2))
|
||||
neweshk(mtmp2);
|
||||
(void) memcpy((genericptr_t) ESHK(mtmp2), (genericptr_t) ESHK(mtmp1),
|
||||
sizeof (struct eshk));
|
||||
*ESHK(mtmp2) = *ESHK(mtmp1);
|
||||
}
|
||||
if (EMIN(mtmp1)) {
|
||||
if (!EMIN(mtmp2))
|
||||
newemin(mtmp2);
|
||||
(void) memcpy((genericptr_t) EMIN(mtmp2), (genericptr_t) EMIN(mtmp1),
|
||||
sizeof (struct emin));
|
||||
*EMIN(mtmp2) = *EMIN(mtmp1);
|
||||
}
|
||||
if (EDOG(mtmp1)) {
|
||||
if (!EDOG(mtmp2))
|
||||
newedog(mtmp2);
|
||||
(void) memcpy((genericptr_t) EDOG(mtmp2), (genericptr_t) EDOG(mtmp1),
|
||||
sizeof (struct edog));
|
||||
*EDOG(mtmp2) = *EDOG(mtmp1);
|
||||
}
|
||||
if (has_mcorpsenm(mtmp1))
|
||||
MCORPSENM(mtmp2) = MCORPSENM(mtmp1);
|
||||
@@ -1735,8 +1780,8 @@ struct monst *mtmp;
|
||||
/* genocided monster can't be life-saved */
|
||||
if (cansee(mtmp->mx, mtmp->my))
|
||||
pline("Unfortunately, %s is still genocided...", mon_nam(mtmp));
|
||||
mtmp->mhp = 0;
|
||||
}
|
||||
mtmp->mhp = 0;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1746,6 +1791,7 @@ register struct monst *mtmp;
|
||||
struct permonst *mptr;
|
||||
int tmp;
|
||||
|
||||
mtmp->mhp = 0; /* in case caller hasn't done this */
|
||||
lifesaved_monster(mtmp);
|
||||
if (mtmp->mhp > 0)
|
||||
return;
|
||||
@@ -1933,7 +1979,7 @@ boolean was_swallowed; /* digestion */
|
||||
return FALSE;
|
||||
|
||||
if (((bigmonst(mdat) || mdat == &mons[PM_LIZARD]) && !mon->mcloned)
|
||||
|| is_golem(mdat) || is_mplayer(mdat) || is_rider(mdat))
|
||||
|| is_golem(mdat) || is_mplayer(mdat) || is_rider(mdat) || mon->isshk)
|
||||
return TRUE;
|
||||
tmp = 2 + ((mdat->geno & G_FREQ) < 2) + verysmall(mdat);
|
||||
return (boolean) !rn2(tmp);
|
||||
@@ -1988,6 +2034,7 @@ struct monst *mdef;
|
||||
* put inventory in it, and we have to check for lifesaving before
|
||||
* making the statue....
|
||||
*/
|
||||
mdef->mhp = 0; /* in case caller hasn't done this */
|
||||
lifesaved_monster(mdef);
|
||||
if (mdef->mhp > 0)
|
||||
return;
|
||||
@@ -2108,52 +2155,45 @@ void
|
||||
killed(mtmp)
|
||||
struct monst *mtmp;
|
||||
{
|
||||
xkilled(mtmp, 1);
|
||||
xkilled(mtmp, XKILL_GIVEMSG);
|
||||
}
|
||||
|
||||
/* the player has killed the monster mtmp */
|
||||
void
|
||||
xkilled(mtmp, dest)
|
||||
xkilled(mtmp, xkill_flags)
|
||||
struct monst *mtmp;
|
||||
int dest; /* dest==1, normal; dest==0, don't print message; dest==2, don't
|
||||
drop corpse either; dest==3, message but no corpse */
|
||||
int xkill_flags; /* 1: suppress message, 2: suppress corpse, 4: pacifist */
|
||||
{
|
||||
int tmp, mndx, x = mtmp->mx, y = mtmp->my;
|
||||
struct permonst *mdat;
|
||||
struct obj *otmp;
|
||||
struct trap *t;
|
||||
boolean wasinside = u.uswallow && (u.ustuck == mtmp);
|
||||
boolean burycorpse = FALSE;
|
||||
boolean wasinside = u.uswallow && (u.ustuck == mtmp),
|
||||
burycorpse = FALSE,
|
||||
nomsg = (xkill_flags & XKILL_NOMSG) != 0,
|
||||
nocorpse = (xkill_flags & XKILL_NOCORPSE) != 0,
|
||||
noconduct = (xkill_flags & XKILL_NOCONDUCT) != 0;
|
||||
|
||||
/* KMH, conduct */
|
||||
u.uconduct.killer++;
|
||||
mtmp->mhp = 0; /* caller will usually have already done this */
|
||||
if (!noconduct) /* KMH, conduct */
|
||||
u.uconduct.killer++;
|
||||
|
||||
if (dest & 1) {
|
||||
const char *verb = nonliving(mtmp->data) ? "destroy" : "kill";
|
||||
|
||||
if (!wasinside && !canspotmon(mtmp))
|
||||
You("%s it!", verb);
|
||||
else {
|
||||
You("%s %s!", verb,
|
||||
!mtmp->mtame
|
||||
? mon_nam(mtmp)
|
||||
: x_monnam(mtmp,
|
||||
(has_mname(mtmp)) ? ARTICLE_NONE : ARTICLE_THE,
|
||||
"poor",
|
||||
(has_mname(mtmp)) ? SUPPRESS_SADDLE : 0,
|
||||
FALSE));
|
||||
}
|
||||
}
|
||||
if (!nomsg)
|
||||
You("%s %s!",
|
||||
nonliving(mtmp->data) ? "destroy" : "kill",
|
||||
!(wasinside || canspotmon(mtmp)) ? "it"
|
||||
: !mtmp->mtame ? mon_nam(mtmp)
|
||||
: x_monnam(mtmp, has_mname(mtmp) ? ARTICLE_NONE : ARTICLE_THE,
|
||||
"poor", has_mname(mtmp) ? SUPPRESS_SADDLE : 0,
|
||||
FALSE));
|
||||
|
||||
if (mtmp->mtrapped && (t = t_at(x, y)) != 0
|
||||
&& (t->ttyp == PIT || t->ttyp == SPIKED_PIT)) {
|
||||
if (sobj_at(BOULDER, x, y))
|
||||
dest |= 2; /*
|
||||
* Prevent corpses/treasure being created "on top"
|
||||
* of the boulder that is about to fall in. This is
|
||||
* out of order, but cannot be helped unless this
|
||||
* whole routine is rearranged.
|
||||
*/
|
||||
nocorpse = TRUE; /* Prevent corpses/treasure being created
|
||||
"on top" of boulder that is about to fall in.
|
||||
This is out of order, but cannot be helped
|
||||
unless this whole routine is rearranged. */
|
||||
if (m_carrying(mtmp, BOULDER))
|
||||
burycorpse = TRUE;
|
||||
}
|
||||
@@ -2183,8 +2223,7 @@ int dest; /* dest==1, normal; dest==0, don't print message; dest==2, don't
|
||||
if (mtmp->mhp > 0) { /* monster lifesaved */
|
||||
/* Cannot put the non-visible lifesaving message in
|
||||
* lifesaved_monster() since the message appears only when you
|
||||
* kill it (as opposed to visible lifesaving which always
|
||||
* appears).
|
||||
* kill it (as opposed to visible lifesaving which always appears).
|
||||
*/
|
||||
stoned = FALSE;
|
||||
if (!cansee(x, y) && !vamp_rise_msg)
|
||||
@@ -2200,7 +2239,7 @@ int dest; /* dest==1, normal; dest==0, don't print message; dest==2, don't
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((dest & 2) || LEVEL_SPECIFIC_NOCORPSE(mdat))
|
||||
if (nocorpse || LEVEL_SPECIFIC_NOCORPSE(mdat))
|
||||
goto cleanup;
|
||||
|
||||
#ifdef MAIL
|
||||
@@ -2227,7 +2266,7 @@ int dest; /* dest==1, normal; dest==0, don't print message; dest==2, don't
|
||||
/* oc_big is also oc_bimanual and oc_bulky */
|
||||
&& (otmp->owt > 30 || objects[otyp].oc_big)) {
|
||||
delobj(otmp);
|
||||
} else if (!flooreffects(otmp, x, y, (dest & 1) ? "fall" : "")) {
|
||||
} else if (!flooreffects(otmp, x, y, nomsg ? "" : "fall")) {
|
||||
place_object(otmp, x, y);
|
||||
stackobj(otmp);
|
||||
}
|
||||
@@ -2237,7 +2276,7 @@ int dest; /* dest==1, normal; dest==0, don't print message; dest==2, don't
|
||||
cadaver = make_corpse(mtmp, burycorpse ? CORPSTAT_BURIED
|
||||
: CORPSTAT_NONE);
|
||||
if (burycorpse && cadaver && cansee(x, y) && !mtmp->minvis
|
||||
&& cadaver->where == OBJ_BURIED && (dest & 1)) {
|
||||
&& cadaver->where == OBJ_BURIED && !nomsg) {
|
||||
pline("%s corpse ends up buried.", s_suffix(Monnam(mtmp)));
|
||||
}
|
||||
}
|
||||
@@ -2249,7 +2288,8 @@ int dest; /* dest==1, normal; dest==0, don't print message; dest==2, don't
|
||||
|
||||
cleanup:
|
||||
/* punish bad behaviour */
|
||||
if (is_human(mdat) && (!always_hostile(mdat) && mtmp->malign <= 0)
|
||||
if (is_human(mdat)
|
||||
&& (!always_hostile(mdat) && mtmp->malign <= 0)
|
||||
&& (mndx < PM_ARCHEOLOGIST || mndx > PM_WIZARD)
|
||||
&& u.ualign.type != A_CHAOTIC) {
|
||||
HTelepat &= ~INTRINSIC;
|
||||
@@ -2346,8 +2386,9 @@ struct monst *mtmp;
|
||||
SUPPRESS_SADDLE | SUPPRESS_HALLUCINATION
|
||||
| SUPPRESS_INVISIBLE | SUPPRESS_IT,
|
||||
FALSE),
|
||||
amorphous(mtmp->data) ? "coalesces on the" :
|
||||
is_flyer(mtmp->data) ? "drops to the" : "writhes on the",
|
||||
amorphous(mtmp->data) ? "coalesces on the"
|
||||
: is_flyer(mtmp->data) ? "drops to the"
|
||||
: "writhes on the",
|
||||
surface(x,y));
|
||||
mtmp->mcanmove = 1;
|
||||
mtmp->mfrozen = 0;
|
||||
@@ -2379,7 +2420,7 @@ struct monst *mtmp;
|
||||
}
|
||||
newsym(mtmp->mx, mtmp->my);
|
||||
return FALSE; /* didn't petrify */
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
@@ -3168,12 +3209,18 @@ boolean msg; /* "The oldmon turns into a newmon!" */
|
||||
int hpn, hpd;
|
||||
int mndx, tryct;
|
||||
struct permonst *olddata = mtmp->data;
|
||||
char oldname[BUFSZ], l_oldname[BUFSZ], newname[BUFSZ];
|
||||
char *p, oldname[BUFSZ], l_oldname[BUFSZ], newname[BUFSZ];
|
||||
|
||||
/* Riders are immune to polymorph and green slime
|
||||
(but apparent Rider might actually be a doppelganger) */
|
||||
if (is_rider(mtmp->data) && mtmp->cham == NON_PM)
|
||||
return 0;
|
||||
if (mtmp->cham == NON_PM) { /* not a shapechanger */
|
||||
if (is_rider(olddata))
|
||||
return 0;
|
||||
/* make Nazgul and erinyes immune too, to reduce chance of
|
||||
anomalous extinction feedback during final disclsoure */
|
||||
if (mbirth_limit(monsndx(olddata)) < MAXMONNO)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (msg) {
|
||||
/* like Monnam() but never mention saddle */
|
||||
@@ -3183,7 +3230,7 @@ boolean msg; /* "The oldmon turns into a newmon!" */
|
||||
}
|
||||
/* we need this one whether msg is true or not */
|
||||
Strcpy(l_oldname, x_monnam(mtmp, ARTICLE_THE, (char *) 0,
|
||||
(has_mname(mtmp)) ? SUPPRESS_SADDLE : 0, FALSE));
|
||||
has_mname(mtmp) ? SUPPRESS_SADDLE : 0, FALSE));
|
||||
|
||||
/* mdat = 0 -> caller wants a random monster shape */
|
||||
if (mdat == 0) {
|
||||
@@ -3206,23 +3253,18 @@ boolean msg; /* "The oldmon turns into a newmon!" */
|
||||
} else if (mvitals[monsndx(mdat)].mvflags & G_GENOD)
|
||||
return 0; /* passed in mdat is genocided */
|
||||
|
||||
if (mdat == mtmp->data)
|
||||
if (mdat == olddata)
|
||||
return 0; /* still the same monster */
|
||||
|
||||
mgender_from_permonst(mtmp, mdat);
|
||||
|
||||
if (In_endgame(&u.uz) && is_mplayer(olddata) && has_mname(mtmp)) {
|
||||
/* mplayers start out as "Foo the Bar", but some of the
|
||||
* titles are inappropriate when polymorphed, particularly
|
||||
* into the opposite sex. players don't use ranks when
|
||||
* polymorphed, so dropping the rank for mplayers seems
|
||||
* reasonable.
|
||||
*/
|
||||
char *p = index(MNAME(mtmp), ' ');
|
||||
|
||||
if (p)
|
||||
*p = '\0';
|
||||
}
|
||||
/* Endgame mplayers start out as "Foo the Bar", but some of the
|
||||
* titles are inappropriate when polymorphed, particularly into
|
||||
* the opposite sex. Player characters don't use ranks when
|
||||
* polymorphed, so dropping rank for mplayers seems reasonable.
|
||||
*/
|
||||
if (In_endgame(&u.uz) && is_mplayer(olddata)
|
||||
&& has_mname(mtmp) && (p = strstr(MNAME(mtmp), " the ")) != 0)
|
||||
*p = '\0';
|
||||
|
||||
if (mtmp->wormno) { /* throw tail away */
|
||||
wormgone(mtmp);
|
||||
@@ -3330,10 +3372,17 @@ boolean msg; /* "The oldmon turns into a newmon!" */
|
||||
? "slime"
|
||||
: x_monnam(mtmp, ARTICLE_A, (char *) 0,
|
||||
SUPPRESS_SADDLE, FALSE));
|
||||
if (!strcmpi(oldname, "it") && !strcmpi(newname, "it"))
|
||||
/* oldname was capitalized above; newname will be lower case */
|
||||
if (!strcmpi(newname, "it")) { /* can't see or sense it now */
|
||||
if (!!strcmpi(oldname, "it")) /* could see or sense it before */
|
||||
pline("%s disappears!", oldname);
|
||||
(void) usmellmon(mdat);
|
||||
else
|
||||
pline("%s turns into %s!", oldname, newname);
|
||||
} else { /* can see or sense it now */
|
||||
if (!strcmpi(oldname, "it")) /* couldn't see or sense it before */
|
||||
pline("%s appears!", upstart(newname));
|
||||
else
|
||||
pline("%s turns into %s!", oldname, newname);
|
||||
}
|
||||
if (save_mname)
|
||||
MNAME(mtmp) = save_mname;
|
||||
}
|
||||
|
||||
+4
-2
@@ -3,8 +3,9 @@
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
#include "hack.h"
|
||||
|
||||
/* These routines provide basic data for any type of monster. */
|
||||
/*
|
||||
* These routines provide basic data for any type of monster.
|
||||
*/
|
||||
|
||||
/* set up an individual monster's base type (initial creation, shapechange) */
|
||||
void
|
||||
@@ -16,6 +17,7 @@ int flag;
|
||||
int new_speed, old_speed = mon->data ? mon->data->mmove : 0;
|
||||
|
||||
mon->data = ptr;
|
||||
mon->mnum = (short) monsndx(ptr);
|
||||
if (flag == -1)
|
||||
return; /* "don't care" */
|
||||
|
||||
|
||||
+37
-18
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 monmove.c $NHDT-Date: 1456959639 2016/03/02 23:00:39 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.85 $ */
|
||||
/* NetHack 3.6 monmove.c $NHDT-Date: 1463704424 2016/05/20 00:33:44 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.87 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -705,6 +705,38 @@ xchar gx, gy;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
boolean
|
||||
m_digweapon_check(mtmp, nix, niy)
|
||||
struct monst *mtmp;
|
||||
xchar nix,niy;
|
||||
{
|
||||
boolean can_tunnel = 0;
|
||||
struct obj *mw_tmp;
|
||||
|
||||
if (!Is_rogue_level(&u.uz))
|
||||
can_tunnel = tunnels(mtmp->data);
|
||||
|
||||
if (can_tunnel && needspick(mtmp->data)
|
||||
&& mtmp->weapon_check != NO_WEAPON_WANTED
|
||||
&& ((IS_ROCK(levl[nix][niy].typ) && may_dig(nix, niy))
|
||||
|| closed_door(nix, niy))) {
|
||||
if (closed_door(nix, niy)) {
|
||||
if (!(mw_tmp = MON_WEP(mtmp))
|
||||
|| !is_pick(mw_tmp)
|
||||
|| !is_axe(mw_tmp))
|
||||
mtmp->weapon_check = NEED_PICK_OR_AXE;
|
||||
} else if (IS_TREE(levl[nix][niy].typ)) {
|
||||
if (!(mw_tmp = MON_WEP(mtmp)) || !is_axe(mw_tmp))
|
||||
mtmp->weapon_check = NEED_AXE;
|
||||
} else if (!(mw_tmp = MON_WEP(mtmp)) || !is_pick(mw_tmp)) {
|
||||
mtmp->weapon_check = NEED_PICK_AXE;
|
||||
}
|
||||
if (mtmp->weapon_check >= NEED_PICK_AXE && mon_wield_item(mtmp))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Return values:
|
||||
* 0: did not move, but can still attack and do other stuff.
|
||||
* 1: moved, possibly can attack.
|
||||
@@ -732,10 +764,10 @@ register int after;
|
||||
long info[9];
|
||||
long flag;
|
||||
int omx = mtmp->mx, omy = mtmp->my;
|
||||
struct obj *mw_tmp;
|
||||
|
||||
if (mtmp->mtrapped) {
|
||||
int i = mintrap(mtmp);
|
||||
|
||||
if (i >= 2) {
|
||||
newsym(mtmp->mx, mtmp->my);
|
||||
return 2;
|
||||
@@ -1108,22 +1140,9 @@ not_special:
|
||||
if (mmoved == 1 && (u.ux != nix || u.uy != niy) && itsstuck(mtmp))
|
||||
return 3;
|
||||
|
||||
if (mmoved == 1 && can_tunnel && needspick(ptr)
|
||||
&& ((IS_ROCK(levl[nix][niy].typ) && may_dig(nix, niy))
|
||||
|| closed_door(nix, niy))) {
|
||||
if (closed_door(nix, niy)) {
|
||||
if (!(mw_tmp = MON_WEP(mtmp)) || !is_pick(mw_tmp)
|
||||
|| !is_axe(mw_tmp))
|
||||
mtmp->weapon_check = NEED_PICK_OR_AXE;
|
||||
} else if (IS_TREE(levl[nix][niy].typ)) {
|
||||
if (!(mw_tmp = MON_WEP(mtmp)) || !is_axe(mw_tmp))
|
||||
mtmp->weapon_check = NEED_AXE;
|
||||
} else if (!(mw_tmp = MON_WEP(mtmp)) || !is_pick(mw_tmp)) {
|
||||
mtmp->weapon_check = NEED_PICK_AXE;
|
||||
}
|
||||
if (mtmp->weapon_check >= NEED_PICK_AXE && mon_wield_item(mtmp))
|
||||
return 3;
|
||||
}
|
||||
if (mmoved == 1 && m_digweapon_check(mtmp, nix,niy))
|
||||
return 3;
|
||||
|
||||
/* If ALLOW_U is set, either it's trying to attack you, or it
|
||||
* thinks it is. In either case, attack this spot in preference to
|
||||
* all others.
|
||||
|
||||
+33
-30
@@ -1,5 +1,5 @@
|
||||
/* NetHack 3.6 mplayer.c $NHDT-Date: 1432512774 2015/05/25 00:12:54 $ $NHDT-Branch: master $:$NHDT-Revision: 1.19 $ */
|
||||
/* Copyright (c) Izchak Miller, 1992. */
|
||||
/* NetHack 3.6 mplayer.c $NHDT-Date: 1458949461 2016/03/25 23:44:21 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.21 $ */
|
||||
/* Copyright (c) Izchak Miller, 1992. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
#include "hack.h"
|
||||
@@ -134,23 +134,13 @@ register boolean special;
|
||||
special = FALSE;
|
||||
|
||||
if ((mtmp = makemon(ptr, x, y, NO_MM_FLAGS)) != 0) {
|
||||
short weapon = rn2(2) ? LONG_SWORD : rnd_class(SPEAR, BULLWHIP);
|
||||
short armor =
|
||||
rnd_class(GRAY_DRAGON_SCALE_MAIL, YELLOW_DRAGON_SCALE_MAIL);
|
||||
short cloak = !rn2(8)
|
||||
? STRANGE_OBJECT
|
||||
: rnd_class(OILSKIN_CLOAK, CLOAK_OF_DISPLACEMENT);
|
||||
short helm = !rn2(8) ? STRANGE_OBJECT : rnd_class(ELVEN_LEATHER_HELM,
|
||||
HELM_OF_TELEPATHY);
|
||||
short shield = !rn2(8)
|
||||
? STRANGE_OBJECT
|
||||
: rnd_class(ELVEN_SHIELD, SHIELD_OF_REFLECTION);
|
||||
short weapon, armor, cloak, helm, shield;
|
||||
int quan;
|
||||
struct obj *otmp;
|
||||
|
||||
mtmp->m_lev = (special ? rn1(16, 15) : rnd(16));
|
||||
mtmp->mhp = mtmp->mhpmax =
|
||||
d((int) mtmp->m_lev, 10) + (special ? (30 + rnd(30)) : 30);
|
||||
mtmp->mhp = mtmp->mhpmax = d((int) mtmp->m_lev, 10)
|
||||
+ (special ? (30 + rnd(30)) : 30);
|
||||
if (special) {
|
||||
get_mplname(mtmp, nam);
|
||||
mtmp = christen_monst(mtmp, nam);
|
||||
@@ -160,6 +150,16 @@ register boolean special;
|
||||
mtmp->mpeaceful = 0;
|
||||
set_malign(mtmp); /* peaceful may have changed again */
|
||||
|
||||
/* default equipment; much of it will be overridden below */
|
||||
weapon = !rn2(2) ? LONG_SWORD : rnd_class(SPEAR, BULLWHIP);
|
||||
armor = rnd_class(GRAY_DRAGON_SCALE_MAIL, YELLOW_DRAGON_SCALE_MAIL);
|
||||
cloak = !rn2(8) ? STRANGE_OBJECT
|
||||
: rnd_class(OILSKIN_CLOAK, CLOAK_OF_DISPLACEMENT);
|
||||
helm = !rn2(8) ? STRANGE_OBJECT
|
||||
: rnd_class(ELVEN_LEATHER_HELM, HELM_OF_TELEPATHY);
|
||||
shield = !rn2(8) ? STRANGE_OBJECT
|
||||
: rnd_class(ELVEN_SHIELD, SHIELD_OF_REFLECTION);
|
||||
|
||||
switch (monsndx(ptr)) {
|
||||
case PM_ARCHEOLOGIST:
|
||||
if (rn2(2))
|
||||
@@ -285,18 +285,18 @@ register boolean special;
|
||||
mk_mplayer_armor(mtmp, helm);
|
||||
mk_mplayer_armor(mtmp, shield);
|
||||
if (rn2(8))
|
||||
mk_mplayer_armor(
|
||||
mtmp, rnd_class(LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY));
|
||||
mk_mplayer_armor(mtmp, rnd_class(LEATHER_GLOVES,
|
||||
GAUNTLETS_OF_DEXTERITY));
|
||||
if (rn2(8))
|
||||
mk_mplayer_armor(mtmp,
|
||||
rnd_class(LOW_BOOTS, LEVITATION_BOOTS));
|
||||
mk_mplayer_armor(mtmp, rnd_class(LOW_BOOTS,
|
||||
LEVITATION_BOOTS));
|
||||
m_dowear(mtmp, TRUE);
|
||||
|
||||
quan = rn2(3) ? rn2(3) : rn2(16);
|
||||
while (quan--)
|
||||
(void) mongets(mtmp, rnd_class(DILITHIUM_CRYSTAL, JADE));
|
||||
/* To get the gold "right" would mean a player can double his */
|
||||
/* gold supply by killing one mplayer. Not good. */
|
||||
/* To get the gold "right" would mean a player can double his
|
||||
gold supply by killing one mplayer. Not good. */
|
||||
mkmonmoney(mtmp, rn2(1000));
|
||||
quan = rn2(10);
|
||||
while (quan--)
|
||||
@@ -331,12 +331,13 @@ boolean special;
|
||||
int pm, x, y;
|
||||
struct monst fakemon;
|
||||
|
||||
fakemon = zeromonst;
|
||||
while (num) {
|
||||
int tryct = 0;
|
||||
|
||||
/* roll for character class */
|
||||
pm = PM_ARCHEOLOGIST + rn2(PM_WIZARD - PM_ARCHEOLOGIST + 1);
|
||||
fakemon.data = &mons[pm];
|
||||
set_mon_data(&fakemon, &mons[pm], -1);
|
||||
|
||||
/* roll for an available location */
|
||||
do {
|
||||
@@ -357,15 +358,17 @@ void
|
||||
mplayer_talk(mtmp)
|
||||
register struct monst *mtmp;
|
||||
{
|
||||
static const char *same_class_msg[3] =
|
||||
{
|
||||
"I can't win, and neither will you!", "You don't deserve to win!",
|
||||
"Mine should be the honor, not yours!",
|
||||
static const char
|
||||
*same_class_msg[3] = {
|
||||
"I can't win, and neither will you!",
|
||||
"You don't deserve to win!",
|
||||
"Mine should be the honor, not yours!",
|
||||
},
|
||||
*other_class_msg[3] = {
|
||||
"The low-life wants to talk, eh?", "Fight, scum!",
|
||||
"Here is what I have to say!",
|
||||
};
|
||||
*other_class_msg[3] = {
|
||||
"The low-life wants to talk, eh?",
|
||||
"Fight, scum!",
|
||||
"Here is what I have to say!",
|
||||
};
|
||||
|
||||
if (mtmp->mpeaceful)
|
||||
return; /* will drop to humanoid talk */
|
||||
|
||||
+1
-1
@@ -225,7 +225,7 @@ boolean verbose; /* give message(s) even when you can't see what happened */
|
||||
/* don't blame hero for unknown rolling boulder trap */
|
||||
if (!context.mon_moving
|
||||
&& (otmp->otyp != BOULDER || range >= 0 || otmp->otrapped))
|
||||
xkilled(mtmp, 0);
|
||||
xkilled(mtmp, XKILL_NOMSG);
|
||||
else
|
||||
mondied(mtmp);
|
||||
}
|
||||
|
||||
+67
-40
@@ -23,6 +23,7 @@ STATIC_DCL int FDECL(precheck, (struct monst *, struct obj *));
|
||||
STATIC_DCL void FDECL(mzapmsg, (struct monst *, struct obj *, BOOLEAN_P));
|
||||
STATIC_DCL void FDECL(mreadmsg, (struct monst *, struct obj *));
|
||||
STATIC_DCL void FDECL(mquaffmsg, (struct monst *, struct obj *));
|
||||
STATIC_DCL boolean FDECL(m_use_healing, (struct monst *));
|
||||
STATIC_PTR int FDECL(mbhitm, (struct monst *, struct obj *));
|
||||
STATIC_DCL void FDECL(mbhit, (struct monst *, int,
|
||||
int FDECL((*), (MONST_P, OBJ_P)),
|
||||
@@ -139,7 +140,7 @@ struct obj *obj;
|
||||
int dam = d(obj->spe + 2, 6);
|
||||
|
||||
/* 3.6.1: no Deaf filter; 'if' message doesn't warrant it, 'else'
|
||||
message doesn't need it since Your_hear() has one of its own */
|
||||
message doesn't need it since You_hear() has one of its own */
|
||||
if (vis) {
|
||||
pline("%s zaps %s, which suddenly explodes!", Monnam(mon),
|
||||
an(xname(obj)));
|
||||
@@ -153,11 +154,11 @@ struct obj *obj;
|
||||
? "nearby" : "in the distance");
|
||||
}
|
||||
m_useup(mon, obj);
|
||||
if (mon->mhp <= dam) {
|
||||
mon->mhp -= dam;
|
||||
if (mon->mhp <= 0) {
|
||||
monkilled(mon, "", AD_RBRE);
|
||||
return 1;
|
||||
} else
|
||||
mon->mhp -= dam;
|
||||
}
|
||||
m.has_defense = m.has_offense = m.has_misc = 0;
|
||||
/* Only one needed to be set to 0 but the others are harmless */
|
||||
}
|
||||
@@ -269,6 +270,29 @@ struct obj *otmp;
|
||||
* that if you polymorph into one you teleport at will.
|
||||
*/
|
||||
|
||||
STATIC_OVL boolean
|
||||
m_use_healing(mtmp)
|
||||
struct monst *mtmp;
|
||||
{
|
||||
struct obj *obj = 0;
|
||||
if ((obj = m_carrying(mtmp, POT_FULL_HEALING)) != 0) {
|
||||
m.defensive = obj;
|
||||
m.has_defense = MUSE_POT_FULL_HEALING;
|
||||
return TRUE;
|
||||
}
|
||||
if ((obj = m_carrying(mtmp, POT_EXTRA_HEALING)) != 0) {
|
||||
m.defensive = obj;
|
||||
m.has_defense = MUSE_POT_EXTRA_HEALING;
|
||||
return TRUE;
|
||||
}
|
||||
if ((obj = m_carrying(mtmp, POT_HEALING)) != 0) {
|
||||
m.defensive = obj;
|
||||
m.has_defense = MUSE_POT_HEALING;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Select a defensive item/action for a monster. Returns TRUE iff one is
|
||||
found. */
|
||||
boolean
|
||||
@@ -339,21 +363,8 @@ struct monst *mtmp;
|
||||
*/
|
||||
if (!mtmp->mcansee && !nohands(mtmp->data)
|
||||
&& mtmp->data != &mons[PM_PESTILENCE]) {
|
||||
if ((obj = m_carrying(mtmp, POT_FULL_HEALING)) != 0) {
|
||||
m.defensive = obj;
|
||||
m.has_defense = MUSE_POT_FULL_HEALING;
|
||||
if (m_use_healing(mtmp))
|
||||
return TRUE;
|
||||
}
|
||||
if ((obj = m_carrying(mtmp, POT_EXTRA_HEALING)) != 0) {
|
||||
m.defensive = obj;
|
||||
m.has_defense = MUSE_POT_EXTRA_HEALING;
|
||||
return TRUE;
|
||||
}
|
||||
if ((obj = m_carrying(mtmp, POT_HEALING)) != 0) {
|
||||
m.defensive = obj;
|
||||
m.has_defense = MUSE_POT_HEALING;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
fraction = u.ulevel < 10 ? 5 : u.ulevel < 14 ? 4 : 3;
|
||||
@@ -363,21 +374,8 @@ struct monst *mtmp;
|
||||
|
||||
if (mtmp->mpeaceful) {
|
||||
if (!nohands(mtmp->data)) {
|
||||
if ((obj = m_carrying(mtmp, POT_FULL_HEALING)) != 0) {
|
||||
m.defensive = obj;
|
||||
m.has_defense = MUSE_POT_FULL_HEALING;
|
||||
if (m_use_healing(mtmp))
|
||||
return TRUE;
|
||||
}
|
||||
if ((obj = m_carrying(mtmp, POT_EXTRA_HEALING)) != 0) {
|
||||
m.defensive = obj;
|
||||
m.has_defense = MUSE_POT_EXTRA_HEALING;
|
||||
return TRUE;
|
||||
}
|
||||
if ((obj = m_carrying(mtmp, POT_HEALING)) != 0) {
|
||||
m.defensive = obj;
|
||||
m.has_defense = MUSE_POT_HEALING;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1500,10 +1498,13 @@ struct monst *mtmp;
|
||||
else
|
||||
losehp(num, "scroll of fire", KILLED_BY_AN);
|
||||
for (mtmp2 = fmon; mtmp2; mtmp2 = mtmp2->nmon) {
|
||||
if (DEADMONSTER(mtmp2)) continue;
|
||||
if (mtmp == mtmp2) continue;
|
||||
if (DEADMONSTER(mtmp2))
|
||||
continue;
|
||||
if (mtmp == mtmp2)
|
||||
continue;
|
||||
if (dist2(mtmp2->mx, mtmp2->my, mtmp->mx, mtmp->my) < 3) {
|
||||
if (resists_fire(mtmp2)) continue;
|
||||
if (resists_fire(mtmp2))
|
||||
continue;
|
||||
mtmp2->mhp -= num;
|
||||
if (resists_cold(mtmp2))
|
||||
mtmp2->mhp -= 3 * num;
|
||||
@@ -2201,7 +2202,7 @@ mon_consume_unstone(mon, obj, by_you, stoning)
|
||||
struct monst *mon;
|
||||
struct obj *obj;
|
||||
boolean by_you;
|
||||
boolean stoning;
|
||||
boolean stoning; /* True: stop petrification, False: cure stun && confusion */
|
||||
{
|
||||
boolean vis = canseemon(mon), tinned = obj->otyp == TIN,
|
||||
food = obj->otyp == CORPSE || tinned,
|
||||
@@ -2240,7 +2241,10 @@ boolean stoning;
|
||||
if (mon->mhp <= 0) {
|
||||
pline("%s dies!", Monnam(mon));
|
||||
if (by_you)
|
||||
xkilled(mon, 0);
|
||||
/* hero gets credit (experience) and blame (possible loss
|
||||
of alignment and/or luck and/or telepathy depending on
|
||||
mon) for the kill but does not break pacifism conduct */
|
||||
xkilled(mon, XKILL_NOMSG | XKILL_NOCONDUCT);
|
||||
else
|
||||
mondead(mon);
|
||||
return;
|
||||
@@ -2404,7 +2408,7 @@ struct trap *trap;
|
||||
boolean by_you; /* true: if mon kills itself, hero gets credit/blame */
|
||||
{ /* [by_you not honored if 'mon' triggers fire trap]. */
|
||||
struct obj *odummyp;
|
||||
int otyp = obj->otyp, dmg;
|
||||
int otyp = obj->otyp, dmg = 0;
|
||||
boolean vis = canseemon(mon), res = TRUE;
|
||||
|
||||
if (vis)
|
||||
@@ -2443,7 +2447,7 @@ boolean by_you; /* true: if mon kills itself, hero gets credit/blame */
|
||||
if (!rn2(3))
|
||||
mon->mspec_used = rn1(10, 5);
|
||||
/* -21 => monster's fire breath; 1 => # of damage dice */
|
||||
(void) zhitm(mon, by_you ? 21 : -21, 1, &odummyp);
|
||||
dmg = zhitm(mon, by_you ? 21 : -21, 1, &odummyp);
|
||||
} else if (otyp == SCR_FIRE) {
|
||||
mreadmsg(mon, obj);
|
||||
if (mon->mconf) {
|
||||
@@ -2462,14 +2466,37 @@ boolean by_you; /* true: if mon kills itself, hero gets credit/blame */
|
||||
explode(mon->mx, mon->my, -11, dmg, SCROLL_CLASS,
|
||||
/* by_you: override -11 for mon but not others */
|
||||
by_you ? -EXPL_FIERY : EXPL_FIERY);
|
||||
dmg = 0; /* damage has been applied by explode() */
|
||||
}
|
||||
} else { /* wand/horn of fire w/ positive charge count */
|
||||
mzapmsg(mon, obj, TRUE);
|
||||
obj->spe--;
|
||||
/* -1 => monster's wand of fire; 2 => # of damage dice */
|
||||
(void) zhitm(mon, by_you ? 1 : -1, 2, &odummyp);
|
||||
dmg = zhitm(mon, by_you ? 1 : -1, 2, &odummyp);
|
||||
}
|
||||
|
||||
if (dmg) {
|
||||
/* zhitm() applies damage but doesn't kill creature off;
|
||||
for fire breath, dmg is going to be 0 (fire breathers are
|
||||
immune to fire damage) but for wand of fire or fire horn,
|
||||
'mon' could have taken damage so might die */
|
||||
if (mon->mhp <= 0) {
|
||||
if (by_you) {
|
||||
/* mon killed self but hero gets credit and blame (except
|
||||
for pacifist conduct); xkilled()'s message would say
|
||||
"You killed/destroyed <mon>" so give our own message */
|
||||
if (vis)
|
||||
pline("%s is %s by the fire!", Monnam(mon),
|
||||
nonliving(mon->data) ? "destroyed" : "killed");
|
||||
xkilled(mon, XKILL_NOMSG | XKILL_NOCONDUCT);
|
||||
} else
|
||||
monkilled(mon, "fire", AD_FIRE);
|
||||
} else {
|
||||
/* non-fatal damage occurred */
|
||||
if (vis)
|
||||
pline("%s is burned%s", Monnam(mon), exclam(dmg));
|
||||
}
|
||||
}
|
||||
if (vis) {
|
||||
if (res && mon->mhp > 0)
|
||||
pline("%s slime is burned away!", s_suffix(Monnam(mon)));
|
||||
|
||||
+14
-14
@@ -352,25 +352,25 @@ int force;
|
||||
/* Falling is okay for falling down
|
||||
within a pit from jostling too */
|
||||
mselftouch(mtmp, "Falling, ", TRUE);
|
||||
if (mtmp->mhp > 0)
|
||||
if ((mtmp->mhp -=
|
||||
rnd(m_already_trapped ? 4 : 6)) <= 0) {
|
||||
if (!cansee(x, y))
|
||||
if (mtmp->mhp > 0) {
|
||||
mtmp->mhp -= rnd(m_already_trapped ? 4 : 6);
|
||||
if (mtmp->mhp <= 0) {
|
||||
if (!cansee(x, y)) {
|
||||
pline("It is destroyed!");
|
||||
else {
|
||||
} else {
|
||||
You("destroy %s!",
|
||||
mtmp->mtame
|
||||
? x_monnam(
|
||||
mtmp, ARTICLE_THE,
|
||||
"poor",
|
||||
(has_mname(mtmp))
|
||||
? SUPPRESS_SADDLE
|
||||
: 0,
|
||||
FALSE)
|
||||
: mon_nam(mtmp));
|
||||
? x_monnam(mtmp, ARTICLE_THE,
|
||||
"poor",
|
||||
has_mname(mtmp)
|
||||
? SUPPRESS_SADDLE
|
||||
: 0,
|
||||
FALSE)
|
||||
: mon_nam(mtmp));
|
||||
}
|
||||
xkilled(mtmp, 0);
|
||||
xkilled(mtmp, XKILL_NOMSG);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (x == u.ux && y == u.uy) {
|
||||
if (Levitation || Flying
|
||||
|
||||
+125
-59
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 objnam.c $NHDT-Date: 1455672990 2016/02/17 01:36:30 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.165 $ */
|
||||
/* NetHack 3.6 objnam.c $NHDT-Date: 1462067746 2016/05/01 01:55:46 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.169 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -11,13 +11,14 @@
|
||||
|
||||
STATIC_DCL char *FDECL(strprepend, (char *, const char *));
|
||||
STATIC_DCL short FDECL(rnd_otyp_by_wpnskill, (SCHAR_P));
|
||||
STATIC_DCL short FDECL(rnd_otyp_by_namedesc, (char *, CHAR_P));
|
||||
STATIC_DCL boolean FDECL(wishymatch, (const char *, const char *, BOOLEAN_P));
|
||||
STATIC_DCL char *NDECL(nextobuf);
|
||||
STATIC_DCL void FDECL(releaseobuf, (char *));
|
||||
STATIC_DCL char *FDECL(minimal_xname, (struct obj *));
|
||||
STATIC_DCL void FDECL(add_erosion_words, (struct obj *, char *));
|
||||
STATIC_DCL boolean
|
||||
FDECL(singplur_lookup, (char *, char *, BOOLEAN_P, const char *const *));
|
||||
STATIC_DCL boolean FDECL(singplur_lookup, (char *, char *, BOOLEAN_P,
|
||||
const char *const *));
|
||||
STATIC_DCL char *FDECL(singplur_compound, (char *));
|
||||
STATIC_DCL char *FDECL(xname_flags, (struct obj *, unsigned));
|
||||
|
||||
@@ -406,9 +407,9 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (Is_pudding(obj)) {
|
||||
if (obj->globby) {
|
||||
Sprintf(buf, "%s%s",
|
||||
(obj->owt < 100)
|
||||
(obj->owt <= 100)
|
||||
? "small "
|
||||
: (obj->owt > 500)
|
||||
? "very large "
|
||||
@@ -730,13 +731,38 @@ char *prefix;
|
||||
: "");
|
||||
}
|
||||
|
||||
/* used to prevent rust on items where rust makes no difference */
|
||||
boolean
|
||||
erosion_matters(obj)
|
||||
struct obj *obj;
|
||||
{
|
||||
switch (obj->oclass) {
|
||||
case TOOL_CLASS:
|
||||
/* it's possible for a rusty weptool to be polymorphed into some
|
||||
non-weptool iron tool, in which case the rust implicitly goes
|
||||
away, but it's also possible for it to be polymorphed into a
|
||||
non-iron tool, in which case rust also implicitly goes away,
|
||||
so there's no particular reason to try to handle the first
|
||||
instance differently [this comment belongs in poly_obj()...] */
|
||||
return is_weptool(obj) ? TRUE : FALSE;
|
||||
case WEAPON_CLASS:
|
||||
case ARMOR_CLASS:
|
||||
case BALL_CLASS:
|
||||
case CHAIN_CLASS:
|
||||
return TRUE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static char *
|
||||
doname_base(obj, with_price)
|
||||
register struct obj *obj;
|
||||
boolean with_price;
|
||||
{
|
||||
boolean ispoisoned = FALSE;
|
||||
boolean known, cknown, bknown, lknown;
|
||||
boolean known, dknown, cknown, bknown, lknown;
|
||||
int omndx = obj->corpsenm;
|
||||
char prefix[PREFIX];
|
||||
char tmpbuf[PREFIX + 1]; /* for when we have to add something at
|
||||
@@ -745,9 +771,10 @@ boolean with_price;
|
||||
register char *bp = xname(obj);
|
||||
|
||||
if (iflags.override_ID) {
|
||||
known = cknown = bknown = lknown = TRUE;
|
||||
known = dknown = cknown = bknown = lknown = TRUE;
|
||||
} else {
|
||||
known = obj->known;
|
||||
dknown = obj->dknown;
|
||||
cknown = obj->cknown;
|
||||
bknown = obj->bknown;
|
||||
lknown = obj->lknown;
|
||||
@@ -765,7 +792,10 @@ boolean with_price;
|
||||
}
|
||||
|
||||
if (obj->quan != 1L) {
|
||||
Sprintf(prefix, "%ld ", obj->quan);
|
||||
if (dknown)
|
||||
Sprintf(prefix, "%ld ", obj->quan);
|
||||
else
|
||||
Strcpy(prefix, "some ");
|
||||
} else if (obj->otyp == CORPSE) {
|
||||
/* skip article prefix for corpses [else corpse_xname()
|
||||
would have to be taught how to strip it off again] */
|
||||
@@ -853,31 +883,27 @@ boolean with_price;
|
||||
plur(itemcount));
|
||||
}
|
||||
|
||||
switch (obj->oclass) {
|
||||
switch (is_weptool(obj) ? WEAPON_CLASS : obj->oclass) {
|
||||
case AMULET_CLASS:
|
||||
if (obj->owornmask & W_AMUL)
|
||||
Strcat(bp, " (being worn)");
|
||||
break;
|
||||
case ARMOR_CLASS:
|
||||
if (obj->owornmask & W_ARMOR)
|
||||
Strcat(bp, (obj == uskin) ? " (embedded in your skin)"
|
||||
: " (being worn)");
|
||||
/*FALLTHRU*/
|
||||
case WEAPON_CLASS:
|
||||
if (ispoisoned)
|
||||
Strcat(prefix, "poisoned ");
|
||||
plus:
|
||||
add_erosion_words(obj, prefix);
|
||||
if (known) {
|
||||
Strcat(prefix, sitoa(obj->spe));
|
||||
Strcat(prefix, " ");
|
||||
}
|
||||
break;
|
||||
case ARMOR_CLASS:
|
||||
if (obj->owornmask & W_ARMOR)
|
||||
Strcat(bp, (obj == uskin) ? " (embedded in your skin)"
|
||||
: " (being worn)");
|
||||
goto plus;
|
||||
case TOOL_CLASS:
|
||||
/* weptools already get this done when we go to the +n code */
|
||||
if (!is_weptool(obj))
|
||||
add_erosion_words(obj, prefix);
|
||||
if (obj->owornmask & (W_TOOL /* blindfold */ | W_SADDLE)) {
|
||||
if (obj->owornmask & (W_TOOL | W_SADDLE)) { /* blindfold */
|
||||
Strcat(bp, " (being worn)");
|
||||
break;
|
||||
}
|
||||
@@ -885,8 +911,6 @@ boolean with_price;
|
||||
Strcat(bp, " (in use)");
|
||||
break;
|
||||
}
|
||||
if (is_weptool(obj))
|
||||
goto plus;
|
||||
if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
|
||||
if (!obj->spe)
|
||||
Strcpy(tmpbuf, "no");
|
||||
@@ -908,7 +932,6 @@ boolean with_price;
|
||||
goto charges;
|
||||
break;
|
||||
case WAND_CLASS:
|
||||
add_erosion_words(obj, prefix);
|
||||
charges:
|
||||
if (known)
|
||||
Sprintf(eos(bp), " (%d:%d)", (int) obj->recharged, obj->spe);
|
||||
@@ -918,7 +941,6 @@ boolean with_price;
|
||||
Strcat(bp, " (lit)");
|
||||
break;
|
||||
case RING_CLASS:
|
||||
add_erosion_words(obj, prefix);
|
||||
ring:
|
||||
if (obj->owornmask & W_RINGR)
|
||||
Strcat(bp, " (on right ");
|
||||
@@ -2408,7 +2430,7 @@ struct alt_spellings {
|
||||
{ (const char *) 0, 0 },
|
||||
};
|
||||
|
||||
short
|
||||
STATIC_OVL short
|
||||
rnd_otyp_by_wpnskill(skill)
|
||||
schar skill;
|
||||
{
|
||||
@@ -2431,6 +2453,48 @@ schar skill;
|
||||
return otyp;
|
||||
}
|
||||
|
||||
STATIC_OVL short
|
||||
rnd_otyp_by_namedesc(name, oclass)
|
||||
char *name;
|
||||
char oclass;
|
||||
{
|
||||
int i, n = 0;
|
||||
short validobjs[NUM_OBJECTS];
|
||||
register const char *zn;
|
||||
long maxprob = 0;
|
||||
|
||||
if (!name)
|
||||
return STRANGE_OBJECT;
|
||||
|
||||
memset((genericptr_t) validobjs, 0, sizeof(validobjs));
|
||||
|
||||
for (i = oclass ? bases[(int)oclass] : STRANGE_OBJECT + 1;
|
||||
i < NUM_OBJECTS && (!oclass || objects[i].oc_class == oclass);
|
||||
++i) {
|
||||
/* don't match extra descriptions (w/o real name) */
|
||||
if ((zn = OBJ_NAME(objects[i])) == 0)
|
||||
continue;
|
||||
if (wishymatch(name, zn, TRUE)
|
||||
|| ((zn = OBJ_DESCR(objects[i])) != 0
|
||||
&& wishymatch(name, zn, FALSE))
|
||||
|| ((zn = objects[i].oc_uname) != 0
|
||||
&& wishymatch(name, zn, FALSE))) {
|
||||
validobjs[n++] = (short) i;
|
||||
maxprob += (objects[i].oc_prob + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (n > 0 && maxprob) {
|
||||
long prob = rn2(maxprob);
|
||||
|
||||
i = 0;
|
||||
while (i < n - 1 && (prob -= (objects[validobjs[i]].oc_prob + 1)) > 0)
|
||||
i++;
|
||||
return validobjs[i];
|
||||
}
|
||||
return STRANGE_OBJECT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return something wished for. Specifying a null pointer for
|
||||
* the user request string results in a random object. Otherwise,
|
||||
@@ -2452,7 +2516,7 @@ struct obj *no_wish;
|
||||
int halfeaten, mntmp, contents;
|
||||
int islit, unlabeled, ishistoric, isdiluted, trapped;
|
||||
int tmp, tinv, tvariety;
|
||||
int wetness;
|
||||
int wetness, gsize = 0;
|
||||
struct fruit *f;
|
||||
int ftype = context.current_fruit;
|
||||
char fruitbuf[BUFSZ];
|
||||
@@ -2471,7 +2535,7 @@ struct obj *no_wish;
|
||||
* automatically sticks 'candied' in front of such names.
|
||||
*/
|
||||
char oclass;
|
||||
char *un, *dn, *actualn;
|
||||
char *un, *dn, *actualn, *origbp = bp;
|
||||
const char *name = 0;
|
||||
|
||||
cnt = spe = spesgn = typ = very = rechrg = blessed = uncursed = iscursed =
|
||||
@@ -2590,6 +2654,15 @@ struct obj *no_wish;
|
||||
isdiluted = 1;
|
||||
} else if (!strncmpi(bp, "empty ", l = 6)) {
|
||||
contents = EMPTY;
|
||||
} else if (!strncmpi(bp, "small ", l = 6)) { /* glob sizes */
|
||||
gsize = 1;
|
||||
} else if (!strncmpi(bp, "medium ", l = 7)) {
|
||||
/* xname() doesn't display "medium" but without this
|
||||
there'd be no way to ask for the intermediate size */
|
||||
gsize = 2;
|
||||
} else if (!strncmpi(bp, "large ", l = 6)) {
|
||||
/* "very large " had "very " peeled off on previous iteration */
|
||||
gsize = (very != 1) ? 3 : 4;
|
||||
} else
|
||||
break;
|
||||
bp += l;
|
||||
@@ -2720,6 +2793,7 @@ struct obj *no_wish;
|
||||
if ((p = strstri(bp, "glob of ")) != 0
|
||||
|| (p = strstri(bp, "globs of ")) != 0) {
|
||||
int globoffset = (*(p + 4) == 's') ? 9 : 8;
|
||||
|
||||
if ((mntmp = name_to_mon(p + globoffset)) >= PM_GRAY_OOZE
|
||||
&& mntmp <= PM_BLACK_PUDDING) {
|
||||
mntmp = NON_PM; /* lie to ourselves */
|
||||
@@ -2991,30 +3065,14 @@ srch:
|
||||
}
|
||||
}
|
||||
}
|
||||
i = oclass ? bases[(int) oclass] : 1;
|
||||
while (i < NUM_OBJECTS && (!oclass || objects[i].oc_class == oclass)) {
|
||||
register const char *zn;
|
||||
|
||||
if (actualn && (zn = OBJ_NAME(objects[i])) != 0
|
||||
&& wishymatch(actualn, zn, TRUE)) {
|
||||
typ = i;
|
||||
goto typfnd;
|
||||
}
|
||||
if (dn && (zn = OBJ_DESCR(objects[i])) != 0
|
||||
&& wishymatch(dn, zn, FALSE)) {
|
||||
/* don't match extra descriptions (w/o real name) */
|
||||
if (!OBJ_NAME(objects[i]))
|
||||
return (struct obj *) 0;
|
||||
typ = i;
|
||||
goto typfnd;
|
||||
}
|
||||
if (un && (zn = objects[i].oc_uname) != 0
|
||||
&& wishymatch(un, zn, FALSE)) {
|
||||
typ = i;
|
||||
goto typfnd;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (((typ = rnd_otyp_by_namedesc(actualn, oclass)) != STRANGE_OBJECT)
|
||||
|| ((typ = rnd_otyp_by_namedesc(dn, oclass)) != STRANGE_OBJECT)
|
||||
|| ((typ = rnd_otyp_by_namedesc(un, oclass)) != STRANGE_OBJECT)
|
||||
|| ((typ = rnd_otyp_by_namedesc(origbp, oclass)) != STRANGE_OBJECT))
|
||||
goto typfnd;
|
||||
typ = 0;
|
||||
|
||||
if (actualn) {
|
||||
struct Jitem *j = Japanese_items;
|
||||
|
||||
@@ -3401,6 +3459,11 @@ typfnd:
|
||||
set_corpsenm(otmp, mntmp);
|
||||
}
|
||||
break;
|
||||
case EGG:
|
||||
mntmp = can_be_hatched(mntmp);
|
||||
/* this also sets hatch timer if appropriate */
|
||||
set_corpsenm(otmp, mntmp);
|
||||
break;
|
||||
case FIGURINE:
|
||||
if (!(mons[mntmp].geno & G_UNIQ) && !is_human(&mons[mntmp])
|
||||
#ifdef MAIL
|
||||
@@ -3409,11 +3472,6 @@ typfnd:
|
||||
)
|
||||
otmp->corpsenm = mntmp;
|
||||
break;
|
||||
case EGG:
|
||||
mntmp = can_be_hatched(mntmp);
|
||||
/* this also sets hatch timer if appropriate */
|
||||
set_corpsenm(otmp, mntmp);
|
||||
break;
|
||||
case STATUE:
|
||||
otmp->corpsenm = mntmp;
|
||||
if (Has_contents(otmp) && verysmall(&mons[mntmp]))
|
||||
@@ -3443,15 +3501,19 @@ typfnd:
|
||||
curse(otmp);
|
||||
}
|
||||
|
||||
/* set eroded */
|
||||
if (is_damageable(otmp) || otmp->otyp == CRYSKNIFE) {
|
||||
/* set eroded and erodeproof */
|
||||
if (erosion_matters(otmp)) {
|
||||
if (eroded && (is_flammable(otmp) || is_rustprone(otmp)))
|
||||
otmp->oeroded = eroded;
|
||||
if (eroded2 && (is_corrodeable(otmp) || is_rottable(otmp)))
|
||||
otmp->oeroded2 = eroded2;
|
||||
|
||||
/* set erodeproof */
|
||||
if (erodeproof && !eroded && !eroded2)
|
||||
/*
|
||||
* 3.6.1: earlier versions included `&& !eroded && !eroded2' here,
|
||||
* but damageproof combined with damaged is feasible (eroded
|
||||
* armor modified by confused reading of cursed destroy armor)
|
||||
* so don't prevent player from wishing for such a combination.
|
||||
*/
|
||||
if (erodeproof && (is_damageable(otmp) || otmp->otyp == CRYSKNIFE))
|
||||
otmp->oerodeproof = (Luck >= 0 || wizard);
|
||||
}
|
||||
|
||||
@@ -3534,6 +3596,10 @@ typfnd:
|
||||
otmp->owt = weight(otmp);
|
||||
if (very && otmp->otyp == HEAVY_IRON_BALL)
|
||||
otmp->owt += IRON_BALL_W_INCR;
|
||||
else if (gsize > 1 && otmp->globby)
|
||||
/* 0: unspecified => small; 1: small => keep default owt of 20;
|
||||
2: medium => 120; 3: large => 320; 4: very large => 520 */
|
||||
otmp->owt += 100 + (gsize - 2) * 200;
|
||||
|
||||
return otmp;
|
||||
}
|
||||
|
||||
+296
-237
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 options.c $NHDT-Date: 1455357588 2016/02/13 09:59:48 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.264 $ */
|
||||
/* NetHack 3.6 options.c $NHDT-Date: 1461102048 2016/04/19 21:40:48 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.268 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -519,6 +519,8 @@ STATIC_DCL int NDECL(msgtype_count);
|
||||
STATIC_DCL boolean FDECL(add_menu_coloring_parsed, (char *, int, int));
|
||||
STATIC_DCL void FDECL(free_one_menu_coloring, (int));
|
||||
STATIC_DCL int NDECL(count_menucolors);
|
||||
STATIC_DCL boolean FDECL(parse_role_opts, (BOOLEAN_P, const char *,
|
||||
char *, char **));
|
||||
|
||||
STATIC_DCL void FDECL(oc_to_str, (char *, char *));
|
||||
STATIC_DCL void FDECL(doset_add_menu, (winid, const char *, int));
|
||||
@@ -585,10 +587,13 @@ boolean val_allowed;
|
||||
|
||||
if (!p || (q && q < p))
|
||||
p = q;
|
||||
while (p && p > user_string && isspace((uchar) * (p - 1)))
|
||||
p--;
|
||||
if (p)
|
||||
if (p) {
|
||||
/* 'user_string' hasn't necessarily been through mungspaces()
|
||||
so might have tabs or consecutive spaces */
|
||||
while (p > user_string && isspace((uchar) *(p - 1)))
|
||||
p--;
|
||||
len = (int) (p - user_string);
|
||||
}
|
||||
}
|
||||
|
||||
return (boolean) (len >= min_length
|
||||
@@ -858,8 +863,8 @@ char *tp;
|
||||
} else if (*cp == '^') { /* expand control-character syntax */
|
||||
cval = (*++cp & 0x1f);
|
||||
++cp;
|
||||
/* remaining cases are all for backslash and we know cp[1] is not
|
||||
* \0 */
|
||||
|
||||
/* remaining cases are all for backslash; we know cp[1] is not \0 */
|
||||
} else if (index(dec, cp[1])) {
|
||||
++cp; /* move past backslash to first digit */
|
||||
do {
|
||||
@@ -1010,17 +1015,20 @@ change_inv_order(op)
|
||||
char *op;
|
||||
{
|
||||
int oc_sym, num;
|
||||
char *sp, buf[BUFSZ];
|
||||
char *sp, buf[QBUFSZ];
|
||||
|
||||
num = 0;
|
||||
/* !!!! probably unnecessary with gold as normal inventory */
|
||||
if (!index(op, GOLD_SYM))
|
||||
buf[num++] = COIN_CLASS;
|
||||
|
||||
for (sp = op; *sp; sp++) {
|
||||
oc_sym = def_char_to_objclass(*sp);
|
||||
/* reject bad or duplicate entries */
|
||||
if (oc_sym == MAXOCLASSES || oc_sym == RANDOM_CLASS
|
||||
|| oc_sym == ILLOBJ_CLASS || !index(flags.inv_order, oc_sym)
|
||||
|| index(sp + 1, *sp))
|
||||
if (oc_sym == MAXOCLASSES /* not an object class char */
|
||||
/* VENOM_CLASS, RANDOM_CLASS, and ILLOBJ_CLASS are excluded
|
||||
because they aren't in def_inv_order[] so don't make it
|
||||
into flags.inv_order, hence always fail this index() test */
|
||||
|| !index(flags.inv_order, oc_sym) || index(sp + 1, *sp))
|
||||
return 0;
|
||||
/* retain good ones */
|
||||
buf[num++] = (char) oc_sym;
|
||||
@@ -1029,10 +1037,9 @@ char *op;
|
||||
|
||||
/* fill in any omitted classes, using previous ordering */
|
||||
for (sp = flags.inv_order; *sp; sp++)
|
||||
if (!index(buf, *sp)) {
|
||||
buf[num++] = *sp;
|
||||
buf[num] = '\0'; /* explicitly terminate for next index() */
|
||||
}
|
||||
if (!index(buf, *sp))
|
||||
(void) strkitten(&buf[num++], *sp);
|
||||
buf[MAXOCLASSES - 1] = '\0';
|
||||
|
||||
Strcpy(flags.inv_order, buf);
|
||||
return 1;
|
||||
@@ -1721,14 +1728,48 @@ count_menucolors()
|
||||
return count;
|
||||
}
|
||||
|
||||
STATIC_OVL boolean
|
||||
parse_role_opts(negated, fullname, opts, opp)
|
||||
boolean negated;
|
||||
const char *fullname;
|
||||
char *opts;
|
||||
char **opp;
|
||||
{
|
||||
char *op = *opp;
|
||||
|
||||
if (negated) {
|
||||
bad_negation(fullname, FALSE);
|
||||
} else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
|
||||
boolean val_negated = FALSE;
|
||||
|
||||
while ((*op == '!') || !strncmpi(op, "no", 2)) {
|
||||
if (*op == '!')
|
||||
op++;
|
||||
else
|
||||
op += 2;
|
||||
val_negated = !val_negated;
|
||||
}
|
||||
if (val_negated) {
|
||||
if (!setrolefilter(op))
|
||||
badoption(opts);
|
||||
} else {
|
||||
if (duplicate_opt_detection(opts, 1))
|
||||
complain_about_duplicate(opts, 1);
|
||||
*opp = op;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
parseoptions(opts, tinitial, tfrom_file)
|
||||
register char *opts;
|
||||
boolean tinitial, tfrom_file;
|
||||
{
|
||||
register char *op;
|
||||
char *op;
|
||||
unsigned num;
|
||||
boolean negated, val_negated, duplicate;
|
||||
boolean negated, duplicate;
|
||||
int i;
|
||||
const char *fullname;
|
||||
|
||||
@@ -1803,26 +1844,9 @@ boolean tinitial, tfrom_file;
|
||||
/* align:string */
|
||||
fullname = "align";
|
||||
if (match_optname(opts, fullname, sizeof("align") - 1, TRUE)) {
|
||||
if (negated) {
|
||||
bad_negation(fullname, FALSE);
|
||||
} else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
|
||||
val_negated = FALSE;
|
||||
while ((*op == '!') || !strncmpi(op, "no", 2)) {
|
||||
if (*op == '!')
|
||||
op++;
|
||||
else
|
||||
op += 2;
|
||||
val_negated = !val_negated;
|
||||
}
|
||||
if (val_negated) {
|
||||
if (!setrolefilter(op))
|
||||
badoption(opts);
|
||||
} else {
|
||||
if (duplicate_opt_detection(opts, 1))
|
||||
complain_about_duplicate(opts, 1);
|
||||
if ((flags.initalign = str2align(op)) == ROLE_NONE)
|
||||
badoption(opts);
|
||||
}
|
||||
if (parse_role_opts(negated, fullname, opts, &op)) {
|
||||
if ((flags.initalign = str2align(op)) == ROLE_NONE)
|
||||
badoption(opts);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1831,28 +1855,11 @@ boolean tinitial, tfrom_file;
|
||||
fullname = "role";
|
||||
if (match_optname(opts, fullname, 4, TRUE)
|
||||
|| match_optname(opts, (fullname = "character"), 4, TRUE)) {
|
||||
if (negated) {
|
||||
bad_negation(fullname, FALSE);
|
||||
} else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
|
||||
val_negated = FALSE;
|
||||
while ((*op == '!') || !strncmpi(op, "no", 2)) {
|
||||
if (*op == '!')
|
||||
op++;
|
||||
else
|
||||
op += 2;
|
||||
val_negated = !val_negated;
|
||||
}
|
||||
if (val_negated) {
|
||||
if (!setrolefilter(op))
|
||||
badoption(opts);
|
||||
} else {
|
||||
if (duplicate_opt_detection(opts, 1))
|
||||
complain_about_duplicate(opts, 1);
|
||||
if ((flags.initrole = str2role(op)) == ROLE_NONE)
|
||||
badoption(opts);
|
||||
else /* Backwards compatibility */
|
||||
nmcpy(pl_character, op, PL_NSIZ);
|
||||
}
|
||||
if (parse_role_opts(negated, fullname, opts, &op)) {
|
||||
if ((flags.initrole = str2role(op)) == ROLE_NONE)
|
||||
badoption(opts);
|
||||
else /* Backwards compatibility */
|
||||
nmcpy(pl_character, op, PL_NSIZ);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1860,28 +1867,11 @@ boolean tinitial, tfrom_file;
|
||||
/* race:string */
|
||||
fullname = "race";
|
||||
if (match_optname(opts, fullname, 4, TRUE)) {
|
||||
if (negated) {
|
||||
bad_negation(fullname, FALSE);
|
||||
} else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
|
||||
val_negated = FALSE;
|
||||
while ((*op == '!') || !strncmpi(op, "no", 2)) {
|
||||
if (*op == '!')
|
||||
op++;
|
||||
else
|
||||
op += 2;
|
||||
val_negated = !val_negated;
|
||||
}
|
||||
if (val_negated) {
|
||||
if (!setrolefilter(op))
|
||||
badoption(opts);
|
||||
} else {
|
||||
if (duplicate_opt_detection(opts, 1))
|
||||
complain_about_duplicate(opts, 1);
|
||||
if ((flags.initrace = str2race(op)) == ROLE_NONE)
|
||||
badoption(opts);
|
||||
else /* Backwards compatibility */
|
||||
pl_race = *op;
|
||||
}
|
||||
if (parse_role_opts(negated, fullname, opts, &op)) {
|
||||
if ((flags.initrace = str2race(op)) == ROLE_NONE)
|
||||
badoption(opts);
|
||||
else /* Backwards compatibility */
|
||||
pl_race = *op;
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1889,28 +1879,11 @@ boolean tinitial, tfrom_file;
|
||||
/* gender:string */
|
||||
fullname = "gender";
|
||||
if (match_optname(opts, fullname, 4, TRUE)) {
|
||||
if (negated) {
|
||||
bad_negation(fullname, FALSE);
|
||||
} else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
|
||||
val_negated = FALSE;
|
||||
while ((*op == '!') || !strncmpi(op, "no", 2)) {
|
||||
if (*op == '!')
|
||||
op++;
|
||||
else
|
||||
op += 2;
|
||||
val_negated = !val_negated;
|
||||
}
|
||||
if (val_negated) {
|
||||
if (!setrolefilter(op))
|
||||
badoption(opts);
|
||||
} else {
|
||||
if (duplicate_opt_detection(opts, 1))
|
||||
complain_about_duplicate(opts, 1);
|
||||
if ((flags.initgend = str2gend(op)) == ROLE_NONE)
|
||||
badoption(opts);
|
||||
else
|
||||
flags.female = flags.initgend;
|
||||
}
|
||||
if (parse_role_opts(negated, fullname, opts, &op)) {
|
||||
if ((flags.initgend = str2gend(op)) == ROLE_NONE)
|
||||
badoption(opts);
|
||||
else
|
||||
flags.female = flags.initgend;
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -2140,7 +2113,7 @@ boolean tinitial, tfrom_file;
|
||||
bad_negation(fullname, TRUE);
|
||||
return;
|
||||
}
|
||||
tmp = tolower(*op);
|
||||
tmp = lowc(*op);
|
||||
}
|
||||
switch (tmp) {
|
||||
case 's': /* single message history cycle (default if negated) */
|
||||
@@ -2544,7 +2517,9 @@ boolean tinitial, tfrom_file;
|
||||
} else if ((op = string_for_opt(opts, TRUE)) != 0) {
|
||||
char *pp, buf[BUFSZ];
|
||||
|
||||
op = mungspaces(strcpy(buf, op));
|
||||
strncpy(buf, op, sizeof buf - 1);
|
||||
buf[sizeof buf - 1] = '\0';
|
||||
op = mungspaces(buf);
|
||||
for (;;) {
|
||||
/* We're looking to parse
|
||||
"paranoid_confirm:whichone wheretwo whothree"
|
||||
@@ -2604,30 +2579,24 @@ boolean tinitial, tfrom_file;
|
||||
bad_negation(fullname, FALSE);
|
||||
return;
|
||||
} else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
|
||||
switch (tolower(*op)) {
|
||||
/* Unencumbered */
|
||||
case 'u':
|
||||
switch (lowc(*op)) {
|
||||
case 'u': /* Unencumbered */
|
||||
flags.pickup_burden = UNENCUMBERED;
|
||||
break;
|
||||
/* Burdened (slight encumbrance) */
|
||||
case 'b':
|
||||
case 'b': /* Burdened (slight encumbrance) */
|
||||
flags.pickup_burden = SLT_ENCUMBER;
|
||||
break;
|
||||
/* streSsed (moderate encumbrance) */
|
||||
case 's':
|
||||
case 's': /* streSsed (moderate encumbrance) */
|
||||
flags.pickup_burden = MOD_ENCUMBER;
|
||||
break;
|
||||
/* straiNed (heavy encumbrance) */
|
||||
case 'n':
|
||||
case 'n': /* straiNed (heavy encumbrance) */
|
||||
flags.pickup_burden = HVY_ENCUMBER;
|
||||
break;
|
||||
/* OverTaxed (extreme encumbrance) */
|
||||
case 'o':
|
||||
case 'o': /* OverTaxed (extreme encumbrance) */
|
||||
case 't':
|
||||
flags.pickup_burden = EXT_ENCUMBER;
|
||||
break;
|
||||
/* overLoaded */
|
||||
case 'l':
|
||||
case 'l': /* overLoaded */
|
||||
flags.pickup_burden = OVERLOADED;
|
||||
break;
|
||||
default:
|
||||
@@ -2813,7 +2782,9 @@ boolean tinitial, tfrom_file;
|
||||
while (*op && num < sizeof flags.end_disclose - 1) {
|
||||
static char valid_settings[] = {
|
||||
DISCLOSE_PROMPT_DEFAULT_YES, DISCLOSE_PROMPT_DEFAULT_NO,
|
||||
DISCLOSE_YES_WITHOUT_PROMPT, DISCLOSE_NO_WITHOUT_PROMPT, '\0'
|
||||
DISCLOSE_PROMPT_DEFAULT_SPECIAL,
|
||||
DISCLOSE_YES_WITHOUT_PROMPT, DISCLOSE_NO_WITHOUT_PROMPT,
|
||||
DISCLOSE_SPECIAL_WITHOUT_PROMPT, '\0'
|
||||
};
|
||||
register char c, *dop;
|
||||
|
||||
@@ -2830,6 +2801,12 @@ boolean tinitial, tfrom_file;
|
||||
continue;
|
||||
}
|
||||
if (prefix_val != -1) {
|
||||
if (*dop != 'v') {
|
||||
if (prefix_val == DISCLOSE_PROMPT_DEFAULT_SPECIAL)
|
||||
prefix_val = DISCLOSE_PROMPT_DEFAULT_YES;
|
||||
if (prefix_val == DISCLOSE_SPECIAL_WITHOUT_PROMPT)
|
||||
prefix_val = DISCLOSE_YES_WITHOUT_PROMPT;
|
||||
}
|
||||
flags.end_disclose[idx] = prefix_val;
|
||||
prefix_val = -1;
|
||||
} else
|
||||
@@ -2901,11 +2878,13 @@ boolean tinitial, tfrom_file;
|
||||
if (match_optname(opts, fullname, 4, TRUE)) {
|
||||
op = string_for_env_opt(fullname, opts, FALSE);
|
||||
if (op) {
|
||||
switch (tolower(*op)) {
|
||||
case 'n':
|
||||
case 'l':
|
||||
case 'f':
|
||||
flags.sortloot = tolower(*op);
|
||||
char c = lowc(*op);
|
||||
|
||||
switch (c) {
|
||||
case 'n': /* none */
|
||||
case 'l': /* loot (pickup) */
|
||||
case 'f': /* full (pickup + invent) */
|
||||
flags.sortloot = c;
|
||||
break;
|
||||
default:
|
||||
badoption(opts);
|
||||
@@ -3096,8 +3075,7 @@ boolean tinitial, tfrom_file;
|
||||
if ((op = string_for_opt(opts, FALSE)) != 0) {
|
||||
if (iflags.wc_tile_file)
|
||||
free(iflags.wc_tile_file);
|
||||
iflags.wc_tile_file = (char *) alloc(strlen(op) + 1);
|
||||
Strcpy(iflags.wc_tile_file, op);
|
||||
iflags.wc_tile_file = dupstr(op);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -3184,22 +3162,26 @@ boolean tinitial, tfrom_file;
|
||||
return; /* string_for_opt gave feedback */
|
||||
tmp = negated ? 'n' : 'f';
|
||||
} else {
|
||||
tmp = tolower(*op);
|
||||
tmp = lowc(*op);
|
||||
}
|
||||
switch (tmp) {
|
||||
case 'n': /* none */
|
||||
case 't': /* traditional */
|
||||
case 't': /* traditional: prompt for class(es) by symbol,
|
||||
prompt for each item within class(es) one at a time */
|
||||
flags.menu_style = MENU_TRADITIONAL;
|
||||
break;
|
||||
case 'c': /* combo: trad.class sel+menu */
|
||||
case 'c': /* combination: prompt for class(es) by symbol,
|
||||
choose items within selected class(es) by menu */
|
||||
flags.menu_style = MENU_COMBINATION;
|
||||
break;
|
||||
case 'p': /* partial: no class menu */
|
||||
flags.menu_style = MENU_PARTIAL;
|
||||
break;
|
||||
case 'f': /* full: class menu + menu */
|
||||
case 'f': /* full: choose class(es) by first menu,
|
||||
choose items within selected class(es) by second menu */
|
||||
flags.menu_style = MENU_FULL;
|
||||
break;
|
||||
case 'p': /* partial: skip class filtering,
|
||||
choose items among all classes by menu */
|
||||
flags.menu_style = MENU_PARTIAL;
|
||||
break;
|
||||
default:
|
||||
badoption(opts);
|
||||
}
|
||||
@@ -3868,7 +3850,7 @@ int numtotal;
|
||||
{
|
||||
winid tmpwin;
|
||||
anything any;
|
||||
int i, pick_cnt, pick_idx, opt_idx;
|
||||
int i, pick_cnt, opt_idx;
|
||||
menu_item *pick_list = (menu_item *) 0;
|
||||
static const struct action {
|
||||
char letr;
|
||||
@@ -3886,6 +3868,7 @@ int numtotal;
|
||||
any = zeroany;
|
||||
for (i = 0; i < SIZE(action_titles); i++) {
|
||||
char tmpbuf[BUFSZ];
|
||||
|
||||
any.a_int++;
|
||||
/* omit list and remove if there aren't any yet */
|
||||
if (!numtotal && (i == 1 || i == 2))
|
||||
@@ -3893,24 +3876,17 @@ int numtotal;
|
||||
Sprintf(tmpbuf, action_titles[i].desc,
|
||||
(i == 1) ? makeplural(optname) : optname);
|
||||
add_menu(tmpwin, NO_GLYPH, &any, action_titles[i].letr, 0, ATR_NONE,
|
||||
tmpbuf,
|
||||
#if 0 /* this ought to work but doesn't... */
|
||||
(action_titles[i].letr == 'x') ? MENU_SELECTED :
|
||||
#endif
|
||||
MENU_UNSELECTED);
|
||||
tmpbuf, (i == 3) ? MENU_SELECTED : MENU_UNSELECTED);
|
||||
}
|
||||
end_menu(tmpwin, "Do what?");
|
||||
if ((pick_cnt = select_menu(tmpwin, PICK_ONE, &pick_list)) > 0) {
|
||||
for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
|
||||
opt_idx = pick_list[pick_idx].item.a_int - 1;
|
||||
}
|
||||
opt_idx = pick_list[0].item.a_int - 1;
|
||||
if (pick_cnt > 1 && opt_idx == 3)
|
||||
opt_idx = pick_list[1].item.a_int - 1;
|
||||
free((genericptr_t) pick_list);
|
||||
pick_list = (menu_item *) 0;
|
||||
}
|
||||
destroy_nhwindow(tmpwin);
|
||||
|
||||
if (pick_cnt < 1)
|
||||
} else
|
||||
opt_idx = 3; /* none selected, exit menu */
|
||||
destroy_nhwindow(tmpwin);
|
||||
return opt_idx;
|
||||
}
|
||||
|
||||
@@ -3924,7 +3900,7 @@ boolean setinitial, setfromfile;
|
||||
{
|
||||
winid tmpwin;
|
||||
anything any;
|
||||
int i;
|
||||
int i, n;
|
||||
char buf[BUFSZ];
|
||||
|
||||
/* Special handling of menustyle, pickup_burden, pickup_types,
|
||||
@@ -4014,6 +3990,7 @@ boolean setinitial, setfromfile;
|
||||
};
|
||||
int disc_cat[NUM_DISCLOSURE_OPTIONS];
|
||||
int pick_cnt, pick_idx, opt_idx;
|
||||
char c;
|
||||
menu_item *disclosure_pick = (menu_item *) 0;
|
||||
|
||||
tmpwin = create_nhwindow(NHW_MENU);
|
||||
@@ -4041,6 +4018,7 @@ boolean setinitial, setfromfile;
|
||||
|
||||
for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) {
|
||||
if (disc_cat[i]) {
|
||||
c = flags.end_disclose[i];
|
||||
Sprintf(buf, "Disclosure options for %s:",
|
||||
disclosure_names[i]);
|
||||
tmpwin = create_nhwindow(NHW_MENU);
|
||||
@@ -4048,24 +4026,41 @@ boolean setinitial, setfromfile;
|
||||
any = zeroany;
|
||||
/* 'y','n',and '+' work as alternate selectors; '-' doesn't */
|
||||
any.a_char = DISCLOSE_NO_WITHOUT_PROMPT;
|
||||
add_menu(tmpwin, NO_GLYPH, &any, 'a', any.a_char, ATR_NONE,
|
||||
add_menu(tmpwin, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
|
||||
"Never disclose, without prompting",
|
||||
MENU_UNSELECTED);
|
||||
(c == any.a_char) ? MENU_SELECTED : MENU_UNSELECTED);
|
||||
any.a_char = DISCLOSE_YES_WITHOUT_PROMPT;
|
||||
add_menu(tmpwin, NO_GLYPH, &any, 'b', any.a_char, ATR_NONE,
|
||||
add_menu(tmpwin, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
|
||||
"Always disclose, without prompting",
|
||||
MENU_UNSELECTED);
|
||||
(c == any.a_char) ? MENU_SELECTED : MENU_UNSELECTED);
|
||||
if (*disclosure_names[i] == 'v') {
|
||||
any.a_char = DISCLOSE_SPECIAL_WITHOUT_PROMPT; /* '#' */
|
||||
add_menu(tmpwin, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
|
||||
"Always disclose, pick sort order from menu",
|
||||
(c == any.a_char) ? MENU_SELECTED
|
||||
: MENU_UNSELECTED);
|
||||
}
|
||||
any.a_char = DISCLOSE_PROMPT_DEFAULT_NO;
|
||||
add_menu(tmpwin, NO_GLYPH, &any, 'c', any.a_char, ATR_NONE,
|
||||
add_menu(tmpwin, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
|
||||
"Prompt, with default answer of \"No\"",
|
||||
MENU_UNSELECTED);
|
||||
(c == any.a_char) ? MENU_SELECTED : MENU_UNSELECTED);
|
||||
any.a_char = DISCLOSE_PROMPT_DEFAULT_YES;
|
||||
add_menu(tmpwin, NO_GLYPH, &any, 'd', any.a_char, ATR_NONE,
|
||||
add_menu(tmpwin, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
|
||||
"Prompt, with default answer of \"Yes\"",
|
||||
MENU_UNSELECTED);
|
||||
(c == any.a_char) ? MENU_SELECTED : MENU_UNSELECTED);
|
||||
if (*disclosure_names[i] == 'v') {
|
||||
any.a_char = DISCLOSE_PROMPT_DEFAULT_SPECIAL; /* '?' */
|
||||
add_menu(tmpwin, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
|
||||
"Prompt, with default answer of \"Ask\" to request sort menu",
|
||||
(c == any.a_char) ? MENU_SELECTED
|
||||
: MENU_UNSELECTED);
|
||||
}
|
||||
end_menu(tmpwin, buf);
|
||||
if (select_menu(tmpwin, PICK_ONE, &disclosure_pick) > 0) {
|
||||
flags.end_disclose[i] = disclosure_pick->item.a_char;
|
||||
n = select_menu(tmpwin, PICK_ONE, &disclosure_pick);
|
||||
if (n > 0) {
|
||||
flags.end_disclose[i] = disclosure_pick[0].item.a_char;
|
||||
if (n > 1 && flags.end_disclose[i] == c)
|
||||
flags.end_disclose[i] = disclosure_pick[1].item.a_char;
|
||||
free((genericptr_t) disclosure_pick);
|
||||
}
|
||||
destroy_nhwindow(tmpwin);
|
||||
@@ -4183,11 +4178,17 @@ boolean setinitial, setfromfile;
|
||||
sortl_name = sortltype[i];
|
||||
any.a_char = *sortl_name;
|
||||
add_menu(tmpwin, NO_GLYPH, &any, *sortl_name, 0, ATR_NONE,
|
||||
sortl_name, MENU_UNSELECTED);
|
||||
sortl_name, (flags.sortloot == *sortl_name)
|
||||
? MENU_SELECTED : MENU_UNSELECTED);
|
||||
}
|
||||
end_menu(tmpwin, "Select loot sorting type:");
|
||||
if (select_menu(tmpwin, PICK_ONE, &sortl_pick) > 0) {
|
||||
flags.sortloot = sortl_pick->item.a_char;
|
||||
n = select_menu(tmpwin, PICK_ONE, &sortl_pick);
|
||||
if (n > 0) {
|
||||
char c = sortl_pick[0].item.a_char;
|
||||
|
||||
if (n > 1 && c == flags.sortloot)
|
||||
c = sortl_pick[1].item.a_char;
|
||||
flags.sortloot = c;
|
||||
free((genericptr_t) sortl_pick);
|
||||
}
|
||||
destroy_nhwindow(tmpwin);
|
||||
@@ -4286,23 +4287,24 @@ boolean setinitial, setfromfile;
|
||||
msgtypes_again:
|
||||
nmt = msgtype_count();
|
||||
opt_idx = handle_add_list_remove("message type", nmt);
|
||||
if (opt_idx == 3) {
|
||||
; /* done--fall through to function exit */
|
||||
if (opt_idx == 3) { /* done */
|
||||
return TRUE;
|
||||
} else if (opt_idx == 0) { /* add new */
|
||||
getlin("What new message pattern?", mtbuf);
|
||||
if (*mtbuf == '\033' || !*mtbuf)
|
||||
goto msgtypes_again;
|
||||
mttyp = query_msgtype();
|
||||
if (mttyp == -1)
|
||||
goto msgtypes_again;
|
||||
if (!msgtype_add(mttyp, mtbuf)) {
|
||||
if (*mtbuf == '\033')
|
||||
return TRUE;
|
||||
if (*mtbuf
|
||||
&& (mttyp = query_msgtype()) != -1
|
||||
&& !msgtype_add(mttyp, mtbuf)) {
|
||||
pline("Error adding the message type.");
|
||||
wait_synch();
|
||||
goto msgtypes_again;
|
||||
}
|
||||
} else { /* list or remove */
|
||||
goto msgtypes_again;
|
||||
} else { /* list (1) or remove (2) */
|
||||
int pick_idx, pick_cnt;
|
||||
int mt_idx;
|
||||
unsigned ln;
|
||||
const char *mtype;
|
||||
menu_item *pick_list = (menu_item *) 0;
|
||||
struct plinemsg_type *tmp = plinemsg_types;
|
||||
|
||||
@@ -4311,10 +4313,14 @@ boolean setinitial, setfromfile;
|
||||
any = zeroany;
|
||||
mt_idx = 0;
|
||||
while (tmp) {
|
||||
const char *mtype = msgtype2name(tmp->msgtype);
|
||||
|
||||
mtype = msgtype2name(tmp->msgtype);
|
||||
any.a_int = ++mt_idx;
|
||||
Sprintf(mtbuf, "%-5s \"%s\"", mtype, tmp->pattern);
|
||||
Sprintf(mtbuf, "%-5s \"", mtype);
|
||||
ln = sizeof mtbuf - strlen(mtbuf) - sizeof "\"";
|
||||
if (strlen(tmp->pattern) > ln)
|
||||
Strcat(strncat(mtbuf, tmp->pattern, ln - 3), "...\"");
|
||||
else
|
||||
Strcat(mtbuf, "\"");
|
||||
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, mtbuf,
|
||||
MENU_UNSELECTED);
|
||||
tmp = tmp->next;
|
||||
@@ -4342,26 +4348,25 @@ boolean setinitial, setfromfile;
|
||||
menucolors_again:
|
||||
nmc = count_menucolors();
|
||||
opt_idx = handle_add_list_remove("menucolor", nmc);
|
||||
if (opt_idx == 3) {
|
||||
; /* done--fall through to function exit */
|
||||
if (opt_idx == 3) { /* done */
|
||||
return TRUE;
|
||||
} else if (opt_idx == 0) { /* add new */
|
||||
getlin("What new menucolor pattern?", mcbuf);
|
||||
if (*mcbuf == '\033' || !*mcbuf)
|
||||
goto menucolors_again;
|
||||
mcclr = query_color();
|
||||
if (mcclr == -1)
|
||||
goto menucolors_again;
|
||||
mcattr = query_attr(NULL);
|
||||
if (mcattr == -1)
|
||||
goto menucolors_again;
|
||||
if (!add_menu_coloring_parsed(mcbuf, mcclr, mcattr)) {
|
||||
if (*mcbuf == '\033')
|
||||
return TRUE;
|
||||
if (*mcbuf
|
||||
&& (mcclr = query_color()) != -1
|
||||
&& (mcattr = query_attr((char *) 0)) != -1
|
||||
&& !add_menu_coloring_parsed(mcbuf, mcclr, mcattr)) {
|
||||
pline("Error adding the menu color.");
|
||||
wait_synch();
|
||||
goto menucolors_again;
|
||||
}
|
||||
} else { /* list or remove */
|
||||
goto menucolors_again;
|
||||
} else { /* list (1) or remove (2) */
|
||||
int pick_idx, pick_cnt;
|
||||
int mc_idx;
|
||||
unsigned ln;
|
||||
const char *sattr, *sclr;
|
||||
menu_item *pick_list = (menu_item *) 0;
|
||||
struct menucoloring *tmp = menu_colorings;
|
||||
|
||||
@@ -4370,13 +4375,22 @@ boolean setinitial, setfromfile;
|
||||
any = zeroany;
|
||||
mc_idx = 0;
|
||||
while (tmp) {
|
||||
const char *sattr = attr2attrname(tmp->attr);
|
||||
const char *sclr = clr2colorname(tmp->color);
|
||||
|
||||
any.a_int = (++mc_idx);
|
||||
Sprintf(mcbuf, "\"%s\"=%s%s%s", tmp->origstr, sclr,
|
||||
sattr = attr2attrname(tmp->attr);
|
||||
sclr = clr2colorname(tmp->color);
|
||||
any.a_int = ++mc_idx;
|
||||
/* construct suffix */
|
||||
Sprintf(buf, "\"\"=%s%s%s", sclr,
|
||||
(tmp->attr != ATR_NONE) ? " & " : "",
|
||||
(tmp->attr != ATR_NONE) ? sattr : "");
|
||||
/* now main string */
|
||||
ln = sizeof buf - strlen(buf) - 1; /* length available */
|
||||
Strcpy(mcbuf, "\"");
|
||||
if (strlen(tmp->origstr) > ln)
|
||||
Strcat(strncat(mcbuf, tmp->origstr, ln - 3), "...");
|
||||
else
|
||||
Strcat(mcbuf, tmp->origstr);
|
||||
/* combine main string and suffix */
|
||||
Strcat(mcbuf, &buf[1]); /* skip buf[]'s initial quote */
|
||||
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, mcbuf,
|
||||
MENU_UNSELECTED);
|
||||
tmp = tmp->next;
|
||||
@@ -4405,26 +4419,24 @@ boolean setinitial, setfromfile;
|
||||
ape_again:
|
||||
totalapes = count_ape_maps(&numapes[AP_LEAVE], &numapes[AP_GRAB]);
|
||||
opt_idx = handle_add_list_remove("autopickup exception", totalapes);
|
||||
if (opt_idx == 3) {
|
||||
; /* done--fall through to function exit */
|
||||
if (opt_idx == 3) { /* done */
|
||||
return TRUE;
|
||||
} else if (opt_idx == 0) { /* add new */
|
||||
getlin("What new autopickup exception pattern?", &apebuf[1]);
|
||||
mungspaces(&apebuf[1]); /* regularize whitespace */
|
||||
if (apebuf[1] == '\033') {
|
||||
; /* fall through to function exit */
|
||||
} else {
|
||||
if (apebuf[1]) {
|
||||
apebuf[0] = '\"';
|
||||
/* guarantee room for \" prefix and \"\0 suffix;
|
||||
-2 is good enough for apebuf[] but -3 makes
|
||||
sure the whole thing fits within normal BUFSZ */
|
||||
apebuf[sizeof apebuf - 3] = '\0';
|
||||
Strcat(apebuf, "\"");
|
||||
add_autopickup_exception(apebuf);
|
||||
}
|
||||
goto ape_again;
|
||||
if (apebuf[1] == '\033')
|
||||
return TRUE;
|
||||
if (apebuf[1]) {
|
||||
apebuf[0] = '\"';
|
||||
/* guarantee room for \" prefix and \"\0 suffix;
|
||||
-2 is good enough for apebuf[] but -3 makes
|
||||
sure the whole thing fits within normal BUFSZ */
|
||||
apebuf[sizeof apebuf - 3] = '\0';
|
||||
Strcat(apebuf, "\"");
|
||||
add_autopickup_exception(apebuf);
|
||||
}
|
||||
} else { /* list or remove */
|
||||
goto ape_again;
|
||||
} else { /* list (1) or remove (2) */
|
||||
int pick_idx, pick_cnt;
|
||||
menu_item *pick_list = (menu_item *) 0;
|
||||
|
||||
@@ -4440,6 +4452,7 @@ boolean setinitial, setfromfile;
|
||||
MENU_UNSELECTED);
|
||||
for (i = 0; i < numapes[pass] && ape; i++) {
|
||||
any.a_void = (opt_idx == 1) ? 0 : ape;
|
||||
/* length of pattern plus quotes is less than BUFSZ */
|
||||
Sprintf(apebuf, "\"%s\"", ape->pattern);
|
||||
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, apebuf,
|
||||
MENU_UNSELECTED);
|
||||
@@ -5025,39 +5038,54 @@ int
|
||||
add_autopickup_exception(mapping)
|
||||
const char *mapping;
|
||||
{
|
||||
static const char
|
||||
APE_regex_error[] = "regex error in AUTOPICKUP_EXCEPTION",
|
||||
APE_syntax_error[] = "syntax error in AUTOPICKUP_EXCEPTION";
|
||||
|
||||
struct autopickup_exception *ape, **apehead;
|
||||
char text[256], *text2;
|
||||
char text[256], end;
|
||||
int n;
|
||||
boolean grab = FALSE;
|
||||
|
||||
if (sscanf(mapping, "\"%255[^\"]\"", text) == 1) {
|
||||
text2 = &text[0];
|
||||
if (*text2 == '<') { /* force autopickup */
|
||||
grab = TRUE;
|
||||
++text2;
|
||||
} else if (*text2 == '>') { /* default - Do not pickup */
|
||||
grab = FALSE;
|
||||
++text2;
|
||||
}
|
||||
apehead = (grab) ? &iflags.autopickup_exceptions[AP_GRAB]
|
||||
: &iflags.autopickup_exceptions[AP_LEAVE];
|
||||
ape = (struct autopickup_exception *) alloc(
|
||||
sizeof (struct autopickup_exception));
|
||||
ape->regex = regex_init();
|
||||
if (!regex_compile(text2, ape->regex)) {
|
||||
raw_print("regex error in AUTOPICKUP_EXCEPTION");
|
||||
regex_free(ape->regex);
|
||||
free((genericptr_t) ape);
|
||||
return 0;
|
||||
}
|
||||
ape->pattern = (char *) alloc(strlen(text2) + 1);
|
||||
strcpy(ape->pattern, text2);
|
||||
ape->grab = grab;
|
||||
ape->next = *apehead;
|
||||
*apehead = ape;
|
||||
/* scan length limit used to be 255, but smaller size allows the
|
||||
quoted value to fit within BUFSZ, simplifying formatting elsewhere;
|
||||
this used to ignore the possibility of trailing junk but now checks
|
||||
for it, accepting whitespace but rejecting anything else unless it
|
||||
starts with '#" for a comment */
|
||||
end = '\0';
|
||||
if ((n = sscanf(mapping, "\"<%253[^\"]\" %c", text, &end)) == 1
|
||||
|| (n == 2 && end == '#')) {
|
||||
grab = TRUE;
|
||||
} else if ((n = sscanf(mapping, "\">%253[^\"]\" %c", text, &end)) == 1
|
||||
|| (n = sscanf(mapping, "\"%253[^\"]\" %c", text, &end)) == 1
|
||||
|| (n == 2 && end == '#')) {
|
||||
grab = FALSE;
|
||||
} else {
|
||||
raw_print("syntax error in AUTOPICKUP_EXCEPTION");
|
||||
if (!iflags.window_inited)
|
||||
raw_print(APE_syntax_error); /* from options file */
|
||||
else
|
||||
pline("%s", APE_syntax_error); /* via 'O' command */
|
||||
return 0;
|
||||
}
|
||||
|
||||
ape = (struct autopickup_exception *) alloc(sizeof *ape);
|
||||
ape->regex = regex_init();
|
||||
if (!regex_compile(text, ape->regex)) {
|
||||
if (!iflags.window_inited)
|
||||
raw_print(APE_regex_error);
|
||||
else
|
||||
pline("%s", APE_regex_error);
|
||||
regex_free(ape->regex);
|
||||
free((genericptr_t) ape);
|
||||
return 0;
|
||||
}
|
||||
apehead = (grab) ? &iflags.autopickup_exceptions[AP_GRAB]
|
||||
: &iflags.autopickup_exceptions[AP_LEAVE];
|
||||
|
||||
ape->pattern = dupstr(text);
|
||||
ape->grab = grab;
|
||||
ape->next = *apehead;
|
||||
*apehead = ape;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -5222,11 +5250,41 @@ char *buf;
|
||||
|
||||
int
|
||||
sym_val(strval)
|
||||
char *strval;
|
||||
const char *strval;
|
||||
{
|
||||
char buf[QBUFSZ];
|
||||
|
||||
buf[0] = '\0';
|
||||
escapes(strval, buf);
|
||||
if (!strval[0] || !strval[1]) { /* empty, or single character */
|
||||
/* if single char is space or tab, leave buf[0]=='\0' */
|
||||
if (!isspace((uchar) strval[0]))
|
||||
buf[0] = strval[0];
|
||||
} else if (strval[0] == '\'') { /* single quote */
|
||||
/* simple matching single quote; we know strval[1] isn't '\0' */
|
||||
if (strval[2] == '\'' && !strval[3]) {
|
||||
/* accepts '\' as backslash and ''' as single quote */
|
||||
buf[0] = strval[1];
|
||||
|
||||
/* if backslash, handle single or double quote or second backslash */
|
||||
} else if (strval[1] == '\\' && strval[2] && strval[3] == '\''
|
||||
&& index("'\"\\", strval[2]) && !strval[4]) {
|
||||
buf[0] = strval[2];
|
||||
|
||||
/* not simple quote or basic backslash;
|
||||
strip closing quote and let escapes() deal with it */
|
||||
} else {
|
||||
char *p, tmp[QBUFSZ];
|
||||
|
||||
(void) strncpy(tmp, strval + 1, sizeof tmp - 1);
|
||||
tmp[sizeof tmp - 1] = '\0';
|
||||
if ((p = rindex(tmp, '\'')) != 0) {
|
||||
*p = '\0';
|
||||
escapes(tmp, buf);
|
||||
} /* else buf[0] stays '\0' */
|
||||
}
|
||||
} else /* not lone char nor single quote */
|
||||
escapes(strval, buf);
|
||||
|
||||
return (int) *buf;
|
||||
}
|
||||
|
||||
@@ -5438,6 +5496,7 @@ struct fruit *replace_fruit;
|
||||
return rnd(127);
|
||||
|
||||
f = newfruit();
|
||||
(void) memset((genericptr_t)f, 0, sizeof(struct fruit));
|
||||
copynchars(f->fname, *altname ? altname : str, PL_FSIZ - 1);
|
||||
f->fid = ++highest_fruit_id;
|
||||
/* we used to go out of our way to add it at the end of the list,
|
||||
|
||||
+123
-77
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 pager.c $NHDT-Date: 1455674291 2016/02/17 01:58:11 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.93 $ */
|
||||
/* NetHack 3.6 pager.c $NHDT-Date: 1463790247 2016/05/21 00:24:07 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.98 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -165,9 +165,13 @@ struct obj **obj_p;
|
||||
if (mtmp && has_mcorpsenm(mtmp)) /* mimic as corpse/statue */
|
||||
otmp->corpsenm = MCORPSENM(mtmp);
|
||||
}
|
||||
/* if located at adjacent spot, mark it as having been seen up close */
|
||||
if (otmp && distu(x, y) <= 2 && !Blind && !Hallucination)
|
||||
otmp->dknown = 1;
|
||||
/* if located at adjacent spot, mark it as having been seen up close
|
||||
(corpse type will be known even if dknown is 0, so we don't need a
|
||||
touch check for cockatrice corpse--we're looking without touching) */
|
||||
if (otmp && distu(x, y) <= 2 && !Blind && !Hallucination
|
||||
/* terrain mode views what's already known, doesn't learn new stuff */
|
||||
&& !iflags.terrainmode) /* so don't set dknown when in terrain mode */
|
||||
otmp->dknown = 1; /* if a pile, clearly see the top item only */
|
||||
|
||||
*obj_p = otmp;
|
||||
return fakeobj; /* when True, caller needs to dealloc *obj_p */
|
||||
@@ -323,7 +327,8 @@ char *buf, *monbuf;
|
||||
|
||||
buf[0] = monbuf[0] = '\0';
|
||||
glyph = glyph_at(x, y);
|
||||
if (u.ux == x && u.uy == y && canspotself()) {
|
||||
if (u.ux == x && u.uy == y && canspotself()
|
||||
&& (!iflags.terrainmode || (iflags.terrainmode & TER_MON) != 0)) {
|
||||
/* fill in buf[] */
|
||||
(void) self_lookat(buf);
|
||||
|
||||
@@ -348,19 +353,19 @@ char *buf, *monbuf;
|
||||
how |= 4;
|
||||
|
||||
if (how)
|
||||
Sprintf(
|
||||
eos(buf), " [seen: %s%s%s%s%s]",
|
||||
(how & 1) ? "infravision" : "",
|
||||
/* add comma if telep and infrav */
|
||||
((how & 3) > 2) ? ", " : "", (how & 2) ? "telepathy" : "",
|
||||
/* add comma if detect and (infrav or telep or both) */
|
||||
((how & 7) > 4) ? ", " : "",
|
||||
(how & 4) ? "monster detection" : "");
|
||||
Sprintf(eos(buf), " [seen: %s%s%s%s%s]",
|
||||
(how & 1) ? "infravision" : "",
|
||||
/* add comma if telep and infrav */
|
||||
((how & 3) > 2) ? ", " : "",
|
||||
(how & 2) ? "telepathy" : "",
|
||||
/* add comma if detect and (infrav or telep or both) */
|
||||
((how & 7) > 4) ? ", " : "",
|
||||
(how & 4) ? "monster detection" : "");
|
||||
}
|
||||
} else if (u.uswallow) {
|
||||
/* all locations when swallowed other than the hero are the monster */
|
||||
Sprintf(buf, "interior of %s",
|
||||
Blind ? "a monster" : a_monnam(u.ustuck));
|
||||
/* when swallowed, we're only called for spots adjacent to hero,
|
||||
and blindness doesn't prevent hero from feeling what holds him */
|
||||
Sprintf(buf, "interior of %s", a_monnam(u.ustuck));
|
||||
pm = u.ustuck->data;
|
||||
} else if (glyph_is_monster(glyph)) {
|
||||
bhitpos.x = x;
|
||||
@@ -377,6 +382,7 @@ char *buf, *monbuf;
|
||||
Strcpy(buf, defsyms[trap_to_defsym(tnum)].explanation);
|
||||
} else if (glyph_is_warning(glyph)) {
|
||||
int warnindx = glyph_to_warning(glyph);
|
||||
|
||||
Strcpy(buf, def_warnsyms[warnindx].explanation);
|
||||
} else if (!glyph_is_cmap(glyph)) {
|
||||
Strcpy(buf, "unexplored area");
|
||||
@@ -411,6 +417,11 @@ char *buf, *monbuf;
|
||||
if (!levl[x][y].seenv) {
|
||||
Strcpy(buf, "unexplored");
|
||||
break;
|
||||
} else if (Underwater && !Is_waterlevel(&u.uz)) {
|
||||
/* "unknown" == previously mapped but not visible when
|
||||
submerged; better terminology appreciated... */
|
||||
Strcpy(buf, (distu(x, y) <= 2) ? "land" : "unknown");
|
||||
break;
|
||||
} else if (levl[x][y].typ == STONE || levl[x][y].typ == SCORR) {
|
||||
Strcpy(buf, "stone");
|
||||
break;
|
||||
@@ -515,10 +526,9 @@ boolean user_typed_name, without_asking;
|
||||
/*
|
||||
* If the object is named, then the name is the alternate description;
|
||||
* otherwise, the result of makesingular() applied to the name is.
|
||||
* This
|
||||
* isn't strictly optimal, but named objects of interest to the user
|
||||
* will usually be found under their name, rather than under their
|
||||
* object type, so looking for a singular form is pointless.
|
||||
* This isn't strictly optimal, but named objects of interest to the
|
||||
* user will usually be found under their name, rather than under
|
||||
* their object type, so looking for a singular form is pointless.
|
||||
*/
|
||||
if (!alt)
|
||||
alt = makesingular(dbase_str);
|
||||
@@ -554,10 +564,11 @@ boolean user_typed_name, without_asking;
|
||||
if (!(ep = index(buf, '\n')))
|
||||
goto bad_data_file;
|
||||
(void) strip_newline((ep > buf) ? ep - 1 : ep);
|
||||
/* if we match a key that begins with "~", skip this entry */
|
||||
/* if we match a key that begins with "~", skip
|
||||
this entry */
|
||||
chk_skip = (*buf == '~') ? 1 : 0;
|
||||
if ((pass == 0 && pmatch(&buf[chk_skip], dbase_str)) ||
|
||||
(pass == 1 && alt && pmatch(&buf[chk_skip], alt))) {
|
||||
if ((pass == 0 && pmatch(&buf[chk_skip], dbase_str))
|
||||
|| (pass == 1 && alt && pmatch(&buf[chk_skip], alt))) {
|
||||
if (chk_skip) {
|
||||
skipping_entry = TRUE;
|
||||
continue;
|
||||
@@ -581,7 +592,7 @@ boolean user_typed_name, without_asking;
|
||||
if (sscanf(buf, "%ld,%d\n", &entry_offset, &entry_count) < 2) {
|
||||
bad_data_file:
|
||||
impossible("'data' file in wrong format or corrupted");
|
||||
/* window will exist if we came here from below via 'goto' */
|
||||
/* window will exist if came here from below via 'goto' */
|
||||
if (datawin != WIN_ERR)
|
||||
destroy_nhwindow(datawin);
|
||||
(void) dlb_fclose(fp);
|
||||
@@ -593,6 +604,7 @@ boolean user_typed_name, without_asking;
|
||||
unsigned maxt = strlen("More info about \"\"?");
|
||||
char *entrytext = pass ? alt : dbase_str;
|
||||
char question[BUFSZ];
|
||||
|
||||
if (strlen(entrytext) < BUFSZ - maxt) {
|
||||
Strcpy(question, "More info about \"");
|
||||
Strcat(question, entrytext);
|
||||
@@ -600,11 +612,11 @@ boolean user_typed_name, without_asking;
|
||||
}
|
||||
if (yn(question) == 'y')
|
||||
yes_to_moreinfo = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (user_typed_name || without_asking || yes_to_moreinfo) {
|
||||
if (dlb_fseek(fp,
|
||||
(long) txt_offset + entry_offset, SEEK_SET) < 0) {
|
||||
if (dlb_fseek(fp, (long) txt_offset + entry_offset,
|
||||
SEEK_SET) < 0) {
|
||||
pline("? Seek error on 'data' file!");
|
||||
(void) dlb_fclose(fp);
|
||||
return;
|
||||
@@ -636,16 +648,15 @@ int sym;
|
||||
char *out_str;
|
||||
const char **firstmatch;
|
||||
{
|
||||
boolean need_to_look = FALSE;
|
||||
int glyph = NO_GLYPH;
|
||||
static const char mon_interior[] = "the interior of a monster",
|
||||
unreconnoitered[] = "unreconnoitered";
|
||||
static char look_buf[BUFSZ];
|
||||
char prefix[BUFSZ];
|
||||
int found = 0; /* count of matching syms found */
|
||||
int i, alt_i;
|
||||
int skipped_venom = 0;
|
||||
boolean hit_trap;
|
||||
int i, alt_i, glyph = NO_GLYPH,
|
||||
skipped_venom = 0, found = 0; /* count of matching syms found */
|
||||
boolean hit_trap, need_to_look = FALSE,
|
||||
submerged = (Underwater && !Is_waterlevel(&u.uz));
|
||||
const char *x_str;
|
||||
static const char *mon_interior = "the interior of a monster";
|
||||
|
||||
if (looked) {
|
||||
int oc;
|
||||
@@ -665,59 +676,91 @@ const char **firstmatch;
|
||||
*/
|
||||
|
||||
/*
|
||||
* Special case: if identifying from the screen, and we're swallowed,
|
||||
* and looking at something other than our own symbol, then just say
|
||||
* "the interior of a monster".
|
||||
* Handle restricted vision range (limited to adjacent spots when
|
||||
* swallowed or underwater) cases first.
|
||||
*
|
||||
* 3.6.0 listed anywhere on map, other than self, as "interior
|
||||
* of a monster" when swallowed, and non-adjacent water or
|
||||
* non-water anywhere as "dark part of a room" when underwater.
|
||||
* "unreconnoitered" is an attempt to convey "even if you knew
|
||||
* what was there earlier, you don't know what is there in the
|
||||
* current circumstance".
|
||||
*
|
||||
* (Note: 'self' will always be visible when swallowed so we don't
|
||||
* need special swallow handling for <ux,uy>.
|
||||
* Another note: for '#terrain' without monsters, u.uswallow and
|
||||
* submerged will always both be False and skip this code.)
|
||||
*/
|
||||
if (u.uswallow && looked
|
||||
&& (is_swallow_sym(sym) || (int) showsyms[S_stone] == sym)) {
|
||||
x_str = 0;
|
||||
if (looked && (u.uswallow || submerged) && distu(cc.x, cc.y) > 2) {
|
||||
x_str = unreconnoitered;
|
||||
need_to_look = FALSE;
|
||||
} else if (looked && u.uswallow && is_swallow_sym(sym)) {
|
||||
x_str = mon_interior;
|
||||
need_to_look = TRUE; /* for specific monster type */
|
||||
}
|
||||
if (x_str) {
|
||||
/* we know 'found' is zero here, but guard against some other
|
||||
special case being inserted ahead of us someday */
|
||||
if (!found) {
|
||||
Sprintf(out_str, "%s%s", prefix, mon_interior);
|
||||
*firstmatch = mon_interior;
|
||||
Sprintf(out_str, "%s%s", prefix, x_str);
|
||||
*firstmatch = x_str;
|
||||
found++;
|
||||
} else {
|
||||
found += append_str(out_str, mon_interior);
|
||||
found += append_str(out_str, x_str); /* not 'an(x_str)' */
|
||||
}
|
||||
need_to_look = TRUE;
|
||||
goto didlook;
|
||||
/* for is_swallow_sym(), we want to list the current symbol's
|
||||
other possibilities (wand for '/', throne for '\\', &c) so
|
||||
don't jump to the end for the x_str==mon_interior case */
|
||||
if (x_str == unreconnoitered)
|
||||
goto didlook;
|
||||
}
|
||||
|
||||
/* Check for monsters */
|
||||
for (i = 0; i < MAXMCLASSES; i++) {
|
||||
if (sym == (looked ? showsyms[i + SYM_OFF_M] : def_monsyms[i].sym)
|
||||
&& def_monsyms[i].explain) {
|
||||
need_to_look = TRUE;
|
||||
if (!found) {
|
||||
Sprintf(out_str, "%s%s", prefix, an(def_monsyms[i].explain));
|
||||
*firstmatch = def_monsyms[i].explain;
|
||||
found++;
|
||||
} else {
|
||||
found += append_str(out_str, an(def_monsyms[i].explain));
|
||||
if (!iflags.terrainmode || (iflags.terrainmode & TER_MON) != 0) {
|
||||
for (i = 0; i < MAXMCLASSES; i++) {
|
||||
if (sym == (looked ? showsyms[i + SYM_OFF_M] : def_monsyms[i].sym)
|
||||
&& def_monsyms[i].explain) {
|
||||
need_to_look = TRUE;
|
||||
if (!found) {
|
||||
Sprintf(out_str, "%s%s",
|
||||
prefix, an(def_monsyms[i].explain));
|
||||
*firstmatch = def_monsyms[i].explain;
|
||||
found++;
|
||||
} else {
|
||||
found += append_str(out_str, an(def_monsyms[i].explain));
|
||||
}
|
||||
}
|
||||
}
|
||||
/* handle '@' as a special case if it refers to you and you're
|
||||
playing a character which isn't normally displayed by that
|
||||
symbol; firstmatch is assumed to already be set for '@' */
|
||||
if ((looked ? (sym == showsyms[S_HUMAN + SYM_OFF_M]
|
||||
&& cc.x == u.ux && cc.y == u.uy)
|
||||
: (sym == def_monsyms[S_HUMAN].sym && !flags.showrace))
|
||||
&& !(Race_if(PM_HUMAN) || Race_if(PM_ELF)) && !Upolyd)
|
||||
found += append_str(out_str, "you"); /* tack on "or you" */
|
||||
}
|
||||
/* handle '@' as a special case if it refers to you and you're
|
||||
playing a character which isn't normally displayed by that
|
||||
symbol; firstmatch is assumed to already be set for '@' */
|
||||
if ((looked ? (sym == showsyms[S_HUMAN + SYM_OFF_M]
|
||||
&& cc.x == u.ux && cc.y == u.uy)
|
||||
: (sym == def_monsyms[S_HUMAN].sym && !flags.showrace))
|
||||
&& !(Race_if(PM_HUMAN) || Race_if(PM_ELF)) && !Upolyd)
|
||||
found += append_str(out_str, "you"); /* tack on "or you" */
|
||||
|
||||
/* Now check for objects */
|
||||
for (i = 1; i < MAXOCLASSES; i++) {
|
||||
if (sym == (looked ? showsyms[i + SYM_OFF_O] : def_oc_syms[i].sym)) {
|
||||
need_to_look = TRUE;
|
||||
if (looked && i == VENOM_CLASS) {
|
||||
skipped_venom++;
|
||||
continue;
|
||||
}
|
||||
if (!found) {
|
||||
Sprintf(out_str, "%s%s", prefix, an(def_oc_syms[i].explain));
|
||||
*firstmatch = def_oc_syms[i].explain;
|
||||
found++;
|
||||
} else {
|
||||
found += append_str(out_str, an(def_oc_syms[i].explain));
|
||||
if (!iflags.terrainmode || (iflags.terrainmode & TER_OBJ) != 0) {
|
||||
for (i = 1; i < MAXOCLASSES; i++) {
|
||||
if (sym == (looked ? showsyms[i + SYM_OFF_O]
|
||||
: def_oc_syms[i].sym)
|
||||
|| (looked && i == ROCK_CLASS && glyph_is_statue(glyph))) {
|
||||
need_to_look = TRUE;
|
||||
if (looked && i == VENOM_CLASS) {
|
||||
skipped_venom++;
|
||||
continue;
|
||||
}
|
||||
if (!found) {
|
||||
Sprintf(out_str, "%s%s",
|
||||
prefix, an(def_oc_syms[i].explain));
|
||||
*firstmatch = def_oc_syms[i].explain;
|
||||
found++;
|
||||
} else {
|
||||
found += append_str(out_str, an(def_oc_syms[i].explain));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -741,13 +784,15 @@ const char **firstmatch;
|
||||
/* when sym is the default background character, we process
|
||||
i == 0 three times: unexplored, stone, dark part of a room */
|
||||
if (alt_i < 2) {
|
||||
x_str = !alt_i++ ? "unexplored" : "stone";
|
||||
x_str = !alt_i++ ? "unexplored" : submerged ? "unknown" : "stone";
|
||||
i = 0; /* for second iteration, undo loop increment */
|
||||
/* alt_i is now 1 or 2 */
|
||||
} else {
|
||||
if (alt_i++ == 2)
|
||||
i = 0; /* undo loop increment */
|
||||
x_str = defsyms[i].explanation;
|
||||
if (submerged && !strcmp(x_str, defsyms[0].explanation))
|
||||
x_str = "land"; /* replace "dark part of a room" */
|
||||
/* alt_i is now 3 or more and no longer of interest */
|
||||
}
|
||||
if (sym == (looked ? showsyms[i] : defsyms[i].sym) && *x_str) {
|
||||
@@ -757,6 +802,7 @@ const char **firstmatch;
|
||||
int article = strstri(x_str, " of a room") ? 2
|
||||
: !(alt_i <= 2
|
||||
|| strcmp(x_str, "air") == 0
|
||||
|| strcmp(x_str, "land") == 0
|
||||
|| strcmp(x_str, "water") == 0);
|
||||
|
||||
if (!found) {
|
||||
@@ -770,7 +816,7 @@ const char **firstmatch;
|
||||
}
|
||||
*firstmatch = x_str;
|
||||
found++;
|
||||
} else if (!u.uswallow && !(hit_trap && is_cmap_trap(i))
|
||||
} else if (!(hit_trap && is_cmap_trap(i))
|
||||
&& !(found >= 3 && is_cmap_drawbridge(i))
|
||||
/* don't mention vibrating square outside of Gehennom
|
||||
unless this happens to be one (hallucination?) */
|
||||
|
||||
+203
-167
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 pickup.c $NHDT-Date: 1453591408 2016/01/23 23:23:28 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.169 $ */
|
||||
/* NetHack 3.6 pickup.c $NHDT-Date: 1461919368 2016/04/29 08:42:48 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.177 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
#define CONTAINED_SYM '>' /* from invent.c */
|
||||
|
||||
STATIC_DCL void FDECL(simple_look, (struct obj *, BOOLEAN_P));
|
||||
STATIC_DCL boolean
|
||||
FDECL(query_classes, (char *, boolean *, boolean *, const char *,
|
||||
struct obj *, BOOLEAN_P, int *));
|
||||
STATIC_DCL boolean FDECL(query_classes, (char *, boolean *, boolean *,
|
||||
const char *, struct obj *,
|
||||
BOOLEAN_P, int *));
|
||||
STATIC_DCL boolean FDECL(fatal_corpse_mistake, (struct obj *, BOOLEAN_P));
|
||||
STATIC_DCL void FDECL(check_here, (BOOLEAN_P));
|
||||
STATIC_DCL boolean FDECL(n_or_more, (struct obj *));
|
||||
@@ -21,6 +21,7 @@ STATIC_DCL boolean FDECL(all_but_uchain, (struct obj *));
|
||||
#if 0 /* not used */
|
||||
STATIC_DCL boolean FDECL(allow_cat_no_uchain, (struct obj *));
|
||||
#endif
|
||||
STATIC_DCL boolean FDECL(autopick_testobj, (struct obj *));
|
||||
STATIC_DCL int FDECL(autopick, (struct obj *, int, menu_item **));
|
||||
STATIC_DCL int FDECL(count_categories, (struct obj *, int));
|
||||
STATIC_DCL long FDECL(carry_count, (struct obj *, struct obj *, long,
|
||||
@@ -33,21 +34,21 @@ STATIC_PTR int FDECL(out_container, (struct obj *));
|
||||
STATIC_DCL void FDECL(removed_from_icebox, (struct obj *));
|
||||
STATIC_DCL long FDECL(mbag_item_gone, (int, struct obj *));
|
||||
STATIC_DCL void FDECL(observe_quantum_cat, (struct obj *));
|
||||
STATIC_DCL void NDECL(explain_container_prompt);
|
||||
STATIC_DCL void FDECL(explain_container_prompt, (BOOLEAN_P));
|
||||
STATIC_DCL int FDECL(traditional_loot, (BOOLEAN_P));
|
||||
STATIC_DCL int FDECL(menu_loot, (int, BOOLEAN_P));
|
||||
STATIC_DCL char FDECL(in_or_out_menu, (const char *, struct obj *, BOOLEAN_P,
|
||||
BOOLEAN_P, BOOLEAN_P));
|
||||
BOOLEAN_P, BOOLEAN_P, BOOLEAN_P));
|
||||
STATIC_DCL int FDECL(container_at, (int, int, BOOLEAN_P));
|
||||
STATIC_DCL boolean FDECL(able_to_loot, (int, int, BOOLEAN_P));
|
||||
STATIC_DCL boolean NDECL(reverse_loot);
|
||||
STATIC_DCL boolean FDECL(mon_beside, (int, int));
|
||||
STATIC_DCL int FDECL(do_loot_cont, (struct obj **));
|
||||
STATIC_DCL int FDECL(do_loot_cont, (struct obj **, int, int));
|
||||
STATIC_DCL void FDECL(tipcontainer, (struct obj *));
|
||||
|
||||
/* define for query_objlist() and autopickup() */
|
||||
#define FOLLOW(curr, flags) \
|
||||
(((flags) &BY_NEXTHERE) ? (curr)->nexthere : (curr)->nobj)
|
||||
(((flags) & BY_NEXTHERE) ? (curr)->nexthere : (curr)->nobj)
|
||||
|
||||
/*
|
||||
* How much the weight of the given container will change when the given
|
||||
@@ -62,10 +63,11 @@ STATIC_DCL void FDECL(tipcontainer, (struct obj *));
|
||||
/* if you can figure this out, give yourself a hearty pat on the back... */
|
||||
#define GOLD_CAPACITY(w, n) (((w) * -100L) - ((n) + 50L) - 1L)
|
||||
|
||||
/* A variable set in use_container(), to be used by the callback routines */
|
||||
/* in_container() and out_container() from askchain() and use_container(). */
|
||||
/* Also used by menu_loot() and container_gone(). */
|
||||
/* A variable set in use_container(), to be used by the callback routines
|
||||
in_container() and out_container() from askchain() and use_container().
|
||||
Also used by menu_loot() and container_gone(). */
|
||||
static NEARDATA struct obj *current_container;
|
||||
static NEARDATA boolean abort_looting;
|
||||
#define Icebox (current_container->otyp == ICE_BOX)
|
||||
|
||||
static const char
|
||||
@@ -220,9 +222,7 @@ int *menu_on_demand;
|
||||
oclasses[oclassct] = '\0';
|
||||
} else {
|
||||
if (!where)
|
||||
where =
|
||||
!strcmp(action, "pick up")
|
||||
? "here"
|
||||
where = !strcmp(action, "pick up") ? "here"
|
||||
: !strcmp(action, "take out") ? "inside" : "";
|
||||
if (*where)
|
||||
There("are no %c's %s.", sym, where);
|
||||
@@ -383,6 +383,7 @@ struct obj *obj;
|
||||
|
||||
if (Role_if(PM_PRIEST))
|
||||
obj->bknown = TRUE;
|
||||
|
||||
/*
|
||||
* There are three types of filters possible and the first and
|
||||
* third can have more than one entry:
|
||||
@@ -399,6 +400,7 @@ struct obj *obj;
|
||||
* in accepting all scrolls and potions regardless of bless/curse
|
||||
* state plus all blessed non-scroll, non-potion objects.)
|
||||
*/
|
||||
|
||||
/* if class is expected but obj's class is not in the list, reject */
|
||||
if (class_filter && !index(valid_menu_classes, obj->oclass))
|
||||
return FALSE;
|
||||
@@ -463,7 +465,7 @@ int what; /* should be a long */
|
||||
int i, n, res, count, n_tried = 0, n_picked = 0;
|
||||
menu_item *pick_list = (menu_item *) 0;
|
||||
boolean autopickup = what > 0;
|
||||
struct obj *objchain;
|
||||
struct obj **objchain_p;
|
||||
int traverse_how;
|
||||
|
||||
/* we might have arrived here while fainted or sleeping, via
|
||||
@@ -480,7 +482,8 @@ int what; /* should be a long */
|
||||
count = 0;
|
||||
|
||||
if (!u.uswallow) {
|
||||
struct trap *ttmp = t_at(u.ux, u.uy);
|
||||
struct trap *ttmp;
|
||||
|
||||
/* no auto-pick if no-pick move, nothing there, or in a pool */
|
||||
if (autopickup && (context.nopick || !OBJ_AT(u.ux, u.uy)
|
||||
|| (is_pool(u.ux, u.uy) && !Underwater)
|
||||
@@ -488,11 +491,11 @@ int what; /* should be a long */
|
||||
read_engr_at(u.ux, u.uy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* no pickup if levitating & not on air or water level */
|
||||
if (!can_reach_floor(TRUE)) {
|
||||
if ((multi && !context.run) || (autopickup && !flags.pickup)
|
||||
|| (ttmp && uteetering_at_seen_pit(ttmp)))
|
||||
|| ((ttmp = t_at(u.ux, u.uy)) != 0
|
||||
&& uteetering_at_seen_pit(ttmp)))
|
||||
read_engr_at(u.ux, u.uy);
|
||||
return 0;
|
||||
}
|
||||
@@ -520,10 +523,10 @@ int what; /* should be a long */
|
||||
|
||||
add_valid_menu_class(0); /* reset */
|
||||
if (!u.uswallow) {
|
||||
objchain = level.objects[u.ux][u.uy];
|
||||
objchain_p = &level.objects[u.ux][u.uy];
|
||||
traverse_how = BY_NEXTHERE;
|
||||
} else {
|
||||
objchain = u.ustuck->minvent;
|
||||
objchain_p = &u.ustuck->minvent;
|
||||
traverse_how = 0; /* nobj */
|
||||
}
|
||||
/*
|
||||
@@ -533,29 +536,29 @@ int what; /* should be a long */
|
||||
* to make things less confusing.
|
||||
*/
|
||||
if (autopickup) {
|
||||
n = autopick(objchain, traverse_how, &pick_list);
|
||||
n = autopick(*objchain_p, traverse_how, &pick_list);
|
||||
goto menu_pickup;
|
||||
}
|
||||
|
||||
if (flags.menu_style != MENU_TRADITIONAL || iflags.menu_requested) {
|
||||
/* use menus exclusively */
|
||||
traverse_how |= AUTOSELECT_SINGLE | INVORDER_SORT;
|
||||
if (count) { /* looking for N of something */
|
||||
char qbuf[QBUFSZ];
|
||||
|
||||
Sprintf(qbuf, "Pick %d of what?", count);
|
||||
val_for_n_or_more = count; /* set up callback selector */
|
||||
n = query_objlist(qbuf, objchain, traverse_how | AUTOSELECT_SINGLE
|
||||
| INVORDER_SORT,
|
||||
n = query_objlist(qbuf, objchain_p, traverse_how,
|
||||
&pick_list, PICK_ONE, n_or_more);
|
||||
/* correct counts, if any given */
|
||||
for (i = 0; i < n; i++)
|
||||
pick_list[i].count = count;
|
||||
} else {
|
||||
n = query_objlist("Pick up what?", objchain,
|
||||
traverse_how | AUTOSELECT_SINGLE | INVORDER_SORT
|
||||
| FEEL_COCKATRICE,
|
||||
n = query_objlist("Pick up what?", objchain_p,
|
||||
(traverse_how | FEEL_COCKATRICE),
|
||||
&pick_list, PICK_ANY, all_but_uchain);
|
||||
}
|
||||
|
||||
menu_pickup:
|
||||
n_tried = n;
|
||||
for (n_picked = i = 0; i < n; i++) {
|
||||
@@ -581,13 +584,12 @@ int what; /* should be a long */
|
||||
selective = FALSE; /* ask for each item */
|
||||
|
||||
/* check for more than one object */
|
||||
for (obj = objchain; obj;
|
||||
obj = (traverse_how == BY_NEXTHERE) ? obj->nexthere : obj->nobj)
|
||||
for (obj = *objchain_p; obj; obj = FOLLOW(obj, traverse_how))
|
||||
ct++;
|
||||
|
||||
if (ct == 1 && count) {
|
||||
/* if only one thing, then pick it */
|
||||
obj = objchain;
|
||||
obj = *objchain_p;
|
||||
lcount = min(obj->quan, (long) count);
|
||||
n_tried++;
|
||||
if (pickup_object(obj, lcount, FALSE) > 0)
|
||||
@@ -599,13 +601,14 @@ int what; /* should be a long */
|
||||
|
||||
There("are %s objects here.", (ct <= 10) ? "several" : "many");
|
||||
if (!query_classes(oclasses, &selective, &all_of_a_type,
|
||||
"pick up", objchain,
|
||||
traverse_how == BY_NEXTHERE, &via_menu)) {
|
||||
"pick up", *objchain_p,
|
||||
(traverse_how & BY_NEXTHERE) ? TRUE : FALSE,
|
||||
&via_menu)) {
|
||||
if (!via_menu)
|
||||
return 0;
|
||||
n = query_objlist("Pick up what?", objchain,
|
||||
traverse_how
|
||||
| (selective ? 0 : INVORDER_SORT),
|
||||
if (selective)
|
||||
traverse_how |= INVORDER_SORT;
|
||||
n = query_objlist("Pick up what?", objchain_p, traverse_how,
|
||||
&pick_list, PICK_ANY,
|
||||
(via_menu == -2) ? allow_all
|
||||
: allow_category);
|
||||
@@ -613,16 +616,12 @@ int what; /* should be a long */
|
||||
}
|
||||
}
|
||||
|
||||
for (obj = objchain; obj; obj = obj2) {
|
||||
if (traverse_how == BY_NEXTHERE)
|
||||
obj2 = obj->nexthere; /* perhaps obj will be picked up */
|
||||
else
|
||||
obj2 = obj->nobj;
|
||||
lcount = -1L;
|
||||
|
||||
for (obj = *objchain_p; obj; obj = obj2) {
|
||||
obj2 = FOLLOW(obj, traverse_how);
|
||||
if (!selective && oclasses[0] && !index(oclasses, obj->oclass))
|
||||
continue;
|
||||
|
||||
lcount = -1L;
|
||||
if (!all_of_a_type) {
|
||||
char qbuf[BUFSZ];
|
||||
|
||||
@@ -647,7 +646,7 @@ int what; /* should be a long */
|
||||
lcount = (long) yn_number;
|
||||
if (lcount > obj->quan)
|
||||
lcount = obj->quan;
|
||||
/* fall thru */
|
||||
/*FALLTHRU*/
|
||||
default: /* 'y' */
|
||||
break;
|
||||
}
|
||||
@@ -700,6 +699,29 @@ boolean grab; /* forced pickup, rather than forced leave behind? */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
boolean
|
||||
autopick_testobj(otmp)
|
||||
struct obj *otmp;
|
||||
{
|
||||
const char *otypes = flags.pickup_types;
|
||||
/* pick if in pickup_types and not unpaid item in shop */
|
||||
boolean pickit = ((!*otypes || index(otypes, otmp->oclass))
|
||||
&& !(otmp->where == OBJ_FLOOR
|
||||
&& !otmp->no_charge
|
||||
&& isok(otmp->ox, otmp->oy)
|
||||
&& costly_spot(otmp->ox, otmp->oy)));
|
||||
/* check for "always pick up */
|
||||
if (!pickit)
|
||||
pickit = is_autopickup_exception(otmp, TRUE);
|
||||
/* then for "never pick up */
|
||||
if (pickit)
|
||||
pickit = !is_autopickup_exception(otmp, FALSE);
|
||||
/* pickup_thrown overrides pickup_types and exceptions */
|
||||
if (!pickit)
|
||||
pickit = (flags.pickup_thrown && otmp->was_thrown);
|
||||
return pickit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pick from the given list using flags.pickup_types. Return the number
|
||||
* of items picked (not counts). Create an array that returns pointers
|
||||
@@ -716,42 +738,17 @@ menu_item **pick_list; /* list of objects and counts to pick up */
|
||||
menu_item *pi; /* pick item */
|
||||
struct obj *curr;
|
||||
int n;
|
||||
boolean pickit;
|
||||
const char *otypes = flags.pickup_types;
|
||||
|
||||
/* first count the number of eligible items */
|
||||
for (n = 0, curr = olist; curr; curr = FOLLOW(curr, follow)) {
|
||||
/* pick if in pickup_types and not unpaid item in shop */
|
||||
pickit = ((!*otypes || index(otypes, curr->oclass))
|
||||
&& !(curr->where == OBJ_FLOOR
|
||||
&& !curr->no_charge
|
||||
&& isok(curr->ox, curr->oy)
|
||||
&& costly_spot(curr->ox, curr->oy)));
|
||||
/* check for "always pick up */
|
||||
if (!pickit)
|
||||
pickit = is_autopickup_exception(curr, TRUE);
|
||||
/* then for "never pick up */
|
||||
if (pickit)
|
||||
pickit = !is_autopickup_exception(curr, FALSE);
|
||||
/* pickup_thrown overrides pickup_types and exceptions */
|
||||
if (!pickit)
|
||||
pickit = (flags.pickup_thrown && curr->was_thrown);
|
||||
/* finally, do we count this object? */
|
||||
if (pickit)
|
||||
if (autopick_testobj(curr))
|
||||
++n;
|
||||
}
|
||||
|
||||
if (n) {
|
||||
*pick_list = pi = (menu_item *) alloc(sizeof (menu_item) * n);
|
||||
for (n = 0, curr = olist; curr; curr = FOLLOW(curr, follow)) {
|
||||
pickit = (!*otypes || index(otypes, curr->oclass));
|
||||
if (!pickit)
|
||||
pickit = is_autopickup_exception(curr, TRUE);
|
||||
if (pickit)
|
||||
pickit = !is_autopickup_exception(curr, FALSE);
|
||||
if (!pickit)
|
||||
pickit = (flags.pickup_thrown && curr->was_thrown);
|
||||
if (pickit) {
|
||||
if (autopick_testobj(curr)) {
|
||||
pi[n].item.a_obj = curr;
|
||||
pi[n].count = curr->quan;
|
||||
n++;
|
||||
@@ -778,11 +775,12 @@ menu_item **pick_list; /* list of objects and counts to pick up */
|
||||
* SIGNAL_NOMENU - Return -1 rather than 0 if nothing passes "allow".
|
||||
* SIGNAL_ESCAPE - Return -1 rather than 0 if player uses ESC to
|
||||
* pick nothing.
|
||||
* FEEL_COCKATRICE - touch corpse.
|
||||
*/
|
||||
int
|
||||
query_objlist(qstr, olist, qflags, pick_list, how, allow)
|
||||
query_objlist(qstr, olist_p, qflags, pick_list, how, allow)
|
||||
const char *qstr; /* query string */
|
||||
struct obj *olist; /* the list to pick from */
|
||||
struct obj **olist_p; /* the list to pick from */
|
||||
int qflags; /* options to control the query */
|
||||
menu_item **pick_list; /* return list of items picked */
|
||||
int how; /* type of query */
|
||||
@@ -790,12 +788,12 @@ boolean FDECL((*allow), (OBJ_P)); /* allow function */
|
||||
{
|
||||
int i, n, actualn;
|
||||
winid win;
|
||||
struct obj *curr, *last, fake_hero_object;
|
||||
struct obj **oarray;
|
||||
struct obj *curr, *last, fake_hero_object, *olist = *olist_p;
|
||||
char *pack;
|
||||
anything any;
|
||||
boolean printed_type_name, sorted = (qflags & INVORDER_SORT) != 0,
|
||||
engulfer = (qflags & INCLUDE_HERO) != 0;
|
||||
boolean printed_type_name, first,
|
||||
sorted = (qflags & INVORDER_SORT) != 0,
|
||||
engulfer = (qflags & INCLUDE_HERO) != 0;
|
||||
|
||||
*pick_list = (menu_item *) 0;
|
||||
if (!olist && !engulfer)
|
||||
@@ -818,27 +816,26 @@ boolean FDECL((*allow), (OBJ_P)); /* allow function */
|
||||
return (qflags & SIGNAL_NOMENU) ? -1 : 0;
|
||||
|
||||
if (n == 1 && (qflags & AUTOSELECT_SINGLE)) {
|
||||
*pick_list = (menu_item *) alloc(sizeof(menu_item));
|
||||
*pick_list = (menu_item *) alloc(sizeof (menu_item));
|
||||
(*pick_list)->item.a_obj = last;
|
||||
(*pick_list)->count = last->quan;
|
||||
return 1;
|
||||
}
|
||||
|
||||
oarray = objarr_init(actualn);
|
||||
/* Add objects to the array */
|
||||
i = 0;
|
||||
for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
|
||||
if ((*allow)(curr)) {
|
||||
objarr_set(curr, i++, oarray, (flags.sortloot == 'f'
|
||||
|| (flags.sortloot == 'l'
|
||||
&& !(qflags & USE_INVLET))));
|
||||
}
|
||||
if (sorted || flags.sortloot != 'n') {
|
||||
sortloot(&olist,
|
||||
(((flags.sortloot == 'f'
|
||||
|| (flags.sortloot == 'l' && !(qflags & USE_INVLET)))
|
||||
? SORTLOOT_LOOT
|
||||
: (qflags & USE_INVLET) ? SORTLOOT_INVLET : 0)
|
||||
| (flags.sortpack ? SORTLOOT_PACK : 0)),
|
||||
(qflags & BY_NEXTHERE) ? TRUE : FALSE);
|
||||
*olist_p = olist;
|
||||
}
|
||||
|
||||
win = create_nhwindow(NHW_MENU);
|
||||
start_menu(win);
|
||||
any = zeroany;
|
||||
|
||||
/*
|
||||
* Run through the list and add the objects to the menu. If
|
||||
* INVORDER_SORT is set, we'll run through the list once for
|
||||
@@ -846,38 +843,41 @@ boolean FDECL((*allow), (OBJ_P)); /* allow function */
|
||||
* be called once per object in the list.
|
||||
*/
|
||||
pack = flags.inv_order;
|
||||
first = TRUE;
|
||||
do {
|
||||
printed_type_name = FALSE;
|
||||
for (i = 0; i < actualn; i++) {
|
||||
curr = oarray[i];
|
||||
for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
|
||||
if (sorted && curr->oclass != *pack)
|
||||
continue;
|
||||
if ((qflags & FEEL_COCKATRICE) && curr->otyp == CORPSE
|
||||
&& will_feel_cockatrice(curr, FALSE)) {
|
||||
destroy_nhwindow(win); /* stop the menu and revert */
|
||||
(void) look_here(0, FALSE);
|
||||
return 0;
|
||||
}
|
||||
if ((!sorted || curr->oclass == *pack) && (*allow)(curr)) {
|
||||
if ((*allow)(curr)) {
|
||||
/* if sorting, print type name (once only) */
|
||||
if (sorted && !printed_type_name) {
|
||||
any = zeroany;
|
||||
add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
|
||||
let_to_name(*pack, FALSE,
|
||||
(how != PICK_NONE)
|
||||
&& iflags.menu_head_objsym),
|
||||
((how != PICK_NONE)
|
||||
&& iflags.menu_head_objsym)),
|
||||
MENU_UNSELECTED);
|
||||
printed_type_name = TRUE;
|
||||
}
|
||||
|
||||
any.a_obj = curr;
|
||||
add_menu(win, obj_to_glyph(curr), &any,
|
||||
(qflags & USE_INVLET) ? curr->invlet : 0,
|
||||
(qflags & USE_INVLET) ? curr->invlet
|
||||
: (first && curr->oclass == COIN_CLASS) ? '$' : 0,
|
||||
def_oc_syms[(int) objects[curr->otyp].oc_class].sym,
|
||||
ATR_NONE, doname_with_price(curr), MENU_UNSELECTED);
|
||||
first = FALSE;
|
||||
}
|
||||
}
|
||||
pack++;
|
||||
} while (sorted && *pack);
|
||||
free(oarray);
|
||||
|
||||
if (engulfer) {
|
||||
char buf[BUFSZ];
|
||||
@@ -1579,16 +1579,22 @@ int x, y;
|
||||
}
|
||||
|
||||
int
|
||||
do_loot_cont(cobjp)
|
||||
do_loot_cont(cobjp, cindex, ccount)
|
||||
struct obj **cobjp;
|
||||
int cindex, ccount; /* index of this container (1..N), number of them (N) */
|
||||
{
|
||||
struct obj *cobj = *cobjp;
|
||||
|
||||
if (!cobj)
|
||||
return 0;
|
||||
if (cobj->olocked) {
|
||||
pline("%s locked.",
|
||||
cobj->lknown ? "It is" : "Hmmm, it turns out to be");
|
||||
if (ccount < 2)
|
||||
pline("%s locked.",
|
||||
cobj->lknown ? "It is" : "Hmmm, it turns out to be");
|
||||
else if (cobj->lknown)
|
||||
pline("%s is locked.", The(xname(cobj)));
|
||||
else
|
||||
pline("Hmmm, %s turns out to be locked.", the(xname(cobj)));
|
||||
cobj->lknown = 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -1597,17 +1603,18 @@ struct obj **cobjp;
|
||||
if (cobj->otyp == BAG_OF_TRICKS) {
|
||||
int tmp;
|
||||
|
||||
You("carefully open the bag...");
|
||||
You("carefully open %s...", the(xname(cobj)));
|
||||
pline("It develops a huge set of teeth and bites you!");
|
||||
tmp = rnd(10);
|
||||
losehp(Maybe_Half_Phys(tmp), "carnivorous bag", KILLED_BY_AN);
|
||||
makeknown(BAG_OF_TRICKS);
|
||||
abort_looting = TRUE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
You("%sopen %s...", (!cobj->cknown || !cobj->lknown) ? "carefully " : "",
|
||||
the(xname(cobj)));
|
||||
return use_container(cobjp, 0);
|
||||
return use_container(cobjp, 0, (boolean) (cindex < ccount));
|
||||
}
|
||||
|
||||
/* loot a container on the floor or loot saddle from mon. */
|
||||
@@ -1626,6 +1633,8 @@ doloot()
|
||||
boolean prev_loot = FALSE;
|
||||
int num_conts;
|
||||
|
||||
abort_looting = FALSE;
|
||||
|
||||
if (check_capacity((char *) 0)) {
|
||||
/* "Can't do that while carrying so much stuff." */
|
||||
return 0;
|
||||
@@ -1646,7 +1655,6 @@ doloot()
|
||||
cc.y = u.uy;
|
||||
|
||||
lootcont:
|
||||
|
||||
if ((num_conts = container_at(cc.x, cc.y, TRUE)) > 0) {
|
||||
boolean anyfound = FALSE;
|
||||
|
||||
@@ -1676,16 +1684,17 @@ lootcont:
|
||||
destroy_nhwindow(win);
|
||||
|
||||
if (n > 0) {
|
||||
for (i = 0; i < n; i++) {
|
||||
timepassed |= do_loot_cont(&pick_list[i].item.a_obj);
|
||||
if (multi < 0 || !pick_list[i].item.a_obj) {
|
||||
for (i = 1; i <= n; i++) {
|
||||
cobj = pick_list[i - 1].item.a_obj;
|
||||
timepassed |= do_loot_cont(&cobj, i, n);
|
||||
if (abort_looting) {
|
||||
/* chest trap or magic bag explosion or <esc> */
|
||||
free((genericptr_t) pick_list);
|
||||
return 1;
|
||||
return timepassed;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pick_list)
|
||||
free((genericptr_t) pick_list);
|
||||
}
|
||||
if (n != 0)
|
||||
c = 'y';
|
||||
} else {
|
||||
@@ -1702,11 +1711,10 @@ lootcont:
|
||||
continue;
|
||||
anyfound = TRUE;
|
||||
|
||||
timepassed |= do_loot_cont(&cobj);
|
||||
/* might have triggered chest trap or magic bag explosion
|
||||
*/
|
||||
if (multi < 0 || !cobj)
|
||||
return 1;
|
||||
timepassed |= do_loot_cont(&cobj, 1, 1);
|
||||
if (abort_looting)
|
||||
/* chest trap or magic bag explosion or <esc> */
|
||||
return timepassed;
|
||||
}
|
||||
}
|
||||
if (anyfound)
|
||||
@@ -1831,8 +1839,8 @@ reverse_loot()
|
||||
boxdummy = zeroobj, boxdummy.otyp = SPE_WIZARD_LOCK;
|
||||
(void) boxlock(coffers, &boxdummy);
|
||||
}
|
||||
} else if (levl[x][y].looted != T_LOOTED &&
|
||||
(mon = makemon(courtmon(), x, y, NO_MM_FLAGS)) != 0) {
|
||||
} else if (levl[x][y].looted != T_LOOTED
|
||||
&& (mon = makemon(courtmon(), x, y, NO_MM_FLAGS)) != 0) {
|
||||
freeinv(goldob);
|
||||
add_to_minv(mon, goldob);
|
||||
pline("The exchequer accepts your contribution.");
|
||||
@@ -1865,11 +1873,12 @@ boolean *prev_loot;
|
||||
*/
|
||||
if (mtmp && mtmp != u.usteed && (otmp = which_armor(mtmp, W_SADDLE))) {
|
||||
long unwornmask;
|
||||
|
||||
if (passed_info)
|
||||
*passed_info = 1;
|
||||
Sprintf(
|
||||
qbuf, "Do you want to remove the saddle from %s?",
|
||||
x_monnam(mtmp, ARTICLE_THE, (char *) 0, SUPPRESS_SADDLE, FALSE));
|
||||
Sprintf(qbuf, "Do you want to remove the saddle from %s?",
|
||||
x_monnam(mtmp, ARTICLE_THE, (char *) 0,
|
||||
SUPPRESS_SADDLE, FALSE));
|
||||
if ((c = yn_function(qbuf, ynqchars, 'n')) == 'y') {
|
||||
if (nolimbs(youmonst.data)) {
|
||||
You_cant("do that without limbs."); /* not body_part(HAND) */
|
||||
@@ -1877,8 +1886,8 @@ boolean *prev_loot;
|
||||
}
|
||||
if (otmp->cursed) {
|
||||
You("can't. The saddle seems to be stuck to %s.",
|
||||
x_monnam(mtmp, ARTICLE_THE, (char *) 0, SUPPRESS_SADDLE,
|
||||
FALSE));
|
||||
x_monnam(mtmp, ARTICLE_THE, (char *) 0,
|
||||
SUPPRESS_SADDLE, FALSE));
|
||||
/* the attempt costs you time */
|
||||
return 1;
|
||||
}
|
||||
@@ -1897,8 +1906,7 @@ boolean *prev_loot;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* 3.4.0 introduced the ability to pick things up from within
|
||||
swallower's stomach */
|
||||
/* 3.4.0 introduced ability to pick things up from swallower's stomach */
|
||||
if (u.uswallow) {
|
||||
int count = passed_info ? *passed_info : 0;
|
||||
|
||||
@@ -2015,15 +2023,14 @@ register struct obj *obj;
|
||||
(void) snuff_lit(obj);
|
||||
|
||||
if (floor_container && costly_spot(u.ux, u.uy)) {
|
||||
if (obj->oclass == COIN_CLASS) {
|
||||
; /* defer gold until after put-in message */
|
||||
} else if (current_container->no_charge && !obj->unpaid) {
|
||||
/* don't sell when putting the item into your own container */
|
||||
obj->no_charge = 1;
|
||||
} else {
|
||||
/* defer gold until after put-in message */
|
||||
if (obj->oclass != COIN_CLASS) {
|
||||
/* sellobj() will take an unpaid item off the shop bill */
|
||||
was_unpaid = obj->unpaid ? TRUE : FALSE;
|
||||
sellobj_state(SELL_DELIBERATE);
|
||||
/* don't sell when putting the item into your own container,
|
||||
* but handle billing correctly */
|
||||
sellobj_state(current_container->no_charge
|
||||
? SELL_DONTSELL : SELL_DELIBERATE);
|
||||
sellobj(obj, u.ux, u.uy);
|
||||
sellobj_state(SELL_NORMAL);
|
||||
}
|
||||
@@ -2081,7 +2088,7 @@ int
|
||||
ck_bag(obj)
|
||||
struct obj *obj;
|
||||
{
|
||||
return current_container && obj != current_container;
|
||||
return (current_container && obj != current_container);
|
||||
}
|
||||
|
||||
/* Returns: -1 to stop, 1 item was removed, 0 item was not removed. */
|
||||
@@ -2208,14 +2215,14 @@ struct obj *box;
|
||||
pline("%s inside the box is still alive!", Monnam(livecat));
|
||||
(void) christen_monst(livecat, sc);
|
||||
} else {
|
||||
deadcat =
|
||||
mk_named_object(CORPSE, &mons[PM_HOUSECAT], box->ox, box->oy, sc);
|
||||
deadcat = mk_named_object(CORPSE, &mons[PM_HOUSECAT],
|
||||
box->ox, box->oy, sc);
|
||||
if (deadcat) {
|
||||
obj_extract_self(deadcat);
|
||||
(void) add_to_container(box, deadcat);
|
||||
}
|
||||
pline_The("%s inside the box is dead!",
|
||||
Hallucination ? rndmonnam(NULL) : "housecat");
|
||||
Hallucination ? rndmonnam((char *) 0) : "housecat");
|
||||
}
|
||||
box->owt = weight(box);
|
||||
return;
|
||||
@@ -2234,14 +2241,16 @@ int FDECL((*fn), (OBJ_P));
|
||||
}
|
||||
|
||||
STATIC_OVL void
|
||||
explain_container_prompt()
|
||||
explain_container_prompt(more_containers)
|
||||
boolean more_containers;
|
||||
{
|
||||
static const char *const explaintext[] = {
|
||||
"Container actions:", "", " : -- Look: examine contents",
|
||||
" o -- Out: take things out", " i -- In: put things in",
|
||||
" b -- Both: first take things out, then put things in",
|
||||
" r -- Reversed: put things in, then take things out",
|
||||
" s -- Stash: put one item in", " q -- Quit: do nothing",
|
||||
" s -- Stash: put one item in", "",
|
||||
" n -- Next: loot next selected container", " q -- Quit: finished",
|
||||
" ? -- Help: display this text.", "", 0
|
||||
};
|
||||
const char *const *txtpp;
|
||||
@@ -2249,8 +2258,11 @@ explain_container_prompt()
|
||||
|
||||
/* "Do what with <container>? [:oibrsq or ?] (q)" */
|
||||
if ((win = create_nhwindow(NHW_TEXT)) != WIN_ERR) {
|
||||
for (txtpp = explaintext; *txtpp; ++txtpp)
|
||||
for (txtpp = explaintext; *txtpp; ++txtpp) {
|
||||
if (!more_containers && !strncmp(*txtpp, " n ", 3))
|
||||
continue;
|
||||
putstr(win, 0, *txtpp);
|
||||
}
|
||||
display_nhwindow(win, FALSE);
|
||||
destroy_nhwindow(win);
|
||||
}
|
||||
@@ -2272,9 +2284,10 @@ u_handsy()
|
||||
static const char stashable[] = { ALLOW_COUNT, COIN_CLASS, ALL_CLASSES, 0 };
|
||||
|
||||
int
|
||||
use_container(objp, held)
|
||||
use_container(objp, held, more_containers)
|
||||
struct obj **objp;
|
||||
int held;
|
||||
boolean more_containers; /* True iff #loot multiple and this isn't last one */
|
||||
{
|
||||
struct obj *curr, *otmp, *obj = *objp;
|
||||
boolean quantum_cat, cursed_mbag, loot_out, loot_in, loot_in_first,
|
||||
@@ -2282,6 +2295,7 @@ int held;
|
||||
char c, emptymsg[BUFSZ], qbuf[QBUFSZ], pbuf[QBUFSZ], xbuf[QBUFSZ];
|
||||
int used = 0;
|
||||
|
||||
abort_looting = FALSE;
|
||||
emptymsg[0] = '\0';
|
||||
|
||||
if (!u_handsy())
|
||||
@@ -2304,12 +2318,15 @@ int held;
|
||||
multi_reason = "opening a container";
|
||||
nomovemsg = "";
|
||||
}
|
||||
abort_looting = TRUE;
|
||||
return 1;
|
||||
}
|
||||
obj->lknown = 1;
|
||||
|
||||
current_container = obj; /* for use by in/out_container */
|
||||
/* from here on out, all early returns go through containerdone */
|
||||
/*
|
||||
* From here on out, all early returns go through 'containerdone:'.
|
||||
*/
|
||||
|
||||
/* check for Schroedinger's Cat */
|
||||
quantum_cat = SchroedingersBox(current_container);
|
||||
@@ -2355,17 +2372,20 @@ int held;
|
||||
* inventory is empty--taking out could alter that;
|
||||
* include do-both-reversed when 'i' is available,
|
||||
* even if container is empty--for similar reason;
|
||||
* always include the quit choice ('q').
|
||||
* include the next container choice ('n') when
|
||||
* relevant, and make it the default;
|
||||
* always include the quit choice ('q'), and make
|
||||
* it the default if there's no next containter;
|
||||
* include the help choice (" or ?") if `cmdassist'
|
||||
* run-time option is set;
|
||||
* (Player can pick any of (o,i,b,r,s,?) even when
|
||||
* (Player can pick any of (o,i,b,r,n,s,?) even when
|
||||
* they're not listed among the available actions.)
|
||||
*
|
||||
* Do what with <the/your/Shk's container>? [:oibrsq or ?] (q)
|
||||
* Do what with <the/your/Shk's container>? [:oibrs nq or ?] (q)
|
||||
* or
|
||||
* <The/Your/Shk's container> is empty. Do what with it? [:irsq or ?]
|
||||
* <The/Your/Shk's container> is empty. Do what with it? [:irs nq or ?]
|
||||
*/
|
||||
for (;;) { /* repeats if '?' or ":' gets chosen */
|
||||
for (;;) { /* repeats iff '?' or ":' gets chosen */
|
||||
outmaybe = (outokay || !current_container->cknown);
|
||||
if (!outmaybe)
|
||||
(void) safe_qbuf(qbuf, (char *) 0, " is empty. Do what with it?",
|
||||
@@ -2375,34 +2395,39 @@ int held;
|
||||
(void) safe_qbuf(qbuf, "Do what with ", "?", current_container,
|
||||
yname, ysimple_name, "it");
|
||||
/* ask player about what to do with this container */
|
||||
if (flags.menu_style == MENU_FULL) {
|
||||
if (flags.menu_style == MENU_PARTIAL
|
||||
|| flags.menu_style == MENU_FULL) {
|
||||
if (!inokay && !outmaybe) {
|
||||
/* nothing to take out, nothing to put in;
|
||||
trying to do both will yield proper feedback */
|
||||
c = 'b';
|
||||
} else {
|
||||
c = in_or_out_menu(qbuf, current_container, outmaybe, inokay,
|
||||
(used != 0));
|
||||
(boolean) (used != 0), more_containers);
|
||||
}
|
||||
} else { /* TRADITIONAL, COMBINATION, or PARTIAL */
|
||||
xbuf[0] = '\0'; /* list of extra acceptable responses */
|
||||
Strcpy(pbuf, ":"); /* look inside */
|
||||
} else { /* TRADITIONAL or COMBINATION */
|
||||
xbuf[0] = '\0'; /* list of extra acceptable responses */
|
||||
Strcpy(pbuf, ":"); /* look inside */
|
||||
Strcat(outmaybe ? pbuf : xbuf, "o"); /* take out */
|
||||
Strcat(inokay ? pbuf : xbuf, "i"); /* put in */
|
||||
Strcat(outmaybe ? pbuf : xbuf, "b"); /* both */
|
||||
Strcat(inokay ? pbuf : xbuf, "rs"); /* reversed, stash */
|
||||
Strcat(pbuf, " "); /* separator */
|
||||
Strcat(more_containers ? pbuf : xbuf, "n"); /* next container */
|
||||
Strcat(pbuf, "q"); /* quit */
|
||||
if (iflags.cmdassist)
|
||||
/* this unintentionally allows user to answer with 'o' or
|
||||
'r'; fortunately, those are already valid choices here */
|
||||
Strcat(pbuf, " or ?"); /* help */
|
||||
else
|
||||
Strcat(xbuf, "?");
|
||||
if (*xbuf)
|
||||
Strcat(strcat(pbuf, "\033"), xbuf);
|
||||
c = yn_function(qbuf, pbuf, 'q');
|
||||
} /* FULL vs other modes */
|
||||
c = yn_function(qbuf, pbuf, more_containers ? 'n' : 'q');
|
||||
} /* PARTIAL|FULL vs other modes */
|
||||
|
||||
if (c == '?') {
|
||||
explain_container_prompt();
|
||||
explain_container_prompt(more_containers);
|
||||
} else if (c == ':') { /* note: will set obj->cknown */
|
||||
if (!current_container->cknown)
|
||||
used = 1; /* gaining info */
|
||||
@@ -2411,7 +2436,9 @@ int held;
|
||||
break;
|
||||
} /* loop until something other than '?' or ':' is picked */
|
||||
|
||||
if (c == 'q') /* [not strictly needed; falling through works] */
|
||||
if (c == 'q')
|
||||
abort_looting = TRUE;
|
||||
if (c == 'n' || c == 'q') /* [not strictly needed; falling thru works] */
|
||||
goto containerdone;
|
||||
loot_out = (c == 'o' || c == 'b' || c == 'r');
|
||||
loot_in = (c == 'i' || c == 'b' || c == 'r');
|
||||
@@ -2459,11 +2486,7 @@ int held;
|
||||
} else {
|
||||
/* couldn't put selected item into container for some
|
||||
reason; might need to undo splitobj() */
|
||||
for (curr = invent; curr; curr = curr->nobj)
|
||||
if (curr->nobj == otmp)
|
||||
break;
|
||||
if (curr && curr->invlet == otmp->invlet)
|
||||
(void) merged(&curr, &otmp);
|
||||
(void) unsplitobj(otmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2499,7 +2522,10 @@ containerdone:
|
||||
}
|
||||
|
||||
*objp = current_container; /* might have become null */
|
||||
current_container = 0; /* avoid hanging on to stale pointer */
|
||||
if (current_container)
|
||||
current_container = 0; /* avoid hanging on to stale pointer */
|
||||
else
|
||||
abort_looting = TRUE;
|
||||
return used;
|
||||
}
|
||||
|
||||
@@ -2558,9 +2584,9 @@ boolean put_in;
|
||||
} else if (flags.menu_style == MENU_FULL) {
|
||||
all_categories = FALSE;
|
||||
Sprintf(buf, "%s what type of objects?", action);
|
||||
mflags = put_in
|
||||
? ALL_TYPES | BUC_ALLBKNOWN | BUC_UNKNOWN
|
||||
: ALL_TYPES | CHOOSE_ALL | BUC_ALLBKNOWN | BUC_UNKNOWN;
|
||||
mflags = (ALL_TYPES | BUC_ALLBKNOWN | BUC_UNKNOWN);
|
||||
if (put_in)
|
||||
mflags |= CHOOSE_ALL;
|
||||
n = query_category(buf, put_in ? invent : current_container->cobj,
|
||||
mflags, &pick_list, PICK_ANY);
|
||||
if (!n)
|
||||
@@ -2591,7 +2617,7 @@ boolean put_in;
|
||||
if (!put_in)
|
||||
current_container->cknown = 1;
|
||||
Sprintf(buf, "%s what?", action);
|
||||
n = query_objlist(buf, put_in ? invent : current_container->cobj,
|
||||
n = query_objlist(buf, put_in ? &invent : &(current_container->cobj),
|
||||
mflags, &pick_list, PICK_ANY,
|
||||
all_categories ? allow_all : allow_category);
|
||||
if (n) {
|
||||
@@ -2623,13 +2649,13 @@ boolean put_in;
|
||||
}
|
||||
|
||||
STATIC_OVL char
|
||||
in_or_out_menu(prompt, obj, outokay, inokay, alreadyused)
|
||||
in_or_out_menu(prompt, obj, outokay, inokay, alreadyused, more_containers)
|
||||
const char *prompt;
|
||||
struct obj *obj;
|
||||
boolean outokay, inokay, alreadyused;
|
||||
boolean outokay, inokay, alreadyused, more_containers;
|
||||
{
|
||||
/* underscore is not a choice; it's used to skip element [0] */
|
||||
static const char lootchars[] = "_:oibrsq", abc_chars[] = "_:abcdeq";
|
||||
static const char lootchars[] = "_:oibrsnq", abc_chars[] = "_:abcdenq";
|
||||
winid win;
|
||||
anything any;
|
||||
menu_item *pick_list;
|
||||
@@ -2674,20 +2700,30 @@ boolean outokay, inokay, alreadyused;
|
||||
add_menu(win, NO_GLYPH, &any, menuselector[any.a_int], 0, ATR_NONE,
|
||||
buf, MENU_UNSELECTED);
|
||||
}
|
||||
any.a_int = 7; /* 'q' */
|
||||
any.a_int = 0;
|
||||
add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
|
||||
if (more_containers) {
|
||||
any.a_int = 7; /* 'n' */
|
||||
add_menu(win, NO_GLYPH, &any, menuselector[any.a_int], 0, ATR_NONE,
|
||||
"loot next container", MENU_SELECTED);
|
||||
}
|
||||
any.a_int = 8; /* 'q' */
|
||||
Strcpy(buf, alreadyused ? "done" : "do nothing");
|
||||
add_menu(win, NO_GLYPH, &any, menuselector[any.a_int], 0, ATR_NONE, buf,
|
||||
MENU_SELECTED);
|
||||
more_containers ? MENU_UNSELECTED : MENU_SELECTED);
|
||||
|
||||
end_menu(win, prompt);
|
||||
n = select_menu(win, PICK_ONE, &pick_list);
|
||||
destroy_nhwindow(win);
|
||||
if (n > 0) {
|
||||
n = pick_list[0].item.a_int;
|
||||
int k = pick_list[0].item.a_int;
|
||||
|
||||
if (n > 1 && k == (more_containers ? 7 : 8))
|
||||
k = pick_list[1].item.a_int;
|
||||
free((genericptr_t) pick_list);
|
||||
return lootchars[n]; /* :,o,i,b,r,s,q */
|
||||
return lootchars[k]; /* :,o,i,b,r,s,n,q */
|
||||
}
|
||||
return 'q'; /* quit */
|
||||
return (n == 0 && more_containers) ? 'n' : 'q'; /* next or quit */
|
||||
}
|
||||
|
||||
static const char tippables[] = { ALL_CLASSES, TOOL_CLASS, 0 };
|
||||
|
||||
+46
-19
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 pline.c $NHDT-Date: 1456528597 2016/02/26 23:16:37 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.49 $ */
|
||||
/* NetHack 3.6 pline.c $NHDT-Date: 1461437814 2016/04/23 18:56:54 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.51 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -436,7 +436,8 @@ register struct monst *mtmp;
|
||||
Strcat(info, ", asleep");
|
||||
#if 0 /* unfortunately mfrozen covers temporary sleep and being busy \
|
||||
(donning armor, for instance) as well as paralysis */
|
||||
else if (mtmp->mfrozen) Strcat(info, ", paralyzed");
|
||||
else if (mtmp->mfrozen)
|
||||
Strcat(info, ", paralyzed");
|
||||
#else
|
||||
else if (mtmp->mfrozen || !mtmp->mcanmove)
|
||||
Strcat(info, ", can't move");
|
||||
@@ -538,23 +539,8 @@ ustatusline()
|
||||
Strcat(info, mon_nam(u.ustuck));
|
||||
}
|
||||
|
||||
pline("Status of %s (%s%s): Level %d HP %d(%d) AC %d%s.", plname,
|
||||
(u.ualign.record >= 20)
|
||||
? "piously "
|
||||
: (u.ualign.record > 13)
|
||||
? "devoutly "
|
||||
: (u.ualign.record > 8)
|
||||
? "fervently "
|
||||
: (u.ualign.record > 3)
|
||||
? "stridently "
|
||||
: (u.ualign.record == 3)
|
||||
? ""
|
||||
: (u.ualign.record >= 1)
|
||||
? "haltingly "
|
||||
: (u.ualign.record == 0)
|
||||
? "nominally "
|
||||
: "insufficiently ",
|
||||
align_str(u.ualign.type),
|
||||
pline("Status of %s (%s): Level %d HP %d(%d) AC %d%s.", plname,
|
||||
piousness(FALSE, align_str(u.ualign.type)),
|
||||
Upolyd ? mons[u.umonnum].mlevel : u.ulevel, Upolyd ? u.mh : u.uhp,
|
||||
Upolyd ? u.mhmax : u.uhpmax, u.uac, info);
|
||||
}
|
||||
@@ -568,6 +554,47 @@ self_invis_message()
|
||||
: "can't see yourself");
|
||||
}
|
||||
|
||||
char *
|
||||
piousness(showneg, suffix)
|
||||
boolean showneg;
|
||||
const char *suffix;
|
||||
{
|
||||
static char buf[32]; /* bigger than "insufficiently neutral" */
|
||||
const char *pio;
|
||||
|
||||
/* note: piousness 20 matches MIN_QUEST_ALIGN (quest.h) */
|
||||
if (u.ualign.record >= 20)
|
||||
pio = "piously";
|
||||
else if (u.ualign.record > 13)
|
||||
pio = "devoutly";
|
||||
else if (u.ualign.record > 8)
|
||||
pio = "fervently";
|
||||
else if (u.ualign.record > 3)
|
||||
pio = "stridently";
|
||||
else if (u.ualign.record == 3)
|
||||
pio = "";
|
||||
else if (u.ualign.record > 0)
|
||||
pio = "haltingly";
|
||||
else if (u.ualign.record == 0)
|
||||
pio = "nominally";
|
||||
else if (!showneg)
|
||||
pio = "insufficiently";
|
||||
else if (u.ualign.record >= -3)
|
||||
pio = "strayed";
|
||||
else if (u.ualign.record >= -8)
|
||||
pio = "sinned";
|
||||
else
|
||||
pio = "transgressed";
|
||||
|
||||
Sprintf(buf, "%s", pio);
|
||||
if (suffix && (!showneg || u.ualign.record >= 0)) {
|
||||
if (u.ualign.record != 3)
|
||||
Strcat(buf, " ");
|
||||
Strcat(buf, suffix);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
void
|
||||
pudding_merge_message(otmp, otmp2)
|
||||
struct obj *otmp;
|
||||
|
||||
+9
-14
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 polyself.c $NHDT-Date: 1451082254 2015/12/25 22:24:14 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.105 $ */
|
||||
/* NetHack 3.6 polyself.c $NHDT-Date: 1457572516 2016/03/10 01:15:16 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.108 $ */
|
||||
/* Copyright (C) 1987, 1988, 1989 by Ken Arromdee */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -592,6 +592,7 @@ int
|
||||
polymon(mntmp)
|
||||
int mntmp;
|
||||
{
|
||||
char buf[BUFSZ];
|
||||
boolean sticky = sticks(youmonst.data) && u.ustuck && !u.uswallow,
|
||||
was_blind = !!Blind, dochange = FALSE;
|
||||
int mlvl;
|
||||
@@ -643,20 +644,16 @@ int mntmp;
|
||||
if (sex_change_ok && !rn2(10))
|
||||
dochange = TRUE;
|
||||
}
|
||||
|
||||
Strcpy(buf, (u.umonnum != mntmp) ? "" : "new ");
|
||||
if (dochange) {
|
||||
flags.female = !flags.female;
|
||||
You("%s %s%s!",
|
||||
(u.umonnum != mntmp) ? "turn into a" : "feel like a new",
|
||||
(is_male(&mons[mntmp]) || is_female(&mons[mntmp]))
|
||||
? ""
|
||||
: flags.female ? "female " : "male ",
|
||||
mons[mntmp].mname);
|
||||
} else {
|
||||
if (u.umonnum != mntmp)
|
||||
You("turn into %s!", an(mons[mntmp].mname));
|
||||
else
|
||||
You_feel("like a new %s!", mons[mntmp].mname);
|
||||
Strcat(buf, (is_male(&mons[mntmp]) || is_female(&mons[mntmp]))
|
||||
? "" : flags.female ? "female " : "male ");
|
||||
}
|
||||
Strcat(buf, mons[mntmp].mname);
|
||||
You("%s %s!", (u.umonnum != mntmp) ? "turn into" : "feel like", an(buf));
|
||||
|
||||
if (Stoned && poly_when_stoned(&mons[mntmp])) {
|
||||
/* poly_when_stoned already checked stone golem genocide */
|
||||
mntmp = PM_STONE_GOLEM;
|
||||
@@ -746,8 +743,6 @@ int mntmp;
|
||||
uunstick();
|
||||
if (u.usteed) {
|
||||
if (touch_petrifies(u.usteed->data) && !Stone_resistance && rnl(3)) {
|
||||
char buf[BUFSZ];
|
||||
|
||||
pline("%s touch %s.", no_longer_petrify_resistant,
|
||||
mon_nam(u.usteed));
|
||||
Sprintf(buf, "riding %s", an(u.usteed->data->mname));
|
||||
|
||||
+50
-26
@@ -957,39 +957,59 @@ register struct obj *otmp;
|
||||
break;
|
||||
case POT_LEVITATION:
|
||||
case SPE_LEVITATION:
|
||||
if (otmp->cursed)
|
||||
HLevitation &= ~I_SPECIAL;
|
||||
/*
|
||||
* BLevitation will be set if levitation is blocked due to being
|
||||
* inside rock (currently or formerly in phazing xorn form, perhaps)
|
||||
* but it doesn't prevent setting or incrementing Levitation timeout
|
||||
* (which will take effect after escaping from the rock if it hasn't
|
||||
* expired by then).
|
||||
*/
|
||||
if (!Levitation && !BLevitation) {
|
||||
/* kludge to ensure proper operation of float_up() */
|
||||
set_itimeout(&HLevitation, 1L);
|
||||
float_up();
|
||||
/* reverse kludge */
|
||||
set_itimeout(&HLevitation, 0L);
|
||||
if (otmp->cursed) {
|
||||
if ((u.ux == xupstair && u.uy == yupstair)
|
||||
|| (sstairs.up && u.ux == sstairs.sx
|
||||
&& u.uy == sstairs.sy)
|
||||
|| (xupladder && u.ux == xupladder
|
||||
&& u.uy == yupladder)) {
|
||||
(void) doup();
|
||||
} else if (has_ceiling(&u.uz)) {
|
||||
int dmg = uarmh ? 1 : rnd(10);
|
||||
|
||||
You("hit your %s on the %s.", body_part(HEAD),
|
||||
ceiling(u.ux, u.uy));
|
||||
losehp(Maybe_Half_Phys(dmg), "colliding with the ceiling",
|
||||
KILLED_BY);
|
||||
}
|
||||
} /*cursed*/
|
||||
} else
|
||||
/* This used to set timeout back to 0, then increment it below
|
||||
for blessed and uncursed effects. But now we leave it so
|
||||
that cursed effect yields "you float down" on next turn.
|
||||
Blessed and uncursed get one extra turn duration. */
|
||||
} else /* already levitating, or can't levitate */
|
||||
nothing++;
|
||||
if (otmp->blessed) {
|
||||
|
||||
if (otmp->cursed) {
|
||||
/* 'already levitating' used to block the cursed effect(s)
|
||||
aside from ~I_SPECIAL; it was not clear whether that was
|
||||
intentional; either way, it no longer does (as of 3.6.1) */
|
||||
HLevitation &= ~I_SPECIAL; /* can't descend upon demand */
|
||||
if (BLevitation) {
|
||||
; /* rising via levitation is blocked */
|
||||
} else if ((u.ux == xupstair && u.uy == yupstair)
|
||||
|| (sstairs.up && u.ux == sstairs.sx && u.uy == sstairs.sy)
|
||||
|| (xupladder && u.ux == xupladder && u.uy == yupladder)) {
|
||||
(void) doup();
|
||||
/* in case we're already Levitating, which would have
|
||||
resulted in incrementing 'nothing' */
|
||||
nothing = 0; /* not nothing after all */
|
||||
} else if (has_ceiling(&u.uz)) {
|
||||
int dmg = rnd(!uarmh ? 10 : !is_metallic(uarmh) ? 6 : 3);
|
||||
|
||||
You("hit your %s on the %s.", body_part(HEAD),
|
||||
ceiling(u.ux, u.uy));
|
||||
losehp(Maybe_Half_Phys(dmg), "colliding with the ceiling",
|
||||
KILLED_BY);
|
||||
nothing = 0; /* not nothing after all */
|
||||
}
|
||||
} else if (otmp->blessed) {
|
||||
/* at this point, timeout is already at least 1 */
|
||||
incr_itimeout(&HLevitation, rn1(50, 250));
|
||||
/* can descend at will (stop levitating via '>') provided timeout
|
||||
is the only factor (ie, not also wearing Lev ring or boots) */
|
||||
HLevitation |= I_SPECIAL;
|
||||
} else
|
||||
} else /* timeout is already at least 1 */
|
||||
incr_itimeout(&HLevitation, rn1(140, 10));
|
||||
if (Levitation)
|
||||
spoteffects(FALSE); /* for sinks */
|
||||
|
||||
if (Levitation && IS_SINK(levl[u.ux][u.uy].typ))
|
||||
spoteffects(FALSE);
|
||||
/* levitating blocks flying */
|
||||
float_vs_flight();
|
||||
break;
|
||||
case POT_GAIN_ENERGY: { /* M. Stephenson */
|
||||
@@ -1090,8 +1110,12 @@ register boolean curesick, cureblind;
|
||||
u.uhp = (u.uhpmax += nxtra);
|
||||
}
|
||||
}
|
||||
if (cureblind)
|
||||
if (cureblind) {
|
||||
/* 3.6.1: it's debatible whether healing magic should clean off
|
||||
mundane 'dirt', but if it doesn't, blindness isn't cured */
|
||||
u.ucreamed = 0;
|
||||
make_blinded(0L, TRUE);
|
||||
}
|
||||
if (curesick) {
|
||||
make_vomiting(0L, TRUE);
|
||||
make_sick(0L, (char *) 0, TRUE, SICK_ALL);
|
||||
|
||||
+16
-8
@@ -289,7 +289,7 @@ worst_cursed_item()
|
||||
} else if (uright && uright->cursed) { /* right ring */
|
||||
otmp = uright;
|
||||
} else if (ublindf && ublindf->cursed) { /* eyewear */
|
||||
otmp = ublindf; /* must be non-blinding lenses */
|
||||
otmp = ublindf; /* must be non-blinding lenses */
|
||||
/* if weapon wasn't handled above, do it now */
|
||||
} else if (welded(uwep)) { /* weapon */
|
||||
otmp = uwep;
|
||||
@@ -520,9 +520,8 @@ int trouble;
|
||||
}
|
||||
}
|
||||
|
||||
/* "I am sometimes shocked by... the nuns who never take a bath without
|
||||
* wearing a bathrobe all the time. When asked why, since no man can see
|
||||
* them,
|
||||
/* "I am sometimes shocked by... the nuns who never take a bath without
|
||||
* wearing a bathrobe all the time. When asked why, since no man can see them,
|
||||
* they reply 'Oh, but you forget the good God'. Apparently they conceive of
|
||||
* the Deity as a Peeping Tom, whose omnipotence enables Him to see through
|
||||
* bathroom walls, but who is foiled by bathrobes." --Bertrand Russell, 1943
|
||||
@@ -540,8 +539,10 @@ aligntyp resp_god;
|
||||
pline("%s fries to a crisp!", Monnam(u.ustuck));
|
||||
/* Yup, you get experience. It takes guts to successfully
|
||||
* pull off this trick on your god, anyway.
|
||||
* Other credit/blame applies (luck or alignment adjustments),
|
||||
* but not direct kill count (pacifist conduct).
|
||||
*/
|
||||
xkilled(u.ustuck, 0);
|
||||
xkilled(u.ustuck, XKILL_NOMSG | XKILL_NOCONDUCT);
|
||||
} else
|
||||
pline("%s seems unaffected.", Monnam(u.ustuck));
|
||||
} else {
|
||||
@@ -565,7 +566,7 @@ aligntyp resp_god;
|
||||
mon_nam(u.ustuck));
|
||||
if (!resists_disint(u.ustuck)) {
|
||||
pline("%s disintegrates into a pile of dust!", Monnam(u.ustuck));
|
||||
xkilled(u.ustuck, 2); /* no corpse */
|
||||
xkilled(u.ustuck, XKILL_NOMSG | XKILL_NOCORPSE | XKILL_NOCONDUCT);
|
||||
} else
|
||||
pline("%s seems unaffected.", Monnam(u.ustuck));
|
||||
} else {
|
||||
@@ -585,9 +586,9 @@ aligntyp resp_god;
|
||||
(void) destroy_arm(uarm);
|
||||
if (uarmu && !uarm && !uarmc)
|
||||
(void) destroy_arm(uarmu);
|
||||
if (!Disint_resistance)
|
||||
if (!Disint_resistance) {
|
||||
fry_by_god(resp_god, TRUE);
|
||||
else {
|
||||
} else {
|
||||
You("bask in its %s glow for a minute...", NH_BLACK);
|
||||
godvoice(resp_god, "I believe it not!");
|
||||
}
|
||||
@@ -1048,8 +1049,15 @@ aligntyp g_align;
|
||||
ABASE(A_STR) = AMAX(A_STR);
|
||||
if (u.uhunger < 900)
|
||||
init_uhunger();
|
||||
/* luck couldn't have been negative at start of prayer because
|
||||
the prayer would have failed, but might have been decremented
|
||||
due to a timed event (delayed death of peaceful monster hit
|
||||
by hero-created stinking cloud) during the praying interval */
|
||||
if (u.uluck < 0)
|
||||
u.uluck = 0;
|
||||
/* superfluous; if hero was blinded we'd be handling trouble
|
||||
rather than issuing a pat-on-head */
|
||||
u.ucreamed = 0;
|
||||
make_blinded(0L, TRUE);
|
||||
context.botl = 1;
|
||||
break;
|
||||
|
||||
+29
-12
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 read.c $NHDT-Date: 1450577673 2015/12/20 02:14:33 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.131 $ */
|
||||
/* NetHack 3.6 read.c $NHDT-Date: 1457660917 2016/03/11 01:48:37 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.136 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -60,6 +60,7 @@ struct obj *otmp;
|
||||
char *buf;
|
||||
{
|
||||
int erosion = greatest_erosion(otmp);
|
||||
|
||||
if (erosion)
|
||||
wipeout_text(buf, (int) (strlen(buf) * erosion / (2 * MAX_ERODE)),
|
||||
otmp->o_id ^ (unsigned) ubirthday);
|
||||
@@ -1312,8 +1313,11 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
|
||||
*/
|
||||
break;
|
||||
case SCR_ENCHANT_WEAPON:
|
||||
/* [What about twoweapon mode? Proofing/repairing/enchanting both
|
||||
would be too powerful, but shouldn't we choose randomly between
|
||||
primary and secondary instead of always acting on primary?] */
|
||||
if (confused && uwep
|
||||
&& (uwep->oclass == WEAPON_CLASS || is_weptool(uwep))) {
|
||||
&& erosion_matters(uwep) && uwep->oclass != ARMOR_CLASS) {
|
||||
old_erodeproof = (uwep->oerodeproof != 0);
|
||||
new_erodeproof = !scursed;
|
||||
uwep->oerodeproof = 0; /* for messages */
|
||||
@@ -1740,9 +1744,9 @@ boolean confused, byu;
|
||||
}
|
||||
mtmp->mhp -= mdmg;
|
||||
if (mtmp->mhp <= 0) {
|
||||
if (byu)
|
||||
xkilled(mtmp, 1);
|
||||
else {
|
||||
if (byu) {
|
||||
killed(mtmp);
|
||||
} else {
|
||||
pline("%s is killed.", Monnam(mtmp));
|
||||
mondied(mtmp);
|
||||
}
|
||||
@@ -2366,11 +2370,9 @@ create_particular()
|
||||
int which, tryct, i, firstchoice = NON_PM;
|
||||
struct permonst *whichpm = NULL;
|
||||
struct monst *mtmp;
|
||||
boolean madeany = FALSE;
|
||||
boolean maketame, makepeaceful, makehostile;
|
||||
boolean randmonst = FALSE;
|
||||
boolean saddled = FALSE;
|
||||
boolean invisible = FALSE;
|
||||
boolean madeany = FALSE, randmonst = FALSE,
|
||||
maketame, makepeaceful, makehostile, saddled, invisible;
|
||||
int fem;
|
||||
|
||||
tryct = 5;
|
||||
do {
|
||||
@@ -2378,18 +2380,29 @@ create_particular()
|
||||
which = urole.malenum; /* an arbitrary index into mons[] */
|
||||
maketame = makepeaceful = makehostile = FALSE;
|
||||
saddled = invisible = FALSE;
|
||||
fem = -1; /* gender not specified */
|
||||
getlin("Create what kind of monster? [type the name or symbol]", buf);
|
||||
bufp = mungspaces(buf);
|
||||
if (*bufp == '\033')
|
||||
return FALSE;
|
||||
if ((tmpp = strstri(bufp, "saddled ")) != 0) {
|
||||
saddled = TRUE;
|
||||
memset(tmpp, ' ', sizeof("saddled ")-1);
|
||||
(void) memset(tmpp, ' ', sizeof "saddled " - 1);
|
||||
}
|
||||
if ((tmpp = strstri(bufp, "invisible ")) != 0) {
|
||||
invisible = TRUE;
|
||||
memset(tmpp, ' ', sizeof("invisible ")-1);
|
||||
(void) memset(tmpp, ' ', sizeof "invisible " - 1);
|
||||
}
|
||||
/* check "female" before "male" to avoid false hit mid-word */
|
||||
if ((tmpp = strstri(bufp, "female ")) != 0) {
|
||||
fem = 1;
|
||||
(void) memset(tmpp, ' ', sizeof "female " - 1);
|
||||
}
|
||||
if ((tmpp = strstri(bufp, "male ")) != 0) {
|
||||
fem = 0;
|
||||
(void) memset(tmpp, ' ', sizeof "male " - 1);
|
||||
}
|
||||
bufp = mungspaces(bufp); /* after potential memset(' ') */
|
||||
/* allow the initial disposition to be specified */
|
||||
if (!strncmpi(bufp, "tame ", 5)) {
|
||||
bufp += 5;
|
||||
@@ -2448,6 +2461,9 @@ create_particular()
|
||||
/* otherwise try again */
|
||||
continue;
|
||||
}
|
||||
/* 'is_FOO()' ought to be called 'always_FOO()' */
|
||||
if (fem != -1 && !is_male(mtmp->data) && !is_female(mtmp->data))
|
||||
mtmp->female = fem; /* ignored for is_neuter() */
|
||||
if (maketame) {
|
||||
(void) tamedog(mtmp, (struct obj *) 0);
|
||||
} else if (makepeaceful || makehostile) {
|
||||
@@ -2457,6 +2473,7 @@ create_particular()
|
||||
}
|
||||
if (saddled && can_saddle(mtmp) && !which_armor(mtmp, W_SADDLE)) {
|
||||
struct obj *otmp = mksobj(SADDLE, TRUE, FALSE);
|
||||
|
||||
put_saddle_on_mon(otmp, mtmp);
|
||||
}
|
||||
if (invisible)
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/* NetHack 3.6 rect.c $NHDT-Date: 1432512774 2015/05/25 00:12:54 $ $NHDT-Branch: master $:$NHDT-Revision: 1.11 $ */
|
||||
/* Copyright (c) 1990 by Jean-Christophe Collet */
|
||||
/* Copyright (c) 1990 by Jean-Christophe Collet */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
#include "hack.h"
|
||||
|
||||
+35
-10
@@ -95,14 +95,13 @@ int nrect;
|
||||
if (nrect > 0) {
|
||||
reg->bounding_box = rects[0];
|
||||
} else {
|
||||
reg->bounding_box.lx = 99;
|
||||
reg->bounding_box.ly = 99;
|
||||
reg->bounding_box.hx = 0;
|
||||
reg->bounding_box.lx = COLNO;
|
||||
reg->bounding_box.ly = ROWNO;
|
||||
reg->bounding_box.hx = 0; /* 1 */
|
||||
reg->bounding_box.hy = 0;
|
||||
}
|
||||
reg->nrects = nrect;
|
||||
reg->rects =
|
||||
nrect > 0 ? (NhRect *) alloc((sizeof(NhRect)) * nrect) : (NhRect *) 0;
|
||||
reg->rects = (nrect > 0) ? (NhRect *) alloc(nrect * sizeof (NhRect)) : 0;
|
||||
for (i = 0; i < nrect; i++) {
|
||||
if (rects[i].lx < reg->bounding_box.lx)
|
||||
reg->bounding_box.lx = rects[i].lx;
|
||||
@@ -145,10 +144,10 @@ NhRect *rect;
|
||||
{
|
||||
NhRect *tmp_rect;
|
||||
|
||||
tmp_rect = (NhRect *) alloc(sizeof(NhRect) * (reg->nrects + 1));
|
||||
tmp_rect = (NhRect *) alloc((reg->nrects + 1) * sizeof (NhRect));
|
||||
if (reg->nrects > 0) {
|
||||
(void) memcpy((genericptr_t) tmp_rect, (genericptr_t) reg->rects,
|
||||
(sizeof(NhRect) * reg->nrects));
|
||||
reg->nrects * sizeof (NhRect));
|
||||
free((genericptr_t) reg->rects);
|
||||
}
|
||||
tmp_rect[reg->nrects] = *rect;
|
||||
@@ -177,7 +176,7 @@ struct monst *mon;
|
||||
unsigned *tmp_m;
|
||||
|
||||
if (reg->max_monst <= reg->n_monst) {
|
||||
tmp_m = (unsigned *) alloc(sizeof(unsigned)
|
||||
tmp_m = (unsigned *) alloc(sizeof (unsigned)
|
||||
* (reg->max_monst + MONST_INC));
|
||||
if (reg->max_monst > 0) {
|
||||
for (i = 0; i < reg->max_monst; i++)
|
||||
@@ -297,10 +296,10 @@ NhRegion *reg;
|
||||
if (max_regions <= n_regions) {
|
||||
tmp_reg = regions;
|
||||
regions =
|
||||
(NhRegion **) alloc(sizeof(NhRegion *) * (max_regions + 10));
|
||||
(NhRegion **) alloc((max_regions + 10) * sizeof (NhRegion *));
|
||||
if (max_regions > 0) {
|
||||
(void) memcpy((genericptr_t) regions, (genericptr_t) tmp_reg,
|
||||
max_regions * sizeof(NhRegion *));
|
||||
max_regions * sizeof (NhRegion *));
|
||||
free((genericptr_t) tmp_reg);
|
||||
}
|
||||
max_regions += 10;
|
||||
@@ -763,6 +762,32 @@ boolean ghostly; /* If a bones file restore */
|
||||
reset_region_mids(regions[i]);
|
||||
}
|
||||
|
||||
/* to support '#stats' wizard-mode command */
|
||||
void
|
||||
region_stats(hdrfmt, hdrbuf, count, size)
|
||||
const char *hdrfmt;
|
||||
char *hdrbuf;
|
||||
long *count, *size;
|
||||
{
|
||||
NhRegion *rg;
|
||||
int i;
|
||||
|
||||
/* other stats formats take one parameter; this takes two */
|
||||
Sprintf(hdrbuf, hdrfmt, (long) sizeof (NhRegion), (long) sizeof (NhRect));
|
||||
*count = (long) n_regions; /* might be 0 even though max_regions isn't */
|
||||
*size = (long) max_regions * (long) sizeof (NhRegion);
|
||||
for (i = 0; i < n_regions; ++i) {
|
||||
rg = regions[i];
|
||||
*size += (long) rg->nrects * (long) sizeof (NhRect);
|
||||
if (rg->enter_msg)
|
||||
*size += (long) (strlen(rg->enter_msg) + 1);
|
||||
if (rg->leave_msg)
|
||||
*size += (long) (strlen(rg->leave_msg) + 1);
|
||||
*size += (long) rg->max_monst * (long) sizeof *rg->monsters;
|
||||
}
|
||||
/* ? */
|
||||
}
|
||||
|
||||
/* update monster IDs for region being loaded from bones; `ghostly' implied */
|
||||
STATIC_OVL void
|
||||
reset_region_mids(reg)
|
||||
|
||||
+39
-12
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 role.c $NHDT-Date: 1456907852 2016/03/02 08:37:32 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.37 $ */
|
||||
/* NetHack 3.6 role.c $NHDT-Date: 1463561393 2016/05/18 08:49:53 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.38 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985-1999. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -1148,9 +1148,9 @@ int rolenum, racenum, gendnum, alignnum;
|
||||
}
|
||||
}
|
||||
|
||||
/* pick a random race subject to any rolenum/gendnum/alignnum constraints */
|
||||
/* If pickhow == PICK_RIGID a race is returned only if there is */
|
||||
/* a single possibility */
|
||||
/* Pick a random race subject to any rolenum/gendnum/alignnum constraints.
|
||||
If pickhow == PICK_RIGID a race is returned only if there is
|
||||
a single possibility. */
|
||||
int
|
||||
pick_race(rolenum, gendnum, alignnum, pickhow)
|
||||
int rolenum, gendnum, alignnum, pickhow;
|
||||
@@ -1284,11 +1284,10 @@ int alignnum;
|
||||
}
|
||||
}
|
||||
|
||||
/* pick a random alignment subject to any rolenum/racenum/gendnum constraints
|
||||
*/
|
||||
/* alignment and gender are not comparable (and also not constrainable) */
|
||||
/* If pickhow == PICK_RIGID an alignment is returned only if there is */
|
||||
/* a single possibility */
|
||||
/* Pick a random alignment subject to any rolenum/racenum/gendnum constraints;
|
||||
alignment and gender are not comparable (and also not constrainable).
|
||||
If pickhow == PICK_RIGID an alignment is returned only if there is
|
||||
a single possibility. */
|
||||
int
|
||||
pick_align(rolenum, racenum, gendnum, pickhow)
|
||||
int rolenum, racenum, gendnum, pickhow;
|
||||
@@ -1317,6 +1316,8 @@ int rolenum, racenum, gendnum, pickhow;
|
||||
void
|
||||
rigid_role_checks()
|
||||
{
|
||||
int tmp;
|
||||
|
||||
/* Some roles are limited to a single race, alignment, or gender and
|
||||
* calling this routine prior to XXX_player_selection() will help
|
||||
* prevent an extraneous prompt that actually doesn't allow
|
||||
@@ -1327,14 +1328,27 @@ rigid_role_checks()
|
||||
*/
|
||||
if (flags.initrole == ROLE_RANDOM) {
|
||||
/* If the role was explicitly specified as ROLE_RANDOM
|
||||
* via -uXXXX-@ then choose the role in here to narrow down
|
||||
* later choices. Pick a random role in this case.
|
||||
* via -uXXXX-@ or OPTIONS=role:random then choose the role
|
||||
* in here to narrow down later choices.
|
||||
*/
|
||||
flags.initrole = pick_role(flags.initrace, flags.initgend,
|
||||
flags.initalign, PICK_RANDOM);
|
||||
if (flags.initrole < 0)
|
||||
flags.initrole = randrole_filtered();
|
||||
}
|
||||
if (flags.initrace == ROLE_RANDOM
|
||||
&& (tmp = pick_race(flags.initrole, flags.initgend,
|
||||
flags.initalign, PICK_RANDOM)) != ROLE_NONE)
|
||||
flags.initrace = tmp;
|
||||
if (flags.initalign == ROLE_RANDOM
|
||||
&& (tmp = pick_align(flags.initrole, flags.initrace,
|
||||
flags.initgend, PICK_RANDOM)) != ROLE_NONE)
|
||||
flags.initalign = tmp;
|
||||
if (flags.initgend == ROLE_RANDOM
|
||||
&& (tmp = pick_gend(flags.initrole, flags.initrace,
|
||||
flags.initalign, PICK_RANDOM)) != ROLE_NONE)
|
||||
flags.initgend = tmp;
|
||||
|
||||
if (flags.initrole != ROLE_NONE) {
|
||||
if (flags.initrace == ROLE_NONE)
|
||||
flags.initrace = pick_race(flags.initrole, flags.initgend,
|
||||
@@ -1639,7 +1653,20 @@ int buflen, rolenum, racenum, gendnum, alignnum;
|
||||
* Now append the post attributes to it
|
||||
*/
|
||||
num_post_attribs = post_attribs;
|
||||
if (post_attribs) {
|
||||
if (!num_post_attribs) {
|
||||
/* some constraints might have been mutually exclusive, in which case
|
||||
some prompting that would have been omitted is needed after all */
|
||||
if (flags.initrole == ROLE_NONE && !pa[BP_ROLE])
|
||||
pa[BP_ROLE] = ++post_attribs;
|
||||
if (flags.initrace == ROLE_NONE && !pa[BP_RACE])
|
||||
pa[BP_RACE] = ++post_attribs;
|
||||
if (flags.initalign == ROLE_NONE && !pa[BP_ALIGN])
|
||||
pa[BP_ALIGN] = ++post_attribs;
|
||||
if (flags.initgend == ROLE_NONE && !pa[BP_GEND])
|
||||
pa[BP_GEND] = ++post_attribs;
|
||||
num_post_attribs = post_attribs;
|
||||
}
|
||||
if (num_post_attribs) {
|
||||
if (pa[BP_RACE]) {
|
||||
(void) promptsep(eos(buf), num_post_attribs);
|
||||
Strcat(buf, "race");
|
||||
|
||||
@@ -1329,6 +1329,9 @@ free_dungeons()
|
||||
void
|
||||
freedynamicdata()
|
||||
{
|
||||
#if defined(UNIX) && defined(MAIL)
|
||||
free_maildata();
|
||||
#endif
|
||||
unload_qtlist();
|
||||
free_menu_coloring();
|
||||
free_invbuf(); /* let_to_name (invent.c) */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 shk.c $NHDT-Date: 1455403704 2016/02/13 22:48:24 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.124 $ */
|
||||
/* NetHack 3.6 shk.c $NHDT-Date: 1464138042 2016/05/25 01:00:42 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.132 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -38,7 +38,8 @@ STATIC_DCL struct monst *FDECL(next_shkp, (struct monst *, BOOLEAN_P));
|
||||
STATIC_DCL long FDECL(shop_debt, (struct eshk *));
|
||||
STATIC_DCL char *FDECL(shk_owns, (char *, struct obj *));
|
||||
STATIC_DCL char *FDECL(mon_owns, (char *, struct obj *));
|
||||
STATIC_DCL void FDECL(clear_unpaid, (struct obj *));
|
||||
STATIC_DCL void FDECL(clear_unpaid_obj, (struct monst *, struct obj *));
|
||||
STATIC_DCL void FDECL(clear_unpaid, (struct monst *, struct obj *));
|
||||
STATIC_DCL long FDECL(check_credit, (long, struct monst *));
|
||||
STATIC_DCL void FDECL(pay, (long, struct monst *));
|
||||
STATIC_DCL long FDECL(get_cost, (struct obj *, struct monst *));
|
||||
@@ -80,7 +81,7 @@ STATIC_DCL const char *FDECL(cad, (BOOLEAN_P));
|
||||
obj->quan <= bp->bquan
|
||||
*/
|
||||
|
||||
static const char *angrytexts[] = {"quite upset", "ticked off", "furious"};
|
||||
static const char *angrytexts[] = { "quite upset", "ticked off", "furious" };
|
||||
|
||||
/*
|
||||
* Transfer money from inventory to monster when paying
|
||||
@@ -260,15 +261,26 @@ boolean ghostly;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the unpaid bit on a single object and its contents. */
|
||||
STATIC_OVL void
|
||||
clear_unpaid_obj(shkp, otmp)
|
||||
struct monst *shkp;
|
||||
struct obj *otmp;
|
||||
{
|
||||
if (Has_contents(otmp))
|
||||
clear_unpaid(shkp, otmp->cobj);
|
||||
if (onbill(otmp, shkp, TRUE))
|
||||
otmp->unpaid = 0;
|
||||
}
|
||||
|
||||
/* Clear the unpaid bit on all of the objects in the list. */
|
||||
STATIC_OVL void
|
||||
clear_unpaid(list)
|
||||
register struct obj *list;
|
||||
clear_unpaid(shkp, list)
|
||||
struct monst *shkp;
|
||||
struct obj *list;
|
||||
{
|
||||
while (list) {
|
||||
if (Has_contents(list))
|
||||
clear_unpaid(list->cobj);
|
||||
list->unpaid = 0;
|
||||
clear_unpaid_obj(shkp, list);
|
||||
list = list->nobj;
|
||||
}
|
||||
}
|
||||
@@ -281,20 +293,17 @@ register struct monst *shkp;
|
||||
register struct obj *obj;
|
||||
register struct monst *mtmp;
|
||||
|
||||
/* FIXME: object handling should be limited to
|
||||
items which are on this particular shk's bill */
|
||||
|
||||
clear_unpaid(invent);
|
||||
clear_unpaid(fobj);
|
||||
clear_unpaid(level.buriedobjlist);
|
||||
clear_unpaid(shkp, invent);
|
||||
clear_unpaid(shkp, fobj);
|
||||
clear_unpaid(shkp, level.buriedobjlist);
|
||||
if (thrownobj)
|
||||
thrownobj->unpaid = 0;
|
||||
clear_unpaid_obj(shkp, thrownobj);
|
||||
if (kickedobj)
|
||||
kickedobj->unpaid = 0;
|
||||
clear_unpaid_obj(shkp, kickedobj);
|
||||
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
|
||||
clear_unpaid(mtmp->minvent);
|
||||
clear_unpaid(shkp, mtmp->minvent);
|
||||
for (mtmp = migrating_mons; mtmp; mtmp = mtmp->nmon)
|
||||
clear_unpaid(mtmp->minvent);
|
||||
clear_unpaid(shkp, mtmp->minvent);
|
||||
|
||||
while ((obj = billobjs) != 0) {
|
||||
obj_extract_self(obj);
|
||||
@@ -575,7 +584,8 @@ char *enterstring;
|
||||
if (!Deaf && !muteshk(shkp))
|
||||
verbalize("Invisible customers are not welcome!");
|
||||
else
|
||||
pline("%s stands firm as if he knows you are there.", Shknam(shkp));
|
||||
pline("%s stands firm as if %s knows you are there.",
|
||||
Shknam(shkp), mhe(shkp));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -587,13 +597,14 @@ char *enterstring;
|
||||
s_suffix(shkname(shkp)), shtypes[rt - SHOPBASE].name);
|
||||
else
|
||||
pline("%s seems %s over your return to %s %s!",
|
||||
Shknam(shkp),
|
||||
angrytexts[rn2(SIZE(angrytexts))],
|
||||
mhis(shkp),
|
||||
shtypes[rt - SHOPBASE].name);
|
||||
Shknam(shkp),
|
||||
angrytexts[rn2(SIZE(angrytexts))],
|
||||
mhis(shkp),
|
||||
shtypes[rt - SHOPBASE].name);
|
||||
} else if (eshkp->robbed) {
|
||||
if (!Deaf)
|
||||
pline("%s mutters imprecations against shoplifters.", shkname(shkp));
|
||||
pline("%s mutters imprecations against shoplifters.",
|
||||
shkname(shkp));
|
||||
else
|
||||
pline("%s is combing through %s inventory list.",
|
||||
Shknam(shkp),
|
||||
@@ -601,8 +612,8 @@ char *enterstring;
|
||||
} else {
|
||||
if (!Deaf && !muteshk(shkp))
|
||||
verbalize("%s, %s! Welcome%s to %s %s!", Hello(shkp), plname,
|
||||
eshkp->visitct++ ? " again" : "", s_suffix(shkname(shkp)),
|
||||
shtypes[rt - SHOPBASE].name);
|
||||
eshkp->visitct++ ? " again" : "",
|
||||
s_suffix(shkname(shkp)), shtypes[rt - SHOPBASE].name);
|
||||
else
|
||||
You("enter %s %s%s!",
|
||||
s_suffix(shkname(shkp)),
|
||||
@@ -691,10 +702,10 @@ struct obj *obj;
|
||||
cad(FALSE));
|
||||
else
|
||||
pline("%s %s your pick!",
|
||||
Shknam(shkp),
|
||||
haseyes(shkp->data) ? "glares at"
|
||||
: "is dismayed because of");
|
||||
}
|
||||
Shknam(shkp),
|
||||
haseyes(shkp->data) ? "glares at"
|
||||
: "is dismayed because of");
|
||||
}
|
||||
pickmovetime = moves;
|
||||
}
|
||||
}
|
||||
@@ -801,11 +812,11 @@ register struct monst *mtmp;
|
||||
|
||||
struct monst *
|
||||
shop_keeper(rmno)
|
||||
register char rmno;
|
||||
char rmno;
|
||||
{
|
||||
struct monst *shkp =
|
||||
rmno >= ROOMOFFSET ? rooms[rmno - ROOMOFFSET].resident : 0;
|
||||
struct monst *shkp;
|
||||
|
||||
shkp = (rmno >= ROOMOFFSET) ? rooms[rmno - ROOMOFFSET].resident : 0;
|
||||
if (shkp) {
|
||||
if (has_eshk(shkp)) {
|
||||
if (NOTANGRY(shkp)) {
|
||||
@@ -817,16 +828,18 @@ register char rmno;
|
||||
}
|
||||
} else {
|
||||
/* would have segfaulted on ESHK dereference previously */
|
||||
impossible(
|
||||
"shopkeeper career change? (rmno=%d, ROOMOFFSET=%d, mnum=%d, %s)",
|
||||
(int)rmno, ROOMOFFSET, shkp->mnum,
|
||||
has_mname(shkp) ? MNAME(shkp) : "anonymous"
|
||||
);
|
||||
|
||||
impossible("%s? (rmno=%d, rtype=%d, mnum=%d, \"%s\")",
|
||||
shkp->isshk ? "shopkeeper career change"
|
||||
: "shop resident not shopkeeper",
|
||||
(int) rmno,
|
||||
(int) rooms[rmno - ROOMOFFSET].rtype,
|
||||
shkp->mnum,
|
||||
/* [real shopkeeper name is kept in ESHK, not MNAME] */
|
||||
has_mname(shkp) ? MNAME(shkp) : "anonymous");
|
||||
/* not sure if this is appropriate, because it does nothing to
|
||||
correct the underlying rooms[].resident issue but... */
|
||||
return (struct monst *)0;
|
||||
}
|
||||
return (struct monst *) 0;
|
||||
}
|
||||
}
|
||||
return shkp;
|
||||
}
|
||||
@@ -858,7 +871,7 @@ boolean silent;
|
||||
} else
|
||||
bp++;
|
||||
}
|
||||
if (obj->unpaid & !silent)
|
||||
if (obj->unpaid && !silent)
|
||||
pline("onbill: unpaid obj not on bill?");
|
||||
return (struct bill_x *) 0;
|
||||
}
|
||||
@@ -1599,13 +1612,13 @@ boolean itemize;
|
||||
ANGRY(shkp) ? "Pay" : "Please pay",
|
||||
simpleonames(obj), /* short name suffices */
|
||||
save_quan > 1L ? "these" : "this one");
|
||||
} else {
|
||||
pline("%s %s%s your bill for the other %s first.",
|
||||
Shknam(shkp),
|
||||
} else {
|
||||
pline("%s %s%s your bill for the other %s first.",
|
||||
Shknam(shkp),
|
||||
ANGRY(shkp) ? "angrily " : "",
|
||||
nolimbs(shkp->data) ? "motions to" : "points out",
|
||||
simpleonames(obj));
|
||||
}
|
||||
nolimbs(shkp->data) ? "motions to" : "points out",
|
||||
simpleonames(obj));
|
||||
}
|
||||
buy = PAY_SKIP; /* shk won't sell */
|
||||
}
|
||||
}
|
||||
@@ -2189,12 +2202,12 @@ boolean quietly;
|
||||
pline("%s seems %s that you want to sell that.",
|
||||
Shknam(shkp),
|
||||
(obj->spe < 7) ? "horrified" : "concerned");
|
||||
} else {
|
||||
} else {
|
||||
verbalize("No thanks, I'd hang onto that if I were you.");
|
||||
if (obj->spe < 7)
|
||||
verbalize(
|
||||
"You'll need %d%s candle%s to go along with it.",
|
||||
(7 - obj->spe), (obj->spe > 0) ? " more" : "",
|
||||
"You'll need %d%s candle%s to go along with it.",
|
||||
(7 - obj->spe), (obj->spe > 0) ? " more" : "",
|
||||
plur(7 - obj->spe));
|
||||
/* [what if hero is already carrying enough candles?
|
||||
should Izchak explain how to attach them instead?] */
|
||||
@@ -2546,9 +2559,10 @@ boolean ininv, dummy, silent;
|
||||
}
|
||||
obj->quan = 1L; /* fool xname() into giving singular */
|
||||
pline("%s %ld %s %s %s%s.\"", buf, ltmp, currency(ltmp),
|
||||
(save_quan > 1L) ? "per" : (contentscount && !obj->unpaid)
|
||||
? "for the contents of this"
|
||||
: "for this",
|
||||
(save_quan > 1L) ? "per"
|
||||
: (contentscount && !obj->unpaid)
|
||||
? "for the contents of this"
|
||||
: "for this",
|
||||
xname(obj),
|
||||
(contentscount && obj->unpaid) ? and_its_contents : "");
|
||||
obj->quan = save_quan;
|
||||
@@ -2879,12 +2893,13 @@ xchar x, y;
|
||||
offer = ltmp + cltmp;
|
||||
|
||||
/* get one case out of the way: nothing to sell, and no gold */
|
||||
if (!isgold && ((offer + gltmp) == 0L || sell_how == SELL_DONTSELL)) {
|
||||
if (!(isgold || cgold)
|
||||
&& ((offer + gltmp) == 0L || sell_how == SELL_DONTSELL)) {
|
||||
boolean unpaid = is_unpaid(obj);
|
||||
|
||||
if (container) {
|
||||
dropped_container(obj, shkp, FALSE);
|
||||
if (!obj->unpaid && !saleitem)
|
||||
if (!obj->unpaid)
|
||||
obj->no_charge = 1;
|
||||
if (unpaid)
|
||||
subfrombill(obj, shkp);
|
||||
@@ -2955,11 +2970,11 @@ xchar x, y;
|
||||
currency(eshkp->credit));
|
||||
}
|
||||
|
||||
if (!offer) {
|
||||
if (!offer || sell_how == SELL_DONTSELL) {
|
||||
if (!isgold) {
|
||||
if (container)
|
||||
dropped_container(obj, shkp, FALSE);
|
||||
if (!obj->unpaid && !saleitem)
|
||||
if (!obj->unpaid)
|
||||
obj->no_charge = 1;
|
||||
subfrombill(obj, shkp);
|
||||
}
|
||||
@@ -3934,7 +3949,7 @@ boolean cant_mollify;
|
||||
if (!Deaf && !muteshk(shkp)) {
|
||||
You_hear("an angry voice:");
|
||||
verbalize("Out of my way, scum!");
|
||||
}
|
||||
}
|
||||
wait_synch();
|
||||
#if defined(UNIX) || defined(VMS)
|
||||
#if defined(SYSV) || defined(ULTRIX) || defined(VMS)
|
||||
@@ -3959,26 +3974,21 @@ boolean cant_mollify;
|
||||
} else if (pursue || uinshp || !um_dist(x, y, 1)) {
|
||||
if (!Deaf)
|
||||
verbalize("How dare you %s my %s?", dmgstr,
|
||||
dugwall ? "shop" : "door");
|
||||
dugwall ? "shop" : "door");
|
||||
else
|
||||
pline("%s is %s that you decided to %s %s %s!",
|
||||
Shknam(shkp),
|
||||
angrytexts[rn2(SIZE(angrytexts))],
|
||||
dmgstr, mhis(shkp),
|
||||
dugwall ? "shop" : "door");
|
||||
Shknam(shkp), angrytexts[rn2(SIZE(angrytexts))],
|
||||
dmgstr, mhis(shkp), dugwall ? "shop" : "door");
|
||||
} else {
|
||||
if (!Deaf) {
|
||||
pline("%s shouts:", shkname(shkp));
|
||||
verbalize("Who dared %s my %s?", dmgstr,
|
||||
dugwall ? "shop" : "door");
|
||||
} else {
|
||||
} else {
|
||||
pline("%s is %s that someone decided to %s %s %s!",
|
||||
Shknam(shkp),
|
||||
angrytexts[rn2(SIZE(angrytexts))],
|
||||
dmgstr,
|
||||
mhis(shkp),
|
||||
dugwall ? "shop" : "door");
|
||||
}
|
||||
Shknam(shkp), angrytexts[rn2(SIZE(angrytexts))],
|
||||
dmgstr, mhis(shkp), dugwall ? "shop" : "door");
|
||||
}
|
||||
}
|
||||
hot_pursuit(shkp);
|
||||
return;
|
||||
@@ -4116,6 +4126,7 @@ long cost;
|
||||
{
|
||||
if (!rn2(3)) {
|
||||
register int o, choice = rn2(5);
|
||||
|
||||
if (choice == 0)
|
||||
choice = (cost < 100L ? 1 : cost < 500L ? 2 : 3);
|
||||
switch (choice) {
|
||||
@@ -4200,7 +4211,6 @@ struct monst *shkp;
|
||||
else
|
||||
pline("%s taps you on the %s.",
|
||||
Shknam(shkp), body_part(ARM));
|
||||
|
||||
}
|
||||
} else if (eshk->billct) {
|
||||
register long total = addupbill(shkp) + eshk->debit;
|
||||
@@ -4218,10 +4228,10 @@ struct monst *shkp;
|
||||
pline("%s encourages you to use your %ld %s of credit.",
|
||||
shkname(shkp), eshk->credit, currency(eshk->credit));
|
||||
} else if (eshk->robbed) {
|
||||
pline("%s %s about a recent robbery.",
|
||||
Shknam(shkp),
|
||||
(!Deaf && !muteshk(shkp)) ? "complains" : "indicates concern");
|
||||
} else if ((shkmoney = money_cnt(shkp->minvent)) < 50) {
|
||||
pline("%s %s about a recent robbery.",
|
||||
Shknam(shkp),
|
||||
(!Deaf && !muteshk(shkp)) ? "complains" : "indicates concern");
|
||||
} else if ((shkmoney = money_cnt(shkp->minvent)) < 50L) {
|
||||
pline("%s %s that business is bad.",
|
||||
shkname(shkp),
|
||||
(!Deaf && !muteshk(shkp)) ? "complains" : "indicates");
|
||||
|
||||
+28
-28
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "hack.h"
|
||||
|
||||
STATIC_DCL boolean FDECL(stock_room_goodpos, (struct mkroom *, int, int, int, int));
|
||||
STATIC_DCL boolean FDECL(veggy_item, (struct obj * obj, int));
|
||||
STATIC_DCL int NDECL(shkveg);
|
||||
STATIC_DCL void FDECL(mkveggy_at, (int, int));
|
||||
@@ -676,6 +677,24 @@ struct mkroom *sroom;
|
||||
return sh;
|
||||
}
|
||||
|
||||
STATIC_OVL boolean
|
||||
stock_room_goodpos(sroom, rmno, sh, sx, sy)
|
||||
struct mkroom *sroom;
|
||||
int rmno, sh, sx,sy;
|
||||
{
|
||||
if (sroom->irregular) {
|
||||
if (levl[sx][sy].edge
|
||||
|| (int) levl[sx][sy].roomno != rmno
|
||||
|| distmin(sx, sy, doors[sh].x, doors[sh].y) <= 1)
|
||||
return FALSE;
|
||||
} else if ((sx == sroom->lx && doors[sh].x == sx - 1)
|
||||
|| (sx == sroom->hx && doors[sh].x == sx + 1)
|
||||
|| (sy == sroom->ly && doors[sh].y == sy - 1)
|
||||
|| (sy == sroom->hy && doors[sh].y == sy + 1))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* stock a newly-created room with objects */
|
||||
void
|
||||
stock_room(shp_indx, sroom)
|
||||
@@ -733,39 +752,20 @@ register struct mkroom *sroom;
|
||||
* going to put stuff, randomly single out one in particular.
|
||||
*/
|
||||
for (sx = sroom->lx; sx <= sroom->hx; sx++)
|
||||
for (sy = sroom->ly; sy <= sroom->hy; sy++) {
|
||||
if (sroom->irregular) {
|
||||
if (levl[sx][sy].edge
|
||||
|| (int) levl[sx][sy].roomno != rmno
|
||||
|| distmin(sx, sy, doors[sh].x, doors[sh].y) <= 1)
|
||||
continue;
|
||||
} else if ((sx == sroom->lx && doors[sh].x == sx - 1)
|
||||
|| (sx == sroom->hx && doors[sh].x == sx + 1)
|
||||
|| (sy == sroom->ly && doors[sh].y == sy - 1)
|
||||
|| (sy == sroom->hy && doors[sh].y == sy + 1))
|
||||
continue;
|
||||
stockcount++;
|
||||
}
|
||||
for (sy = sroom->ly; sy <= sroom->hy; sy++)
|
||||
if (stock_room_goodpos(sroom, rmno, sh, sx,sy))
|
||||
stockcount++;
|
||||
specialspot = rnd(stockcount);
|
||||
stockcount = 0;
|
||||
}
|
||||
|
||||
for (sx = sroom->lx; sx <= sroom->hx; sx++)
|
||||
for (sy = sroom->ly; sy <= sroom->hy; sy++) {
|
||||
if (sroom->irregular) {
|
||||
if (levl[sx][sy].edge
|
||||
|| (int) levl[sx][sy].roomno != rmno
|
||||
|| distmin(sx, sy, doors[sh].x, doors[sh].y) <= 1)
|
||||
continue;
|
||||
} else if ((sx == sroom->lx && doors[sh].x == sx - 1)
|
||||
|| (sx == sroom->hx && doors[sh].x == sx + 1)
|
||||
|| (sy == sroom->ly && doors[sh].y == sy - 1)
|
||||
|| (sy == sroom->hy && doors[sh].y == sy + 1))
|
||||
continue;
|
||||
stockcount++;
|
||||
mkshobj_at(shp, sx, sy,
|
||||
((stockcount) && (stockcount == specialspot)));
|
||||
}
|
||||
for (sy = sroom->ly; sy <= sroom->hy; sy++)
|
||||
if (stock_room_goodpos(sroom, rmno, sh, sx,sy)) {
|
||||
stockcount++;
|
||||
mkshobj_at(shp, sx, sy,
|
||||
((stockcount) && (stockcount == specialspot)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Special monster placements (if any) should go here: that way,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 sit.c $NHDT-Date: 1445906863 2015/10/27 00:47:43 $ $NHDT-Branch: master $:$NHDT-Revision: 1.51 $ */
|
||||
/* NetHack 3.6 sit.c $NHDT-Date: 1458341129 2016/03/18 22:45:29 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.53 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -184,6 +184,7 @@ dosit()
|
||||
if (u.uhp >= (u.uhpmax - 5))
|
||||
u.uhpmax += 4;
|
||||
u.uhp = u.uhpmax;
|
||||
u.ucreamed = 0;
|
||||
make_blinded(0L, TRUE);
|
||||
make_sick(0L, (char *) 0, FALSE, SICK_ALL);
|
||||
heal_legs();
|
||||
@@ -225,6 +226,7 @@ dosit()
|
||||
"A curse upon thee for sitting upon this most holy throne!");
|
||||
if (Luck > 0) {
|
||||
make_blinded(Blinded + rn1(100, 250), TRUE);
|
||||
change_luck((Luck > 1) ? -rnd(2) : -1);
|
||||
} else
|
||||
rndcurse();
|
||||
break;
|
||||
|
||||
+35
-20
@@ -72,6 +72,7 @@ STATIC_DCL void FDECL(create_door, (room_door *, struct mkroom *));
|
||||
STATIC_DCL void FDECL(create_trap, (trap *, struct mkroom *));
|
||||
STATIC_DCL int FDECL(noncoalignment, (ALIGNTYP_P));
|
||||
STATIC_DCL boolean FDECL(m_bad_boulder_spot, (int, int));
|
||||
STATIC_DCL int FDECL(pm_to_humidity, (struct permonst *));
|
||||
STATIC_DCL void FDECL(create_monster, (monster *, struct mkroom *));
|
||||
STATIC_DCL void FDECL(create_object, (object *, struct mkroom *));
|
||||
STATIC_DCL void FDECL(create_altar, (altar *, struct mkroom *));
|
||||
@@ -611,8 +612,8 @@ schar filling;
|
||||
if (level.flags.corrmaze)
|
||||
levl[x][y].typ = STONE;
|
||||
else
|
||||
levl[x][y].typ =
|
||||
(y < 2 || ((x % 2) && (y % 2))) ? STONE : filling;
|
||||
levl[x][y].typ = (y < 2 || ((x % 2) && (y % 2))) ? STONE
|
||||
: filling;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -895,6 +896,8 @@ register int humidity;
|
||||
|| typ == CORR)
|
||||
return TRUE;
|
||||
}
|
||||
if ((humidity & SPACELOC) && SPACE_POS(levl[x][y].typ))
|
||||
return TRUE;
|
||||
if ((humidity & WET) && is_pool(x, y))
|
||||
return TRUE;
|
||||
if ((humidity & HOT) && is_lava(x, y))
|
||||
@@ -1495,6 +1498,24 @@ int x, y;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
STATIC_OVL int
|
||||
pm_to_humidity(pm)
|
||||
struct permonst *pm;
|
||||
{
|
||||
int loc = DRY;
|
||||
if (!pm)
|
||||
return loc;
|
||||
if (pm->mlet == S_EEL || amphibious(pm) || is_swimmer(pm))
|
||||
loc = WET;
|
||||
if (is_flyer(pm) || is_floater(pm))
|
||||
loc |= (HOT | WET);
|
||||
if (passes_walls(pm) || noncorporeal(pm))
|
||||
loc |= SOLID;
|
||||
if (flaming(pm))
|
||||
loc |= HOT;
|
||||
return loc;
|
||||
}
|
||||
|
||||
STATIC_OVL void
|
||||
create_monster(m, croom)
|
||||
monster *m;
|
||||
@@ -1543,15 +1564,7 @@ struct mkroom *croom;
|
||||
pm = (struct permonst *) 0;
|
||||
|
||||
if (pm) {
|
||||
int loc = DRY;
|
||||
if (pm->mlet == S_EEL || amphibious(pm) || is_swimmer(pm))
|
||||
loc = WET;
|
||||
if (is_flyer(pm) || is_floater(pm))
|
||||
loc |= (HOT | WET);
|
||||
if (passes_walls(pm) || noncorporeal(pm))
|
||||
loc |= SOLID;
|
||||
if (flaming(pm))
|
||||
loc |= HOT;
|
||||
int loc = pm_to_humidity(pm);
|
||||
/* If water-liking monster, first try is without DRY */
|
||||
get_location_coord(&x, &y, loc | NO_LOC_WARN, croom, m->coord);
|
||||
if (x == -1 && y == -1) {
|
||||
@@ -4089,8 +4102,8 @@ struct opvar *ov;
|
||||
my = ((y1 + y2) / 2);
|
||||
} else {
|
||||
do {
|
||||
dx = (Rand() % rough) - (rough / 2);
|
||||
dy = (Rand() % rough) - (rough / 2);
|
||||
dx = rn2(rough) - (rough / 2);
|
||||
dy = rn2(rough) - (rough / 2);
|
||||
mx = ((x1 + x2) / 2) + dx;
|
||||
my = ((y1 + y2) / 2) + dy;
|
||||
} while ((mx > COLNO - 1 || mx < 0 || my < 0 || my > ROWNO - 1));
|
||||
@@ -4747,7 +4760,8 @@ struct sp_coder *coder;
|
||||
dy1 = (xchar) SP_REGION_Y1(OV_i(r));
|
||||
dx2 = (xchar) SP_REGION_X2(OV_i(r));
|
||||
dy2 = (xchar) SP_REGION_Y2(OV_i(r));
|
||||
wallify_map(dx1 < 0 ? (xstart-1) : dx1, dy1 < 0 ? (ystart-1) : dy1,
|
||||
wallify_map(dx1 < 0 ? (xstart - 1) : dx1,
|
||||
dy1 < 0 ? (ystart - 1) : dy1,
|
||||
dx2 < 0 ? (xstart + xsize + 1) : dx2,
|
||||
dy2 < 0 ? (ystart + ysize + 1) : dy2);
|
||||
break;
|
||||
@@ -4846,7 +4860,7 @@ struct sp_coder *coder;
|
||||
ystart = valign;
|
||||
break;
|
||||
}
|
||||
if ((ystart < 0) || (ystart + ysize > ROWNO)) {
|
||||
if (ystart < 0 || ystart + ysize > ROWNO) {
|
||||
/* try to move the start a bit */
|
||||
ystart += (ystart > 0) ? -2 : 2;
|
||||
if (ysize == ROWNO)
|
||||
@@ -4860,13 +4874,13 @@ struct sp_coder *coder;
|
||||
xsize = COLNO - 1;
|
||||
ysize = ROWNO;
|
||||
} else {
|
||||
xchar x, y;
|
||||
xchar x, y, mptyp;
|
||||
|
||||
/* Load the map */
|
||||
for (y = ystart; y < ystart + ysize; y++)
|
||||
for (x = xstart; x < xstart + xsize; x++) {
|
||||
xchar mptyp =
|
||||
(mpmap->vardata.str[(y - ystart) * xsize + (x - xstart)]
|
||||
- 1);
|
||||
mptyp = (mpmap->vardata.str[(y - ystart) * xsize
|
||||
+ (x - xstart)] - 1);
|
||||
if (mptyp >= MAX_TYPE)
|
||||
continue;
|
||||
levl[x][y].typ = mptyp;
|
||||
@@ -5907,7 +5921,8 @@ const char *name;
|
||||
(void) dlb_fclose(fd);
|
||||
goto give_up;
|
||||
}
|
||||
lvl = (sp_lev *) alloc(sizeof(sp_lev));
|
||||
|
||||
lvl = (sp_lev *) alloc(sizeof (sp_lev));
|
||||
result = sp_level_loader(fd, lvl);
|
||||
(void) dlb_fclose(fd);
|
||||
if (result)
|
||||
|
||||
+2
-2
@@ -866,8 +866,8 @@ int spell;
|
||||
break;
|
||||
case 7:
|
||||
case 8:
|
||||
make_stunned(old_conf + 2L * duration / 3L, FALSE); /* 20% */
|
||||
make_confused(old_stun + duration / 3L, FALSE);
|
||||
make_stunned(old_stun + 2L * duration / 3L, FALSE); /* 20% */
|
||||
make_confused(old_conf + duration / 3L, FALSE);
|
||||
break;
|
||||
case 9:
|
||||
make_stunned(old_stun + duration, FALSE); /* 10% */
|
||||
|
||||
+5
-4
@@ -646,10 +646,11 @@ boolean verbosely;
|
||||
if (mon->mhp > 0) {
|
||||
mon->misc_worn_check &= ~obj->owornmask;
|
||||
update_mon = TRUE;
|
||||
/* don't charge for an owned saddle on dead steed (provided
|
||||
that the hero is within the same shop at the time) */
|
||||
} else if (mon->mtame && (obj->owornmask & W_SADDLE) && !obj->unpaid
|
||||
&& costly_spot(omx, omy)
|
||||
|
||||
/* don't charge for an owned saddle on dead steed (provided
|
||||
that the hero is within the same shop at the time) */
|
||||
} else if (mon->mtame && (obj->owornmask & W_SADDLE) != 0L
|
||||
&& !obj->unpaid && costly_spot(omx, omy)
|
||||
/* being at costly_spot guarantees lev->roomno is not 0 */
|
||||
&& index(in_rooms(u.ux, u.uy, SHOPBASE),
|
||||
levl[omx][omy].roomno)) {
|
||||
|
||||
+3
-1
@@ -128,7 +128,9 @@ unsigned entflags;
|
||||
/* default to player's original monster type */
|
||||
mdat = &mons[u.umonster];
|
||||
}
|
||||
fakemon.data = mdat; /* set up for goodpos */
|
||||
fakemon = zeromonst;
|
||||
set_mon_data(&fakemon, mdat, -1); /* set up for goodpos */
|
||||
|
||||
good_ptr = good;
|
||||
range = 1;
|
||||
/*
|
||||
|
||||
@@ -1533,6 +1533,7 @@ anything *arg;
|
||||
panic("start_timer");
|
||||
|
||||
gnu = (timer_element *) alloc(sizeof(timer_element));
|
||||
(void) memset((genericptr_t)gnu, 0, sizeof(timer_element));
|
||||
gnu->next = 0;
|
||||
gnu->tid = timer_id++;
|
||||
gnu->timeout = monstermoves + when;
|
||||
@@ -1998,6 +1999,23 @@ long adjust; /* how much to adjust timeout */
|
||||
}
|
||||
}
|
||||
|
||||
/* to support '#stats' wizard-mode command */
|
||||
void
|
||||
timer_stats(hdrfmt, hdrbuf, count, size)
|
||||
const char *hdrfmt;
|
||||
char *hdrbuf;
|
||||
long *count, *size;
|
||||
{
|
||||
timer_element *te;
|
||||
|
||||
Sprintf(hdrbuf, hdrfmt, (long) sizeof (timer_element));
|
||||
*count = *size = 0L;
|
||||
for (te = timer_base; te; te = te->next) {
|
||||
++*count;
|
||||
*size += (long) sizeof *te;
|
||||
}
|
||||
}
|
||||
|
||||
/* reset all timers that are marked for reseting */
|
||||
void
|
||||
relink_timers(ghostly)
|
||||
|
||||
+74
-64
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 trap.c $NHDT-Date: 1454528963 2016/02/03 19:49:23 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.261 $ */
|
||||
/* NetHack 3.6 trap.c $NHDT-Date: 1464138044 2016/05/25 01:00:44 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.272 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -197,6 +197,8 @@ int ef_flags;
|
||||
if (check_grease && otmp->greased) {
|
||||
grease_protect(otmp, ostr, victim);
|
||||
return ER_GREASED;
|
||||
} else if (!erosion_matters(otmp)) {
|
||||
return ER_NOTHING;
|
||||
} else if (!vulnerable || (otmp->oerodeproof && otmp->rknown)) {
|
||||
if (flags.verbose && print && (uvictim || vismon))
|
||||
pline("%s %s %s not affected by %s.",
|
||||
@@ -309,12 +311,12 @@ struct monst *victim;
|
||||
|
||||
struct trap *
|
||||
maketrap(x, y, typ)
|
||||
register int x, y, typ;
|
||||
int x, y, typ;
|
||||
{
|
||||
static union vlaunchinfo zero_vl;
|
||||
register struct trap *ttmp;
|
||||
register struct rm *lev;
|
||||
boolean oldplace;
|
||||
struct trap *ttmp;
|
||||
struct rm *lev = &levl[x][y];
|
||||
|
||||
if ((ttmp = t_at(x, y)) != 0) {
|
||||
if (ttmp->ttyp == MAGIC_PORTAL || ttmp->ttyp == VIBRATING_SQUARE)
|
||||
@@ -327,13 +329,15 @@ register int x, y, typ;
|
||||
&& typ != SPIKED_PIT)))
|
||||
u.utrap = 0;
|
||||
/* old <tx,ty> remain valid */
|
||||
} else if (IS_FURNITURE(levl[x][y].typ)) {
|
||||
} else if (IS_FURNITURE(lev->typ)
|
||||
&& (!IS_GRAVE(lev->typ) || (typ != PIT && typ != HOLE))) {
|
||||
/* no trap on top of furniture (caller usually screens the
|
||||
location to inhibit this, but wizard mode wishing doesn't) */
|
||||
return (struct trap *) 0;
|
||||
} else {
|
||||
oldplace = FALSE;
|
||||
ttmp = newtrap();
|
||||
(void) memset((genericptr_t)ttmp, 0, sizeof(struct trap));
|
||||
ttmp->ntrap = 0;
|
||||
ttmp->tx = x;
|
||||
ttmp->ty = y;
|
||||
@@ -399,7 +403,6 @@ register int x, y, typ;
|
||||
/*FALLTHRU*/
|
||||
case HOLE:
|
||||
case TRAPDOOR:
|
||||
lev = &levl[x][y];
|
||||
if (*in_rooms(x, y, SHOPBASE)
|
||||
&& (typ == HOLE || typ == TRAPDOOR
|
||||
|| IS_DOOR(lev->typ) || IS_WALL(lev->typ)))
|
||||
@@ -687,6 +690,7 @@ int *fail_reason;
|
||||
which refers to "it" so needs to follow a message describing
|
||||
the object ("the statue comes to life" one above) */
|
||||
if (cause != ANIMATE_NORMAL && costly_spot(x, y)
|
||||
&& (carried(statue) ? statue->unpaid : !statue->no_charge)
|
||||
&& (shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) != 0
|
||||
/* avoid charging for Manlobbi's statue of Manlobbi
|
||||
if stone-to-flesh is used on petrified shopkeep */
|
||||
@@ -791,6 +795,49 @@ struct obj *objchn, *saddle;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* monster or you go through and possibly destroy a web.
|
||||
return TRUE if could go through. */
|
||||
boolean
|
||||
mu_maybe_destroy_web(mtmp, domsg, trap)
|
||||
struct monst *mtmp;
|
||||
boolean domsg;
|
||||
struct trap *trap;
|
||||
{
|
||||
boolean isyou = (mtmp == &youmonst);
|
||||
struct permonst *mptr = mtmp->data;
|
||||
if (amorphous(mptr) || is_whirly(mptr) || flaming(mptr)
|
||||
|| unsolid(mptr) || mptr == &mons[PM_GELATINOUS_CUBE]) {
|
||||
xchar x = trap->tx;
|
||||
xchar y = trap->ty;
|
||||
if (flaming(mptr) || acidic(mptr)) {
|
||||
if (domsg) {
|
||||
if (isyou)
|
||||
You("%s %s spider web!",
|
||||
(flaming(mptr)) ? "burn" : "dissolve",
|
||||
a_your[trap->madeby_u]);
|
||||
else
|
||||
pline("%s %s %s spider web!", Monnam(mtmp),
|
||||
(flaming(mptr)) ? "burns" : "dissolves",
|
||||
a_your[trap->madeby_u]);
|
||||
}
|
||||
deltrap(trap);
|
||||
newsym(x, y);
|
||||
return TRUE;
|
||||
}
|
||||
if (domsg) {
|
||||
if (isyou)
|
||||
You("flow through %s spider web.", a_your[trap->madeby_u]);
|
||||
else {
|
||||
pline("%s flows through %s spider web.", Monnam(mtmp),
|
||||
a_your[trap->madeby_u]);
|
||||
seetrap(trap);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
dotrap(trap, trflags)
|
||||
register struct trap *trap;
|
||||
@@ -1195,23 +1242,8 @@ unsigned trflags;
|
||||
|
||||
case WEB: /* Our luckless player has stumbled into a web. */
|
||||
feeltrap(trap);
|
||||
if (amorphous(youmonst.data) || is_whirly(youmonst.data)
|
||||
|| unsolid(youmonst.data)) {
|
||||
if (acidic(youmonst.data) || u.umonnum == PM_GELATINOUS_CUBE
|
||||
|| u.umonnum == PM_FIRE_ELEMENTAL) {
|
||||
if (webmsgok)
|
||||
You("%s %s spider web!",
|
||||
(u.umonnum == PM_FIRE_ELEMENTAL) ? "burn"
|
||||
: "dissolve",
|
||||
a_your[trap->madeby_u]);
|
||||
deltrap(trap);
|
||||
newsym(u.ux, u.uy);
|
||||
break;
|
||||
}
|
||||
if (webmsgok)
|
||||
You("flow through %s spider web.", a_your[trap->madeby_u]);
|
||||
if (mu_maybe_destroy_web(&youmonst, webmsgok, trap))
|
||||
break;
|
||||
}
|
||||
if (webmaker(youmonst.data)) {
|
||||
if (webmsgok)
|
||||
pline(trap->madeby_u ? "You take a walk on your web."
|
||||
@@ -2410,28 +2442,8 @@ register struct monst *mtmp;
|
||||
/* Monster in a web. */
|
||||
if (webmaker(mptr))
|
||||
break;
|
||||
if (amorphous(mptr) || is_whirly(mptr) || unsolid(mptr)) {
|
||||
if (acidic(mptr) || mptr == &mons[PM_GELATINOUS_CUBE]
|
||||
|| mptr == &mons[PM_FIRE_ELEMENTAL]
|
||||
|| mptr == &mons[PM_FIRE_VORTEX]) {
|
||||
if (in_sight)
|
||||
pline("%s %s %s spider web!", Monnam(mtmp),
|
||||
(mptr == &mons[PM_FIRE_ELEMENTAL]
|
||||
|| mptr == &mons[PM_FIRE_VORTEX])
|
||||
? "burns"
|
||||
: "dissolves",
|
||||
a_your[trap->madeby_u]);
|
||||
deltrap(trap);
|
||||
newsym(mtmp->mx, mtmp->my);
|
||||
break;
|
||||
}
|
||||
if (in_sight) {
|
||||
pline("%s flows through %s spider web.", Monnam(mtmp),
|
||||
a_your[trap->madeby_u]);
|
||||
seetrap(trap);
|
||||
}
|
||||
if (mu_maybe_destroy_web(mtmp, in_sight, trap))
|
||||
break;
|
||||
}
|
||||
tear_web = FALSE;
|
||||
switch (monsndx(mptr)) {
|
||||
case PM_OWLBEAR: /* Eric Backus */
|
||||
@@ -2521,7 +2533,8 @@ register struct monst *mtmp;
|
||||
|
||||
if (in_sight)
|
||||
seetrap(trap);
|
||||
if ((mtmp->mhp -= dmgval2) <= 0)
|
||||
mtmp->mhp -= dmgval2;
|
||||
if (mtmp->mhp <= 0)
|
||||
monkilled(mtmp,
|
||||
in_sight
|
||||
? "compression from an anti-magic field"
|
||||
@@ -2553,18 +2566,19 @@ register struct monst *mtmp;
|
||||
}
|
||||
} else if (in_sight) {
|
||||
newsym(mtmp->mx, mtmp->my);
|
||||
pline("KAABLAMM!!! %s triggers %s land mine!", Monnam(mtmp),
|
||||
pline("%s%s triggers %s land mine!",
|
||||
!Deaf ? "KAABLAMM!!! " : "", Monnam(mtmp),
|
||||
a_your[trap->madeby_u]);
|
||||
}
|
||||
if (!in_sight)
|
||||
if (!in_sight && !Deaf)
|
||||
pline("Kaablamm! You hear an explosion in the distance!");
|
||||
blow_up_landmine(trap);
|
||||
/* explosion might have destroyed a drawbridge; don't
|
||||
dish out more damage if monster is already dead */
|
||||
if (mtmp->mhp <= 0
|
||||
|| thitm(0, mtmp, (struct obj *) 0, rnd(16), FALSE))
|
||||
|| thitm(0, mtmp, (struct obj *) 0, rnd(16), FALSE)) {
|
||||
trapkilled = TRUE;
|
||||
else {
|
||||
} else {
|
||||
/* monsters recursively fall into new pit */
|
||||
if (mintrap(mtmp) == 2)
|
||||
trapkilled = TRUE;
|
||||
@@ -2668,7 +2682,7 @@ boolean byplayer;
|
||||
pline("%s turns to stone.", Monnam(mon));
|
||||
if (byplayer) {
|
||||
stoned = TRUE;
|
||||
xkilled(mon, 0);
|
||||
xkilled(mon, XKILL_NOMSG);
|
||||
} else
|
||||
monstone(mon);
|
||||
}
|
||||
@@ -3874,7 +3888,8 @@ boolean force_failure;
|
||||
if (ttype == BEAR_TRAP) {
|
||||
if (mtmp->mtame)
|
||||
abuse_dog(mtmp);
|
||||
if ((mtmp->mhp -= rnd(4)) <= 0)
|
||||
mtmp->mhp -= rnd(4);
|
||||
if (mtmp->mhp <= 0)
|
||||
killed(mtmp);
|
||||
} else if (ttype == WEB) {
|
||||
if (!webmaker(youmonst.data)) {
|
||||
@@ -4524,7 +4539,7 @@ boolean *noticed; /* set to true iff hero notices the effect; */
|
||||
--force_mintrap;
|
||||
/* mon might now be on the migrating monsters list */
|
||||
}
|
||||
return TRUE;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* only called when the player is doing something to the chest directly */
|
||||
@@ -4605,16 +4620,11 @@ boolean disarm;
|
||||
loss += stolen_value(obj, ox, oy, (boolean) shkp->mpeaceful,
|
||||
TRUE);
|
||||
delete_contents(obj);
|
||||
/* we're about to delete all things at this location,
|
||||
* which could include the ball & chain.
|
||||
* If we attempt to call unpunish() in the
|
||||
* for-loop below we can end up with otmp2
|
||||
* being invalid once the chain is gone.
|
||||
* Deal with ball & chain right now instead.
|
||||
*/
|
||||
if (Punished && !carried(uball)
|
||||
&& ((uchain->ox == u.ux && uchain->oy == u.uy)
|
||||
|| (uball->ox == u.ux && uball->oy == u.uy)))
|
||||
/* unpunish() in advance if either ball or chain (or both)
|
||||
is going to be destroyed */
|
||||
if (Punished && ((uchain->ox == u.ux && uchain->oy == u.uy)
|
||||
|| (uball->where == OBJ_FLOOR
|
||||
&& uball->ox == u.ux && uball->oy == u.uy)))
|
||||
unpunish();
|
||||
|
||||
for (otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp2) {
|
||||
@@ -4935,9 +4945,9 @@ boolean nocorpse;
|
||||
if (dam < 1)
|
||||
dam = 1;
|
||||
}
|
||||
if ((mon->mhp -= dam) <= 0) {
|
||||
int xx = mon->mx;
|
||||
int yy = mon->my;
|
||||
mon->mhp -= dam;
|
||||
if (mon->mhp <= 0) {
|
||||
int xx = mon->mx, yy = mon->my;
|
||||
|
||||
monkilled(mon, "", nocorpse ? -AD_RBRE : AD_PHYS);
|
||||
if (mon->mhp <= 0) {
|
||||
|
||||
+30
-20
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 uhitm.c $NHDT-Date: 1456992470 2016/03/03 08:07:50 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.155 $ */
|
||||
/* NetHack 3.6 uhitm.c $NHDT-Date: 1460103141 2016/04/08 08:12:21 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.156 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -662,15 +662,19 @@ int thrown; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
|
||||
&& P_SKILL(wtype) >= P_SKILLED)
|
||||
&& ((monwep = MON_WEP(mon)) != 0
|
||||
&& !is_flimsy(monwep)
|
||||
&& !obj_resists(
|
||||
monwep, 50 + 15 * greatest_erosion(obj),
|
||||
100))) {
|
||||
&& !obj_resists(monwep,
|
||||
50 + 15 * (greatest_erosion(obj)
|
||||
- greatest_erosion(monwep)),
|
||||
100))) {
|
||||
/*
|
||||
* 2.5% chance of shattering defender's weapon when
|
||||
* using a two-handed weapon; less if uwep is rusted.
|
||||
* [dieroll == 2 is most successful non-beheading or
|
||||
* -bisecting hit, in case of special artifact damage;
|
||||
* the percentage chance is (1/20)*(50/100).]
|
||||
* If attacker's weapon is rustier than defender's,
|
||||
* the obj_resists chance is increased so the shatter
|
||||
* chance is decreased; if less rusty, then vice versa.
|
||||
*/
|
||||
setmnotwielded(mon, monwep);
|
||||
mon->weapon_check = NEED_WEAPON;
|
||||
@@ -1148,7 +1152,7 @@ int thrown; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
|
||||
if (poiskilled) {
|
||||
pline_The("poison was deadly...");
|
||||
if (!already_killed)
|
||||
xkilled(mon, 0);
|
||||
xkilled(mon, XKILL_NOMSG);
|
||||
destroyed = TRUE; /* return FALSE; */
|
||||
} else if (destroyed) {
|
||||
if (!already_killed)
|
||||
@@ -1467,7 +1471,7 @@ register struct attack *mattk;
|
||||
if (pd == &mons[PM_STRAW_GOLEM] || pd == &mons[PM_PAPER_GOLEM]) {
|
||||
if (!Blind)
|
||||
pline("%s burns completely!", Monnam(mdef));
|
||||
xkilled(mdef, 2);
|
||||
xkilled(mdef, XKILL_NOMSG | XKILL_NOCORPSE);
|
||||
tmp = 0;
|
||||
break;
|
||||
/* Don't return yet; keep hp<1 and tmp=0 for pet msg */
|
||||
@@ -1585,7 +1589,7 @@ register struct attack *mattk;
|
||||
if (!Blind)
|
||||
pline("Some writing vanishes from %s head!",
|
||||
s_suffix(mon_nam(mdef)));
|
||||
xkilled(mdef, 0);
|
||||
xkilled(mdef, XKILL_NOMSG);
|
||||
/* Don't return yet; keep hp<1 and tmp=0 for pet msg */
|
||||
} else {
|
||||
mdef->mcan = 1;
|
||||
@@ -1597,11 +1601,14 @@ register struct attack *mattk;
|
||||
case AD_DRLI:
|
||||
if (!negated && !rn2(3) && !resists_drli(mdef)) {
|
||||
int xtmp = d(2, 6);
|
||||
|
||||
pline("%s suddenly seems weaker!", Monnam(mdef));
|
||||
mdef->mhpmax -= xtmp;
|
||||
if ((mdef->mhp -= xtmp) <= 0 || !mdef->m_lev) {
|
||||
mdef->mhp -= xtmp;
|
||||
/* !m_lev: level 0 monster is killed rather than drop to -1 */
|
||||
if (mdef->mhp <= 0 && !mdef->m_lev) {
|
||||
pline("%s dies!", Monnam(mdef));
|
||||
xkilled(mdef, 0);
|
||||
xkilled(mdef, XKILL_NOMSG);
|
||||
} else
|
||||
mdef->m_lev--;
|
||||
tmp = 0;
|
||||
@@ -1610,7 +1617,7 @@ register struct attack *mattk;
|
||||
case AD_RUST:
|
||||
if (pd == &mons[PM_IRON_GOLEM]) {
|
||||
pline("%s falls to pieces!", Monnam(mdef));
|
||||
xkilled(mdef, 0);
|
||||
xkilled(mdef, XKILL_NOMSG);
|
||||
}
|
||||
erode_armor(mdef, ERODE_RUST);
|
||||
tmp = 0;
|
||||
@@ -1622,7 +1629,7 @@ register struct attack *mattk;
|
||||
case AD_DCAY:
|
||||
if (pd == &mons[PM_WOOD_GOLEM] || pd == &mons[PM_LEATHER_GOLEM]) {
|
||||
pline("%s falls to pieces!", Monnam(mdef));
|
||||
xkilled(mdef, 0);
|
||||
xkilled(mdef, XKILL_NOMSG);
|
||||
}
|
||||
erode_armor(mdef, ERODE_ROT);
|
||||
tmp = 0;
|
||||
@@ -1762,15 +1769,16 @@ register struct attack *mattk;
|
||||
}
|
||||
|
||||
mdef->mstrategy &= ~STRAT_WAITFORU; /* in case player is very fast */
|
||||
if ((mdef->mhp -= tmp) < 1) {
|
||||
mdef->mhp -= tmp;
|
||||
if (mdef->mhp < 1) {
|
||||
if (mdef->mtame && !cansee(mdef->mx, mdef->my)) {
|
||||
You_feel("embarrassed for a moment.");
|
||||
if (tmp)
|
||||
xkilled(mdef, 0); /* !tmp but hp<1: already killed */
|
||||
xkilled(mdef, XKILL_NOMSG); /* !tmp but hp<1: already killed */
|
||||
} else if (!flags.verbose) {
|
||||
You("destroy it!");
|
||||
if (tmp)
|
||||
xkilled(mdef, 0);
|
||||
xkilled(mdef, XKILL_NOMSG);
|
||||
} else if (tmp)
|
||||
killed(mdef);
|
||||
return 2;
|
||||
@@ -1929,7 +1937,7 @@ register struct attack *mattk;
|
||||
m_useup(mdef, otmp);
|
||||
|
||||
newuhs(FALSE);
|
||||
xkilled(mdef, 2);
|
||||
xkilled(mdef, XKILL_NOMSG | XKILL_NOCORPSE);
|
||||
if (mdef->mhp > 0) { /* monster lifesaved */
|
||||
You("hurriedly regurgitate the sizzling in your %s.",
|
||||
body_part(STOMACH));
|
||||
@@ -2038,7 +2046,8 @@ register struct attack *mattk;
|
||||
break;
|
||||
}
|
||||
end_engulf();
|
||||
if ((mdef->mhp -= dam) <= 0) {
|
||||
mdef->mhp -= dam;
|
||||
if (mdef->mhp <= 0) {
|
||||
killed(mdef);
|
||||
if (mdef->mhp <= 0) /* not lifesaved */
|
||||
return 2;
|
||||
@@ -2546,17 +2555,17 @@ struct attack *mattk; /* null means we find one internally */
|
||||
break;
|
||||
case AD_ACID:
|
||||
if (!rn2(6)) {
|
||||
(void) erode_obj(obj, NULL, ERODE_CORRODE, EF_NONE);
|
||||
(void) erode_obj(obj, NULL, ERODE_CORRODE, EF_GREASE);
|
||||
}
|
||||
break;
|
||||
case AD_RUST:
|
||||
if (!mon->mcan) {
|
||||
(void) erode_obj(obj, NULL, ERODE_RUST, EF_NONE);
|
||||
(void) erode_obj(obj, (char *) 0, ERODE_RUST, EF_GREASE);
|
||||
}
|
||||
break;
|
||||
case AD_CORR:
|
||||
if (!mon->mcan) {
|
||||
(void) erode_obj(obj, NULL, ERODE_CORRODE, EF_NONE);
|
||||
(void) erode_obj(obj, (char *) 0, ERODE_CORRODE, EF_GREASE);
|
||||
}
|
||||
break;
|
||||
case AD_ENCH:
|
||||
@@ -2685,7 +2694,8 @@ int dmg;
|
||||
{
|
||||
pline("%s %s!", Monnam(mon),
|
||||
(dmg > mon->mhp / 2) ? "wails in agony" : "cries out in pain");
|
||||
if ((mon->mhp -= dmg) <= 0) {
|
||||
mon->mhp -= dmg;
|
||||
if (mon->mhp <= 0) {
|
||||
if (context.mon_moving)
|
||||
monkilled(mon, (char *) 0, AD_BLND);
|
||||
else
|
||||
|
||||
+21
-18
@@ -377,8 +377,8 @@ invault()
|
||||
}
|
||||
trycount = 5;
|
||||
do {
|
||||
getlin(Deaf ? "You are required to supply your name. -" :
|
||||
"\"Hello stranger, who are you?\" -", buf);
|
||||
getlin(Deaf ? "You are required to supply your name. -"
|
||||
: "\"Hello stranger, who are you?\" -", buf);
|
||||
(void) mungspaces(buf);
|
||||
} while (!buf[0] && --trycount > 0);
|
||||
|
||||
@@ -392,10 +392,11 @@ invault()
|
||||
|| !strcmpi(buf, "Creosote")) {
|
||||
if (!mvitals[PM_CROESUS].died) {
|
||||
if (Deaf) {
|
||||
if (!Blind) pline("%s waves goodbye.", noit_Monnam(guard));
|
||||
if (!Blind)
|
||||
pline("%s waves goodbye.", noit_Monnam(guard));
|
||||
} else {
|
||||
verbalize(
|
||||
"Oh, yes, of course. Sorry to have disturbed you.");
|
||||
"Oh, yes, of course. Sorry to have disturbed you.");
|
||||
}
|
||||
mongone(guard);
|
||||
} else {
|
||||
@@ -403,10 +404,11 @@ invault()
|
||||
if (Deaf) {
|
||||
if (!Blind)
|
||||
pline("%s mouths something and looks very angry!",
|
||||
noit_Monnam(guard));
|
||||
} else {
|
||||
verbalize("Back from the dead, are you? I'll remedy that!");
|
||||
}
|
||||
noit_Monnam(guard));
|
||||
} else {
|
||||
verbalize(
|
||||
"Back from the dead, are you? I'll remedy that!");
|
||||
}
|
||||
/* don't want guard to waste next turn wielding a weapon */
|
||||
if (!MON_WEP(guard)) {
|
||||
guard->weapon_check = NEED_HTH_WEAPON;
|
||||
@@ -424,7 +426,7 @@ invault()
|
||||
if (!umoney && !hidden_gold()) {
|
||||
if (Deaf)
|
||||
pline("%s stomps%s.", noit_Monnam(guard),
|
||||
(Blind) ? "" : " and beckons");
|
||||
(Blind) ? "" : " and beckons");
|
||||
else
|
||||
verbalize("Please follow me.");
|
||||
} else {
|
||||
@@ -432,20 +434,21 @@ invault()
|
||||
if (Deaf) {
|
||||
if (!Blind)
|
||||
pline("%s glares at you%s.", noit_Monnam(guard),
|
||||
invent ? "r stuff" : "");
|
||||
invent ? "r stuff" : "");
|
||||
} else {
|
||||
verbalize("You have hidden gold.");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Deaf) {
|
||||
if (!Blind)
|
||||
pline("%s holds out %s palm and beckons with %s other hand.",
|
||||
noit_Monnam(guard), mhis(guard), mhis(guard));
|
||||
} else {
|
||||
pline(
|
||||
"%s holds out %s palm and beckons with %s other hand.",
|
||||
noit_Monnam(guard), mhis(guard), mhis(guard));
|
||||
} else {
|
||||
verbalize(
|
||||
"Most likely all your gold was stolen from this vault.");
|
||||
verbalize("Please drop that gold and follow me.");
|
||||
}
|
||||
}
|
||||
}
|
||||
EGD(guard)->gdx = gx;
|
||||
EGD(guard)->gdy = gy;
|
||||
@@ -695,16 +698,16 @@ register struct monst *grd;
|
||||
noit_Monnam(grd), mhis(grd));
|
||||
} else {
|
||||
verbalize("Drop all your gold, scoundrel!");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
if (Deaf) {
|
||||
if (!Blind)
|
||||
pline("%s rubs %s hands with enraged delight!",
|
||||
noit_Monnam(grd), mhis(grd));
|
||||
noit_Monnam(grd), mhis(grd));
|
||||
} else {
|
||||
verbalize("So be it, rogue!");
|
||||
}
|
||||
}
|
||||
grd->mpeaceful = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
+3
-1
@@ -200,7 +200,9 @@ boolean
|
||||
comp_times(filetime)
|
||||
long filetime;
|
||||
{
|
||||
return (boolean) (filetime < BUILD_TIME);
|
||||
/* BUILD_TIME is constant but might have L suffix rather than UL;
|
||||
'filetime' is historically signed but ought to have been unsigned */
|
||||
return (boolean) ((unsigned long) filetime < (unsigned long) BUILD_TIME);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+153
-44
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 wield.c $NHDT-Date: 1450577672 2015/12/20 02:14:32 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.48 $ */
|
||||
/* NetHack 3.6 wield.c $NHDT-Date: 1461967849 2016/04/29 22:10:49 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.49 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -174,6 +174,10 @@ struct obj *wep;
|
||||
* and the message must be before the death message and
|
||||
* Lifesaved rewielding. Yet we want the message to
|
||||
* say "weapon in hand", thus this kludge.
|
||||
* [That comment is obsolete. It dates from the days (3.0)
|
||||
* when unwielding Firebrand could cause hero to be burned
|
||||
* to death in Hell due to loss of fire resistance.
|
||||
* "Lifesaved re-wielding or re-wearing" is ancient history.]
|
||||
*/
|
||||
long dummy = wep->owornmask;
|
||||
|
||||
@@ -232,12 +236,16 @@ register struct obj *obj;
|
||||
|
||||
/*** Commands to change particular slot(s) ***/
|
||||
|
||||
static NEARDATA const char wield_objs[] = { ALL_CLASSES, ALLOW_NONE,
|
||||
WEAPON_CLASS, TOOL_CLASS, 0 };
|
||||
static NEARDATA const char ready_objs[] = { COIN_CLASS, ALL_CLASSES,
|
||||
ALLOW_NONE, WEAPON_CLASS, 0 };
|
||||
static NEARDATA const char bullets[] = /* (note: different from dothrow.c) */
|
||||
{ COIN_CLASS, ALL_CLASSES, ALLOW_NONE, GEM_CLASS, WEAPON_CLASS, 0 };
|
||||
static NEARDATA const char wield_objs[] = {
|
||||
ALL_CLASSES, ALLOW_NONE, WEAPON_CLASS, TOOL_CLASS, 0
|
||||
};
|
||||
static NEARDATA const char ready_objs[] = {
|
||||
ALLOW_COUNT, COIN_CLASS, ALL_CLASSES, ALLOW_NONE, WEAPON_CLASS, 0
|
||||
};
|
||||
static NEARDATA const char bullets[] = { /* (note: different from dothrow.c) */
|
||||
ALLOW_COUNT, COIN_CLASS, ALL_CLASSES, ALLOW_NONE,
|
||||
GEM_CLASS, WEAPON_CLASS, 0
|
||||
};
|
||||
|
||||
int
|
||||
dowield()
|
||||
@@ -316,10 +324,10 @@ doswapweapon()
|
||||
result = ready_weapon(oldswap);
|
||||
|
||||
/* Set your new secondary weapon */
|
||||
if (uwep == oldwep)
|
||||
if (uwep == oldwep) {
|
||||
/* Wield failed for some reason */
|
||||
setuswapwep(oldswap);
|
||||
else {
|
||||
} else {
|
||||
setuswapwep(oldwep);
|
||||
if (uswapwep)
|
||||
prinv((char *) 0, uswapwep, 0L);
|
||||
@@ -336,64 +344,165 @@ doswapweapon()
|
||||
int
|
||||
dowieldquiver()
|
||||
{
|
||||
register struct obj *newquiver;
|
||||
const char *quivee_types =
|
||||
(uslinging()
|
||||
|| (uswapwep && objects[uswapwep->otyp].oc_skill == P_SLING))
|
||||
? bullets
|
||||
: ready_objs;
|
||||
char qbuf[QBUFSZ];
|
||||
struct obj *newquiver;
|
||||
const char *quivee_types;
|
||||
int res;
|
||||
boolean finish_splitting = FALSE,
|
||||
was_uwep = FALSE, was_twoweap = u.twoweap;
|
||||
|
||||
/* Since the quiver isn't in your hands, don't check cantwield(), */
|
||||
/* will_weld(), touch_petrifies(), etc. */
|
||||
multi = 0;
|
||||
/* forget last splitobj() before calling getobj() with ALLOW_COUNT */
|
||||
context.objsplit.child_oid = context.objsplit.parent_oid = 0;
|
||||
|
||||
/* Prompt for a new quiver */
|
||||
if (!(newquiver = getobj(quivee_types, "ready")))
|
||||
/* Prompt for a new quiver: "What do you want to ready?"
|
||||
(Include gems/stones as likely candidates if either primary
|
||||
or secondary weapon is a sling.) */
|
||||
quivee_types = (uslinging()
|
||||
|| (uswapwep
|
||||
&& objects[uswapwep->otyp].oc_skill == P_SLING))
|
||||
? bullets
|
||||
: ready_objs;
|
||||
newquiver = getobj(quivee_types, "ready");
|
||||
|
||||
if (!newquiver) {
|
||||
/* Cancelled */
|
||||
return 0;
|
||||
|
||||
/* Handle no object, or object in other slot */
|
||||
/* Any type is okay, since we give no intrinsics anyways */
|
||||
if (newquiver == &zeroobj) {
|
||||
} else if (newquiver == &zeroobj) { /* no object */
|
||||
/* Explicitly nothing */
|
||||
if (uquiver) {
|
||||
You("now have no ammunition readied.");
|
||||
setuqwep(newquiver = (struct obj *) 0);
|
||||
/* skip 'quivering: prinv()' */
|
||||
setuqwep((struct obj *) 0);
|
||||
} else {
|
||||
You("already have no ammunition readied!");
|
||||
return 0;
|
||||
}
|
||||
} else if (newquiver == uquiver) {
|
||||
pline("That ammunition is already readied!");
|
||||
return 0;
|
||||
} else if (newquiver == uwep) {
|
||||
/* Prevent accidentally readying the main weapon */
|
||||
pline("%s already being used as a weapon!",
|
||||
!is_plural(uwep) ? "That is" : "They are");
|
||||
} else if (newquiver->o_id == context.objsplit.child_oid) {
|
||||
/* if newquiver is the result of supplying a count to getobj()
|
||||
we don't want to split something already in the quiver;
|
||||
for any other item, we need to give it its own inventory slot */
|
||||
if (uquiver && uquiver->o_id == context.objsplit.parent_oid) {
|
||||
unsplitobj(newquiver);
|
||||
goto already_quivered;
|
||||
}
|
||||
finish_splitting = TRUE;
|
||||
} else if (newquiver == uquiver) {
|
||||
already_quivered:
|
||||
pline("That ammunition is already readied!");
|
||||
return 0;
|
||||
} else if (newquiver->owornmask & (W_ARMOR | W_ACCESSORY | W_SADDLE)) {
|
||||
You("cannot ready that!");
|
||||
return 0;
|
||||
} else {
|
||||
long dummy;
|
||||
} else if (newquiver == uwep) {
|
||||
int weld_res = !uwep->bknown;
|
||||
|
||||
/* Check if it's the secondary weapon */
|
||||
if (newquiver == uswapwep) {
|
||||
setuswapwep((struct obj *) 0);
|
||||
untwoweapon();
|
||||
if (welded(uwep)) {
|
||||
weldmsg(uwep);
|
||||
reset_remarm(); /* same as dowield() */
|
||||
return weld_res;
|
||||
}
|
||||
|
||||
/* Okay to put in quiver; print it */
|
||||
dummy = newquiver->owornmask;
|
||||
newquiver->owornmask |= W_QUIVER;
|
||||
prinv((char *) 0, newquiver, 0L);
|
||||
newquiver->owornmask = dummy;
|
||||
/* offer to split stack if wielding more than 1 */
|
||||
if (uwep->quan > 1L && inv_cnt(FALSE) < 52 && splittable(uwep)) {
|
||||
Sprintf(qbuf, "You are wielding %ld %s. Ready %ld of them?",
|
||||
uwep->quan, simpleonames(uwep), uwep->quan - 1L);
|
||||
switch (ynq(qbuf)) {
|
||||
case 'q':
|
||||
return 0;
|
||||
case 'y':
|
||||
/* leave 1 wielded, split rest off and put into quiver */
|
||||
newquiver = splitobj(uwep, uwep->quan - 1L);
|
||||
finish_splitting = TRUE;
|
||||
goto quivering;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Strcpy(qbuf, "Ready all of them instead?");
|
||||
} else {
|
||||
Sprintf(qbuf, "You are wielding %s. Ready %s instead?",
|
||||
/* uwep->quan is 1, but name might be plural ('boots') */
|
||||
!is_plural(uwep) ? "that" : "those",
|
||||
!is_plural(uwep) ? "it" : "them");
|
||||
}
|
||||
/* require confirmation to ready the main weapon */
|
||||
if (ynq(qbuf) != 'y') {
|
||||
(void) Shk_Your(qbuf, uwep); /* replace qbuf[] contents */
|
||||
pline("%s%s %s wielded.", qbuf,
|
||||
simpleonames(uwep), otense(uwep, "remain"));
|
||||
return 0;
|
||||
}
|
||||
/* quivering main weapon, so no longer wielding it */
|
||||
setuwep((struct obj *) 0);
|
||||
untwoweapon();
|
||||
was_uwep = TRUE;
|
||||
} else if (newquiver == uswapwep) {
|
||||
if (uswapwep->quan > 1L && inv_cnt(FALSE) < 52
|
||||
&& splittable(uswapwep)) {
|
||||
Sprintf(qbuf, "%s %ld %s. Ready %ld of them?",
|
||||
u.twoweap ? "You are dual wielding"
|
||||
: "Your alternate weapon is",
|
||||
uswapwep->quan, simpleonames(uswapwep),
|
||||
uswapwep->quan - 1L);
|
||||
switch (ynq(qbuf)) {
|
||||
case 'q':
|
||||
return 0;
|
||||
case 'y':
|
||||
/* leave 1 alt-wielded, split rest off and put into quiver */
|
||||
newquiver = splitobj(uswapwep, uswapwep->quan - 1L);
|
||||
finish_splitting = TRUE;
|
||||
goto quivering;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Strcpy(qbuf, "Ready all of them instead?");
|
||||
} else {
|
||||
Sprintf(qbuf, "%s your %s weapon. Ready %s instead?",
|
||||
!is_plural(uswapwep) ? "That is" : "Those are",
|
||||
u.twoweap ? "second" : "alternate",
|
||||
/* uswapwep->quan is 1, but name might be plural */
|
||||
!is_plural(uswapwep) ? "it" : "them");
|
||||
}
|
||||
/* require confirmation to ready the alternate weapon */
|
||||
if (ynq(qbuf) != 'y') {
|
||||
(void) Shk_Your(qbuf, uswapwep); /* replace qbuf[] contents */
|
||||
pline("%s%s %s %s.", qbuf,
|
||||
simpleonames(uswapwep), otense(uswapwep, "remain"),
|
||||
u.twoweap ? "wielded" : "as secondary weapon");
|
||||
return 0;
|
||||
}
|
||||
/* quivering alternate weapon, so no more uswapwep */
|
||||
setuswapwep((struct obj *) 0);
|
||||
untwoweapon();
|
||||
}
|
||||
|
||||
/* Finally, place it in the quiver */
|
||||
quivering:
|
||||
if (finish_splitting) {
|
||||
freeinv(newquiver);
|
||||
newquiver->nomerge = 1;
|
||||
addinv(newquiver);
|
||||
newquiver->nomerge = 0;
|
||||
}
|
||||
/* place item in quiver before printing so that inventory feedback
|
||||
includes "(at the ready)" */
|
||||
setuqwep(newquiver);
|
||||
/* Take no time since this is a convenience slot */
|
||||
return 0;
|
||||
prinv((char *) 0, newquiver, 0L);
|
||||
|
||||
/* quiver is a convenience slot and manipulating it ordinarily
|
||||
consumes no time, but unwielding primary or secondary weapon
|
||||
should take time (perhaps we're adjacent to a rust monster
|
||||
or disenchanter and want to hit it immediately, but not with
|
||||
something we're wielding that's vulnerable to its damage) */
|
||||
res = 0;
|
||||
if (was_uwep) {
|
||||
You("are now empty %s.", body_part(HANDED));
|
||||
res = 1;
|
||||
} else if (was_twoweap && !u.twoweap) {
|
||||
You("are no longer wielding two weapons at once.");
|
||||
res = 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* used for #rub and for applying pick-axe, whip, grappling hook or polearm */
|
||||
|
||||
@@ -677,6 +677,14 @@ register xchar *nx, *ny;
|
||||
: (y > 1 ? (y < ROWNO ? (rn2(3) - 1) : -rn2(2)) : rn2(2)));
|
||||
}
|
||||
|
||||
/* for size_monst(cmd.c) to support #stats */
|
||||
int
|
||||
size_wseg(worm)
|
||||
struct monst *worm;
|
||||
{
|
||||
return (int) (count_wsegs(worm) * sizeof (struct wseg));
|
||||
}
|
||||
|
||||
/* count_wsegs()
|
||||
* returns the number of segments that a worm has.
|
||||
*/
|
||||
|
||||
+2
-2
@@ -128,12 +128,12 @@ register struct obj *pen;
|
||||
if (Blind) {
|
||||
if (!paper->dknown) {
|
||||
You("don't know if that %s is blank or not.", typeword);
|
||||
return 1;
|
||||
return 0;
|
||||
} else if (paper->oclass == SPBOOK_CLASS) {
|
||||
/* can't write a magic book while blind */
|
||||
pline("%s can't create braille text.",
|
||||
upstart(ysimple_name(pen)));
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
paper->dknown = 1;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 zap.c $NHDT-Date: 1456528600 2016/02/26 23:16:40 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.247 $ */
|
||||
/* NetHack 3.6 zap.c $NHDT-Date: 1464163779 2016/05/25 08:09:39 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.258 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -221,11 +221,17 @@ struct obj *otmp;
|
||||
it guard against involuntary polymorph attacks too... */
|
||||
shieldeff(mtmp->mx, mtmp->my);
|
||||
} else if (!resist(mtmp, otmp->oclass, 0, NOTELL)) {
|
||||
boolean polyspot = (otyp != POT_POLYMORPH),
|
||||
give_msg = (!Hallucination
|
||||
&& (canseemon(mtmp)
|
||||
|| (u.uswallow && mtmp == u.ustuck)));
|
||||
|
||||
/* dropped inventory (due to death by system shock,
|
||||
or loss of wielded weapon and/or worn armor due to
|
||||
limitations of new shape) won't be hit by this zap */
|
||||
for (obj = mtmp->minvent; obj; obj = obj->nobj)
|
||||
bypass_obj(obj);
|
||||
if (polyspot)
|
||||
for (obj = mtmp->minvent; obj; obj = obj->nobj)
|
||||
bypass_obj(obj);
|
||||
/* natural shapechangers aren't affected by system shock
|
||||
(unless protection from shapechangers is interfering
|
||||
with their metabolism...) */
|
||||
@@ -236,10 +242,17 @@ struct obj *otmp;
|
||||
}
|
||||
/* context.bypasses = TRUE; ## for make_corpse() */
|
||||
/* no corpse after system shock */
|
||||
xkilled(mtmp, 3);
|
||||
xkilled(mtmp, XKILL_GIVEMSG | XKILL_NOCORPSE);
|
||||
} else if (newcham(mtmp, (struct permonst *) 0,
|
||||
(otyp != POT_POLYMORPH), FALSE)) {
|
||||
if (!Hallucination && canspotmon(mtmp))
|
||||
polyspot, give_msg) != 0
|
||||
/* if shapechange failed because there aren't
|
||||
enough eligible candidates (most likely for
|
||||
vampshifter), try reverting to original form */
|
||||
|| (mtmp->cham >= LOW_PM
|
||||
&& newcham(mtmp, &mons[mtmp->cham],
|
||||
polyspot, give_msg) != 0)) {
|
||||
if (give_msg && (canspotmon(mtmp)
|
||||
|| (u.uswallow && mtmp == u.ustuck)))
|
||||
learn_it = TRUE;
|
||||
}
|
||||
}
|
||||
@@ -388,14 +401,15 @@ struct obj *otmp;
|
||||
dmg *= 2;
|
||||
if (otyp == SPE_DRAIN_LIFE)
|
||||
dmg = spell_damage_bonus(dmg);
|
||||
if (resists_drli(mtmp))
|
||||
if (resists_drli(mtmp)) {
|
||||
shieldeff(mtmp->mx, mtmp->my);
|
||||
else if (!resist(mtmp, otmp->oclass, dmg, NOTELL) && mtmp->mhp > 0) {
|
||||
} else if (!resist(mtmp, otmp->oclass, dmg, NOTELL) && mtmp->mhp > 0) {
|
||||
mtmp->mhp -= dmg;
|
||||
mtmp->mhpmax -= dmg;
|
||||
if (mtmp->mhp <= 0 || mtmp->mhpmax <= 0 || mtmp->m_lev < 1)
|
||||
xkilled(mtmp, 1);
|
||||
else {
|
||||
/* die if already level 0, regardless of hit points */
|
||||
if (mtmp->mhp <= 0 || mtmp->mhpmax <= 0 || mtmp->m_lev < 1) {
|
||||
killed(mtmp);
|
||||
} else {
|
||||
mtmp->m_lev--;
|
||||
if (canseemon(mtmp))
|
||||
pline("%s suddenly seems weaker!", Monnam(mtmp));
|
||||
@@ -453,7 +467,8 @@ struct monst *mtmp;
|
||||
otmp->cknown = 1;
|
||||
}
|
||||
}
|
||||
(void) display_minventory(mtmp, MINV_ALL | MINV_NOLET, (char *) 0);
|
||||
(void) display_minventory(mtmp, MINV_ALL | MINV_NOLET | PICK_NONE,
|
||||
(char *) 0);
|
||||
} else {
|
||||
pline("%s is not carrying anything%s.", noit_Monnam(mtmp),
|
||||
(u.uswallow && mtmp == u.ustuck) ? " besides you" : "");
|
||||
@@ -562,9 +577,9 @@ coord *cc;
|
||||
if (mtmp->m_id) {
|
||||
mtmp2->m_id = mtmp->m_id;
|
||||
/* might be bringing quest leader back to life */
|
||||
if (quest_status.leader_is_dead &&
|
||||
if (quest_status.leader_is_dead
|
||||
/* leader_is_dead implies leader_m_id is valid */
|
||||
mtmp2->m_id == quest_status.leader_m_id)
|
||||
&& mtmp2->m_id == quest_status.leader_m_id)
|
||||
quest_status.leader_is_dead = FALSE;
|
||||
}
|
||||
mtmp2->mx = mtmp->mx;
|
||||
@@ -600,6 +615,16 @@ coord *cc;
|
||||
mtmp2->mblinded = 0;
|
||||
mtmp2->mstun = 0;
|
||||
mtmp2->mconf = 0;
|
||||
/* when traits are for a shopeekper, dummy monster 'mtmp' won't
|
||||
have necessary eshk data for replmon() -> replshk() */
|
||||
if (mtmp2->isshk) {
|
||||
neweshk(mtmp);
|
||||
*ESHK(mtmp) = *ESHK(mtmp2);
|
||||
if (ESHK(mtmp2)->bill_p != 0
|
||||
&& ESHK(mtmp2)->bill_p != (struct bill_x *) -1000)
|
||||
ESHK(mtmp)->bill_p = &(ESHK(mtmp)->bill[0]);
|
||||
mtmp->isshk = 1;
|
||||
}
|
||||
replmon(mtmp, mtmp2);
|
||||
newsym(mtmp2->mx, mtmp2->my); /* Might now be invisible */
|
||||
|
||||
@@ -648,6 +673,8 @@ int *container_nesting;
|
||||
/*
|
||||
* Attempt to revive the given corpse, return the revived monster if
|
||||
* successful. Note: this does NOT use up the corpse if it fails.
|
||||
* If corpse->quan is more than 1, only one corpse will be affected
|
||||
* and only one monster will be resurrected.
|
||||
*/
|
||||
struct monst *
|
||||
revive(corpse, by_hero)
|
||||
@@ -659,6 +686,7 @@ boolean by_hero;
|
||||
struct obj *container;
|
||||
coord xy;
|
||||
xchar x, y;
|
||||
boolean one_of;
|
||||
int montype, container_nesting = 0;
|
||||
|
||||
if (corpse->otyp != CORPSE) {
|
||||
@@ -693,16 +721,16 @@ boolean by_hero;
|
||||
break; /* x,y are 0 */
|
||||
}
|
||||
}
|
||||
if (!x || !y ||
|
||||
if (!x || !y
|
||||
/* Rules for revival from containers:
|
||||
- the container cannot be locked
|
||||
- the container cannot be heavily nested (>2 is arbitrary)
|
||||
- the container cannot be a statue or bag of holding
|
||||
(except in very rare cases for the latter)
|
||||
*/
|
||||
(container && (container->olocked || container_nesting > 2
|
||||
|| container->otyp == STATUE
|
||||
|| (container->otyp == BAG_OF_HOLDING && rn2(40)))))
|
||||
* - the container cannot be locked
|
||||
* - the container cannot be heavily nested (>2 is arbitrary)
|
||||
* - the container cannot be a statue or bag of holding
|
||||
* (except in very rare cases for the latter)
|
||||
*/
|
||||
|| (container && (container->olocked || container_nesting > 2
|
||||
|| container->otyp == STATUE
|
||||
|| (container->otyp == BAG_OF_HOLDING && rn2(40)))))
|
||||
return (struct monst *) 0;
|
||||
|
||||
/* record the object's location now that we're sure where it is */
|
||||
@@ -765,24 +793,33 @@ boolean by_hero;
|
||||
if (mtmp->m_ap_type)
|
||||
seemimic(mtmp);
|
||||
|
||||
one_of = (corpse->quan > 1L);
|
||||
if (one_of)
|
||||
corpse = splitobj(corpse, 1L);
|
||||
|
||||
/* if this is caused by the hero there might be a shop charge */
|
||||
if (by_hero) {
|
||||
struct monst *shkp = 0;
|
||||
|
||||
x = corpse->ox, y = corpse->oy;
|
||||
if (costly_spot(x, y))
|
||||
if (costly_spot(x, y)
|
||||
&& (carried(corpse) ? corpse->unpaid : !corpse->no_charge))
|
||||
shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
|
||||
|
||||
if (cansee(x, y)) {
|
||||
char buf[BUFSZ];
|
||||
unsigned pfx = CXN_PFX_THE;
|
||||
|
||||
Strcpy(buf, (corpse->quan > 1L) ? "one of " : "");
|
||||
Strcpy(buf, one_of ? "one of " : "");
|
||||
if (carried(corpse) && !corpse->unpaid) {
|
||||
Strcat(buf, "your ");
|
||||
pfx = CXN_NO_PFX;
|
||||
}
|
||||
if (one_of)
|
||||
corpse->quan++; /* force plural */
|
||||
Strcat(buf, corpse_xname(corpse, (const char *) 0, pfx));
|
||||
if (one_of) /* could be simplified to ''corpse->quan = 1L;'' */
|
||||
corpse->quan--;
|
||||
pline("%s glows iridescently.", upstart(buf));
|
||||
} else if (shkp) {
|
||||
/* need some prior description of the corpse since
|
||||
@@ -890,10 +927,11 @@ struct monst *mon;
|
||||
struct monst *mtmp2;
|
||||
char owner[BUFSZ], corpse[BUFSZ];
|
||||
boolean youseeit;
|
||||
int once = 0, res = 0;
|
||||
int res = 0;
|
||||
|
||||
youseeit = (mon == &youmonst) ? TRUE : canseemon(mon);
|
||||
otmp2 = (mon == &youmonst) ? invent : mon->minvent;
|
||||
owner[0] = corpse[0] = '\0'; /* lint suppression */
|
||||
|
||||
while ((otmp = otmp2) != 0) {
|
||||
otmp2 = otmp->nobj;
|
||||
@@ -902,19 +940,18 @@ struct monst *mon;
|
||||
if (otmp->otyp != CORPSE)
|
||||
continue;
|
||||
/* save the name; the object is liable to go away */
|
||||
if (youseeit)
|
||||
if (youseeit) {
|
||||
Strcpy(corpse,
|
||||
corpse_xname(otmp, (const char *) 0, CXN_SINGULAR));
|
||||
Shk_Your(owner, otmp); /* includes a trailing space */
|
||||
}
|
||||
|
||||
/* for a merged group, only one is revived; should this be fixed? */
|
||||
/* for a stack, only one is revived */
|
||||
if ((mtmp2 = revive(otmp, !context.mon_moving)) != 0) {
|
||||
++res;
|
||||
if (youseeit) {
|
||||
if (!once++)
|
||||
Strcpy(owner, (mon == &youmonst) ? "Your"
|
||||
: s_suffix(Monnam(mon)));
|
||||
pline("%s %s suddenly comes alive!", owner, corpse);
|
||||
} else if (canseemon(mtmp2))
|
||||
if (youseeit)
|
||||
pline("%s%s suddenly comes alive!", owner, corpse);
|
||||
else if (canseemon(mtmp2))
|
||||
pline("%s suddenly appears!", Amonnam(mtmp2));
|
||||
}
|
||||
}
|
||||
@@ -1423,14 +1460,15 @@ int id;
|
||||
|
||||
otmp->cursed = obj->cursed;
|
||||
otmp->blessed = obj->blessed;
|
||||
otmp->oeroded = obj->oeroded;
|
||||
otmp->oeroded2 = obj->oeroded2;
|
||||
if (!is_flammable(otmp) && !is_rustprone(otmp))
|
||||
otmp->oeroded = 0;
|
||||
if (!is_corrodeable(otmp) && !is_rottable(otmp))
|
||||
otmp->oeroded2 = 0;
|
||||
if (is_damageable(otmp))
|
||||
otmp->oerodeproof = obj->oerodeproof;
|
||||
|
||||
if (erosion_matters(otmp)) {
|
||||
if (is_flammable(otmp) || is_rustprone(otmp))
|
||||
otmp->oeroded = obj->oeroded;
|
||||
if (is_corrodeable(otmp) || is_rottable(otmp))
|
||||
otmp->oeroded2 = obj->oeroded2;
|
||||
if (is_damageable(otmp))
|
||||
otmp->oerodeproof = obj->oerodeproof;
|
||||
}
|
||||
|
||||
/* Keep chest/box traps and poisoned ammo if we may */
|
||||
if (obj->otrapped && Is_box(otmp))
|
||||
@@ -1586,9 +1624,9 @@ int id;
|
||||
if (*u.ushops
|
||||
&& *in_rooms(u.ux, u.uy, 0)
|
||||
== *in_rooms(shkp->mx, shkp->my, 0)
|
||||
&& !costly_spot(u.ux, u.uy))
|
||||
&& !costly_spot(u.ux, u.uy)) {
|
||||
make_angry_shk(shkp, ox, oy);
|
||||
else {
|
||||
} else {
|
||||
pline("%s gets angry!", Monnam(shkp));
|
||||
hot_pursuit(shkp);
|
||||
}
|
||||
@@ -1607,7 +1645,7 @@ struct obj *obj;
|
||||
{
|
||||
int res = 1; /* affected object by default */
|
||||
struct permonst *ptr;
|
||||
struct monst *mon;
|
||||
struct monst *mon, *shkp;
|
||||
struct obj *item;
|
||||
xchar oox, ooy;
|
||||
boolean smell = FALSE, golem_xform = FALSE;
|
||||
@@ -1638,19 +1676,18 @@ struct obj *obj;
|
||||
break;
|
||||
}
|
||||
if (obj->otyp == STATUE) {
|
||||
/* animate_statue() forces all golems to become flesh golems
|
||||
*/
|
||||
/* animate_statue() forces all golems to become flesh golems */
|
||||
mon = animate_statue(obj, oox, ooy, ANIMATE_SPELL, (int *) 0);
|
||||
} else { /* (obj->otyp == FIGURINE) */
|
||||
if (golem_xform)
|
||||
ptr = &mons[PM_FLESH_GOLEM];
|
||||
mon = makemon(ptr, oox, ooy, NO_MINVENT);
|
||||
if (mon) {
|
||||
if (costly_spot(oox, ooy) && !obj->no_charge) {
|
||||
if (costly_spot(u.ux, u.uy))
|
||||
addtobill(obj, carried(obj), FALSE, FALSE);
|
||||
else
|
||||
stolen_value(obj, oox, ooy, TRUE, FALSE);
|
||||
if (costly_spot(oox, ooy)
|
||||
&& (carried(obj) ? obj->unpaid : !obj->no_charge)) {
|
||||
shkp = shop_keeper(*in_rooms(oox, ooy, SHOPBASE));
|
||||
stolen_value(obj, oox, ooy,
|
||||
(shkp && shkp->mpeaceful), FALSE);
|
||||
}
|
||||
if (obj->timed)
|
||||
obj_stop_timers(obj);
|
||||
@@ -2119,6 +2156,7 @@ dozap()
|
||||
&& !(objects[obj->otyp].oc_dir == NODIR)) {
|
||||
if ((damage = zapyourself(obj, TRUE)) != 0) {
|
||||
char buf[BUFSZ];
|
||||
|
||||
Sprintf(buf, "zapped %sself with a wand", uhim());
|
||||
losehp(Maybe_Half_Phys(damage), buf, NO_KILLER_PREFIX);
|
||||
}
|
||||
@@ -2678,10 +2716,10 @@ struct obj *obj; /* wand or spell */
|
||||
if (is_db_wall(x, y) && find_drawbridge(&xx, &yy)) {
|
||||
open_drawbridge(xx, yy);
|
||||
disclose = TRUE;
|
||||
} else if (u.dz > 0 && (x == xdnstair && y == ydnstair) &&
|
||||
} else if (u.dz > 0 && (x == xdnstair && y == ydnstair)
|
||||
/* can't use the stairs down to quest level 2 until
|
||||
leader "unlocks" them; give feedback if you try */
|
||||
on_level(&u.uz, &qstart_level) && !ok_to_quest()) {
|
||||
&& on_level(&u.uz, &qstart_level) && !ok_to_quest()) {
|
||||
pline_The("stairs seem to ripple momentarily.");
|
||||
disclose = TRUE;
|
||||
}
|
||||
@@ -3100,7 +3138,7 @@ struct obj **pobj; /* object tossed/used, set to NULL
|
||||
}
|
||||
|
||||
if (is_pick(obj) && inside_shop(x, y)
|
||||
&& (mtmp = shkcatch(obj, x, y))) {
|
||||
&& (mtmp = shkcatch(obj, x, y)) != 0) {
|
||||
tmp_at(DISP_END, 0);
|
||||
return mtmp;
|
||||
}
|
||||
@@ -3109,9 +3147,9 @@ struct obj **pobj; /* object tossed/used, set to NULL
|
||||
|
||||
/* iron bars will block anything big enough */
|
||||
if ((weapon == THROWN_WEAPON || weapon == KICKED_WEAPON)
|
||||
&& typ == IRONBARS && hits_bars(pobj, x - ddx, y - ddy,
|
||||
bhitpos.x, bhitpos.y,
|
||||
point_blank ? 0 : !rn2(5), 1)) {
|
||||
&& typ == IRONBARS
|
||||
&& hits_bars(pobj, x - ddx, y - ddy, bhitpos.x, bhitpos.y,
|
||||
point_blank ? 0 : !rn2(5), 1)) {
|
||||
/* caveat: obj might now be null... */
|
||||
obj = *pobj;
|
||||
bhitpos.x -= ddx;
|
||||
@@ -3286,6 +3324,7 @@ struct obj **pobj; /* object tossed/used, set to NULL
|
||||
&& obj->otyp == HEAVY_IRON_BALL) {
|
||||
struct obj *bobj;
|
||||
struct trap *t;
|
||||
|
||||
if ((bobj = sobj_at(BOULDER, x, y)) != 0) {
|
||||
if (cansee(x, y))
|
||||
pline("%s hits %s.", The(distant_name(obj, xname)),
|
||||
@@ -3404,7 +3443,8 @@ int dx, dy;
|
||||
return (struct monst *) 0;
|
||||
}
|
||||
|
||||
/* used by buzz(); also used by munslime(muse.c); returns damage to mon */
|
||||
/* used by buzz(); also used by munslime(muse.c); returns damage applied
|
||||
to mon; note: caller is responsible for killing mon if damage is fatal */
|
||||
int
|
||||
zhitm(mon, type, nd, ootmp)
|
||||
register struct monst *mon;
|
||||
@@ -3826,7 +3866,7 @@ const char *fltxt;
|
||||
if (type < 0)
|
||||
monkilled(mon, (char *) 0, -AD_RBRE);
|
||||
else
|
||||
xkilled(mon, 2);
|
||||
xkilled(mon, XKILL_NOMSG | XKILL_NOCORPSE);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3845,7 +3885,6 @@ register xchar sx, sy;
|
||||
register int dx, dy;
|
||||
{
|
||||
int range, abstype = abs(type) % 10;
|
||||
struct rm *lev;
|
||||
register xchar lsx, lsy;
|
||||
struct monst *mon;
|
||||
coord save_bhitpos;
|
||||
@@ -3889,23 +3928,24 @@ register int dx, dy;
|
||||
sx += dx;
|
||||
lsy = sy;
|
||||
sy += dy;
|
||||
if (isok(sx, sy) && (lev = &levl[sx][sy])->typ) {
|
||||
mon = m_at(sx, sy);
|
||||
if (cansee(sx, sy)) {
|
||||
/* reveal/unreveal invisible monsters before tmp_at() */
|
||||
if (mon && !canspotmon(mon))
|
||||
map_invisible(sx, sy);
|
||||
else if (!mon && glyph_is_invisible(levl[sx][sy].glyph)) {
|
||||
unmap_object(sx, sy);
|
||||
newsym(sx, sy);
|
||||
}
|
||||
if (ZAP_POS(lev->typ) || (isok(lsx, lsy) && cansee(lsx, lsy)))
|
||||
tmp_at(sx, sy);
|
||||
delay_output(); /* wait a little */
|
||||
}
|
||||
} else
|
||||
if (!isok(sx, sy) || levl[sx][sy].typ == STONE)
|
||||
goto make_bounce;
|
||||
|
||||
mon = m_at(sx, sy);
|
||||
if (cansee(sx, sy)) {
|
||||
/* reveal/unreveal invisible monsters before tmp_at() */
|
||||
if (mon && !canspotmon(mon))
|
||||
map_invisible(sx, sy);
|
||||
else if (!mon && glyph_is_invisible(levl[sx][sy].glyph)) {
|
||||
unmap_object(sx, sy);
|
||||
newsym(sx, sy);
|
||||
}
|
||||
if (ZAP_POS(levl[sx][sy].typ)
|
||||
|| (isok(lsx, lsy) && cansee(lsx, lsy)))
|
||||
tmp_at(sx, sy);
|
||||
delay_output(); /* wait a little */
|
||||
}
|
||||
|
||||
/* hit() and miss() need bhitpos to match the target */
|
||||
bhitpos.x = sx, bhitpos.y = sy;
|
||||
/* Fireballs only damage when they explode */
|
||||
@@ -4017,24 +4057,28 @@ register int dx, dy;
|
||||
nomul(0);
|
||||
}
|
||||
|
||||
if (!ZAP_POS(lev->typ) || (closed_door(sx, sy) && (range >= 0))) {
|
||||
if (!ZAP_POS(levl[sx][sy].typ)
|
||||
|| (closed_door(sx, sy) && range >= 0)) {
|
||||
int bounce;
|
||||
uchar rmn;
|
||||
boolean fireball;
|
||||
|
||||
make_bounce:
|
||||
if (type == ZT_SPELL(ZT_FIRE)) {
|
||||
sx = lsx;
|
||||
sy = lsy;
|
||||
break; /* fireballs explode before the wall */
|
||||
}
|
||||
bounce = 0;
|
||||
range--;
|
||||
if (range && isok(lsx, lsy) && cansee(lsx, lsy)) {
|
||||
pline("%s %s!", The(fltxt),
|
||||
Is_airlevel(&u.uz)
|
||||
? "vanishes into the aether"
|
||||
: "bounces");
|
||||
if (Is_airlevel(&u.uz)) goto get_out_buzz;
|
||||
fireball = (type == ZT_SPELL(ZT_FIRE));
|
||||
if ((--range > 0 && isok(lsx, lsy) && cansee(lsx, lsy))
|
||||
|| fireball) {
|
||||
if (Is_airlevel(&u.uz)) { /* nothing to bounce off of */
|
||||
pline_The("%s vanishes into the aether!", fltxt);
|
||||
if (fireball)
|
||||
type = ZT_WAND(ZT_FIRE); /* skip pending fireball */
|
||||
break;
|
||||
} else if (fireball) {
|
||||
sx = lsx;
|
||||
sy = lsy;
|
||||
break; /* fireballs explode before the obstacle */
|
||||
} else
|
||||
pline_The("%s bounces!", fltxt);
|
||||
}
|
||||
if (!dx || !dy || !rn2(20)) {
|
||||
dx = -dx;
|
||||
@@ -4069,7 +4113,6 @@ register int dx, dy;
|
||||
tmp_at(DISP_END, 0);
|
||||
if (type == ZT_SPELL(ZT_FIRE))
|
||||
explode(sx, sy, type, d(12, 6), 0, EXPL_FIERY);
|
||||
get_out_buzz:
|
||||
if (shopdamage)
|
||||
pay_for_damage(abstype == ZT_FIRE
|
||||
? "burn away"
|
||||
@@ -4686,9 +4729,12 @@ register int osym, dmgtyp;
|
||||
|
||||
if (!cnt)
|
||||
continue;
|
||||
mult = (cnt == quan)
|
||||
? (quan > 1) ? "All of your " : "Your"
|
||||
: (cnt == 1L) ? "One of your" : "Some of your";
|
||||
mult = (cnt == 1L)
|
||||
? (quan == 1L) ? "Your" /* 1 of 1 */
|
||||
: "One of your" /* 1 of N */
|
||||
: (cnt < quan) ? "Some of your" /* n of N */
|
||||
: (quan == 2L) ? "Both of your" /* 2 of 2 */
|
||||
: "All of your"; /* N of N */
|
||||
pline("%s %s %s!", mult, xname(obj),
|
||||
destroy_strings[dindx][(cnt > 1L)]);
|
||||
if (osym == POTION_CLASS && dmgtyp != AD_COLD) {
|
||||
|
||||
+1613
File diff suppressed because it is too large
Load Diff
+39
-21
@@ -1,5 +1,5 @@
|
||||
# NetHack Makefile.
|
||||
# NetHack 3.6 Makefile.src $NHDT-Date: 1447313972 2015/11/12 07:39:32 $ $NHDT-Branch: master $:$NHDT-Revision: 1.45 $
|
||||
# NetHack 3.6 Makefile.src $NHDT-Date: 1459122529 2016/03/27 23:48:49 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.46 $
|
||||
|
||||
# Root of source tree:
|
||||
NHSROOT=..
|
||||
@@ -167,6 +167,11 @@ CXX=g++
|
||||
#CXX=arm-linux-g++
|
||||
#LINK=arm-linux-gcc
|
||||
|
||||
# we specify C preprocessor flags via CFLAGS; files built with default rules
|
||||
# might include $(CPPFLAGS) which could get a value from user's environment;
|
||||
# we avoid that by forcing it empty rather than by overriding default rules
|
||||
CPPFLAGS =
|
||||
|
||||
# file for regular expression matching
|
||||
REGEXOBJ = posixregex.o
|
||||
#REGEXOBJ = pmatchregex.o
|
||||
@@ -333,11 +338,11 @@ HACKCSRC = allmain.c alloc.c apply.c artifact.c attrib.c ball.c bones.c \
|
||||
mkmaze.c mkobj.c mkroom.c mon.c mondata.c monmove.c monst.c \
|
||||
mplayer.c mthrowu.c muse.c music.c o_init.c objects.c objnam.c \
|
||||
options.c pager.c pickup.c pline.c polyself.c potion.c pray.c \
|
||||
priest.c quest.c questpgr.c read.c rect.c region.c restore.c rip.c \
|
||||
rnd.c role.c rumors.c save.c shk.c shknam.c sit.c sounds.c sp_lev.c \
|
||||
spell.c steal.c steed.c sys.c teleport.c timeout.c topten.c track.c \
|
||||
trap.c \
|
||||
u_init.c uhitm.c vault.c version.c vision.c weapon.c were.c wield.c \
|
||||
priest.c quest.c questpgr.c read.c rect.c region.c restore.c \
|
||||
rip.c rnd.c role.c rumors.c save.c shk.c shknam.c sit.c sounds.c \
|
||||
sp_lev.c spell.c steal.c steed.c sys.c teleport.c timeout.c \
|
||||
topten.c track.c trap.c u_init.c \
|
||||
uhitm.c vault.c version.c vision.c weapon.c were.c wield.c \
|
||||
windows.c wizard.c worm.c worn.c write.c zap.c
|
||||
|
||||
# all operating-system-dependent .c (for dependencies and such)
|
||||
@@ -347,6 +352,7 @@ SYSCSRC = ../sys/atari/tos.c ../sys/share/pcmain.c ../sys/share/pcsys.c \
|
||||
../sys/share/random.c \
|
||||
../sys/share/ioctl.c ../sys/share/unixtty.c ../sys/unix/unixmain.c \
|
||||
../sys/unix/unixunix.c ../sys/unix/unixres.c ../sys/be/bemain.c
|
||||
SYSCXXSRC = ../sys/share/cppregex.cpp
|
||||
|
||||
# generated source files (tile.c is handled separately via WINxxxSRC)
|
||||
GENCSRC = monstr.c vis_tab.c #tile.c
|
||||
@@ -357,9 +363,9 @@ WINCSRC = $(WINTTYSRC) $(WINX11SRC) $(WINGNOMESRC) $(WINGEMSRC)
|
||||
WINCXXSRC = $(WINQTSRC) $(WINBESRC)
|
||||
|
||||
# Files for window system chaining. Requires SYSCF; include via HINTSRC/HINTOBJ
|
||||
CHAINSRC=../win/chain/wc_chainin.c ../win/chain/wc_chainout.c \
|
||||
../win/chain/wc_trace.c
|
||||
CHAINOBJ=wc_chainin.o wc_chainout.o wc_trace.o
|
||||
CHAINSRC = ../win/chain/wc_chainin.c ../win/chain/wc_chainout.c \
|
||||
../win/chain/wc_trace.c
|
||||
CHAINOBJ = wc_chainin.o wc_chainout.o wc_trace.o
|
||||
|
||||
# .c files for this version (for date.h)
|
||||
VERSOURCES = $(HACKCSRC) $(SYSSRC) $(WINSRC) $(CHAINSRC) $(GENCSRC)
|
||||
@@ -378,9 +384,9 @@ HACKINCL = align.h amiconf.h artifact.h artilist.h attrib.h beconf.h botl.h \
|
||||
global.h hack.h lev.h lint.h macconf.h mextra.h mfndpos.h micro.h \
|
||||
mkroom.h \
|
||||
monattk.h mondata.h monflag.h monst.h monsym.h obj.h objclass.h \
|
||||
os2conf.h patchlevel.h pcconf.h permonst.h prop.h rect.h region.h rm.h \
|
||||
sp_lev.h spell.h sys.h system.h tcap.h timeout.h tosconf.h tradstdc.h \
|
||||
trampoli.h trap.h unixconf.h vision.h vmsconf.h wintty.h \
|
||||
os2conf.h patchlevel.h pcconf.h permonst.h prop.h rect.h region.h \
|
||||
rm.h sp_lev.h spell.h sys.h system.h tcap.h timeout.h tosconf.h \
|
||||
tradstdc.h trampoli.h trap.h unixconf.h vision.h vmsconf.h wintty.h \
|
||||
winX.h winprocs.h wintype.h you.h youprop.h
|
||||
|
||||
HSOURCES = $(HACKINCL) date.h onames.h pm.h vis_tab.h\
|
||||
@@ -490,23 +496,33 @@ qt_win.moc: ../include/qt_win.h
|
||||
qttableview.moc: ../include/qttableview.h
|
||||
$(QTDIR)/bin/moc -o qttableview.moc ../include/qttableview.h
|
||||
|
||||
$(MAKEDEFS): ../util/makedefs.c $(CONFIG_H) ../include/permonst.h \
|
||||
# build monst.o and objects.o before executing '$(MAKE) makedefs'
|
||||
$(MAKEDEFS): $(FIRSTOBJ) \
|
||||
../util/makedefs.c $(CONFIG_H) ../include/permonst.h \
|
||||
../include/objclass.h ../include/monsym.h \
|
||||
../include/artilist.h ../include/dungeon.h ../include/obj.h \
|
||||
../include/monst.h ../include/you.h ../include/flag.h \
|
||||
../include/dlb.h ../include/patchlevel.h ../include/qtext.h
|
||||
@( cd ../util ; $(MAKE) makedefs)
|
||||
@( cd ../util ; $(MAKE) makedefs )
|
||||
|
||||
# Source files created by 'makedefs' at build time.
|
||||
# Each is given an artificial dependency upon the one before
|
||||
# so that parallel makes will have to build them sequentially.
|
||||
# (More for documentation than effect; 'make' should know not
|
||||
# to try to build $(MAKEDEFS) for bar.h while it is in the
|
||||
# process of building it for foo.h.)
|
||||
../include/onames.h: $(MAKEDEFS)
|
||||
@( cd ../util ; $(MAKE) ../include/onames.h )
|
||||
../include/pm.h: $(MAKEDEFS)
|
||||
../include/pm.h: $(MAKEDEFS) ../include/onames.h
|
||||
@( cd ../util ; $(MAKE) ../include/pm.h )
|
||||
monstr.c: $(MAKEDEFS)
|
||||
monstr.c: $(MAKEDEFS) ../include/pm.h
|
||||
@( cd ../util ; $(MAKE) ../src/monstr.c )
|
||||
../include/vis_tab.h: $(MAKEDEFS)
|
||||
../include/vis_tab.h: $(MAKEDEFS) monstr.c
|
||||
@( cd ../util ; $(MAKE) ../include/vis_tab.h )
|
||||
# makedefs -z makes both vis_tab.h and vis_tab.c, but writes the .h first
|
||||
vis_tab.c: ../include/vis_tab.h
|
||||
# Created at build time for configurations which support tiles,
|
||||
# but not by makedefs so not connected to the others.
|
||||
tile.c: ../win/share/tilemap.c $(HACK_H)
|
||||
@( cd ../util ; $(MAKE) ../src/tile.c )
|
||||
|
||||
@@ -551,11 +567,11 @@ spotless: clean
|
||||
|
||||
|
||||
depend: ../sys/unix/depend.awk \
|
||||
$(SYSCSRC) $(WINCSRC) $(WINCXXSRC) $(CHAINSRC) $(GENCSRC) \
|
||||
$(HACKCSRC)
|
||||
$(SYSCSRC) $(WINCSRC) $(SYSCXXSRC) $(WINCXXSRC) \
|
||||
$(CHAINSRC) $(GENCSRC) $(HACKCSRC)
|
||||
$(AWK) -f ../sys/unix/depend.awk ../include/*.h \
|
||||
$(SYSCSRC) $(WINCSRC) $(WINCXXSRC) $(CHAINSRC) $(GENCSRC) \
|
||||
$(HACKCSRC) >makedep
|
||||
$(SYSCSRC) $(WINCSRC) $(SYSCXXSRC) $(WINCXXSRC) \
|
||||
$(CHAINSRC) $(GENCSRC) $(HACKCSRC) >makedep
|
||||
@echo '/^# DO NOT DELETE THIS LINE OR CHANGE ANYTHING BEYOND IT/+2,$$d' >eddep
|
||||
@echo '$$r makedep' >>eddep
|
||||
@echo 'w' >>eddep
|
||||
@@ -710,6 +726,8 @@ load_img.o: ../win/gem/load_img.c ../include/load_img.h
|
||||
gr_rect.o: ../win/gem/gr_rect.c ../include/gr_rect.h
|
||||
$(CC) $(CFLAGS) -c ../win/gem/gr_rect.c
|
||||
tile.o: tile.c $(HACK_H)
|
||||
cppregex.o: ../sys/share/cppregex.cpp
|
||||
$(CXX) $(CXXFLAGS) -c ../sys/share/cppregex.cpp
|
||||
qt_win.o: ../win/Qt/qt_win.cpp $(HACK_H) ../include/func_tab.h \
|
||||
../include/dlb.h ../include/patchlevel.h ../include/tile2x11.h \
|
||||
../include/qt_win.h ../include/qt_clust.h ../include/qt_kde0.h \
|
||||
|
||||
@@ -186,7 +186,7 @@ check-dlb: options
|
||||
|
||||
dlb:
|
||||
( cd util ; $(MAKE) dlb )
|
||||
( cd dat ; ../util/dlb cf nhdat $(DATDLB) )
|
||||
( cd dat ; LC_ALL=C ; ../util/dlb cf nhdat $(DATDLB) )
|
||||
|
||||
# recover can be used when INSURANCE is defined in include/config.h
|
||||
# and the checkpoint option is true
|
||||
|
||||
@@ -95,6 +95,11 @@ NHSROOT=..
|
||||
#CFLAGS = -O -I../include
|
||||
#LFLAGS =
|
||||
|
||||
# we specify C preprocessor flags via CFLAGS; files built with default rules
|
||||
# might include $(CPPFLAGS) which could get a value from user's environment;
|
||||
# we avoid that by forcing it empty rather than by overriding default rules
|
||||
CPPFLAGS =
|
||||
|
||||
LIBS =
|
||||
|
||||
# If you are cross-compiling, you must use this:
|
||||
|
||||
Regular → Executable
+129
-50
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 makedefs.c $NHDT-Date: 1455357861 2016/02/13 10:04:21 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.109 $ */
|
||||
/* NetHack 3.6 makedefs.c $NHDT-Date: 1459208813 2016/03/28 23:46:53 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.110 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* Copyright (c) M. Stephenson, 1990, 1991. */
|
||||
/* Copyright (c) Dean Luick, 1990. */
|
||||
@@ -578,36 +578,35 @@ do_ext_makedefs(int argc, char **argv)
|
||||
#undef CONSUME
|
||||
|
||||
/*
|
||||
Filtering syntax:
|
||||
Any line NOT starting with a caret is either suppressed or passed through
|
||||
unchanged depending on the current conditional state.
|
||||
|
||||
The default conditional state is printing on.
|
||||
|
||||
Conditionals may be nested.
|
||||
|
||||
makedefs will exit with a EXIT_FAILURE if any errors are detected; as many
|
||||
errors as possible are detected before giving up.
|
||||
|
||||
Unknown identifiers are treated as TRUE and also as an error to allow
|
||||
processing to continue past the unknown identifier (note that "#undef" is
|
||||
different than unknown).
|
||||
|
||||
Any line starting with a caret is a control line; as in C, zero or more
|
||||
spaces
|
||||
may be embedded in the line almost anywhere; the caret MUST be in column 1.
|
||||
(XXX for the moment, no white space is allowed after the caret because
|
||||
existing lines in the docs look like that)
|
||||
|
||||
Control lines:
|
||||
^^ a line starting with a (single) literal caret
|
||||
^# a comment - the line is ignored
|
||||
^?ID if defined(ID)
|
||||
^!ID if !defined(ID)
|
||||
^: else
|
||||
^. endif
|
||||
|
||||
*/
|
||||
* Filtering syntax:
|
||||
* Any line NOT starting with a caret is either suppressed or passed
|
||||
* through unchanged depending on the current conditional state.
|
||||
*
|
||||
* The default conditional state is printing on.
|
||||
*
|
||||
* Conditionals may be nested.
|
||||
*
|
||||
* makedefs will exit with a EXIT_FAILURE if any errors are detected;
|
||||
* as many errors as possible are detected before giving up.
|
||||
*
|
||||
* Unknown identifiers are treated as TRUE and also as an error to
|
||||
* allow processing to continue past the unknown identifier (note
|
||||
* that "#undef" is different than unknown).
|
||||
*
|
||||
* Any line starting with a caret is a control line; as in C, zero or
|
||||
* more spaces may be embedded in the line almost anywhere; the caret
|
||||
* MUST be in column 1.
|
||||
* (XXX for the moment, no white space is allowed after the caret because
|
||||
* existing lines in the docs look like that.)
|
||||
*
|
||||
* Control lines:
|
||||
* ^^ a line starting with a (single) literal caret
|
||||
* ^# a comment - the line is ignored
|
||||
* ^?ID if defined(ID)
|
||||
* ^!ID if !defined(ID)
|
||||
* ^: else
|
||||
* ^. endif
|
||||
*/
|
||||
#define GREP_MAGIC '^'
|
||||
#define GREP_STACK_SIZE 100
|
||||
#ifdef notyet
|
||||
@@ -616,9 +615,9 @@ static int grep_rewrite = 0; /* need to (possibly) rewrite lines */
|
||||
static int grep_writing = 1; /* need to copy lines to output */
|
||||
static int grep_errors = 0;
|
||||
static int grep_sp = 0;
|
||||
#define ST_LD(old, opp) (!!(old) | (!!(opp) << 1))
|
||||
#define ST_OLD(v) ((v) &1)
|
||||
#define ST_OPP(v) !!((v) &2)
|
||||
#define ST_LD(old, opp) (((old) ? 1 : 0) | ((opp) ? 2 : 0))
|
||||
#define ST_OLD(v) (((v) & 1) != 0)
|
||||
#define ST_OPP(v) (((v) & 2) != 0)
|
||||
#define ST_ELSE 4
|
||||
static int grep_stack[GREP_STACK_SIZE] = { ST_LD(1, 0) };
|
||||
static int grep_lineno = 0;
|
||||
@@ -1166,6 +1165,9 @@ make_version()
|
||||
return;
|
||||
}
|
||||
|
||||
/* REPRODUCIBLE_BUILD will change this to TRUE */
|
||||
static boolean date_via_env = FALSE;
|
||||
|
||||
static char *
|
||||
version_string(outbuf, delim)
|
||||
char *outbuf;
|
||||
@@ -1195,8 +1197,9 @@ const char *build_date;
|
||||
Strcat(subbuf, " Beta");
|
||||
#endif
|
||||
|
||||
Sprintf(outbuf, "%s NetHack%s Version %s - last build %s.", PORT_ID,
|
||||
subbuf, version_string(versbuf, "."), build_date);
|
||||
Sprintf(outbuf, "%s NetHack%s Version %s - last %s %s.", PORT_ID,
|
||||
subbuf, version_string(versbuf, "."),
|
||||
date_via_env ? "revision" : "build", build_date);
|
||||
return outbuf;
|
||||
}
|
||||
|
||||
@@ -1216,8 +1219,9 @@ const char *build_date;
|
||||
Strcat(subbuf, " Beta");
|
||||
#endif
|
||||
|
||||
Sprintf(outbuf, " Version %s %s%s, built %s.",
|
||||
version_string(versbuf, "."), PORT_ID, subbuf, &build_date[4]);
|
||||
Sprintf(outbuf, " Version %s %s%s, %s %s.",
|
||||
version_string(versbuf, "."), PORT_ID, subbuf,
|
||||
date_via_env ? "revised" : "built", &build_date[4]);
|
||||
#if 0
|
||||
Sprintf(outbuf, "%s NetHack%s %s Copyright 1985-%s (built %s)",
|
||||
PORT_ID, subbuf, version_string(versbuf,"."), RELEASE_YEAR,
|
||||
@@ -1256,20 +1260,96 @@ do_date()
|
||||
Fprintf(ofp, "%s", Dont_Edit_Code);
|
||||
|
||||
(void) time(&clocktim);
|
||||
Strcpy(cbuf, ctime(&clocktim));
|
||||
#ifdef REPRODUCIBLE_BUILD
|
||||
{
|
||||
/*
|
||||
* Use date+time of latest source file revision (set up in
|
||||
* our environment rather than derived by scanning sources)
|
||||
* instead of current date+time, so that later rebuilds of
|
||||
* the same sources specifying the same configuration will
|
||||
* produce the same result.
|
||||
*
|
||||
* Changing the configuration should be done by modifying
|
||||
* config.h or <port>conf.h and setting SOURCE_DATE_EPOCH
|
||||
* based on whichever changed most recently, not by using
|
||||
* make CFLAGS='-Dthis -Dthat'
|
||||
* to make alterations on the fly.
|
||||
*
|
||||
* Limited validation is performed to prevent dates in the
|
||||
* future (beyond a leeway of 24 hours) or distant past.
|
||||
*
|
||||
* Assumes the value of time_t is in seconds, which is
|
||||
* fundamental for Unix and mandated by POSIX. For any ports
|
||||
* where that isn't true, leaving REPRODUCIBLE_BUILD disabled
|
||||
* is probably preferrable to hacking this code....
|
||||
*/
|
||||
static struct tm nh360; /* static init should yield UTC timezone */
|
||||
unsigned long sd_num, sd_earliest, sd_latest;
|
||||
const char *sd_str = getenv("SOURCE_DATE_EPOCH");
|
||||
|
||||
for (c = cbuf; *c; c++)
|
||||
if (*c == '\n')
|
||||
break;
|
||||
*c = '\0'; /* strip off the '\n' */
|
||||
Fprintf(ofp, "#define BUILD_DATE \"%s\"\n", cbuf);
|
||||
Fprintf(ofp, "#define BUILD_TIME (%ldL)\n", (long) clocktim);
|
||||
Fprintf(ofp, "\n");
|
||||
if (sd_str) {
|
||||
sd_num = strtoul(sd_str, (char **) 0, 10);
|
||||
/*
|
||||
* Note: this does not need to be updated for future
|
||||
* releases. It serves as a sanity check for potentially
|
||||
* mis-set environment, not a hard baseline for when the
|
||||
* current version could have first been built.
|
||||
*/
|
||||
/* oldest date we'll accept: 7-Dec-2015 (release of 3.6.0) */
|
||||
nh360.tm_mday = 7;
|
||||
nh360.tm_mon = 12 - 1;
|
||||
nh360.tm_year = 2015 - 1900;
|
||||
sd_earliest = (unsigned long) mktime(&nh360);
|
||||
/* 'youngest' date we'll accept: 24 hours in the future */
|
||||
sd_latest = (unsigned long) clocktim + 24L * 60L * 60L;
|
||||
|
||||
if (sd_num >= sd_earliest && sd_num <= sd_latest) {
|
||||
/* use SOURCE_DATE_EPOCH value */
|
||||
clocktim = (time_t) sd_num;
|
||||
date_via_env = TRUE;
|
||||
} else {
|
||||
Fprintf(stderr, "? Invalid value for SOURCE_DATE_EPOCH (%lu)",
|
||||
sd_num);
|
||||
if (sd_num > 0L && sd_num < sd_earliest)
|
||||
Fprintf(stderr, ", older than %lu", sd_earliest);
|
||||
else if (sd_num > sd_latest)
|
||||
Fprintf(stderr, ", newer than %lu", sd_latest);
|
||||
Fprintf(stderr, ".\n");
|
||||
Fprintf(stderr, ": Reverting to current date+time (%lu).\n",
|
||||
(unsigned long) clocktim);
|
||||
(void) fflush(stderr);
|
||||
}
|
||||
} else {
|
||||
/* REPRODUCIBLE_BUILD enabled but SOURCE_DATE_EPOCH is missing */
|
||||
Fprintf(stderr, "? No value for SOURCE_DATE_EPOCH.\n");
|
||||
Fprintf(stderr, ": Using current date+time (%lu).\n",
|
||||
(unsigned long) clocktim);
|
||||
(void) fflush(stderr);
|
||||
}
|
||||
Strcpy(cbuf, asctime(gmtime(&clocktim)));
|
||||
}
|
||||
#else
|
||||
/* ordinary build: use current date+time */
|
||||
Strcpy(cbuf, ctime(&clocktim));
|
||||
#endif
|
||||
|
||||
if ((c = index(cbuf, '\n')) != 0)
|
||||
*c = '\0'; /* strip off the '\n' */
|
||||
#ifdef NHSTDC
|
||||
ul_sfx = "UL";
|
||||
#else
|
||||
ul_sfx = "L";
|
||||
#endif
|
||||
if (date_via_env)
|
||||
Fprintf(ofp, "#define SOURCE_DATE_EPOCH (%lu%s) /* via getenv() */\n",
|
||||
(unsigned long) clocktim, ul_sfx);
|
||||
Fprintf(ofp, "#define BUILD_DATE \"%s\"\n", cbuf);
|
||||
if (date_via_env)
|
||||
Fprintf(ofp, "#define BUILD_TIME SOURCE_DATE_EPOCH\n");
|
||||
else
|
||||
Fprintf(ofp, "#define BUILD_TIME (%lu%s)\n",
|
||||
(unsigned long) clocktim, ul_sfx);
|
||||
Fprintf(ofp, "\n");
|
||||
Fprintf(ofp, "#define VERSION_NUMBER 0x%08lx%s\n", version.incarnation,
|
||||
ul_sfx);
|
||||
Fprintf(ofp, "#define VERSION_FEATURES 0x%08lx%s\n", version.feature_set,
|
||||
@@ -1294,10 +1374,11 @@ do_date()
|
||||
#ifdef AMIGA
|
||||
{
|
||||
struct tm *tm = localtime((time_t *) &clocktim);
|
||||
|
||||
Fprintf(ofp, "#define AMIGA_VERSION_STRING ");
|
||||
Fprintf(ofp, "\"\\0$VER: NetHack %d.%d.%d (%d.%d.%d)\"\n",
|
||||
VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL, tm->tm_mday,
|
||||
tm->tm_mon + 1, tm->tm_year + 1900);
|
||||
VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL,
|
||||
tm->tm_mday, tm->tm_mon + 1, tm->tm_year + 1900);
|
||||
}
|
||||
#endif
|
||||
Fclose(ofp);
|
||||
@@ -1963,7 +2044,6 @@ do_oracles()
|
||||
void
|
||||
do_dungeon()
|
||||
{
|
||||
int rcnt = 0;
|
||||
char *line;
|
||||
|
||||
Sprintf(filename, DATA_IN_TEMPLATE, DGN_I_FILE);
|
||||
@@ -1989,7 +2069,6 @@ do_dungeon()
|
||||
while ((line = fgetline(ifp)) != 0) {
|
||||
SpinCursor(3);
|
||||
|
||||
rcnt++;
|
||||
if (line[0] == '#') {
|
||||
free(line);
|
||||
continue; /* discard comments */
|
||||
|
||||
+44
-12
@@ -1379,6 +1379,7 @@ void NetHackQtStringRequestor::SetDefault(const char* d)
|
||||
{
|
||||
input.setText(d);
|
||||
}
|
||||
|
||||
bool NetHackQtStringRequestor::Get(char* buffer, int maxchar)
|
||||
{
|
||||
input.setMaxLength(maxchar);
|
||||
@@ -1432,6 +1433,7 @@ void NetHackQtStringRequestor::done(int i)
|
||||
NetHackQtWindow::NetHackQtWindow()
|
||||
{
|
||||
}
|
||||
|
||||
NetHackQtWindow::~NetHackQtWindow()
|
||||
{
|
||||
}
|
||||
@@ -1514,7 +1516,10 @@ void NetHackQtMapWindow::putMessage(int attr, const char* text)
|
||||
messages += "\n";
|
||||
messages += text;
|
||||
QFontMetrics fm = fontMetrics();
|
||||
messages_rect = fm.boundingRect(viewport.contentsX(),viewport.contentsY(),viewport.width(),0, WordBreak|AlignTop|AlignLeft|DontClip, messages);
|
||||
messages_rect = fm.boundingRect(viewport.contentsX(), viewport.contentsY(),
|
||||
viewport.width(), 0,
|
||||
WordBreak|AlignTop|AlignLeft|DontClip,
|
||||
messages);
|
||||
update(messages_rect);
|
||||
}
|
||||
|
||||
@@ -1701,7 +1706,9 @@ void NetHackQtMapWindow::paintEvent(QPaintEvent* event)
|
||||
&& ::iflags.hilite_pet
|
||||
#endif
|
||||
) {
|
||||
painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pet_annotation);
|
||||
painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(),
|
||||
j*qt_settings->glyphs().height()),
|
||||
pet_annotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1717,7 +1724,9 @@ void NetHackQtMapWindow::paintEvent(QPaintEvent* event)
|
||||
&& ::iflags.hilite_pet
|
||||
#endif
|
||||
) {
|
||||
painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pet_annotation);
|
||||
painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(),
|
||||
j*qt_settings->glyphs().height()),
|
||||
pet_annotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2827,6 +2836,7 @@ void NetHackQtMenuWindow::Layout()
|
||||
invert->setGeometry(x,0,butw,buth); x+=butw; butw=(dialog->width()-x)/1;
|
||||
search->setGeometry(x,0,butw,buth);
|
||||
}
|
||||
|
||||
int NetHackQtMenuWindow::SelectMenu(int h, MENU_ITEM_P **menu_list)
|
||||
{
|
||||
setFont(str_fixed ?
|
||||
@@ -2947,6 +2957,7 @@ int NetHackQtMenuWindow::SelectMenu(int h, MENU_ITEM_P **menu_list)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void NetHackQtMenuWindow::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
if (viewHeight() < totalHeight() && !(event->state()&ShiftButton)) {
|
||||
@@ -2974,12 +2985,14 @@ void NetHackQtMenuWindow::ChooseNone()
|
||||
if (item[i].selected) ToggleSelect(i);
|
||||
}
|
||||
}
|
||||
|
||||
void NetHackQtMenuWindow::Invert()
|
||||
{
|
||||
for (int i=0; i<itemcount; i++) {
|
||||
ToggleSelect(i);
|
||||
}
|
||||
}
|
||||
|
||||
void NetHackQtMenuWindow::Search()
|
||||
{
|
||||
NetHackQtStringRequestor requestor(keysource,"Search for:");
|
||||
@@ -2991,6 +3004,7 @@ void NetHackQtMenuWindow::Search()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetHackQtMenuWindow::ToggleSelect(int i)
|
||||
{
|
||||
if (item[i].Selectable()) {
|
||||
@@ -3115,6 +3129,7 @@ void NetHackQtMenuWindow::mousePressEvent(QMouseEvent* event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetHackQtMenuWindow::mouseReleaseEvent(QMouseEvent* event)
|
||||
{
|
||||
if (pressed>=0) {
|
||||
@@ -3123,6 +3138,7 @@ void NetHackQtMenuWindow::mouseReleaseEvent(QMouseEvent* event)
|
||||
updateCell(p,3);
|
||||
}
|
||||
}
|
||||
|
||||
void NetHackQtMenuWindow::mouseMoveEvent(QMouseEvent* event)
|
||||
{
|
||||
if (pressed>=0) {
|
||||
@@ -3292,7 +3308,7 @@ static char** rip_line=0;
|
||||
Sprintf(rip_line[GOLD_LINE], "%ld Au", done_money);
|
||||
|
||||
/* Put together death description */
|
||||
formatkiller(buf, sizeof buf, how);
|
||||
formatkiller(buf, sizeof buf, how, FALSE);
|
||||
|
||||
/* Put death type on stone */
|
||||
for (line=DEATH_LINE, dpx = buf; line<YEAR_LINE; line++) {
|
||||
@@ -4274,8 +4290,9 @@ NetHackQtGlyphs::NetHackQtGlyphs()
|
||||
} else {
|
||||
tiles_per_row = TILES_PER_ROW;
|
||||
if (img.width()%tiles_per_row) {
|
||||
impossible("Tile file \"%s\" has %d columns, not multiple of row count (%d)",
|
||||
tile_file, img.width(), tiles_per_row);
|
||||
impossible(
|
||||
"Tile file \"%s\" has %d columns, not multiple of row count (%d)",
|
||||
tile_file, img.width(), tiles_per_row);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -4368,18 +4385,30 @@ QWidget* NetHackQtMenuOrTextWindow::Widget()
|
||||
// Text
|
||||
void NetHackQtMenuOrTextWindow::Clear()
|
||||
{
|
||||
if (!actual) impossible("Clear called before we know if Menu or Text");
|
||||
actual->Clear();
|
||||
if (!actual)
|
||||
impossible("Clear called before we know if Menu or Text");
|
||||
else
|
||||
actual->Clear();
|
||||
}
|
||||
|
||||
void NetHackQtMenuOrTextWindow::Display(bool block)
|
||||
{
|
||||
if (!actual) impossible("Display called before we know if Menu or Text");
|
||||
actual->Display(block);
|
||||
if (!actual)
|
||||
impossible("Display called before we know if Menu or Text");
|
||||
else
|
||||
actual->Display(block);
|
||||
}
|
||||
|
||||
bool NetHackQtMenuOrTextWindow::Destroy()
|
||||
{
|
||||
if (!actual) impossible("Destroy called before we know if Menu or Text");
|
||||
return actual->Destroy();
|
||||
bool res = FALSE;
|
||||
|
||||
if (!actual)
|
||||
impossible("Destroy called before we know if Menu or Text");
|
||||
else
|
||||
res = actual->Destroy();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void NetHackQtMenuOrTextWindow::PutStr(int attr, const char* text)
|
||||
@@ -4394,17 +4423,20 @@ void NetHackQtMenuOrTextWindow::StartMenu()
|
||||
if (!actual) actual=new NetHackQtMenuWindow(keysource);
|
||||
actual->StartMenu();
|
||||
}
|
||||
|
||||
void NetHackQtMenuOrTextWindow::AddMenu(int glyph, const ANY_P* identifier, char ch, char gch, int attr,
|
||||
const char* str, bool presel)
|
||||
{
|
||||
if (!actual) impossible("AddMenu called before we know if Menu or Text");
|
||||
actual->AddMenu(glyph,identifier,ch,gch,attr,str,presel);
|
||||
}
|
||||
|
||||
void NetHackQtMenuOrTextWindow::EndMenu(const char* prompt)
|
||||
{
|
||||
if (!actual) impossible("EndMenu called before we know if Menu or Text");
|
||||
actual->EndMenu(prompt);
|
||||
}
|
||||
|
||||
int NetHackQtMenuOrTextWindow::SelectMenu(int how, MENU_ITEM_P **menu_list)
|
||||
{
|
||||
if (!actual) impossible("SelectMenu called before we know if Menu or Text");
|
||||
|
||||
@@ -0,0 +1,512 @@
|
||||
/* NetHack 3.6 giftiles.c $NHDT-Date: 1457358406 2016/03/07 13:46:46 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.0 $ */
|
||||
/* Copyright (c) Ray Chason, 2016. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
/* giftiles.c -- read a tile map in GIF format */
|
||||
/* Reference: GIF specification,, retrieved from
|
||||
* http://www.w3.org/Graphics/GIF/spec-gif89a.txt */
|
||||
|
||||
#include "config.h"
|
||||
#include "tileset.h"
|
||||
|
||||
#define MIN_LZW_BITS 3
|
||||
#define MAX_LZW_BITS 12
|
||||
#define END_OF_DATA 0x7FFF
|
||||
|
||||
/* For use when reading the GIF as a bitstream */
|
||||
struct Bitstream {
|
||||
/* The file */
|
||||
FILE *fp;
|
||||
|
||||
/* For unpacking LZW codes */
|
||||
unsigned long bits;
|
||||
unsigned char num_bits;
|
||||
unsigned char bit_width;
|
||||
unsigned char initial_bit_width;
|
||||
unsigned char block_size;
|
||||
|
||||
/* The dictionary */
|
||||
struct {
|
||||
unsigned char byte;
|
||||
unsigned short next;
|
||||
} dictionary[1 << MAX_LZW_BITS];
|
||||
unsigned short dict_size;
|
||||
|
||||
/* The string currently being decoded */
|
||||
unsigned char string[1 << MAX_LZW_BITS];
|
||||
unsigned short str_size;
|
||||
|
||||
unsigned short last_code;
|
||||
};
|
||||
|
||||
struct DataBlock {
|
||||
size_t size;
|
||||
size_t index;
|
||||
unsigned char *data;
|
||||
};
|
||||
|
||||
static boolean FDECL(read_data_block, (struct Bitstream *gif, struct DataBlock *block));
|
||||
static void FDECL(free_data_block, (struct DataBlock *block));
|
||||
static unsigned short FDECL(read_u16, (const unsigned char buf[2]));
|
||||
static void FDECL(init_decoder, (struct Bitstream *gif, unsigned bit_width));
|
||||
static void FDECL(reset_decoder, (struct Bitstream *gif));
|
||||
static int FDECL(decode, (struct Bitstream *gif, struct DataBlock *block));
|
||||
static int FDECL(get_code, (struct Bitstream *gif, struct DataBlock *block));
|
||||
static unsigned FDECL(interlace_incr, (unsigned y, unsigned height));
|
||||
|
||||
/*
|
||||
* GIF specifies a canvas, which may have a palette (the "global color table")
|
||||
* of up to 256 colors, of which one is a background color, and zero or more
|
||||
* images, each of which may have its own palette (a "local color table")
|
||||
* independently of the canvas. We will join all palettes found into a single
|
||||
* palette, and indicate that the image uses a palette if, and only if, the
|
||||
* various palettes do not total more than 256 colors.
|
||||
*/
|
||||
|
||||
boolean
|
||||
read_gif_tiles(filename, image)
|
||||
const char *filename;
|
||||
struct TileSetImage *image;
|
||||
{
|
||||
struct Bitstream gif;
|
||||
struct DataBlock block;
|
||||
|
||||
unsigned char buf[1024];
|
||||
size_t size, num_pixels, i;
|
||||
|
||||
/* Image data not returned to the caller */
|
||||
boolean have_gct; /* global color table is present */
|
||||
unsigned gct_size; /* global color table size */
|
||||
unsigned back_color; /* index for background color */
|
||||
unsigned trans_color = 0xFFFF; /* index for transparent palette entry */
|
||||
|
||||
block.data = NULL; /* custodial */
|
||||
gif.fp = NULL; /* custodial */
|
||||
|
||||
image->width = 0;
|
||||
image->height = 0;
|
||||
image->pixels = NULL; /* custodial, returned */
|
||||
image->indexes = NULL; /* custodial, returned */
|
||||
image->image_desc = NULL; /* custodial, returned */
|
||||
image->tile_width = 0;
|
||||
image->tile_height = 0;
|
||||
|
||||
gif.fp = fopen(filename, "rb");
|
||||
if (gif.fp == NULL) goto error;
|
||||
|
||||
/* 17. Header */
|
||||
size = fread(buf, 1, 6, gif.fp);
|
||||
if (size < 6) goto error;
|
||||
if (memcmp(buf, "GIF87a", 6) != 0 && memcmp(buf, "GIF89a", 6) != 0)
|
||||
goto error;
|
||||
|
||||
/* 18. Logical screen descriptor */
|
||||
size = fread(buf, 1, 7, gif.fp);
|
||||
if (size < 7) goto error;
|
||||
image->width = read_u16(buf + 0);
|
||||
image->height = read_u16(buf + 2);
|
||||
have_gct = (buf[4] & 0x80) != 0;
|
||||
gct_size = 1 << ((buf[4] & 0x07) + 1);
|
||||
back_color = buf[5];
|
||||
if (image->width == 0 || image->height == 0) goto error;
|
||||
|
||||
/* 19. Global Color Table */
|
||||
for (i = 0; i < SIZE(image->palette); ++i) {
|
||||
image->palette[i].r = 0;
|
||||
image->palette[i].g = 0;
|
||||
image->palette[i].b = 0;
|
||||
image->palette[i].a = 255;
|
||||
}
|
||||
if (have_gct) {
|
||||
size = fread(buf, 3, gct_size, gif.fp);
|
||||
if (size < gct_size) goto error;
|
||||
for (i = 0; i < gct_size; ++i) {
|
||||
image->palette[i].r = buf[i * 3 + 0];
|
||||
image->palette[i].g = buf[i * 3 + 1];
|
||||
image->palette[i].b = buf[i * 3 + 2];
|
||||
image->palette[i].a = 255;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate pixel area; watch out for overflow */
|
||||
num_pixels = (size_t) image->width * (size_t) image->height;
|
||||
if (num_pixels / image->width != image->height) goto error; /* overflow */
|
||||
size = num_pixels * sizeof(image->pixels[0]);
|
||||
if (size / sizeof(image->pixels[0]) != num_pixels) goto error; /* overflow */
|
||||
image->pixels = (struct Pixel *) alloc(size);
|
||||
image->indexes = (unsigned char *) alloc(num_pixels);
|
||||
|
||||
/* Fill with the background color */
|
||||
for (i = 0; i < num_pixels; ++i) {
|
||||
image->pixels[i] = image->palette[back_color];
|
||||
image->indexes[i] = back_color;
|
||||
}
|
||||
|
||||
/* Read the image data */
|
||||
while (TRUE) {
|
||||
int b = fgetc(gif.fp);
|
||||
if (b == EOF) goto error;
|
||||
|
||||
/* 27. Trailer (0x3B) */
|
||||
if (b == 0x3B) break;
|
||||
|
||||
switch (b) {
|
||||
case 0x2C:
|
||||
/* 20. Image descriptor (0x2C) */
|
||||
{
|
||||
unsigned img_left, img_top, img_width, img_height;
|
||||
boolean have_lct, interlace;
|
||||
unsigned lct_start, lct_size;
|
||||
struct Pixel lct[256];
|
||||
int b;
|
||||
unsigned x, y, x2, y2;
|
||||
|
||||
size = fread(buf, 1, 9, gif.fp);
|
||||
if (size < 9) goto error;
|
||||
img_left = read_u16(buf + 0);
|
||||
img_top = read_u16(buf + 2);
|
||||
img_width = read_u16(buf + 4);
|
||||
img_height = read_u16(buf + 6);
|
||||
have_lct = (buf[8] & 0x80) != 0;
|
||||
interlace = (buf[8] & 0x40) != 0;
|
||||
lct_size = 1 << ((buf[8] & 0x07) + 1);
|
||||
|
||||
/* 21. Local color table */
|
||||
lct_start = 0;
|
||||
memcpy(lct, image->palette, sizeof(lct));
|
||||
if (have_lct) {
|
||||
size = fread(buf, 3, lct_size, gif.fp);
|
||||
if (size < lct_size) goto error;
|
||||
for (i = 0; i < lct_size; ++i) {
|
||||
lct[i].r = buf[i * 3 + 0];
|
||||
lct[i].g = buf[i * 3 + 1];
|
||||
lct[i].b = buf[i * 3 + 2];
|
||||
lct[i].a = 255;
|
||||
}
|
||||
/*
|
||||
* The combined palette may exceed 256 colors, in which
|
||||
* case the indexes array will be discarded, indicating a
|
||||
* full-color image.
|
||||
*/
|
||||
if (lct_size + gct_size <= 256) {
|
||||
memcpy(image->palette, lct, sizeof(lct[0]) * lct_size);
|
||||
}
|
||||
lct_start = gct_size;
|
||||
gct_size += lct_start;
|
||||
}
|
||||
if (trans_color != 0xFFFF) {
|
||||
lct[trans_color].a = 0;
|
||||
if (!have_lct) {
|
||||
/* FIXME: this will affect all images using the global
|
||||
* color table, not just the current one */
|
||||
image->palette[trans_color].a = 0;
|
||||
}
|
||||
}
|
||||
/* 22. Table based image data */
|
||||
b = fgetc(gif.fp);
|
||||
if (b == EOF) goto error;
|
||||
if (b < MIN_LZW_BITS - 1 || MAX_LZW_BITS - 1 < b) goto error;
|
||||
init_decoder(&gif, b);
|
||||
x = 0;
|
||||
y = 0;
|
||||
if (!read_data_block(&gif, &block)) goto error;
|
||||
while (TRUE) {
|
||||
b = decode(&gif, &block);
|
||||
if (b == EOF) goto error;
|
||||
if (b == END_OF_DATA) break;
|
||||
if (y >= img_height) goto error;
|
||||
x2 = img_left + x;
|
||||
y2 = img_top + y;
|
||||
if (x2 < image->width && y2 < image->height) {
|
||||
image->pixels[y2 * image->width + x2] = lct[b];
|
||||
image->indexes[y2 * image->width + x2] = b + lct_start;
|
||||
}
|
||||
++x;
|
||||
if (x >= img_width) {
|
||||
x = 0;
|
||||
if (interlace) {
|
||||
y = interlace_incr(y, img_height);
|
||||
} else {
|
||||
++y;
|
||||
}
|
||||
}
|
||||
}
|
||||
free_data_block(&block);
|
||||
trans_color = 0xFFFF;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x21:
|
||||
/* Extension blocks */
|
||||
{
|
||||
int label;
|
||||
|
||||
label = fgetc(gif.fp);
|
||||
if (label == EOF) goto error;
|
||||
if (!read_data_block(&gif, &block)) goto error;
|
||||
switch (label) {
|
||||
case 0xF9:
|
||||
/* 23. Graphic control extension (0xF9) */
|
||||
if (block.size >= 4 && (block.data[0] & 0x01) != 0) {
|
||||
/* image has a transparent index */
|
||||
trans_color = block.data[3];
|
||||
}
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case 0xFE:
|
||||
/* 24. Comment extension (0xFE) */
|
||||
break;
|
||||
|
||||
case 0x01:
|
||||
/* 25. Plain text extension (0x01) */
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 0xFF:
|
||||
/* 26. Application extension (0xFF) */
|
||||
if (block.size > 11
|
||||
&& memcmp(block.data, "NETHACK3GIF", 11) == 0
|
||||
&& image->image_desc == NULL) {
|
||||
memmove(block.data, block.data + 11, block.size - 11);
|
||||
block.data[block.size - 11] = '\0';
|
||||
image->image_desc = (char *) block.data;
|
||||
block.data = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Unknown extension type */
|
||||
break;
|
||||
}
|
||||
free_data_block(&block);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(gif.fp);
|
||||
free_data_block(&block);
|
||||
if (gct_size > 256) {
|
||||
/* Max palette size exceeded; indexes array is not meaningful */
|
||||
free(image->indexes);
|
||||
image->indexes = NULL;
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
error:
|
||||
if (gif.fp) fclose(gif.fp);
|
||||
free_data_block(&block);
|
||||
free(image->pixels);
|
||||
image->pixels = NULL;
|
||||
free(image->indexes);
|
||||
image->indexes = NULL;
|
||||
free(image->image_desc);
|
||||
image->image_desc = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
init_decoder(gif, bit_width)
|
||||
struct Bitstream *gif;
|
||||
unsigned bit_width;
|
||||
{
|
||||
unsigned i;
|
||||
unsigned clear;
|
||||
|
||||
gif->bits = 0;
|
||||
gif->num_bits = 0;
|
||||
gif->initial_bit_width = bit_width;
|
||||
gif->block_size = 0;
|
||||
|
||||
clear = 1 << bit_width;
|
||||
gif->dict_size = clear + 2;
|
||||
for (i = 0; i < clear; ++i) {
|
||||
gif->dictionary[i].byte = i;
|
||||
gif->dictionary[i].next = 0xFFFF;
|
||||
}
|
||||
|
||||
gif->str_size = 0;
|
||||
|
||||
reset_decoder(gif);
|
||||
}
|
||||
|
||||
static void
|
||||
reset_decoder(gif)
|
||||
struct Bitstream *gif;
|
||||
{
|
||||
/* Set the bit width */
|
||||
gif->bit_width = gif->initial_bit_width + 1;
|
||||
|
||||
/* Reset the dictionary */
|
||||
gif->dict_size = (1 << gif->initial_bit_width) + 2;
|
||||
|
||||
/* No last code */
|
||||
gif->last_code = 0xFFFF;
|
||||
}
|
||||
|
||||
static int
|
||||
decode(gif, block)
|
||||
struct Bitstream *gif;
|
||||
struct DataBlock *block;
|
||||
{
|
||||
int code;
|
||||
unsigned clear = 1 << gif->initial_bit_width;
|
||||
|
||||
/* If a string is being decoded, return the next byte */
|
||||
if (gif->str_size != 0) {
|
||||
return gif->string[--gif->str_size];
|
||||
}
|
||||
|
||||
/* Get the next code, until code other than clear */
|
||||
while (TRUE) {
|
||||
code = get_code(gif, block);
|
||||
if (code != clear) break;
|
||||
reset_decoder(gif);
|
||||
}
|
||||
|
||||
if (code == EOF) return EOF;
|
||||
if (code == clear + 1) return END_OF_DATA;
|
||||
if (code > gif->dict_size) return EOF;
|
||||
|
||||
/* Add a new string to the dictionary */
|
||||
if (gif->last_code != 0xFFFF && gif->dict_size < SIZE(gif->dictionary)) {
|
||||
unsigned next_code;
|
||||
if (code < gif->dict_size) {
|
||||
next_code = code;
|
||||
} else {
|
||||
next_code = gif->last_code;
|
||||
}
|
||||
while (next_code >= clear) {
|
||||
next_code = gif->dictionary[next_code].next;
|
||||
}
|
||||
gif->dictionary[gif->dict_size].next = gif->last_code;
|
||||
gif->dictionary[gif->dict_size].byte = next_code;
|
||||
++gif->dict_size;
|
||||
if (gif->dict_size >= 1 << gif->bit_width
|
||||
&& gif->bit_width < MAX_LZW_BITS) {
|
||||
++gif->bit_width;
|
||||
}
|
||||
}
|
||||
gif->last_code = code;
|
||||
|
||||
/* code is less than gif->dict_size and not equal to clear or clear + 1 */
|
||||
/* Prepare the decoded string for return; note that it is stored in
|
||||
* reverse order */
|
||||
while (code >= clear) {
|
||||
gif->string[gif->str_size++] = gif->dictionary[code].byte;
|
||||
code = gif->dictionary[code].next;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static int
|
||||
get_code(gif, block)
|
||||
struct Bitstream *gif;
|
||||
struct DataBlock *block;
|
||||
{
|
||||
int code;
|
||||
|
||||
while (gif->num_bits < gif->bit_width) {
|
||||
unsigned char b;
|
||||
if (block->index >= block->size) return EOF;
|
||||
b = block->data[block->index++];
|
||||
gif->bits |= (unsigned long)b << gif->num_bits;
|
||||
gif->num_bits += 8;
|
||||
}
|
||||
|
||||
code = (int) (gif->bits & ((1UL << gif->bit_width) - 1));
|
||||
gif->bits >>= gif->bit_width;
|
||||
gif->num_bits -= gif->bit_width;
|
||||
return code;
|
||||
}
|
||||
|
||||
static unsigned
|
||||
interlace_incr(y, height)
|
||||
unsigned y;
|
||||
unsigned height;
|
||||
{
|
||||
static const unsigned char incr[] = { 8, 2, 4, 2 };
|
||||
|
||||
/* The lower three bits indicate the current pass */
|
||||
|
||||
/* Advance to the next row of the current pass */
|
||||
y += incr[y & 0x3];
|
||||
|
||||
/* Go to the next pass if y exceeds height */
|
||||
/* Might not be the immediately following pass if height is small */
|
||||
if (y >= height && (y & 0x7) == 0) {
|
||||
/* Pass 1 -> Pass 2 */
|
||||
y = 4;
|
||||
}
|
||||
if (y >= height && (y & 0x7) == 4) {
|
||||
/* Pass 2 -> Pass 3 */
|
||||
y = 2;
|
||||
}
|
||||
if (y >= height && (y & 0x3) == 2) {
|
||||
/* Pass 3 -> Pass 4 */
|
||||
y = 1;
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
/* Decode an unsigned 16 bit quantity */
|
||||
static unsigned short
|
||||
read_u16(buf)
|
||||
const unsigned char buf[2];
|
||||
{
|
||||
return ((unsigned short)buf[0] << 0)
|
||||
| ((unsigned short)buf[1] << 8);
|
||||
}
|
||||
|
||||
static boolean
|
||||
read_data_block(gif, block)
|
||||
struct Bitstream *gif;
|
||||
struct DataBlock *block;
|
||||
{
|
||||
long pos = ftell(gif->fp);
|
||||
int b;
|
||||
size_t i;
|
||||
|
||||
free_data_block(block);
|
||||
|
||||
/* Get the length of the data block */
|
||||
while (TRUE) {
|
||||
b = fgetc(gif->fp);
|
||||
if (b == EOF) return FALSE;
|
||||
if (b == 0) break;
|
||||
block->size += b;
|
||||
fseek(gif->fp, b, SEEK_CUR);
|
||||
}
|
||||
fseek(gif->fp, pos, SEEK_SET);
|
||||
|
||||
/* Allocate memory */
|
||||
block->data = (unsigned char *) alloc(block->size);
|
||||
|
||||
/* Read the data from the file */
|
||||
i = 0;
|
||||
while (TRUE) {
|
||||
b = fgetc(gif->fp);
|
||||
if (b == EOF) return FALSE;
|
||||
if (b == 0) break;
|
||||
if (fread(block->data + i, 1, b, gif->fp) != b) return FALSE;
|
||||
i += b;
|
||||
}
|
||||
|
||||
block->index = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
free_data_block(block)
|
||||
struct DataBlock *block;
|
||||
{
|
||||
free(block->data);
|
||||
block->size = 0;
|
||||
block->data = NULL;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user