]> granicus.if.org Git - nethack/commitdiff
keep track of how artifacts got created
authorPatR <rankin@nethack.org>
Thu, 10 Mar 2022 00:11:14 +0000 (16:11 -0800)
committerPatR <rankin@nethack.org>
Thu, 10 Mar 2022 00:11:14 +0000 (16:11 -0800)
Since the struct used for elements of artiexist[] has a lot of unused
bits, add some new ones to extend it to indicate how artifacts have
been created.  It had
| .exists (has been created) and
| .found (hero is aware that it has been created)
introduce
| .gift (divine gift),
| .wish (player wish),
| .named (naming elven weapon Sting or Orcrist)
| .viadip (made Excalibur by dipping long sword into fountain)
| .rndm (randomly created), and
| .bones (from bones file--how it got created in earlier game isn't
tracked).  The first four are implemented, fifth and sixth aren't.

Some of the feedback when receiving an artifact or spellbook has been
revised.

When artiexist[] was changed from an array of booleans to an array of
structs a couple of days ago, EDITLEVEL should have been incremented
but I overlooked that at the time.  This commit does so now.

include/extern.h
include/patchlevel.h
src/artifact.c
src/do_name.c
src/fountain.c
src/pray.c
src/zap.c

index 62a8d029802b753dd8331a3f6f5b49de1d9fe35a..e7c6802e65472fffc801440c6675fc01773d19fc 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.7 extern.h        $NHDT-Date: 1646838387 2022/03/09 15:06:27 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1068 $ */
+/* NetHack 3.7 extern.h        $NHDT-Date: 1646870811 2022/03/10 00:06:51 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1069 $ */
 /* Copyright (c) Steve Creps, 1988.                              */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -73,6 +73,10 @@ extern void artifact_exists(struct obj *, const char *, boolean, boolean);
 extern void found_artifact(int);
 extern void find_artifact(struct obj *);
 extern int nartifact_exist(void);
+extern int artifact_gift(struct obj *, boolean);
+extern int artifact_wish(struct obj *, boolean);
+extern int artifact_named(struct obj *, boolean);
+extern int artifact_viadip(struct obj *, boolean);
 extern boolean arti_immune(struct obj *, int);
 extern boolean spec_ability(struct obj *, unsigned long);
 extern boolean confers_luck(struct obj *);
index 2dd5481f783e00ef15cdc9689438290d2123ee24..ba152069427112ed9746286aba5088c10cf65d4a 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.7 patchlevel.h    $NHDT-Date: 1646451566 2022/03/05 03:39:26 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.201 $ */
+/* NetHack 3.7 patchlevel.h    $NHDT-Date: 1646870832 2022/03/10 00:07:12 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.202 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Michael Allison, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -17,7 +17,7 @@
  * Incrementing EDITLEVEL can be used to force invalidation of old bones
  * and save files.
  */
-#define EDITLEVEL 51
+#define EDITLEVEL 52
 
 /*
  * Development status possibilities.
index 5734b89bd25604a6c5cff21cb9279b8b46b8c849..3aab1b5b7207791c0a785001bda2f07cffce4e1e 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.7 artifact.c      $NHDT-Date: 1646688062 2022/03/07 21:21:02 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.181 $ */
+/* NetHack 3.7 artifact.c      $NHDT-Date: 1646870837 2022/03/10 00:07:17 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.182 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Robert Patrick Rankin, 2013. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -39,10 +39,17 @@ static int count_surround_traps(int, int);
    of hit points that will fit in a 15 bit integer. */
 #define FATAL_DAMAGE_MODIFIER 200
 
-/* artifact tracking */
+/* artifact tracking; gift and wish imply found; it also gets set for items
+   seen on the floor, in containers, and wielded or dropped by monsters */
 struct arti_info {
     Bitfield(exists, 1); /* True if corresponding artifact has been created */
     Bitfield(found, 1);  /* True if artifact is known by hero to exist */
+    Bitfield(gift, 1);   /* True if artifact was created as a prayer reward */
+    Bitfield(wish, 1);   /* True if artifact was created via wish */
+    Bitfield(named, 1);  /* True if artifact was made by naming an item */
+    Bitfield(viadip, 1); /* True if dipped long sword became Excalibur */
+    Bitfield(rndm, 1);   /* randomly generated; not (yet?) implemented */
+    Bitfield(bones, 1);  /* came from bones file; not (yet?) implemented */
 };
 /* array of flags tracking which artifacts exist, indexed by ART_xx;
    ART_xx values are 1..N, element [0] isn't used */
