From def25495924245669a128ca30ee7628d29f5668f Mon Sep 17 00:00:00 2001 From: PatR Date: Thu, 4 Jun 2015 15:31:25 -0700 Subject: [PATCH] shapeshifting on rogue level Limit vampire shapeshifting on rogue level to vampire bats (only choice represented by uppercase letter) and have other shapeshifting try for uppercase. The latter isn't rigorous because shapeshifters (chameleon=':', doppelganger='@', sandestin='&') aren't uppercase themselves, so won't be created there under ordinary circumstances. It applies to the "summon nasties" monster spell and post-invocation/ post-Wizard's-death harassment effect too. --- src/makemon.c | 21 ++++++++------------- src/mon.c | 32 ++++++++++++++++++++++++++------ src/wizard.c | 16 +++++++++++++--- 3 files changed, 47 insertions(+), 22 deletions(-) diff --git a/src/makemon.c b/src/makemon.c index a1fc167fe..5aea3392d 100644 --- a/src/makemon.c +++ b/src/makemon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 makemon.c $NHDT-Date: 1432685497 2015/05/27 00:11:37 $ $NHDT-Branch: master $:$NHDT-Revision: 1.89 $ */ +/* NetHack 3.6 makemon.c $NHDT-Date: 1433457069 2015/06/04 22:31:09 $ $NHDT-Branch: master $:$NHDT-Revision: 1.92 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1134,23 +1134,18 @@ register int mmflags; mtmp->cham = NON_PM; /* default is "not a shapechanger" */ if ((mcham = pm_to_cham(mndx)) != NON_PM) { /* this is a shapechanger after all */ - if (Protection_from_shape_changers) { + if (Protection_from_shape_changers + || mtmp->cham == PM_VLAD_THE_IMPALER) { ; /* stuck in its natural form (NON_PM) */ } else { /* Note: shapechanger's initial form used to be - chosen with rndmonst(), yielding a monster + chosen here with rndmonst(), yielding a monster which was approriate to the level's difficulty but ignored the changer's usual type selection - so would be inppropriate for vampshifters. */ - mtmp->cham = mcham; /* remember base form */ - if (mcham != PM_VLAD_THE_IMPALER && - /* select initial shape */ - (mcham = select_newcham_form(mtmp)) != NON_PM) { - /* take on initial shape; if successful, - avoid giving that shape's usual inventory */ - if (newcham(mtmp, &mons[mcham], FALSE, FALSE)) - allow_minvent = FALSE; - } + so would be inppropriate for vampshifters. + Let newcham() pick the shape. */ + if (newcham(mtmp, (struct permonst *) 0, FALSE, FALSE)) + allow_minvent = FALSE; } } else if (mndx == PM_WIZARD_OF_YENDOR) { mtmp->iswiz = TRUE; diff --git a/src/mon.c b/src/mon.c index cf168fd82..8ca8d16a1 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mon.c $NHDT-Date: 1432512774 2015/05/25 00:12:54 $ $NHDT-Branch: master $:$NHDT-Revision: 1.177 $ */ +/* NetHack 3.6 mon.c $NHDT-Date: 1433457072 2015/06/04 22:31:12 $ $NHDT-Branch: master $:$NHDT-Revision: 1.178 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2667,10 +2667,18 @@ boolean construct; STATIC_OVL int pick_animal() { + int res; + if (!animal_list) mon_animal_list(TRUE); - return animal_list[rn2(animal_list_count)]; + res = animal_list[rn2(animal_list_count)]; + /* rogue level should use monsters represented by uppercase letters + only, but since chameleons aren't generated there (not uppercase!) + we don't perform a lot of retries */ + if (Is_rogue_level(&u.uz) && !isupper((uchar) mons[res].mlet)) + res = animal_list[rn2(animal_list_count)]; + return res; } void @@ -2710,6 +2718,9 @@ pickvampshape(mon) struct monst *mon; { int mndx = mon->cham; + /* avoid picking monsters with lowercase display symbols ('d' for wolf + and 'v' for fog cloud) on rogue level*/ + boolean uppercase_only = Is_rogue_level(&u.uz); switch (mndx) { case PM_VLAD_THE_IMPALER: @@ -2718,13 +2729,13 @@ struct monst *mon; break; /* leave mndx as is */ /*FALLTHRU*/ case PM_VAMPIRE_LORD: /* vampire lord or Vlad can become wolf */ - if (!rn2(10)) { + if (!rn2(10) && !uppercase_only) { mndx = PM_WOLF; break; } /*FALLTHRU*/ case PM_VAMPIRE: /* any vampire can become fog or bat */ - mndx = !rn2(4) ? PM_FOG_CLOUD : PM_VAMPIRE_BAT; + mndx = (!rn2(4) && !uppercase_only) ? PM_FOG_CLOUD : PM_VAMPIRE_BAT; break; } return mndx; @@ -2786,7 +2797,8 @@ int *mndx_p, monclass; *mndx_p = PM_VLAD_THE_IMPALER; return TRUE; } - /* basic vampires can't become wolves; any can become fog or bat */ + /* basic vampires can't become wolves; any can become fog or bat + (we don't enforce upper-case only for rogue level here) */ if (*mndx_p == PM_WOLF) return (mon->cham != PM_VAMPIRE); if (*mndx_p == PM_FOG_CLOUD || *mndx_p == PM_VAMPIRE_BAT) @@ -2916,7 +2928,10 @@ struct monst *mon; tryct = 50; do { mndx = rn1(SPECIAL_PM - LOW_PM, LOW_PM); - } while (--tryct > 0 && !validspecmon(mon, mndx)); + } while (--tryct > 0 && !validspecmon(mon, mndx) + /* try harder to select uppercase monster on rogue level */ + && (tryct > 40 && Is_rogue_level(&u.uz) + && !isupper((uchar) mons[mndx].mlet))); } return mndx; } @@ -2995,6 +3010,11 @@ boolean msg; /* "The oldmon turns into a newmon!" */ do { mndx = select_newcham_form(mtmp); mdat = accept_newcham_form(mndx); + /* for the first several tries we require upper-case on + the rogue level (after that, we take whatever we get) */ + if (tryct > 15 && Is_rogue_level(&u.uz) + && !isupper((uchar) mdat->mlet)) + mdat = 0; if (mdat) break; } while (--tryct > 0); diff --git a/src/wizard.c b/src/wizard.c index 261c831b1..d0a6c371c 100644 --- a/src/wizard.c +++ b/src/wizard.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 wizard.c $NHDT-Date: 1432512766 2015/05/25 00:12:46 $ $NHDT-Branch: master $:$NHDT-Revision: 1.37 $ */ +/* NetHack 3.6 wizard.c $NHDT-Date: 1433457074 2015/06/04 22:31:14 $ $NHDT-Branch: master $:$NHDT-Revision: 1.38 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -428,9 +428,19 @@ clonewiz() int pick_nasty() { + int res = nasties[rn2(SIZE(nasties))]; + /* To do? Possibly should filter for appropriate forms when - in the elemental planes or surrounded by water or lava. */ - return nasties[rn2(SIZE(nasties))]; + * in the elemental planes or surrounded by water or lava. + * + * We want monsters represented by uppercase on rogue level, + * but we don't try very hard. + */ + if (Is_rogue_level(&u.uz) + && !('A' <= mons[res].mlet && mons[res].mlet <= 'Z')) + res = nasties[rn2(SIZE(nasties))]; + + return res; } /* create some nasty monsters, aligned or neutral with the caster */