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

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)

215
src/cmd.c
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)

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

220
src/end.c
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
}
}

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)

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

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) {

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

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

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]);

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

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

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;

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