]> granicus.if.org Git - nethack/commitdiff
first divine gift artifact (trunk only)
authornethack.rankin <nethack.rankin>
Mon, 7 Jul 2008 03:01:30 +0000 (03:01 +0000)
committernethack.rankin <nethack.rankin>
Mon, 7 Jul 2008 03:01:30 +0000 (03:01 +0000)
     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.

doc/fixes35.0
src/artifact.c

index 825b60573b2cb1518c0dfa406f8efe2d9b471d32..c910f95ea365eb8b2fd73452b5207bc1637cf46c 100644 (file)
@@ -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
index 2f492e04a4107785742a9f7c467edb09cf9a0e1f..25df6f46dd487ebdbcaa1b9fae3f3f1958e55008 100644 (file)
@@ -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;