Merge remote-tracking branch 'origin/NetHack-3.6.0'

This commit is contained in:
keni
2017-03-13 18:50:47 -04:00
27 changed files with 947 additions and 244 deletions
+1 -1
View File
@@ -207,7 +207,7 @@ They say that a xorn knows of no obstacles when pursuing you.
They say that abusing a credit card could shock you sooner or later.
They say that amulets, like most things, can be deadly or life saving.
They say that an altar can identify blessings.
They say that an ooze will bite your boots and a rockmole will eat them.
They say that an ooze will bite your boots and a rock mole might eat them.
They say that an unlucky hacker was once killed by an exploding tin.
They say that antique dealers are always interested in precious stones.
They say that bandaging one's wounds helps to keep up one's appearance.
+23
View File
@@ -929,6 +929,7 @@ dungeon level. All levels with annotations are displayed by the
``#overview'' command. Autocompletes. Default key is 'M-A', and '^N' if number_pad is on.
.lp #apply
Apply (use) a tool such as a pick-axe, a key, or a lamp. Default key is 'a'.
If the tool used acts on items on the floor, using the `m' prefix skips those items.
.lp #attributes
Show your attributes. Default key is '^X'.
.lp #autopickup
@@ -957,6 +958,7 @@ Drop an item. Default key is 'd'.
Drop specific item types. Default key is 'D'.
.lp "#eat "
Eat something. Default key is 'e'.
The `m' prefix skips eating items on the floor.
.lp #engrave
Engrave writing on the floor. Default key is 'E'.
.lp #enhance
@@ -1008,6 +1010,7 @@ Name a monster, an individual object, or a type of object. Same as #call.
Autocompletes. Default keys are 'N', 'M-n', and 'M-N'.
.lp #offer
Offer a sacrifice to the gods. Autocompletes. Default key is 'M-o'.
The `m' prefix skips offering items on the altar.
.lp ""
You'll need to find an altar to have any chance at success.
Corpses of recently killed monsters are the fodder of choice.
@@ -1029,6 +1032,7 @@ Test the panic routine. Autocompletes. Wizard-mode only.
Pay your shopping bill. Default key is 'p'.
.lp #pickup
Pick up things at the current location. Default key is ','.
The `m' prefix forces use of a menu.
.lp #polyself
Polymorph self. Autocompletes. Wizard-mode only.
.lp #pray
@@ -1118,6 +1122,7 @@ Look at the timeout queue. Autocompletes. Wizard-mode only.
.lp "#tip "
Tip over a container (bag or box) to pour out its contents.
Autocompletes. Default key is 'M-T'.
The `m' prefix makes the command use a menu.
.lp #travel
Travel to a specific location on the map. Default key is '_'.
Using the ``request menu'' prefix shows a menu of interesting targets in sight
@@ -3776,6 +3781,24 @@ to identify unique people for the score file.
.lp
MAX_STATUENAME_RANK\ =\ Maximum number of score file entries to use for
random statue names (default is 10).
.lp
DUMPLOGFILE\ =\ A filename where the end-of-game dumplog is saved.
Not defining this will prevent dumplog from being created. Only available
if your game is compiled with DUMPLOG. Allows the following placeholders:
.sd
.si
%% - literal '%'
%v - version (eg. "3.6.1-0")
%u - game UID
%t - game start time, UNIX timestamp format
%T - current time, UNIX timestamp format
%d - game start time, YYYYMMDDhhmmss format
%D - current time, YYYYMMDDhhmmss format
%n - player name
%N - first character of player name
.ei
.ed
.hn 1
Scoring
.pg
+24
View File
@@ -1113,6 +1113,8 @@ and '{\tt \^{}N}' if {\it number\verb+_+pad\/} is on.
\item[\tb{\#apply}]
Apply (use) a tool such as a pick-axe, a key, or a lamp.
Default key is '{\tt a}'.
If the tool used acts on items on the floor, using the `{\tt m}' prefix
skips those items.
%.lp
\item[\tb{\#attributes}]
Show your attributes. Default key is '{\tt \^{}X}'.\\
@@ -1154,6 +1156,7 @@ Drop specific item types. Default key is '{\tt D}'.
%.lp
\item[\tb{\#eat}]
Eat something. Default key is '{\tt e}'.
The `{\tt m}' prefix skips eating items on the floor.
%.lp
\item[\tb{\#engrave}]
Engrave writing on the floor. Default key is '{\tt E}'.
@@ -1230,6 +1233,7 @@ Autocompletes. Default keys are '{\tt N}', '{\tt M-n}', and '{\tt M-N}'.
%.lp
\item[\tb{\#offer}]
Offer a sacrifice to the gods. Autocompletes. Default key is '{\tt M-o}'.\\
The `{\tt m}' prefix skips offering items on the altar.
%.lp ""
You'll need to find an altar to have any chance at success.
Corpses of recently killed monsters are the fodder of choice.
@@ -1257,6 +1261,7 @@ Pay your shopping bill. Default key is '{\tt p}'.
%.lp
\item[\tb{\#pickup}]
Pick up things at the current location. Default key is '{\tt ,}'.
The `{\tt m}' prefix forces use of a menu.
%.lp
\item[\tb{\#polyself}]
Polymorph self. Autocompletes. Wizard-mode only.
@@ -1384,6 +1389,7 @@ Look at the timeout queue. Autocompletes. Wizard-mode only.
\item[\tb{\#tip}]
Tip over a container (bag or box) to pour out its contents.
Autocompletes. Default key is '{\tt M-T}'.
The `{\tt m}' prefix makes the command use a menu.
%.lp
\item[\tb{\#travel}]
Travel to a specific location on the map. Default key is '{\tt _}'.
@@ -4589,6 +4595,24 @@ Minimum number of points to get an entry in the score file.
\item[\ib{PERS\verb+_+IS\verb+_+UID}]
0 or 1 to use user names or numeric userids, respectively, to identify
unique people for the score file
%.lp
\item[\ib{DUMPLOGFILE}]
A filename where the end-of-game dumplog is saved.
Not defining this will prevent dumplog from being created. Only available
if your game is compiled with DUMPLOG. Allows the following placeholders:
%.sd
%.si
{\tt \%\%} --- literal `{\tt \%}'\\
{\tt \%v} --- version (eg. "3.6.1-0")\\
{\tt \%u} --- game UID\\
{\tt \%t} --- game start time, UNIX timestamp format\\
{\tt \%T} --- current time, UNIX timestamp format\\
{\tt \%d} --- game start time, YYYYMMDDhhmmss format\\
{\tt \%D} --- current time, YYYYMMDDhhmmss format\\
{\tt \%n} --- player name\\
{\tt \%N} --- first character of player name
%.ei
%.ed
\elist
%.hn 1
+15 -5
View File
@@ -41,7 +41,7 @@ make a previously-discovered scroll written with marker while blind have its
don't show the old level when you die going down the stairs because of an
iron ball
new high score with ", while helpless" attribute appended would erroneously
result in ", while helpless" being appended to all scores
result in ", while helpless" being appended to all following entries
allow bright aliases for colors in menucolors
avoid hearing yelps when you are deaf
make corpse visible if stethoscope told you about it being there
@@ -83,7 +83,7 @@ when a pet moves reluctantly, name the top item of the pile it is reluctant
ensure sufficient messages are given to clarify the transition from detected
vampire bats to fog clouds in Vlad's tower
fix "killing by kicking something weird" when kicking an object causes death
guard macros available for mextra fields similar to those for oextra fields
avoid accessing mextra fields which haven't been allocated
compile-time option for an alternate paniclog format for public server use
make monsters forget where they stepped when fleeing or teleporting
requiver pickup_thrown objects if quiver is empty
@@ -125,10 +125,9 @@ make status hilites use same color names as menucolors
limit monster spell aggravate monsters to either outside or inside of the
Wizard's tower
prevent revived unique from inheriting a user-defined name
make hurtling out of water bubble on the Plane of Water handle entering water
make hurtling out of air bubble on the Plane of Water handle entering water
fix floor descriptions on the Planes when levitating
fix warning glyph description when monster symbol coincided the warning symbol
allow the same color names for status hilites and menucolors
override MSGTYPE=norep while executing the ':' command
if a chameleon took vampire form, it would stop periodically changing shape
corpses obtained from tipping an ice box wouldn't rot away
@@ -302,7 +301,7 @@ conduct: wishing for an artifact and not getting it because it already exists
because of quest restrictions or too many artifacts in play does
avoid ring of poison resistance as starting equipment for orcish wizard
gelatinous cube shouldn't be able to eat a scroll of scare monster
make fireballs or cones of cold cast a skilled or higher not go through walls
make fireballs or cones of cold cast at skilled or higher not go through walls
prevent flying monsters from hovering over unreachable underwater objects
lembas wafer gives increased nutrition to elves, reduced nutrition to orcs;
cram ration gives increase nutrition to dwarves
@@ -366,6 +365,9 @@ when sitting at a trap spot: You sit down. You step on a level teleporter.
(likewise for polymorph trap, and similar issue for web)
show all statusline information in #attributes
add option status_updates to prevent bottom of screen status line updates
fix achievement recording bug with mines and sokoban prizes
g.cubes would eat globs of green slime without harm; engulf those instead
fix up true rumor about rock moles vs boots
Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository
@@ -389,6 +391,13 @@ when picking a destination for #jump, '$' to show valid dest. is more accurate
enchant armor gave "your pair of boots/gloves glow", should have been "glows"
when autopickup is overridden in a shop, always-pick-up exceptions and
pickup_thrown still picked unpaid items up
the fix for giving an alternate grow up message when a monster becomes a new
form with the opposite sex (female gnome into male gnome lord, for
example) had the logic wrong
DUMPLOG: genocided and extinct species was always a blank line;
vanquished creatures was just a blank line if nothing had been killed
DUMPLOG: RIP tombstone was printed for characters who survived (ascended,
escaped dungeon, quit, trickery or panic)
Platform- and/or Interface-Specific Fixes
@@ -557,6 +566,7 @@ Ray Chason's MS-DOS port restored to functionality with credit to Reddit user
Ray Chason's MSDOS port support for some VESA modes
Darshan Shaligram's pet ranged attack
Jason Dorje Short's key rebinding
Maxime Bacoux's new dumplog
Code Cleanup and Reorganization
+26
View File
@@ -521,6 +521,32 @@ typedef unsigned char uchar;
# define CONWAY /* Conway's Life level */
#endif
/* #define DUMPLOG */ /* End-of-game dump logs */
#ifdef DUMPLOG
#ifndef DUMPLOG_MSG_COUNT
#define DUMPLOG_MSG_COUNT 50
#endif
#ifndef DUMPLOG_FILE
#define DUMPLOG_FILE "/tmp/nethack.%n.%d.log"
/* DUMPLOG_FILE allows following placeholders:
%% literal '%'
%v version (eg. "3.6.1-0")
%u game UID
%t game start time, UNIX timestamp format
%T current time, UNIX timestamp format
%d game start time, YYYYMMDDhhmmss format
%D current time, YYYYMMDDhhmmss format
%n player name
%N first character of player name
DUMPLOG_FILE is not used if SYSCF is defined
*/
#endif
#endif
/* End of Section 4 */
#ifdef TTY_TILES_ESCCODES
+13 -1
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 extern.h $NHDT-Date: 1471112244 2016/08/13 18:17:24 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.570 $ */
/* NetHack 3.6 extern.h $NHDT-Date: 1489192904 2017/03/11 00:41:44 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.583 $ */
/* Copyright (c) Steve Creps, 1988. */
/* NetHack may be freely redistributed. See license for details. */
@@ -141,6 +141,8 @@ E int NDECL(getbones);
/* ### botl.c ### */
E char *NDECL(do_statusline1);
E char *NDECL(do_statusline2);
E int FDECL(xlev_to_rank, (int));
E int FDECL(title_to_mon, (const char *, int *, int *));
E void NDECL(max_rank_sz);
@@ -268,6 +270,7 @@ E void NDECL(warnreveal);
E int FDECL(dosearch0, (int));
E int NDECL(dosearch);
E void NDECL(sokoban_detect);
E void NDECL(dump_map);
E void FDECL(reveal_terrain, (int, int));
/* ### dig.c ### */
@@ -1801,6 +1804,10 @@ E boolean FDECL(is_autopickup_exception, (struct obj *, BOOLEAN_P));
/* ### pline.c ### */
#ifdef DUMPLOG
E void FDECL(dumplogmsg, (const char *));
E void NDECL(dumplogfreemessages);
#endif
E void VDECL(pline, (const char *, ...)) PRINTF_F(1, 2);
E void VDECL(Norep, (const char *, ...)) PRINTF_F(1, 2);
E void NDECL(free_youbuf);
@@ -2714,6 +2721,11 @@ E void FDECL(genl_status_threshold, (int, int, anything, int, int, int));
#endif
#endif
E void FDECL(dump_open_log, (time_t));
E void NDECL(dump_close_log);
E void FDECL(dump_redirect, (BOOLEAN_P));
E void FDECL(dump_forward_putstr, (winid, int, const char*, int));
/* ### wizard.c ### */
E void NDECL(amulet);
+1
View File
@@ -201,6 +201,7 @@ struct instance_flags {
boolean vision_inited; /* true if vision is ready */
boolean sanity_check; /* run sanity checks */
boolean mon_polycontrol; /* debug: control monster polymorphs */
boolean in_dumplog; /* doing the dumplog right now? */
/* stuff that is related to options and/or user or platform preferences
*/
+8
View File
@@ -342,6 +342,14 @@ struct obj {
&& !undiscovered_artifact(ART_EYES_OF_THE_OVERWORLD)))
#define pair_of(o) ((o)->otyp == LENSES || is_gloves(o) || is_boots(o))
#define is_mines_prize(o) \
((o)->otyp == LUCKSTONE && Is_mineend_level(&u.uz))
#define is_soko_prize(o) \
(((o)->otyp == AMULET_OF_REFLECTION \
|| (o)->otyp == BAG_OF_HOLDING) \
&& Is_sokoend_level(&u.uz))
/* Flags for get_obj_location(). */
#define CONTAINED_TOO 0x1
#define BURIED_TOO 0x2
+3
View File
@@ -15,6 +15,9 @@ struct sysopt {
char *shellers; /* like wizards, for ! command (-DSHELL); also ^Z */
char *genericusers; /* usernames that prompt for user name */
char *debugfiles; /* files to show debugplines in. '*' is all. */
#ifdef DUMPLOG
char *dumplogfile; /* where the dump file is saved */
#endif
int env_dbgfl; /* 1: debugfiles comes from getenv("DEBUGFILES")
* so sysconf's DEBUGFILES shouldn't override it;
* 0: getenv() hasn't been attempted yet;
+18 -19
View File
@@ -13,15 +13,12 @@ const char *const enc_stat[] = { "", "Burdened", "Stressed",
STATIC_OVL NEARDATA int mrank_sz = 0; /* loaded by max_rank_sz (from u_init) */
STATIC_DCL const char *NDECL(rank);
#ifndef STATUS_VIA_WINDOWPORT
#if !defined(STATUS_VIA_WINDOWPORT) || defined(DUMPLOG)
STATIC_DCL void NDECL(bot1);
STATIC_DCL void NDECL(bot2);
STATIC_OVL void
bot1()
char *
do_statusline1()
{
char newbot1[MAXCO];
static char newbot1[BUFSZ];
register char *nb;
register int i, j;
@@ -71,14 +68,13 @@ bot1()
if (flags.showscore)
Sprintf(nb = eos(nb), " S:%ld", botl_score());
#endif
curs(WIN_STATUS, 1, 0);
putstr(WIN_STATUS, 0, newbot1);
return newbot1;
}
STATIC_OVL void
bot2()
char *
do_statusline2()
{
char newbot2[MAXCO], /* MAXCO: botl.h */
static char newbot2[BUFSZ], /* MAXCO: botl.h */
/* dungeon location (and gold), hero health (HP, PW, AC),
experience (HD if poly'd, else Exp level and maybe Exp points),
time (in moves), varying number of status conditions */
@@ -102,7 +98,8 @@ bot2()
if ((money = money_cnt(invent)) < 0L)
money = 0L; /* ought to issue impossible() and then discard gold */
Sprintf(eos(dloc), "%s:%-2ld", /* strongest hero can lift ~300000 gold */
encglyph(objnum_to_glyph(GOLD_PIECE)), min(money, 999999L));
iflags.in_dumplog ? "$" : encglyph(objnum_to_glyph(GOLD_PIECE)),
min(money, 999999L));
dln = strlen(dloc);
/* '$' encoded as \GXXXXNNNN is 9 chars longer than display will need */
dx = strstri(dloc, "\\G") ? 9 : 0;
@@ -205,23 +202,25 @@ bot2()
/* only two or three consecutive spaces available to squeeze out */
mungspaces(newbot2);
}
curs(WIN_STATUS, 1, 1);
putmixed(WIN_STATUS, 0, newbot2);
return newbot2;
}
#ifndef STATUS_VIA_WINDOWPORT
void
bot()
{
if (youmonst.data && iflags.status_updates) {
bot1();
bot2();
curs(WIN_STATUS, 1, 0);
putstr(WIN_STATUS, 0, do_statusline1());
curs(WIN_STATUS, 1, 1);
putmixed(WIN_STATUS, 0, do_statusline2());
}
context.botl = context.botlx = 0;
}
#endif /* !STATUS_VIA_WINDOWPORT */
#endif /* !STATUS_VIA_WINDOWPORT || DUMPLOG */
/* convert experience level (1..30) to rank index (0..8) */
int
xlev_to_rank(xlev)
+140 -75
View File
@@ -2756,133 +2756,198 @@ int final;
#define ISCTRL(c) ((uchar)(c) < 0x20)
#define UNCTRL(c) (ISCTRL(c) ? (0x60 | (c)) : (c))
/* ordered by command name */
struct ext_func_tab extcmdlist[] = {
{ '#', "#", "perform an extended command", doextcmd, IFBURIED|GENERALCMD },
{ M('?'), "?", "get this list of extended commands", doextlist, IFBURIED|AUTOCOMPLETE|GENERALCMD },
{ M('a'), "adjust", "adjust inventory letters", doorganize, IFBURIED|AUTOCOMPLETE },
{ M('A'), "annotate", "name current level", donamelevel, IFBURIED|AUTOCOMPLETE },
{ 'a', "apply", "apply (use) a tool (pick-axe, key, lamp...)", doapply },
{ C('x'), "attributes", "show your attributes", doattributes, IFBURIED },
{ '@', "autopickup", "toggle the pickup option on/off", dotogglepickup, IFBURIED },
{ '#', "#", "perform an extended command",
doextcmd, IFBURIED | GENERALCMD },
{ M('?'), "?", "get this list of extended commands",
doextlist, IFBURIED | AUTOCOMPLETE | GENERALCMD },
{ M('a'), "adjust", "adjust inventory letters",
doorganize, IFBURIED | AUTOCOMPLETE },
{ M('A'), "annotate", "name current level",
donamelevel, IFBURIED | AUTOCOMPLETE },
{ 'a', "apply", "apply (use) a tool (pick-axe, key, lamp...)",
doapply },
{ C('x'), "attributes", "show your attributes",
doattributes, IFBURIED },
{ '@', "autopickup", "toggle the pickup option on/off",
dotogglepickup, IFBURIED },
{ 'C', "call", "call (name) something", docallcmd, IFBURIED },
{ 'Z', "cast", "zap (cast) a spell", docast, IFBURIED },
{ M('c'), "chat", "talk to someone", dotalk, IFBURIED|AUTOCOMPLETE },
{ M('c'), "chat", "talk to someone", dotalk, IFBURIED | AUTOCOMPLETE },
{ 'c', "close", "close a door", doclose },
{ M('C'), "conduct", "list voluntary challenges you have maintained", doconduct, IFBURIED|AUTOCOMPLETE },
{ M('C'), "conduct", "list voluntary challenges you have maintained",
doconduct, IFBURIED | AUTOCOMPLETE },
{ M('d'), "dip", "dip an object into something", dodip, AUTOCOMPLETE },
{ '>', "down", "go down a staircase", dodown },
{ 'd', "drop", "drop an item", dodrop },
{ 'D', "droptype", "drop specific item types", doddrop },
{ 'e', "eat", "eat something", doeat },
{ 'E', "engrave", "engrave writing on the floor", doengrave },
{ M('e'), "enhance", "advance or check weapon and spell skills", enhance_weapon_skill, IFBURIED|AUTOCOMPLETE },
{ '\0', "exploremode", "enter explore (discovery) mode", enter_explore_mode, IFBURIED },
{ M('e'), "enhance", "advance or check weapon and spell skills",
enhance_weapon_skill, IFBURIED | AUTOCOMPLETE },
{ '\0', "exploremode", "enter explore (discovery) mode",
enter_explore_mode, IFBURIED },
{ 'f', "fire", "fire ammunition from quiver", dofire },
{ M('f'), "force", "force a lock", doforce, AUTOCOMPLETE },
{ ';', "glance", "show what type of thing a map symbol corresponds to", doquickwhatis, IFBURIED|GENERALCMD },
{ '?', "help", "give a help message", dohelp, IFBURIED|GENERALCMD },
{ 'V', "history", "show long version and game history", dohistory, IFBURIED|GENERALCMD },
{ ';', "glance", "show what type of thing a map symbol corresponds to",
doquickwhatis, IFBURIED | GENERALCMD },
{ '?', "help", "give a help message", dohelp, IFBURIED | GENERALCMD },
{ 'V', "history", "show long version and game history",
dohistory, IFBURIED | GENERALCMD },
{ 'i', "inventory", "show your inventory", ddoinv, IFBURIED },
{ 'I', "inventtype", "inventory specific item types", dotypeinv, IFBURIED },
{ M('i'), "invoke", "invoke an object's special powers", doinvoke, IFBURIED|AUTOCOMPLETE },
{ 'I', "inventtype", "inventory specific item types",
dotypeinv, IFBURIED },
{ M('i'), "invoke", "invoke an object's special powers",
doinvoke, IFBURIED | AUTOCOMPLETE },
{ M('j'), "jump", "jump to another location", dojump, AUTOCOMPLETE },
{ C('d'), "kick", "kick something", dokick },
{ '\\', "known", "show what object types have been discovered", dodiscovered, IFBURIED|GENERALCMD },
{ '`', "knownclass", "show discovered types for one class of objects", doclassdisco, IFBURIED|GENERALCMD },
{ '\0', "levelchange", "change experience level", wiz_level_change, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ '\0', "lightsources", "show mobile light sources", wiz_light_sources, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ '\\', "known", "show what object types have been discovered",
dodiscovered, IFBURIED | GENERALCMD },
{ '`', "knownclass", "show discovered types for one class of objects",
doclassdisco, IFBURIED|GENERALCMD },
{ '\0', "levelchange", "change experience level",
wiz_level_change, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ '\0', "lightsources", "show mobile light sources",
wiz_light_sources, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ ':', "look", "look at what is here", dolook, IFBURIED },
{ M('l'), "loot", "loot a box on the floor", doloot, AUTOCOMPLETE },
#ifdef DEBUG_MIGRATING_MONS
{ '\0', "migratemons", "migrate n random monsters", wiz_migrate_mons, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ '\0', "migratemons", "migrate N random monsters",
wiz_migrate_mons, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
#endif
{ '\0', "monpolycontrol", "control monster polymorphs", wiz_mon_polycontrol, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ M('m'), "monster", "use a monster's special ability", domonability, IFBURIED|AUTOCOMPLETE },
{ 'N', "name", "name a monster or an object", docallcmd, IFBURIED|AUTOCOMPLETE },
{ M('o'), "offer", "offer a sacrifice to the gods", dosacrifice, AUTOCOMPLETE },
{ '\0', "monpolycontrol", "control monster polymorphs",
wiz_mon_polycontrol, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ M('m'), "monster", "use monster's special ability",
domonability, IFBURIED | AUTOCOMPLETE },
{ 'N', "name", "name a monster or an object",
docallcmd, IFBURIED | AUTOCOMPLETE },
{ M('o'), "offer", "offer a sacrifice to the gods",
dosacrifice, AUTOCOMPLETE },
{ 'o', "open", "open a door", doopen },
{ 'O', "options", "show option settings, possibly change them", doset, IFBURIED|GENERALCMD },
{ C('o'), "overview", "show a summary of the explored dungeon", dooverview, IFBURIED|AUTOCOMPLETE },
{ '\0', "panic", "test panic routine (fatal to game)", wiz_panic, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ 'O', "options", "show option settings, possibly change them",
doset, IFBURIED|GENERALCMD },
{ C('o'), "overview", "show a summary of the explored dungeon",
dooverview, IFBURIED|AUTOCOMPLETE },
{ '\0', "panic", "test panic routine (fatal to game)",
wiz_panic, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ 'p', "pay", "pay your shopping bill", dopay },
{ ',', "pickup", "pick up things at the current location", dopickup },
{ '\0', "polyself", "polymorph self", wiz_polyself, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ '\0', "polyself", "polymorph self",
wiz_polyself, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
#ifdef PORT_DEBUG
{ '\0', "portdebug", "wizard port debug command", wiz_port_debug, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ '\0', "portdebug", "wizard port debug command",
wiz_port_debug, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
#endif
{ M('p'), "pray", "pray to the gods for help", dopray, IFBURIED|AUTOCOMPLETE },
{ C('p'), "prevmsg", "toggle through previously displayed game messages", doprev_message, IFBURIED|GENERALCMD },
{ M('p'), "pray", "pray to the gods for help",
dopray, IFBURIED | AUTOCOMPLETE },
{ C('p'), "prevmsg", "view recent game messages",
doprev_message, IFBURIED|GENERALCMD },
{ 'P', "puton", "put on an accessory (ring, amulet, etc)", doputon },
{ 'q', "quaff", "quaff (drink) something", dodrink },
{ M('q'), "quit", "exit without saving current game", done2, IFBURIED|AUTOCOMPLETE|GENERALCMD },
{ M('q'), "quit", "exit without saving current game",
done2, IFBURIED | AUTOCOMPLETE | GENERALCMD },
{ 'Q', "quiver", "select ammunition for quiver", dowieldquiver },
{ 'r', "read", "read a scroll or spellbook", doread },
{ C('r'), "redraw", "redraw screen", doredraw, IFBURIED|GENERALCMD },
{ C('r'), "redraw", "redraw screen", doredraw, IFBURIED | GENERALCMD },
{ 'R', "remove", "remove an accessory (ring, amulet, etc)", doremring },
{ M('R'), "ride", "mount or dismount a saddled steed", doride, AUTOCOMPLETE },
{ M('R'), "ride", "mount or dismount a saddled steed",
doride, AUTOCOMPLETE },
{ M('r'), "rub", "rub a lamp or a stone", dorub, AUTOCOMPLETE },
{ 'S', "save", "save the game", dosave, IFBURIED|GENERALCMD },
{ 's', "search", "search for traps and secret doors", dosearch, IFBURIED, "searching" },
{ 'S', "save", "save the game and exit", dosave, IFBURIED | GENERALCMD },
{ 's', "search", "search for traps and secret doors",
dosearch, IFBURIED, "searching" },
{ '*', "seeall", "show all equipment in use", doprinuse, IFBURIED },
{ AMULET_SYM, "seeamulet", "show the amulet currently worn", dopramulet, IFBURIED },
{ ARMOR_SYM, "seearmor", "show the armor currently worn", doprarm, IFBURIED },
{ AMULET_SYM, "seeamulet", "show the amulet currently worn",
dopramulet, IFBURIED },
{ ARMOR_SYM, "seearmor", "show the armor currently worn",
doprarm, IFBURIED },
{ GOLD_SYM, "seegold", "count your gold", doprgold, IFBURIED },
{ '\0', "seenv", "show seen vectors", wiz_show_seenv, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ RING_SYM, "seerings", "show the ring(s) currently worn", doprring, IFBURIED },
{ SPBOOK_SYM, "seespells", "list and reorder known spells", dovspell, IFBURIED },
{ TOOL_SYM, "seetools", "show the tools currently in use", doprtool, IFBURIED },
{ '^', "seetrap", "show the type of a trap", doidtrap, IFBURIED },
{ WEAPON_SYM, "seeweapon", "show the weapon currently wielded", doprwep, IFBURIED },
{ '\0', "seenv", "show seen vectors",
wiz_show_seenv, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ RING_SYM, "seerings", "show the ring(s) currently worn",
doprring, IFBURIED },
{ SPBOOK_SYM, "seespells", "list and reorder known spells",
dovspell, IFBURIED },
{ TOOL_SYM, "seetools", "show the tools currently in use",
doprtool, IFBURIED },
{ '^', "seetrap", "show the type of adjacent trap", doidtrap, IFBURIED },
{ WEAPON_SYM, "seeweapon", "show the weapon currently wielded",
doprwep, IFBURIED },
#ifdef SHELL
{ '!', "shell", "do a shell escape", dosh, IFBURIED|GENERALCMD },
{ '!', "shell", "do a shell escape", dosh, IFBURIED | GENERALCMD },
#endif /* SHELL */
{ M('s'), "sit", "sit down", dosit, AUTOCOMPLETE },
{ '\0', "stats", "show memory statistics", wiz_show_stats, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ '\0', "stats", "show memory statistics",
wiz_show_stats, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
#ifdef SUSPEND
{ C('z'), "suspend", "suspend the game", dosuspend_core, IFBURIED|GENERALCMD },
{ C('z'), "suspend", "suspend the game",
dosuspend_core, IFBURIED | GENERALCMD },
#endif /* SUSPEND */
{ 'x', "swap", "swap wielded and secondary weapons", doswapweapon },
{ 'T', "takeoff", "take off one piece of armor", dotakeoff },
{ 'A', "takeoffall", "remove all armor", doddoremarm },
{ C('t'), "teleport", "teleport around the level", dotele, IFBURIED },
{ '\0', "terrain", "show map without obstructions", doterrain, IFBURIED|AUTOCOMPLETE },
{ '\0', "terrain", "show map without obstructions",
doterrain, IFBURIED | AUTOCOMPLETE },
{ 't', "throw", "throw something", dothrow },
{ '\0', "timeout", "look at timeout queue", wiz_timeout_queue, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ '\0', "timeout", "look at timeout queue",
wiz_timeout_queue, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ M('T'), "tip", "empty a container", dotip, AUTOCOMPLETE },
{ '_', "travel", "travel to a specific location on the map", dotravel },
{ M('t'), "turn", "turn undead away", doturn, IFBURIED|AUTOCOMPLETE },
{ 'X', "twoweapon", "toggle two-weapon combat", dotwoweapon, AUTOCOMPLETE },
{ M('t'), "turn", "turn undead away", doturn, IFBURIED | AUTOCOMPLETE },
{ 'X', "twoweapon", "toggle two-weapon combat",
dotwoweapon, AUTOCOMPLETE },
{ M('u'), "untrap", "untrap something", dountrap, AUTOCOMPLETE },
{ '<', "up", "go up a staircase", doup },
{ '\0', "vanquished", "list vanquished monsters", dovanquished, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ M('v'), "version", "list compile time options for this version of NetHack", doextversion, IFBURIED|AUTOCOMPLETE|GENERALCMD },
{ 'v', "versionshort", "show version", doversion, IFBURIED|GENERALCMD },
{ '\0', "vision", "show vision array", wiz_show_vision, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ '.', "wait", "rest one move while doing nothing", donull, IFBURIED, "waiting" },
{ '\0', "vanquished", "list vanquished monsters",
dovanquished, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ M('v'), "version",
"list compile time options for this version of NetHack",
doextversion, IFBURIED | AUTOCOMPLETE | GENERALCMD },
{ 'v', "versionshort", "show version", doversion, IFBURIED | GENERALCMD },
{ '\0', "vision", "show vision array",
wiz_show_vision, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ '.', "wait", "rest one move while doing nothing",
donull, IFBURIED, "waiting" },
{ 'W', "wear", "wear a piece of armor", dowear },
{ '&', "whatdoes", "tell what a command does", dowhatdoes, IFBURIED },
{ '/', "whatis", "show what type of thing a symbol corresponds to", dowhatis, IFBURIED|GENERALCMD },
{ '/', "whatis", "show what type of thing a symbol corresponds to",
dowhatis, IFBURIED | GENERALCMD },
{ 'w', "wield", "wield (put in use) a weapon", dowield },
{ M('w'), "wipe", "wipe off your face", dowipe, AUTOCOMPLETE },
#ifdef DEBUG
{ '\0', "wizdebug_bury", "wizard debug: bury objs under and around you", wiz_debug_cmd_bury, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ '\0', "wizdebug_traveldisplay", "wizard debug: toggle travel display", wiz_debug_cmd_traveldisplay, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ '\0', "wizdebug_bury", "wizard debug: bury objs under and around you",
wiz_debug_cmd_bury, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ '\0', "wizdebug_traveldisplay", "wizard debug: toggle travel display",
wiz_debug_cmd_traveldisplay, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
#endif
{ C('e'), "wizdetect", "search a room", wiz_detect, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ C('g'), "wizgenesis", "create a monster", wiz_genesis, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ C('i'), "wizidentify", "identify all items in inventory", wiz_identify, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ '\0', "wizintrinsic", "set intrinsic", wiz_intrinsic, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ C('v'), "wizlevelport", "teleport to another level", wiz_level_tele, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ '\0', "wizmakemap", "recreate the current level", wiz_makemap, IFBURIED|WIZMODECMD },
{ C('f'), "wizmap", "map the level", wiz_map, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ '\0', "wizrumorcheck", "verify rumor boundaries", wiz_rumor_check, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ '\0', "wizsmell", "smell monster", wiz_smell, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ '\0', "wizwhere", "show locations of special levels", wiz_where, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ C('w'), "wizwish", "wish for something", wiz_wish, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ '\0', "wmode", "show wall modes", wiz_show_wmodes, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
{ C('e'), "wizdetect", "reveal hidden things within a small radius",
wiz_detect, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ C('g'), "wizgenesis", "create a monster",
wiz_genesis, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ C('i'), "wizidentify", "identify all items in inventory",
wiz_identify, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ '\0', "wizintrinsic", "set an intrinsic",
wiz_intrinsic, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ C('v'), "wizlevelport", "teleport to another level",
wiz_level_tele, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ '\0', "wizmakemap", "recreate the current level",
wiz_makemap, IFBURIED | WIZMODECMD },
{ C('f'), "wizmap", "map the level",
wiz_map, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ '\0', "wizrumorcheck", "verify rumor boundaries",
wiz_rumor_check, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ '\0', "wizsmell", "smell monster",
wiz_smell, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ '\0', "wizwhere", "show locations of special levels",
wiz_where, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ C('w'), "wizwish", "wish for something",
wiz_wish, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ '\0', "wmode", "show wall modes",
wiz_show_wmodes, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ 'z', "zap", "zap a wand", dozap },
{ '\0', (char *)0, (char *)0, donull } /* sentinel */
{ '\0', (char *) 0, (char *) 0, donull, 0, (char *) 0 } /* sentinel */
};
const char *
@@ -3676,7 +3741,7 @@ char *txt; /* sufficiently long buffer */
else if (c == '\n')
Sprintf(txt, "<enter>");
else if (ISCTRL(c))
Sprintf(txt, "^%c", UNCTRL(c));
Sprintf(txt, "^%c", highc(UNCTRL(c)));
else if (ISMETA(c))
Sprintf(txt, "M-%c", UNMETA(c));
else if (c >= 33 && c <= 126)
+109 -70
View File
@@ -25,6 +25,8 @@ STATIC_DCL void FDECL(show_map_spot, (int, int));
STATIC_PTR void FDECL(findone, (int, int, genericptr_t));
STATIC_PTR void FDECL(openone, (int, int, genericptr_t));
STATIC_DCL int FDECL(mfind0, (struct monst *, BOOLEAN_P));
STATIC_DCL int FDECL(reveal_terrain_getglyph, (int, int, int,
unsigned, int, int));
/* bring hero out from underwater or underground or being engulfed;
return True iff any change occurred */
@@ -1715,6 +1717,109 @@ sokoban_detect()
}
}
STATIC_DCL int
reveal_terrain_getglyph(x, y, full, swallowed, default_glyph, which_subset)
int x, y, full;
unsigned swallowed;
int default_glyph, which_subset;
{
int glyph, levl_glyph;
uchar seenv;
boolean keep_traps = (which_subset & TER_TRP) !=0,
keep_objs = (which_subset & TER_OBJ) != 0,
keep_mons = (which_subset & TER_MON) != 0;
struct monst *mtmp;
struct trap *t;
/* for 'full', show the actual terrain for the entire level,
otherwise what the hero remembers for seen locations with
monsters, objects, and/or traps removed as caller dictates */
seenv = (full || level.flags.hero_memory)
? levl[x][y].seenv : cansee(x, y) ? SVALL : 0;
if (full) {
levl[x][y].seenv = SVALL;
glyph = back_to_glyph(x, y);
levl[x][y].seenv = seenv;
} else {
levl_glyph = level.flags.hero_memory
? levl[x][y].glyph
: seenv ? back_to_glyph(x, y): default_glyph;
/* glyph_at() returns the displayed glyph, which might
be a monster. levl[][].glyph contains the remembered
glyph, which will never be a monster (unless it is
the invisible monster glyph, which is handled like
an object, replacing any object or trap at its spot) */
glyph = !swallowed ? glyph_at(x, y) : levl_glyph;
if (keep_mons && x == u.ux && y == u.uy && swallowed)
glyph = mon_to_glyph(u.ustuck);
else if (((glyph_is_monster(glyph)
|| glyph_is_warning(glyph)) && !keep_mons)
|| glyph_is_swallow(glyph))
glyph = levl_glyph;
if (((glyph_is_object(glyph) && !keep_objs)
|| glyph_is_invisible(glyph))
&& keep_traps && !covers_traps(x, y)) {
if ((t = t_at(x, y)) != 0 && t->tseen)
glyph = trap_to_glyph(t);
}
if ((glyph_is_object(glyph) && !keep_objs)
|| (glyph_is_trap(glyph) && !keep_traps)
|| glyph_is_invisible(glyph)) {
if (!seenv) {
glyph = default_glyph;
} else if (lastseentyp[x][y] == levl[x][y].typ) {
glyph = back_to_glyph(x, y);
} else {
/* look for a mimic here posing as furniture;
if we don't find one, we'll have to fake it */
if ((mtmp = m_at(x, y)) != 0
&& mtmp->m_ap_type == M_AP_FURNITURE) {
glyph = cmap_to_glyph(mtmp->mappearance);
} else {
/* we have a topology type but we want a screen
symbol in order to derive a glyph; some screen
symbols need the flags field of levl[][] in
addition to the type (to disambiguate STAIRS to
S_upstair or S_dnstair, for example; current
flags might not be intended for remembered type,
but we've got no other choice) */
schar save_typ = levl[x][y].typ;
levl[x][y].typ = lastseentyp[x][y];
glyph = back_to_glyph(x, y);
levl[x][y].typ = save_typ;
}
}
}
}
if (glyph == cmap_to_glyph(S_darkroom))
glyph = cmap_to_glyph(S_room); /* FIXME: dirty hack */
return glyph;
}
void
dump_map()
{
int x, y, glyph;
int subset = TER_MAP | TER_TRP | TER_OBJ | TER_MON;
int default_glyph = cmap_to_glyph(level.flags.arboreal ? S_tree : S_stone);
char buf[BUFSZ];
for (y = 0; y < ROWNO; y++) {
for (x = 1; x < COLNO; x++) {
int ch, color;
unsigned special;
glyph = reveal_terrain_getglyph(x,y, FALSE, u.uswallow,
default_glyph, subset);
(void) mapglyph(glyph, &ch, &color, &special, x, y);
buf[x-1] = ch;
}
buf[x-2] = '\0';
putstr(0,0, buf);
}
}
/* idea from crawl; show known portion of map without any monsters,
objects, or traps occluding the view of the underlying terrain */
void
@@ -1725,10 +1830,7 @@ int which_subset; /* when not full, whether to suppress objs and/or traps */
if ((Hallucination || Stunned || Confusion) && !full) {
You("are too disoriented for this.");
} else {
int x, y, glyph, levl_glyph, default_glyph;
uchar seenv;
struct monst *mtmp;
struct trap *t;
int x, y, glyph, default_glyph;
char buf[BUFSZ];
/* there is a TER_MAP bit too; we always show map regardless of it */
boolean keep_traps = (which_subset & TER_TRP) !=0,
@@ -1739,74 +1841,11 @@ int which_subset; /* when not full, whether to suppress objs and/or traps */
if (unconstrain_map())
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
monsters, objects, and/or traps removed as caller dictates */
for (x = 1; x < COLNO; x++)
for (y = 0; y < ROWNO; y++) {
seenv = (full || level.flags.hero_memory)
? levl[x][y].seenv : cansee(x, y) ? SVALL : 0;
if (full) {
levl[x][y].seenv = SVALL;
glyph = back_to_glyph(x, y);
levl[x][y].seenv = seenv;
} else {
levl_glyph = level.flags.hero_memory
? levl[x][y].glyph
: seenv
? back_to_glyph(x, y)
: default_glyph;
/* glyph_at() returns the displayed glyph, which might
be a monster. levl[][].glyph contains the remembered
glyph, which will never be a monster (unless it is
the invisible monster glyph, which is handled like
an object, replacing any object or trap at its spot) */
glyph = !swallowed ? glyph_at(x, y) : levl_glyph;
if (keep_mons && x == u.ux && y == u.uy && swallowed)
glyph = mon_to_glyph(u.ustuck);
else if (((glyph_is_monster(glyph)
|| glyph_is_warning(glyph)) && !keep_mons)
|| glyph_is_swallow(glyph))
glyph = levl_glyph;
if (((glyph_is_object(glyph) && !keep_objs)
|| glyph_is_invisible(glyph))
&& keep_traps && !covers_traps(x, y)) {
if ((t = t_at(x, y)) != 0 && t->tseen)
glyph = trap_to_glyph(t);
}
if ((glyph_is_object(glyph) && !keep_objs)
|| (glyph_is_trap(glyph) && !keep_traps)
|| glyph_is_invisible(glyph)) {
if (!seenv) {
glyph = default_glyph;
} else if (lastseentyp[x][y] == levl[x][y].typ) {
glyph = back_to_glyph(x, y);
} else {
/* look for a mimic here posing as furniture;
if we don't find one, we'll have to fake it */
if ((mtmp = m_at(x, y)) != 0
&& mtmp->m_ap_type == M_AP_FURNITURE) {
glyph = cmap_to_glyph(mtmp->mappearance);
} else {
/* we have a topology type but we want a
screen symbol in order to derive a glyph;
some screen symbols need the flags field
of levl[][] in addition to the type
(to disambiguate STAIRS to S_upstair or
S_dnstair, for example; current flags
might not be intended for remembered
type, but we've got no other choice) */
schar save_typ = levl[x][y].typ;
levl[x][y].typ = lastseentyp[x][y];
glyph = back_to_glyph(x, y);
levl[x][y].typ = save_typ;
}
}
}
}
if (glyph == cmap_to_glyph(S_darkroom))
glyph = cmap_to_glyph(S_room); /* FIXME: dirty hack */
glyph = reveal_terrain_getglyph(x,y, full, swallowed,
default_glyph, which_subset);
show_glyph(x, y, glyph);
}
+169 -51
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 end.c $NHDT-Date: 1461919723 2016/04/29 08:48:43 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.116 $ */
/* NetHack 3.6 end.c $NHDT-Date: 1489192539 2017/03/11 00:35:39 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.130 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -56,6 +56,10 @@ 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 *));
#ifdef DUMPLOG
STATIC_DCL void NDECL(dump_plines);
#endif
STATIC_DCL void FDECL(dump_everything, (int));
STATIC_DCL int NDECL(num_extinct);
#if defined(__BEOS__) || defined(MICRO) || defined(WIN32) || defined(OS2)
@@ -667,6 +671,88 @@ char *defquery;
return TRUE;
}
#ifdef DUMPLOG
STATIC_OVL void
dump_plines()
{
int i, j;
char buf[BUFSZ], **strp;
extern char *saved_plines[];
extern unsigned saved_pline_index;
Strcpy(buf, " ");
putstr(0, 0, "");
putstr(0, 0, "Latest messages:");
for (i = 0, j = (int) saved_pline_index; i < DUMPLOG_MSG_COUNT;
++i, j = (j + 1) % DUMPLOG_MSG_COUNT) {
strp = &saved_plines[j];
if (*strp) {
copynchars(&buf[1], *strp, BUFSZ - 1 - 1);
putstr(0, 0, buf);
#ifdef FREE_ALL_MEMORY
free(*strp), *strp = 0;
#endif
}
}
}
#endif
STATIC_OVL void
dump_everything(how)
int how;
{
#ifdef DUMPLOG
struct obj *obj;
char pbuf[BUFSZ];
dump_redirect(TRUE);
if (!iflags.in_dumplog)
return;
init_symbols();
for (obj = invent; obj; obj = obj->nobj) {
makeknown(obj->otyp);
obj->known = obj->bknown = obj->dknown = obj->rknown = 1;
if (Is_container(obj) || obj->otyp == STATUE)
obj->cknown = obj->lknown = 1;
}
Sprintf(pbuf, "%s, %s %s %s %s", plname,
aligns[1 - u.ualign.type].adj,
genders[flags.female].adj,
urace.adj,
(flags.female && urole.name.f) ? urole.name.f : urole.name.m);
putstr(0, 0, pbuf);
putstr(0, 0, "");
dump_map();
putstr(0, 0, do_statusline1());
putstr(0, 0, do_statusline2());
putstr(0, 0, "");
dump_plines();
putstr(0, 0, "");
putstr(0, 0, "Inventory:");
display_inventory((char *) 0, TRUE);
container_contents(invent, TRUE, TRUE, FALSE);
enlightenment((BASICENLIGHTENMENT | MAGICENLIGHTENMENT),
(how >= PANICKED) ? ENL_GAMEOVERALIVE : ENL_GAMEOVERDEAD);
putstr(0, 0, "");
list_vanquished('d', FALSE); /* 'd' => 'y' */
putstr(0, 0, "");
list_genocided('d', FALSE); /* 'd' => 'y' */
putstr(0, 0, "");
show_conduct((how >= PANICKED) ? 1 : 2);
putstr(0, 0, "");
show_overview((how >= PANICKED) ? 1 : 2, how);
putstr(0, 0, "");
dump_redirect(FALSE);
#else
nhUse(how);
#endif
}
STATIC_OVL void
disclose(how, taken)
int how;
@@ -1016,6 +1102,7 @@ int how;
urealtime.finish_time = endtime = getnow();
urealtime.realtime += (long) (endtime - urealtime.start_timing);
dump_open_log(endtime);
/* Sometimes you die on the first move. Life's not fair.
* On those rare occasions you get hosed immediately, go out
* smiling... :-) -3.
@@ -1082,6 +1169,8 @@ int how;
if (strcmp(flags.end_disclose, "none") && how != PANICKED)
disclose(how, taken);
dump_everything(how);
/* finish_paybill should be called after disclosure but before bones */
if (bones_ok && taken)
finish_paybill();
@@ -1179,6 +1268,15 @@ int how;
} else
done_stopprint = 1; /* just avoid any more output */
#ifdef DUMPLOG
/* 'how' reasons beyond genocide shouldn't show tombstone;
for normal end of game, genocide doesn't either */
if (how <= GENOCIDED) {
dump_redirect(TRUE);
genl_outrip(0, how, endtime);
dump_redirect(FALSE);
}
#endif
if (u.uhave.amulet) {
Strcat(killer.name, " (with the Amulet)");
} else if (how == ESCAPED) {
@@ -1189,16 +1287,14 @@ int how;
/* don't bother counting to see whether it should be plural */
}
if (!done_stopprint) {
Sprintf(pbuf, "%s %s the %s...", Goodbye(), plname,
(how != ASCENDED)
? (const char *) ((flags.female && urole.name.f)
? urole.name.f
: urole.name.m)
: (const char *) (flags.female ? "Demigoddess" : "Demigod"));
putstr(endwin, 0, pbuf);
putstr(endwin, 0, "");
}
Sprintf(pbuf, "%s %s the %s...", Goodbye(), plname,
(how != ASCENDED)
? (const char *) ((flags.female && urole.name.f)
? urole.name.f
: urole.name.m)
: (const char *) (flags.female ? "Demigoddess" : "Demigod"));
dump_forward_putstr(endwin, 0, pbuf, done_stopprint);
dump_forward_putstr(endwin, 0, "", done_stopprint);
if (how == ESCAPED || how == ASCENDED) {
struct monst *mtmp;
@@ -1223,45 +1319,48 @@ int how;
/* count the points for artifacts */
artifact_score(invent, TRUE, endwin);
#ifdef DUMPLOG
dump_redirect(TRUE);
artifact_score(invent, TRUE, endwin);
dump_redirect(FALSE);
#endif
viz_array[0][0] |= IN_SIGHT; /* need visibility for naming */
mtmp = mydogs;
if (!done_stopprint)
Strcpy(pbuf, "You");
Strcpy(pbuf, "You");
if (!Schroedingers_cat) /* check here in case disclosure was off */
Schroedingers_cat = odds_and_ends(invent, CAT_CHECK);
if (Schroedingers_cat) {
int mhp, m_lev = adj_lev(&mons[PM_HOUSECAT]);
mhp = d(m_lev, 8);
nowrap_add(u.urexp, mhp);
if (!done_stopprint)
Strcat(eos(pbuf), " and Schroedinger's cat");
Strcat(eos(pbuf), " and Schroedinger's cat");
}
if (mtmp) {
while (mtmp) {
if (!done_stopprint)
Sprintf(eos(pbuf), " and %s", mon_nam(mtmp));
Sprintf(eos(pbuf), " and %s", mon_nam(mtmp));
if (mtmp->mtame)
nowrap_add(u.urexp, mtmp->mhp);
mtmp = mtmp->nmon;
}
if (!done_stopprint)
putstr(endwin, 0, pbuf);
dump_forward_putstr(endwin, 0, pbuf, done_stopprint);
pbuf[0] = '\0';
} else {
if (!done_stopprint)
Strcat(pbuf, " ");
}
if (!done_stopprint) {
Sprintf(eos(pbuf), "%s with %ld point%s,",
how == ASCENDED ? "went to your reward"
: "escaped from the dungeon",
u.urexp, plur(u.urexp));
putstr(endwin, 0, pbuf);
Strcat(pbuf, " ");
}
Sprintf(eos(pbuf), "%s with %ld point%s,",
how == ASCENDED ? "went to your reward"
: "escaped from the dungeon",
u.urexp, plur(u.urexp));
dump_forward_putstr(endwin, 0, pbuf, done_stopprint);
if (!done_stopprint)
artifact_score(invent, FALSE, endwin); /* list artifacts */
#if DUMPLOG
dump_redirect(TRUE);
artifact_score(invent, FALSE, 0);
dump_redirect(FALSE);
#endif
/* list valuables here */
for (val = valuables; val->list; val++) {
@@ -1288,11 +1387,11 @@ int how;
Sprintf(pbuf, "%8ld worthless piece%s of colored glass,",
count, plur(count));
}
putstr(endwin, 0, pbuf);
dump_forward_putstr(endwin, 0, pbuf, 0);
}
}
} else if (!done_stopprint) {
} else {
/* did not escape or ascend */
if (u.uz.dnum == 0 && u.uz.dlevel <= 0) {
/* level teleported out of the dungeon; `how' is DIED,
@@ -1312,26 +1411,23 @@ int how;
}
Sprintf(eos(pbuf), " with %ld point%s,", u.urexp, plur(u.urexp));
putstr(endwin, 0, pbuf);
dump_forward_putstr(endwin, 0, pbuf, done_stopprint);
}
if (!done_stopprint) {
Sprintf(pbuf, "and %ld piece%s of gold, after %ld move%s.", umoney,
plur(umoney), moves, plur(moves));
putstr(endwin, 0, pbuf);
}
if (!done_stopprint) {
Sprintf(pbuf,
"You were level %d with a maximum of %d hit point%s when you %s.",
u.ulevel, u.uhpmax, plur(u.uhpmax), ends[how]);
putstr(endwin, 0, pbuf);
putstr(endwin, 0, "");
}
Sprintf(pbuf, "and %ld piece%s of gold, after %ld move%s.", umoney,
plur(umoney), moves, plur(moves));
dump_forward_putstr(endwin, 0, pbuf, done_stopprint);
Sprintf(pbuf,
"You were level %d with a maximum of %d hit point%s when you %s.",
u.ulevel, u.uhpmax, plur(u.uhpmax), ends[how]);
dump_forward_putstr(endwin, 0, pbuf, done_stopprint);
dump_forward_putstr(endwin, 0, "", done_stopprint);
if (!done_stopprint)
display_nhwindow(endwin, TRUE);
if (endwin != WIN_ERR)
destroy_nhwindow(endwin);
dump_close_log();
/* "So when I die, the first thing I will see in Heaven is a
* score list?" */
if (have_windows && !iflags.toptenwin)
@@ -1594,7 +1690,7 @@ dovanquished()
/* 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)
&& mndx != PM_HIGH_PRIEST)
STATIC_OVL void
list_vanquished(defquery, ask)
@@ -1608,6 +1704,11 @@ boolean ask;
winid klwin;
short mindx[NUMMONS];
char c, buf[BUFSZ], buftoo[BUFSZ];
boolean dumping; /* for DUMPLOG; doesn't need to be conditional */
dumping = (defquery == 'd');
if (dumping)
defquery = 'y';
/* get totals first */
ntypes = 0;
@@ -1644,7 +1745,8 @@ boolean ask;
klwin = create_nhwindow(NHW_MENU);
putstr(klwin, 0, "Vanquished creatures:");
putstr(klwin, 0, "");
if (!dumping)
putstr(klwin, 0, "");
qsort((genericptr_t) mindx, ntypes, sizeof *mindx, vanqsort_cmp);
for (ni = 0; ni < ntypes; ni++) {
@@ -1703,7 +1805,8 @@ boolean ask;
* putstr(klwin, 0, "and a partridge in a pear tree");
*/
if (ntypes > 1) {
putstr(klwin, 0, "");
if (!dumping)
putstr(klwin, 0, "");
Sprintf(buf, "%ld creatures vanquished.", total_killed);
putstr(klwin, 0, buf);
}
@@ -1712,7 +1815,11 @@ boolean ask;
}
} else if (defquery == 'a') {
/* #dovanquished rather than final disclosure, so pline() is ok */
pline("No monsters have been vanquished.");
pline("No creatures have been vanquished.");
#ifdef DUMPLOG
} else if (dumping) {
putstr(0, 0, "No creatures were vanquished."); /* not pline() */
#endif
}
}
@@ -1733,7 +1840,7 @@ num_genocides()
return n;
}
int
STATIC_OVL int
num_extinct()
{
int i, n = 0;
@@ -1757,6 +1864,11 @@ boolean ask;
char c;
winid klwin;
char buf[BUFSZ];
boolean dumping; /* for DUMPLOG; doesn't need to be conditional */
dumping = (defquery == 'd');
if (dumping)
defquery = 'y';
ngenocided = num_genocides();
nextinct = num_extinct();
@@ -1776,7 +1888,8 @@ boolean ask;
(ngenocided) ? "Genocided" : "Extinct",
(nextinct && ngenocided) ? " or extinct" : "");
putstr(klwin, 0, buf);
putstr(klwin, 0, "");
if (!dumping)
putstr(klwin, 0, "");
for (i = LOW_PM; i < NUMMONS; i++) {
/* uniques can't be genocided but can become extinct;
@@ -1784,7 +1897,7 @@ boolean ask;
if (UniqCritterIndx(i))
continue;
if (mvitals[i].mvflags & G_GONE) {
Strcpy(buf, makeplural(mons[i].mname));
Sprintf(buf, " %s", makeplural(mons[i].mname));
/*
* "Extinct" is unfortunate terminology. A species
* is marked extinct when its birth limit is reached,
@@ -1796,7 +1909,8 @@ boolean ask;
putstr(klwin, 0, buf);
}
}
putstr(klwin, 0, "");
if (!dumping)
putstr(klwin, 0, "");
if (ngenocided > 0) {
Sprintf(buf, "%d species genocided.", ngenocided);
putstr(klwin, 0, buf);
@@ -1809,6 +1923,10 @@ boolean ask;
display_nhwindow(klwin, TRUE);
destroy_nhwindow(klwin);
}
#ifdef DUMPLOG
} else if (dumping) {
putstr(0, 0, "No species were genocided or became extinct.");
#endif
}
}
+8 -1
View File
@@ -2267,8 +2267,15 @@ int src;
free((genericptr_t) sysopt.debugfiles);
sysopt.debugfiles = dupstr(bufp);
}
} else if (src == SET_IN_SYS && match_varname(buf, "DUMPLOGFILE", 7)) {
#ifdef DUMPLOG
if (sysopt.dumplogfile)
free((genericptr_t) sysopt.dumplogfile);
sysopt.dumplogfile = dupstr(bufp);
#endif
} else if (src == SET_IN_SYS && match_varname(buf, "GENERICUSERS", 12)) {
if (sysopt.genericusers) free(sysopt.genericusers);
if (sysopt.genericusers)
free((genericptr_t) sysopt.genericusers);
sysopt.genericusers = dupstr(bufp);
} else if (src == SET_IN_SYS && match_varname(buf, "SUPPORT", 7)) {
if (sysopt.support)
+2 -4
View File
@@ -513,12 +513,10 @@ struct obj *obj;
}
set_artifact_intrinsic(obj, 1, W_ART);
}
if (obj->otyp == LUCKSTONE && obj->record_achieve_special) {
if (is_mines_prize(obj) && obj->record_achieve_special) {
u.uachieve.mines_luckstone = 1;
obj->record_achieve_special = 0;
} else if ((obj->otyp == AMULET_OF_REFLECTION
|| obj->otyp == BAG_OF_HOLDING)
&& obj->record_achieve_special) {
} else if (is_soko_prize(obj) && obj->record_achieve_special) {
u.uachieve.finish_sokoban = 1;
obj->record_achieve_special = 0;
}
+5 -4
View File
@@ -1794,11 +1794,11 @@ 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];
/* new form might force gender change */
fem = is_male(ptr) ? 0 : is_female(ptr) ? 1 : mtmp->female;
if (mvitals[newtype].mvflags & G_GENOD) { /* allow G_EXTINCT */
if (canspotmon(mtmp))
pline("As %s grows up into %s, %s %s!", mon_nam(mtmp),
@@ -1830,8 +1830,9 @@ struct monst *mtmp, *victim;
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 */
}
mtmp->female = fem; /* gender might be changing */
/* sanity checks */
if ((int) mtmp->m_lev > lev_limit) {
+2 -1
View File
@@ -929,7 +929,8 @@ struct monst *mtmp;
|| otmp->otyp == RIN_SLOW_DIGESTION)
/* cockatrice corpses handled above; this
touch_petrifies() check catches eggs */
|| ((otmp->otyp == CORPSE || otmp->otyp == EGG)
|| ((otmp->otyp == CORPSE || otmp->otyp == EGG
|| otmp->globby)
&& ((touch_petrifies(&mons[otmp->corpsenm])
&& !resists_ston(mtmp))
|| (otmp->corpsenm == PM_GREEN_SLIME
+57 -2
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 pline.c $NHDT-Date: 1461437814 2016/04/23 18:56:54 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.51 $ */
/* NetHack 3.6 pline.c $NHDT-Date: 1489192905 2017/03/11 00:41:45 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.57 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -14,6 +14,53 @@ static char *FDECL(You_buf, (int));
static void FDECL(execplinehandler, (const char *));
#endif
#ifdef DUMPLOG
/* also used in end.c */
unsigned saved_pline_index = 0; /* slot in saved_plines[] to use next */
char *saved_plines[DUMPLOG_MSG_COUNT] = { (char *) 0 };
/* keep the most recent DUMPLOG_MSG_COUNT messages */
void
dumplogmsg(line)
const char *line;
{
/*
* TODO:
* This essentially duplicates message history, which is
* currently implemented in an interface-specific manner.
* The core should take responsibility for that and have
* this share it.
*/
unsigned indx = saved_pline_index; /* next slot to use */
char *oldest = saved_plines[indx]; /* current content of that slot */
if (oldest && strlen(oldest) >= strlen(line)) {
/* this buffer will gradually shrink until the 'else' is needed;
there's no pressing need to track allocation size instead */
Strcpy(oldest, line);
} else {
if (oldest)
free((genericptr_t) oldest);
saved_plines[indx] = dupstr(line);
}
saved_pline_index = (indx + 1) % DUMPLOG_MSG_COUNT;
}
/* called during save (unlike the interface-specific message history,
this data isn't saved and restored); end-of-game releases saved_pline[]
while writing its contents to the final dump log */
void
dumplogfreemessages()
{
unsigned indx;
for (indx = 0; indx < DUMPLOG_MSG_COUNT; ++indx)
if (saved_plines[indx])
free((genericptr_t) saved_plines[indx]), saved_plines[indx] = 0;
saved_pline_index = 0;
}
#endif
/*VARARGS1*/
/* Note that these declarations rely on knowledge of the internals
* of the variable argument handling stuff in "tradstdc.h"
@@ -87,6 +134,14 @@ VA_DECL(const char *, line)
return;
}
#ifdef DUMPLOG
/* We hook here early to have options-agnostic output.
* Unfortunately, that means Norep() isn't honored (general issue) and
* that short lines aren't combined into one longer one (tty behavior).
*/
dumplogmsg(line);
#endif
msgtyp = msgtype_type(line, no_repeat);
if (msgtyp == MSGTYP_NOSHOW
|| (msgtyp == MSGTYP_NOREP && !strcmp(line, prevmsg)))
@@ -104,7 +159,7 @@ VA_DECL(const char *, line)
/* this gets cleared after every pline message */
iflags.last_msg = PLNMSG_UNKNOWN;
strncpy(prevmsg, line, BUFSZ), prevmsg[BUFSZ - 1] = '\0';
(void) strncpy(prevmsg, line, BUFSZ), prevmsg[BUFSZ - 1] = '\0';
if (msgtyp == MSGTYP_STOP)
display_nhwindow(WIN_MESSAGE, TRUE); /* --more-- */
+12 -3
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 rip.c $NHDT-Date: 1450432760 2015/12/18 09:59:20 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.22 $ */
/* NetHack 3.6 rip.c $NHDT-Date: 1488788514 2017/03/06 08:21:54 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.23 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -141,12 +141,21 @@ time_t when;
Sprintf(buf, "%4ld", year);
center(YEAR_LINE, buf);
putstr(tmpwin, 0, "");
#ifdef DUMPLOG
if (tmpwin == 0)
dump_forward_putstr(0, 0, "Gave over:", TRUE);
else
#endif
putstr(tmpwin, 0, "");
for (; *dp; dp++)
putstr(tmpwin, 0, *dp);
putstr(tmpwin, 0, "");
putstr(tmpwin, 0, "");
#ifdef DUMPLOG
if (tmpwin != 0)
#endif
putstr(tmpwin, 0, "");
for (x = 0; rip_txt[x]; x++) {
free((genericptr_t) rip[x]);
+4 -1
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 save.c $NHDT-Date: 1450231175 2015/12/16 01:59:35 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.98 $ */
/* NetHack 3.6 save.c $NHDT-Date: 1489192905 2017/03/11 00:41:45 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.101 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1413,6 +1413,9 @@ freedynamicdata()
#ifdef STATUS_VIA_WINDOWPORT
status_finish();
#endif
#ifdef DUMPLOG
dumplogfreemessages();
#endif
/* last, because it frees data that might be used by panic() to provide
feedback to the user; conceivably other freeing might trigger panic */
+1 -5
View File
@@ -1951,11 +1951,7 @@ struct mkroom *croom;
* "prize" and then set record_achieve_special (maps to corpsenm)
* for the object. That field will later be checked to find out if
* the player obtained the prize. */
if (otmp->otyp == LUCKSTONE && Is_mineend_level(&u.uz)) {
otmp->record_achieve_special = 1;
} else if ((otmp->otyp == AMULET_OF_REFLECTION
|| otmp->otyp == BAG_OF_HOLDING)
&& Is_sokoend_level(&u.uz)) {
if (is_mines_prize(otmp) || is_soko_prize(otmp)) {
otmp->record_achieve_special = 1;
}
+7
View File
@@ -31,6 +31,9 @@ sys_early_init()
sysopt.debugfiles = (char *) 0;
#else
sysopt.debugfiles = dupstr(DEBUGFILES);
#endif
#ifdef DUMPLOG
sysopt.dumplogfile = (char *) 0;
#endif
sysopt.env_dbgfl = 0; /* haven't checked getenv("DEBUGFILES") yet */
sysopt.shellers = (char *) 0;
@@ -95,6 +98,10 @@ sysopt_release()
if (sysopt.debugfiles)
free((genericptr_t) sysopt.debugfiles),
sysopt.debugfiles = (char *) 0;
#ifdef DUMPLOG
if (sysopt.dumplogfile)
free((genericptr_t)sysopt.dumplogfile), sysopt.dumplogfile=(char *)0;
#endif
if (sysopt.genericusers)
free((genericptr_t) sysopt.genericusers),
sysopt.genericusers = (char *) 0;
+267 -1
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 windows.c $NHDT-Date: 1448013599 2015/11/20 09:59:59 $ $NHDT-Branch: master $:$NHDT-Revision: 1.35 $ */
/* NetHack 3.6 windows.c $NHDT-Date: 1488075979 2017/02/26 02:26:19 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.39 $ */
/* Copyright (c) D. Cohrs, 1993. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1032,4 +1032,270 @@ int behavior UNUSED, under UNUSED, over UNUSED;
#endif /* STATUS_HILITES */
#endif /* STATUS_VIA_WINDOWPORT */
STATIC_VAR struct window_procs dumplog_windowprocs_backup;
STATIC_PTR FILE *dumplog_file;
#ifdef DUMPLOG
STATIC_VAR time_t dumplog_now;
STATIC_DCL char *FDECL(dump_fmtstr, (const char *, char *));
STATIC_OVL char *
dump_fmtstr(fmt, buf)
const char *fmt;
char *buf;
{
const char *fp = fmt;
char *bp = buf;
int slen, len = 0;
char tmpbuf[BUFSZ];
char verbuf[BUFSZ];
long uid;
time_t now;
now = dumplog_now;
uid = (long) getuid();
/*
* Note: %t and %T assume that time_t is a 'long int' number of
* seconds since some epoch value. That's quite iffy.... The
* unit of time might be different and the datum size might be
* some variant of 'long long int'. [Their main purpose is to
* construct a unique file name rather than record the date and
* time; violating the 'long seconds since base-date' assumption
* may or may not interfere with that usage.]
*/
while (fp && *fp && len < BUFSZ-1) {
if (*fp == '%') {
fp++;
switch (*fp) {
default:
goto finish;
case '\0': /* fallthrough */
case '%': /* literal % */
Sprintf(tmpbuf, "%%");
break;
case 't': /* game start, timestamp */
Sprintf(tmpbuf, "%lu", (unsigned long) ubirthday);
break;
case 'T': /* current time, timestamp */
Sprintf(tmpbuf, "%lu", (unsigned long) now);
break;
case 'd': /* game start, YYYYMMDDhhmmss */
Sprintf(tmpbuf, "%08ld%06ld",
yyyymmdd(ubirthday), hhmmss(ubirthday));
break;
case 'D': /* current time, YYYYMMDDhhmmss */
Sprintf(tmpbuf, "%08ld%06ld", yyyymmdd(now), hhmmss(now));
break;
case 'v': /* version, eg. "3.6.1-0" */
Sprintf(tmpbuf, "%s", version_string(verbuf));
break;
case 'u': /* UID */
Sprintf(tmpbuf, "%ld", uid);
break;
case 'n': /* player name */
Sprintf(tmpbuf, "%s", *plname ? plname : "unknown");
break;
case 'N': /* first character of player name */
Sprintf(tmpbuf, "%c", *plname ? *plname : 'u');
break;
}
slen = strlen(tmpbuf);
if (len + slen < BUFSZ-1) {
len += slen;
Sprintf(bp, "%s", tmpbuf);
bp += slen;
if (*fp) fp++;
} else
break;
} else {
*bp = *fp;
bp++;
fp++;
len++;
}
}
finish:
*bp = '\0';
return buf;
}
#endif /* DUMPLOG */
void
dump_open_log(now)
time_t now;
{
#ifdef DUMPLOG
char buf[BUFSZ];
char *fname;
dumplog_now = now;
#ifdef SYSCF
if (!sysopt.dumplogfile)
return;
fname = dump_fmtstr(sysopt.dumplogfile, buf);
#else
fname = dump_fmtstr(DUMPLOG_FILE, buf);
#endif
dumplog_file = fopen(fname, "w");
dumplog_windowprocs_backup = windowprocs;
#else /*!DUMPLOG*/
nhUse(now);
#endif /*?DUMPLOG*/
}
void
dump_close_log()
{
if (dumplog_file) {
fclose(dumplog_file);
dumplog_file = NULL;
}
}
void
dump_putc(ch)
int ch;
{
/* Not very efficient, but we mostly don't care. */
if (dumplog_file)
putc(ch, dumplog_file);
}
void
dump_forward_putstr(win, attr, str, no_forward)
winid win;
int attr;
const char *str;
int no_forward;
{
if (dumplog_file)
fprintf(dumplog_file, "%s\n", str);
if (!no_forward)
putstr(win, attr, str);
}
/*ARGSUSED*/
STATIC_OVL void
dump_putstr(win, attr, str)
winid win UNUSED;
int attr UNUSED;
const char *str;
{
if (dumplog_file)
fprintf(dumplog_file, "%s\n", str);
}
STATIC_OVL winid
dump_create_nhwindow(dummy)
int dummy;
{
return dummy;
}
/*ARGUSED*/
STATIC_OVL void
dump_clear_nhwindow(win)
winid win UNUSED;
{
return;
}
/*ARGSUSED*/
STATIC_OVL void
dump_display_nhwindow(win, p)
winid win UNUSED;
boolean p UNUSED;
{
return;
}
/*ARGUSED*/
STATIC_OVL void
dump_destroy_nhwindow(win)
winid win UNUSED;
{
return;
}
/*ARGUSED*/
STATIC_OVL void
dump_start_menu(win)
winid win UNUSED;
{
return;
}
/*ARGSUSED*/
STATIC_OVL void
dump_add_menu(win, glyph, identifier, ch, gch, attr, str, preselected)
winid win UNUSED;
int glyph UNUSED;
const anything *identifier UNUSED;
char ch;
char gch UNUSED;
int attr UNUSED;
const char *str;
boolean preselected UNUSED;
{
if (dumplog_file) {
if (glyph == NO_GLYPH)
fprintf(dumplog_file, " %s\n", str);
else
fprintf(dumplog_file, " %c - %s\n", ch, str);
}
}
/*ARGSUSED*/
STATIC_OVL void
dump_end_menu(win, str)
winid win UNUSED;
const char *str;
{
if (dumplog_file) {
if (str)
fprintf(dumplog_file, "%s\n", str);
else
fputs("\n", dumplog_file);
}
}
STATIC_OVL int
dump_select_menu(win, how, item)
winid win UNUSED;
int how UNUSED;
menu_item **item;
{
*item = (menu_item *) 0;
return 0;
}
void
dump_redirect(onoff_flag)
boolean onoff_flag;
{
if (dumplog_file) {
if (onoff_flag) {
windowprocs.win_create_nhwindow = dump_create_nhwindow;
windowprocs.win_clear_nhwindow = dump_clear_nhwindow;
windowprocs.win_display_nhwindow = dump_display_nhwindow;
windowprocs.win_destroy_nhwindow = dump_destroy_nhwindow;
windowprocs.win_start_menu = dump_start_menu;
windowprocs.win_add_menu = dump_add_menu;
windowprocs.win_end_menu = dump_end_menu;
windowprocs.win_select_menu = dump_select_menu;
windowprocs.win_putstr = dump_putstr;
} else {
windowprocs = dumplog_windowprocs_backup;
}
iflags.in_dumplog = onoff_flag;
} else {
iflags.in_dumplog = FALSE;
}
}
/*windows.c*/
+1
View File
@@ -25,6 +25,7 @@ CFLAGS1=-DCOMPRESS=\"/bin/gzip\" -DCOMPRESS_EXTENSION=\".gz\"
CFLAGS+=-DSYSCF -DSYSCF_FILE=\"$(HACKDIR)/sysconf\" -DSECURE
CFLAGS+=-DTIMED_DELAY
CFLAGS+=-DHACKDIR=\"$(HACKDIR)\"
CFLAGS+=-DDUMPLOG
LINK=$(CC)
# Only needed for GLIBC stack trace:
+14
View File
@@ -84,6 +84,20 @@ MAXPLAYERS=10
# overridden via DEBUGFILES environment variable.
#DEBUGFILES=*
# Save end of game dump log to this file.
# Only available if NetHack was compiled with DUMPLOG
# Allows following placeholders:
# %% literal '%'
# %v version (eg. "3.6.1-0")
# %u game UID
# %t game start time, UNIX timestamp format
# %T current time, UNIX timestamp format
# %d game start time, YYYYMMDDhhmmss format
# %D current time, YYYYMMDDhhmmss format
# %n player name
# %N first character of player name
#DUMPLOGFILE=/tmp/nethack.%n.%d.log
# Try to get more info in case of a program bug or crash. Only used
# if the program is built with the PANICTRACE compile-time option enabled.
# By default PANICTRACE is enabled if BETA is defined, otherwise disabled.
+14
View File
@@ -18,6 +18,20 @@ WIZARDS=*
# Only available if game has been compiled with DEBUG.
#DEBUGFILES=*
# Save end of game dump log to this file.
# Only available if NetHack was compiled with DUMPLOG
# Allows following placeholders:
# %% literal '%'
# %v version (eg. "3.6.1-0")
# %u game UID
# %t game start time, UNIX timestamp format
# %T current time, UNIX timestamp format
# %d game start time, YYYYMMDDhhmmss format
# %D current time, YYYYMMDDhhmmss format
# %n player name
# %N first character of player name
#DUMPLOGFILE=nethack-%n-%d.log
# Limit the number of simultaneous games (see also nethack.sh).
#MAXPLAYERS=10
+3
View File
@@ -1448,6 +1448,9 @@ static const char *build_opts[] = {
#ifdef DLB
"data librarian",
#endif
#ifdef DUMPLOG
"end-of-game dumplogs",
#endif
#ifdef MFLOPPY
"floppy drive support",
#endif