@@ -55,6 +62,7 @@ static xchar artidisco[NROFARTIFACTS];
  * bulk re-init if game restart ever gets implemented.  They are saved
  * and restored but that is done through this file so they can be local.
  */
+static const struct arti_info zero_artiexist; /* all bits zero */
 
 static void hack_artifacts(void);
 static boolean attacks(int, struct obj *);
@@ -206,8 +214,8 @@ mk_artifact(
         if (otmp) {
             otmp = oname(otmp, a->name, ONAME_NO_FLAGS);
             otmp->oartifact = m;
+            artiexist[m] = zero_artiexist;
             artiexist[m].exists = 1;
-            artiexist[m].found = 0;
         }
     } else {
         /* nothing appropriate could be found; return original object */
@@ -260,11 +268,13 @@ exist_artifact(int otyp, const char *name)
     return FALSE;
 }
 
+/* an artifact has just been created or is being "un-created" for a chance
+   to be created again later */
 void
 artifact_exists(
     struct obj *otmp,
     const char *name,
-    boolean mod,      /* True: exists, False: being uncreated */
+    boolean mod,      /* True: exists, False: being un-created */
     boolean knwn)     /* True: hero knows it exists */
 {
     register const struct artifact *a;
@@ -278,6 +288,8 @@ artifact_exists(
                 otmp->age = 0;
                 if (otmp->otyp == RIN_INCREASE_DAMAGE)
                     otmp->spe = 0;
+                /* clear all the flag bits, then maybe set a couple of them */
+                artiexist[m] = zero_artiexist;
                 artiexist[m].exists = mod ? 1 : 0;
                 artiexist[m].found = (mod && knwn) ? 1 : 0;
                 break;
@@ -289,7 +301,12 @@ artifact_exists(
 void
 found_artifact(int a)
 {
-    artiexist[a].found = 1;
+    if (a < 1 || a > NROFARTIFACTS)
+        impossible("found_artifact: invalid artifact index! (%d)", a);
+    else if (!artiexist[a].exists)
+        impossible("found_artifact: artifact doesn't exist yet? (%d)", a);
+    else
+        artiexist[a].found = 1;
 }
 
 /* if an artifact hasn't already been designated 'found', do that now
@@ -300,7 +317,6 @@ find_artifact(struct obj *otmp)
     int a = otmp->oartifact;
 
     if (a && !artiexist[a].found) {
-        char buf[BUFSZ];
         const char *where;
 
         found_artifact(a); /* artiexist[a].found = 1 */
@@ -330,8 +346,8 @@ find_artifact(struct obj *otmp)
                         blind but now seen; there's no previous_where to
                         figure out how it got here */
                      : "");
-        (void) strsubst(strcpy(buf, artiname(a)), "The ", "the ");
-        livelog_printf(LL_ARTIFACT, "found %s%s", buf, where);
+        livelog_printf(LL_ARTIFACT, "found %s%s",
+                       bare_artifactname(otmp), where);
     }
 }
 
@@ -347,6 +363,102 @@ nartifact_exist(void)
     return a;
 }
 
+/*
+ * TODO:
+ *  artifact_gift(), artifact_wish(), artifact_named(), and artifact_viadip()
+ *  are nearly identical and should be folded into a single routine.
+ */
+
+/* mark artifact as a divine gift or query if it has been marked as such */
+int
+artifact_gift(
+    struct obj *otmp,
+    boolean set) /* True, mark otmp->oartifact as gift; False, ask if it is */
+{
+    int a = otmp->oartifact;
+
+    if (a) {
+        if (set && !artiexist[a].gift) {
+            /* clear all bits; most are mutually exclusive */
+            artiexist[a] = zero_artiexist;
+            /* set gift bit and force exists bit back on */
+            artiexist[a].gift = 1;
+            artiexist[a].exists = 1;
+            found_artifact(a); /* assume hero is aware of the gift... */
+
+            u.ugifts++; /* used to be done at several places in pray.c */
+        }
+        return (int) artiexist[a].gift; /* cast: convert unsigned bitfield */
+    }
+    return 0;
+}
+
+/* mark artifact as a player wish or query if it has been marked as such */
+int
+artifact_wish(
+    struct obj *otmp,
+    boolean set) /* True, mark otmp->oartifact as wish; False, ask if it is */
+{
+    int a = otmp->oartifact;
+
+    if (a) {
+        if (set && !artiexist[a].wish) {
+            /* clear all bits; most are mutually exclusive */
+            artiexist[a] = zero_artiexist;
+            /* set wish bit and force exists bit back on */
+            artiexist[a].wish = 1;
+            artiexist[a].exists = 1;
+            found_artifact(a); /* assume hero is aware of wish outcome */
+        }
+        return (int) artiexist[a].wish; /* cast: convert unsigned bitfield */
+    }
+    return 0;
+}
+
+/* mark artifact as created via naming or query if it is marked as such */
+int
+artifact_named(
+    struct obj *otmp,
+    boolean set) /* True, mark otmp->oartifact as named */
+{
+    int a = otmp->oartifact;
+
+    if (a) {
+        if (set && !artiexist[a].named) {
+            /* clear all bits; most are mutually exclusive */
+            artiexist[a] = zero_artiexist;
+            /* set named bit and force exists bit back on */
+            artiexist[a].named = 1;
+            artiexist[a].exists = 1;
+            found_artifact(a); /* hero should be aware of naming outcome */
+        }
+        return (int) artiexist[a].named; /* cast: convert unsigned bitfield */
+    }
+    return 0;
+}
+
+/* mark artifact as created via dipping or query if it is marked as such */
+int
+artifact_viadip(
+    struct obj *otmp,
+    boolean set) /* True, mark otmp->oartifact as viadip */
+{
+    int a = otmp->oartifact;
+
+    if (a) {
+        if (set && !artiexist[a].viadip) {
+            /* clear all bits; most are mutually exclusive */
+            artiexist[a] = zero_artiexist;
+            /* set viadip bit and force exists bit back on */
+            artiexist[a].viadip = 1;
+            artiexist[a].exists = 1;
+            found_artifact(a); /* hero is aware of dip outcome */
+        }
+        return (int) artiexist[a].viadip; /* cast: convert unsigned bitfield */
+    }
+    return 0;
+}
+
 boolean
 spec_ability(struct obj *otmp, unsigned long abil)
 {
index 843ecf3b152f00490fedf2a770f24a37b42d2641..3bac70e0bd59cdea7f246d5511580932b3bf9af3 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.7 do_name.c       $NHDT-Date: 1644347168 2022/02/08 19:06:08 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.231 $ */
+/* NetHack 3.7 do_name.c       $NHDT-Date: 1646870842 2022/03/10 00:07:22 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.239 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Pasi Kallinen, 2018. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -1341,6 +1341,8 @@ oname(struct obj *obj, const char *name, unsigned oflgs)
         if (obj->unpaid)
             alter_cost(obj, 0L);
         if (via_naming) {
+            artifact_named(obj, TRUE);
+
             /* violate illiteracy conduct since successfully wrote arti-name */
             if (!u.uconduct.literate++)
                 livelog_printf(LL_CONDUCT | LL_ARTIFACT,
index b9292ed495bd4a685b8d463cf7cfbb6ba73b889b..dc9d2779a9badd97ebcc9505c8e3a664f26f9083 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.7 fountain.c      $NHDT-Date: 1596498170 2020/08/03 23:42:50 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.69 $ */
+/* NetHack 3.7 fountain.c      $NHDT-Date: 1646870844 2022/03/10 00:07:24 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.78 $ */
 /*      Copyright Scott R. Turner, srt@ucla, 10/27/86 */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -404,6 +404,7 @@ dipfountain(register struct obj *obj)
             pline("As the hand retreats, the fountain disappears!");
             obj = oname(obj, artiname(ART_EXCALIBUR), ONAME_FOUND_ARTI);
             discover_artifact(ART_EXCALIBUR);
+            artifact_viadip(obj, TRUE);
             bless(obj);
             obj->oeroded = obj->oeroded2 = 0;
             obj->oerodeproof = TRUE;
index c5ae676df8fb33ada4eff7c5243846e602f6e79e..baeda569dd3bf7b51a1febe684fb8f156e9414a2 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.7 pray.c  $NHDT-Date: 1646838389 2022/03/09 15:06:29 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.163 $ */
+/* NetHack 3.7 pray.c  $NHDT-Date: 1646870846 2022/03/10 00:07:26 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.164 $ */
 /* Copyright (c) Benson I. Margulies, Mike Stephenson, Steve Linhart, 1989. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -750,8 +750,9 @@ at_your_feet(const char *str)
               s_suffix(mon_nam(u.ustuck)), mbodypart(u.ustuck, STOMACH));
     } else {
         pline("%s %s %s your %s!", str,
-              Blind ? "lands" : vtense(str, "appear"),
-              Levitation ? "beneath" : "at", makeplural(body_part(FOOT)));
+              vtense(str, Blind ? "land" : "appear"),
+              Levitation ? "beneath" : "at",
+              makeplural(body_part(FOOT)));
     }
 }
 
@@ -829,9 +830,10 @@ gcrownu(void)
                                          * even if hero doesn't know book */
         bless(obj);
         obj->bknown = 1; /* ok to skip set_bknown() */
-        at_your_feet("A spellbook");
+        obj->dknown = 1;
+        at_your_feet(upstart(ansimpleoname(obj)));
         dropy(obj);
-        u.ugifts++;
+        u.ugifts++; /* bypass artifact_gift() */
         /* not an artifact, but treat like one for this situation;
            classify as a spoiler in case player hasn't IDed the book yet */
         livelog_printf(LL_DIVINEGIFT | LL_ARTIFACT | LL_SPOILER,
@@ -855,7 +857,7 @@ gcrownu(void)
                 Your("sword shines brightly for a moment.");
             obj = oname(obj, artiname(ART_EXCALIBUR), ONAME_FOUND_ARTI);
             if (obj && obj->oartifact == ART_EXCALIBUR) {
-                u.ugifts++;
+                artifact_gift(obj, TRUE); /* u.ugifts++; */
                 livelog_printf(LL_DIVINEGIFT | LL_ARTIFACT,
                                "wielded %s transformed into %s",
                                lbuf, artiname(ART_EXCALIBUR));
@@ -878,7 +880,7 @@ gcrownu(void)
             obj->spe = 1;
             at_your_feet("A sword");
             dropy(obj);
-            u.ugifts++;
+            artifact_gift(obj, TRUE); /* u.ugifts++; */
             livelog_printf(LL_DIVINEGIFT | LL_ARTIFACT,
                            "bestowed with %s", artiname(ART_VORPAL_BLADE));
         }
@@ -902,7 +904,7 @@ gcrownu(void)
             obj->spe = 1;
             at_your_feet(An(swordbuf));
             dropy(obj);
-            u.ugifts++;
+            artifact_gift(obj, TRUE); /* u.ugifts++; */
             livelog_printf(LL_DIVINEGIFT | LL_ARTIFACT,
                            "bestowed with %s", artiname(ART_STORMBRINGER));
         }
@@ -1003,16 +1005,7 @@ give_spell(void)
         if (otmp->otyp == SPE_BLANK_PAPER || !rn2(100))
             makeknown(otmp->otyp);
         bless(otmp);
-        /* note: Hallucination case can't happen because we only get
-           called for a boon and boons are only bestowed if all troubles
-           (including hallucination) have been cured/repaired; might
-           apply in variants that offer "always high" as a play option
-           and classify hallucinating as not trouble or not fixable */
-        at_your_feet(Hallucination ? "A thesarus"
-                     : Blind ? "A spellbook"
-                       /* "An orange spellbook" or "A spellbook of knock"
-                          depending on discoveries */
-                       : upstart(ansimpleoname(otmp)));
+        at_your_feet(upstart(ansimpleoname(otmp)));
         place_object(otmp, u.ux, u.uy);
         newsym(u.ux, u.uy);
     }
@@ -1859,15 +1852,23 @@ dosacrifice(void)
                 && !rn2(10 + (2 * u.ugifts * nartifacts))) {
                 otmp = mk_artifact((struct obj *) 0, a_align(u.ux, u.uy));
                 if (otmp) {
+                    char buf[BUFSZ];
+
                     if (otmp->spe < 0)
                         otmp->spe = 0;
                     if (otmp->cursed)
                         uncurse(otmp);
                     otmp->oerodeproof = TRUE;
-                    at_your_feet("An object");
+                    Strcpy(buf, (Hallucination ? "a doodad"
+                                 : Blind ? "an object"
+                                   : ansimpleoname(otmp)));
+                    if (!Blind)
+                        Sprintf(eos(buf), " named %s",
+                                bare_artifactname(otmp));
+                    at_your_feet(upstart(buf));
                     dropy(otmp);
                     godvoice(u.ualign.type, "Use my gift wisely!");
-                    u.ugifts++;
+                    artifact_gift(otmp, TRUE); /* u.ugifts++; */
                     u.ublesscnt = rnz(300 + (50 * nartifacts));
                     exercise(A_WIS, TRUE);
                     livelog_printf (LL_DIVINEGIFT | LL_ARTIFACT,
index cf6180dd1ae9f3780e71e31d62086553cdab5004..2d32b315d60b2e17a5aec96aaaa734a4f082318f 100644 (file)
--- a/src/zap.c
+++ b/src/zap.c
@@ -1,4 +1,4 @@
-/* NetHack 3.7 zap.c   $NHDT-Date: 1646652775 2022/03/07 11:32:55 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.401 $ */
+/* NetHack 3.7 zap.c   $NHDT-Date: 1646870848 2022/03/10 00:07:28 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.402 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Robert Patrick Rankin, 2013. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -5554,7 +5554,7 @@ makewish(void)
     struct obj *otmp, nothing;
     long maybe_LL_arti;
     int tries = 0;
-    int prev_artwish = u.uconduct.wisharti;
+    int oldwisharti = u.uconduct.wisharti;
 
     promptbuf[0] = '\0';
     nothing = cg.zeroobj; /* lint suppression; only its address matters */
@@ -5595,22 +5595,30 @@ makewish(void)
         return;
     }
 
-    if (otmp->oartifact)
-        /* update artifact bookkeeping; doesn't produce a livelog event */
-        found_artifact(otmp->oartifact);
+    if (otmp != &cg.zeroobj) {
+        /* treat as if seen up close even if hero is blind and hasn't
+           touched it yet */
+        otmp->dknown = 1;
+
+        if (otmp->oartifact)
+            /* update artifact bookkeeping; doesn't produce a livelog event */
+            artifact_wish(otmp, TRUE); /* calls found_artifact() */
+    }
 
-    maybe_LL_arti = ((prev_artwish < u.uconduct.wisharti) ? LL_ARTIFACT : 0L);
+    /* wisharti conduct handled in readobjnam() */
+    maybe_LL_arti = ((oldwisharti < u.uconduct.wisharti) ? LL_ARTIFACT : 0L);
     /* KMH, conduct */
     if (!u.uconduct.wishes++)
         livelog_printf((LL_CONDUCT | LL_WISH | maybe_LL_arti),
                        "made %s first wish - \"%s\"", uhis(), bufcpy);
-    else if (!prev_artwish && u.uconduct.wisharti) /* wisharti conduct handled
-                                                    * in readobjnam() above */
+    else if (!oldwisharti && u.uconduct.wisharti)
         livelog_printf((LL_CONDUCT | LL_WISH | LL_ARTIFACT),
                        "made %s first artifact wish - \"%s\"", uhis(), bufcpy);
     else
         livelog_printf((LL_WISH | maybe_LL_arti),
                        "wished for \"%s\"", bufcpy);
+    /* TODO? maybe generate a second event decribing what was received since
+       those just echo player's request rather than show actual result */
 
     if (otmp != &cg.zeroobj) {
         const char