artifact tracking again
Redo the recent artifact creation stuff by replacing several nearly identical routines with one more general one. Also adds a tracking bit for one or two more creation methods. That changed artiexist[] from an array of structs holding 8 or less bits to one holding 9, so bump EDITLEVEL in case the total size changed.
This commit is contained in:
207
src/artifact.c
207
src/artifact.c
@@ -42,14 +42,15 @@ static int count_surround_traps(int, int);
|
||||
/* 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 */
|
||||
@@ -214,10 +215,8 @@ mk_artifact(
|
||||
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 */
|
||||
@@ -277,7 +276,7 @@ artifact_exists(
|
||||
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;
|
||||
|
||||
@@ -290,10 +289,20 @@ 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;
|
||||
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;
|
||||
@@ -365,123 +374,46 @@ nartifact_exist(void)
|
||||
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 */
|
||||
/* 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].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 */
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
{
|
||||
int a = otmp->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 */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean
|
||||
@@ -1135,17 +1067,18 @@ dump_artifact_info(winid tmpwin)
|
||||
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user