]> granicus.if.org Git - nethack/commitdiff
fix [again] exploiting artifact name rejection
authorPatR <rankin@nethack.org>
Tue, 21 Jun 2022 15:57:58 +0000 (08:57 -0700)
committerPatR <rankin@nethack.org>
Tue, 21 Jun 2022 15:57:58 +0000 (08:57 -0700)
Reported by entrez:  attempting to name certain undiscovered items
after an artifact could be used to tell whether the item being named
was the same type as the artifact, so trying to name a gray stone
the Heart of Ahriman would let you tell whether it was a luckstone.
That was fixed years ago to reject for any undiscovered gray stone
rather than only for luckstone; you'll get "your hand slips" and the
name would be smudged.  But that fix allowed a loophole and could
still be exploited if the player used lowercase for the name:  it
would get changed to mixed capitalization if the object was the
artifact's type or stay lowercase if it only matched by description.

This changes to the capitalized name even when the type isn't an
exact match, so attempting to name either a luckstone or a touchstone
"the heart of ahriman" will name it "The Aeart of Xhriman" with at
least one smudged letter to avoid the actual artifact name.

Unrelated change:  when attempting to apply a new name to an existing
artifact, it now says "<Artifact> resists" rather than "The artifact
seems to resist" because there's no "seeming" about it.

doc/fixes3-7-0.txt
src/do_name.c

index d7f742c7bf96bda1bbd1ad0bf99b7acb94e48b3e..81f06cce1318458a1bb24c4a3efa33d66cc8e753 100644 (file)
@@ -925,6 +925,9 @@ be less specific when cause of death is "handling a <ring or wand>" that
 adjust the row placement of copyright and early startup messages so that
        aren't partially overwritten by prompts that follow
 ball and chain could be accessed after having been freed if bones were saved
+early post-3.4.3 tried to fix the "naming artifacts trick" which could be used
+       to distinguish the type of some undiscovered items, but using a name
+       that only matched an artifact after capitalization was exploitable
 
 
 Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
index c153e8c0d0c51f786938aabbd951ee04de27cbbb..1b007eb3f190f59d930172458d5e3e1bce26e709 100644 (file)
@@ -1252,7 +1252,7 @@ do_oname(struct obj *obj)
 {
     char *bufp, buf[BUFSZ], bufcpy[BUFSZ], qbuf[QBUFSZ];
     const char *aname;
-    short objtyp;
+    short objtyp = STRANGE_OBJECT;
 
     /* Do this now because there's no point in even asking for a name */
     if (obj->otyp == SPE_NOVEL) {
@@ -1285,15 +1285,21 @@ do_oname(struct obj *obj)
      * Orcrist, clearly being literate (no pun intended...).
      */
 
+    if (obj->oartifact) {
+        /* this used to give "The artifact seems to resist the attempt."
+           but resisting is definite, no "seems to" about it */
+        pline("%s resists the attempt.",
+              /* any artifact should always pass the has_oname() test
+                 but be careful just in case */
+              has_oname(obj) ? ONAME(obj) : "The artifact");
+        return;
+    }
+
     /* relax restrictions over proper capitalization for artifacts */
     if ((aname = artifact_name(buf, &objtyp, TRUE)) != 0
-        && objtyp == obj->otyp)
+        && (restrict_name(obj, aname) || exist_artifact(obj->otyp, aname))) {
+        /* substitute canonical spelling before slippage */
         Strcpy(buf, aname);
-
-    if (obj->oartifact) {
-        pline_The("artifact seems to resist the attempt.");
-        return;
-    } else if (restrict_name(obj, buf) || exist_artifact(obj->otyp, buf)) {
         /* this used to change one letter, substituting a value
            of 'a' through 'y' (due to an off by one error, 'z'
            would never be selected) and then force that to
@@ -1307,7 +1313,7 @@ do_oname(struct obj *obj)
            because buf[] matches a valid artifact name) */
         Strcpy(bufcpy, buf);
         /* for "the Foo of Bar", only scuff "Foo of Bar" part */
-        bufp = !strncmpi(bufcpy, "the ", 4) ? (buf + 4) : buf;
+        bufp = !strncmpi(buf, "the ", 4) ? (buf + 4) : buf;
         do {
             wipeout_text(bufp, rn2_on_display_rng(2), (unsigned) 0);
         } while (!strcmp(buf, bufcpy));
@@ -1317,8 +1323,15 @@ do_oname(struct obj *obj)
         /* violate illiteracy conduct since hero attempted to write
            a valid artifact name */
         u.uconduct.literate++;
+    } else if (obj->otyp == objtyp) {
+        /* artifact_name() found a match and restrict_name() didn't reject
+           it; since 'obj' is the right type, naming will change it into an
+           artifact so use canonical capitalization (Sting or Orcrist) */
+        Strcpy(buf, aname);
     }
+
     obj = oname(obj, buf, ONAME_VIA_NAMING | ONAME_KNOW_ARTI);
+    nhUse(obj);
 }
 
 struct obj *