From c59b7bf11b5fa7cea516f63da0615d8fe7d23072 Mon Sep 17 00:00:00 2001 From: PatR Date: Sat, 4 Nov 2017 16:04:46 -0700 Subject: [PATCH 01/14] fix #H6391 - artifact #invoke for charging Latent bug: if a non-role-specific artifact which could be invoked for charging existed, it would never work as if blessed because the test for no-role was wrong. Caused when 3.3.0 changed the Role_if() predicate and artilist[] array to use monster index numbers (PM_foo) instead of role letters; the non-role value changed from '\0' to NON_PM (-1) but the test for non-role didn't. No fixes36.1 entry; there aren't any artifacts which were affected. --- src/artifact.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/artifact.c b/src/artifact.c index 25fc17118..a7678551a 100644 --- a/src/artifact.c +++ b/src/artifact.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 artifact.c $NHDT-Date: 1451081581 2015/12/25 22:13:01 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.99 $ */ +/* NetHack 3.6 artifact.c $NHDT-Date: 1509836679 2017/11/04 23:04:39 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.106 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1496,8 +1496,8 @@ struct obj *obj; obj->age = 0; return 0; } - b_effect = (obj->blessed - && (Role_switch == oart->role || !oart->role)); + b_effect = (obj->blessed && (oart->role == Role_switch + || oart->role == NON_PM)); recharge(otmp, b_effect ? 1 : obj->cursed ? -1 : 0); update_inventory(); break; From b87db2dd3f38b70c82425bf8c090bea3aac75b42 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Sun, 5 Nov 2017 14:17:22 +0200 Subject: [PATCH 02/14] Init variables to random --- src/sp_lev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sp_lev.c b/src/sp_lev.c index fc1dcf9e1..f5a532230 100644 --- a/src/sp_lev.c +++ b/src/sp_lev.c @@ -1435,7 +1435,7 @@ create_trap(t, croom) trap *t; struct mkroom *croom; { - schar x, y; + schar x = -1, y = -1; coord tm; if (croom) @@ -1994,7 +1994,7 @@ create_altar(a, croom) altar *a; struct mkroom *croom; { - schar sproom, x, y; + schar sproom, x = -1, y = -1; aligntyp amask; boolean croom_is_temple = TRUE; int oldtyp; From 81b14616005090dc054c958c0ffad24bed5c5dfe Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Sun, 5 Nov 2017 17:11:37 +0200 Subject: [PATCH 03/14] Explicitly ignore the return value Fixes scan-build complaint about dead assignment --- src/apply.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/apply.c b/src/apply.c index ca72cc466..130a53d33 100644 --- a/src/apply.c +++ b/src/apply.c @@ -1861,8 +1861,8 @@ struct obj *obj; verbalize(you_buy_it); useupf(corpse, 1L); } - can = hold_another_object(can, "You make, but cannot pick up, %s.", - doname(can), (const char *) 0); + (void) hold_another_object(can, "You make, but cannot pick up, %s.", + doname(can), (const char *) 0); } else impossible("Tinning failed."); } @@ -2807,8 +2807,8 @@ struct obj *obj; pline("Snatching %s is a fatal mistake.", kbuf); instapetrify(kbuf); } - otmp = hold_another_object( - otmp, "You drop %s!", doname(otmp), (const char *) 0); + (void) hold_another_object(otmp, "You drop %s!", + doname(otmp), (const char *) 0); break; default: /* to floor beneath mon */ From 5a31603680c2816bf9c690f69e78cb00a73c13c8 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 6 Nov 2017 01:28:48 +0000 Subject: [PATCH 04/14] Intentionally spoil foodpois mechanics when it happens One of the huge strengths of NetHack is that there's a lot of mechanical content in it; you can continue learning about the game more or less continuously, and when you die, it's usually possible to figure out what you did wrong and avoid that for future games. There are two parts to this: a) a death should only happen if the player didn't play perfectly, b) the nature of the problem should be clear. FoodPois status meets a) just fine, but not b); food poisoning mechanics tend (based on my research) to actively give the wrong impression to new players. (Normally, something along the lines of "corpses are sometimes randomly dangerous", which is insidious in the sense that it'll cause players to leave them as a last resort and thus never discover what they're doing wrong.) The easiest way to fix this is to explain what the rule is explicitly. Additionally, this should hopefully go some way towards changing the incorrect perception many people who haven't played (any/much) NetHack have that the game is arbitrarily cruel... It's important to get the "everything happens for a reason" attitude across from an early stage, by tying it to an event like this that's commonly seen by new plyers. Experienced players should not be affected much if at all by this change, because they hardly ever get food poisoning anyway. (Note: there are actually two main mechanics related to food poisoning, one widely applicable, one much more subtle. The message here is focused mainly on the common case, but doesn't actually contradict the rare case, and attentive players may be able to deduce both mechanics from the one message. Most likely, players will hit the common case, see the message, learn the common case, and some time later hit the rare case, get the message again, and read it more carefully this time.) --- src/eat.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/eat.c b/src/eat.c index a1b4bc33d..ae690a1b2 100644 --- a/src/eat.c +++ b/src/eat.c @@ -1616,6 +1616,8 @@ struct obj *otmp; sick_time = (Sick > 1L) ? Sick - 1L : 1L; make_sick(sick_time, corpse_xname(otmp, "rotted", CXN_NORMAL), TRUE, SICK_VOMITABLE); + + pline("(It must have died too long ago to be safe to eat.)"); } if (carried(otmp)) useup(otmp); From c2f767e1feb3a0f06ea66c24ca8e92ee897734a3 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Mon, 6 Nov 2017 15:28:13 +0200 Subject: [PATCH 05/14] Fix a warning --- src/do_name.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/do_name.c b/src/do_name.c index 38b90fc45..6e3bfd981 100644 --- a/src/do_name.c +++ b/src/do_name.c @@ -40,12 +40,12 @@ static void FDECL((*getpos_hilitefunc), (int)) = (void FDECL((*), (int))) 0; static boolean FDECL((*getpos_getvalid), (int,int)) = (boolean FDECL((*), (int,int))) 0; void -getpos_sethilite(f, d) -void FDECL((*f), (int)); -boolean FDECL((*d), (int,int)); +getpos_sethilite(gp_hilitef, gp_getvalidf) +void FDECL((*gp_hilitef), (int)); +boolean FDECL((*gp_getvalidf), (int,int)); { - getpos_hilitefunc = f; - getpos_getvalid = d; + getpos_hilitefunc = gp_hilitef; + getpos_getvalid = gp_getvalidf; } const char *const gloc_descr[NUM_GLOCS][4] = { From 2f4fcb837d2c6a51f25f739e83bc06437bc9aa5c Mon Sep 17 00:00:00 2001 From: PatR Date: Sun, 12 Nov 2017 16:06:28 -0800 Subject: [PATCH 06/14] monst.c comment formatting --- src/monst.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/monst.c b/src/monst.c index 18178bf0a..ace007141 100644 --- a/src/monst.c +++ b/src/monst.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 monst.c $NHDT-Date: 1451084423 2015/12/25 23:00:23 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.55 $ */ +/* NetHack 3.6 monst.c $NHDT-Date: 1510531569 2017/11/13 00:06:09 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.59 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2361,8 +2361,8 @@ struct permonst _mons2[] = { M1_HUMANOID | M1_POIS | M1_SWIM, M2_NOPOLY | M2_DEMON | M2_STALK | M2_HOSTILE | M2_NASTY | M2_COLLECT, M3_INFRAVISIBLE | M3_INFRAVISION, CLR_BLUE), -/* standard demons & devils - */ + /* standard demons & devils + */ #define SEDUCTION_ATTACKS_YES \ A(ATTK(AT_BITE, AD_SSEX, 0, 0), ATTK(AT_CLAW, AD_PHYS, 1, 3), \ ATTK(AT_CLAW, AD_PHYS, 1, 3), NO_ATTK, NO_ATTK, NO_ATTK) @@ -2387,8 +2387,8 @@ struct permonst _mons2[] = { MR_FIRE | MR_POISON, 0, M1_HUMANOID | M1_FLY | M1_POIS, M2_DEMON | M2_STALK | M2_HOSTILE | M2_NASTY | M2_MALE, M3_INFRAVISIBLE | M3_INFRAVISION, CLR_GRAY), - /* Used by AD&D for a type of demon, originally one of the Furies */ - /* and spelled this way */ + /* Used by AD&D for a type of demon, originally one of the Furies + and spelled this way */ MON("erinys", S_DEMON, LVL(7, 12, 2, 30, 10), (G_HELL | G_NOCORPSE | G_SGROUP | 2), A(ATTK(AT_WEAP, AD_DRST, 2, 4), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, @@ -2559,7 +2559,8 @@ struct permonst _mons2[] = { M2_NOPOLY | M2_DEMON | M2_STALK | M2_HOSTILE | M2_PNAME | M2_NASTY | M2_PRINCE | M2_MALE, M3_WANTSAMUL | M3_INFRAVISIBLE | M3_INFRAVISION, HI_LORD), - /* Riders -- the Four Horsemen of the Apocalypse ("War" == player) + /* Riders -- the Four Horsemen of the Apocalypse ("War" == player); + * depicted with '&' but do not have M2_DEMON set. */ MON("Death", S_DEMON, LVL(30, 12, -5, 100, 0), (G_UNIQ | G_NOGEN), A(ATTK(AT_TUCH, AD_DETH, 8, 8), ATTK(AT_TUCH, AD_DETH, 8, 8), NO_ATTK, @@ -2585,8 +2586,8 @@ struct permonst _mons2[] = { M1_FLY | M1_HUMANOID | M1_REGEN | M1_SEE_INVIS | M1_TPORT_CNTRL, M2_NOPOLY | M2_STALK | M2_HOSTILE | M2_PNAME | M2_STRONG | M2_NASTY, M3_INFRAVISIBLE | M3_INFRAVISION | M3_DISPLACES, HI_LORD), -/* other demons - */ + /* other demons + */ #ifdef MAIL MON("mail daemon", S_DEMON, LVL(56, 24, 10, 127, 0), (G_NOGEN | G_NOCORPSE), @@ -2703,14 +2704,12 @@ struct permonst _mons2[] = { /* * dummy monster needed for visual interface - */ - /* (marking it unique prevents figurines) + * (marking it unique prevents figurines) */ MON("long worm tail", S_WORM_TAIL, LVL(0, 0, 0, 0, 0), (G_NOGEN | G_NOCORPSE | G_UNIQ), A(NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(0, 0, 0, 0), 0, 0, 0L, M2_NOPOLY, 0, CLR_BROWN), - /* Note: * Worm tail must be between the normal monsters and the special * quest & pseudo-character ones because an optimization in the @@ -2854,8 +2853,8 @@ struct permonst _mons2[] = { | M2_COLLECT | M2_MAGIC, M3_CLOSE | M3_INFRAVISIBLE, HI_LORD), #if 0 /* OBSOLETE */ - /* Two for elves - one of each sex. - */ + /* Two for elves - one of each sex. + */ MON("Earendil", S_HUMAN, LVL(20, 12, 0, 50, -20), (G_NOGEN | G_UNIQ), A(ATTK(AT_WEAP, AD_PHYS, 1, 8), From b4b3dedd59f182437112f304dfcf915100bc09ae Mon Sep 17 00:00:00 2001 From: PatR Date: Sun, 12 Nov 2017 17:35:30 -0800 Subject: [PATCH 07/14] options.c formatting --- src/options.c | 259 ++++++++++++++++++++++++++------------------------ 1 file changed, 137 insertions(+), 122 deletions(-) diff --git a/src/options.c b/src/options.c index bfd42b189..511b31a00 100644 --- a/src/options.c +++ b/src/options.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 options.c $NHDT-Date: 1508827592 2017/10/24 06:46:32 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.316 $ */ +/* NetHack 3.6 options.c $NHDT-Date: 1510536906 2017/11/13 01:35:06 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.318 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -106,8 +106,7 @@ static struct Bool_Opt { #endif { "confirm", &flags.confirm, TRUE, SET_IN_GAME }, { "dark_room", &flags.dark_room, TRUE, SET_IN_GAME }, - { "eight_bit_tty", &iflags.wc_eight_bit_input, FALSE, - SET_IN_GAME }, /*WC*/ + { "eight_bit_tty", &iflags.wc_eight_bit_input, FALSE, SET_IN_GAME }, /*WC*/ #ifdef TTY_GRAPHICS { "extmenu", &iflags.extmenu, FALSE, SET_IN_GAME }, #else @@ -408,8 +407,9 @@ static struct Comp_Opt { #endif { "whatis_coord", "show coordinates when auto-describing cursor position", 1, SET_IN_GAME }, - { "whatis_filter", "filter coordinate locations when targeting next or previous", - 1, SET_IN_GAME }, + { "whatis_filter", + "filter coordinate locations when targeting next or previous", + 1, SET_IN_GAME }, { "windowcolors", "the foreground/background colors of windows", /*WC*/ 80, DISP_IN_GAME }, { "windowtype", "windowing system to use", WINTYPELEN, DISP_IN_GAME }, @@ -492,7 +492,8 @@ static const menu_cmd_t default_menu_cmd_info[] = { { "menu_deselect_all", MENU_UNSELECT_ALL, "Unselect all items" }, { "menu_invert_all", MENU_INVERT_ALL, "Invert selection" }, { "menu_select_page", MENU_SELECT_PAGE, "Select items in current page" }, - { "menu_deselect_page", MENU_UNSELECT_PAGE, "Unselect items in current page" }, + { "menu_deselect_page", MENU_UNSELECT_PAGE, + "Unselect items in current page" }, { "menu_invert_page", MENU_INVERT_PAGE, "Invert current page selection" }, { "menu_search", MENU_SEARCH, "Search and toggle matching items" }, }; @@ -713,8 +714,8 @@ initoptions_init() iflags.getpos_coords = GPCOORDS_NONE; /* hero's role, race, &c haven't been chosen yet */ - flags.initrole = flags.initrace = flags.initgend = flags.initalign = - ROLE_NONE; + flags.initrole = flags.initrace = flags.initgend = flags.initalign + = ROLE_NONE; /* Set the default monster and object class symbols. */ init_symbols(); @@ -1165,14 +1166,14 @@ int on_or_off; /*-- ON --*/ if (iflags.opt_booldup) impossible("iflags.opt_booldup already on (memory leak)"); - iflags.opt_booldup = (int *) alloc(SIZE(boolopt) * sizeof(int)); + iflags.opt_booldup = (int *) alloc(SIZE(boolopt) * sizeof (int)); optptr = iflags.opt_booldup; for (k = 0; k < SIZE(boolopt); ++k) *optptr++ = 0; if (iflags.opt_compdup) impossible("iflags.opt_compdup already on (memory leak)"); - iflags.opt_compdup = (int *) alloc(SIZE(compopt) * sizeof(int)); + iflags.opt_compdup = (int *) alloc(SIZE(compopt) * sizeof (int)); optptr = iflags.opt_compdup; for (k = 0; k < SIZE(compopt); ++k) *optptr++ = 0; @@ -1233,7 +1234,7 @@ int iscompound; /* 0 == boolean option, 1 == compound */ */ #else /* !MAC */ config_error_add("%s option specified multiple times: %s", - iscompound ? "compound" : "boolean", opts); + iscompound ? "compound" : "boolean", opts); #endif /* ?MAC */ return; } @@ -1458,7 +1459,7 @@ const char *prompt; static const struct { const char *name; - const xchar msgtyp; + xchar msgtyp; const char *descr; } msgtype_names[] = { { "show", MSGTYP_NORMAL, "Show message normally" }, @@ -1514,11 +1515,9 @@ msgtype_add(typ, pattern) int typ; char *pattern; { - struct plinemsg_type *tmp - = (struct plinemsg_type *) alloc(sizeof (struct plinemsg_type)); + struct plinemsg_type + *tmp = (struct plinemsg_type *) alloc(sizeof (struct plinemsg_type)); - if (!tmp) - return FALSE; tmp->msgtype = typ; tmp->regex = regex_init(); if (!regex_compile(pattern, tmp->regex)) { @@ -1670,7 +1669,8 @@ const char *errmsg; } if (!regex_compile(str, match)) { - config_error_add("%s: %s", errmsg ? errmsg : re_error, regex_error_desc(match)); + config_error_add("%s: %s", errmsg ? errmsg : re_error, + regex_error_desc(match)); retval = FALSE; } regex_free(match); @@ -1901,7 +1901,7 @@ boolean tinitial, tfrom_file; } if (strlen(opts) > BUFSZ / 2) { config_error_add("Option too long, max length is %i characters", - (BUFSZ / 2)); + (BUFSZ / 2)); return FALSE; } @@ -2025,8 +2025,7 @@ boolean tinitial, tfrom_file; /* We always check for duplicates on the remaining compound options, although individual option processing can choose to complain or not */ - duplicate = - duplicate_opt_detection(opts, 1); /* 1 means check compounds */ + duplicate = duplicate_opt_detection(opts, 1); /* 1: check compounds */ fullname = "pettype"; if (match_optname(opts, fullname, 3, TRUE)) { @@ -2485,7 +2484,8 @@ boolean tinitial, tfrom_file; forig = fruit_from_name(pl_fruit, FALSE, (int *) 0); if (!forig && fnum >= 100) { - config_error_add("Doing that so many times isn't very fruitful."); + config_error_add( + "Doing that so many times isn't very fruitful."); return retval; } } @@ -2681,6 +2681,7 @@ boolean tinitial, tfrom_file; } return retval; } + /* WINCAP * align_message:[left|top|right|bottom] */ fullname = "align_message"; @@ -2707,7 +2708,8 @@ boolean tinitial, tfrom_file; } return retval; } - /* the order to list the pack */ + + /* the order to list inventory */ fullname = "packorder"; if (match_optname(opts, fullname, 4, TRUE)) { if (duplicate) @@ -2831,9 +2833,10 @@ boolean tinitial, tfrom_file; } /* types of objects to pick up automatically */ - if (match_optname(opts, "pickup_types", 8, TRUE)) { + fullname = "pickup_types"; + if (match_optname(opts, fullname, 8, TRUE)) { char ocl[MAXOCLASSES + 1], tbuf[MAXOCLASSES + 1], qbuf[QBUFSZ], - abuf[BUFSZ]; + abuf[BUFSZ]; int oc_sym; boolean badopt = FALSE, compat = (strlen(opts) <= 6), use_menu; @@ -2855,7 +2858,7 @@ boolean tinitial, tfrom_file; if (flags.menu_style == MENU_TRADITIONAL || flags.menu_style == MENU_COMBINATION) { use_menu = FALSE; - Sprintf(qbuf, "New pickup_types: [%s am] (%s)", ocl, + Sprintf(qbuf, "New %s: [%s am] (%s)", fullname, ocl, *tbuf ? tbuf : "all"); getlin(qbuf, abuf); op = mungspaces(abuf); @@ -2871,7 +2874,7 @@ boolean tinitial, tfrom_file; } } if (negated) { - bad_negation("pickup_types", TRUE); + bad_negation(fullname, TRUE); return FALSE; } while (*op == ' ') @@ -2890,8 +2893,7 @@ boolean tinitial, tfrom_file; op++; } if (badopt) { - config_error_add("Unknown %s parameter '%s'", - "pickup_types", op); + config_error_add("Unknown %s parameter '%s'", fullname, op); return FALSE; } } @@ -3256,10 +3258,11 @@ boolean tinitial, tfrom_file; } return retval; } + /* WINCAP * scroll_amount:nn */ fullname = "scroll_amount"; - if (match_optname(opts, fullname, sizeof("scroll_amount") - 1, TRUE)) { + if (match_optname(opts, fullname, sizeof "scroll_amount" - 1, TRUE)) { if (duplicate) complain_about_duplicate(opts, 1); op = string_for_opt(opts, negated); @@ -3271,10 +3274,11 @@ boolean tinitial, tfrom_file; } return retval; } + /* WINCAP * scroll_margin:nn */ fullname = "scroll_margin"; - if (match_optname(opts, fullname, sizeof("scroll_margin") - 1, TRUE)) { + if (match_optname(opts, fullname, sizeof "scroll_margin" - 1, TRUE)) { if (duplicate) complain_about_duplicate(opts, 1); op = string_for_opt(opts, negated); @@ -3286,6 +3290,7 @@ boolean tinitial, tfrom_file; } return retval; } + fullname = "subkeyvalue"; if (match_optname(opts, fullname, 5, TRUE)) { /* no duplicate complaint here */ @@ -3302,6 +3307,7 @@ boolean tinitial, tfrom_file; } return retval; } + /* WINCAP * tile_width:nn */ fullname = "tile_width"; @@ -3346,6 +3352,7 @@ boolean tinitial, tfrom_file; } return retval; } + /* WINCAP * vary_msgcount:nn */ fullname = "vary_msgcount"; @@ -3361,6 +3368,19 @@ boolean tinitial, tfrom_file; } return retval; } + + /* + * windowtype: option to choose the interface for binaries built + * with support for more than one interface (tty + X11, for instance). + * + * Ideally, 'windowtype' should be processed first, because it + * causes the wc_ and wc2_ flags to be set up. + * For user, making it be first in a config file is trivial, use + * OPTIONS=windowtype:Foo + * as the first non-comment line of the file. + * Making it first in NETHACKOPTIONS requires it to be at the _end_ + * because option strings are processed from right to left. + */ fullname = "windowtype"; if (match_optname(opts, fullname, 3, TRUE)) { if (duplicate) @@ -3370,6 +3390,7 @@ boolean tinitial, tfrom_file; return FALSE; } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) { char buf[WINTYPELEN]; + nmcpy(buf, op, WINTYPELEN); choose_windows(buf); } else @@ -3385,6 +3406,7 @@ boolean tinitial, tfrom_file; return FALSE; } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) { char buf[WINTYPELEN]; + nmcpy(buf, op, WINTYPELEN); addto_windowchain(buf); } else @@ -3452,6 +3474,7 @@ boolean tinitial, tfrom_file; fullname = "menu_headings"; if (match_optname(opts, fullname, 12, TRUE)) { int tmpattr; + if (duplicate) complain_about_duplicate(opts, 1); if (negated) { @@ -3491,6 +3514,7 @@ boolean tinitial, tfrom_file; return retval; } } + /* hilite fields in status prompt */ fullname = "hilite_status"; if (match_optname(opts, fullname, 13, TRUE)) { @@ -3886,8 +3910,10 @@ get_menu_cmd_key(ch) char ch; { char *found = index(mapped_menu_op, ch); + if (found) { int idx = (int) (found - mapped_menu_op); + ch = mapped_menu_cmds[idx]; } return ch; @@ -3902,8 +3928,10 @@ map_menu_cmd(ch) char ch; { char *found = index(mapped_menu_cmds, ch); + if (found) { int idx = (int) (found - mapped_menu_cmds); + ch = mapped_menu_op[idx]; } return ch; @@ -3919,6 +3947,7 @@ boolean dolist; putstr(win, 0, "Menu control keys:"); if (dolist) { int i; + for (i = 0; i < SIZE(default_menu_cmd_info); i++) { Sprintf(buf, "%-8s %s", visctrl(get_menu_cmd_key(default_menu_cmd_info[i].cmd)), @@ -4186,8 +4215,7 @@ doset() /* changing options via menu by Per Liboriussen */ any = zeroany; add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED); add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings, - "Other settings:", - MENU_UNSELECTED); + "Other settings:", MENU_UNSELECTED); for (i = 0; (name = othropt[i].name) != 0; i++) { if ((is_wc_option(name) && !wc_supported(name)) @@ -4216,7 +4244,8 @@ doset() /* changing options via menu by Per Liboriussen */ */ for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) { opt_indx = pick_list[pick_idx].item.a_int - 1; - if (opt_indx < -1) opt_indx++; /* -1 offset for select_menu() */ + if (opt_indx < -1) + opt_indx++; /* -1 offset for select_menu() */ if (opt_indx == OPT_OTHER_APEXC) { (void) special_handling("autopickup_exception", setinitial, fromfile); @@ -4342,6 +4371,7 @@ boolean setinitial, setfromfile; if (!strcmp("menustyle", optname)) { const char *style_name; menu_item *style_pick = (menu_item *) 0; + tmpwin = create_nhwindow(NHW_MENU); start_menu(tmpwin); any = zeroany; @@ -4529,8 +4559,8 @@ boolean setinitial, setfromfile; 0, ATR_NONE, "compass ('east' or '3s' or '2n,4w')", (gp == GPCOORDS_COMPASS) ? MENU_SELECTED : MENU_UNSELECTED); any.a_char = GPCOORDS_COMFULL; - add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_COMFULL, - 0, ATR_NONE, "full compass ('east' or '3south' or '2north,4west')", + add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_COMFULL, 0, ATR_NONE, + "full compass ('east' or '3south' or '2north,4west')", (gp == GPCOORDS_COMFULL) ? MENU_SELECTED : MENU_UNSELECTED); any.a_char = GPCOORDS_MAP; add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_MAP, @@ -4596,7 +4626,7 @@ boolean setinitial, setfromfile; 0, ATR_NONE, "in same area", (gf == GFILTER_AREA) ? MENU_SELECTED : MENU_UNSELECTED); end_menu(tmpwin, - "Select location filtering when going for next/previous map position:"); + "Select location filtering when going for next/previous map position:"); if ((pick_cnt = select_menu(tmpwin, PICK_ONE, &window_pick)) > 0) { iflags.getloc_filter = (window_pick[0].item.a_char - 1); /* PICK_ONE doesn't unselect preselected entry when @@ -4955,10 +4985,7 @@ boolean setinitial, setfromfile; struct symsetentry *sl; int res, which_set, setcount = 0, chosen = -2; - if (rogueflag) - which_set = ROGUESET; - else - which_set = PRIMARY; + which_set = rogueflag ? ROGUESET : PRIMARY; /* clear symset[].name as a flag to read_sym_file() to build list */ symset_name = symset[which_set].name; @@ -5238,36 +5265,23 @@ char *buf; Sprintf(buf, "%s", rolestring(flags.initgend, genders, adj)); else if (!strcmp(optname, "horsename")) Sprintf(buf, "%s", horsename[0] ? horsename : none); - else if (!strcmp(optname, "map_mode")) + else if (!strcmp(optname, "map_mode")) { + i = iflags.wc_map_mode; Sprintf(buf, "%s", - iflags.wc_map_mode == MAP_MODE_TILES - ? "tiles" - : iflags.wc_map_mode == MAP_MODE_ASCII4x6 - ? "ascii4x6" - : iflags.wc_map_mode == MAP_MODE_ASCII6x8 - ? "ascii6x8" - : iflags.wc_map_mode == MAP_MODE_ASCII8x8 - ? "ascii8x8" - : iflags.wc_map_mode == MAP_MODE_ASCII16x8 - ? "ascii16x8" - : iflags.wc_map_mode == MAP_MODE_ASCII7x12 - ? "ascii7x12" - : iflags.wc_map_mode == MAP_MODE_ASCII8x12 - ? "ascii8x12" - : iflags.wc_map_mode - == MAP_MODE_ASCII16x12 - ? "ascii16x12" - : iflags.wc_map_mode - == MAP_MODE_ASCII12x16 - ? "ascii12x16" - : iflags.wc_map_mode - == MAP_MODE_ASCII10x18 - ? "ascii10x18" - : iflags.wc_map_mode - == MAP_MODE_ASCII_FIT_TO_SCREEN - ? "fit_to_screen" - : defopt); - else if (!strcmp(optname, "menustyle")) + (i == MAP_MODE_TILES) ? "tiles" + : (i == MAP_MODE_ASCII4x6) ? "ascii4x6" + : (i == MAP_MODE_ASCII6x8) ? "ascii6x8" + : (i == MAP_MODE_ASCII8x8) ? "ascii8x8" + : (i == MAP_MODE_ASCII16x8) ? "ascii16x8" + : (i == MAP_MODE_ASCII7x12) ? "ascii7x12" + : (i == MAP_MODE_ASCII8x12) ? "ascii8x12" + : (i == MAP_MODE_ASCII16x12) ? "ascii16x12" + : (i == MAP_MODE_ASCII12x16) ? "ascii12x16" + : (i == MAP_MODE_ASCII10x18) ? "ascii10x18" + : (i == MAP_MODE_ASCII_FIT_TO_SCREEN) + ? "fit_to_screen" + : defopt); + } else if (!strcmp(optname, "menustyle")) Sprintf(buf, "%s", menutype[(int) flags.menu_style]); else if (!strcmp(optname, "menu_deselect_all")) Sprintf(buf, "%s", to_be_done); @@ -5299,13 +5313,10 @@ char *buf; Sprintf(buf, "%u", iflags.msg_history); #ifdef TTY_GRAPHICS } else if (!strcmp(optname, "msg_window")) { - Sprintf(buf, "%s", (iflags.prevmsg_window == 's') - ? "single" - : (iflags.prevmsg_window == 'c') - ? "combination" - : (iflags.prevmsg_window == 'f') - ? "full" - : "reversed"); + Sprintf(buf, "%s", (iflags.prevmsg_window == 's') ? "single" + : (iflags.prevmsg_window == 'c') ? "combination" + : (iflags.prevmsg_window == 'f') ? "full" + : "reversed"); #endif } else if (!strcmp(optname, "name")) { Sprintf(buf, "%s", plname); @@ -5589,8 +5600,9 @@ count_ape_maps(leave, grab) int *leave, *grab; { struct autopickup_exception *ape; - int pass, totalapes, numapes[2] = { 0, 0 }; + int pass, totalapes, numapes[2]; + numapes[0] = numapes[1] = 0; for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) { ape = iflags.autopickup_exceptions[pass]; while (ape) { @@ -6075,53 +6087,56 @@ char *class_select; return ret; } -struct wc_Opt wc_options[] = { { "ascii_map", WC_ASCII_MAP }, - { "color", WC_COLOR }, - { "eight_bit_tty", WC_EIGHT_BIT_IN }, - { "hilite_pet", WC_HILITE_PET }, - { "popup_dialog", WC_POPUP_DIALOG }, - { "player_selection", WC_PLAYER_SELECTION }, - { "preload_tiles", WC_PRELOAD_TILES }, - { "tiled_map", WC_TILED_MAP }, - { "tile_file", WC_TILE_FILE }, - { "tile_width", WC_TILE_WIDTH }, - { "tile_height", WC_TILE_HEIGHT }, - { "use_inverse", WC_INVERSE }, - { "align_message", WC_ALIGN_MESSAGE }, - { "align_status", WC_ALIGN_STATUS }, - { "font_map", WC_FONT_MAP }, - { "font_menu", WC_FONT_MENU }, - { "font_message", WC_FONT_MESSAGE }, +static struct wc_Opt wc_options[] = { + { "ascii_map", WC_ASCII_MAP }, + { "color", WC_COLOR }, + { "eight_bit_tty", WC_EIGHT_BIT_IN }, + { "hilite_pet", WC_HILITE_PET }, + { "popup_dialog", WC_POPUP_DIALOG }, + { "player_selection", WC_PLAYER_SELECTION }, + { "preload_tiles", WC_PRELOAD_TILES }, + { "tiled_map", WC_TILED_MAP }, + { "tile_file", WC_TILE_FILE }, + { "tile_width", WC_TILE_WIDTH }, + { "tile_height", WC_TILE_HEIGHT }, + { "use_inverse", WC_INVERSE }, + { "align_message", WC_ALIGN_MESSAGE }, + { "align_status", WC_ALIGN_STATUS }, + { "font_map", WC_FONT_MAP }, + { "font_menu", WC_FONT_MENU }, + { "font_message", WC_FONT_MESSAGE }, #if 0 - {"perm_invent", WC_PERM_INVENT}, + {"perm_invent", WC_PERM_INVENT}, #endif - { "font_size_map", WC_FONTSIZ_MAP }, - { "font_size_menu", WC_FONTSIZ_MENU }, - { "font_size_message", WC_FONTSIZ_MESSAGE }, - { "font_size_status", WC_FONTSIZ_STATUS }, - { "font_size_text", WC_FONTSIZ_TEXT }, - { "font_status", WC_FONT_STATUS }, - { "font_text", WC_FONT_TEXT }, - { "map_mode", WC_MAP_MODE }, - { "scroll_amount", WC_SCROLL_AMOUNT }, - { "scroll_margin", WC_SCROLL_MARGIN }, - { "splash_screen", WC_SPLASH_SCREEN }, - { "vary_msgcount", WC_VARY_MSGCOUNT }, - { "windowcolors", WC_WINDOWCOLORS }, - { "mouse_support", WC_MOUSE_SUPPORT }, - { (char *) 0, 0L } }; - -struct wc_Opt wc2_options[] = { { "fullscreen", WC2_FULLSCREEN }, - { "softkeyboard", WC2_SOFTKEYBOARD }, - { "wraptext", WC2_WRAPTEXT }, - { "use_darkgray", WC2_DARKGRAY }, - { "hitpointbar", WC2_HITPOINTBAR }, - { "hilite_status", WC2_HILITE_STATUS }, - /* name shown in 'O' menu is different */ - { "status hilite rules", WC2_HILITE_STATUS }, - /* statushilites doesn't have its own bit */ - { "statushilites", WC2_HILITE_STATUS }, - { (char *) 0, 0L } }; + { "font_size_map", WC_FONTSIZ_MAP }, + { "font_size_menu", WC_FONTSIZ_MENU }, + { "font_size_message", WC_FONTSIZ_MESSAGE }, + { "font_size_status", WC_FONTSIZ_STATUS }, + { "font_size_text", WC_FONTSIZ_TEXT }, + { "font_status", WC_FONT_STATUS }, + { "font_text", WC_FONT_TEXT }, + { "map_mode", WC_MAP_MODE }, + { "scroll_amount", WC_SCROLL_AMOUNT }, + { "scroll_margin", WC_SCROLL_MARGIN }, + { "splash_screen", WC_SPLASH_SCREEN }, + { "vary_msgcount", WC_VARY_MSGCOUNT }, + { "windowcolors", WC_WINDOWCOLORS }, + { "mouse_support", WC_MOUSE_SUPPORT }, + { (char *) 0, 0L } +}; +static struct wc_Opt wc2_options[] = { + { "fullscreen", WC2_FULLSCREEN }, + { "softkeyboard", WC2_SOFTKEYBOARD }, + { "wraptext", WC2_WRAPTEXT }, + { "use_darkgray", WC2_DARKGRAY }, + { "hitpointbar", WC2_HITPOINTBAR }, + { "hilite_status", WC2_HILITE_STATUS }, + /* name shown in 'O' menu is different */ + { "status hilite rules", WC2_HILITE_STATUS }, + /* statushilites doesn't have its own bit */ + { "statushilites", WC2_HILITE_STATUS }, + { (char *) 0, 0L } +}; /* * If a port wants to change or ensure that the SET_IN_SYS, From 59d4ac02f7737216a54aa3957fe83f22e8a5f7e3 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Tue, 14 Nov 2017 15:57:18 +0200 Subject: [PATCH 08/14] TTY: Treat carriage return as newline Before this change, more-prompts and input text -prompts could not be accepted with carriage return. Now, just like in menus, carriage return is treated the same as a newline. To test, use 'stty -icrnl' --- doc/fixes36.1 | 1 + win/tty/getline.c | 8 ++------ win/tty/wintty.c | 2 ++ 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 04d4f53a1..c064ebb7f 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -596,6 +596,7 @@ PANICTRACE: PANICTRACE_GDB used wrong value for ARGV0 when launching gdb if win32gui: gather raw_print error messages into a single dialog window win32tty: fix display errors when using a font with double wide or ambiguous width characters +tty: treat carriage return as a newline for input text and more-prompts General New Features diff --git a/win/tty/getline.c b/win/tty/getline.c index f3dd6cbf2..a73fa4060 100644 --- a/win/tty/getline.c +++ b/win/tty/getline.c @@ -129,11 +129,7 @@ getlin_hook_proc hook; #endif /* NEWAUTOCOMP */ } else tty_nhbell(); -#if defined(apollo) } else if (c == '\n' || c == '\r') { -#else - } else if (c == '\n') { -#endif #ifndef NEWAUTOCOMP *bufp = 0; #endif /* not NEWAUTOCOMP */ @@ -213,7 +209,7 @@ register const char *s; /* chars allowed besides return */ !program_state.done_hup && #endif (c = tty_nhgetch()) != EOF) { - if (c == '\n') + if (c == '\n' || c == '\r') break; if (iflags.cbreak) { @@ -223,7 +219,7 @@ register const char *s; /* chars allowed besides return */ morc = '\033'; break; } - if ((s && index(s, c)) || c == x) { + if ((s && index(s, c)) || c == x || (x == '\n' && c == '\r')) { morc = (char) c; break; } diff --git a/win/tty/wintty.c b/win/tty/wintty.c index 821239c68..32dc6b3c5 100644 --- a/win/tty/wintty.c +++ b/win/tty/wintty.c @@ -1167,6 +1167,8 @@ tty_askname() while ((c = tty_nhgetch()) != '\n') { if (c == EOF) c = '\033'; + if (c == '\r') + break; if (c == '\033') { ct = 0; break; From 18aab1ab12f8e5033629e8a701287a5645c8455c Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Tue, 14 Nov 2017 19:32:31 +0200 Subject: [PATCH 09/14] Make shopkeepers bill hero for burying merchandise --- doc/fixes36.1 | 1 + src/dig.c | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index c064ebb7f..d78178c42 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -471,6 +471,7 @@ charisma affects the leeway in demon lord bribes make Vlad slightly tougher reduce the amount of gold laying on the floor locked chests and large boxes contain more stuff +make shopkeepers bill hero for burying merchandise Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository diff --git a/src/dig.c b/src/dig.c index 364d1cce6..497de8cd4 100644 --- a/src/dig.c +++ b/src/dig.c @@ -1863,16 +1863,33 @@ bury_objs(x, y) int x, y; { struct obj *otmp, *otmp2; + struct monst *shkp; + long loss = 0L; + boolean costly; + + costly = ((shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) + && costly_spot(x, y)); if (level.objects[x][y] != (struct obj *) 0) { debugpline2("bury_objs: at <%d,%d>", x, y); } - for (otmp = level.objects[x][y]; otmp; otmp = otmp2) + for (otmp = level.objects[x][y]; otmp; otmp = otmp2) { + if (costly) { + loss += stolen_value(otmp, x, y, (boolean) shkp->mpeaceful, TRUE); + if (otmp->oclass != COIN_CLASS) + otmp->no_charge = 1; + } otmp2 = bury_an_obj(otmp, (boolean *) 0); + } /* don't expect any engravings here, but just in case */ del_engr_at(x, y); newsym(x, y); + + if (costly && loss) { + You("owe %s %ld %s for burying merchandise.", mon_nam(shkp), loss, + currency(loss)); + } } /* move objects from buriedobjlist to fobj/nexthere lists */ From 761180ce3613f2f588443503de786ccf221e56bf Mon Sep 17 00:00:00 2001 From: PatR Date: Tue, 14 Nov 2017 15:31:26 -0800 Subject: [PATCH 10/14] vomiting while fainting From a beta-tester running 3.6.0: |You faint from lack of food. |You suddenly vomit! The latter has already been changed to "You vomit" (it's given at the end of a multiple-message vomiting countdown so wasn't "sudden") but is still odd if your stomach is so empty that you're subject to fainting. Give an alternate message in that case: |Your stomach heaves convulsively! Vomiting while unconscious (when that's due to something other than fainting from hunger) should pose a risk of choking to death, but I'm going to pretend that this hasn't occurred to me.... --- doc/fixes36.1 | 3 ++- src/eat.c | 10 ++++++++-- src/timeout.c | 6 ++++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index d78178c42..af1de2a6c 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -437,6 +437,7 @@ fix buffer overflow in wizard mode for '#' command when 'extmenu' option is on "you suddenly vomit" was given two turns before actually vomiting, so you could get that message, move a bit, then get "you can move again" after the 2 turn freeze applied along with the actual vomit +give an alternate message if you vomit when stomach is empty (ie, fainting) corpses and other flammable items not subject to direct burning or fire-based erosion which were thrown or dropped into lava remained intact if a potion on the floor survived a land mine explosion and got propelled at @@ -557,6 +558,7 @@ tty: if "--More--" was written to leftmost column (beginning of second line) tty: long message lines which wrap when shown on the top line might be re-displayed incorrectly by ^P for msg_window={full,combo,reverse} tty: MSGTYPE=hide could interfere with display of prompts +tty: treat carriage return as a newline for input text and --More-- prompts unix/X11: in top level Makefile, some commented out definitions of VARDATND misspelled pilemark.xbm (as pilemark.xpm) unix: options file with CR+LF line ends and an invalid option line resulted in @@ -597,7 +599,6 @@ PANICTRACE: PANICTRACE_GDB used wrong value for ARGV0 when launching gdb if win32gui: gather raw_print error messages into a single dialog window win32tty: fix display errors when using a font with double wide or ambiguous width characters -tty: treat carriage return as a newline for input text and more-prompts General New Features diff --git a/src/eat.c b/src/eat.c index ae690a1b2..dc33cca8a 100644 --- a/src/eat.c +++ b/src/eat.c @@ -3154,12 +3154,18 @@ skipfloor: void vomit() /* A good idea from David Neves */ { - if (cantvomit(youmonst.data)) + if (cantvomit(youmonst.data)) { /* doesn't cure food poisoning; message assumes that we aren't dealing with some esoteric body_part() */ Your("jaw gapes convulsively."); - else + } else { make_sick(0L, (char *) 0, TRUE, SICK_VOMITABLE); + /* if not enough in stomach to actually vomit then dry heave; + vomiting_dialog() gives a vomit message when its countdown + reaches 0, but only if u.uhs < FAINTING (and !cantvomit()) */ + if (u.uhs >= FAINTING) + Your("%s heaves convulsively!", body_part(STOMACH)); + } /* nomul()/You_can_move_again used to be unconditional, which was viable while eating but not for Vomiting countdown where hero might diff --git a/src/timeout.c b/src/timeout.c index a85baf552..b8535bbd5 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -204,8 +204,10 @@ vomiting_dialogue() that message and "You can move again." (from vomit()'s nomul(-2)) with no intervening message; give one here to have more specific point at which hero became unable to move - [vomit() issues its own message for the cantvomit() case] */ - You("%s!", !Hallucination ? "vomit" : "hurl chunks"); + [vomit() issues its own message for the cantvomit() case + and for the FAINTING-or-worse case where stomach is empty] */ + if (u.uhs < FAINTING) + You("%s!", !Hallucination ? "vomit" : "hurl chunks"); } vomit(); break; From 8e1b28a4532222bc33c21adf86910dfa904094b5 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 16 Nov 2017 16:42:16 +0000 Subject: [PATCH 11/14] Less misleading message when impossible() is called Telling people to #quit due to something going wrong internally is probably a bad idea; the game might or might not be corrupted, but even if it is, most players will want to play on rather than lose their game entirely. Instead, advise saving and reloading; this will fix the underlying cause of many impossible()s (which are normally related to inconsistent internal structures; the save file format has much less redundancy, therefore less chance of inconsistency, than the in-memory format). Thanks to AmyBSOD for reminding me to do this. --- src/pline.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pline.c b/src/pline.c index 270272042..b35a29f18 100644 --- a/src/pline.c +++ b/src/pline.c @@ -436,7 +436,8 @@ VA_DECL(const char *, s) pbuf[BUFSZ - 1] = '\0'; /* sanity */ paniclog("impossible", pbuf); pline("%s", VA_PASS1(pbuf)); - pline("%s", VA_PASS1("Program in disorder - perhaps you'd better #quit.")); + pline( + "Program in disorder! (Saving and reloading may fix this problem.)"); program_state.in_impossible = 0; VA_END(); } From 024906300ed1db22d2c9c32053c1ae258518759b Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 17 Nov 2017 16:05:35 -0800 Subject: [PATCH 12/14] options processing: ascii_map vs tiled_map Toggling either ascii_map or tiled_map with the X11 interface switches the map window from one style to another, but it was only working as intended when done via the 'O' command. Setting ascii_map via initial options only worked if tiled_map was explicitly cleared. This fixes that. --- src/options.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/options.c b/src/options.c index 511b31a00..1228f1a90 100644 --- a/src/options.c +++ b/src/options.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 options.c $NHDT-Date: 1510536906 2017/11/13 01:35:06 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.318 $ */ +/* NetHack 3.6 options.c $NHDT-Date: 1510963525 2017/11/18 00:05:25 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.319 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -3721,6 +3721,17 @@ boolean tinitial, tfrom_file; if (boolopt[i].addr == &iflags.zerocomp) set_savepref(iflags.zerocomp ? "zerocomp" : "externalcomp"); #endif + if (boolopt[i].addr == &iflags.wc_ascii_map) { + /* toggling ascii_map; set tiled_map to its opposite; + what does it mean to turn off ascii map if tiled map + isn't supported? -- right now, we do nothing */ + iflags.wc_tiled_map = negated; + } else if (boolopt[i].addr == &iflags.wc_tiled_map) { + /* toggling tiled_map; set ascii_map to its opposite; + as with ascii_map, what does it mean to turn off tiled + map if ascii map isn't supported? */ + iflags.wc_ascii_map = negated; + } /* only do processing below if setting with doset() */ if (initial) return retval; @@ -3750,22 +3761,12 @@ boolean tinitial, tfrom_file; vision_full_recalc = 1; /* delayed recalc */ if (iflags.use_color) need_redraw = TRUE; /* darkroom refresh */ - } else if (boolopt[i].addr == &iflags.wc_ascii_map) { - /* toggling ascii_map; set tiled_map to its opposite; - what does it mean to turn off ascii map if tiled map - isn't supported? -- right now, we do nothing */ - iflags.wc_tiled_map = negated; - need_redraw = TRUE; - } else if (boolopt[i].addr == &iflags.wc_tiled_map) { - /* toggling tiled_map; set ascii_map to its opposite; - as with ascii_map, what does it mean to turn off tiled - map if ascii map isn't supported? */ - iflags.wc_ascii_map = negated; - need_redraw = TRUE; } else if (boolopt[i].addr == &flags.showrace || boolopt[i].addr == &iflags.use_inverse || boolopt[i].addr == &iflags.hilite_pile - || boolopt[i].addr == &iflags.hilite_pet) { + || boolopt[i].addr == &iflags.hilite_pet + || boolopt[i].addr == &iflags.wc_ascii_map + || boolopt[i].addr == &iflags.wc_tiled_map) { need_redraw = TRUE; #ifdef STATUS_HILITES } else if (boolopt[i].addr == &iflags.wc2_hitpointbar) { From c9153a22efbf97ea820113a0d93fb5afa6e6bca4 Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 17 Nov 2017 23:38:28 -0800 Subject: [PATCH 13/14] impossible fixup For USE_OLDARGS, the varargs calls in pline.c actually need to pass a fixed number of arguments (padded with dummies for unused ones) when using a compiler which checks argument usage for consistency. pline.c used to be the only core source file which needs VA_PASSx() handling, but it looks like calls to config_error_add() in files.c now need it too. (If there were any calls to panic() in end.c, they would need it as well, but there aren't.) --- src/pline.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pline.c b/src/pline.c index b35a29f18..d6ee70266 100644 --- a/src/pline.c +++ b/src/pline.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 pline.c $NHDT-Date: 1501803108 2017/08/03 23:31:48 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.61 $ */ +/* NetHack 3.6 pline.c $NHDT-Date: 1510990667 2017/11/18 07:37:47 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.64 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -436,8 +436,8 @@ VA_DECL(const char *, s) pbuf[BUFSZ - 1] = '\0'; /* sanity */ paniclog("impossible", pbuf); pline("%s", VA_PASS1(pbuf)); - pline( - "Program in disorder! (Saving and reloading may fix this problem.)"); + pline(VA_PASS1( + "Program in disorder! (Saving and reloading may fix this problem.)")); program_state.in_impossible = 0; VA_END(); } From 59c357de9a783e2ef385cb3adee8107db8bb262d Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sun, 19 Nov 2017 16:16:00 +0000 Subject: [PATCH 14/14] Balance fix to level drain and potions of restore ability Right now, the punishment for being hit more than twice by a level drainer pre-Quest is disproportionate; grinding back up to level 14 from level 13 takes a long time, and yet isn't particularly difficult, just slow, and a potion of full healing will only regain one of the lost levels (as only half the lost levels can be regained this way). Meanwhile, potions of restore ability are currently automatically blanked by almost all spoiled players; they don't do anything that doesn't have more convenient sources (unicorn horn or the spell), so they're only useful in the very early game for getting poison resistance. This commit aims to fix both problems, by allowing potions of restore ability to restore lost experience levels, in addition to lost attribute points; an uncursed potion restores one lost level (with multiple potions making it possible to hit the cap), a blessed potion restores all of them. That gives players an incentive to keep them around rather than blanking them. (Notably, the spell and tool were not changed the same way; for restoring levels, you need to use the potion.) --- src/exper.c | 4 +++- src/potion.c | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/exper.c b/src/exper.c index 06456e0c0..675375ebe 100644 --- a/src/exper.c +++ b/src/exper.c @@ -293,9 +293,11 @@ boolean incr; /* true iff via incremental experience growth */ u.uexp = newuexp(u.ulevel); } ++u.ulevel; + pline("Welcome %sto experience level %d.", + u.ulevelmax < u.ulevel ? "" : "back ", + u.ulevel); if (u.ulevelmax < u.ulevel) u.ulevelmax = u.ulevel; - pline("Welcome to experience level %d.", u.ulevel); adjabil(u.ulevel - 1, u.ulevel); /* give new intrinsics */ reset_rndmonst(NON_PM); /* new monster selection */ } diff --git a/src/potion.c b/src/potion.c index 4925b27b0..5daa9fbcc 100644 --- a/src/potion.c +++ b/src/potion.c @@ -577,6 +577,18 @@ register struct obj *otmp; if (++i >= A_MAX) i = 0; } + + /* when using the potion (not the spell) also restore lost levels, + to make the potion more worth keeping around for players with + the spell or with a unihorn; this is better than full healing + in that it can restore all of them, not just half, and a + blessed potion restores them all at once */ + if (otmp->otyp == POT_RESTORE_ABILITY && + u.ulevel < u.ulevelmax) { + do { + pluslvl(FALSE); + } while (u.ulevel < u.ulevelmax && otmp->blessed); + } } break; case POT_HALLUCINATION: