extern struct obj *mk_artifact(struct obj *, aligntyp);
extern const char *artifact_name(const char *, short *);
extern boolean exist_artifact(int, const char *);
-extern void artifact_exists(struct obj *, const char *, boolean, boolean);
+extern void artifact_exists(struct obj *, const char *, boolean, unsigned);
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 int artifact_bones(struct obj *, boolean);
+extern void artifact_origin(struct obj *, unsigned);
extern boolean arti_immune(struct obj *, int);
extern boolean spec_ability(struct obj *, unsigned long);
extern boolean confers_luck(struct obj *);
#define BUCX_TYPES (BUC_ALLBKNOWN | BUC_UNKNOWN)
#define ALL_TYPES_SELECTED -2
-/* Flags for oname() */
-#define ONAME_NO_FLAGS 0U /* none of the below */
-#define ONAME_VIA_NAMING 1U /* oname() is being called by do_oname() */
-#define ONAME_FOUND_ARTI 2U /* if an artifact, hero becomes aware of it */
+/* Flags for oname(), artifact_exists(), artifact_origin() */
+#define ONAME_NO_FLAGS 0U /* none of the below; they apply to artifacts */
+/* 0x0001U is reserved for 'exists' */
+/* flags indicating where an artifact came from */
+#define ONAME_VIA_NAMING 0x0002U /* oname() is being called by do_oname();
+ * only matters if creating Sting|Orcrist */
+#define ONAME_WISH 0x0004U /* created via wish */
+#define ONAME_GIFT 0x0008U /* created as a divine reward after #offer or
+ * special #pray result of being crowned */
+#define ONAME_VIA_DIP 0x0010U /* created Excalibur in a fountain */
+#define ONAME_LEVEL_DEF 0x0020U /* placed by a special level's definition */
+#define ONAME_BONES 0x0040U /* object came from bones; in its original
+ * game it had one of the other bits but we
+ * don't care which one */
+#define ONAME_RANDOM 0x0080U /* something created an artifact randomly
+ * with mk_artifact() (mksboj or mk_player)
+ * or m_initweap() (lawful Angel) */
+/* flag congrolling potential livelog event of finding an artifact */
+#define ONAME_KNOW_ARTI 0x0100U /* hero is already aware of this artifact */
/* Flags to control find_mid() */
#define FM_FMON 0x01 /* search the fmon chain */
* Incrementing EDITLEVEL can be used to force invalidation of old bones
* and save files.
*/
-#define EDITLEVEL 52
+#define EDITLEVEL 53
/*
* Development status possibilities.
/* 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 */
+ Bitfield(exists, 1); /* 1 if corresponding artifact has been created */
+ Bitfield(found, 1); /* 1 if artifact is known by hero to exist */
+ Bitfield(gift, 1); /* 1 iff artifact was created as a prayer reward */
+ Bitfield(wish, 1); /* 1 iff artifact was created via wish */
+ Bitfield(named, 1); /* 1 iff artifact was made by naming an item */
+ Bitfield(viadip, 1); /* 1 iff dipped long sword became Excalibur */
+ Bitfield(lvldef, 1); /* 1 iff created by special level definition */
+ Bitfield(bones, 1); /* 1 iff came from bones file */
+ Bitfield(rndm, 1); /* 1 iff randomly generated */
};
/* array of flags tracking which artifacts exist, indexed by ART_xx;
ART_xx values are 1..N, element [0] isn't used; no terminator needed */
if (otmp) {
otmp = oname(otmp, a->name, ONAME_NO_FLAGS);
otmp->oartifact = m;
- artiexist[m] = zero_artiexist;
- artiexist[m].exists = 1;
- /* default creation reason is 'random'; caller can revise it */
- artiexist[m].rndm = 1;
+ /* set existence and reason for creation bits */
+ artifact_origin(otmp, ONAME_RANDOM); /* 'random' is default */
}
} else {
/* nothing appropriate could be found; return original object */
struct obj *otmp,
const char *name,
boolean mod, /* True: exists, False: being un-created */
- boolean knwn) /* True: hero knows it exists */
+ unsigned flgs) /* ONAME_xyz flags; not relevant if !mod */
{
register const struct artifact *a;
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;
+ if (mod) { /* means being created rather than un-created */
+ /* one--and only one--of these should always be set */
+ if ((flgs & (ONAME_VIA_NAMING | ONAME_WISH | ONAME_GIFT
+ | ONAME_VIA_DIP | ONAME_LEVEL_DEF
+ | ONAME_BONES | ONAME_RANDOM)) == 0)
+ flgs |= ONAME_RANDOM; /* the default origin */
+ /* 'exists' bit will become set (in artifact_origin();
+ there's no ONAME_ flag) and flgs might also contain
+ the know_arti bit (hero knows that artifact exists) */
+ artifact_origin(otmp, flgs);
+ } else { /* uncreate */
+ /* clear all the flag bits */
+ artiexist[m] = zero_artiexist;
+ }
break;
}
return;
return a;
}
-/*
- * TODO:
- * artifact_gift(), artifact_wish(), artifact_named(), artifact_viadip(),
- * and artifact_bones() 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;
-}
-
-/* mark artifact as coming from a bones file or query if it did */
-int
-artifact_bones(
- struct obj *otmp,
- boolean set) /* True, mark otmp->oartifact as bones */
+/* set artifact tracking flags;
+ calling sequence: oname() -> artifact_exists() -> artifact_origin() or
+ mksobj(),others -> mk_artifact() -> artifact_origin(random) possibly
+ followed by mksobj(),others -> artifact_origin(non-random origin) */
+void
+artifact_origin(
+ struct obj *arti, /* new artifact */
+ unsigned aflags) /* ONAME_xxx flags, shared by artifact_exists() */
{
- int a = otmp->oartifact;
+ int ct, a = arti->oartifact;
if (a) {
- if (set && !artiexist[a].bones) {
- /* clear all bits; most are mutually exclusive */
- artiexist[a] = zero_artiexist;
- /* set bones bit and force exists bit back on */
- artiexist[a].bones = 1;
- artiexist[a].exists = 1;
- /* don't mark artifact from bones as found */
- }
- return (int) artiexist[a].bones; /* cast: convert unsigned bitfield */
+ /* start by clearing all bits; most are mutually exclusive */
+ artiexist[a] = zero_artiexist;
+ /* set 'exists' bit back on; not specified via flag bit in aflags */
+ artiexist[a].exists = 1;
+ /* 'hero knows it exists' is expected for wish, gift, viadip, or
+ named and could eventually become set for any of the others */
+ if ((aflags & ONAME_KNOW_ARTI) != 0)
+ artiexist[a].found = 1;
+ /* should be exactly one of wish, gift, via_dip, via_naming,
+ level_def (quest), bones, and random (floor or monst's minvent) */
+ ct = 0;
+ if ((aflags & ONAME_WISH) != 0)
+ artiexist[a].wish = 1, ++ct;
+ if ((aflags & ONAME_GIFT) != 0)
+ artiexist[a].gift = 1, ++ct;
+ if ((aflags & ONAME_VIA_DIP) != 0)
+ artiexist[a].viadip = 1, ++ct;
+ if ((aflags & ONAME_VIA_NAMING) != 0)
+ artiexist[a].named = 1, ++ct;
+ if ((aflags & ONAME_LEVEL_DEF) != 0)
+ artiexist[a].lvldef = 1, ++ct;
+ if ((aflags & ONAME_BONES) != 0)
+ artiexist[a].bones = 1, ++ct;
+ if ((aflags & ONAME_RANDOM) != 0)
+ artiexist[a].rndm = 1, ++ct;
+ if (ct != 1)
+ impossible("invalid artifact origin: %4o", aflags);
}
- return 0;
}
boolean
putstr(tmpwin, iflags.menu_headings, "Artifacts");
for (m = 1; m <= NROFARTIFACTS; ++m) {
- Sprintf(buf2, "[%s%s%s%s%s%s%s%s]",
- /* if any of these are non-zero we expect .exists to be too
- so no leading space for it */
- artiexist[m].exists ? "exists" : "",
- artiexist[m].found ? " found" : "",
+ Sprintf(buf2, "[%s%s%s%s%s%s%s%s%s]", /* 9 bits overall */
+ artiexist[m].exists ? "exists;" : "",
+ artiexist[m].found ? " hero knows;" : "",
+ /* .exists and .found have different punctuation because
+ they're expected to be combined with one of these */
artiexist[m].gift ? " gift" : "",
artiexist[m].wish ? " wish" : "",
artiexist[m].named ? " named" : "",
artiexist[m].viadip ? " viadip" : "",
- artiexist[m].rndm ? " random" : "",
- artiexist[m].bones ? " bones" : "");
+ artiexist[m].lvldef ? " lvldef" : "",
+ artiexist[m].bones ? " bones" : "",
+ artiexist[m].rndm ? " random" : "");
#if 0 /* 'tmpwin' here is a text window, not a menu */
if (iflags.menu_tab_sep)
Sprintf(buf, " %s\t%s", artiname(m), buf2);
if (has_oname(otmp))
free_oname(otmp);
} else {
- artifact_exists(otmp, safe_oname(otmp), TRUE, FALSE);
- (void) artifact_bones(otmp, TRUE);
+ artifact_exists(otmp, safe_oname(otmp), TRUE,
+ ONAME_BONES);
}
} else if (has_oname(otmp)) {
sanitize_name(ONAME(otmp));
a valid artifact name */
u.uconduct.literate++;
}
- obj = oname(obj, buf, ONAME_VIA_NAMING);
+ obj = oname(obj, buf, ONAME_VIA_NAMING | ONAME_KNOW_ARTI);
}
struct obj *
-oname(struct obj *obj, const char *name, unsigned oflgs)
+oname(
+ struct obj *obj, /* item to assign name to */
+ const char *name, /* name to assign */
+ unsigned oflgs) /* flags for artifact creation; otherwise ignored */
{
int lth;
char buf[PL_PSIZ];
- boolean via_naming = (oflgs & ONAME_VIA_NAMING) != 0,
- found_arti = (oflgs & ONAME_FOUND_ARTI) != 0;
+ boolean via_naming = (oflgs & ONAME_VIA_NAMING) != 0;
lth = *name ? (int) (strlen(name) + 1) : 0;
if (lth > PL_PSIZ) {
Strcpy(ONAME(obj), name);
if (lth)
- artifact_exists(obj, name, TRUE, via_naming || found_arti);
+ artifact_exists(obj, name, TRUE, oflgs);
if (obj->oartifact) {
/* can't dual-wield with artifact as secondary weapon */
if (obj == uswapwep)
if (obj->unpaid)
alter_cost(obj, 0L);
if (via_naming) {
- (void) artifact_named(obj, TRUE);
-
/* violate illiteracy conduct since successfully wrote arti-name */
if (!u.uconduct.literate++)
livelog_printf(LL_CONDUCT | LL_ARTIFACT,
pline(
"From the murky depths, a hand reaches up to bless the sword.");
pline("As the hand retreats, the fountain disappears!");
- obj = oname(obj, artiname(ART_EXCALIBUR), ONAME_FOUND_ARTI);
+ obj = oname(obj, artiname(ART_EXCALIBUR),
+ ONAME_VIA_DIP | ONAME_KNOW_ARTI);
discover_artifact(ART_EXCALIBUR);
- (void) artifact_viadip(obj, TRUE);
bless(obj);
obj->oeroded = obj->oeroded2 = 0;
obj->oerodeproof = TRUE;
: ptr->maligntyp) == A_LAWFUL)
otmp = oname(otmp,
artiname(rn2(2) ? ART_DEMONBANE : ART_SUNSWORD),
- ONAME_NO_FLAGS);
+ ONAME_RANDOM); /* randomly created */
bless(otmp);
otmp->oerodeproof = TRUE;
otmp->spe = rn2(4);
/* this has now become very similar to m_useupall()... */
extract_from_minvent(mtmp, otmp, TRUE, TRUE);
if (uncreate_artifacts && otmp->oartifact)
- artifact_exists(otmp, safe_oname(otmp), FALSE, FALSE);
+ artifact_exists(otmp, safe_oname(otmp), FALSE, ONAME_NO_FLAGS);
obfree(otmp, (struct obj *) 0); /* dealloc_obj() isn't sufficient */
}
}
if (mdat->msize < MZ_HUMAN && otyp != FIGURINE
/* oc_big is also oc_bimanual and oc_bulky */
&& (otmp->owt > 30 || objects[otyp].oc_big)) {
- if (otmp->oartifact)
- artifact_exists(otmp, safe_oname(otmp), FALSE, FALSE);
+ if (otmp->oartifact) /* un-create */
+ artifact_exists(otmp, safe_oname(otmp), FALSE,
+ ONAME_NO_FLAGS);
delobj(otmp);
} else if (!flooreffects(otmp, x, y, nomsg ? "" : "fall")) {
place_object(otmp, x, y);
d.name = novelname;
}
- d.otmp = oname(d.otmp, d.name, ONAME_NO_FLAGS);
+ d.otmp = oname(d.otmp, d.name, ONAME_WISH);
/* name==aname => wished for artifact (otmp->oartifact => got it) */
if (d.otmp->oartifact || d.name == aname) {
d.otmp->quan = 1L;
/* and make them pay; charge them for the wish anyway! */
if ((is_quest_artifact(d.otmp)
|| (d.otmp->oartifact && rn2(nartifact_exist()) > 1)) && !wizard) {
- artifact_exists(d.otmp, safe_oname(d.otmp), FALSE, FALSE);
+ artifact_exists(d.otmp, safe_oname(d.otmp), FALSE, ONAME_NO_FLAGS);
obfree(d.otmp, (struct obj *) 0);
d.otmp = (struct obj *) &cg.zeroobj;
pline("For a moment, you feel %s in your %s, but it disappears!",
obj->dknown = 1;
at_your_feet(upstart(ansimpleoname(obj)));
dropy(obj);
- u.ugifts++; /* bypass artifact_gift() */
+ u.ugifts++;
/* 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,
Strcpy(lbuf, simpleonames(obj)); /* before transformation */
if (!Blind)
Your("sword shines brightly for a moment.");
- obj = oname(obj, artiname(ART_EXCALIBUR), ONAME_FOUND_ARTI);
+ obj = oname(obj, artiname(ART_EXCALIBUR),
+ ONAME_GIFT | ONAME_KNOW_ARTI);
if (obj && obj->oartifact == ART_EXCALIBUR) {
- (void) artifact_gift(obj, TRUE); /* u.ugifts++; */
+ u.ugifts++;
livelog_printf(LL_DIVINEGIFT | LL_ARTIFACT,
"wielded %s transformed into %s",
lbuf, artiname(ART_EXCALIBUR));
obj->dknown = 1;
} else if (!already_exists) {
obj = mksobj(LONG_SWORD, FALSE, FALSE);
- obj = oname(obj, artiname(ART_VORPAL_BLADE), ONAME_FOUND_ARTI);
+ obj = oname(obj, artiname(ART_VORPAL_BLADE),
+ ONAME_GIFT | ONAME_KNOW_ARTI);
obj->spe = 1;
at_your_feet("A sword");
dropy(obj);
- (void) artifact_gift(obj, TRUE); /* u.ugifts++; */
+ u.ugifts++;
livelog_printf(LL_DIVINEGIFT | LL_ARTIFACT,
"bestowed with %s", artiname(ART_VORPAL_BLADE));
}
obj->dknown = 1;
} else if (!already_exists) {
obj = mksobj(RUNESWORD, FALSE, FALSE);
- obj = oname(obj, artiname(ART_STORMBRINGER), ONAME_FOUND_ARTI);
+ obj = oname(obj, artiname(ART_STORMBRINGER),
+ ONAME_GIFT | ONAME_KNOW_ARTI);
obj->spe = 1;
at_your_feet(An(swordbuf));
dropy(obj);
- (void) artifact_gift(obj, TRUE); /* u.ugifts++; */
+ u.ugifts++;
livelog_printf(LL_DIVINEGIFT | LL_ARTIFACT,
"bestowed with %s", artiname(ART_STORMBRINGER));
}
if (otmp) {
char buf[BUFSZ];
+ artifact_origin(otmp, ONAME_GIFT | ONAME_KNOW_ARTI);
if (otmp->spe < 0)
otmp->spe = 0;
if (otmp->cursed)
at_your_feet(upstart(buf));
dropy(otmp);
godvoice(u.ualign.type, "Use my gift wisely!");
- (void) artifact_gift(otmp, TRUE); /* u.ugifts++; */
+ u.ugifts++;
u.ublesscnt = rnz(300 + (50 * nartifacts));
exercise(A_WIS, TRUE);
livelog_printf (LL_DIVINEGIFT | LL_ARTIFACT,
/* set_corpsenm() took care of egg hatch and corpse timers */
if (named) {
- otmp = oname(otmp, o->name.str, ONAME_NO_FLAGS);
+ otmp = oname(otmp, o->name.str, ONAME_LEVEL_DEF);
if (otmp->otyp == SPE_NOVEL) {
/* needs to be an existing title */
(void) lookup_novel(o->name.str, &otmp->novelidx);
}
}
-
if (o->eroded) {
if (o->eroded < 0) {
otmp->oerodeproof = 1;
cobj->owt = weight(cobj);
} else {
obj_extract_self(otmp);
+ /* uncreate a random artifact created in a container */
+ /* FIXME: it could be intentional rather than random */
if (otmp->oartifact)
- artifact_exists(otmp, safe_oname(otmp), FALSE, FALSE);
+ artifact_exists(otmp, safe_oname(otmp), FALSE,
+ ONAME_NO_FLAGS); /* flags don't matter */
obfree(otmp, NULL);
return;
}
if (otmp->oartifact)
/* update artifact bookkeeping; doesn't produce a livelog event */
- (void) artifact_wish(otmp, TRUE); /* calls found_artifact() */
+ artifact_origin(otmp, ONAME_WISH | ONAME_KNOW_ARTI);
}
/* wisharti conduct handled in readobjnam() */