From: Michael Meyer Date: Thu, 28 Oct 2021 21:18:20 +0000 (-0400) Subject: Writing scrolls by type-name followup X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c9cef70d51173cb8079e77a5b82c947fe8e3cdd1;p=nethack Writing scrolls by type-name followup Don't allow type-name of a scroll that has since been formally identified to override a real scroll name. For example, if a user typenames a scroll of fire 'earth', then IDs fire but doesn't change the typename (reasonable, since it doesn't show up anywhere in inventory at that point), if they try to write 'earth' with a magic marker, don't produce a scroll of fire just because it's still type-named 'earth'. At that point they know it's not a scroll of earth and it's no longer reasonable to assume they mean to use the typename. In other words, if a user-assigned typename matches a real scroll type, write the scroll with the typename -- unless the player knows for sure it doesn't match the actual scroll (whether because the actual scroll is already IDed, or the typenamed scroll has been IDed as something else). In that case write (or attempt to write) the actual scroll as though the typename didn't exist. --- diff --git a/src/write.c b/src/write.c index 20c4ba3bd..6ccd45546 100644 --- a/src/write.c +++ b/src/write.c @@ -108,7 +108,7 @@ dowrite(struct obj *pen) int basecost, actualcost; int curseval; char qbuf[QBUFSZ]; - int first, last, i, deferred, deferralchance; + int first, last, i, deferred, deferralchance, real; boolean by_descr = FALSE; const char *typeword; @@ -170,10 +170,11 @@ dowrite(struct obj *pen) (void) mungspaces(bp + 1); /* remove the extra space */ } - deferred = 0; /* not any scroll or book */ - deferralchance = 0; /* incremented for each oc_uname match */ + deferred = real = 0; /* not any scroll or book */ + deferralchance = 0; /* incremented for each oc_uname match */ first = g.bases[(int) paper->oclass]; last = g.bases[(int) paper->oclass + 1] - 1; + /* first loop: look for match with name/description */ for (i = first; i <= last; i++) { /* extra shufflable descr not representing a real object */ if (!OBJ_NAME(objects[i])) @@ -184,24 +185,30 @@ dowrite(struct obj *pen) /* spellbooks can only be written by_name, so no need to hold out for a 'better' by_descr match */ || paper->oclass == SPBOOK_CLASS) { - by_descr = FALSE; goto found; - } else if (!deferralchance) { - /* save item in case there are no better by_descr matches; - don't increment deferralchance so that the first uname - match will always override this */ - deferred = i; + } else { + /* save item in case there are no better by_descr matches */ + real = deferred = i; + break; } } + if (!strcmpi(OBJ_DESCR(objects[i]), nm)) { by_descr = TRUE; goto found; } - /* user-assigned name might match real name of a later - entry, so we don't simply use first match with it; - also, player might assign same name multiple times - and if so, we choose one of those matches randomly */ + } + /* second loop: look for match with user-assigned name */ + /* we will get here if 'nm' isn't a real scroll name/descr, or is the name + * of a real scroll that hasn't been formally IDed. */ + for (i = first; i <= last; i++) { + /* player might assign same name multiple times and if so, + we choose one of those matches randomly */ if (objects[i].oc_uname && !strcmpi(objects[i].oc_uname, nm) + /* prefer attempting to write the real scroll type if + the typename clobbers a real scroll and is known to + be incorrect */ + && !(real && objects[i].oc_name_known) /* * First match: chance incremented to 1, * !rn2(1) is 1, we remember i;