Make an artifact. If a specific alignment is specified, then an object of the appropriate alignment is created from scratch, or 0 is returned if none is available. (If at least one aligned artifact has already been given, then unaligned ones also become eligible for this.) If no alignment is given, then 'otmp' is converted into an artifact of matching type, or returned as-is if th
| 169 | by sacrificing, or 99 otherwise. |
| 170 | */ |
| 171 | struct obj * |
| 172 | mk_artifact( |
| 173 | struct obj *otmp, /* existing object; ignored and disposed of |
| 174 | * if alignment specified */ |
| 175 | aligntyp alignment, /* target alignment, or A_NONE */ |
| 176 | uchar max_giftvalue, /* cap on generated giftvalue */ |
| 177 | boolean adjust_spe) /* whether to add spe to situational artifacts */ |
| 178 | { |
| 179 | const struct artifact *a; |
| 180 | int m, n, altn; |
| 181 | boolean by_align = (alignment != A_NONE); |
| 182 | short o_typ = (by_align || !otmp) ? 0 : otmp->otyp; |
| 183 | boolean unique = !by_align && otmp && objects[o_typ].oc_unique; |
| 184 | short eligible[NROFARTIFACTS]; |
| 185 | xint16 skill_compatibility; |
| 186 | |
| 187 | n = altn = 0; /* no candidates found yet */ |
| 188 | eligible[0] = 0; /* lint suppression */ |
| 189 | /* gather eligible artifacts */ |
| 190 | for (m = 1, a = &artilist[m]; a->otyp; a++, m++) { |
| 191 | if (artiexist[m].exists) |
| 192 | continue; |
| 193 | if ((a->spfx & SPFX_NOGEN) || unique) |
| 194 | continue; |
| 195 | if (a->gift_value > max_giftvalue && !Role_if(a->role)) |
| 196 | continue; |
| 197 | |
| 198 | if (!by_align) { |
| 199 | /* looking for a particular type of item; not producing a |
| 200 | divine gift so we don't care about role's first choice */ |
| 201 | if (a->otyp == o_typ) |
| 202 | eligible[n++] = m; |
| 203 | continue; /* move on to next possibility */ |
| 204 | } |
| 205 | |
| 206 | /* we're looking for an alignment-specific item |
| 207 | suitable for hero's role+race */ |
| 208 | if ((a->alignment == alignment || a->alignment == A_NONE) |
| 209 | /* avoid enemies' equipment */ |
| 210 | && (a->race == NON_PM || !race_hostile(&mons[a->race]))) { |
| 211 | /* when a role-specific first choice is available, use it */ |
| 212 | if (Role_if(a->role)) { |
| 213 | /* make this be the only possibility in the list */ |
| 214 | eligible[0] = m; |
| 215 | n = 1; |
| 216 | break; /* skip all other candidates */ |
| 217 | } |
| 218 | |
| 219 | /* check if this is skill-compatible */ |
| 220 | skill_compatibility = P_SKILLED; |
| 221 | if (objects[a->otyp].oc_class == WEAPON_CLASS) { |
| 222 | schar skill = objects[a->otyp].oc_skill; |
| 223 | if (skill < 0) |
| 224 | skill_compatibility = P_MAX_SKILL(-skill); |
| 225 | else |
| 226 | skill_compatibility = P_MAX_SKILL(skill); |
| 227 | } |
| 228 |
no test coverage detected