From 31306760773b5200209869d62d73682ac53e67ec Mon Sep 17 00:00:00 2001 From: PatR Date: Mon, 25 Nov 2019 15:01:40 -0800 Subject: [PATCH] alignment of mimicked or polymorphed altars A reddit thread about an unaligned altar in an aligned temple was a tipoff that mimics posing as altars didn't have any particular alignment. The look-at code was misusing an operloaded field of the underlying terrain. Pick an alignment at random when taking on the appearance of an altar, store it in the mimic's mon->mextra->mcorpsenm field, and have look-at use that. Also, dropping a ring of polymorph into a sink can transform it, and one possible outcome is an altar. In this case, the alignment is part of the location's topology, but code setting that up was using Align2amask(rn2(foo)). That's a macro which evaluates its argument more than once. The first evaluation was effectively a no-op. If the second evaluation picked lawful then the result was lawful as intended. But if the second picked non-lawful and the third picked lawful, the result would end up as none-of-the-above (a value of 3 when it needs to be a single-bit mask of 1, 2, or 4). --- doc/fixes36.3 | 8 ++++++-- include/mextra.h | 7 ++++--- src/do.c | 9 +++++++-- src/makemon.c | 17 ++++++++++++----- src/pager.c | 19 +++++++++++++------ 5 files changed, 42 insertions(+), 18 deletions(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index f522e20b5..238f156ca 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.190 $ $NHDT-Date: 1574638389 2019/11/24 23:33:09 $ +$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.191 $ $NHDT-Date: 1574722861 2019/11/25 23:01:01 $ 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, @@ -302,7 +302,11 @@ when Riders use their bargethrough capability, don't let them swap places with there'd be no corpse so no auto-revive) putting on levitation boots while on sink would crash when attempting to set the enchantment known flag on Null 'uarmf' pointer -unix: Fix double DLB definition in linux hints file +look-at of mimics mimicking altars got an arbitary alignment from misuse of + underlying terrain +polymorph_sink creating an altar passed a call to rn2() as an argument to a + macro which evaluates its parameter more than once +unix: fix double DLB definition in linux hints file windows: fix --showpaths output for the data file which relies on being constructed programmatically to incorporate the version suffix diff --git a/include/mextra.h b/include/mextra.h index 6879a16ac..2fd27472a 100644 --- a/include/mextra.h +++ b/include/mextra.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 mextra.h $NHDT-Date: 1571531885 2019/10/20 00:38:05 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.23 $ */ +/* NetHack 3.6 mextra.h $NHDT-Date: 1574722861 2019/11/25 23:01:01 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.24 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2006. */ /* NetHack may be freely redistributed. See license for details. */ @@ -179,8 +179,9 @@ struct mextra { struct eshk *eshk; struct emin *emin; struct edog *edog; - int mcorpsenm; /* obj->corpsenm for mimic posing as statue or corpse, or - * obj->spe (fruit index) for one posing as a slime mold */ + int mcorpsenm; /* obj->corpsenm for mimic posing as statue or corpse, + * obj->spe (fruit index) for one posing as a slime mold, + * or an alignment mask for one posing as an altar */ }; #define MNAME(mon) ((mon)->mextra->mname) diff --git a/src/do.c b/src/do.c index 035fd3a8e..72b315640 100644 --- a/src/do.c +++ b/src/do.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 do.c $NHDT-Date: 1559670603 2019/06/04 17:50:03 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.192 $ */ +/* NetHack 3.6 do.c $NHDT-Date: 1574722862 2019/11/25 23:01:02 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.193 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -309,6 +309,7 @@ polymorph_sink() { uchar sym = S_sink; boolean sinklooted; + int algn; if (levl[u.ux][u.uy].typ != SINK) return; @@ -335,7 +336,11 @@ polymorph_sink() case 2: sym = S_altar; levl[u.ux][u.uy].typ = ALTAR; - levl[u.ux][u.uy].altarmask = Align2amask(rn2((int) A_LAWFUL + 2) - 1); + /* 3.6.3: this used to pass 'rn2(A_LAWFUL + 2) - 1' to + Align2mask() but it evaluates its argument more than once */ + algn = rn2(3) - 1; /* -1 (A_Cha) or 0 (A_Neu) or +1 (A_Law) */ + levl[u.ux][u.uy].altarmask = ((Inhell && rn2(3)) ? AM_NONE + : Align2amask(algn)); break; case 3: sym = S_room; diff --git a/src/makemon.c b/src/makemon.c index 2ec04698c..3145ad6de 100644 --- a/src/makemon.c +++ b/src/makemon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 makemon.c $NHDT-Date: 1571531888 2019/10/20 00:38:08 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.141 $ */ +/* NetHack 3.6 makemon.c $NHDT-Date: 1574722863 2019/11/25 23:01:03 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.142 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2194,10 +2194,12 @@ register struct monst *mtmp; } else if (rt == TEMPLE) { ap_type = M_AP_FURNITURE; appear = S_altar; - /* - * We won't bother with beehives, morgues, barracks, throne rooms - * since they shouldn't contain too many mimics anyway... - */ + + /* + * We won't bother with beehives, morgues, barracks, throne rooms + * since they shouldn't contain too many mimics anyway... + */ + } else if (rt >= SHOPBASE) { s_sym = get_shop_item(rt - SHOPBASE); if (s_sym < 0) { @@ -2254,6 +2256,11 @@ register struct monst *mtmp; current_fruit is equivalent to creating an instance of that fruit (no-op if a fruit of this type has actually been made) */ flags.made_fruit = TRUE; + } else if (ap_type == M_AP_FURNITURE && appear == S_altar) { + int algn = rn2(3) - 1; /* -1 (A_Cha) or 0 (A_Neu) or +1 (A_Law) */ + + newmcorpsenm(mtmp); + MCORPSENM(mtmp) = (Inhell && rn2(3)) ? AM_NONE : Align2amask(algn); } else if (has_mcorpsenm(mtmp)) { /* don't retain stale value from a previously mimicked shape */ MCORPSENM(mtmp) = NON_PM; diff --git a/src/pager.c b/src/pager.c index 77cff068b..7f14b0ffb 100644 --- a/src/pager.c +++ b/src/pager.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 pager.c $NHDT-Date: 1574011494 2019/11/17 17:24:54 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.161 $ */ +/* NetHack 3.6 pager.c $NHDT-Date: 1574722864 2019/11/25 23:01:04 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.162 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2018. */ /* NetHack may be freely redistributed. See license for details. */ @@ -477,17 +477,24 @@ char *buf, *monbuf; Strcpy(buf, def_warnsyms[warnindx].explanation); } else if (!glyph_is_cmap(glyph)) { Strcpy(buf, "unexplored area"); - } else + } else { + int amsk; + aligntyp algn; + switch (glyph_to_cmap(glyph)) { case S_altar: + amsk = ((mtmp = m_at(x, y)) != 0 && has_mcorpsenm(mtmp) + && M_AP_TYPE(mtmp) == M_AP_FURNITURE + && mtmp->mappearance == S_altar) ? MCORPSENM(mtmp) + : levl[x][y].altarmask; + algn = Amask2align(amsk & ~AM_SHRINE); Sprintf(buf, "%s %saltar", /* like endgame high priests, endgame high altars are only recognizable when immediately adjacent */ (Is_astralevel(&u.uz) && distu(x, y) > 2) ? "aligned" - : align_str( - Amask2align(levl[x][y].altarmask & ~AM_SHRINE)), - ((levl[x][y].altarmask & AM_SHRINE) + : align_str(algn), + ((amsk & AM_SHRINE) != 0 && (Is_astralevel(&u.uz) || Is_sanctum(&u.uz))) ? "high " : ""); @@ -522,7 +529,7 @@ char *buf, *monbuf; Strcpy(buf, defsyms[glyph_to_cmap(glyph)].explanation); break; } - + } return (pm && !Hallucination) ? pm : (struct permonst *) 0; } -- 2.50.1