diff --git a/doc/fixes36.3 b/doc/fixes36.3 index 909dbd345..00745966a 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.94 $ $NHDT-Date: 1562838835 2019/07/11 09:53:55 $ +$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.99 $ $NHDT-Date: 1564771880 2019/08/02 18:51:20 $ This fixes36.3 file is here to capture information about updates in the 3.6.x lineage following the release of 3.6.2 in May 2019. Please note, however, @@ -105,6 +105,16 @@ when farlook describes a monster at a visible spot as trapped, reveal the trap fix theft when poly'd into nymph form; 3.6.2 change made that anger the victim hero poly'd into nymph would steal gold along with other items change wizard mode #panic to require "yes" if 'paranoid_confirm:quit' is set +add some additional validation checks when setting up a new timer (triggered + by an ancient source comment rather than by any observed problems) +if a chaotic monk or wizard gets crowned and is given a spellbook rather than + Stormbringer as the crowning gift, don't describe the hero as having + been "chosen to steal souls for [Arioch's] glory" +for multi-shot shooting by monsters, a typo checked hero's weapon for + compatibility with ammo when monster was wielding an elven bow +when a boulder was teleported, if it landed in a pit or trap door or hole its + former location wasn't updated to show that it wasn't there anymore + (noticed in Sokoban but not limited to there) Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository @@ -121,6 +131,8 @@ fix for feedback when a monster plays a fire horn at self to cure green slime ended up being used for zapping a wand of fire at self too wizard mode ^I "not carrying anything" still claimed "not carrying anything" if "(all items are already identified)" was given +monster throwing from stack of missiles (darts, daggers, spears) would cause + crash if it wasn't wielding a weapon (bug in multi-shot shooting fix) curses: sometimes the message window would show a blank line after a prompt curses: the change to show map in columns 1..79 instead of 2..80 made the highlight for '@' show up in the wrong place if clipped map had been diff --git a/include/artilist.h b/include/artilist.h index 26320b080..4a8b40554 100644 --- a/include/artilist.h +++ b/include/artilist.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 artilist.h $NHDT-Date: 1433050874 2015/05/31 05:41:14 $ $NHDT-Branch: master $:$NHDT-Revision: 1.16 $ */ +/* NetHack 3.6 artilist.h $NHDT-Date: 1564351548 2019/07/28 22:05:48 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.20 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2017. */ /* NetHack may be freely redistributed. See license for details. */ @@ -57,8 +57,16 @@ static NEARDATA struct artifact artilist[] = { DRLI(5, 2), DRLI(0, 0), NO_CARY, 0, A_CHAOTIC, NON_PM, NON_PM, 8000L, NO_COLOR), /* - * Mjollnir will return to the hand of the wielder when thrown - * if the wielder is a Valkyrie wearing Gauntlets of Power. + * Mjollnir can be thrown when wielded if hero has 25 Strength + * (usually via gauntlets of power but possible with rings of + * gain strength). If the thrower is a Valkyrie, Mjollnir will + * usually (99%) return and then usually (separate 99%) be caught + * and automatically be re-wielded. When returning Mjollnir is + * not caught, there is a 50:50 chance of hitting hero for damage + * and its lightning shock might destroy some wands and/or rings. + * + * Monsters don't throw Mjollnir regardless of strength (not even + * fake-player valkyries). */ A("Mjollnir", WAR_HAMMER, /* Mjo:llnir */ (SPFX_RESTR | SPFX_ATTK), 0, 0, ELEC(5, 24), NO_DFNS, NO_CARY, 0, diff --git a/include/timeout.h b/include/timeout.h index 0cb4c706a..0ac85a3c8 100644 --- a/include/timeout.h +++ b/include/timeout.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 timeout.h $NHDT-Date: 1432512775 2015/05/25 00:12:55 $ $NHDT-Branch: master $:$NHDT-Revision: 1.10 $ */ +/* NetHack 3.6 timeout.h $NHDT-Date: 1564269131 2019/07/27 23:12:11 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.12 $ */ /* Copyright 1994, Dean Luick */ /* NetHack may be freely redistributed. See license for details. */ @@ -10,10 +10,11 @@ typedef void FDECL((*timeout_proc), (ANY_P *, long)); /* kind of timer */ enum timer_type { - TIMER_LEVEL = 0, /* event specific to level */ - TIMER_GLOBAL, /* event follows current play */ - TIMER_OBJECT, /* event follows a object */ - TIMER_MONSTER /* event follows a monster */ + TIMER_LEVEL = 0, /* event specific to level [melting ice] */ + TIMER_GLOBAL = 1, /* event follows current play [not used] */ + TIMER_OBJECT = 2, /* event follows an object [various] */ + TIMER_MONSTER = 3, /* event follows a monster [not used] */ + NUM_TIMER_KINDS /* 4 */ }; /* save/restore timer ranges */ diff --git a/src/mthrowu.c b/src/mthrowu.c index c2538ab5c..504cb533a 100644 --- a/src/mthrowu.c +++ b/src/mthrowu.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mthrowu.c $NHDT-Date: 1542765360 2018/11/21 01:56:00 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.78 $ */ +/* NetHack 3.6 mthrowu.c $NHDT-Date: 1564767726 2019/08/02 17:42:06 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.85 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Pasi Kallinen, 2016. */ /* NetHack may be freely redistributed. See license for details. */ @@ -175,7 +175,10 @@ struct obj *otmp, *mwep; /* Elven Craftsmanship makes for light, quick bows */ if (otmp->otyp == ELVEN_ARROW && !otmp->cursed) multishot++; - if (ammo_and_launcher(otmp, uwep) && mwep->otyp == ELVEN_BOW + /* for arrow, we checked bow&arrow when entering block, but for + bow, so far we've only validated that otmp is a weapon stack; + need to verify that it's a stack of arrows rather than darts */ + if (mwep && mwep->otyp == ELVEN_BOW && ammo_and_launcher(otmp, mwep) && !mwep->cursed) multishot++; /* 1/3 of launcher enchantment */ diff --git a/src/pray.c b/src/pray.c index a22cecb29..c438f99d3 100644 --- a/src/pray.c +++ b/src/pray.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 pray.c $NHDT-Date: 1562462064 2019/07/07 01:14:24 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.116 $ */ +/* NetHack 3.6 pray.c $NHDT-Date: 1564532667 2019/07/31 00:24:27 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.117 $ */ /* Copyright (c) Benson I. Margulies, Mike Stephenson, Steve Linhart, 1989. */ /* NetHack may be freely redistributed. See license for details. */ @@ -765,6 +765,20 @@ gcrownu() HPoison_resistance |= FROMOUTSIDE; godvoice(u.ualign.type, (char *) 0); + class_gift = STRANGE_OBJECT; + /* 3.3.[01] had this in the A_NEUTRAL case, + preventing chaotic wizards from receiving a spellbook */ + if (Role_if(PM_WIZARD) + && (!uwep || (uwep->oartifact != ART_VORPAL_BLADE + && uwep->oartifact != ART_STORMBRINGER)) + && !carrying(SPE_FINGER_OF_DEATH)) { + class_gift = SPE_FINGER_OF_DEATH; + } else if (Role_if(PM_MONK) && (!uwep || !uwep->oartifact) + && !carrying(SPE_RESTORE_ABILITY)) { + /* monks rarely wield a weapon */ + class_gift = SPE_RESTORE_ABILITY; + } + obj = ok_wep(uwep) ? uwep : 0; already_exists = in_hand = FALSE; /* lint suppression */ switch (u.ualign.type) { @@ -785,19 +799,13 @@ gcrownu() already_exists = exist_artifact(RUNESWORD, artiname(ART_STORMBRINGER)); verbalize("Thou art chosen to %s for My Glory!", - already_exists && !in_hand ? "take lives" : "steal souls"); + ((already_exists && !in_hand) + || class_gift != STRANGE_OBJECT) ? "take lives" + : "steal souls"); break; } - class_gift = STRANGE_OBJECT; - /* 3.3.[01] had this in the A_NEUTRAL case below, - preventing chaotic wizards from receiving a spellbook */ - if (Role_if(PM_WIZARD) - && (!uwep || (uwep->oartifact != ART_VORPAL_BLADE - && uwep->oartifact != ART_STORMBRINGER)) - && !carrying(SPE_FINGER_OF_DEATH)) { - class_gift = SPE_FINGER_OF_DEATH; - make_splbk: + if (objects[class_gift].oc_class == SPBOOK_CLASS) { obj = mksobj(class_gift, TRUE, FALSE); bless(obj); obj->bknown = 1; /* ok to skip set_bknown() */ @@ -812,11 +820,6 @@ gcrownu() obj = uwep; /* to be blessed,&c */ break; } - } else if (Role_if(PM_MONK) && (!uwep || !uwep->oartifact) - && !carrying(SPE_RESTORE_ABILITY)) { - /* monks rarely wield a weapon */ - class_gift = SPE_RESTORE_ABILITY; - goto make_splbk; } switch (u.ualign.type) { diff --git a/src/teleport.c b/src/teleport.c index ff41b95a3..febb6221b 100644 --- a/src/teleport.c +++ b/src/teleport.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 teleport.c $NHDT-Date: 1561336020 2019/06/24 00:27:00 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.89 $ */ +/* NetHack 3.6 teleport.c $NHDT-Date: 1564771880 2019/08/02 18:51:20 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.92 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2011. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1447,6 +1447,9 @@ register struct obj *obj; g.dndest.nhx, g.dndest.nhy))); if (flooreffects(obj, tx, ty, "fall")) { + /* update old location since flooreffects() couldn't; + unblock_point() for boulder handled by obj_extract_self() */ + newsym(otx, oty); return FALSE; } else if (otx == 0 && oty == 0) { ; /* fell through a trap door; no update of old loc needed */ @@ -1463,6 +1466,7 @@ register struct obj *obj; newsym(otx, oty); /* update old location */ } place_object(obj, tx, ty); + /* note: block_point() for boulder handled by place_object() */ newsym(tx, ty); return TRUE; } diff --git a/src/timeout.c b/src/timeout.c index b39937ee8..c4a059839 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 timeout.c $NHDT-Date: 1559664953 2019/06/04 16:15:53 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.90 $ */ +/* NetHack 3.6 timeout.c $NHDT-Date: 1564269133 2019/07/27 23:12:13 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.91 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2018. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1866,13 +1866,32 @@ short kind; short func_index; anything *arg; { - timer_element *gnu; + timer_element *gnu, *dup; - if (func_index < 0 || func_index >= NUM_TIME_FUNCS) - panic("start_timer"); + if (kind < 0 || kind >= NUM_TIMER_KINDS + || func_index < 0 || func_index >= NUM_TIME_FUNCS) + panic("start_timer (%s: %d)", kind_name(kind), (int) func_index); - gnu = (timer_element *) alloc(sizeof(timer_element)); - (void) memset((genericptr_t)gnu, 0, sizeof(timer_element)); + /* fail if already has a timer running */ + for (dup = g.timer_base; dup; dup = dup->next) + if (dup->kind == kind + && dup->func_index == func_index + && dup->arg.a_void == arg->a_void) + break; + if (dup) { + char idbuf[QBUFSZ]; + +#ifdef VERBOSE_TIMER + Sprintf(idbuf, "%s timer", timeout_funcs[func_index].name); +#else + Sprintf(idbuf, "%s timer (%d)", kind_name(kind), (int) func_index); +#endif + impossible("Attempted to start duplicate %s, aborted.", idbuf); + return FALSE; + } + + gnu = (timer_element *) alloc(sizeof *gnu); + (void) memset((genericptr_t) gnu, 0, sizeof *gnu); gnu->next = 0; gnu->tid = g.timer_id++; gnu->timeout = g.monstermoves + when; @@ -1885,7 +1904,6 @@ anything *arg; if (kind == TIMER_OBJECT) /* increment object's timed count */ (arg->a_obj)->timed++; - /* should check for duplicates and fail if any */ return TRUE; }