From: PatR Date: Thu, 10 Mar 2022 00:11:14 +0000 (-0800) Subject: keep track of how artifacts got created X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2d977a5d483265609ce9fba567c1dbdbd0b6e5f8;p=nethack keep track of how artifacts got created 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. --- diff --git a/include/extern.h b/include/extern.h index 62a8d0298..e7c6802e6 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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 *); diff --git a/include/patchlevel.h b/include/patchlevel.h index 2dd5481f7..ba1520694 100644 --- a/include/patchlevel.h +++ b/include/patchlevel.h @@ -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. diff --git a/src/artifact.c b/src/artifact.c index 5734b89bd..3aab1b5b7 100644 --- a/src/artifact.c +++ b/src/artifact.c @@ -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) { diff --git a/src/do_name.c b/src/do_name.c index 843ecf3b1..3bac70e0b 100644 --- a/src/do_name.c +++ b/src/do_name.c @@ -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, diff --git a/src/fountain.c b/src/fountain.c index b9292ed49..dc9d2779a 100644 --- a/src/fountain.c +++ b/src/fountain.c @@ -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; diff --git a/src/pray.c b/src/pray.c index c5ae676df..baeda569d 100644 --- a/src/pray.c +++ b/src/pray.c @@ -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, diff --git a/src/zap.c b/src/zap.c index cf6180dd1..2d32b315d 100644 --- 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