From: nethack.rankin Date: Mon, 7 Jul 2008 03:01:30 +0000 (+0000) Subject: first divine gift artifact (trunk only) X-Git-Tag: MOVE2GIT~435 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e053cb3447efa7ef96d6cea3b54e0196adade5d5;p=nethack first divine gift artifact (trunk only) From the newsgroup: if no co-aligned artifacts are available when attempting to give the first divine gift for an offered corpse, nothing would be given. Since the gift counter stayed at 0, subsequent attempts to select one would still treat it as first gift and always fail again. The first divine gift from offering corpses must match the hero's alignment; after that, nonaligned artifacts (Frost Brand, Giant Slayer, &c) are added to the pool of choices for further divine gifts. It's pretty easy for a chaotic character to use up the co-aligned artifacts before getting any divine gift. There aren't many chaotic ones and some are inelgible due to being race-specific items. Wishing for Stormbringer--or loading a bones file which contains it--and creating Sting and Orcrist via naming will do the trick for an elven hero. This patch expands the pool of candidates to include nonaligned artifacts during first gift selection if no co-aligned ones are available. --- diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 825b60573..c910f95ea 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -286,6 +286,8 @@ can no longer get both strength and resistance from eating one giant corpse aborting key/lock pick usage via ESC at direction prompt no longer use a move when probing from inside an engulfer, "not carrying anything" overlooked hero wearing or removing an amulet of restful sleep clobbered permanent sleepiness +if attempt to select a co-aligned artifact for first divine gift fails because + none is available, choose one from among nonaligned artifacts Platform- and/or Interface-Specific Fixes diff --git a/src/artifact.c b/src/artifact.c index 2f492e04a..25df6f46d 100644 --- a/src/artifact.c +++ b/src/artifact.c @@ -123,37 +123,74 @@ struct obj *otmp; /* existing object; ignored if alignment specified */ aligntyp alignment; /* target alignment, or A_NONE */ { const struct artifact *a; - int n, m; + int m, n, altn; boolean by_align = (alignment != A_NONE); short o_typ = (by_align || !otmp) ? 0 : otmp->otyp; boolean unique = !by_align && otmp && objects[o_typ].oc_unique; short eligible[NROFARTIFACTS]; + n = altn = 0; /* no candidates found yet */ + eligible[0] = 0; /* lint suppression */ /* gather eligible artifacts */ - for (n = 0, a = artilist+1, m = 1; a->otyp; a++, m++) - if ((!by_align ? a->otyp == o_typ : - (a->alignment == alignment || - (a->alignment == A_NONE && u.ugifts > 0))) && - (!(a->spfx & SPFX_NOGEN) || unique) && !artiexist[m]) { - if (by_align && a->race != NON_PM && race_hostile(&mons[a->race])) - continue; /* skip enemies' equipment */ - else if (by_align && Role_if(a->role)) - goto make_artif; /* 'a' points to the desired one */ - else + for (m = 1, a = &artilist[m]; a->otyp; a++, m++) { + if (artiexist[m]) continue; + if ((a->spfx & SPFX_NOGEN) || unique) continue; + + if (!by_align) { + /* looking for a particular type of item; not producing a + divine gift so we don't care about role's first choice */ + if (a->otyp == o_typ) eligible[n++] = m; + continue; /* move on to next possibility */ + } + + /* we're looking for an alignment-specific item + suitable for hero's role+race */ + if ((a->alignment == alignment || a->alignment == A_NONE) && + /* avoid enemies' equipment */ + (a->race == NON_PM || !race_hostile(&mons[a->race]))) { + /* when a role-specific first choice is available, use it */ + if (Role_if(a->role)) { + /* make this be the only possibility in the list */ + eligible[0] = m; + n = 1; + break; /* skip all other candidates */ + } + /* found something to consider for random selection */ + if (a->alignment != A_NONE || u.ugifts > 0) { + /* right alignment, or non-aligned with at least 1 + previous gift bestowed, makes this one viable */ eligible[n++] = m; + } else { + /* non-aligned with no previous gifts; + if no candidates have been found yet, record + this one as a[nother] fallback possibility in + case all aligned candidates have been used up + (via wishing, naming, bones, random generation) */ + if (!n) eligible[altn++] = m; + /* [once a regular candidate is found, the list + is overwritten and `altn' becomes irrelevant] */ + } } + } + + /* resort to fallback list if main list was empty */ + if (!n) n = altn; - if (n) { /* found at least one candidate */ + if (n) { + /* found at least one candidate; pick one at random */ m = eligible[rn2(n)]; /* [0..n-1] */ a = &artilist[m]; /* make an appropriate object if necessary, then christen it */ -make_artif: if (by_align) otmp = mksobj((int)a->otyp, TRUE, FALSE); - otmp = oname(otmp, a->name); - otmp->oartifact = m; - artiexist[m] = TRUE; + if (by_align) otmp = mksobj((int)a->otyp, TRUE, FALSE); + + if (otmp) { + otmp = oname(otmp, a->name); + otmp->oartifact = m; + artiexist[m] = TRUE; + } } else { - /* nothing appropriate could be found; return the original object */ + /* nothing appropriate could be found; return original object */ if (by_align) otmp = 0; /* (there was no original object) */ } return otmp;