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; - maybe_LL_arti = ((prev_artwish < u.uconduct.wisharti) ? LL_ARTIFACT : 0L); + if (otmp->oartifact) + /* update artifact bookkeeping; doesn't produce a livelog event */ + artifact_wish(otmp, TRUE); /* calls found_artifact() */ + } + + /* 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