From 2b1f8a1b432911948cc6c40af2336b5d7f8a07b2 Mon Sep 17 00:00:00 2001 From: PatR Date: Mon, 13 Jan 2020 12:34:01 -0800 Subject: [PATCH 01/24] fix #K166 - role selection filtering pick_role() had a 5 year old copy+paste error where a pair of lines were cloned multiple times but one of the resulting lines didn't get the intended revision, preventing OPTIONS=align:!chaotic or !neutral or !lawful from working as intended when letting the game choose role randomly. The bad line should have been calling ok_align() but that routine turned out to have a bug too. Fixing those lead to other less obvious problems with role selection, particularly the tty menu version for picking manually. Roles and/or races which should have been excluded by partial specification weren't always kept out. Also, if any filtering was specified, trying to disable all filters (via choosing 'reset filtering' and de-selecting everything in the menu) was a no-op. Once any filtering was in place you had to leave at least one role or race or gender or alignment flagged as not acceptable in order to change any of the filtering. When that was fixed and it was possible to turn off all filtering, there was no way to turn it back on because the menu choice to reset the filters wasn't offered unless there was some filtering in place (that was intentional but turned out not to be a good idea). I checked curses and X11; they both offer less versatile selection capability that don't seem to need the tty-specific fixes. --- doc/fixes37.0 | 5 ++++- src/role.c | 14 +++++++++----- win/tty/wintty.c | 42 +++++++++++++++++++++++++++--------------- 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 63533bb38..988af40ac 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.65 $ $NHDT-Date: 1578896120 2020/01/13 06:15:20 $ +$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.66 $ $NHDT-Date: 1578947634 2020/01/13 20:33:54 $ General Fixes and Modified Features ----------------------------------- @@ -44,6 +44,7 @@ walking out of tethered-to-buried-object trap condition was supposed to attached chain that got dragged around but had no ball attached when poly'd into a giant and moving onto a boulder's spot, message given was confused about whether autopickup would occur so could be misleading +random role selection wasn't honoring unwanted alignment(s) properly Fixes to 3.7.0-x Problems that Were Exposed Via git Repository @@ -75,6 +76,8 @@ data.base lookup of an entry with any blank lines would falsely claim that Platform- and/or Interface-Specific Fixes ----------------------------------------- +tty: role and race selection menus weren't filtering out potential choices + which got excluded by OPTIONS=align:!lawful or !neutral or !chaotic General New Features diff --git a/src/role.c b/src/role.c index 1a1a88986..f93859da1 100644 --- a/src/role.c +++ b/src/role.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 role.c $NHDT-Date: 1574648943 2019/11/25 02:29:03 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.65 $ */ +/* NetHack 3.6 role.c $NHDT-Date: 1578947634 2020/01/13 20:33:54 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.68 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985-1999. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1047,8 +1047,8 @@ int racenum, gendnum, alignnum, pickhow; gendnum, alignnum) && ok_gend(i, racenum, (gendnum >= 0) ? gendnum : ROLE_RANDOM, alignnum) - && ok_race(i, racenum, - gendnum, (alignnum >= 0) ? alignnum : ROLE_RANDOM)) + && ok_align(i, racenum, + gendnum, (alignnum >= 0) ? alignnum : ROLE_RANDOM)) set[roles_ok++] = i; } if (roles_ok == 0 || (roles_ok > 1 && pickhow == PICK_RIGID)) @@ -1221,7 +1221,7 @@ int alignnum; /* random; check whether any selection is possible */ for (i = 0; i < ROLE_ALIGNS; i++) { if (g.rfilter.mask & aligns[i].allow) - return FALSE; + continue; allow = aligns[i].allow; if (rolenum >= 0 && rolenum < SIZE(roles) - 1 && !(allow & roles[rolenum].allow & ROLE_ALIGNMASK)) @@ -1909,9 +1909,13 @@ boolean preselect; add_menu(where, NO_GLYPH, &any, RS_menu_let[which], 0, ATR_NONE, buf, MENU_ITEMFLAGS_NONE); } else if (which == RS_filter) { + char setfiltering[40]; + any.a_int = RS_menu_arg(RS_filter); + Sprintf(setfiltering, "%s role/race/&c filtering", + gotrolefilter() ? "Reset" : "Set"); add_menu(where, NO_GLYPH, &any, '~', 0, ATR_NONE, - "Reset role/race/&c filtering", MENU_ITEMFLAGS_NONE); + setfiltering, MENU_ITEMFLAGS_NONE); } else if (which == ROLE_RANDOM) { any.a_int = ROLE_RANDOM; add_menu(where, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random", diff --git a/win/tty/wintty.c b/win/tty/wintty.c index 0fbe47648..a6ad2f7a2 100644 --- a/win/tty/wintty.c +++ b/win/tty/wintty.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 wintty.c $NHDT-Date: 1575245194 2019/12/02 00:06:34 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.227 $ */ +/* NetHack 3.6 wintty.c $NHDT-Date: 1578947635 2020/01/13 20:33:55 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.244 $ */ /* Copyright (c) David Cohrs, 1991 */ /* NetHack may be freely redistributed. See license for details. */ @@ -582,8 +582,7 @@ tty_player_selection() role_menu_extra(RS_RACE, win, FALSE); role_menu_extra(RS_GENDER, win, FALSE); role_menu_extra(RS_ALGNMNT, win, FALSE); - if (gotrolefilter()) - role_menu_extra(RS_filter, win, FALSE); + role_menu_extra(RS_filter, win, FALSE); role_menu_extra(ROLE_NONE, win, FALSE); /* quit */ Strcpy(pbuf, "Pick a role or profession"); end_menu(win, pbuf); @@ -681,8 +680,7 @@ tty_player_selection() role_menu_extra(RS_ROLE, win, FALSE); role_menu_extra(RS_GENDER, win, FALSE); role_menu_extra(RS_ALGNMNT, win, FALSE); - if (gotrolefilter()) - role_menu_extra(RS_filter, win, FALSE); + role_menu_extra(RS_filter, win, FALSE); role_menu_extra(ROLE_NONE, win, FALSE); /* quit */ Strcpy(pbuf, "Pick a race or species"); end_menu(win, pbuf); @@ -774,8 +772,7 @@ tty_player_selection() role_menu_extra(RS_ROLE, win, FALSE); role_menu_extra(RS_RACE, win, FALSE); role_menu_extra(RS_ALGNMNT, win, FALSE); - if (gotrolefilter()) - role_menu_extra(RS_filter, win, FALSE); + role_menu_extra(RS_filter, win, FALSE); role_menu_extra(ROLE_NONE, win, FALSE); /* quit */ Strcpy(pbuf, "Pick a gender or sex"); end_menu(win, pbuf); @@ -863,8 +860,7 @@ tty_player_selection() role_menu_extra(RS_ROLE, win, FALSE); role_menu_extra(RS_RACE, win, FALSE); role_menu_extra(RS_GENDER, win, FALSE); - if (gotrolefilter()) - role_menu_extra(RS_filter, win, FALSE); + role_menu_extra(RS_filter, win, FALSE); role_menu_extra(ROLE_NONE, win, FALSE); /* quit */ Strcpy(pbuf, "Pick an alignment or creed"); end_menu(win, pbuf); @@ -1032,6 +1028,7 @@ reset_role_filtering() winid win; anything any; int i, n; + char filterprompt[QBUFSZ]; menu_item *selected = 0; win = create_nhwindow(NHW_MENU); @@ -1058,10 +1055,12 @@ reset_role_filtering() "Unacceptable alignments", MENU_ITEMFLAGS_NONE); setup_algnmenu(win, FALSE, ROLE_NONE, ROLE_NONE, ROLE_NONE); - end_menu(win, "Pick all that apply"); + Sprintf(filterprompt, "Pick all that apply%s", + gotrolefilter() ? " and/or unpick any that no longer apply" : ""); + end_menu(win, filterprompt); n = select_menu(win, PICK_ANY, &selected); - if (n > 0) { + if (n >= 0) { /* n==0: clear current filters and don't set new ones */ clearrolefilter(); for (i = 0; i < n; i++) setrolefilter(selected[i].item.a_string); @@ -1093,7 +1092,11 @@ int race, gend, algn; /* all ROLE_NONE for !filtering case */ any = cg.zeroany; /* zero out all bits */ for (i = 0; roles[i].name.m; i++) { - role_ok = ok_role(i, race, gend, algn); + /* role can be constrained by any of race, gender, or alignment */ + role_ok = (ok_role(i, race, gend, algn) + && ok_race(i, race, gend, algn) + && ok_gend(i, race, gend, algn) + && ok_align(i, race, gend, algn)); if (filtering && !role_ok) continue; if (filtering) @@ -1137,7 +1140,10 @@ int role, gend, algn; any = cg.zeroany; for (i = 0; races[i].noun; i++) { - race_ok = ok_race(role, i, gend, algn); + /* no ok_gend(); race isn't constrained by gender */ + race_ok = (ok_race(role, i, gend, algn) + && ok_role(role, i, gend, algn) + && ok_align(role, i, gend, algn)); if (filtering && !race_ok) continue; if (filtering) @@ -1171,7 +1177,10 @@ int role, race, algn; any = cg.zeroany; for (i = 0; i < ROLE_GENDERS; i++) { - gend_ok = ok_gend(role, race, i, algn); + /* no ok_align(); gender isn't constrained by alignment */ + gend_ok = (ok_gend(role, race, i, algn) + && ok_role(role, race, i, algn) + && ok_race(role, race, i, algn)); if (filtering && !gend_ok) continue; if (filtering) @@ -1203,7 +1212,10 @@ int role, race, gend; any = cg.zeroany; for (i = 0; i < ROLE_ALIGNS; i++) { - algn_ok = ok_align(role, race, gend, i); + /* no ok_gend(); alignment isn't constrained by gender */ + algn_ok = (ok_align(role, race, gend, i) + && ok_role(role, race, gend, i) + && ok_race(role, race, gend, i)); if (filtering && !algn_ok) continue; if (filtering) From bd254e0853514e6052468c80e2a75eac1e8249ec Mon Sep 17 00:00:00 2001 From: nhw_cron Date: Tue, 14 Jan 2020 11:17:42 -0500 Subject: [PATCH 02/24] This is cron-daily v1-Jan-14-2020. manpages updated: dlb.txt --- doc/dlb.txt | 144 +++++++++++++++------------------------------------- 1 file changed, 42 insertions(+), 102 deletions(-) diff --git a/doc/dlb.txt b/doc/dlb.txt index afc09c2d0..7fbd931f5 100644 --- a/doc/dlb.txt +++ b/doc/dlb.txt @@ -1,132 +1,72 @@ - - - -DLB(6) 1993 DLB(6) +DLB(6) Games Manual DLB(6) NAME - dlb - NetHack data librarian + dlb - NetHack data librarian SYNOPSIS - dlb { xct } [ vfIC ] arguments... [ files... ] + dlb { xct } [ vfIC ] arguments... [ files... ] DESCRIPTION - Dlb is a file archiving tool in the spirit (and tradition) - of tar for NetHack version 3.1 and higher. It is used to - maintain the archive files from which NetHack reads special - level files and other read-only information. Note that like - tar the command and option specifiers are specified as a - continuous string and are followed by any arguments required - in the same order as the option specifiers. + Dlb is a file archiving tool in the spirit (and tradition) of tar for + NetHack version 3.1 and higher. It is used to maintain the archive + files from which NetHack reads special level files and other read-only + information. Note that like tar the command and option specifiers are + specified as a continuous string and are followed by any arguments + required in the same order as the option specifiers. - This facility is optional and may be excluded during NetHack - configuration. + ^?ALLDOCS This facility is optional and may be excluded during NetHack + configuration. ^: ^?DLB This facility is optional but is included in + this NetHack configuration. ^: This facility is optional and was + excluded from this NetHack configuration. ^. ^. COMMANDS - The x command causes dlb to extract the contents of the - archive into the current directory. + The x command causes dlb to extract the contents of the archive into + the current directory. - The c command causes dlb to create a new archive from files - in the current directory. + The c command causes dlb to create a new archive from files in the cur- + rent directory. - The t command lists the files in the archive. + The t command lists the files in the archive. OPTIONS AND ARGUMENTS - v verbose output + v verbose output - f archive specify the archive. Default if f not specified - is LIBFILE (usually the nhdat file in the playground). + f archive specify the archive. Default if f not specified is LIBFILE + (usually the nhdat file in the playground). - I lfile specify the file containing the list of files to - put in to or extract from the archive if no files are listed - on the command line. Default for archive creation if no - files are listed is LIBLISTFILE. + I lfile specify the file containing the list of files to put in to + or extract from the archive if no files are listed on the command line. + Default for archive creation if no files are listed is LIBLISTFILE. - C dir change directory. Changes directory before try- - ing to read any files (including the archive and the lfile). + C dir change directory. Changes directory before trying to read + any files (including the archive and the lfile). EXAMPLES - Create the default archive from the default file list: - dlb c + Create the default archive from the default file list: + dlb c - List the contents of the archive 'foo': - dlb tf foo + List the contents of the archive 'foo': + dlb tf foo AUTHOR - Kenneth Lorber - - - - - -Oct Last change: 28 1 - - - - - - -DLB(6) 1993 DLB(6) - - + Kenneth Lorber SEE ALSO - nethack(6), tar(1) + nethack(6), tar(1) BUGS - Not a good tar emulation; - does not mean stdin or stdout. - Should include an optional compression facility. Not all - read-only files for NetHack can be read out of an archive; - examining the source is the only way to know which files can - be. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Oct Last change: 28 2 + Not a good tar emulation; - does not mean stdin or stdout. Should + include an optional compression facility. Not all read-only files for + NetHack can be read out of an archive; examining the source is the only + way to know which files can be. + +COPYRIGHT + This file is Copyright (C) Kenneth Lorber and was last modified + 2018/04/25 (version NetHack-3.6.0:1.7). NetHack may be freely redis- + tributed. See license for details. +NETHACK 25 May 2015 DLB(6) From f431c72873a4ee39d1006bb994177ea94c02cb1f Mon Sep 17 00:00:00 2001 From: nhw_cron Date: Tue, 14 Jan 2020 11:17:43 -0500 Subject: [PATCH 03/24] This is cron-daily v1-Jan-14-2020. manpages updated: makedefs.txt --- doc/makedefs.txt | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/doc/makedefs.txt b/doc/makedefs.txt index 8c2edb3c8..08ca2c9ef 100644 --- a/doc/makedefs.txt +++ b/doc/makedefs.txt @@ -1,4 +1,4 @@ -MAKEDEFS(6) MAKEDEFS(6) +MAKEDEFS(6) Games Manual MAKEDEFS(6) @@ -30,21 +30,28 @@ SHORT COMMANDS through the same logic as that used by the --grep command; see the MDGREP FUNCTIONS section below for details. - -m Generate monster.c. - - -v Generate date.h and options file. + -m Generate date.h and options file. It will read dat/gitinfo.txt, + only if it is present, to obtain githash= and gitbranch= + info and include related preprocessor #defines in date.h file. -p Generate pm.h - -q Generate quest.dat. + -q Generate the rumors file. - -r Generate the rumors file. + -s Generate the bogusmon , engrave and epitaphfiles. -h Generate the oracles file. -z Generate vis_tab.c and vis_tab.h. LONG COMMANDS + --debug + Show debugging output. + + --make [command] + Execute a short command. Command is given without preceding + dash. + --input file Specify the input file for the command (if needed). If the file is - standard input is read. @@ -58,7 +65,7 @@ LONG COMMANDS newline. If specified, the delimiter is used between each part of the version string. - --grep Filter the input file to the output file. See the MDGREP FUNC + --grep Filter the input file to the output file. See the MDGREP FUNC- TIONS section below for information on controlling the filtering operation. @@ -82,7 +89,7 @@ MDGREP FUNCTIONS The --grep command (and certain other commands) filter their input, on a line-by-line basis, according to control lines embedded in the input and on information gleaned from the NetHack(6) configuration. This - allows certain changes such as embedding platform-specific documenta + allows certain changes such as embedding platform-specific documenta- tion into the master documentation files. Rules: @@ -90,11 +97,11 @@ MDGREP FUNCTIONS - The default conditional state is printing enabled. - Any line NOT starting with a caret (^) is either suppressed - or passed through unchanged depending on the current condi + or passed through unchanged depending on the current condi- tional state. - Any line starting with a caret is a control line; as in C, - zero or more spaces may be embedded in the line almost any + zero or more spaces may be embedded in the line almost any- where (except immediately after the caret); however the caret must be in column 1. @@ -105,7 +112,7 @@ MDGREP FUNCTIONS many errors as possible to be detected. - Unknown identifiers are treated as both TRUE and as an - error. Note that --undef or #undef in the NetHack(6) con + error. Note that --undef or #undef in the NetHack(6) con- figuration are different from unknown. Control lines: @@ -130,6 +137,11 @@ AUTHOR SEE ALSO dgn_comp(6) +COPYRIGHT + This file is Copyright (C) Kenneth Lorber and was last modified + 2018/04/25 (version NetHack-3.6.0:1.10). NetHack may be freely redis- + tributed. See license for details. -4th Berkeley Distribution 29 Apr 2010 MAKEDEFS(6) + +NETHACK 1 Jan 2020 MAKEDEFS(6) From 32c7279e63762287c1fd006c29974422092c4eec Mon Sep 17 00:00:00 2001 From: nhw_cron Date: Tue, 14 Jan 2020 11:17:43 -0500 Subject: [PATCH 04/24] This is cron-daily v1-Jan-14-2020. manpages updated: mn.txt --- doc/mn.txt | 215 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 doc/mn.txt diff --git a/doc/mn.txt b/doc/mn.txt new file mode 100644 index 000000000..502a0f3bb --- /dev/null +++ b/doc/mn.txt @@ -0,0 +1,215 @@ +MN(7) Miscellaneous Information Manual MN(7) + + + +NAME + mn - text formatting macros for the news documentation + +SYNOPSIS + nroff -mn [ options ] file ... + troff -mn [ options ] file ... + +DESCRIPTION + This package of nroff(1) and troff(1) macro definitions provides a for- + matting facility which may be used to run off the formatted news docu- + ments. When reverse line motions are needed, filter the output through + col(1). + + All -mn macros, diversions, string registers, and number registers are + defined below. Many nroff and troff requests are unsafe in conjunction + with this package. However, the requests below may be used with + impunity: + + .bp begin new page + .br break output line + .sp n insert n spacing lines + .ce n center next n lines + .ls n line spacing: n=1 single, n=2 double space + .na no alignment of right margin + + Font and point size changes with \f and \s are also allowed; for exam- + ple, ``\f2word\fR'' will italicize word. Output of the tbl(1), eqn(1), + and refer(1) preprocessors for equations, tables, and references is + acceptable as input. + +FILES + /usr/lib/tmac/tmac.n + +SEE ALSO + eqn(1), refer(1), tbl(1), troff(1) + +WARNINGS + If you do not set the string register ``.f'' to the file name, you will + only be told the line number on which any errors occur. If you define + this string to be the file name, you will get the file name, too. This + is useful when dealing with a document split up into many files. + + This package is not now intended for uses other than with the news doc- + umentation. + + Bug reports are always welcome; please send them to the author. + (Include a sample of the input; this helps track down the bug.) + +AUTHOR + Matt Bishop (mab@riacs.arpa, ihnp4!ames!riacs!mab, dec- + vax!decwrl!riacs!mab) + Updated for versions 1.4-1.6 by The NetHack Development Team + +REQUESTS + In the Note column, b means the request causes a break, and i means the + macro, number register, string register, or diversion is internal and + should not be used for anything. In the What It Is column, div means + diversion, mac means macro, num means number register, and str means + string register. In the Initial Value column, a hyphen means no ini- + tial value is used, anything else is the initial value, and if two val- + ues are given, the first is for nroff and the second for troff. + +Macro What Initial Note Explanation +Name It Is Value +.f num - - file name, used in error messages if set +.ai mac - - author's institution +.au mac - b author's name +.b x y z mac - - print x in font 3, y after, z before; + if no arguments, switch to font 3 +b num - i used to embolden italics +.bi x y z mac - - print x in emboldened font 2, y after, + z before +bm num 1i,1i+1v - height of bottom margin +.bt mac - - print pottom title +bt num .5i+1v - bottom of footer to bottom of page +.cf x y z mac - - print contents of header line (double + quotes around x, y before, z after) +cm num 0 - 0 if no cut marks, nonzero if cut marks +.cn x y z mac - - print computer/site name; same as .i +.dd div - i text of display +dg str *,- - footnote mark +dw str current - name of current day of week +dy str current - full date +.ed mac - b end display +.ef mac - b end footnote +.ei mac - b move left margin to the right +.er mac - - print error message +.et mac - b,i macro called at end of text +f0 str - - left bottom title +f1 num - i current font number +f1 str date,- - center bottom title +f2 num - i previous font number +f2 str - - right bottom title +fc num - i per-page footnote count +.fd mac - b,i drop footnotes +fg num - i gets fudge factor for footnote +fl num 5.5i - default footnote line length +.fn mac - - begin footnote +.fo mac - - bottom of page (footer) macro +fp num - i current location of trap for .fo macro +.fs mac - i print text/footnote separator +fs num - i position where footnote printing should begin +.fx mac - i collect overflow footnotes +.fy div - i text of footnote overflow +.fz mac - i move overflow footnotes from .fy to .tf +gs num - i used to be sure footnotes fit +h0 num 0 i current level 1 section number +h0 str - - left header title +h1 num 0 i current level 2 section number +h1 str - page - - center header title +h2 num 0 i current level 3 section number +h2 str - - right header title +h3 num 0 i current level 4 section number +.hd mac - i top of page (header) macro +.hf mac - - print header field name; same as .cf +.hn x mac - b numbered section; if present, x is level +hn num 0 i current level of numbering (temporary) +hs num 1v - default intra-section spacing +.hu mac - b unnumbered section header +.i x y z mac - - print x in font 2, y after, z before; + if no arguments, switch to font 2 +i1 num - i current indent +i2 num - i previous indent +id num 0 i 1 if in display, 0 otherwise +if num 0 i 1 if in footnote, 0 otherwise +.is x y z mac - - print x 2p bigger, y after, z before; + if no arguments, increase point size by 2p +it num 0 i 0 before .bt called, 1 after +l0 num 0 i leftmost position for left margin +l1 num - i first level of indent for left margin +l2 num - i second level of indent for left margin +l3 num - i third level of indent for left margin +l4 num - i fourth level of indent for left margin +l5 num - i fifth level of indent for left margin +l6 num - i sixth level of indent for left margin +l7 num - i seventh level of indent for left margin +l8 num - i eighth level of indent for left margin +l9 num - i ninth level of indent for left margin +li num 5n - paragraph indent +ll num 6i - default line length +lm num 0 i current level of indent for left margin +lo num - i previous level for left margin +.lp x y mac - b labelled paragraph; x is label, y indent +lq str ",`` - left double quotation marks +mo str current - name of current month +.mt mac - b title +mt num 1.5i+1v - distance of title from top of page +.ng x y z mac - - newsgroup name; same as .b +.nl mac - b reset point size to default +ns num 0 i if nonzero, .fn does not call .fs +.op x y z mac - - command option; same as .b +p1 num 0 i 1 after PDP-11(tm) footnote printed, + 0 before +.pa x y z mac - - print protocol appellation; same as .i +.pd x y mac - - print PDP-11(tm), footnote; x after, + y before +pd num 1v,.3v - intra-paragraph spacing +.pf mac - - print footer title +.pg x mac - b paragraph; if x is l, left justify +pi num 5n - default paragraph indent +po num 1.25i - default page offset +ps num 12p - default point size +.pt x mac - - print header; x is distance from top of + page +.qc x y z mac - - print name of control char; x is name, + in font 3, between <>, y after, z before +.qp x y z mac - - print char; same as .b +.r mac - - switch to font 1 +rg str - - registered trademark symbol +rq str ",'' - right double quotation marks +s1 num - i current point size +s2 num - i previous point size +.sd x mac - - start display; if x is c, center display +sf num - i 1 if center display, 0 otherwise +.si x num - - indent left margin by x (5n default) +.sm x y z mac - - print x 2p smaller, y after, z before; + if no arguments, decrease point size by 2p +.sn x mac - b space by x (1v default), enter nospace mode +.sr x mac - - enter spacemode, space by x (1v default) +t2 num 0 i 0 if little/no space, nonzero otherwise +.tf div - i text of footnotes +tm num 1i-.5v - height of top margin +tt num .5i-.5v - distance from top of page to header +.ux x y mac - - print UNIX(tm), footnote; x after, + y before +ux num 0 i 1 after UNIX(tm) footnote printed, + 0 before +v1 num - i current vertical spacing +v2 num - i previous vertical spacing +vr str - - current version of news +vs num 16p - default vertical spacing +vx num 0 i 1 after VAX(tm) footnote printed, + 0 before +.vx x y mac - - print VAX(tm), footnote; x after, + y before +ws str - - used to construct error message +.ya mac - - same as calling .yf, .yi, .ys, .yv +.yf mac - - restore fonts saved by .zf +.yi mac - - restore indents saved by .zi +Yr str - - current year +.ys mac - - restore point sizes saved by .zs +.yv mac - - restore vertical spacings saved by .zv +.za mac - - same as calling .zf, .zi, .zs, .zv +.zf mac - - save previous, current fonts +.zi mac - - save previous, current indents +.zs mac - - save previous, current point sizes +.zv mac - - save previous, current vertical spacings + + + + News Version B2.11 MN(7) From 6a768b0cbe5da7d53f59f361f8a3659b00d997c7 Mon Sep 17 00:00:00 2001 From: nhw_cron Date: Tue, 14 Jan 2020 11:17:43 -0500 Subject: [PATCH 05/24] This is cron-daily v1-Jan-14-2020. manpages updated: mnh.txt --- doc/mnh.txt | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 doc/mnh.txt diff --git a/doc/mnh.txt b/doc/mnh.txt new file mode 100644 index 000000000..b7e966065 --- /dev/null +++ b/doc/mnh.txt @@ -0,0 +1,59 @@ +MNH(7) Miscellaneous Information Manual MNH(7) + + + +NAME + mnh - additional text formatting macros for the NetHack Guidebook + +SYNOPSIS + make Guidebook + +DESCRIPTION + This package of nroff(1) and troff(1) macro definitions extends + tmac.n(7) for the NetHack Guidebook. This document should be read as + an addendum to the documentation for tmac.n. + + All -mnh macros, diversions, string registers, and number registers are + defined below. + +FILES + doc/tmac.nh + +SEE ALSO + mn(7) + +AUTHOR + Pat Rankin + +REQUESTS + In the Note column, b means the request causes a break, and i means the + macro, number register, string register, or diversion is internal and + should not be used for anything. In the What It Is column, div means + diversion, mac means macro, num means number register, and str means + string register. In the Initial Value column, a hyphen means no ini- + tial value is used, anything else is the initial value, and if two val- + ues are given, the first is for nroff and the second for troff. + +Macro What Initial Note Explanation +Name It Is Value +.BR mac - - hard line break with vertical padding inserted +bR num - i +.CC x y mac - - aligned one char key x with short definition y +CW num - i +CX num - i +CY num - i +CZ num - i +CZ num - i +.ED mac - - ends .SD +.PE mac - b labelled paragraph end +.PL x mac - b labelled paragraph label is x +.PS x mac - b labelled paragraph start for label the width of x +PX num - i +PY num - i +.SD x mac - - .sd with options c-center i-indent n-no indent +SF num - i +.UX mac - - .ux with updated trademark owner + + + + NETHACK MNH(7) From 0415a5a235bd0b8156e564d2f7e45c26b8d8f3d5 Mon Sep 17 00:00:00 2001 From: nhw_cron Date: Tue, 14 Jan 2020 11:17:43 -0500 Subject: [PATCH 06/24] This is cron-daily v1-Jan-14-2020. manpages updated: nethack.txt --- doc/nethack.txt | 142 ++++++++++++++++++++++++++---------------------- 1 file changed, 78 insertions(+), 64 deletions(-) diff --git a/doc/nethack.txt b/doc/nethack.txt index 9cd48ce3d..dfe694737 100644 --- a/doc/nethack.txt +++ b/doc/nethack.txt @@ -1,4 +1,4 @@ -NETHACK(6) NETHACK(6) +NETHACK(6) Games Manual NETHACK(6) @@ -7,113 +7,124 @@ NAME SYNOPSIS nethack [ -d directory ] [ -n ] [ -p profession ] [ -r race ] [ -[DX] ] - [ -u playername ] [ -dec ] [ -ibm ] [ --version[:paste] ] + [ -u playername ] [ -dec ] [ -ibm ] [ --showpaths ] [ --version[:paste] + ] nethack [ -d directory ] -s [ -v ] [ -p profession ] [ -r race ] [ playernames ] DESCRIPTION - NetHack is a display oriented Dungeons & Dragons(tm) - like game. The + NetHack is a display oriented Dungeons & Dragons(tm) - like game. The standard tty display and command structure resemble rogue. Other, more graphical display options exist for most platforms. - To get started you really only need to know two commands. The command - ? will give you a list of the available commands (as well as other - information) and the command / will identify the things you see on the + To get started you really only need to know two commands. The command + ? will give you a list of the available commands (as well as other + information) and the command / will identify the things you see on the screen. - To win the game (as opposed to merely playing to beat other people's - high scores) you must locate the Amulet of Yendor which is somewhere + To win the game (as opposed to merely playing to beat other people's + high scores) you must locate the Amulet of Yendor which is somewhere below the 20th level of the dungeon and get it out. Few people achieve this; most never do. Those who have go down in history as heroes among - heroes - and then they find ways of making the game even harder. See - the Guidebook section on Conduct if this game has gotten too easy for + heroes - and then they find ways of making the game even harder. See + the Guidebook section on Conduct if this game has gotten too easy for you. - When the game ends, whether by your dying, quitting, or escaping from - the caves, NetHack will give you (a fragment of) the list of top scor- - ers. The scoring is based on many aspects of your behavior, but a + When the game ends, whether by your dying, quitting, or escaping from + the caves, NetHack will give you (a fragment of) the list of top scor- + ers. The scoring is based on many aspects of your behavior, but a rough estimate is obtained by taking the amount of gold you've found in - the cave plus four times your (real) experience. Precious stones may - be worth a lot of gold when brought to the exit. There is a 10% + the cave plus four times your (real) experience. Precious stones may + be worth a lot of gold when brought to the exit. There is a 10% penalty for getting yourself killed. - The environment variable NETHACKOPTIONS can be used to initialize many - run-time options. The ? command provides a description of these + The environment variable NETHACKOPTIONS can be used to initialize many + run-time options. The ? command provides a description of these options and syntax. (The -dec and -ibm command line options are equiv- - alent to the decgraphics and ibmgraphics run-time options described - there, and are provided purely for convenience on systems supporting + alent to the decgraphics and ibmgraphics run-time options described + there, and are provided purely for convenience on systems supporting multiple types of terminals.) - Because the option list can be very long (particularly when specifying - graphics characters), options may also be included in a configuration - file. The default is located in your home directory and named - .nethackrc on Unix systems. On other systems, the default may be dif- - ferent, usually NetHack.cnf. On DOS or Windows, the name is - defaults.nh, while on the Macintosh or BeOS, it is NetHack Defaults. - The configuration file's location may be specified by setting NETHACK- - OPTIONS to a string consisting of an @ character followed by the file- + Because the option list can be very long (particularly when specifying + graphics characters), options may also be included in a configuration + file. The default is located in your home directory and named + .nethackrc on Unix systems. On other systems, the default may be dif- + ferent, usually NetHack.cnf. On DOS or Windows, the name is + defaults.nh, while on the Macintosh or BeOS, it is NetHack Defaults. + The configuration file's location may be specified by setting NETHACK- + OPTIONS to a string consisting of an @ character followed by the file- name. - The -u playername option supplies the answer to the question "Who are - you?". It overrides any name from the options or configuration file, - USER, LOGNAME, or getlogin(), which will otherwise be tried in order. - If none of these provides a useful name, the player will be asked for + The -u playername option supplies the answer to the question "Who are + you?". It overrides any name from the options or configuration file, + USER, LOGNAME, or getlogin(), which will otherwise be tried in order. + If none of these provides a useful name, the player will be asked for one. Player names (in conjunction with uids) are used to identify save files, so you can have several saved games under different names. Con- - versely, you must use the appropriate player name to restore a saved + versely, you must use the appropriate player name to restore a saved game. A playername suffix can be used to specify the profession, race, align- ment and/or gender of the character. The full syntax of the playername - that includes a suffix is "name-ppp-rrr-aaa-ggg". "ppp" are at least - the first three letters of the profession (this can also be specified - using a separate -p profession option). "rrr" are at least the first + that includes a suffix is "name-ppp-rrr-aaa-ggg". "ppp" are at least + the first three letters of the profession (this can also be specified + using a separate -p profession option). "rrr" are at least the first three letters of the character's race (this can also be specified using - a separate -r race option). "aaa" are at last the first three letters - of the character's alignment, and "ggg" are at least the first three - letters of the character's gender. Any of the parts of the suffix may + a separate -r race option). "aaa" are at least the first three letters + of the character's alignment, and "ggg" are at least the first three + letters of the character's gender. Any of the parts of the suffix may be left out. - -p profession can be used to determine the character profession, also - known as the role. You can specify either the male or female name for - the character role, or the first three characters of the role as an + -p profession can be used to determine the character profession, also + known as the role. You can specify either the male or female name for + the character role, or the first three characters of the role as an abbreviation. -p @ has been retained to explicitly request that a ran- - dom role be chosen. It may need to be quoted with a backslash (\@) if - @ is the "kill" character (see "stty") for the terminal, in order to + dom role be chosen. It may need to be quoted with a backslash (\@) if + @ is the "kill" character (see "stty") for the terminal, in order to prevent the current input line from being cleared. Likewise, -r race can be used to explicitly request that a race be cho- sen. - Leaving out any of these characteristics will result in you being + Leaving out any of these characteristics will result in you being prompted during the game startup for the information. - - The -s option alone will print out the list of your scores on the cur- - rent version. An immediately following -v reports on all versions + The -s option alone will print out the list of your scores on the cur- + rent version. An immediately following -v reports on all versions present in the score file. The -s may also be followed by arguments -p - and -r to print the scores of particular roles and races only. It may + and -r to print the scores of particular roles and races only. It may also be followed by one or more player names to print the scores of the - players mentioned, by 'all' to print out all scores, or by a number to + players mentioned, by 'all' to print out all scores, or by a number to print that many top scores. The -n option suppresses printing of any news from the game administra- tor. - The -D or -X option will start the game in a special non-scoring dis- - covery mode. -D will, if the player is the game administrator, start + The -D or -X option will start the game in a special non-scoring dis- + covery mode. -D will, if the player is the game administrator, start in debugging (wizard) mode instead. The -d option, which must be the first argument if it appears, supplies - a directory which is to serve as the playground. It overrides the - value from NETHACKDIR, HACKDIR, or the directory specified by the game - administrator during compilation (usually /usr/games/lib/nethackdir). - This option is usually only useful to the game administrator. The + a directory which is to serve as the playground. It overrides the + value from NETHACKDIR, HACKDIR, or the directory specified by the game + administrator during compilation (usually /usr/games/lib/nethackdir). + This option is usually only useful to the game administrator. The playground must contain several auxiliary files such as help files, the list of top scorers, and a subdirectory save where games are saved. + --showpaths can be used to cause NetHack to show where it is expecting + to find various configuration files. + + --version can be used to cause NetHack to show the version information + it was compiled with, then exit. That will include the git commit hash + if the information was available when the game was compiled. On some + platforms, such as windows and macosx, a variation --version:paste can + be used to cause NetHack to show the version information, then exit, + while also leaving a copy of the version information in the paste buf- + fer or clipboard for potential insertion into things like bug reports. + AUTHORS Jay Fenlason (+ Kenny Woodland, Mike Thome and Jon Payne) wrote the original hack, very much like rogue (but full of bugs). @@ -143,7 +154,7 @@ FILES nethack The program itself. data, oracles, rumors Data files used by NetHack. - quest.dat, bogusmon More data files. + bogusmon another data file. engrave, epitaph, tribute Still more data files. symbols Data file holding sets of specifications for how to display monsters, objects, and @@ -152,8 +163,8 @@ FILES build-time option settings. help, hh Help data files. cmdhelp, opthelp, wizhelp More help data files. - *.lev Predefined special levels. - dungeon Control file for special levels. + *.lua Predefined special levels, dungeon control + for special levels, quest texts history A short history of NetHack. license Rules governing redistribution. record The list of top scorers. @@ -181,8 +192,8 @@ FILES program is built with 'SYSCF' option enabled, ignored if not. - The location of 'sysconf' is specified at build time and can't be - changed except by updating source file "config.h" and rebuilding the + The location of 'sysconf' is specified at build time and can't be + changed except by updating source file "config.h" and rebuilding the program. In a perfect world, 'paniclog' would remain empty. @@ -200,22 +211,25 @@ ENVIRONMENT NETHACKOPTIONS String predefining several NetHack options. - If the same option is specified in both NETHACKOPTIONS and .nethackrc, + If the same option is specified in both NETHACKOPTIONS and .nethackrc, the value assigned in NETHACKOPTIONS takes precedence. SHOPTYPE and SPLEVTYPE can be used in debugging (wizard) mode. DEBUGFILES can be used if the program was built with 'DEBUG' enabled. SEE ALSO - dgn_comp(6), lev_comp(6), recover(6) + recover(6) BUGS Probably infinite. - +COPYRIGHT + This file is Copyright (C) Robert Patrick Rankin and was last modified + 2019/09/15 (version NetHack-3.6:1.16). NetHack may be freely redis- + tributed. See license for details. Dungeons & Dragons is a Trademark of Wizards of the Coast, Inc. - 7 December 2015 NETHACK(6) +NETHACK 2 February 2018 NETHACK(6) From 2e570e03e90a9451c1200509c62916cfcc3e64af Mon Sep 17 00:00:00 2001 From: nhw_cron Date: Tue, 14 Jan 2020 11:17:43 -0500 Subject: [PATCH 07/24] This is cron-daily v1-Jan-14-2020. manpages updated: recover.txt --- doc/recover.txt | 173 ++++++++++++++++++------------------------------ 1 file changed, 65 insertions(+), 108 deletions(-) diff --git a/doc/recover.txt b/doc/recover.txt index 80eeadb51..c2d4af038 100644 --- a/doc/recover.txt +++ b/doc/recover.txt @@ -1,132 +1,89 @@ - - - -RECOVER(6) 1993 RECOVER(6) +RECOVER(6) Games Manual RECOVER(6) NAME - recover - recover a NetHack game interrupted by disaster + recover - recover a NetHack game interrupted by disaster SYNOPSIS - recover [ -d directory ] base1 base2 ... + recover [ -d directory ] base1 base2 ... DESCRIPTION - Occasionally, a NetHack game will be interrupted by disaster - when the game or the system crashes. Prior to NetHack v3.1, - these games were lost because various information like the - player's inventory was kept only in memory. Now, all per- - tinent information can be written out to disk, so such games - can be recovered at the point of the last level change. + Occasionally, a NetHack game will be interrupted by disaster when the + game or the system crashes. Prior to NetHack v3.1, these games were + lost because various information like the player's inventory was kept + only in memory. Now, all pertinent information can be written out to + disk, so such games can be recovered at the point of the last level + change. - The base options tell recover which files to process. Each - base option specifies recovery of a separate game. + The base options tell recover which files to process. Each base option + specifies recovery of a separate game. - The -d option, which must be the first argument if it - appears, supplies a directory which is the NetHack play- - ground. It overrides the value from NETHACKDIR, HACKDIR, or - the directory specified by the game administrator during - compilation (usually /usr/games/lib/nethackdir). + The -d option, which must be the first argument if it appears, supplies + a directory which is the NetHack playground. It overrides the value + from NETHACKDIR, HACKDIR, or the directory specified by the game admin- + istrator during compilation (usually /usr/games/lib/nethackdir). - For recovery to be possible, nethack must have been compiled - with the INSURANCE option, and the run-time option check- - point must also have been on. NetHack normally writes out - files for levels as the player leaves them, so they will be - ready for return visits. When checkpointing, NetHack also - writes out the level entered and the current game state on - every level change. This naturally slows level changes down - somewhat. + ^?ALLDOCS For recovery to be possible, nethack must have been compiled + with the INSURANCE option, and the run-time option checkpoint must also + have been on. ^: ^?INSURANCE For recovery to be possible, nethack must + have been compiled with the INSURANCE option (this configuration was), + and the run-time option checkpoint must also have been on. ^: This + configuration of nethack was created without support for recovery. ^. + ^. NetHack normally writes out files for levels as the player leaves + them, so they will be ready for return visits. When checkpointing, + NetHack also writes out the level entered and the current game state on + every level change. This naturally slows level changes down somewhat. - The level file names are of the form base.nn, where nn is an - internal bookkeeping number for the level. The file base.0 - is used for game identity, locking, and, when checkpointing, - for the game state. Various OSes use different strategies - for constructing the base name. Microcomputers use the - character name, possibly truncated and modified to be a - legal filename on that system. Multi-user systems use the - (modified) character name prefixed by a user number to avoid - conflicts, or "xlock" if the number of concurrent players is - being limited. It may be necessary to look in the play- - ground to find the correct base name of the interrupted - game. recover will transform these level files into a save - file of the same name as nethack would have used. + The level file names are of the form base.nn, where nn is an internal + bookkeeping number for the level. The file base.0 is used for game + identity, locking, and, when checkpointing, for the game state. Vari- + ous OSes use different strategies for constructing the base name. + Microcomputers use the character name, possibly truncated and modified + to be a legal filename on that system. Multi-user systems use the + (modified) character name prefixed by a user number to avoid conflicts, + or "xlock" if the number of concurrent players is being limited. It + may be necessary to look in the playground to find the correct base + name of the interrupted game. recover will transform these level files + into a save file of the same name as nethack would have used. - Since recover must be able to read and delete files from the - playground and create files in the save directory, it has - interesting interactions with game security. Giving ordi- - nary players access to recover through setuid or setgid is - tantamount to leaving the playground world-writable, with - respect to both cheating and messing up other players. For + Since recover must be able to read and delete files from the playground + and create files in the save directory, it has interesting interactions + with game security. Giving ordinary players access to recover through + setuid or setgid is tantamount to leaving the playground world- + writable, with respect to both cheating and messing up other players. + For a single-user system, this of course does not change anything, so + some of the microcomputer ports install recover by default. - - -January Last change: 9 1 - - - - - - -RECOVER(6) 1993 RECOVER(6) - - - - a single-user system, this of course does not change any- - thing, so some of the microcomputer ports install recover by - default. - - For a multi-user system, the game administrator may want to - arrange for all .0 files in the playground to be fed to - recover when the host machine boots, and handle game crashes - individually. If the user population is sufficiently - trustworthy, recover can be installed with the same permis- - sions the nethack executable has. In either case, recover - is easily compiled from the distribution utility directory. + For a multi-user system, the game administrator may want to arrange for + all .0 files in the playground to be fed to recover when the host + machine boots, and handle game crashes individually. If the user popu- + lation is sufficiently trustworthy, recover can be installed with the + same permissions the nethack executable has. In either case, recover + is easily compiled from the distribution utility directory. NOTES - Like nethack itself, recover will overwrite existing save- - files of the same name. Savefiles created by recover are - uncompressed; they may be compressed afterwards if desired, - but even a compression-using nethack will find them in the - uncompressed form. + Like nethack itself, recover will overwrite existing savefiles of the + same name. Savefiles created by recover are uncompressed; they may be + compressed afterwards if desired, but even a compression-using nethack + will find them in the uncompressed form. SEE ALSO - nethack(6) + nethack(6) BUGS - recover makes no attempt to find out if a base name speci- - fies a game in progress. If multiple machines share a play- - ground, this would be impossible to determine. + recover makes no attempt to find out if a base name specifies a game in + progress. If multiple machines share a playground, this would be + impossible to determine. - recover should be taught to use the nethack playground lock- - ing mechanism to avoid conflicts. - - - - - - - - - - - - - - - - - - - - - - - - - - -January Last change: 9 2 + recover should be taught to use the nethack playground locking mecha- + nism to avoid conflicts. + +COPYRIGHT + This file is Copyright (C) Kenneth Lorber and was last modified + 2018/04/25 (version NetHack-3.6.0:1.9). NetHack may be freely redis- + tributed. See license for details. +NETHACK 14 December 2015 RECOVER(6) From 2f52fd3db3361347cf2df3a2d34c3667c4fce5f0 Mon Sep 17 00:00:00 2001 From: nhw_cron Date: Tue, 14 Jan 2020 11:17:46 -0500 Subject: [PATCH 08/24] This is cron-daily v1-Jan-14-2020. files updated: Files --- Files | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Files b/Files index 66e0b84bd..ff31522e2 100644 --- a/Files +++ b/Files @@ -72,8 +72,9 @@ fixes32.1 fixes32.2 fixes32.3 fixes33.0 fixes33.1 fixes34.0 fixes34.1 fixes34.2 fixes34.3 fixes35.0 fixes36.0 fixes36.1 fixes36.2 fixes36.3 fixes36.4 fixes36.5 fixes37.0 fixesXX.X makedefs.6 makedefs.txt -mn.7 mnh.7 nethack.6 nethack.txt recover.6 -recover.txt tmac.n tmac.nh window.doc +mn.7 mn.txt mnh.7 mnh.txt nethack.6 +nethack.txt recover.6 recover.txt tmac.n tmac.nh +window.doc include: (files for GEM versions) From fe4bdae7407b56dbbc3fbe536c0292b6e25d26f8 Mon Sep 17 00:00:00 2001 From: nhmall Date: Tue, 14 Jan 2020 23:50:06 -0500 Subject: [PATCH 09/24] closes #282 closes #282 --- doc/fixes37.0 | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 988af40ac..f027001a4 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -123,8 +123,6 @@ NetHack Community Patches (or Variation) Included ------------------------------------------------- hallucinatory trap names from github pull request #174 autounlock feature originally from unnethack in github pull request #228 -applying a candelabrum with no candles gives a tip (github #265) -candelabrum now reads "(n of 7 candles attached)" (github #265) replace "You feel cold" message for freezing unseen door (github #265) applying a candelabrum with no candles gives a tip (github #265) candelabrum now reads "(n of 7 candles attached)" (github #265) From 1a89e44e19e755f2c499f62d0cd793f0fc52ea8f Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 17 Jan 2020 02:43:32 -0800 Subject: [PATCH 10/24] fix #K188 - trying to move past edge of level Trying to move into a wall or solid rock fails and doesn't do anything (unless the 'mention_walls' option is On) and doesn't use a turn, and trying to move off the edge of the map window also doesn't do anything (except for 'mention_walls') but that did use a turn. Don't. --- doc/fixes37.0 | 3 ++- src/hack.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/fixes37.0 b/doc/fixes37.0 index f027001a4..e19b8c84c 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.66 $ $NHDT-Date: 1578947634 2020/01/13 20:33:54 $ +$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.68 $ $NHDT-Date: 1579257808 2020/01/17 10:43:28 $ General Fixes and Modified Features ----------------------------------- @@ -45,6 +45,7 @@ walking out of tethered-to-buried-object trap condition was supposed to when poly'd into a giant and moving onto a boulder's spot, message given was confused about whether autopickup would occur so could be misleading random role selection wasn't honoring unwanted alignment(s) properly +if at the edge of the map window, trying to move farther fails but used a turn Fixes to 3.7.0-x Problems that Were Exposed Via git Repository diff --git a/src/hack.c b/src/hack.c index 06a99cf88..c1eb4f35c 100644 --- a/src/hack.c +++ b/src/hack.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 hack.c $NHDT-Date: 1578916008 2020/01/13 11:46:48 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.243 $ */ +/* NetHack 3.6 hack.c $NHDT-Date: 1579257808 2020/01/17 10:43:28 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.244 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1511,6 +1511,7 @@ domove_core() directionname(xytod(dx, dy))); } nomul(0); + g.context.move = 0; return; } if (((trap = t_at(x, y)) && trap->tseen) From d19cab4d98dc341e0432c0037e47e56efaede6eb Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 17 Jan 2020 04:03:14 -0800 Subject: [PATCH 11/24] implicit_uncursed, mention_walls Move 'implicit_uncursed' and 'mention_walls' from iflags to flags to make their current setting persist across save/restore. Invalidates existing save files. --- doc/Guidebook.mn | 9 +++++++-- doc/Guidebook.tex | 10 ++++++++-- doc/fixes37.0 | 4 +++- include/flag.h | 6 +++--- include/patchlevel.h | 4 ++-- src/hack.c | 28 +++++++++++++--------------- src/objnam.c | 4 ++-- src/options.c | 8 ++++---- 8 files changed, 42 insertions(+), 31 deletions(-) diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index f823faf06..d6594f328 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -1,4 +1,4 @@ -.\" $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.346 $ $NHDT-Date: 1578448653 2020/01/08 01:57:33 $ +.\" $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.347 $ $NHDT-Date: 1579262524 2020/01/17 12:02:04 $ .\" .\" This is an excerpt from the 'roff' man page from the 'groff' package. .\" NetHack's Guidebook.mn currently does *not* adhere to these guidelines. @@ -3160,7 +3160,11 @@ Cannot be set with the \(oqO\(cq command. .lp ignintr Ignore interrupt signals, including breaks (default off). Persistent. .lp implicit_uncursed -Omit "uncursed" from inventory lists, if possible (default on). +Omit \(lquncursed\(rq from object descriptions when it can be deduced from +other aspects of the description (default on). +Persistent. +.lp "" +If you use menu coloring, you may want to turn this off. .lp legacy Display an introductory message when starting the game (default on). Persistent. @@ -3180,6 +3184,7 @@ An obsolete synonym for \(lqgender:male\(rq. Cannot be set with the \(oqO\(cq command. .lp mention_walls Give feedback when walking against a wall (default off). +Persistent. .lp menucolors Enable coloring menu lines (default off). See \(lqConfiguring Menu Colors\(rq on how to configure the colors. diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index 626eb6490..649b09d80 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -3436,6 +3436,7 @@ Visually distinguish pets from similar animals (default off). The behavior of this option depends on the type of windowing you use. In text windowing, text highlighting or inverse video is often used; with tiles, generally displays a heart symbol near pets. + %.lp "" With the curses interface, the {\it petattr\/} option controls how to highlight pets and setting it will turn the @@ -3460,7 +3461,12 @@ Only available for TTY and Windows GUI, and only when statushilites is on. Ignore interrupt signals, including breaks (default off). Persistent. %.lp \item[\ib{implicit\verb+_+uncursed}] -Omit ``uncursed'' from inventory lists, if possible (default on). +Omit ``uncursed'' from object descriptions when it can be deduced from +other aspects of the description (default on). +Persistent. + +%.lp "" +If you use menu coloring, you may want to turn this off. %.lp \item[\ib{legacy}] Display an introductory message when starting the game (default on). @@ -3484,7 +3490,7 @@ An obsolete synonym for ``{\tt gender:male}''. Cannot be set with the `{\tt O}' command. %.lp \item[\ib{mention\verb+_+walls}] -Give feedback when walking against a wall (default off). +Give feedback when walking against a wall (default off). Persistent. %.lp \item[\ib{menucolors}] Enable coloring menu lines (default off). diff --git a/doc/fixes37.0 b/doc/fixes37.0 index e19b8c84c..c9908ed92 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.68 $ $NHDT-Date: 1579257808 2020/01/17 10:43:28 $ +$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.69 $ $NHDT-Date: 1579261284 2020/01/17 11:41:24 $ General Fixes and Modified Features ----------------------------------- @@ -114,6 +114,8 @@ tiny chance for randomly created spellbooks to be Discworld novels instead of having only one in the first book or scroll shop created (won't occur in hero's initial inventory or NPC priest inventory or be bestowed as a prayer boon or be found in statues) +'goldX', 'implicit_uncursed', and 'mention_walls' options changed to be + persistent across save/restore Platform- and/or Interface-Specific New Features diff --git a/include/flag.h b/include/flag.h index c94ae1549..0cfd3dabc 100644 --- a/include/flag.h +++ b/include/flag.h @@ -1,4 +1,4 @@ -/* NetHack 3.7 flag.h $NHDT-Date: 1577050470 2019/12/22 21:34:30 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.167 $ */ +/* NetHack 3.7 flag.h $NHDT-Date: 1579261284 2020/01/17 11:41:24 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.172 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2006. */ /* NetHack may be freely redistributed. See license for details. */ @@ -36,10 +36,12 @@ struct flag { boolean goldX; /* for BUCX filtering, whether gold is X or U */ boolean help; /* look in data file for info about stuff */ boolean ignintr; /* ignore interrupts */ + boolean implicit_uncursed; /* maybe omit "uncursed" status in inventory */ boolean ins_chkpt; /* checkpoint as appropriate; INSURANCE */ boolean invlet_constant; /* let objects keep their inventory symbol */ boolean legacy; /* print game entry "story" */ boolean lit_corridor; /* show a dark corr as lit if it is in sight */ + boolean mention_walls; /* give feedback when bumping walls */ boolean nap; /* `timed_delay' option for display effects */ boolean null; /* OK to send nulls to the terminal */ boolean pickup; /* whether you pickup or move and look */ @@ -258,8 +260,6 @@ struct instance_flags { boolean echo; /* 1 to echo characters */ boolean force_invmenu; /* always menu when handling inventory */ boolean hilite_pile; /* mark piles of objects with a hilite */ - boolean implicit_uncursed; /* maybe omit "uncursed" status in inventory */ - boolean mention_walls; /* give feedback when bumping walls */ boolean menu_head_objsym; /* Show obj symbol in menu headings */ boolean menu_overlay; /* Draw menus over the map */ boolean menu_requested; /* Flag for overloaded use of 'm' prefix diff --git a/include/patchlevel.h b/include/patchlevel.h index e84ab9d72..50eccc543 100644 --- a/include/patchlevel.h +++ b/include/patchlevel.h @@ -1,4 +1,4 @@ -/* NetHack 3.7 patchlevel.h $NHDT-Date: 1577050471 2019/12/22 21:34:31 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.142 $ */ +/* NetHack 3.7 patchlevel.h $NHDT-Date: 1579261287 2020/01/17 11:41:27 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.148 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -14,7 +14,7 @@ * Incrementing EDITLEVEL can be used to force invalidation of old bones * and save files. */ -#define EDITLEVEL 9 +#define EDITLEVEL 10 #define COPYRIGHT_BANNER_A "NetHack, Copyright 1985-2020" #define COPYRIGHT_BANNER_B \ diff --git a/src/hack.c b/src/hack.c index c1eb4f35c..84639f63e 100644 --- a/src/hack.c +++ b/src/hack.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 hack.c $NHDT-Date: 1579257808 2020/01/17 10:43:28 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.244 $ */ +/* NetHack 3.6 hack.c $NHDT-Date: 1579261288 2020/01/17 11:41:28 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.245 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -750,7 +750,7 @@ int mode; return FALSE; } if (!(Passes_walls || passes_bars(g.youmonst.data))) { - if (mode == DO_MOVE && iflags.mention_walls) + if (mode == DO_MOVE && flags.mention_walls) You("cannot pass through the bars."); return FALSE; } @@ -772,7 +772,7 @@ int mode; else if (Passes_walls && !may_passwall(x, y) && In_sokoban(&u.uz)) pline_The("Sokoban walls resist your ability."); - else if (iflags.mention_walls) + else if (flags.mention_walls) pline("It's %s.", (IS_WALL(tmpr->typ) || tmpr->typ == SDOOR) ? "a wall" : IS_TREE(tmpr->typ) ? "a tree" @@ -842,7 +842,7 @@ int mode; if (mode == DO_MOVE) { if (Blind) feel_location(x, y); - if (Underwater || iflags.mention_walls) + if (Underwater || flags.mention_walls) You_cant("move diagonally into an intact doorway."); } return FALSE; @@ -896,7 +896,7 @@ int mode; if (dx && dy && !Passes_walls && IS_DOOR(ust->typ) && (!doorless_door(ux, uy) || block_entry(x, y))) { /* Can't move at a diagonal out of a doorway with door. */ - if (mode == DO_MOVE && iflags.mention_walls) + if (mode == DO_MOVE && flags.mention_walls) You_cant("move diagonally out of an intact doorway."); return FALSE; } @@ -904,7 +904,7 @@ int mode; if (sobj_at(BOULDER, x, y) && (Sokoban || !Passes_walls)) { if (!(Blind || Hallucination) && (g.context.run >= 2) && mode != TEST_TRAV) { - if (mode == DO_MOVE && iflags.mention_walls) + if (mode == DO_MOVE && flags.mention_walls) pline("A boulder blocks your path."); return FALSE; } @@ -1495,7 +1495,7 @@ domove_core() } } if (!isok(x, y)) { - if (iflags.mention_walls) { + if (flags.mention_walls) { int dx = u.dx, dy = u.dy; if (dx && dy) { /* diagonal */ @@ -1518,7 +1518,7 @@ domove_core() || (Blind && !Levitation && !Flying && !is_clinger(g.youmonst.data) && is_pool_or_lava(x, y) && levl[x][y].seenv)) { if (g.context.run >= 2) { - if (iflags.mention_walls) { + if (flags.mention_walls) { if (trap && trap->tseen) { You("stop in front of %s.", an(trapname(trap->ttyp, FALSE))); @@ -2729,7 +2729,7 @@ lookaround() if ((g.context.run != 1 && !mtmp->mtame) || (x == u.ux + u.dx && y == u.uy + u.dy && !g.context.travel)) { - if (iflags.mention_walls) + if (flags.mention_walls) pline("%s blocks your path.", upstart(a_monnam(mtmp))); goto stop; } @@ -2747,7 +2747,7 @@ lookaround() if (x != u.ux && y != u.uy) continue; if (g.context.run != 1) { - if (iflags.mention_walls) + if (flags.mention_walls) You("stop in front of the door."); goto stop; } @@ -2776,11 +2776,9 @@ lookaround() if (g.context.run == 1) goto bcorr; /* if you must */ if (x == u.ux + u.dx && y == u.uy + u.dy) { - if (iflags.mention_walls) { - + if (flags.mention_walls) You("stop in front of %s.", an(trapname(trap->ttyp, FALSE))); - } goto stop; } continue; @@ -2794,7 +2792,7 @@ lookaround() * to test boots by trying to SHIFT-direction * into a pool and seeing if the game allowed it */ - if (iflags.mention_walls) + if (flags.mention_walls) You("stop at the edge of the %s.", hliquid(is_pool(x,y) ? "water" : "lava")); goto stop; @@ -2817,7 +2815,7 @@ lookaround() } /* end for loops */ if (corrct > 1 && g.context.run == 2) { - if (iflags.mention_walls) + if (flags.mention_walls) pline_The("corridor widens here."); goto stop; } diff --git a/src/objnam.c b/src/objnam.c index 102dbb03e..b2897c906 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 objnam.c $NHDT-Date: 1578896203 2020/01/13 06:16:43 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.287 $ */ +/* NetHack 3.7 objnam.c $NHDT-Date: 1579261291 2020/01/17 11:41:31 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.288 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2011. */ /* NetHack may be freely redistributed. See license for details. */ @@ -998,7 +998,7 @@ unsigned doname_flags; Strcat(prefix, "cursed "); else if (obj->blessed) Strcat(prefix, "blessed "); - else if (!iflags.implicit_uncursed + else if (!flags.implicit_uncursed /* For most items with charges or +/-, if you know how many * charges are left or what the +/- is, then you must have * totally identified the item, so "uncursed" is unnecessary, diff --git a/src/options.c b/src/options.c index f27eaf2e1..0fc52a0af 100644 --- a/src/options.c +++ b/src/options.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 options.c $NHDT-Date: 1577050473 2019/12/22 21:34:33 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.422 $ */ +/* NetHack 3.7 options.c $NHDT-Date: 1579261293 2020/01/17 11:41:33 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.428 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2008. */ /* NetHack may be freely redistributed. See license for details. */ @@ -146,7 +146,7 @@ static const struct Bool_Opt { #else { "ignintr", (boolean *) 0, FALSE, SET_IN_FILE }, #endif - { "implicit_uncursed", &iflags.implicit_uncursed, TRUE, SET_IN_GAME }, + { "implicit_uncursed", &flags.implicit_uncursed, TRUE, SET_IN_GAME }, { "large_font", &iflags.obsolete, FALSE, SET_IN_FILE }, /* OBSOLETE */ { "legacy", &flags.legacy, TRUE, DISP_IN_GAME }, { "lit_corridor", &flags.lit_corridor, FALSE, SET_IN_GAME }, @@ -156,7 +156,7 @@ static const struct Bool_Opt { #else { "mail", (boolean *) 0, TRUE, SET_IN_FILE }, #endif - { "mention_walls", &iflags.mention_walls, FALSE, SET_IN_GAME }, + { "mention_walls", &flags.mention_walls, FALSE, SET_IN_GAME }, { "menucolors", &iflags.use_menu_color, FALSE, SET_IN_GAME }, /* for menu debugging only*/ { "menu_tab_sep", &iflags.menu_tab_sep, FALSE, SET_IN_WIZGAME }, @@ -4052,7 +4052,7 @@ boolean tinitial, tfrom_file; g.context.botl = TRUE; } else if (boolopt[i].addr == &flags.invlet_constant || boolopt[i].addr == &flags.sortpack - || boolopt[i].addr == &iflags.implicit_uncursed) { + || boolopt[i].addr == &flags.implicit_uncursed) { if (!flags.invlet_constant) reassign(); update_inventory(); From 3f0b9f26c530288adad93cd0bbebccd8a1230bfa Mon Sep 17 00:00:00 2001 From: PatR Date: Sat, 18 Jan 2020 18:47:01 -0800 Subject: [PATCH 12/24] losing via #offer to Moloch Recently added "you hear an invisible choir chant in Latin ..." is jarring. Unfortunately, something like "in an archaic language" would make the message too long so just take out "in Latin". Also a few reformatting bits for pray.c. --- src/pray.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/pray.c b/src/pray.c index 173996c09..3d4045141 100644 --- a/src/pray.c +++ b/src/pray.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 pray.c $NHDT-Date: 1578895347 2020/01/13 06:02:27 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.138 $ */ +/* NetHack 3.6 pray.c $NHDT-Date: 1579401997 2020/01/19 02:46:37 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.139 $ */ /* Copyright (c) Benson I. Margulies, Mike Stephenson, Steve Linhart, 1989. */ /* NetHack may be freely redistributed. See license for details. */ @@ -484,7 +484,7 @@ int trouble; what = rightglow; else if (otmp == uleft) what = leftglow; - decurse: + decurse: if (!otmp) { impossible("fix_worst_trouble: nothing to uncurse."); return; @@ -1496,7 +1496,7 @@ dosacrifice() if (otmp->otyp == AMULET_OF_YENDOR) { if (!highaltar) { - too_soon: + too_soon: if (altaralign == A_NONE && Inhell) /* hero has left Moloch's Sanctum so is in the process of getting away with the Amulet (outside of Gehennom, @@ -1526,7 +1526,8 @@ dosacrifice() /* Moloch's high altar */ if (u.ualign.record > -99) u.ualign.record = -99; - pline("An invisible choir chants in Latin, and you are bathed in darkness..."); + pline( + "An invisible choir chants, and you are bathed in darkness..."); /*[apparently shrug/snarl can be sensed without being seen]*/ pline("%s shrugs and retains dominion over %s,", Moloch, u_gname()); @@ -1593,7 +1594,7 @@ dosacrifice() } if (altaralign != u.ualign.type && highaltar) { - desecrate_high_altar: + desecrate_high_altar: /* * REAL BAD NEWS!!! High altars cannot be converted. Even an attempt * gets the god who owns it truly pissed off. @@ -1830,7 +1831,8 @@ boolean praying; /* false means no messages should be given */ } if (is_undead(g.youmonst.data) && !Inhell - && (g.p_aligntyp == A_LAWFUL || (g.p_aligntyp == A_NEUTRAL && !rn2(10)))) + && (g.p_aligntyp == A_LAWFUL + || (g.p_aligntyp == A_NEUTRAL && !rn2(10)))) g.p_type = -1; /* Note: when !praying, the random factor for neutrals makes the return value a non-deterministic approximation for enlightenment. From 2ba3fa9240ee9b353b2dacb904c58c892602cfa2 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Wed, 15 Jan 2020 20:17:02 +0200 Subject: [PATCH 13/24] Fix warning on nonexistent quest.lua text Cavemen don't have goal_alt message - before lua, that one fell through into goal_next message, but now it tried to load the "common" message. Add ability to define message fallbacks, and make goal_next the fallback for goal_alt. Also prevent issuing quest.lua errors twice. --- dat/quest.lua | 6 +++++- src/questpgr.c | 47 ++++++++++++++++++++++++++++++++++++----------- 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/dat/quest.lua b/dat/quest.lua index 891556987..7e484df1d 100644 --- a/dat/quest.lua +++ b/dat/quest.lua @@ -4,7 +4,7 @@ -- - export the quest string replacements to lua, instead of %H etc -- - allow checking if hero is carrying item (see comments for %Cp Arc 00042) -- - fold quest_portal, quest_portal_again, quest_portal_demand into one --- - some roles have no goal_alt, fold into goal_next? +-- - write tests to check questtext validity? -- - qt_pager hack(?): if (qt_msg->delivery == 'p' && strcmp(windowprocs.name, "X11")) @@ -25,6 +25,10 @@ questtext = { + -- If a role doesn't have a specific message, try a fallback + msg_fallbacks = { + goal_alt = "goal_next" + }, common = { TEST_PATTERN = { output = "text", diff --git a/src/questpgr.c b/src/questpgr.c index 85c272557..5df059fd1 100644 --- a/src/questpgr.c +++ b/src/questpgr.c @@ -432,9 +432,10 @@ boolean common UNUSED; } boolean -com_pager_core(section, msgid) +com_pager_core(section, msgid, showerror) const char *section; const char *msgid; +boolean showerror; { const char *const howtoput[] = { "pline", "window", "text", "menu", "default", NULL }; const int howtoput2i[] = { 1, 2, 2, 3, 0, 0 }; @@ -442,6 +443,7 @@ const char *msgid; lua_State *L; char *synopsis; char *text; + char *fallback_msgid = NULL; if (skip_pager(TRUE)) return FALSE; @@ -449,7 +451,8 @@ const char *msgid; L = nhl_init(); if (!nhl_loadlua(L, QTEXT_FILE)) { - impossible("com_pager: %s not found.", QTEXT_FILE); + if (showerror) + impossible("com_pager: %s not found.", QTEXT_FILE); lua_close(L); return FALSE; } @@ -457,21 +460,40 @@ const char *msgid; lua_settop(L, 0); lua_getglobal(L, "questtext"); if (!lua_istable(L, -1)) { - impossible("com_pager: questtext in %s is not a lua table", QTEXT_FILE); + if (showerror) + impossible("com_pager: questtext in %s is not a lua table", + QTEXT_FILE); lua_close(L); return FALSE; } lua_getfield(L, -1, section); if (!lua_istable(L, -1)) { - impossible("com_pager: questtext[%s] in %s is not a lua table", section, QTEXT_FILE); + if (showerror) + impossible("com_pager: questtext[%s] in %s is not a lua table", + section, QTEXT_FILE); lua_close(L); return FALSE; } - lua_getfield(L, -1, msgid); +tryagain: + lua_getfield(L, -1, fallback_msgid ? fallback_msgid : msgid); if (!lua_istable(L, -1)) { - impossible("com_pager: questtext[%s][%s] in %s is not a lua table", section, msgid, QTEXT_FILE); + if (!fallback_msgid) { + /* Do we have questtxt[msg_fallbacks][]? */ + lua_getfield(L, -3, "msg_fallbacks"); + if (lua_istable(L, -1)) { + fallback_msgid = get_table_str_opt(L, msgid, NULL); + lua_pop(L, 2); + if (fallback_msgid) + goto tryagain; + } + } + + if (showerror) + impossible("com_pager: questtext[%s][%s] in %s is not a lua table", + section, msgid, QTEXT_FILE); + free(fallback_msgid); lua_close(L); return FALSE; } @@ -487,9 +509,11 @@ const char *msgid; nelems = (int) lua_tointeger(L, -1); lua_pop(L, 1); if (nelems < 2) { - impossible( - "com_pager: questtext[%s][%s] in %s in not an array of strings", + if (showerror) + impossible( + "com_pager: questtext[%s][%s] in %s in not an array of strings", section, msgid, QTEXT_FILE); + free(fallback_msgid); lua_close(L); return FALSE; } @@ -518,6 +542,7 @@ const char *msgid; free(synopsis); } + free(fallback_msgid); free(text); lua_close(L); return TRUE; @@ -527,15 +552,15 @@ void com_pager(msgid) const char *msgid; { - com_pager_core("common", msgid); + com_pager_core("common", msgid, TRUE); } void qt_pager(msgid) const char *msgid; { - if (!com_pager_core(g.urole.filecode, msgid)) - com_pager_core("common", msgid); + if (!com_pager_core(g.urole.filecode, msgid, FALSE)) + com_pager_core("common", msgid, TRUE); } struct permonst * From 5175c6ab07e1317d2efe8717a4646ac22c65aa5d Mon Sep 17 00:00:00 2001 From: nhmall Date: Sun, 19 Jan 2020 23:09:53 -0500 Subject: [PATCH 14/24] doc bit; closes #287 closes #287 --- doc/nethack.6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/nethack.6 b/doc/nethack.6 index 446568ffb..d599a0b1a 100644 --- a/doc/nethack.6 +++ b/doc/nethack.6 @@ -95,7 +95,7 @@ will identify the things you see on the screen. To win the game (as opposed to merely playing to beat other people's high scores) you must locate the Amulet of Yendor which is somewhere below the 20th level of the dungeon and get it out. -Few people achieve this; most never do. Those who have go down +Few people achieve this; most never do. Those who have done so go down in history as heroes among heroes - and then they find ways of making the game even harder. See the .I Guidebook From b4446980050dde3ca594225b915cd1ff1027ce43 Mon Sep 17 00:00:00 2001 From: nhw_cron Date: Sun, 19 Jan 2020 23:17:10 -0500 Subject: [PATCH 15/24] This is cron-daily v1-Jan-19-2020. manpages updated: nethack.txt --- doc/nethack.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/nethack.txt b/doc/nethack.txt index dfe694737..d1d187016 100644 --- a/doc/nethack.txt +++ b/doc/nethack.txt @@ -27,10 +27,10 @@ DESCRIPTION To win the game (as opposed to merely playing to beat other people's high scores) you must locate the Amulet of Yendor which is somewhere below the 20th level of the dungeon and get it out. Few people achieve - this; most never do. Those who have go down in history as heroes among - heroes - and then they find ways of making the game even harder. See - the Guidebook section on Conduct if this game has gotten too easy for - you. + this; most never do. Those who have done so go down in history as he- + roes among heroes - and then they find ways of making the game even + harder. See the Guidebook section on Conduct if this game has gotten + too easy for you. When the game ends, whether by your dying, quitting, or escaping from the caves, NetHack will give you (a fragment of) the list of top scor- From 57e0e30d1015d560b5d768fcc1464fc6d1a3542b Mon Sep 17 00:00:00 2001 From: nhmall Date: Mon, 20 Jan 2020 11:10:16 -0500 Subject: [PATCH 16/24] travis-ci bits: try to avoid failure-flagging on transient connectivity issues Attempt to test whether Lua fetch succeeded (and pdcurses for windows and msdos as well) If those prerequisite fetches and untars didn't work, just exit without marking the travis-ci build as a failure so that the development team isn't notified about something transient that they don't need to fix in the code. --- .travis.yml | 91 ++++++++++++++++++++++---------- sys/msdos/msdos-cross-compile.sh | 6 +++ sys/winnt/travis-gcc.sh | 2 +- win/win32/vs2017/travisci.sh | 14 +++-- 4 files changed, 81 insertions(+), 32 deletions(-) diff --git a/.travis.yml b/.travis.yml index dba3f2649..dd9c6903b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,21 +1,37 @@ language: c matrix: include: - - os: linux - env: DESCR=linux-xenial-gcc HINTS=linux + - name: linux-xenial-gcc + os: linux + env: HINTS=linux LUA_VERSION=5.3.5 compiler: gcc - script: "cd sys/unix/ && sh setup.sh hints/$HINTS && cd ../../ && make fetch-lua && make install" - - os: linux - env: DESCR=linux-bionic-gcc HINTS=linux + script: + - cd sys/unix/ && sh setup.sh hints/$HINTS && cd ../../ + - make fetch-lua + - test -d "lib/lua-$LUA_VERSION/src" || exit 0 + - make install + - name: linux-bionic-gcc + os: linux + env: HINTS=linux LUA_VERSION=5.3.5 dist: bionic compiler: gcc - script: "cd sys/unix/ && sh setup.sh hints/$HINTS && cd ../../ && make fetch-lua && make install" - - os: linux - env: DESCR=linux-xenial-clang HINTS=linux + script: + - cd sys/unix/ && sh setup.sh hints/$HINTS && cd ../../ + - make fetch-lua + - test -d "lib/lua-$LUA_VERSION/src" || exit 0 + - make install + - name: linux-xenial-clang + os: linux + env: HINTS=linux LUA_VERSION=5.3.5 compiler: clang - script: "cd sys/unix/ && sh setup.sh hints/$HINTS && cd ../../ && make fetch-lua && make install" - - os: linux - env: DESCR=linux-xenial-gcc-x11 HINTS=linux-x11 + script: + - cd sys/unix/ && sh setup.sh hints/$HINTS && cd ../../ + - make fetch-lua + - test -d "lib/lua-$LUA_VERSION/src" || exit 0 + - make install + - name: linux-xenial-gcc-x11 + os: linux + env: HINTS=linux-x11 LUA_VERSION=5.3.5 compiler: gcc addons: apt: @@ -23,9 +39,14 @@ matrix: - libx11-dev - libxaw7-dev - xfonts-utils - script: "cd sys/unix/ && sh setup.sh hints/$HINTS && cd ../../ && make fetch-lua && make install" - - os: linux - env: DESCR=linux-xenial-gcc-qt5 HINTS=linux-qt5 + script: + - cd sys/unix/ && sh setup.sh hints/$HINTS && cd ../../ + - make fetch-lua + - test -d "lib/lua-$LUA_VERSION/src" || exit 0 + - make install + - name: linux-xenial-gcc-qt5 + os: linux + env: HINTS=linux-qt5 LUA_VERSION=5.3.5 compiler: gcc addons: apt: @@ -36,9 +57,14 @@ matrix: - qtbase5-dev - qtmultimedia5-dev - qtbase5-dev-tools - script: "cd sys/unix/ && sh setup.sh hints/$HINTS && cd ../../ && make fetch-lua && make QT_SELECT=5 MOC=moc install" - - os: linux - env: DESCR=linux-bionic-gcc-x11 HINTS=linux-x11 + script: + - cd sys/unix/ && sh setup.sh hints/$HINTS && cd ../../ + - make fetch-lua + - test -d "lib/lua-$LUA_VERSION/src" || exit 0 + - make QT_SELECT=5 MOC=moc install + - name: linux-bionic-gcc-x11 + os: linux + env: HINTS=linux-x11 LUA_VERSION=5.3.5 dist: bionic compiler: gcc addons: @@ -47,9 +73,14 @@ matrix: - libx11-dev - libxaw7-dev - xfonts-utils - script: "cd sys/unix/ && sh setup.sh hints/$HINTS && cd ../../ && make fetch-lua && make install" - - os: linux - env: DESCR=linux-xenial-gcc-minimal HINTS=linux-minimal + script: + - cd sys/unix/ && sh setup.sh hints/$HINTS && cd ../../ + - make fetch-lua + - test -d "lib/lua-$LUA_VERSION/src" || exit 0 + - make install + - name: linux-xenial-gcc-minimal + os: linux + env: HINTS=linux-minimal LUA_VERSION=5.3.5 compiler: gcc script: | cd sys/unix/ && sh setup.sh hints/$HINTS && cd ../../ @@ -72,31 +103,37 @@ matrix: sed -i '/^#define SHELL/d' include/unixconf.h sed -i '/^#define SUSPEND/d' include/unixconf.h sed -i 's/^#define TEXTCOLOR//' include/unixconf.h - make fetch-lua && make install + make fetch-lua + test -d "lib/lua-$LUA_VERSION/src" || exit 0 + make install cat dat/options - - os: windows - env: DESCR=windows-visualstudio + - name: windows-visualstudio + os: windows language: shell script: - ./win/win32/vs2017/travisci.sh - - os: windows + - name: windows-mingw + os: windows # install: choco install mingw - env: DESCR=windows-mingw script: - sh sys/winnt/travis-gcc.sh + - test -d "lib/lua-$LUA_VERSION/src" || exit 0 + - test -d "lib/pdcurses" || exit 0 - export ADD_CURSES=Y - export PDCURSES_TOP=../lib/pdcurses - export LUA_VERSION=5.3.5 - cd src - cp ../sys/winnt/Makefile.gcc ./Makefile - mingw32-make install - - os: linux - env: DESCR=msdos-cross-on-linux HINTS=linux LUA_VERSION=5.3.5 + - name: msdos crosscompile on linux + os: linux + env: HINTS=linux LUA_VERSION=5.3.5 compiler: gcc script: # - export - cd sys/unix/ && sh setup.sh hints/$HINTS && cd ../../ - make fetch-lua + - test -d "lib/lua-$LUA_VERSION/src" || exit 0 - cd lib/lua-$LUA_VERSION/src && make a && cd ../../.. - sh sys/msdos/msdos-cross-compile.sh exclude: diff --git a/sys/msdos/msdos-cross-compile.sh b/sys/msdos/msdos-cross-compile.sh index 4dd7ee617..3de2b701b 100644 --- a/sys/msdos/msdos-cross-compile.sh +++ b/sys/msdos/msdos-cross-compile.sh @@ -74,6 +74,12 @@ fi cd ../ +# Don't fail the build if lua fetch failed because we cannot do anything about it +# but don't bother proceeding forward either +if [ ! -d "lib/lua-$LUA_VERSION/src" ]; then + exit 0 +fi + #echo after dos extender cd src diff --git a/sys/winnt/travis-gcc.sh b/sys/winnt/travis-gcc.sh index 562b1a142..6f731cea8 100644 --- a/sys/winnt/travis-gcc.sh +++ b/sys/winnt/travis-gcc.sh @@ -2,7 +2,7 @@ set -x mkdir -p lib cd lib git clone --depth 1 https://github.com/wmcbrine/PDCurses.git pdcurses -git clone --depth 1 https://github.com/universal-ctags/ctags.git ctags +#git clone --depth 1 https://github.com/universal-ctags/ctags.git ctags curl -R -O http://www.lua.org/ftp/lua-5.3.5.tar.gz tar zxf lua-5.3.5.tar.gz cd ../ diff --git a/win/win32/vs2017/travisci.sh b/win/win32/vs2017/travisci.sh index b3e7de13e..7c16f6c9c 100644 --- a/win/win32/vs2017/travisci.sh +++ b/win/win32/vs2017/travisci.sh @@ -24,15 +24,21 @@ export LIB=/c/Program\ Files\ \(x86\)/Microsoft\ Visual\ Studio/$VSVER/$TOOLSVER export LIB=/c/Program\ Files\ \(x86\)/Microsoft\ Visual\ Studio/$VSVER/$TOOLSVER/VC/Tools/MSVC/$MSVER/lib/x86:$LIB export LIB=/c/Program\ Files\ \(x86\)/Windows\ Kits/10/lib/$WKITVER/ucrt/x86:$LIB export LIB=/c/Program\ Files\ \(x86\)/Windows\ Kits/10/lib/$WKITVER/um/x86:$LIB +export LUA_VERSION=5.3.5 mkdir -p lib cd lib git clone --depth 1 https://github.com/wmcbrine/PDCurses.git pdcurses -git clone --depth 1 https://github.com/universal-ctags/ctags.git ctags +#git clone --depth 1 https://github.com/universal-ctags/ctags.git ctags curl -R -O http://www.lua.org/ftp/lua-5.3.5.tar.gz tar zxf lua-5.3.5.tar.gz -cd ctags -nmake -f mk_mvc.mak -cd ../../ +#cd ctags +#nmake -f mk_mvc.mak +#cd ../../ +cd ../ +test -d "lib/lua-$LUA_VERSION/src" || echo "Lua-$LUA_VERSION fetch failed" +test -d "lib/pdcurses" || echo "pdcurses fetch failed" +test -d "lib/pdcurses" || exit 0 +test -d "lib/lua-$LUA_VERSION/src" || exit 0 export ADD_CURSES=Y export PDCURSES_TOP=../lib/pdcurses export From 08775c2c78552214626199e2f25011585c6dff06 Mon Sep 17 00:00:00 2001 From: PatR Date: Tue, 21 Jan 2020 06:20:45 -0800 Subject: [PATCH 17/24] add some long worm comments and keep the remove_monster()+place_monster() followed by worm_move() operations together. No change in behavior. --- src/monmove.c | 15 +++++++++++---- src/worm.c | 9 ++++++++- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/monmove.c b/src/monmove.c index b72353629..324eaeb05 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 monmove.c $NHDT-Date: 1575245074 2019/12/02 00:04:34 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.116 $ */ +/* NetHack 3.6 monmove.c $NHDT-Date: 1579616424 2020/01/21 14:20:24 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.128 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2006. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1286,20 +1286,27 @@ register int after; if (!m_in_out_region(mtmp, nix, niy)) return 3; + /* move a normal monster; for a long worm, remove_monster() and + place_monster() only manipulate the head; they leave tail as-is */ remove_monster(omx, omy); place_monster(mtmp, nix, niy); + /* for a long worm, insert a new segment to reconnect the head + with the tail; worm_move() keeps the end of the tail if worm + is scheduled to grow, removes that for move-without-growing */ + if (mtmp->wormno) + worm_move(mtmp); + for (j = MTSZ - 1; j > 0; j--) mtmp->mtrack[j] = mtmp->mtrack[j - 1]; mtmp->mtrack[0].x = omx; mtmp->mtrack[0].y = omy; - /* Place a segment at the old position. */ - if (mtmp->wormno) - worm_move(mtmp); } else { if (is_unicorn(ptr) && rn2(2) && !tele_restrict(mtmp)) { (void) rloc(mtmp, TRUE); return 1; } + /* for a long worm, shrink it (by discarding end of tail) when + it has failed to move */ if (mtmp->wormno) worm_nomove(mtmp); } diff --git a/src/worm.c b/src/worm.c index 3d7fb3f93..c5395cbe9 100644 --- a/src/worm.c +++ b/src/worm.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 worm.c $NHDT-Date: 1561340880 2019/06/24 01:48:00 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.30 $ */ +/* NetHack 3.6 worm.c $NHDT-Date: 1579616437 2020/01/21 14:20:37 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.40 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2009. */ /* NetHack may be freely redistributed. See license for details. */ @@ -218,6 +218,13 @@ struct monst *worm; seg->nseg = new_seg; /* attach it to the end of the list */ wheads[wnum] = new_seg; /* move the end pointer */ + /* + * [maybe] FIXME? + * scheduling wgrowtime[] seems to be based on normal movement + * speed (12) but long worms move at 1/4 of that (3), so they'll + * reach the scheduled 'moves' more quickly (in terms of their + * actual movement) and grow faster than was probably intended. + */ if (wgrowtime[wnum] <= g.moves) { if (!wgrowtime[wnum]) wgrowtime[wnum] = g.moves + rnd(5); From fa890fc7a227cbfd7bffec25f370b6f0fe456bae Mon Sep 17 00:00:00 2001 From: PatR Date: Tue, 21 Jan 2020 15:11:59 -0800 Subject: [PATCH 18/24] wielded tin opener For simplified weapon description (used by ^X and a few other places), show "tin opener" instead of generic "tool" for that item since there are cases where it is expected to be wielded. Also, don't describe a wielded "glob of " as "food". --- src/weapon.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/weapon.c b/src/weapon.c index e61a7438f..d55f8e4e9 100644 --- a/src/weapon.c +++ b/src/weapon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 weapon.c $NHDT-Date: 1559998716 2019/06/08 12:58:36 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.70 $ */ +/* NetHack 3.6 weapon.c $NHDT-Date: 1579648295 2020/01/21 23:11:35 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.82 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2011. */ /* NetHack may be freely redistributed. See license for details. */ @@ -95,13 +95,17 @@ struct obj *obj; switch (skill) { case P_NONE: /* not a weapon or weptool: use item class name; - override class name "food" for corpses, tins, and eggs, - "large rock" for statues and boulders, and "tool" for towels */ + override class name for things where it sounds strange and + for things that aren't unexpected to find being wielded: + corpses, tins, eggs, and globs avoid "food", + statues and boulders avoid "large rock", + and towels and tin openers avoid "tool" */ descr = (obj->otyp == CORPSE || obj->otyp == TIN || obj->otyp == EGG || obj->otyp == STATUE || obj->otyp == BOULDER - || obj->otyp == TOWEL) - ? OBJ_NAME(objects[obj->otyp]) - : def_oc_syms[(int) obj->oclass].name; + || obj->otyp == TOWEL || obj->otyp == TIN_OPENER) + ? OBJ_NAME(objects[obj->otyp]) + : obj->globby ? "glob" + : def_oc_syms[(int) obj->oclass].name; break; case P_SLING: if (is_ammo(obj)) From a13d6c03c9e7094c7b4c01c548043f7e27f21bbb Mon Sep 17 00:00:00 2001 From: PatR Date: Tue, 21 Jan 2020 15:36:33 -0800 Subject: [PATCH 19/24] no more headless eyewear Noticed while working on something else: hero kept wearing a towel after polymorphing into a form without any head. And when not already wearing one, could put on a blindfold/towel/lenses while in a headless form. --- doc/fixes37.0 | 3 ++- src/do_wear.c | 26 ++++++++++++++++++++++---- src/polyself.c | 19 +++++++++++++++++-- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/doc/fixes37.0 b/doc/fixes37.0 index c9908ed92..7f067bcf0 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.69 $ $NHDT-Date: 1579261284 2020/01/17 11:41:24 $ +$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.70 $ $NHDT-Date: 1579649788 2020/01/21 23:36:28 $ General Fixes and Modified Features ----------------------------------- @@ -46,6 +46,7 @@ when poly'd into a giant and moving onto a boulder's spot, message given was confused about whether autopickup would occur so could be misleading random role selection wasn't honoring unwanted alignment(s) properly if at the edge of the map window, trying to move farther fails but used a turn +hero can no longer wear blindfold/towel/lenses when poly'd into headless form Fixes to 3.7.0-x Problems that Were Exposed Via git Repository diff --git a/src/do_wear.c b/src/do_wear.c index 584d9fb7c..663cb6947 100644 --- a/src/do_wear.c +++ b/src/do_wear.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 do_wear.c $NHDT-Date: 1575768410 2019/12/08 01:26:50 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.126 $ */ +/* NetHack 3.6 do_wear.c $NHDT-Date: 1579649788 2020/01/21 23:36:28 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.127 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1159,15 +1159,19 @@ void Blindf_off(otmp) struct obj *otmp; { - boolean was_blind = Blind, changed = FALSE; + boolean was_blind = Blind, changed = FALSE, + nooffmsg = !otmp; + if (!otmp) + otmp = ublindf; if (!otmp) { - impossible("Blindf_off without otmp"); + impossible("Blindf_off without eyewear?"); return; } g.context.takeoff.mask &= ~W_TOOL; setworn((struct obj *) 0, otmp->owornmask); - off_msg(otmp); + if (!nooffmsg) + off_msg(otmp); if (Blind) { if (was_blind) { @@ -1895,6 +1899,15 @@ struct obj *obj; return 1; } } else { + /* + * FIXME: + * except for the rings/nolimbs case, this allows you to put on + * accessories without having any hands to manipulate them, and + * to put them on when poly'd into a tiny or huge form where + * they shouldn't fit. [If the latter situation changes, make + * comparable change to break_armor(polyself.c).] + */ + /* accessory */ if (ring) { char answer, qbuf[QBUFSZ]; @@ -1965,6 +1978,11 @@ struct obj *obj; return 0; } } else if (eyewear) { + if (!has_head(g.youmonst.data)) { + You("have no head to wear %s on.", ansimpleoname(obj)); + return 0; + } + if (ublindf) { if (ublindf->otyp == TOWEL) Your("%s is already covered by a towel.", diff --git a/src/polyself.c b/src/polyself.c index 6c0f5c732..d61a461cb 100644 --- a/src/polyself.c +++ b/src/polyself.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 polyself.c $NHDT-Date: 1573290419 2019/11/09 09:06:59 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.135 $ */ +/* NetHack 3.6 polyself.c $NHDT-Date: 1579649789 2020/01/21 23:36:29 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.148 $ */ /* Copyright (C) 1987, 1988, 1989 by Ken Arromdee */ /* NetHack may be freely redistributed. See license for details. */ @@ -934,7 +934,7 @@ break_armor() useup(uarmu); } } else if (sliparm(g.youmonst.data)) { - if (((otmp = uarm) != 0) && (racial_exception(&g.youmonst, otmp) < 1)) { + if ((otmp = uarm) != 0 && racial_exception(&g.youmonst, otmp) < 1) { if (donning(otmp)) cancel_don(); Your("armor falls around you!"); @@ -1016,6 +1016,21 @@ break_armor() dropp(otmp); } } + /* not armor, but eyewear shouldn't stay worn without a head to wear + it/them on (should also come off if head is too tiny or too huge, + but putting accessories on doesn't reject those cases [yet?]); + amulet stays worn */ + if ((otmp = ublindf) != 0 && !has_head(g.youmonst.data)) { + int l; + const char *eyewear = simpleonames(otmp); /* blindfold|towel|lenses */ + + if (!strncmp(eyewear, "pair of ", l = 8)) /* lenses */ + eyewear += l; + Your("%s %s off!", eyewear, vtense(eyewear, "fall")); + (void) Blindf_off((struct obj *) 0); /* Null: skip usual off mesg */ + dropp(otmp); + } + /* rings stay worn even when no hands */ } static void From 3e18804371413d9da397bacdd317dd06fe285998 Mon Sep 17 00:00:00 2001 From: PatR Date: Tue, 21 Jan 2020 17:03:54 -0800 Subject: [PATCH 20/24] half poison gas damage from wearing a wet towel Make wearing a wet towel confer new attribute Half_gas_damage in addition to the usual blindness. It reduces damage from being inside a gas cloud region and from being hit by poison gas breath attack. It also fully blocks breathing of potion vapors. Might make the Plane of Fire easier although overcoming its blindness with telepathy won't reveal elementals. Definitely has the potential to make blind-from-birth conduct easier which wasn't the intent and probably isn't significant. --- doc/fixes37.0 | 3 ++- include/youprop.h | 6 +++++- src/attrib.c | 11 ++++++++--- src/cmd.c | 4 +++- src/dothrow.c | 5 +++-- src/potion.c | 14 ++++++++++---- src/region.c | 7 +++++-- 7 files changed, 36 insertions(+), 14 deletions(-) diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 7f067bcf0..cdbe956cd 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.70 $ $NHDT-Date: 1579649788 2020/01/21 23:36:28 $ +$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.71 $ $NHDT-Date: 1579655025 2020/01/22 01:03:45 $ General Fixes and Modified Features ----------------------------------- @@ -117,6 +117,7 @@ tiny chance for randomly created spellbooks to be Discworld novels instead bestowed as a prayer boon or be found in statues) 'goldX', 'implicit_uncursed', and 'mention_walls' options changed to be persistent across save/restore +wearing a wet towel confers "half damage from poison gas" attribute Platform- and/or Interface-Specific New Features diff --git a/include/youprop.h b/include/youprop.h index 20d1045e8..0faafe102 100644 --- a/include/youprop.h +++ b/include/youprop.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 youprop.h $NHDT-Date: 1568831820 2019/09/18 18:37:00 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.27 $ */ +/* NetHack 3.6 youprop.h $NHDT-Date: 1579655025 2020/01/22 01:03:45 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.30 $ */ /* Copyright (c) 1989 Mike Threepoint */ /* NetHack may be freely redistributed. See license for details. */ @@ -374,4 +374,8 @@ #define Hate_silver (u.ulycn >= LOW_PM || hates_silver(g.youmonst.data)) +/* _Hitchhikers_Guide_to_the_Galaxy_ on uses for 'towel': "wrap it round + your head to ward off noxious fumes" [we require it to be damp or wet] */ +#define Half_gas_damage (ublindf && ublindf->otyp == TOWEL && ublindf->spe > 0) + #endif /* YOUPROP_H */ diff --git a/src/attrib.c b/src/attrib.c index 31c9fef67..eb069a1f0 100644 --- a/src/attrib.c +++ b/src/attrib.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 attrib.c $NHDT-Date: 1575245050 2019/12/02 00:04:10 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.66 $ */ +/* NetHack 3.6 attrib.c $NHDT-Date: 1579655026 2020/01/22 01:03:46 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.74 $ */ /* Copyright 1988, 1989, 1990, 1992, M. Stephenson */ /* NetHack may be freely redistributed. See license for details. */ @@ -277,11 +277,12 @@ int typ, fatal; /* if fatal is 0, limit damage to adjattrib */ boolean thrown_weapon; /* thrown weapons are less deadly */ { int i, loss, kprefix = KILLED_BY_AN; + boolean blast = !strcmp(reason, "blast"); /* inform player about being poisoned unless that's already been done; "blast" has given a "blast of poison gas" message; "poison arrow", "poison dart", etc have implicitly given poison messages too... */ - if (strcmp(reason, "blast") && !strstri(reason, "poison")) { + if (!blast && !strstri(reason, "poison")) { boolean plural = (reason[strlen(reason) - 1] == 's') ? 1 : 0; /* avoid "The" Orcus's sting was poisoned... */ @@ -290,7 +291,7 @@ boolean thrown_weapon; /* thrown weapons are less deadly */ plural ? "were" : "was"); } if (Poison_resistance) { - if (!strcmp(reason, "blast")) + if (blast) shieldeff(u.ux, u.uy); pline_The("poison doesn't seem to affect you."); return; @@ -315,8 +316,12 @@ boolean thrown_weapon; /* thrown weapons are less deadly */ g.context.botl = TRUE; pline_The("poison was deadly..."); } else if (i > 5) { + boolean cloud = !strcmp(reason, "gas cloud"); + /* HP damage; more likely--but less severe--with missiles */ loss = thrown_weapon ? rnd(6) : rn1(10, 6); + if ((blast || cloud) && Half_gas_damage) /* worn towel */ + loss = (loss + 1) / 2; losehp(loss, pkiller, kprefix); /* poison damage */ } else { /* attribute loss; if typ is A_STR, reduction in current and diff --git a/src/cmd.c b/src/cmd.c index 11eb394b2..90dd2be5c 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 cmd.c $NHDT-Date: 1578764033 2020/01/11 17:33:53 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.391 $ */ +/* NetHack 3.6 cmd.c $NHDT-Date: 1579655026 2020/01/22 01:03:46 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.392 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2984,6 +2984,8 @@ int final; enlght_halfdmg(HALF_PHDAM, final); if (Half_spell_damage) enlght_halfdmg(HALF_SPDAM, final); + if (Half_gas_damage) + enl_msg(You_, "take", "took", " reduced poison gas damage", ""); /* polymorph and other shape change */ if (Protection_from_shape_changers) you_are("protected from shape changers", diff --git a/src/dothrow.c b/src/dothrow.c index ace9d4984..2369e1326 100644 --- a/src/dothrow.c +++ b/src/dothrow.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 dothrow.c $NHDT-Date: 1573688688 2019/11/13 23:44:48 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.164 $ */ +/* NetHack 3.6 dothrow.c $NHDT-Date: 1579655027 2020/01/22 01:03:47 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.181 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1977,7 +1977,8 @@ boolean from_invent; explode_oil(obj, x, y); } else if (distu(x, y) <= 2) { if (!breathless(g.youmonst.data) || haseyes(g.youmonst.data)) { - if (obj->otyp != POT_WATER) { + /* wet towel protects both eyes and breathing */ + if (obj->otyp != POT_WATER && !Half_gas_damage) { if (!breathless(g.youmonst.data)) { /* [what about "familiar odor" when known?] */ You("smell a peculiar odor..."); diff --git a/src/potion.c b/src/potion.c index 5032e4e51..612ba9388 100644 --- a/src/potion.c +++ b/src/potion.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 potion.c $NHDT-Date: 1573848199 2019/11/15 20:03:19 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.167 $ */ +/* NetHack 3.6 potion.c $NHDT-Date: 1579655028 2020/01/22 01:03:48 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.179 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1627,13 +1627,19 @@ register struct obj *obj; remains in inventory where our caller expects it to be */ obj->in_use = 1; - switch (obj->otyp) { + /* wearing a wet towel protects both eyes and breathing, even when + the breath effect might be beneficial; we still pass down to the + naming opportunity in case potion was thrown at hero by a monster */ + switch (Half_gas_damage ? TOWEL : obj->otyp) { + case TOWEL: + pline("Some vapor passes harmlessly around you."); + break; case POT_RESTORE_ABILITY: case POT_GAIN_ABILITY: if (obj->cursed) { - if (!breathless(g.youmonst.data)) + if (!breathless(g.youmonst.data)) { pline("Ulch! That potion smells terrible!"); - else if (haseyes(g.youmonst.data)) { + } else if (haseyes(g.youmonst.data)) { const char *eyes = body_part(EYE); if (eyecount(g.youmonst.data) != 1) diff --git a/src/region.c b/src/region.c index cc2215e7e..aca233561 100644 --- a/src/region.c +++ b/src/region.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 region.c $NHDT-Date: 1573957877 2019/11/17 02:31:17 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.45 $ */ +/* NetHack 3.6 region.c $NHDT-Date: 1579655029 2020/01/22 01:03:49 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.60 $ */ /* Copyright (c) 1996 by Jean-Christophe Collet */ /* NetHack may be freely redistributed. See license for details. */ @@ -1024,7 +1024,10 @@ genericptr_t p2; pline("%s is burning your %s!", Something, makeplural(body_part(LUNG))); You("cough and spit blood!"); - losehp(Maybe_Half_Phys(rnd(dam) + 5), "gas cloud", KILLED_BY_AN); + dam = Maybe_Half_Phys(rnd(dam) + 5); + if (Half_gas_damage) /* worn towel */ + dam = (dam + 1) / 2; + losehp(dam, "gas cloud", KILLED_BY_AN); return FALSE; } else { You("cough!"); From 424750867ab80c9e468aaded7313f1ab0f48cdca Mon Sep 17 00:00:00 2001 From: PatR Date: Tue, 21 Jan 2020 18:29:23 -0800 Subject: [PATCH 21/24] wizard mode un-polymorph When already polymorphed, polymorphing into 'human' (or character's species) to revert to normal when at low level has the infuriating tendency to yield "your new form isn't healthy enough to survive". Allow specifying your own role as a way to rehumanize() instead of going through newman() and level/sex/characteristics randomization which that performs. --- src/polyself.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/polyself.c b/src/polyself.c index d61a461cb..691e70c86 100644 --- a/src/polyself.c +++ b/src/polyself.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 polyself.c $NHDT-Date: 1579649789 2020/01/21 23:36:29 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.148 $ */ +/* NetHack 3.6 polyself.c $NHDT-Date: 1579660157 2020/01/22 02:29:17 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.149 $ */ /* Copyright (C) 1987, 1988, 1989 by Ken Arromdee */ /* NetHack may be freely redistributed. See license for details. */ @@ -462,14 +462,19 @@ int psflags; pline("I've never heard of such monsters."); else You_cant("polymorph into any of those."); + } else if (wizard && Upolyd && mntmp == u.umonster) { + /* in wizard mode, picking own role while poly'd reverts to + normal without newman()'s chance of level or sex change */ + rehumanize(); + goto made_change; } else if (iswere && (were_beastie(mntmp) == u.ulycn || mntmp == counter_were(u.ulycn) || (Upolyd && mntmp == PM_HUMAN))) { goto do_shift; - /* Note: humans are illegal as monsters, but an - * illegal monster forces newman(), which is what we - * want if they specified a human.... */ } else if (!polyok(&mons[mntmp]) + /* Note: humans are illegal as monsters, but an + illegal monster forces newman(), which is what + we want if they specified a human.... */ && !(mntmp == PM_HUMAN || your_race(&mons[mntmp]) || mntmp == g.urole.malenum || mntmp == g.urole.femalenum)) { From b2fa6292dbb9b6f7f693d07649264656b9354d97 Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 24 Jan 2020 12:52:35 -0800 Subject: [PATCH 22/24] Lua error reporting buffer overflow nhl_error() was clobbering the stack. I assume that the 'source' field in the Lua debugging structure is normally a file name, but nethack loads an entire Lua script into one long string because it usually comes out of the DLB container, and 'source' contained the full string. That would overflow the local buffer in nhl_error() if nethack encountered a Lua problem and tried to report it. (In my case, the problem was in a level description file modification.) [Not something under user control unless user can modify dat/*.lua and put the result into $HACKDIR/nhdat.] --- doc/fixes37.0 | 3 ++- src/nhlua.c | 12 ++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/doc/fixes37.0 b/doc/fixes37.0 index cdbe956cd..539ce7f9a 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.71 $ $NHDT-Date: 1579655025 2020/01/22 01:03:45 $ +$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.72 $ $NHDT-Date: 1579899144 2020/01/24 20:52:24 $ General Fixes and Modified Features ----------------------------------- @@ -74,6 +74,7 @@ if running and Blind or Stunned or Fumbling or Dex < 10, encountering a closed data.base lookup of an entry with any blank lines would falsely claim that "'data' file in wrong fromat or corrupted" after some extra checks were added while investigating tab handling anomalies +using nhl_error() to report a Lua processing problem would clobber the stack Platform- and/or Interface-Specific Fixes diff --git a/src/nhlua.c b/src/nhlua.c index f215ea01c..170e3c3ed 100644 --- a/src/nhlua.c +++ b/src/nhlua.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 nhlua.c $NHDT-Date: 1575246766 2019/12/02 00:32:46 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.16 $ */ +/* NetHack 3.7 nhlua.c $NHDT-Date: 1579899144 2020/01/24 20:52:24 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.28 $ */ /* Copyright (c) 2018 by Pasi Kallinen */ /* NetHack may be freely redistributed. See license for details. */ @@ -44,8 +44,16 @@ const char *msg; lua_getstack(L, 1, &ar); lua_getinfo(L, "lS", &ar); - Sprintf(buf, "%s (line %i%s)", msg, ar.currentline, ar.source); + Sprintf(buf, "%s (line %d ", msg, ar.currentline); + Sprintf(eos(buf), "%.*s)", + /* (max length of ar.short_src is actually LUA_IDSIZE + so this is overkill for it, but crucial for ar.source) */ + (int) (sizeof buf - (strlen(buf) + sizeof ")")), + ar.short_src); /* (used to be 'ar.source' here) */ lua_pushstring(L, buf); +#if 0 /* defined(PANICTRACE) && !defined(NO_SIGNALS) */ + panictrace_setsignals(FALSE); +#endif (void) lua_error(L); /*NOTREACHED*/ } From dba6c20e2d0eb8874fb5dca35ea7ffdfdd08cba9 Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 24 Jan 2020 13:26:01 -0800 Subject: [PATCH 23/24] loading Lua scripts When loading a Lua script, modify it with a comment containing the file name (or DLB module name) so that error reporting doesn't just show the first 60 bytes of the script. Also, don't assume that it's possible to load an entire script in one fread(). Unfortunately that got way out of hand and the result isn't pretty. But something of the sort is necessary. (Reading the script into one string first and then applying modifications while copying it into a second one would probably be a lot cleaner than mixing the two operations.) If a script starts with a comment or a blank line, the insertion of the file name comment won't disturb the line number reported in an error message. But if the script starts out with code on its first line, error reports will be off by one for the line number. Showing the file name is more useful than keeping that number accurate. --- src/nhlua.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 115 insertions(+), 14 deletions(-) diff --git a/src/nhlua.c b/src/nhlua.c index 170e3c3ed..bafefbfc2 100644 --- a/src/nhlua.c +++ b/src/nhlua.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 nhlua.c $NHDT-Date: 1579899144 2020/01/24 20:52:24 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.28 $ */ +/* NetHack 3.7 nhlua.c $NHDT-Date: 1579901146 2020/01/24 21:25:46 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.29 $ */ /* Copyright (c) 2018 by Pasi Kallinen */ /* NetHack may be freely redistributed. See license for details. */ @@ -931,16 +931,21 @@ lua_State *L; return 1; } +/* read lua code/data from a dlb module or an external file, insert the + file name as new first record so that we aren't at the mercy of whoever + edits it to maintain that, and since we're forced to muck with messy + details, replace comments with empty lines so that Lua won't need to */ boolean nhl_loadlua(L, fname) lua_State *L; const char *fname; { - boolean ret = TRUE; +#define LOADCHUNKSIZE (1L << 13) /* 8K */ + boolean ret = TRUE, is_comment; dlb *fh; - char *buf = (char *) 0; - long buflen; - int cnt, llret; + char *buf = (char *) 0, *bufin, *bufout, *p, *nl; + long buflen, ct, cnt, fnamesiz; + int llret, first = 0, spanlines = 0; fh = dlb_fopen(fname, "r"); if (!fh) { @@ -949,20 +954,117 @@ const char *fname; goto give_up; } + fnamesiz = strlen(fname) + 7L; /* 7: "--{" + "}--\n" (no '\0') */ dlb_fseek(fh, 0L, SEEK_END); buflen = dlb_ftell(fh); - buf = (char *) alloc(buflen + 1); dlb_fseek(fh, 0L, SEEK_SET); - if ((cnt = dlb_fread(buf, 1, buflen, fh)) != buflen) { - impossible("nhl_loadlua: Error loading %s, got %i/%li bytes", - fname, cnt, buflen); - ret = FALSE; - goto give_up; + /* extra +1: room to add final '\n' if missing */ + buf = bufout = (char *) alloc(fnamesiz + buflen + 1 + 1); + /* insert file name as first record so nhl_error() can report it; + leading dashes make it be a comment, trailing ones are for + symmetry; delimit file name with braces instead of spaces to + avoid an undesireable line split during error feedback */ + Sprintf(bufout, "--{%s}--\n", fname); + bufin = bufout = eos(buf); + + ct = 0L; + while (buflen > 0 || ct) { + /* + * Semi-arbitrarily limit reads to 8K at a time. That's big + * enough to cover the majority of our Lua files in one bite + * but small enough to fully exercise the partial record + * handling (when processing the castle's level description). + * + * [For an external file (non-DLB), VMS may only be able to + * read at most 32K-1 at a time depending on the file format + * in use, and fseek(SEEK_END) only yields an upper bound on + * the actual amount of data in that situation.] + */ + if ((cnt = dlb_fread(bufin, 1, min(buflen, LOADCHUNKSIZE), fh)) < 0L) + break; + buflen -= cnt; /* set up for next iteration, if any */ + if (cnt == 0L) { + *bufin = '\n'; /* very last line is unterminated? */ + cnt = 1; + } + bufin[cnt] = '\0'; /* fread() doesn't do this */ + + /* in case partial line was leftover from previous fread */ + bufin -= ct, cnt += ct, ct = 0; + + while (cnt > 0) { + if ((nl = index(bufin, '\n')) != 0) { + /* normal case, newline is present */ + ct = (long) (nl - bufin + 1L); /* +1: keep the newline */ + for (p = bufin; *p == ' '; ++p) + continue; + is_comment = (p[0] == '-' && p[1] == '-' && !spanlines); + if (spanlines && index("])}", *p)) + --spanlines; + if (!first++ && (*p == '\n' || is_comment)) { + /* if first line is blank or a comment, omit it so that + our "--{fname}--\n" line doesn't make the line count + be out of sync; note: when first line is code, line + number reported in error messages will be off by one */ + bufin = nl + 1; + } else if (is_comment) { + /* discard comment to shorten the string Lua will deal + with but keep the line to maintain Lua line counter */ +#if 0 + Strcpy(bufout, "--\n"), bufout += 3; +#else + Strcpy(bufout, "\n"), bufout += 1; +#endif + bufin += ct; + } else { + /* normal case; some text terminated by newline */ + for (p = bufin; p <= nl; ++p) + *bufout++ = *bufin++; + for (p = &bufout[-2]; *p == ' '; --p) /* [-1] is '\n' */ + continue; + if (index("[({", *p)) + ++spanlines; + } + if (*bufin == '\r') + ++bufin, ++ct; + /* update for next loop iteration */ + cnt -= ct; + ct = 0; + } else { + /* no newline => partial record; move unprocessed chars + to front of input buffer (bufin portion of buf[]) */ + ct = cnt = (long) (eos(bufin) - bufin); + for (p = bufout; cnt > 0; --cnt) + *p++ = *bufin++; + *p = '\0'; + bufin = p; /* next fread() populates buf[] starting here */ + /* cnt==0 so inner loop will terminate */ + } + } } - buf[buflen] = '\0'; + *bufout = '\0'; (void) dlb_fclose(fh); +#ifdef DEBUG + if (explicitdebug("loadlua")) { + FILE *fp; + char oname[QBUFSZ]; + + (void) strsubst(strcpy(oname, fname), ".lua", ".txt"); + if ((fp = fopen(oname, "w")) != 0) { + for (buflen = strlen(buf), p = buf; + buflen > 0; + buflen -= cnt, p += cnt) { + cnt = min(buflen, LOADCHUNKSIZE); + if ((long) fwrite(p, 1, cnt, fp) < cnt) + break; + } + (void) fclose(fp); + } + } +#endif + llret = luaL_loadstring(L, buf); if (llret != LUA_OK) { impossible("luaL_loadstring: Error loading %s (errcode %i)", @@ -981,8 +1083,7 @@ const char *fname; give_up: if (buf) { - free(buf); - buf = (char *) 0; + free((genericptr_t) buf); buflen = 0; } return ret; From 0166239a2276c175c42e4fc33d1f8a794ee6fe75 Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 24 Jan 2020 13:54:23 -0800 Subject: [PATCH 24/24] simplify achievement tracking for special objects This turned out to be a lot more work than I anticipated, but it is definitely simpler (other than having #wizmakemap take achievements away if you replace the level that contains the 'prize', which wasn't handled before). I cheated and made Mine's End into a no-bones level because the new flagging scheme for luckstone, bag, and amulet can't carry over from one game to another. It probably should have been no-bones all along. Sokoban didn't have this issue because it's already no-bones. Existing save files are invalidated. --- dat/dungeon.lua | 3 +- doc/fixes37.0 | 2 ++ include/context.h | 6 ++++ include/decl.h | 6 ++-- include/obj.h | 16 ++-------- include/patchlevel.h | 2 +- src/bones.c | 12 +++----- src/cmd.c | 19 ++++++++++++ src/decl.c | 2 -- src/invent.c | 12 ++------ src/options.c | 6 ++-- src/sp_lev.c | 70 +++++++++++++++++++++++++------------------- 12 files changed, 85 insertions(+), 71 deletions(-) diff --git a/dat/dungeon.lua b/dat/dungeon.lua index 6112a25ad..014d3dab3 100644 --- a/dat/dungeon.lua +++ b/dat/dungeon.lua @@ -178,7 +178,8 @@ dungeon = { }, { name = "minend", - bonetag = "E", +-- 3.7.0: minend changed to no-bones to simplify achievement tracking +-- bonetag = "E" base = -1, nlevels = 3 }, diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 539ce7f9a..dfd769792 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -47,6 +47,8 @@ when poly'd into a giant and moving onto a boulder's spot, message given was random role selection wasn't honoring unwanted alignment(s) properly if at the edge of the map window, trying to move farther fails but used a turn hero can no longer wear blindfold/towel/lenses when poly'd into headless form +revamp achievement tracking for exploring Mine's End and Sokoban (by acquiring + luckstone and bag of holding or amulet of reflection, respectively) Fixes to 3.7.0-x Problems that Were Exposed Via git Repository diff --git a/include/context.h b/include/context.h index 4e8b01f62..dafc0c3f8 100644 --- a/include/context.h +++ b/include/context.h @@ -105,6 +105,11 @@ struct novel_tracking { /* for choosing random passage when reading novel */ passage from the Death Quotes section of dat/tribute */ }; +struct achievement_tracking { + unsigned mines_prize_oid, soko_prize_oid; /* obj->o_id */ + short mines_prize_type, soko_prize_typ1, soko_prize_typ2; /* obj->otyp */ +}; + struct context_info { unsigned ident; /* social security number for each monster */ unsigned no_of_wizards; /* 0, 1 or 2 (wizard and his shadow) */ @@ -143,6 +148,7 @@ struct context_info { struct obj_split objsplit; /* track most recently split object stack */ struct tribute_info tribute; struct novel_tracking novel; + struct achievement_tracking achieveo; }; #endif /* CONTEXT_H */ diff --git a/include/decl.h b/include/decl.h index d6100e241..54a58aa03 100644 --- a/include/decl.h +++ b/include/decl.h @@ -215,7 +215,7 @@ typedef struct { boolean fieldlevel; /* fieldlevel saves saves each field individually */ boolean addinfo; /* if set, some additional context info from core */ boolean eof; /* place to mark eof reached */ - boolean bendian; /* set to true if executing on a big-endian machine */ + boolean bendian; /* set to true if executing on big-endian machine */ FILE *fpdef; /* file pointer for fieldlevel default style */ FILE *fpdefmap; /* file pointer mapfile for def format */ FILE *fplog; /* file pointer logfile */ @@ -1184,15 +1184,13 @@ struct instance_globals { char *lev_message; lev_region *lregions; int num_lregions; - /* positions touched by level elements explicitly defined in the des-file */ + /* positions touched by level elements explicitly defined in des-file */ char SpLev_Map[COLNO][ROWNO]; struct sp_coder *coder; xchar xstart, ystart; char xsize, ysize; boolean splev_init_present; boolean icedpools; - int mines_prize_count; - int soko_prize_count; /* achievements */ struct obj *container_obj[MAX_CONTAINMENT]; int container_idx; struct monst *invent_carrying_monster; diff --git a/include/obj.h b/include/obj.h index b31181394..6b0d9c5e9 100644 --- a/include/obj.h +++ b/include/obj.h @@ -346,19 +346,9 @@ struct obj { && !undiscovered_artifact(ART_EYES_OF_THE_OVERWORLD))) #define pair_of(o) ((o)->otyp == LENSES || is_gloves(o) || is_boots(o)) -/* 'PRIZE' values override obj->corpsenm so prizes mustn't be object types - which use that field for monster type (or other overloaded purpose) */ -#define MINES_PRIZE 1 -#define SOKO_PRIZE1 2 -#define SOKO_PRIZE2 3 -#define is_mines_prize(o) \ - ((o)->otyp == iflags.mines_prize_type \ - && (o)->record_achieve_special == MINES_PRIZE) -#define is_soko_prize(o) \ - (((o)->otyp == iflags.soko_prize_type1 \ - && (o)->record_achieve_special == SOKO_PRIZE1) \ - || ((o)->otyp == iflags.soko_prize_type2 \ - && (o)->record_achieve_special == SOKO_PRIZE2)) +/* achievement tracking; 3.6.x did this differently */ +#define is_mines_prize(o) ((o)->o_id == g.context.achieveo.mines_prize_oid) +#define is_soko_prize(o) ((o)->o_id == g.context.achieveo.soko_prize_oid) /* Flags for get_obj_location(). */ #define CONTAINED_TOO 0x1 diff --git a/include/patchlevel.h b/include/patchlevel.h index 50eccc543..f9196a31f 100644 --- a/include/patchlevel.h +++ b/include/patchlevel.h @@ -14,7 +14,7 @@ * Incrementing EDITLEVEL can be used to force invalidation of old bones * and save files. */ -#define EDITLEVEL 10 +#define EDITLEVEL 11 #define COPYRIGHT_BANNER_A "NetHack, Copyright 1985-2020" #define COPYRIGHT_BANNER_B \ diff --git a/src/bones.c b/src/bones.c index 8ebe47cea..6816baa87 100644 --- a/src/bones.c +++ b/src/bones.c @@ -165,14 +165,10 @@ boolean restore; if (mnum == PM_DOPPELGANGER && otmp->otyp == CORPSE) set_corpsenm(otmp, mnum); } - } else if ((otmp->otyp == iflags.mines_prize_type - && !Is_mineend_level(&u.uz)) - || ((otmp->otyp == iflags.soko_prize_type1 - || otmp->otyp == iflags.soko_prize_type2) - && !Is_sokoend_level(&u.uz))) { - /* "special prize" in this game becomes ordinary object - if loaded into another game */ - otmp->record_achieve_special = NON_PM; + } else if (is_mines_prize(otmp) || is_soko_prize(otmp)) { + /* achievement tracking; in case prize was moved off its + original level (which is always a no-bones level) */ + otmp->nomerge = 0; } else if (otmp->otyp == AMULET_OF_YENDOR) { /* no longer the real Amulet */ otmp->otyp = FAKE_AMULET_OF_YENDOR; diff --git a/src/cmd.c b/src/cmd.c index 90dd2be5c..46f210f19 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -806,6 +806,24 @@ boolean pre, wiztower; continue; if (mtmp->isshk) setpaid(mtmp); + /* achievement tracking */ + { + static const char Unachieve[] = "%s achievement revoked."; + + if (Is_mineend_level(&u.uz)) { + if (u.uachieve.mines_luckstone) { + pline(Unachieve, "Mine's end"); + u.uachieve.mines_luckstone = 0; + } + g.context.achieveo.mines_prize_oid = 0; + } else if (Is_sokoend_level(&u.uz)) { + if (u.uachieve.finish_sokoban) { + pline(Unachieve, "Sokoban end"); + u.uachieve.finish_sokoban = 0; + } + g.context.achieveo.soko_prize_oid = 0; + } + } /* TODO? * Reduce 'born' tally for each monster about to be discarded * by savelev(), otherwise replacing heavily populated levels @@ -877,6 +895,7 @@ wiz_makemap(VOID_ARGS) { if (wizard) { boolean was_in_W_tower = In_W_tower(u.ux, u.uy, &u.uz); + makemap_prepost(TRUE, was_in_W_tower); /* create a new level; various things like bestowing a guardian angel on Astral or setting off alarm on Ft.Ludios are handled diff --git a/src/decl.c b/src/decl.c index 8ae9aa6c7..79cbd199a 100644 --- a/src/decl.c +++ b/src/decl.c @@ -638,8 +638,6 @@ const struct instance_globals g_init = { UNDEFINED_VALUE, /* ysize */ FALSE, /* splev_init_present */ FALSE, /* icedpools */ - 0, /* mines_prize_count */ - 0, /* soki_prize_count */ { UNDEFINED_PTR }, /* container_obj */ 0, /* container_idx */ NULL, /* invent_carrying_monster */ diff --git a/src/invent.c b/src/invent.c index 6c3d7c363..88d6fb1d3 100644 --- a/src/invent.c +++ b/src/invent.c @@ -835,20 +835,14 @@ struct obj *obj; } /* "special achievements" aren't discoverable during play, they - end up being recorded in XLOGFILE at end of game, nowhere else; - record_achieve_special overloads corpsenm which is ordinarily - initialized to NON_PM (-1) rather than to 0; any special prize - must never be a corpse, egg, tin, figurine, or statue because - their use of obj->corpsenm for monster type would conflict, - nor be a leash (corpsenm overloaded for m_id of leashed - monster) or a novel (corpsenm overloaded for novel index) */ + end up being recorded in XLOGFILE at end of game, nowhere else */ if (is_mines_prize(obj)) { u.uachieve.mines_luckstone = 1; - obj->record_achieve_special = NON_PM; + g.context.achieveo.mines_prize_oid = 0; obj->nomerge = 0; } else if (is_soko_prize(obj)) { u.uachieve.finish_sokoban = 1; - obj->record_achieve_special = NON_PM; + g.context.achieveo.soko_prize_oid = 0; obj->nomerge = 0; } } diff --git a/src/options.c b/src/options.c index 0fc52a0af..f6f572689 100644 --- a/src/options.c +++ b/src/options.c @@ -737,9 +737,9 @@ initoptions_init() /* for "special achievement" tracking (see obj.h, create_object(sp_lev.c), addinv_core1(invent.c) */ - iflags.mines_prize_type = LUCKSTONE; - iflags.soko_prize_type1 = BAG_OF_HOLDING; - iflags.soko_prize_type2 = AMULET_OF_REFLECTION; + g.context.achieveo.mines_prize_type = LUCKSTONE; + g.context.achieveo.soko_prize_typ1 = BAG_OF_HOLDING; + g.context.achieveo.soko_prize_typ2 = AMULET_OF_REFLECTION; /* assert( sizeof flags.inv_order == sizeof def_inv_order ); */ (void) memcpy((genericptr_t) flags.inv_order, diff --git a/src/sp_lev.c b/src/sp_lev.c index c463c8b74..3a76dbb72 100644 --- a/src/sp_lev.c +++ b/src/sp_lev.c @@ -1569,32 +1569,34 @@ struct mkroom *croom; if (o->id != -1) { static const char prize_warning[] = "multiple prizes on %s level"; - /* if this is a specific item of the right type and it is being - created on the right level, flag it as the designated item - used to detect a special achievement (to whit, reaching and - exploring the target level, although the exploration part - might be short-circuited if a monster brings object to hero) */ - if (Is_mineend_level(&u.uz)) { - if (otmp->otyp == iflags.mines_prize_type) { - if (!g.mines_prize_count++) { - /* Note: the first luckstone on lev will become the prize - even if its not the explicit one, but random */ - otmp->record_achieve_special = MINES_PRIZE; - /* prevent stacking; cleared when achievement is recorded */ - otmp->nomerge = 1; - } + /* + * If this is a specific item of the right type and it is being + * created on the right level, flag it as the designated item + * used to detect a special achievement (to whit, reaching and + * exploring the target level, although the exploration part + * might be short-circuited if a monster brings object to hero). + * + * Random items of the appropriate type won't trigger a false + * match--they'll fail the (id != -1) test above--but the level + * definition should not include a second instance of any prize. + */ + if (Is_mineend_level(&u.uz) + && otmp->otyp == g.context.achieveo.mines_prize_type) { + if (!g.context.achieveo.mines_prize_oid) { + g.context.achieveo.mines_prize_oid = otmp->o_id; + /* prevent stacking; cleared when achievement is recorded */ + otmp->nomerge = 1; + } else { + impossible(prize_warning, "mines end"); } - } else if (Is_sokoend_level(&u.uz)) { - if (otmp->otyp == iflags.soko_prize_type1) { - otmp->record_achieve_special = SOKO_PRIZE1; + } else if (Is_sokoend_level(&u.uz) + && (otmp->otyp == g.context.achieveo.soko_prize_typ1 + || otmp->otyp == g.context.achieveo.soko_prize_typ2)) { + if (!g.context.achieveo.soko_prize_oid) { + g.context.achieveo.soko_prize_oid = otmp->o_id; otmp->nomerge = 1; /* redundant; Sokoban prizes don't stack */ - if (++g.soko_prize_count > 1) - impossible(prize_warning, "sokoban end"); - } else if (otmp->otyp == iflags.soko_prize_type2) { - otmp->record_achieve_special = SOKO_PRIZE2; - otmp->nomerge = 1; /* redundant; Sokoban prizes don't stack */ - if (++g.soko_prize_count > 1) - impossible(prize_warning, "sokoban end"); + } else { + impossible(prize_warning, "sokoban end"); } } } @@ -2590,14 +2592,26 @@ const char *s; /* find by object name */ for (i = 0; i < NUM_OBJECTS; i++) { - objname = obj_descr[i].oc_name; + objname = OBJ_NAME(objects[i]); if (objname && !strcmpi(s, objname)) return i; } + /* + * FIXME: + * If the file specifies "orange potion", the actual object + * description is just "orange" and won't match. [There's a + * reason that wish handling is insanely complicated.] And + * even if that gets fixed, if the file specifies "gray stone" + * it will start matching but would always pick the first one. + * + * "orange potion" is an unlikely thing to have in a special + * level description but "gray stone" is not.... + */ + /* find by object description */ for (i = 0; i < NUM_OBJECTS; i++) { - objname = obj_descr[i].oc_descr; + objname = OBJ_DESCR(objects[i]); if (objname && !strcmpi(s, objname)) return i; } @@ -5419,10 +5433,6 @@ sp_level_coder_init() g.splev_init_present = FALSE; g.icedpools = FALSE; - /* achievement tracking; static init would suffice except we need to - reset if #wizmakemap is used to recreate mines' end or sokoban end; - once either level is created, these values can be forgotten */ - g.mines_prize_count = g.soko_prize_count = 0; for (tmpi = 0; tmpi <= MAX_NESTED_ROOMS; tmpi++) { coder->tmproomlist[tmpi] = (struct mkroom *) 0;