diff --git a/include/mondata.h b/include/mondata.h index f565d9da1..b12d6e382 100644 --- a/include/mondata.h +++ b/include/mondata.h @@ -1,4 +1,4 @@ -/* NetHack 3.7 mondata.h $NHDT-Date: 1606473485 2020/11/27 10:38:05 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.45 $ */ +/* NetHack 3.7 mondata.h $NHDT-Date: 1703845738 2023/12/29 10:28:58 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.63 $ */ /* Copyright (c) 1989 Mike Threepoint */ /* NetHack may be freely redistributed. See license for details. */ @@ -161,6 +161,8 @@ #define is_rider(ptr) \ ((ptr) == &mons[PM_DEATH] || (ptr) == &mons[PM_FAMINE] \ || (ptr) == &mons[PM_PESTILENCE]) +/* note: placeholder monsters are used for corposes of zombies and mummies; + PM_DWARF and PM_GNOME are normal monsters, not placeholders */ #define is_placeholder(ptr) \ ((ptr) == &mons[PM_ORC] || (ptr) == &mons[PM_GIANT] \ || (ptr) == &mons[PM_ELF] || (ptr) == &mons[PM_HUMAN]) diff --git a/include/monsters.h b/include/monsters.h index 14ee32dd6..a34c662c8 100644 --- a/include/monsters.h +++ b/include/monsters.h @@ -1,4 +1,4 @@ -/* NetHack 3.7 monsters.h $NHDT-Date: 1700725870 2023/11/23 07:51:10 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.113 $ */ +/* NetHack 3.7 monsters.h $NHDT-Date: 1703845746 2023/12/29 10:29:06 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.117 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2006. */ /* NetHack may be freely redistributed. See license for details. */ @@ -417,12 +417,13 @@ NO_ATTK), SIZ(500, 200, MS_HUMANOID, MZ_SMALL), 0, 0, M1_HUMANOID | M1_OMNIVORE, M2_COLLECT, M3_INFRAVISIBLE | M3_INFRAVISION, 2, CLR_GREEN, HOBBIT), + /* unlike plain human|elf|orc, plain "dwarf" is an ordinary monster */ MON("dwarf", S_HUMANOID, LVL(2, 6, 10, 10, 4), (G_GENO | 3), A(ATTK(AT_WEAP, AD_PHYS, 1, 8), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(900, 300, MS_HUMANOID, MZ_HUMAN), 0, 0, M1_TUNNEL | M1_NEEDPICK | M1_HUMANOID | M1_OMNIVORE, - M2_NOPOLY | M2_DWARF | M2_STRONG | M2_GREEDY | M2_JEWELS | M2_COLLECT, + M2_DWARF | M2_STRONG | M2_GREEDY | M2_JEWELS | M2_COLLECT, M3_INFRAVISIBLE | M3_INFRAVISION, 4, CLR_RED, DWARF), MON("bugbear", S_HUMANOID, LVL(3, 9, 5, 0, -6), (G_GENO | 1), A(ATTK(AT_WEAP, AD_PHYS, 2, 4), @@ -630,10 +631,9 @@ SIZ(1000, 200, MS_ORC, MZ_HUMAN), 0, 0, M1_HUMANOID | M1_OMNIVORE, M2_ORC | M2_STRONG | M2_COLLECT, M3_INFRAVISIBLE | M3_INFRAVISION, 3, CLR_BROWN, HOBGOBLIN), - /* plain "orc" for zombie corpses only; not created at random; - * orcs (but not goblins and hobgoblins) are granted poison resistance; - * however, their corpses don't confer it - */ + /* Plain "orc" for zombie and mummy corpses only; not created at random. + * Orcs (but not goblins and hobgoblins) are granted poison resistance; + * however, their corpses don't confer it. */ MON("orc", S_ORC, LVL(1, 9, 10, 0, -3), (G_GENO | G_NOGEN | G_LGROUP), A(ATTK(AT_WEAP, AD_PHYS, 1, 8), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), @@ -1417,12 +1417,13 @@ M2_HOSTILE | M2_NEUTER, 0, 5, CLR_MAGENTA, VIOLET_FUNGUS), /* * Gnomes + * Unlike plain human|elf|orc, plain "gnome" is an ordinary monster. */ MON("gnome", S_GNOME, LVL(1, 6, 10, 4, 0), (G_GENO | G_SGROUP | 1), A(ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(650, 100, MS_ORC, MZ_SMALL), 0, 0, M1_HUMANOID | M1_OMNIVORE, - M2_NOPOLY | M2_GNOME | M2_COLLECT, M3_INFRAVISIBLE | M3_INFRAVISION, + M2_GNOME | M2_COLLECT, M3_INFRAVISIBLE | M3_INFRAVISION, 3, CLR_BROWN, GNOME), MON3("gnome lord", "gnome lady", "gnome leader", S_GNOME, LVL(3, 8, 10, 4, 0), (G_GENO | 2), @@ -2205,14 +2206,15 @@ /* * humans, including elves and were-critters; * the '@' class does not obey rule #2. + * Plain "human" is a placeholder, not a normal monster. */ MON("human", S_HUMAN, LVL(0, 12, 10, 0, 0), G_NOGEN, /* for corpses */ A(ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, MS_HUMANOID, MZ_HUMAN), 0, 0, M1_HUMANOID | M1_OMNIVORE, - M2_NOPOLY | M2_HUMAN | M2_STRONG | M2_COLLECT, M3_INFRAVISIBLE, - 2, HI_DOMESTIC, HUMAN), + M2_NOPOLY | M2_HUMAN | M2_STRONG | M2_COLLECT, + M3_INFRAVISIBLE, 2, HI_DOMESTIC, HUMAN), MON("wererat", S_HUMAN, LVL(2, 12, 10, 10, -7), (1), A(ATTK(AT_WEAP, AD_PHYS, 2, 4), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), @@ -2234,6 +2236,7 @@ M1_HUMANOID | M1_POIS | M1_REGEN | M1_OMNIVORE, M2_NOPOLY | M2_WERE | M2_HOSTILE | M2_HUMAN | M2_COLLECT, M3_INFRAVISIBLE, 6, CLR_ORANGE, HUMAN_WEREWOLF), + /* plain "elf" is a placeholder, not a normal monster */ MON("elf", S_HUMAN, LVL(0, 12, 10, 2, -3), G_NOGEN, /* for corpses */ A(ATTK(AT_WEAP, AD_PHYS, 1, 8), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), diff --git a/src/polyself.c b/src/polyself.c index 807e5ef8c..c5f7b077a 100644 --- a/src/polyself.c +++ b/src/polyself.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 polyself.c $NHDT-Date: 1702274031 2023/12/11 05:53:51 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.204 $ */ +/* NetHack 3.7 polyself.c $NHDT-Date: 1703845752 2023/12/29 10:29:12 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.207 $ */ /* Copyright (C) 1987, 1988, 1989 by Ken Arromdee */ /* NetHack may be freely redistributed. See license for details. */ @@ -502,6 +502,7 @@ polyself(int psflags) if (controllable_poly || forcecontrol) { buf[0] = '\0'; tryct = 5; + do { mntmp = NON_PM; getlin("Become what kind of monster? [type the name]", buf); @@ -528,7 +529,28 @@ polyself(int psflags) mntmp = (draconian && class == S_DRAGON) ? armor_to_dragon(uarm->otyp) : mkclass_poly(class); + + /* placeholder monsters are for corpses and all flagged + M2_NOPOLY but they are reasonable polymorph targets; + pick a suitable substitute (which might be geno'd) */ + } else if (is_placeholder(&mons[mntmp]) + /* when your own race, fall to !polyok() case */ + && !your_race(&mons[mntmp]) + /* same for generic human, even if hero isn't human */ + && mntmp != PM_HUMAN) { + /* far less general than mkclass() */ + if (mntmp == PM_ORC) + mntmp = rn2(3) ? PM_HILL_ORC : PM_MORDOR_ORC; + else if (mntmp == PM_ELF) + mntmp = rn2(3) ? PM_GREEN_ELF : PM_GREY_ELF; + else if (mntmp == PM_GIANT) + mntmp = rn2(3) ? PM_STONE_GIANT : PM_HILL_GIANT; + /* note: PM_DWARF and PM_GNOME are ordinary monsters and + no longer flagged no-poly so have no need for placeholder + handling; PM_HUMAN is a placeholder without a suitable + substitute so gets handled differently below */ } + if (mntmp < LOW_PM) { if (!class) pline("I've never heard of such monsters."); @@ -581,6 +603,7 @@ polyself(int psflags) } else break; } while (--tryct > 0); + if (!tryct) pline1(thats_enough_tries); /* allow skin merging, even when polymorph is controlled */