]> granicus.if.org Git - nethack/commitdiff
disclosing genocided/extinct monsters
authorPatR <rankin@nethack.org>
Thu, 5 May 2016 00:42:58 +0000 (17:42 -0700)
committerPatR <rankin@nethack.org>
Thu, 5 May 2016 00:42:58 +0000 (17:42 -0700)
Make the handling of unique monsters consistent between vanquished
monsters and genocided/extinct monsters.  No visible difference to
players.

This also prevents Nazgul and erinys from being polymorphed into
some other form to reduce the chance that their kill count fails
to match the expected number when they're reported to be extinct.
[My long test game (with 3451 total dead critters as of the last
save file) used for exercising the sorting of vanquished monsters
included
 120 soldiers
 111 wolves
   9 Nazgul
   2 erinyes
and the genocided/extinct list had none genocided, those four
extinct.  No doubt the missing third erinys was alive somewhere
rather than counted as something else after getting polymorphed,
so this band-aid wouldn't have helped this particular game.]

src/end.c
src/makemon.c
src/mon.c

index eab613d9db8257ab1dbe6dffc601a066d9e4e3e1..f41890dc68a74f34b4d6d19ce17a883debdb8288 100644 (file)
--- a/src/end.c
+++ b/src/end.c
@@ -1578,6 +1578,10 @@ dovanquished()
     return 0;
 }
 
+/* high priests aren't unique but are flagged as such to simplify something */
+#define UniqCritterIndx(mndx) ((mons[mndx].geno & G_UNIQ) \
+                             && mndx != PM_HIGH_PRIEST)
+
 STATIC_OVL void
 list_vanquished(defquery, ask)
 char defquery;
@@ -1639,7 +1643,7 @@ boolean ask;
                            upstart(buf));
                     prev_mlet = mlet;
                 }
-                if ((mons[i].geno & G_UNIQ) && i != PM_HIGH_PRIEST) {
+                if (UniqCritterIndx(i)) {
                     Sprintf(buf, "%s%s",
                             !type_is_pname(&mons[i]) ? "the " : "",
                             mons[i].mname);
@@ -1704,10 +1708,14 @@ num_genocides()
 {
     int i, n = 0;
 
-    for (i = LOW_PM; i < NUMMONS; ++i)
-        if (mvitals[i].mvflags & G_GENOD)
+    for (i = LOW_PM; i < NUMMONS; ++i) {
+        if (mvitals[i].mvflags & G_GENOD) {
             ++n;
-
+            if (UniqCritterIndx(i))
+                impossible("unique creature '%d: %s' genocided?",
+                           i, mons[i].mname);
+        }
+    }
     return n;
 }
 
@@ -1716,11 +1724,12 @@ num_extinct()
 {
     int i, n = 0;
 
-    for (i = LOW_PM; i < NUMMONS; ++i)
-        if (!(mvitals[i].mvflags & G_GENOD) && (mvitals[i].mvflags & G_GONE)
-            && !(mons[i].geno & G_UNIQ))
+    for (i = LOW_PM; i < NUMMONS; ++i) {
+        if (UniqCritterIndx(i))
+            continue;
+        if ((mvitals[i].mvflags & G_GONE) == G_EXTINCT)
             ++n;
-
+    }
     return n;
 }
 
@@ -1755,19 +1764,24 @@ boolean ask;
             putstr(klwin, 0, buf);
             putstr(klwin, 0, "");
 
-            for (i = LOW_PM; i < NUMMONS; i++)
-                if (mvitals[i].mvflags & G_GONE && !(mons[i].geno & G_UNIQ)) {
-                    if ((mons[i].geno & G_UNIQ) && i != PM_HIGH_PRIEST)
-                        Sprintf(buf, "%s%s",
-                                !type_is_pname(&mons[i]) ? "" : "the ",
-                                mons[i].mname);
-                    else
-                        Strcpy(buf, makeplural(mons[i].mname));
-                    if (!(mvitals[i].mvflags & G_GENOD))
+            for (i = LOW_PM; i < NUMMONS; i++) {
+                /* uniques can't be genocided but can become extinct;
+                   however, they're never reported as extinct, so skip them */
+                if (UniqCritterIndx(i))
+                    continue;
+                if (mvitals[i].mvflags & G_GONE) {
+                    Strcpy(buf, makeplural(mons[i].mname));
+                    /*
+                     * "Extinct" is unfortunate terminology.  A species
+                     * is marked extinct when its birth limit is reached,
+                     * but there might be members of the species still
+                     * alive, contradicting the meaning of the word.
+                     */
+                    if ((mvitals[i].mvflags & G_GONE) == G_EXTINCT)
                         Strcat(buf, " (extinct)");
                     putstr(klwin, 0, buf);
                 }
-
+            }
             putstr(klwin, 0, "");
             if (ngenocided > 0) {
                 Sprintf(buf, "%d species genocided.", ngenocided);
index 61de5af0e0b56783f0a18473ba2f3975d571320c..73a1138d49f7b9a4d9d8d4b2f83b4b2754a8d8d8 100644 (file)
@@ -1326,6 +1326,11 @@ int
 mbirth_limit(mndx)
 int mndx;
 {
+    /* There is an implicit limit of 4 for "high priest of <deity>",
+     * but aligned priests can grow into high priests, thus they aren't
+     * really limited to 4, so leave the default amount in place for them.
+     */
+
     /* assert(MAXMONNO < 255); */
     return (mndx == PM_NAZGUL ? 9 : mndx == PM_ERINYS ? 3 : MAXMONNO);
 }
index d3e9c97dedbbf84905711b1cccca250437acf23c..b4a8f97f65c57d90392a3d75dde5744bd68750e7 100644 (file)
--- a/src/mon.c
+++ b/src/mon.c
@@ -3217,8 +3217,14 @@ boolean msg;      /* "The oldmon turns into a newmon!" */
 
     /* Riders are immune to polymorph and green slime
        (but apparent Rider might actually be a doppelganger) */
-    if (is_rider(mtmp->data) && mtmp->cham == NON_PM)
-        return 0;
+    if (mtmp->cham == NON_PM) { /* not a shapechanger */
+        if (is_rider(olddata))
+            return 0;
+        /* make Nazgul and erinyes immune too, to reduce chance of
+           anomalous extinction feedback during final disclsoure */
+        if (mbirth_limit(monsndx(olddata)) < MAXMONNO)
+            return 0;
+    }
 
     if (msg) {
         /* like Monnam() but never mention saddle */