diff --git a/doc/.gitattributes b/doc/.gitattributes index add1a82f7..80fecb1d5 100644 --- a/doc/.gitattributes +++ b/doc/.gitattributes @@ -1,5 +1,6 @@ *.mn NHSUBST *.6 NHSUBST +*.7 NHSUBST fixes* NHSUBST window.doc NHSUBST config.nh NHSUBST diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index e2f534dfc..1a194ea54 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -5495,7 +5495,7 @@ maintained the port of {\it NetHack\/} 3.6 for Microsoft Windows. %.pg \medskip {\it Pat Rankin} attempted to keep the VMS port running for NetHack 3.6.1, -hindered by limited access. {it Kevin Smolkowski} has updated and tested it +hindered by limited access. {\it Kevin Smolkowski} has updated and tested it for the most recent version of OpenVMS (V8.4 as of this writing) on Alpha and Integrity (aka Itanium aka IA64) but not VAX. diff --git a/doc/fixes36.2 b/doc/fixes36.2 index f8e4c8b11..323d911df 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -151,7 +151,7 @@ wizard mode ^T shouldn't have been diminishing player power but it was fix missing space in "would flyif you weren't levitating" a wand of polymorph lost its magical ability for the turn just because the player using it to engrave happened to be blind, which didn't make - a much sense + much sense floating eye is classified as a flyer but flying is blocked while levitating, so don't set intrinsic flying if hero is polymorphed into one being trapped (bear trap, web, molten or solidified lava, chained to buried @@ -176,6 +176,15 @@ prayer result which enhanced strength (fix weakness from hunger) didn't give a message if a change in encumbrance occurred; it came on next move add current location within the dungeon to the Background section of ^X and final disclosure (it's not background but doesn't fit anywhere else) +death from something other than loss of hit points could leave hero with + non-zero HP at end of game (during "really die?" prompt, disclosure) +added several special cases for genocide and/or wishing prompt: (cookie, + pie, genie, watchmen) +lightning strike from Mjollnir did not make any noise +with menustyle:Full, picking 'A - autoselect all' when putting items into a + container actually took everything out of that container +add missing 'A - autoselect all' choice for menustyle:Full when taking items + out while looting a container Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository @@ -189,6 +198,8 @@ make long extended commands list be more navigable simplify #wizidentify; don't rely on having bold menu entries ensure tmp_at() structures are initialized for all code paths when swallowed trapped-vs-levitation/flying change broke Sting releasing hero from web +life-saving while poly'd and Unchanging wasn't restoring u.mh (HP as monster) +change in searching stopped finding unseen monsters except hiders and eels tty: turn off an optimization that is the suspected cause of Windows reported partial status lines following level changes tty: ensure that current status fields are always copied to prior status @@ -199,6 +210,7 @@ tty: fix leftover display artifact when the last field on the row got placed to its left, getting shorter X11: its use of genl_status_update exposed a negative index use that could lead to a segfault +X11: rollback disabling of keystroke input for PICK_NONE menus (for scrolling) Platform- and/or Interface-Specific Fixes @@ -248,6 +260,7 @@ X11: handle X errors via panic X11: don't reuse perm_invent window for picking an object X11: obey mouse_support and allow toggling it in game X11: obey menu movement keys +X11: enable menu [cancel] button for PICK_NONE menus General New Features @@ -270,6 +283,12 @@ make mine town "orctown" variation a multiple level feature of the mines replace #monpolycontrol command with monpolycontrol boolean option replace #wizdebug_traveldisplay command with travel_debug boolean option rename #wizdebug_bury command to #wizbury +life-saving now makes swallower or grabber release hero +for ^X and enlightenment, display the information in a menu rather than a + plain text popup, so that player can go back within the text via + '<' (menu_previous_page) and '^' (menu_first_page) menu keys; + needed for interfaces (tty) without text popup scrollbar support; + end of game disclosure of attributes remains single-forward-pass Code Cleanup and Reorganization diff --git a/doc/mn.7 b/doc/mn.7 new file mode 100644 index 000000000..1d40edc2c --- /dev/null +++ b/doc/mn.7 @@ -0,0 +1,273 @@ +.\" $NHDT-Branch: NetHack-3.6.2 $:$NHDT-Revision: 1.0 $ $NHDT-Date: 1541298619 2018/11/04 02:30:19 $ +.TH MN 7 "News Version B2.11" +.SH NAME +mn \- text formatting macros for the news documentation +.SH SYNOPSIS +.B "nroff \-mn" +[ options ] file ... +.br +.B "troff \-mn" +[ options ] file ... +.SH DESCRIPTION +.PP +This package of +.IR nroff (1) +and +.IR troff (1) +macro definitions provides a formatting facility +which may be used to run off the formatted news documents. +When reverse line motions are needed, +filter the output through +.IR col (1). +.PP +All \-mn macros, +diversions, +string registers, +and number registers are defined below. +Many +.I nroff +and +.I troff +requests are unsafe in conjunction with this package. +However, +the requests below may be used with impunity: +.LP +.ta 5n 12n +.nf + .bp begin new page + .br break output line + .sp \f2n\fP insert \f2n\fP spacing lines + .ce \f2n\fP center next \f2n\fP lines + .ls \f2n\fP line spacing: \f2n\fP=1 single, \f2n\fP=2 double space + .na no alignment of right margin +.fi +.PP +Font and point size changes with \ef and \es are also allowed; +for example, +\&``\ef2word\efR'' will italicize \f2word.\fP +Output of the +.IR tbl (1), +.IR eqn (1), +and +.IR refer (1) +preprocessors for equations, +tables, +and references is acceptable as input. +.SH FILES +/usr/lib/tmac/tmac.n +.SH "SEE ALSO" +eqn(1), refer(1), tbl(1), troff(1) +.SH WARNINGS +.PP +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. +.PP +This package is not now intended for uses +other than with the news documentation. +.PP +Bug reports are always welcome; +please send them to the author. +(Include a sample of the input; +this helps track down the bug.) +.SH AUTHOR +Matt Bishop +.RI ( mab@riacs.arpa , +.IR ihnp4!ames!riacs!mab , +.IR decvax!decwrl!riacs!mab ) +.br +Updated for versions 1.4-1.6 by The NetHack Development Team +.SH REQUESTS +.PP +In the +.I Note +column, +.I b +means the request causes a break, +and +.I i +means the macro, +number register, +string register, +or diversion is internal and should not be used for anything. +In the +.I "What It Is" +column, +.IR div " means " diversion , +.IR mac " means " macro , +.IR num " means " "number register" , +and +.IR str " means " "string register" . +In the +.I "Initial Value" +column, +a hyphen means no initial value is used, +anything else is the initial value, +and if two values are given, +the first is for +.I nroff +and the second for +.IR troff . +.PP +.if n .in 0 +.ds x \f2x\fP\| +.ds y \f2y\fP\| +.ds z \f2z\fP\| +.ds X "\*x +.ds Y "\*x \*y +.ds Z "\*x \*y \*z +.tr _. +.ta \w'MacroNames'u +\w'WhatItIs'u +\w'InitialVal'u +\w'Note 'u +.sp .3 +.nf +Macro What Initial Note \0 Explanation +Name It Is Value +.sp .3 +_f num \- \- file name, used in error messages if set +_ai mac \- \- author's institution +_au mac \- b author's name +_b \*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 \*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 \*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 \*Z mac \- \- print computer/site name; same as _i +_dd div \- i text of display +dg str \(**,\(dg \- footnote mark +dw str \f2current\fP \- name of current day of week +dy str \f2current\fP \- 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 \f2date\fP,\- \- 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 \f2\- page \-\fP \- 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 \*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 \*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 \*Y mac \- b labelled paragraph; \*x is label, \*y indent +lq str ",`` \- left double quotation marks +mo str \f2current\fP \- name of current month +_mt mac \- b title +mt num 1.5i+1v \- distance of title from top of page +_ng \*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 \*Z mac \- \- command option; same as _b +p1 num 0 i 1 after PDP-11(tm) footnote printed, + 0 before +_pa \*Z mac \- \- print protocol appellation; same as _i +_pd \*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 \*Z mac \- \- print name of control char; \*x is name, + in font 3, between <>, \*y after, \*z before +_qp \*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 \*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 \*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 \*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 +.fi diff --git a/doc/mnh.7 b/doc/mnh.7 new file mode 100644 index 000000000..daed16283 --- /dev/null +++ b/doc/mnh.7 @@ -0,0 +1,95 @@ +.\" $NHDT-Branch: NetHack-3.6.2 $:$NHDT-Revision: 1.0 $ $NHDT-Date: 1541298620 2018/11/04 02:30:20 $ +.TH MNH 7 NETHACK +.SH NAME +mnh \- additional text formatting macros for the NetHack Guidebook +.SH SYNOPSIS +.B "make Guidebook" +.\"[ options ] file ... +.\".br +.\".B "troff \-mn" +.\"[ options ] file ... +.SH DESCRIPTION +.PP +This package of +.IR nroff (1) +and +.IR troff (1) +macro definitions extends +.IR tmac.n (7) +for the NetHack Guidebook. This document should be +read as an addendum to the documentation for +.IR tmac.n . +.PP +All \-mnh macros, +diversions, +string registers, +and number registers are defined below. +.SH FILES +doc/tmac.nh +.SH "SEE ALSO" +mn(7) +.SH AUTHOR +Pat Rankin +.SH REQUESTS +.PP +In the +.I Note +column, +.I b +means the request causes a break, +and +.I i +means the macro, +number register, +string register, +or diversion is internal and should not be used for anything. +In the +.I "What It Is" +column, +.IR div " means " diversion , +.IR mac " means " macro , +.IR num " means " "number register" , +and +.IR str " means " "string register" . +In the +.I "Initial Value" +column, +a hyphen means no initial value is used, +anything else is the initial value, +and if two values are given, +the first is for +.I nroff +and the second for +.IR troff . +.PP +.if n .in 0 +.ds x \f2x\fP\| +.ds y \f2y\fP\| +.ds z \f2z\fP\| +.ds X "\*x +.ds Y "\*x \*y +.ds Z "\*x \*y \*z +.tr _. +.ta \w'MacroNames'u +\w'WhatItIs'u +\w'InitialVal'u +\w'Note 'u +.sp .3 +.nf +Macro What Initial Note \0 Explanation +Name It Is Value +.sp .3 +_BR mac \- \- hard line break with vertical padding inserted +bR num \- i +_CC \*Y mac \- \- aligned one char key \*x with \fIshort\fP 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 diff --git a/include/extern.h b/include/extern.h index 2f2fe7f51..74e6ef0a6 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 extern.h $NHDT-Date: 1535812936 2018/09/01 14:42:16 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.636 $ */ +/* NetHack 3.6 extern.h $NHDT-Date: 1541145514 2018/11/02 07:58:34 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.645 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -721,6 +721,7 @@ E void FDECL(make_grave, (int, int, const char *)); /* ### exper.c ### */ +E long FDECL(newuexp, (int)); E int NDECL(newpw); E int FDECL(experience, (struct monst *, int)); E void FDECL(more_experienced, (int, int)); @@ -2727,6 +2728,9 @@ E int NDECL(abon); E int NDECL(dbon); E void FDECL(wet_a_towel, (struct obj *, int, BOOLEAN_P)); E void FDECL(dry_a_towel, (struct obj *, int, BOOLEAN_P)); +E char *FDECL(skill_level_name, (int, char *)); +E const char *FDECL(skill_name, (int)); +E boolean FDECL(can_advance, (int, BOOLEAN_P)); E int NDECL(enhance_weapon_skill); E void FDECL(unrestrict_weapon_skill, (int)); E void FDECL(use_skill, (int, int)); diff --git a/src/artifact.c b/src/artifact.c index 2ef7dfa7c..87cbf3b61 100644 --- a/src/artifact.c +++ b/src/artifact.c @@ -1215,6 +1215,8 @@ int dieroll; /* needed for Magicbane and vorpal blades */ pline_The("massive hammer hits%s %s%c", !spec_dbon_applies ? "" : "! Lightning strikes", hittee, !spec_dbon_applies ? '.' : '!'); + if (spec_dbon_applies) + wake_nearto(mdef->mx, mdef->my, 4 * 4); if (!rn2(5)) (void) destroy_mitem(mdef, RING_CLASS, AD_ELEC); if (!rn2(5)) diff --git a/src/cmd.c b/src/cmd.c index f88247ec7..9b4579857 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 cmd.c $NHDT-Date: 1523306904 2018/04/09 20:48:24 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.281 $ */ +/* NetHack 3.6 cmd.c $NHDT-Date: 1541235664 2018/11/03 09:01:04 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.298 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -182,6 +182,7 @@ STATIC_DCL int NDECL(wiz_port_debug); STATIC_PTR int NDECL(wiz_rumor_check); STATIC_PTR int NDECL(doattributes); +STATIC_DCL void FDECL(enlght_out, (const char *)); STATIC_DCL void FDECL(enlght_line, (const char *, const char *, const char *, const char *)); STATIC_DCL char *FDECL(enlght_combatinc, (const char *, int, int, char *)); @@ -190,6 +191,7 @@ STATIC_DCL boolean NDECL(walking_on_water); STATIC_DCL boolean FDECL(cause_known, (int)); STATIC_DCL char *FDECL(attrval, (int, int, char *)); STATIC_DCL void FDECL(background_enlightenment, (int, int)); +STATIC_DCL void FDECL(basics_enlightenment, (int, int)); STATIC_DCL void FDECL(characteristics_enlightenment, (int, int)); STATIC_DCL void FDECL(one_characteristic, (int, int, int)); STATIC_DCL void FDECL(status_enlightenment, (int, int)); @@ -1533,6 +1535,7 @@ doterrain(VOID_ARGS) /* -enlightenment and conduct- */ static winid en_win = WIN_ERR; +static boolean en_via_menu = FALSE; static const char You_[] = "You ", are[] = "are ", were[] = "were ", have[] = "have ", had[] = "had ", can[] = "can ", could[] = "could "; @@ -1550,6 +1553,19 @@ static const char have_been[] = "have been ", have_never[] = "have never ", #define you_have_X(something) \ enl_msg(You_, have, (const char *) "", something, "") +static void +enlght_out(buf) +const char *buf; +{ + if (en_via_menu) { + anything any; + + any = zeroany; + add_menu(en_win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE); + } else + putstr(en_win, 0, buf); +} + static void enlght_line(start, middle, end, ps) const char *start, *middle, *end, *ps; @@ -1557,7 +1573,7 @@ const char *start, *middle, *end, *ps; char buf[BUFSZ]; Sprintf(buf, " %s%s%s%s.", start, middle, end, ps); - putstr(en_win, 0, buf); + enlght_out(buf); } /* format increased chance to hit or damage or defense (Protection) */ @@ -1679,6 +1695,11 @@ int final; /* ENL_GAMEINPROGRESS:0, ENL_GAMEOVERALIVE, ENL_GAMEOVERDEAD */ { char buf[BUFSZ], tmpbuf[BUFSZ]; + en_win = create_nhwindow(NHW_MENU); + en_via_menu = !final; + if (en_via_menu) + start_menu(en_win); + Strcpy(tmpbuf, plname); *tmpbuf = highc(*tmpbuf); /* same adjustment as bottom line */ /* as in background_enlightenment, when poly'd we need to use the saved @@ -1688,13 +1709,14 @@ int final; /* ENL_GAMEINPROGRESS:0, ENL_GAMEOVERALIVE, ENL_GAMEOVERDEAD */ ? urole.name.f : urole.name.m); - en_win = create_nhwindow(NHW_MENU); /* title */ - putstr(en_win, 0, buf); /* "Conan the Archeologist's attributes:" */ + enlght_out(buf); /* "Conan the Archeologist's attributes:" */ /* background and characteristics; ^X or end-of-game disclosure */ if (mode & BASICENLIGHTENMENT) { - /* role, race, alignment, deities */ + /* role, race, alignment, deities, dungeon level, time, experience */ background_enlightenment(mode, final); + /* hit points, energy points, armor class, gold */ + basics_enlightenment(mode, final); /* strength, dexterity, &c */ characteristics_enlightenment(mode, final); } @@ -1710,7 +1732,17 @@ int final; /* ENL_GAMEINPROGRESS:0, ENL_GAMEOVERALIVE, ENL_GAMEOVERDEAD */ /* intrinsics and other traditional enlightenment feedback */ attributes_enlightenment(mode, final); } - display_nhwindow(en_win, TRUE); + + if (!en_via_menu) { + display_nhwindow(en_win, TRUE); + } else { + menu_item *selected = 0; + + end_menu(en_win, (char *) 0); + if (select_menu(en_win, PICK_NONE, &selected) > 0) + free((genericptr_t) selected); + en_via_menu = FALSE; + } destroy_nhwindow(en_win); en_win = WIN_ERR; } @@ -1732,8 +1764,8 @@ int final; role_titl = (innategend && urole.name.f) ? urole.name.f : urole.name.m; rank_titl = rank_of(u.ulevel, Role_switch, innategend); - putstr(en_win, 0, ""); /* separator after title */ - putstr(en_win, 0, "Background:"); + enlght_out(""); /* separator after title */ + enlght_out("Background:"); /* if polymorphed, report current shape before underlying role; will be repeated as first status: "you are transformed" and also @@ -1795,7 +1827,7 @@ int final; /* lastly, normal case */ : "", u_gname()); - putstr(en_win, 0, buf); + enlght_out(buf); /* show the rest of this game's pantheon (finishes previous sentence) [appending "also Moloch" at the end would allow for straightforward trailing "and" on all three aligned entries but looks too verbose] */ @@ -1811,7 +1843,7 @@ int final; Sprintf(eos(buf), " %s (%s)", align_gname(A_CHAOTIC), align_str(A_CHAOTIC)); Strcat(buf, "."); /* terminate sentence */ - putstr(en_win, 0, buf); + enlght_out(buf); /* show original alignment,gender,race,role if any have been changed; giving separate message for temporary alignment change bypasses need @@ -1831,7 +1863,7 @@ int final; difgend ? genders[flags.initgend].adj : "", (difgend && difalgn) ? " and " : "", difalgn ? align_str(u.ualignbase[A_ORIGINAL]) : ""); - putstr(en_win, 0, buf); + enlght_out(buf); } /* 3.6.2: dungeon level, so that ^X really has all status info as @@ -1868,36 +1900,78 @@ int final; Sprintf(buf, "in %s, on %s", dgnbuf, tmpbuf); } you_are(buf, ""); + + /* this is shown even if the 'time' option is off */ + if (moves == 1L) { + you_have("just started your adventure", ""); + } else { + /* 'turns' grates on the nerves in this context... */ + Sprintf(buf, "the dungeon %ld turn%s ago", moves, plur(moves)); + /* same phrasing for current and final: "entered" is unconditional */ + enlght_line(You_, "entered ", buf, ""); + } + if (!Upolyd) { + /* flags.showexp does not matter */ + /* experience level is already shown above */ + Sprintf(buf, "%-1ld experience point%s", u.uexp, plur(u.uexp)); + if (wizard) { + if (u.ulevel < 30) { + int ulvl = (int) u.ulevel; + long nxtlvl = newuexp(ulvl); + /* long oldlvl = (ulvl > 1) ? newuexp(ulvl - 1) : 0; */ + + Sprintf(eos(buf), ", %ld %s%sneeded to attain level %d", + (nxtlvl - u.uexp), (u.uexp > 0) ? "more " : "", + !final ? "" : "were ", (ulvl + 1)); + } + } + you_have(buf, ""); + } +#ifdef SCORE_ON_BOTL + if (flags.showscore) { + /* describes what's shown on status line, which is an approximation; + only show it here if player has the 'showscore' option enabled */ + Sprintf(buf, "%ld%s", botl_score(), + !final ? "" : " before end-of-game adjustments"); + enl_msg("Your score ", "is ", "was ", buf, ""); + } +#endif } -/* characteristics: expanded version of bottom line strength, dexterity, &c; - [3.6.1: now includes all status info (except things already shown in the - 'background' section), primarily so that blind players can suppress the - status line(s) altogether and use ^X feedback on demand to view HP, &c] */ +/* hit points, energy points, armor class -- essential information which + doesn't fit very well in other categories */ +/*ARGSUSED*/ STATIC_OVL void -characteristics_enlightenment(mode, final) -int mode; +basics_enlightenment(mode, final) +int mode UNUSED; int final; { + static char Power[] = "energy points (spell power)"; char buf[BUFSZ]; - int hp = Upolyd ? u.mh : u.uhp; - int hpmax = Upolyd ? u.mhmax : u.uhpmax; + int pw = u.uen, hp = (Upolyd ? u.mh : u.uhp), + pwmax = u.uenmax, hpmax = (Upolyd ? u.mhmax : u.uhpmax); - putstr(en_win, 0, ""); /* separator after background */ - putstr(en_win, 0, - final ? "Final Characteristics:" : "Current Characteristics:"); + enlght_out(""); /* separator after background */ + enlght_out("Basics:"); if (hp < 0) hp = 0; - Sprintf(buf, "%d hit points (max:%d)", hp, hpmax); + /* "1 out of 1" rather than "all" if max is only 1; should never happen */ + if (hp == hpmax && hpmax > 1) + Sprintf(buf, "all %d hit points", hpmax); + else + Sprintf(buf, "%d out of %d hit point%s", hp, hpmax, plur(hpmax)); you_have(buf, ""); - Sprintf(buf, "%d magic power (max:%d)", u.uen, u.uenmax); + /* low max energy is feasible, so handle couple of extra special cases */ + if (pwmax == 0 || (pw == pwmax && pwmax == 2)) /* both: "all 2" is silly */ + Sprintf(buf, "%s %s", !pwmax ? "no" : "both", Power); + else if (pw == pwmax && pwmax > 2) + Sprintf(buf, "all %d %s", pwmax, Power); + else + Sprintf(buf, "%d out of %d %s", pw, pwmax, Power); you_have(buf, ""); - Sprintf(buf, "%d", u.uac); - enl_msg("Your armor class ", "is ", "was ", buf, ""); - if (Upolyd) { switch (mons[u.umonnum].mlevel) { case 0: @@ -1911,28 +1985,38 @@ int final; Sprintf(buf, "%d hit dice", mons[u.umonnum].mlevel); break; } - } else { - /* flags.showexp does not matter */ - /* experience level is already shown in the Background section */ - Sprintf(buf, "%-1ld experience point%s", - u.uexp, plur(u.uexp)); + you_have(buf, ""); } - you_have(buf, ""); - /* this is shown even if the 'time' option is off */ - Sprintf(buf, "the dungeon %ld turn%s ago", moves, plur(moves)); - /* same phrasing at end of game: "entered" is unconditional */ - enlght_line(You_, "entered ", buf, ""); + Sprintf(buf, "%d", u.uac); + enl_msg("Your armor class ", "is ", "was ", buf, ""); -#ifdef SCORE_ON_BOTL - if (flags.showscore) { - /* describes what's shown on status line, which is an approximation; - only show it here if player has the 'showscore' option enabled */ - Sprintf(buf, "%ld%s", botl_score(), - !final ? "" : " before end-of-game adjustments"); - enl_msg("Your score ", "is ", "was ", buf, ""); + /* gold; similar to doprgold(#seegold) but without shop billing info; + same amount as shown on status line which ignores container contents */ + { + static const char Your_wallet[] = "Your wallet "; + long umoney = money_cnt(invent); + + if (!umoney) { + enl_msg(Your_wallet, "is ", "was ", "empty", ""); + } else { + Sprintf(buf, "%ld %s", umoney, currency(umoney)); + enl_msg(Your_wallet, "contains ", "contained ", buf, ""); + } } -#endif +} + +/* characteristics: expanded version of bottom line strength, dexterity, &c */ +STATIC_OVL void +characteristics_enlightenment(mode, final) +int mode; +int final; +{ + char buf[BUFSZ]; + + enlght_out(""); + Sprintf(buf, "%s Characteristics:", !final ? "Current" : "Final"); + enlght_out(buf); /* bottom line order */ one_characteristic(mode, final, A_STR); /* strength */ @@ -2045,7 +2129,7 @@ int mode; int final; { boolean magic = (mode & MAGICENLIGHTENMENT) ? TRUE : FALSE; - int cap; + int cap, wtype; char buf[BUFSZ], youtoo[BUFSZ]; boolean Riding = (u.usteed /* if hero dies while dismounting, u.usteed will still @@ -2063,8 +2147,8 @@ int final; * Status (many are abbreviated on bottom line; others are or * should be discernible to the hero hence to the player) \*/ - putstr(en_win, 0, ""); /* separator after title or characteristics */ - putstr(en_win, 0, final ? "Final Status:" : "Current Status:"); + enlght_out(""); /* separator after title or characteristics */ + enlght_out(final ? "Final Status:" : "Current Status:"); Strcpy(youtoo, You_); /* not a traditional status but inherently obvious to player; more @@ -2286,6 +2370,7 @@ int final; still useful though) */ you_are("unencumbered", ""); } + /* report being weaponless; distinguish whether gloves are worn */ if (!uwep) { you_are(uarmg ? "empty handed" /* gloves imply hands */ @@ -2295,7 +2380,8 @@ int final; /* alternate phrasing for paws or lack of hands */ : "not wielding anything", ""); - /* two-weaponing implies a weapon (not other odd stuff) in each hand */ + /* two-weaponing implies hands (can't be polymorphed) and + a weapon or wep-tool (not other odd stuff) in each hand */ } else if (u.twoweap) { you_are("wielding two weapons at once", ""); /* report most weapons by their skill class (so a katana will be @@ -2312,6 +2398,33 @@ int final; (uwep->quan == 1L) ? an(what) : makeplural(what)); you_are(buf, ""); } + /* + * Skill with current weapon. Might help players who've never + * noticed #enhance or decided that it was pointless. + * + * TODO? Maybe merge wielding line and skill line into one sentence. + */ + if ((wtype = uwep_skill_type()) != P_NONE) { + char sklvlbuf[20]; + int sklvl = P_SKILL(wtype); + boolean hav = (sklvl != P_UNSKILLED && sklvl != P_SKILLED); + + if (sklvl == P_ISRESTRICTED) + Strcpy(sklvlbuf, "no"); + else + (void) lcase(skill_level_name(wtype, sklvlbuf)); + /* "you have no/basic/expert/master/grand-master skill with " + or "you are unskilled/skilled in " */ + Sprintf(buf, "%s %s %s", sklvlbuf, + hav ? "skill with" : "in", skill_name(wtype)); + if (can_advance(wtype, FALSE)) + Sprintf(eos(buf), " and %s that", + !final ? "can enhance" : "could have enhanced"); + if (hav) + you_have(buf, ""); + else + you_are(buf, ""); + } /* report 'nudity' */ if (!uarm && !uarmu && !uarmc && !uarmg && !uarmf && !uarmh) { if (u.uroleplay.nudist) @@ -2335,8 +2448,8 @@ int final; /*\ * Attributes \*/ - putstr(en_win, 0, ""); - putstr(en_win, 0, final ? "Final Attributes:" : "Current Attributes:"); + enlght_out(""); + enlght_out(final ? "Final Attributes:" : "Current Attributes:"); if (u.uevent.uhand_of_elbereth) { static const char *const hofe_titles[3] = { "the Hand of Elbereth", diff --git a/src/detect.c b/src/detect.c index 80a985096..ca6eda709 100644 --- a/src/detect.c +++ b/src/detect.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 detect.c $NHDT-Date: 1539908137 2018/10/19 00:15:37 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.83 $ */ +/* NetHack 3.6 detect.c $NHDT-Date: 1541144458 2018/11/02 07:40:58 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.85 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2018. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1548,14 +1548,16 @@ boolean via_warning; if (mtmp->m_ap_type) { seemimic(mtmp); found_something = TRUE; - } else if (mtmp->mundetected - && (is_hider(mtmp->data) || mtmp->data->mlet == S_EEL)) { - if (via_warning) { - Your("warning senses cause you to take a second %s.", - Blind ? "to check nearby" : "look close by"); - display_nhwindow(WIN_MESSAGE, FALSE); /* flush messages */ + } else if (!canspotmon(mtmp)) { + if (mtmp->mundetected + && (is_hider(mtmp->data) || mtmp->data->mlet == S_EEL)) { + if (via_warning) { + Your("warning senses cause you to take a second %s.", + Blind ? "to check nearby" : "look close by"); + display_nhwindow(WIN_MESSAGE, FALSE); /* flush messages */ + } + mtmp->mundetected = 0; } - mtmp->mundetected = 0; newsym(x, y); found_something = TRUE; } diff --git a/src/end.c b/src/end.c index 93216c76c..c423fbcde 100644 --- a/src/end.c +++ b/src/end.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 end.c $NHDT-Date: 1539804880 2018/10/17 19:34:40 $ $NHDT-Branch: keni-makedefsm $:$NHDT-Revision: 1.146 $ */ +/* NetHack 3.6 end.c $NHDT-Date: 1540767809 2018/10/28 23:03:29 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.148 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -851,7 +851,8 @@ int how; if (u.uhpmax < uhpmin) u.uhpmax = uhpmin; u.uhp = u.uhpmax; - u.uswldtim = 0; + if (Upolyd) /* Unchanging, or death which bypasses losing hit points */ + u.mh = u.mhmax; if (u.uhunger < 500) { u.uhunger = 500; newuhs(FALSE); @@ -877,6 +878,16 @@ int how; curs_on_u(); if (!context.mon_moving) endmultishot(FALSE); + if (u.uswallow) { + /* might drop hero onto a trap that kills her all over again */ + expels(u.ustuck, u.ustuck->data, TRUE); + } else if (u.ustuck) { + if (Upolyd && sticks(youmonst.data)) + You("release %s.", mon_nam(u.ustuck)); + else + pline("%s releases you.", Monnam(u.ustuck)); + unstuck(u.ustuck); + } } /* @@ -1006,13 +1017,16 @@ void done(how) int how; { + boolean survive = FALSE; + if (how == TRICKED) { if (killer.name[0]) { paniclog("trickery", killer.name); - killer.name[0] = 0; + killer.name[0] = '\0'; } if (wizard) { You("are a very tricky wizard, it seems."); + killer.format = KILLED_BY_AN; /* reset to 0 */ return; } } @@ -1037,8 +1051,17 @@ int how; if (!killer.name[0] || how >= PANICKED) Strcpy(killer.name, deaths[how]); - if (how < PANICKED) + if (how < PANICKED) { u.umortality++; + /* in case caller hasn't already done this */ + if (u.uhp > 0 || (Upolyd && u.mh > 0)) { + /* for deaths not triggered by loss of hit points, force + current HP to zero (0 HP when turning into green slime + is iffy but we don't have much choice--that is fatal) */ + u.uhp = u.mh = 0; + context.botl = 1; + } + } if (Lifesaved && (how <= GENOCIDED)) { pline("But wait..."); makeknown(AMULET_OF_LIFE_SAVING); @@ -1055,20 +1078,24 @@ int how; if (how == GENOCIDED) { pline("Unfortunately you are still genocided..."); } else { - killer.name[0] = 0; - killer.format = 0; - return; + survive = TRUE; } } - if ((wizard || discover) && (how <= GENOCIDED) + /* explore and wizard modes offer player the option to keep playing */ + if (!survive && (wizard || discover) && how <= GENOCIDED && !paranoid_query(ParanoidDie, "Die?")) { pline("OK, so you don't %s.", (how == CHOKING) ? "choke" : "die"); savelife(how); - killer.name[0] = 0; - killer.format = 0; + survive = TRUE; + } + + if (survive) { + killer.name[0] = '\0'; + killer.format = KILLED_BY_AN; /* reset to 0 */ return; } really_done(how); + /*NOTREACHED*/ } /* separated from done() in order to specify the __noreturn__ attribute */ diff --git a/src/exper.c b/src/exper.c index a9b3eed77..5bca20e46 100644 --- a/src/exper.c +++ b/src/exper.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 exper.c $NHDT-Date: 1446975467 2015/11/08 09:37:47 $ $NHDT-Branch: master $:$NHDT-Revision: 1.26 $ */ +/* NetHack 3.6 exper.c $NHDT-Date: 1541145516 2018/11/02 07:58:36 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.30 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2007. */ /* NetHack may be freely redistributed. See license for details. */ @@ -6,10 +6,9 @@ #include "hack.h" #include -STATIC_DCL long FDECL(newuexp, (int)); STATIC_DCL int FDECL(enermod, (int)); -STATIC_OVL long +long newuexp(lev) int lev; { diff --git a/src/invent.c b/src/invent.c index 34b784475..2a52cda32 100644 --- a/src/invent.c +++ b/src/invent.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 invent.c $NHDT-Date: 1519672703 2018/02/26 19:18:23 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.225 $ */ +/* NetHack 3.6 invent.c $NHDT-Date: 1541145517 2018/11/02 07:58:37 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.241 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -3605,6 +3605,7 @@ doprgold() /* the messages used to refer to "carrying gold", but that didn't take containers into account */ long umoney = money_cnt(invent); + if (!umoney) Your("wallet is empty."); else diff --git a/src/mhitu.c b/src/mhitu.c index f3fecbd92..85293d57b 100644 --- a/src/mhitu.c +++ b/src/mhitu.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mhitu.c $NHDT-Date: 1513297347 2017/12/15 00:22:27 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.149 $ */ +/* NetHack 3.6 mhitu.c $NHDT-Date: 1540767817 2018/10/28 23:03:37 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.159 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1956,11 +1956,17 @@ struct attack *mattk; if (tmp) stop_occupation(); - if (touch_petrifies(youmonst.data) && !resists_ston(mtmp)) { + if (!u.uswallow) { + ; /* life-saving has already expelled swallowed hero */ + } else if (touch_petrifies(youmonst.data) && !resists_ston(mtmp)) { pline("%s very hurriedly %s you!", Monnam(mtmp), is_animal(mtmp->data) ? "regurgitates" : "expels"); expels(mtmp, mtmp->data, FALSE); } else if (!u.uswldtim || youmonst.data->msize >= MZ_HUGE) { + /* 3.6.2: u.uswldtim used to be set to 0 by life-saving but it + expels now so the !u.uswldtim case is no longer possible; + however, polymorphing into a huge form while already + swallowed is still possible */ You("get %s!", is_animal(mtmp->data) ? "regurgitated" : "expelled"); if (flags.verbose && (is_animal(mtmp->data) diff --git a/src/mondata.c b/src/mondata.c index 312448466..74814bd3d 100644 --- a/src/mondata.c +++ b/src/mondata.c @@ -762,6 +762,7 @@ const char *in_str; { "lurkers above", PM_LURKER_ABOVE }, { "cavemen", PM_CAVEMAN }, { "cavewomen", PM_CAVEWOMAN }, + { "watchmen", PM_WATCHMAN }, { "djinn", PM_DJINNI }, { "mumakil", PM_MUMAK }, { "erinyes", PM_ERINYS }, diff --git a/src/pickup.c b/src/pickup.c index fae1e2f03..319f1f031 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 pickup.c $NHDT-Date: 1516581051 2018/01/22 00:30:51 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.194 $ */ +/* NetHack 3.6 pickup.c $NHDT-Date: 1541312259 2018/11/04 06:17:39 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.201 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2720,9 +2720,7 @@ boolean put_in; } else if (flags.menu_style == MENU_FULL) { all_categories = FALSE; Sprintf(buf, "%s what type of objects?", action); - mflags = (ALL_TYPES | UNPAID_TYPES | BUCX_TYPES); - if (put_in) - mflags |= CHOOSE_ALL; + mflags = (ALL_TYPES | UNPAID_TYPES | BUCX_TYPES | CHOOSE_ALL); n = query_category(buf, put_in ? invent : current_container->cobj, mflags, &pick_list, PICK_ANY); if (!n) @@ -2739,12 +2737,23 @@ boolean put_in; } if (loot_everything) { - current_container->cknown = 1; - for (otmp = current_container->cobj; otmp; otmp = otmp2) { - otmp2 = otmp->nobj; - res = out_container(otmp); - if (res < 0) - break; + if (!put_in) { + current_container->cknown = 1; + for (otmp = current_container->cobj; otmp; otmp = otmp2) { + otmp2 = otmp->nobj; + res = out_container(otmp); + if (res < 0) + break; + n_looted += res; + } + } else { + for (otmp = invent; otmp && current_container; otmp = otmp2) { + otmp2 = otmp->nobj; + res = in_container(otmp); + if (res < 0) + break; + n_looted += res; + } } } else { mflags = INVORDER_SORT; diff --git a/src/weapon.c b/src/weapon.c index b680f864c..a590366bb 100644 --- a/src/weapon.c +++ b/src/weapon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 weapon.c $NHDT-Date: 1454660575 2016/02/05 08:22:55 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.57 $ */ +/* NetHack 3.6 weapon.c $NHDT-Date: 1541145518 2018/11/02 07:58:38 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.60 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2011. */ /* NetHack may be freely redistributed. See license for details. */ @@ -10,6 +10,12 @@ */ #include "hack.h" +STATIC_DCL void FDECL(give_may_advance_msg, (int)); +STATIC_DCL boolean FDECL(could_advance, (int)); +STATIC_DCL boolean FDECL(peaked_skill, (int)); +STATIC_DCL int FDECL(slots_required, (int)); +STATIC_DCL void FDECL(skill_advance, (int)); + /* Categories whose names don't come from OBJ_NAME(objects[type]) */ #define PN_BARE_HANDED (-1) /* includes martial arts */ @@ -27,8 +33,6 @@ #define PN_ESCAPE_SPELL (-13) #define PN_MATTER_SPELL (-14) -STATIC_DCL void FDECL(give_may_advance_msg, (int)); - STATIC_VAR NEARDATA const short skill_names_indices[P_NUM_SKILLS] = { 0, DAGGER, KNIFE, AXE, PICK_AXE, SHORT_SWORD, BROADSWORD, LONG_SWORD, TWO_HANDED_SWORD, SCIMITAR, PN_SABER, CLUB, MACE, MORNING_STAR, FLAIL, @@ -51,25 +55,6 @@ STATIC_VAR NEARDATA const char *const barehands_or_martial[] = { "bare handed combat", "martial arts" }; -STATIC_OVL void -give_may_advance_msg(skill) -int skill; -{ - You_feel("more confident in your %sskills.", - skill == P_NONE ? "" : skill <= P_LAST_WEAPON - ? "weapon " - : skill <= P_LAST_SPELL - ? "spell casting " - : "fighting "); -} - -STATIC_DCL boolean FDECL(can_advance, (int, BOOLEAN_P)); -STATIC_DCL boolean FDECL(could_advance, (int)); -STATIC_DCL boolean FDECL(peaked_skill, (int)); -STATIC_DCL int FDECL(slots_required, (int)); -STATIC_DCL char *FDECL(skill_level_name, (int, char *)); -STATIC_DCL void FDECL(skill_advance, (int)); - #define P_NAME(type) \ ((skill_names_indices[type] > 0) \ ? OBJ_NAME(objects[skill_names_indices[type]]) \ @@ -80,6 +65,17 @@ STATIC_DCL void FDECL(skill_advance, (int)); static NEARDATA const char kebabable[] = { S_XORN, S_DRAGON, S_JABBERWOCK, S_NAGA, S_GIANT, '\0' }; +STATIC_OVL void +give_may_advance_msg(skill) +int skill; +{ + You_feel("more confident in your %sskills.", + (skill == P_NONE) ? "" + : (skill <= P_LAST_WEAPON) ? "weapon " + : (skill <= P_LAST_SPELL) ? "spell casting " + : "fighting "); +} + /* weapon's skill category name for use as generalized description of weapon; mostly used to shorten "you drop your " messages when slippery fingers or polymorph causes hero to involuntarily drop wielded weapon(s) */ @@ -871,7 +867,7 @@ boolean verbose; } /* copy the skill level name into the given buffer */ -STATIC_OVL char * +char * skill_level_name(skill, buf) int skill; char *buf; @@ -906,6 +902,13 @@ char *buf; return buf; } +const char * +skill_name(skill) +int skill; +{ + return P_NAME(skill); +} + /* return the # of slots required to advance the skill */ STATIC_OVL int slots_required(skill) @@ -932,8 +935,7 @@ int skill; } /* return true if this skill can be advanced */ -/*ARGSUSED*/ -STATIC_OVL boolean +boolean can_advance(skill, speedy) int skill; boolean speedy; diff --git a/win/X11/winX.c b/win/X11/winX.c index 0c1016da9..7337e6f04 100644 --- a/win/X11/winX.c +++ b/win/X11/winX.c @@ -202,6 +202,9 @@ boolean init; static int numlines = 0; struct xwindow *wp = &window_list[WIN_MESSAGE]; + if (init) + curr = (struct line_element *) 0; + if (!curr) { curr = wp->mesg_information->head; numlines = 0; @@ -1920,35 +1923,38 @@ char *input; /* Display file ----------------------------------------------------------- */ +/* uses a menu (with no selectors specified) rather than a text window + to allow previous_page and first_menu actions to move backwards */ void X11_display_file(str, complain) const char *str; boolean complain; { dlb *fp; + winid newwin; + struct xwindow *wp; + anything any; + menu_item *menu_list; #define LLEN 128 char line[LLEN]; /* Use the port-independent file opener to see if the file exists. */ fp = dlb_fopen(str, RDTMODE); - if (!fp) { if (complain) pline("Cannot open %s. Sorry.", str); return; /* it doesn't exist, ignore */ } - winid newwin = X11_create_nhwindow(NHW_MENU); - struct xwindow *wp = &window_list[newwin]; - anything any = zeroany; - menu_item *menu_list; - + newwin = X11_create_nhwindow(NHW_MENU); + wp = &window_list[newwin]; X11_start_menu(newwin); + any = zeroany; while (dlb_fgets(line, LLEN, fp)) { - X11_add_menu(newwin, NO_GLYPH, &any, 0, 0, ATR_NONE, line, MENU_UNSELECTED); + X11_add_menu(newwin, NO_GLYPH, &any, 0, 0, ATR_NONE, + line, MENU_UNSELECTED); } - (void) dlb_fclose(fp); /* show file name as the window title */ diff --git a/win/X11/winmenu.c b/win/X11/winmenu.c index 05f0bba36..eaba350d4 100644 --- a/win/X11/winmenu.c +++ b/win/X11/winmenu.c @@ -254,7 +254,8 @@ Cardinal *num_params; return; } - if (menu_info->is_active && menu_info->how != PICK_NONE) { /* waiting for input */ + /* don't exclude PICK_NONE menus; doing so disables scrolling via keys */ + if (menu_info->is_active) { /* waiting for input */ /* first check for an explicit selector match, so that it won't be overridden if it happens to duplicate a mapped menu command (':' to look inside a container vs ':' to select via search string) */ @@ -324,12 +325,14 @@ Cardinal *num_params; } else if (ch == MENU_FIRST_PAGE || ch == MENU_LAST_PAGE) { Widget hbar = (Widget) 0, vbar = (Widget) 0; float top = (ch == MENU_FIRST_PAGE) ? 0.0 : 1.0; + find_scrollbars(wp->w, &hbar, &vbar); if (vbar) XtCallCallbacks(vbar, XtNjumpProc, &top); return; } else if (ch == MENU_NEXT_PAGE || ch == MENU_PREVIOUS_PAGE) { Widget hbar = (Widget) 0, vbar = (Widget) 0; + find_scrollbars(wp->w, &hbar, &vbar); if (vbar) { float shown, top; @@ -1029,7 +1032,9 @@ Widget form,under; num_args = 0; XtSetArg(args[num_args], nhStr(XtNfromVert), label); num_args++; XtSetArg(args[num_args], nhStr(XtNfromHoriz), ok); num_args++; +#if 0 /* [cancel] is a viable choice even for PICK_NONE */ XtSetArg(args[num_args], nhStr(XtNsensitive), how != PICK_NONE); num_args++; +#endif XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++; XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop); num_args++; XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++; diff --git a/win/tty/topl.c b/win/tty/topl.c index 8aed570e7..97919a3d9 100644 --- a/win/tty/topl.c +++ b/win/tty/topl.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 topl.c $NHDT-Date: 1490908468 2017/03/30 21:14:28 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.36 $ */ +/* NetHack 3.6 topl.c $NHDT-Date: 1540934784 2018/10/30 21:26:24 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.38 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2009. */ /* NetHack may be freely redistributed. See license for details. */ @@ -637,7 +637,7 @@ boolean init; * * It's also called by the quest pager code when a block message * has a one-line summary specified. We put that line directly - * message history for ^P recall without having displayed it. + * into message history for ^P recall without having displayed it. */ void tty_putmsghistory(msg, restoring_msghist)