From abe4db6e60b2f42a74a9616b31ebd13022a20ba0 Mon Sep 17 00:00:00 2001 From: PatR Date: Tue, 14 Jul 2020 17:03:51 -0700 Subject: [PATCH] fix pull request #365 - monster max HP The recently added sanity check for monster maximum HP was giving false complaints when Nd8 monster had N mhpmax. Most noticeable for level 1 monsters (level 0 monsters use 1d4 instead of 0d8 and weren't affected) but possible for higher level ones if they were unlucky--from their own perspective--with all their d8 rolls. Give level N monsters a minimum of N+1 HP, so minimum of 2 for level 1 monsters, making 1/8 of those stronger. Same minimum for level 0 monsters, 25% of which will become stronger now. (The pull request's patch gave every Nd8 monster 1 extra HP; this only does so for Nd8 and 1d4 ones which have rolled lowest possible amount.) Also relax the sanity check so that existing to-be-3.7 save files don't continue to trigger sanity complaints for existing monsters that have the old minimum. Fixes 365 --- doc/fixes37.0 | 4 +++- src/makemon.c | 30 +++++++++++++++++++++--------- src/mon.c | 4 ++-- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 0fa488c33..5789b56c4 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.248 $ $NHDT-Date: 1594730609 2020/07/14 12:43:29 $ +$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.249 $ $NHDT-Date: 1594771373 2020/07/15 00:02:53 $ General Fixes and Modified Features ----------------------------------- @@ -287,6 +287,8 @@ only generate shop items on solid floor squares avoid gcc 10 warning by removing duplicate definition of 'head_engr' if a monster removed a corpse from an ice box, the corpse would never rot away monster creation on quest levels could make genocided creatures +enabling wizard mode 'sanity_check' option would complain about invalid mhpmax + value for level N monsters created with a d8 value of 1 for all N d8's tty: redraw unexplored locations as S_unexplored rather than after map has been partially overwritten by popup menu or text display diff --git a/src/makemon.c b/src/makemon.c index b325c64a7..09b082ed8 100644 --- a/src/makemon.c +++ b/src/makemon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 makemon.c $NHDT-Date: 1591178397 2020/06/03 09:59:57 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.173 $ */ +/* NetHack 3.6 makemon.c $NHDT-Date: 1594771378 2020/07/15 00:02:58 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.174 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -997,13 +997,16 @@ struct monst *mon; int mndx; { struct permonst *ptr = &mons[mndx]; + int basehp = 0; mon->m_lev = adj_lev(ptr); if (is_golem(ptr)) { + /* golems have a fixed amount of HP, varying by golem type */ mon->mhpmax = mon->mhp = golemhp(mndx); } else if (is_rider(ptr)) { /* we want low HP, but a high mlevel so they can attack well */ - mon->mhpmax = mon->mhp = d(10, 8); + basehp = 10; /* minimum is 1 per false (weaker) level */ + mon->mhpmax = mon->mhp = d(basehp, 8); } else if (ptr->mlevel > 49) { /* "special" fixed hp monster * the hit points are encoded in the mlevel in a somewhat strange @@ -1012,17 +1015,26 @@ int mndx; mon->mhpmax = mon->mhp = 2 * (ptr->mlevel - 6); mon->m_lev = mon->mhp / 4; /* approximation */ } else if (ptr->mlet == S_DRAGON && mndx >= PM_GRAY_DRAGON) { - /* adult dragons */ - mon->mhpmax = mon->mhp = - (int) (In_endgame(&u.uz) - ? (8 * mon->m_lev) - : (4 * mon->m_lev + d((int) mon->m_lev, 4))); + /* adult dragons; N*(4+rnd(4)) before endgame, N*8 once there */ + basehp = (int) mon->m_lev; /* not really applicable; isolates cast */ + mon->mhpmax = mon->mhp = In_endgame(&u.uz) ? (8 * basehp) + : (4 * basehp + d(basehp, 4)); } else if (!mon->m_lev) { + basehp = 1; /* minimum is 1, increased to 2 below */ mon->mhpmax = mon->mhp = rnd(4); } else { - mon->mhpmax = mon->mhp = d((int) mon->m_lev, 8); + basehp = (int) mon->m_lev; /* minimum possible is one per level */ + mon->mhpmax = mon->mhp = d(basehp, 8); if (is_home_elemental(ptr)) - mon->mhpmax = (mon->mhp *= 3); + mon->mhpmax = (mon->mhp *= 3); /* leave 'basehp' as-is */ + } + + /* if d(X,8) rolled a 1 all X times, give a boost; + most beneficial for level 0 and level 1 monsters, making mhpmax + and starting mhp always be at least 2 */ + if (mon->mhpmax == basehp) { + mon->mhpmax += 1; + mon->mhp = mon->mhpmax; } } diff --git a/src/mon.c b/src/mon.c index 9ca2633aa..901797938 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mon.c $NHDT-Date: 1594727746 2020/07/14 11:55:46 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.340 $ */ +/* NetHack 3.6 mon.c $NHDT-Date: 1594771374 2020/07/15 00:02:54 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.341 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -59,7 +59,7 @@ const char *msg; /* check before DEADMONSTER() because dead monsters should still have sane mhpmax */ if (mtmp->mhpmax < 1 - || mtmp->mhpmax < (int) mtmp->m_lev + 1 + || mtmp->mhpmax < (int) mtmp->m_lev || mtmp->mhp > mtmp->mhpmax) impossible( "%s: level %d monster #%u [%s] has %d cur HP, %d max HP",