From e9f1e032717921cb7a51c0f2822628355a35ec36 Mon Sep 17 00:00:00 2001 From: PatR Date: Sat, 19 May 2018 04:19:18 -0700 Subject: [PATCH] fix some of #H7156 - perm_invent issues > [1. perm_invent is kept in flags so persists across save/restore, but > perm_invent capability can change if player restores with a different > interface--or same one running on a different-sized display--so it > ought to be in iflags instead.] Not addressed here. > 2. perm_invent window does not get updated when charging a wand (or > other chargeable item presumably), with a scroll of charging. Most scrolls rely on useup() -> update_inventory(), but charging uses up the scroll early so that it will be gone from inventory when choosing an item to charge. It needed an explicit update_inventory() after charging. > 3. update_inventory(), is called from setworn(), which is called from > dorestore(), when loading a save. Segfaults have been observed in > variants based on this code (though not yet in vanilla 3.6.1), so it's > possible this may be unsafe. The update_inventory() call in setworn() > could be protected with "if (!restoring) ..." tty doesn't support perm_invent, so this might be a win32 issue. I've made the suggested change, but a better fix would be to turn off perm_invent as soon as options processing (new game) or options restore (old game unless/until #1 gets changed) has finished setting things up, then turn it back on at the end of moveloop()'s prolog when play is about to start. = = Most of the read.c change is reordering prototypes to match the order of the corresponding functions. I did this when adding a new static routine, then ended up discarding that routine. --- doc/fixes36.2 | 2 ++ src/read.c | 36 ++++++++++++++++++++++++------------ src/worn.c | 9 ++++++--- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/doc/fixes36.2 b/doc/fixes36.2 index db900eae1..7aa79d563 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -14,6 +14,8 @@ Killing Vlad while he was in bat/fog cloud/wolf form gave poorly worded spaces in hilite_status option title text field not working numeric hilite_status values didn't allow negative numbers (needed for AC); change them to accept leading '-', also accept unary '+' as a no-op +permanent inventory window was updated too soon when a scroll of charging + was used to [re]charge an item, not reflecting the item's change(s) Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository diff --git a/src/read.c b/src/read.c index 02cb79b91..f86afe04a 100644 --- a/src/read.c +++ b/src/read.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 read.c $NHDT-Date: 1515802375 2018/01/13 00:12:55 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.150 $ */ +/* NetHack 3.6 read.c $NHDT-Date: 1526728750 2018/05/19 11:19:10 $ $NHDT-Branch: NetHack-3.6.2 $:$NHDT-Revision: 1.155 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -19,19 +19,23 @@ static NEARDATA const char readable[] = { ALL_CLASSES, SCROLL_CLASS, static const char all_count[] = { ALLOW_COUNT, ALL_CLASSES, 0 }; STATIC_DCL boolean FDECL(learnscrolltyp, (SHORT_P)); -STATIC_DCL char * FDECL(erode_obj_text, (struct obj *, char *)); -STATIC_DCL void NDECL(do_class_genocide); +STATIC_DCL char *FDECL(erode_obj_text, (struct obj *, char *)); +STATIC_DCL char *FDECL(apron_text, (struct obj *, char *buf)); STATIC_DCL void FDECL(stripspe, (struct obj *)); STATIC_DCL void FDECL(p_glow1, (struct obj *)); STATIC_DCL void FDECL(p_glow2, (struct obj *, const char *)); -STATIC_DCL void FDECL(randomize, (int *, int)); STATIC_DCL void FDECL(forget_single_object, (int)); +#if 0 /* not used */ +STATIC_DCL void FDECL(forget_objclass, (int)); +#endif +STATIC_DCL void FDECL(randomize, (int *, int)); STATIC_DCL void FDECL(forget, (int)); STATIC_DCL int FDECL(maybe_tame, (struct monst *, struct obj *)); -STATIC_DCL boolean FDECL(is_valid_stinking_cloud_pos, (int, int, BOOLEAN_P)); -STATIC_DCL void FDECL(display_stinking_cloud_positions, (int)); STATIC_DCL boolean FDECL(get_valid_stinking_cloud_pos, (int, int)); +STATIC_DCL boolean FDECL(is_valid_stinking_cloud_pos, (int, int, BOOLEAN_P)); +STATIC_PTR void FDECL(display_stinking_cloud_positions, (int)); STATIC_PTR void FDECL(set_lit, (int, int, genericptr)); +STATIC_DCL void NDECL(do_class_genocide); STATIC_OVL boolean learnscrolltyp(scrolltyp) @@ -56,7 +60,7 @@ struct obj *sobj; (void) learnscrolltyp(sobj->otyp); } -char * +STATIC_OVL char * erode_obj_text(otmp, buf) struct obj *otmp; char *buf; @@ -158,7 +162,7 @@ char *buf; return erode_obj_text(tshirt, buf); } -char * +STATIC_OVL char * apron_text(apron, buf) struct obj *apron; char *buf; @@ -324,6 +328,7 @@ doread() return 0; } else if (Blind && (scroll->otyp != SPE_BOOK_OF_THE_DEAD)) { const char *what = 0; + if (scroll->oclass == SPBOOK_CLASS) what = "mystic runes"; else if (!scroll->dknown) @@ -953,7 +958,7 @@ int x,y; || distu(x, y) >= 32)); } -boolean +STATIC_OVL boolean is_valid_stinking_cloud_pos(x, y, showmsg) int x, y; boolean showmsg; @@ -966,7 +971,7 @@ boolean showmsg; return TRUE; } -void +STATIC_PTR void display_stinking_cloud_positions(state) int state; { @@ -1621,7 +1626,8 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */ pline("This is a scroll of fire!"); dam *= 5; pline("Where do you want to center the explosion?"); - getpos_sethilite(display_stinking_cloud_positions, get_valid_stinking_cloud_pos); + getpos_sethilite(display_stinking_cloud_positions, + get_valid_stinking_cloud_pos); (void) getpos(&cc, TRUE, "the desired position"); if (!is_valid_stinking_cloud_pos(cc.x, cc.y, FALSE)) { /* try to reach too far, get burned */ @@ -1693,7 +1699,8 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */ already_known ? "stinking " : ""); cc.x = u.ux; cc.y = u.uy; - getpos_sethilite(display_stinking_cloud_positions, get_valid_stinking_cloud_pos); + getpos_sethilite(display_stinking_cloud_positions, + get_valid_stinking_cloud_pos); if (getpos(&cc, TRUE, "the desired position") < 0) { pline1(Never_mind); break; @@ -1707,6 +1714,11 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */ default: impossible("What weird effect is this? (%u)", otyp); } + /* if sobj is gone, we've already called useup() above and the + update_inventory() that it performs might have come too soon + (before charging an item, for instance) */ + if (!sobj) + update_inventory(); return sobj ? 0 : 1; } diff --git a/src/worn.c b/src/worn.c index 612f71bac..cf45277a9 100644 --- a/src/worn.c +++ b/src/worn.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 worn.c $NHDT-Date: 1496959481 2017/06/08 22:04:41 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.49 $ */ +/* NetHack 3.6 worn.c $NHDT-Date: 1526728754 2018/05/19 11:19:14 $ $NHDT-Branch: NetHack-3.6.2 $:$NHDT-Revision: 1.51 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -105,7 +105,8 @@ long mask; } } } - update_inventory(); + if (!restoring) + update_inventory(); } /* called e.g. when obj is destroyed */ @@ -136,7 +137,9 @@ register struct obj *obj; if ((p = w_blocks(obj, wp->w_mask)) != 0) u.uprops[p].blocked &= ~wp->w_mask; } - update_inventory(); + /* setnotworn() isn't called during restore but parallel setworn() */ + if (!restoring) + update_inventory(); } /* return a bitmask of the equipment slot(s) a given item might be worn in */ -- 2.40.0