/* Greg's random artifact generator (randart) */ #include #include #include #include #include "angband.h" #ifdef GJW_RANDART #define NAMES_FILE "names.txt" #define BUFLEN 1024 #define MAX_NAMES 512 #define MAX_TRIES 200 char *names[MAX_NAMES]; int nnames = 0; char *a_base; int init_names (void); int scramble (void); void choose_item (artifact_type *, u32b activates); void add_ability (artifact_type *); void do_pval (artifact_type *); void do_curse (artifact_type *); int artifact_power (const artifact_type *); char *my_strdup (const char *); #define abs(x) ((x) > 0 ? (x) : (-(x))) /* Hack -- if we're just in the standalone randart a_info generator, then we can't use msg_format(). */ #ifdef STANDALONE_RANDART #include #define msg_format ra_msg_format void ra_msg_format (cptr fmt, ...) { va_list ap; va_start (ap, fmt); vfprintf (stderr, fmt, ap); fprintf (stderr, "\n"); va_end (ap); } #endif int do_randart (u32b randart_seed) { int rc; /* Prepare to use the Angband "simple" RNG. We want this to follow the precedents set by the town layout and object flavor code. */ Rand_value = randart_seed; Rand_quick = TRUE; msg_format ("Reading new artifact names..."); if ((rc = init_names()) != 0) return rc; msg_format ("Scrambling artifacts..."); if ((rc = scramble()) != 0) return rc; /* When done, resume use of the Angband "complex" RNG. Right now this does nothing, but later it will be important! */ Rand_quick = FALSE; return 0; } /* Read our list of usable names from an external file. */ int init_names (void) { FILE *f; char buf [BUFLEN]; path_build (buf, BUFLEN, ANGBAND_DIR_FILE, NAMES_FILE); if ((f = fopen (buf, "r")) == NULL) { msg_format ("could not open '" NAMES_FILE "'\n"); return 1; } while (nnames < MAX_NAMES && fgets (buf, BUFLEN, f) != NULL) { int i = strlen (buf) - 1; if (buf[i] == '\n') buf[i] = '\0'; names[nnames] = my_strdup (buf); if (names[nnames] == NULL) { msg_format ("memory allocation error\n"); return 2; } nnames++; } if (nnames == MAX_NAMES) msg_format ("(using the first %d names) ", MAX_NAMES); fclose (f); if (nnames < MAX_A_IDX) { msg_format ("Not enough names!"); return 3; } return 0; } /* Note the two special cases (Grond, Morgoth). Note also that if an artifact has an activation, it must be preserved by artifact number, since activations are hard-coded into the game. */ int scramble (void) { int i; size_t name_size; char *a_next; /* Mix up the names. */ for (i = 0; i < nnames; i++) { int j = rand_int (nnames); if (i != j) { char *tmp = names[i]; names[i] = names[j]; names[j] = tmp; } } /* Special cases -- keep these three names separate. */ free (names [ART_POWER - 1]); free (names [ART_GROND - 1]); free (names [ART_MORGOTH - 1]); if ((names [ART_POWER - 1] = my_strdup ("of Power (The One Ring)")) == NULL) { msg_format ("Memory allocation error"); return 1; } if ((names [ART_GROND - 1] = my_strdup ("'Grond'")) == NULL) { msg_format ("Memory allocation error"); return 1; } if ((names [ART_MORGOTH - 1] = my_strdup ("of Morgoth")) == NULL) { msg_format ("Memory allocation error"); return 1; } /* Convert our names array into an a_name structure for later use. */ name_size = 0; for (i = 1; i < MAX_A_IDX; i++) { name_size += strlen (names[i-1]) + 1; } if ((a_base = malloc (name_size)) == NULL) { msg_format ("Memory allocation error"); return 1; } a_next = a_base; for (i = 1; i < MAX_A_IDX; i++) { strcpy (a_next, names[i-1]); if (a_info[i].tval > 0) /* skip unused! */ a_info[i].name = a_next - a_base; a_next += strlen (names[i-1]) + 1; } a_name = a_base; /* Generate all the artifacts. */ for (i = 1; i < MAX_A_IDX; i++) { artifact_type *a_ptr = &a_info[i]; u32b activates = a_ptr->flags3 & TR3_ACTIVATE; int power; int tries; /* a_ptr->name = names[i] - names[0]; */ /* Special cases -- don't randomize these! */ if (i == ART_POWER || i == ART_GROND || i == ART_MORGOTH) continue; /* Skip unused artifacts, too! */ if (a_ptr->tval == 0) continue; if (i >= ART_MIN_NORMAL) { /* Normal artifact - choose a random base item type. */ choose_item (a_ptr, activates); } else { /* Special artifact (light source, ring, or amulet) */ /* Clear the following fields; leave the rest alone. */ a_ptr->pval = 0; a_ptr->to_h = a_ptr->to_d = a_ptr->to_a = 0; a_ptr->flags1 = a_ptr->flags2 = a_ptr->flags3 = 0; } /* Use the level/rarity rating from the "original" artifact, and select a random set of abilities which roughly matches the original's in terms of overall power/usefulness. */ power = a_ptr->level + a_ptr->rarity; for (tries = 0; tries < MAX_TRIES; tries++) { artifact_type atmp; int ap; /* Copy artifact info temporarily. */ atmp = *a_ptr; add_ability (&atmp); ap = artifact_power (&atmp); if (ap > (power * 11) / 10 + 1) continue; /* too powerful */ /* Keep this ability -- copy it back. */ *a_ptr = atmp; if (ap >= (power * 9) / 10) /* just right */ { a_ptr->cost = ap * (s32b)1000; if (a_ptr->flags3 & TR3_CURSED) a_ptr->cost -= 10000; if (a_ptr->flags3 & TR3_HEAVY_CURSE) a_ptr->cost -= 20000; if (a_ptr->flags3 & TR3_PERMA_CURSE) a_ptr->cost -= 40000; if (a_ptr->cost < 0) a_ptr->cost = 0; break; } } if (activates) a_ptr->flags3 |= TR3_ACTIVATE; if (i < ART_MIN_NORMAL) a_ptr->flags3 |= TR3_INSTA_ART; } return 0; } /* Randomly select a base item type (tval,sval). Assign the various fields corresponding to that choice. */ void choose_item (artifact_type *a_ptr, u32b activates) { int tval, sval, k_idx; object_kind *k_ptr; int r; r = rand_int (100); if (r < 5) { tval = TV_BOW; r = rand_int (6); if (r < 1) sval = SV_SLING; else if (r < 2) sval = SV_SHORT_BOW; else if (r < 4) sval = SV_LONG_BOW; else if (r < 5) sval = SV_LIGHT_XBOW; else sval = SV_HEAVY_XBOW; } else if (r < 10) { tval = TV_DIGGING; r = rand_int (6); if (r < 1) sval = SV_SHOVEL; else if (r < 2) sval = SV_GNOMISH_SHOVEL; else if (r < 3) sval = SV_DWARVEN_SHOVEL; else if (r < 4) sval = SV_PICK; else if (r < 5) sval = SV_ORCISH_PICK; else sval = SV_DWARVEN_PICK; } else if (r < 20) { tval = TV_HAFTED; r = rand_int (21); if (r < 2) sval = SV_WHIP; else if (r < 4) sval = SV_QUARTERSTAFF; else if (r < 6) sval = SV_MACE; else if (r < 8) sval = SV_BALL_AND_CHAIN; else if (r < 10) sval = SV_WAR_HAMMER; else if (r < 12) sval = SV_LUCERN_HAMMER; else if (r < 14) sval = SV_MORNING_STAR; else if (r < 16) sval = SV_FLAIL; else if (r < 18) sval = SV_LEAD_FILLED_MACE; else if (r < 20) sval = SV_TWO_HANDED_FLAIL; else sval = SV_MACE_OF_DISRUPTION; } else if (r < 35) { tval = TV_SWORD; r = rand_int (33); if (r < 1) sval = SV_BROKEN_DAGGER; else if (r < 2) sval = SV_BROKEN_SWORD; else if (r < 4) sval = SV_DAGGER; else if (r < 6) sval = SV_MAIN_GAUCHE; else if (r < 8) sval = SV_RAPIER; else if (r < 10) sval = SV_SMALL_SWORD; else if (r < 12) sval = SV_SHORT_SWORD; else if (r < 14) sval = SV_SABRE; else if (r < 16) sval = SV_CUTLASS; else if (r < 18) sval = SV_TULWAR; else if (r < 20) sval = SV_BROAD_SWORD; else if (r < 22) sval = SV_LONG_SWORD; else if (r < 24) sval = SV_SCIMITAR; else if (r < 26) sval = SV_KATANA; else if (r < 28) sval = SV_BASTARD_SWORD; else if (r < 30) sval = SV_TWO_HANDED_SWORD; else if (r < 32) sval = SV_EXECUTIONERS_SWORD; else sval = SV_BLADE_OF_CHAOS; } else if (r < 45) { tval = TV_POLEARM; r = rand_int (27); if (r < 2) sval = SV_SPEAR; else if (r < 4) sval = SV_AWL_PIKE; else if (r < 6) sval = SV_TRIDENT; else if (r < 8) sval = SV_PIKE; else if (r < 10) sval = SV_BEAKED_AXE; else if (r < 12) sval = SV_BROAD_AXE; else if (r < 14) sval = SV_GLAIVE; else if (r < 16) sval = SV_HALBERD; else if (r < 18) sval = SV_SCYTHE; else if (r < 20) sval = SV_LANCE; else if (r < 22) sval = SV_BATTLE_AXE; else if (r < 24) sval = SV_GREAT_AXE; else if (r < 26) sval = SV_LOCHABER_AXE; else sval = SV_SCYTHE_OF_SLICING; } else if (r < 55) { tval = TV_SOFT_ARMOR; r = rand_int (13); if (r < 1) sval = SV_FILTHY_RAG; else if (r < 3) sval = SV_ROBE; else if (r < 5) sval = SV_SOFT_LEATHER_ARMOR; else if (r < 7) sval = SV_SOFT_STUDDED_LEATHER; else if (r < 9) sval = SV_HARD_LEATHER_ARMOR; else if (r < 11) sval = SV_HARD_STUDDED_LEATHER; else sval = SV_LEATHER_SCALE_MAIL; } else if (r < 70) { tval = TV_HARD_ARMOR; r = rand_int (24); if (r < 1) sval = SV_RUSTY_CHAIN_MAIL; else if (r < 3) sval = SV_METAL_SCALE_MAIL; else if (r < 5) sval = SV_CHAIN_MAIL; else if (r < 7) sval = SV_AUGMENTED_CHAIN_MAIL; else if (r < 9) sval = SV_DOUBLE_CHAIN_MAIL; else if (r < 11) sval = SV_BAR_CHAIN_MAIL; else if (r < 13) sval = SV_METAL_BRIGANDINE_ARMOUR; else if (r < 15) sval = SV_PARTIAL_PLATE_ARMOUR; else if (r < 17) sval = SV_METAL_LAMELLAR_ARMOUR; else if (r < 19) sval = SV_FULL_PLATE_ARMOUR; else if (r < 21) sval = SV_RIBBED_PLATE_ARMOUR; else if (r < 22) sval = SV_MITHRIL_CHAIN_MAIL; else if (r < 23) sval = SV_MITHRIL_PLATE_MAIL; else sval = SV_ADAMANTITE_PLATE_MAIL; } else if (r < 75) { tval = TV_BOOTS; r = rand_int (3); if (r < 1) sval = SV_PAIR_OF_SOFT_LEATHER_BOOTS; else if (r < 2) sval = SV_PAIR_OF_HARD_LEATHER_BOOTS; else sval = SV_PAIR_OF_METAL_SHOD_BOOTS; } else if (r < 80) { tval = TV_GLOVES; r = rand_int (4); if (r < 2) sval = SV_SET_OF_LEATHER_GLOVES; else if (r < 3) sval = SV_SET_OF_GAUNTLETS; else sval = SV_SET_OF_CESTI; } else if (r < 85) { tval = TV_HELM; r = rand_int (4); if (r < 1) sval = SV_HARD_LEATHER_CAP; else if (r < 2) sval = SV_METAL_CAP; else if (r < 3) sval = SV_IRON_HELM; else sval = SV_STEEL_HELM; } else if (r < 90) { tval = TV_CROWN; r = rand_int (3); if (r < 1) sval = SV_IRON_CROWN; else if (r < 2) sval = SV_GOLDEN_CROWN; else sval = SV_JEWELED_CROWN; } else if (r < 95) { tval = TV_SHIELD; r = rand_int (4); if (r < 1) sval = SV_SMALL_LEATHER_SHIELD; else if (r < 2) sval = SV_SMALL_METAL_SHIELD; else if (r < 3) sval = SV_LARGE_LEATHER_SHIELD; else sval = SV_LARGE_METAL_SHIELD; } else { tval = TV_CLOAK; r = rand_int (3); if (r < 2) sval = SV_CLOAK; else sval = SV_SHADOW_CLOAK; } k_idx = lookup_kind (tval, sval); k_ptr = &k_info[k_idx]; a_ptr->tval = k_ptr->tval; a_ptr->sval = k_ptr->sval; a_ptr->pval = k_ptr->pval; a_ptr->to_h = k_ptr->to_h; a_ptr->to_d = k_ptr->to_d; a_ptr->to_a = k_ptr->to_a; a_ptr->ac = k_ptr->ac; a_ptr->dd = k_ptr->dd; a_ptr->ds = k_ptr->ds; a_ptr->weight = k_ptr->weight; a_ptr->flags1 = k_ptr->flags1; a_ptr->flags2 = k_ptr->flags2; a_ptr->flags3 = k_ptr->flags3; a_ptr->flags3 &= ~(TR3_IGNORE_ACID | TR3_IGNORE_ELEC | TR3_IGNORE_FIRE | TR3_IGNORE_COLD); switch (a_ptr->tval) { case TV_BOW: case TV_DIGGING: case TV_HAFTED: case TV_SWORD: case TV_POLEARM: a_ptr->to_h += a_ptr->level / 10 + rand_int (4) + rand_int (4); a_ptr->to_d += a_ptr->level / 20 + rand_int (4) + rand_int ((a_ptr->dd * a_ptr->ds) / 2 + 1); break; case TV_BOOTS: case TV_GLOVES: case TV_HELM: case TV_CROWN: case TV_SHIELD: case TV_CLOAK: case TV_SOFT_ARMOR: case TV_HARD_ARMOR: a_ptr->to_a += a_ptr->ac / 3 + rand_int (8); break; } } /* Randomly select an extra ability to be added to the artifact in question. This function is way too large. */ void add_ability (artifact_type *a_ptr) { int r; r = rand_int (10); if (r < 4) /* Pick something dependent on item type. */ { r = rand_int (100); switch (a_ptr->tval) { case TV_BOW: { if (r < 15) a_ptr->flags3 |= TR3_XTRA_SHOTS; else if (r < 35) a_ptr->flags3 |= TR3_XTRA_MIGHT; else if (r < 65) a_ptr->to_h += 2 + rand_int (2); else a_ptr->to_d += 2 + rand_int (3); break; } case TV_DIGGING: case TV_HAFTED: case TV_POLEARM: case TV_SWORD: { if (r < 3) a_ptr->flags1 |= TR1_IMPACT; else if (r < 7) { a_ptr->flags1 |= TR1_BRAND_ACID; if (rand_int (2)) a_ptr->flags2 |= TR2_RES_ACID; } else if (r < 11) { a_ptr->flags1 |= TR1_BRAND_ELEC; if (rand_int (2)) a_ptr->flags2 |= TR2_RES_ELEC; } else if (r < 17) { a_ptr->flags1 |= TR1_BRAND_FIRE; if (rand_int (2)) a_ptr->flags2 |= TR2_RES_FIRE; } else if (r < 22) { a_ptr->flags1 |= TR1_BRAND_COLD; if (rand_int (2)) a_ptr->flags2 |= TR2_RES_COLD; } else if (r < 27) { if (a_ptr->dd < 9) a_ptr->dd++; } else if (r < 30) a_ptr->flags1 |= TR1_KILL_DRAGON; else if (r < 33) { if (a_ptr->tval == TV_SWORD || a_ptr->tval == TV_POLEARM) a_ptr->flags3 |= TR3_BLESSED; break; } else if (r < 35) a_ptr->flags1 |= TR1_SLAY_DRAGON; else if (r < 40) a_ptr->flags1 |= TR1_SLAY_EVIL; else if (r < 44) a_ptr->flags1 |= TR1_SLAY_ANIMAL; else if (r < 49) a_ptr->flags1 |= TR1_SLAY_UNDEAD; else if (r < 54) a_ptr->flags1 |= TR1_SLAY_DEMON; else if (r < 59) a_ptr->flags1 |= TR1_SLAY_ORC; else if (r < 63) a_ptr->flags1 |= TR1_SLAY_TROLL; else if (r < 67) a_ptr->flags1 |= TR1_SLAY_GIANT; else if (r < 70) a_ptr->flags3 |= TR3_SEE_INVIS; else if (r < 75) { if (a_ptr->pval < 0) break; a_ptr->flags1 |= TR1_BLOWS; do_pval (a_ptr); } else if (r < 88) { a_ptr->to_d += 3 + rand_int (3); a_ptr->to_h += 3 + rand_int (3); } else if (r < 92) a_ptr->to_a += 3 + rand_int (3); else if (r < 98) a_ptr->weight = (a_ptr->weight * 9) / 10; else if (a_ptr->tval != TV_DIGGING) { a_ptr->flags1 |= TR1_TUNNEL; do_pval (a_ptr); } break; } case TV_BOOTS: { if (r < 10) a_ptr->flags3 |= TR3_FEATHER; else if (r < 50) a_ptr->to_a += 2 + rand_int (4); else if (r < 80) { a_ptr->flags1 |= TR1_STEALTH; do_pval (a_ptr); } else if (r < 90) { a_ptr->flags1 |= TR1_SPEED; if (a_ptr->pval < 0) break; if (a_ptr->pval == 0) a_ptr->pval = 3 + rand_int (3); else if (rand_int (2) == 0) a_ptr->pval++; } else a_ptr->weight = (a_ptr->weight * 9) / 10; break; } case TV_GLOVES: { if (r < 25) a_ptr->flags2 |= TR2_FREE_ACT; else if (r < 50) { a_ptr->flags1 |= TR1_DEX; do_pval (a_ptr); } else if (r < 75) a_ptr->to_a += 3 + rand_int (3); else { a_ptr->to_h += 2 + rand_int (3); a_ptr->to_d += 2 + rand_int (3); a_ptr->flags3 |= TR3_SHOW_MODS; } break; } case TV_HELM: case TV_CROWN: { if (r < 20) a_ptr->flags2 |= TR2_RES_BLIND; else if (r < 40) a_ptr->flags3 |= TR3_TELEPATHY; else if (r < 70) a_ptr->flags3 |= TR3_SEE_INVIS; else a_ptr->to_a += 3 + rand_int (3); break; } case TV_SHIELD: { if (r < 20) a_ptr->flags2 |= TR2_RES_ACID; else if (r < 40) a_ptr->flags2 |= TR2_RES_ELEC; else if (r < 60) a_ptr->flags2 |= TR2_RES_FIRE; else if (r < 80) a_ptr->flags2 |= TR2_RES_COLD; else a_ptr->to_a += 3 + rand_int (3); break; } case TV_CLOAK: { if (r < 50) { a_ptr->flags1 |= TR1_STEALTH; do_pval (a_ptr); } else a_ptr->to_a += 3 + rand_int (3); break; } case TV_SOFT_ARMOR: case TV_HARD_ARMOR: { if (r < 10) { a_ptr->flags1 |= TR1_STEALTH; do_pval (a_ptr); } else if (r < 20) a_ptr->flags2 |= TR2_HOLD_LIFE; else if (r < 30) a_ptr->flags2 |= TR2_RES_ACID; else if (r < 40) a_ptr->flags2 |= TR2_RES_ELEC; else if (r < 50) a_ptr->flags2 |= TR2_RES_FIRE; else if (r < 60) a_ptr->flags2 |= TR2_RES_COLD; else if (r < 70) a_ptr->weight = (a_ptr->weight * 9) / 10; else a_ptr->to_a += 3 + rand_int (3); break; } } } else /* Pick something universally useful. */ { r = rand_int (48); switch (r) { case 0: a_ptr->flags1 |= TR1_STR; do_pval (a_ptr); if (rand_int (3) == 0) a_ptr->flags2 |= TR2_SUST_STR; break; case 1: a_ptr->flags1 |= TR1_INT; do_pval (a_ptr); if (rand_int (3) == 0) a_ptr->flags2 |= TR2_SUST_INT; break; case 2: a_ptr->flags1 |= TR1_WIS; do_pval (a_ptr); if (rand_int (3) == 0) a_ptr->flags2 |= TR2_SUST_WIS; break; case 3: a_ptr->flags1 |= TR1_DEX; do_pval (a_ptr); if (rand_int (3) == 0) a_ptr->flags2 |= TR2_SUST_DEX; break; case 4: a_ptr->flags1 |= TR1_CON; do_pval (a_ptr); if (rand_int (3) == 0) a_ptr->flags2 |= TR2_SUST_CON; break; case 5: a_ptr->flags1 |= TR1_CHR; do_pval (a_ptr); if (rand_int (3) == 0) a_ptr->flags2 |= TR2_SUST_CHR; break; case 6: a_ptr->flags1 |= TR1_STEALTH; do_pval (a_ptr); break; case 7: a_ptr->flags1 |= TR1_SEARCH; do_pval (a_ptr); break; case 8: a_ptr->flags1 |= TR1_INFRA; do_pval (a_ptr); break; case 9: a_ptr->flags1 |= TR1_SPEED; if (a_ptr->pval == 0) a_ptr->pval = 3 + rand_int (3); else do_pval (a_ptr); break; case 10: a_ptr->flags2 |= TR2_SUST_STR; break; case 11: a_ptr->flags2 |= TR2_SUST_INT; break; case 12: a_ptr->flags2 |= TR2_SUST_WIS; break; case 13: a_ptr->flags2 |= TR2_SUST_DEX; break; case 14: a_ptr->flags2 |= TR2_SUST_CON; break; case 15: a_ptr->flags2 |= TR2_SUST_CHR; break; case 16: { if (rand_int (2) == 0) a_ptr->flags2 |= TR2_IM_ACID; break; } case 17: { if (rand_int (2) == 0) a_ptr->flags2 |= TR2_IM_ELEC; break; } case 18: { if (rand_int (3) == 0) a_ptr->flags2 |= TR2_IM_FIRE; break; } case 19: { if (rand_int (2) == 0) a_ptr->flags2 |= TR2_IM_COLD; break; } case 20: a_ptr->flags2 |= TR2_FREE_ACT; break; case 21: a_ptr->flags2 |= TR2_HOLD_LIFE; break; case 22: a_ptr->flags2 |= TR2_RES_ACID; break; case 23: a_ptr->flags2 |= TR2_RES_ELEC; break; case 24: a_ptr->flags2 |= TR2_RES_FIRE; break; case 25: a_ptr->flags2 |= TR2_RES_COLD; break; case 26: a_ptr->flags2 |= TR2_RES_POIS; break; case 27: a_ptr->flags2 |= TR2_RES_LITE; break; case 28: a_ptr->flags2 |= TR2_RES_DARK; break; case 29: a_ptr->flags2 |= TR2_RES_BLIND; break; case 30: a_ptr->flags2 |= TR2_RES_CONF; break; case 31: a_ptr->flags2 |= TR2_RES_SOUND; break; case 32: a_ptr->flags2 |= TR2_RES_SHARDS; break; case 33: a_ptr->flags2 |= TR2_RES_NETHER; break; case 34: a_ptr->flags2 |= TR2_RES_NEXUS; break; case 35: a_ptr->flags2 |= TR2_RES_CHAOS; break; case 36: a_ptr->flags2 |= TR2_RES_DISEN; break; case 37: a_ptr->flags3 |= TR3_FEATHER; break; case 38: a_ptr->flags3 |= TR3_LITE; break; case 39: a_ptr->flags3 |= TR3_SEE_INVIS; break; case 40: a_ptr->flags3 |= TR3_TELEPATHY; break; case 41: a_ptr->flags3 |= TR3_SLOW_DIGEST; break; case 42: case 43: a_ptr->flags3 |= TR3_REGEN; break; case 44: if (rand_int (2) == 0) { a_ptr->flags3 |= TR3_DRAIN_EXP; do_curse (a_ptr); } break; case 45: a_ptr->flags3 |= TR3_TELEPORT; do_curse (a_ptr); break; case 46: case 47: a_ptr->flags3 |= TR3_AGGRAVATE; if (rand_int (2) == 0) do_curse (a_ptr); break; } } /* Now remove contradictory powers. */ if (a_ptr->pval > 0 && a_ptr->flags3 & TR3_AGGRAVATE) a_ptr->flags1 &= ~(TR1_STEALTH); if (a_ptr->flags2 & TR2_IM_ACID) a_ptr->flags2 &= ~(TR2_RES_ACID); if (a_ptr->flags2 & TR2_IM_ELEC) a_ptr->flags2 &= ~(TR2_RES_ELEC); if (a_ptr->flags2 & TR2_IM_FIRE) a_ptr->flags2 &= ~(TR2_RES_FIRE); if (a_ptr->flags2 & TR2_IM_COLD) a_ptr->flags2 &= ~(TR2_RES_COLD); if (a_ptr->pval < 0) { if (a_ptr->flags1 & TR1_STR) a_ptr->flags2 &= ~(TR2_SUST_STR); if (a_ptr->flags1 & TR1_INT) a_ptr->flags2 &= ~(TR2_SUST_INT); if (a_ptr->flags1 & TR1_WIS) a_ptr->flags2 &= ~(TR2_SUST_WIS); if (a_ptr->flags1 & TR1_DEX) a_ptr->flags2 &= ~(TR2_SUST_DEX); if (a_ptr->flags1 & TR1_CON) a_ptr->flags2 &= ~(TR2_SUST_CON); if (a_ptr->flags1 & TR1_CHR) a_ptr->flags2 &= ~(TR2_SUST_CHR); } if (a_ptr->flags3 & TR3_CURSED) a_ptr->flags3 &= ~(TR3_BLESSED); if (a_ptr->flags1 & TR1_KILL_DRAGON) a_ptr->flags1 &= ~(TR1_SLAY_DRAGON); } /* We've just added an ability which uses the pval bonus. Make sure it's not zero. If it's currently negative, leave it negative (heh heh). */ void do_pval (artifact_type *a_ptr) { if (a_ptr->pval == 0) a_ptr->pval = 1; else if (a_ptr->pval < 0) { if (rand_int (2)) a_ptr->pval--; } else if (rand_int (3)) a_ptr->pval++; } /* Make it bad, or if it's already bad, make it worse! */ void do_curse (artifact_type *a_ptr) { if ((a_ptr->pval > 0) && (rand_int (2) == 0)) a_ptr->pval = -a_ptr->pval; if ((a_ptr->to_a > 0) && (rand_int (2) == 0)) a_ptr->to_a = -a_ptr->to_a; if ((a_ptr->to_h > 0) && (rand_int (2) == 0)) a_ptr->to_h = -a_ptr->to_h; if ((a_ptr->to_d > 0) && (rand_int (4) == 0)) a_ptr->to_d = -a_ptr->to_d; if (a_ptr->flags3 & TR3_HEAVY_CURSE) { if (rand_int (3) == 0) a_ptr->flags3 |= TR3_PERMA_CURSE; return; } if (a_ptr->flags3 & TR3_CURSED) { if (rand_int (2) == 0) a_ptr->flags3 |= TR3_HEAVY_CURSE; return; } a_ptr->flags3 |= TR3_CURSED; if (rand_int (4) == 0) a_ptr->flags3 |= TR3_HEAVY_CURSE; } /* Evaluate the artifact's overall power level. Perversely, curses and other bad things add to the artifact's "power" level, so that we'll actually have some bad (or mixed good/bad) artifacts. */ int artifact_power (const artifact_type *a_ptr) { int p = 0; s16b k_idx; object_kind *k_ptr; /* Start with the "power" of the base item's level. */ k_idx = lookup_kind (a_ptr->tval, a_ptr->sval); if (k_idx) { k_ptr = &k_info[k_idx]; p = k_ptr->level / 8; } /* Evaluate certain abilities based on type of object. */ switch (a_ptr->tval) { case TV_BOW: { int mult; p += a_ptr->to_d / 2; mult = a_ptr->sval % 10; /* yes, really */ if (a_ptr->flags3 & TR3_XTRA_MIGHT) mult++; p += mult * 2; if (a_ptr->flags3 & TR3_XTRA_SHOTS) p = (p * 3) / 2; p += (abs(a_ptr->to_h) + 3) / 4; if (a_ptr->weight < k_ptr->weight) p++; break; } case TV_DIGGING: case TV_HAFTED: case TV_POLEARM: case TV_SWORD: { p += (a_ptr->dd * a_ptr->ds) / 2; p += a_ptr->to_d / 3; if (a_ptr->to_d > 15) p += (a_ptr->to_d - 14) / 2; if (a_ptr->flags1 & TR1_SLAY_EVIL) p = (p * 3) / 2; if (a_ptr->flags1 & TR1_KILL_DRAGON) p = (p * 3) / 2; if (a_ptr->flags1 & TR1_SLAY_ANIMAL) p = (p * 4) / 3; if (a_ptr->flags1 & TR1_SLAY_UNDEAD) p = (p * 4) / 3; if (a_ptr->flags1 & TR1_SLAY_DRAGON) p = (p * 4) / 3; if (a_ptr->flags1 & TR1_SLAY_DEMON) p = (p * 5) / 4; if (a_ptr->flags1 & TR1_SLAY_TROLL) p = (p * 5) / 4; if (a_ptr->flags1 & TR1_SLAY_ORC) p = (p * 5) / 4; if (a_ptr->flags1 & TR1_SLAY_GIANT) p = (p * 6) / 5; if (a_ptr->flags1 & TR1_BRAND_ACID) p = p * 2; if (a_ptr->flags1 & TR1_BRAND_ELEC) p = (p * 3) / 2; if (a_ptr->flags1 & TR1_BRAND_FIRE) p = (p * 4) / 3; if (a_ptr->flags1 & TR1_BRAND_COLD) p = (p * 4) / 3; if (a_ptr->flags1 & TR1_BLOWS) { if (a_ptr->pval > 3) p += 20000; /* inhibit */ else if (a_ptr->pval > 0) p = (p * 4) / (4 - a_ptr->pval); } if (a_ptr->flags1 & TR1_IMPACT) p += 20; if ((a_ptr->flags1 & TR1_TUNNEL) && (a_ptr->tval != TV_DIGGING)) p += a_ptr->pval * 3; p += (abs(a_ptr->to_h) + 3) / 4; /* Remember, weight is in 0.1 lb. units. */ if (a_ptr->weight != k_ptr->weight) p += (k_ptr->weight - a_ptr->weight) / 20; break; } case TV_BOOTS: case TV_GLOVES: case TV_HELM: case TV_CROWN: case TV_SHIELD: case TV_CLOAK: case TV_SOFT_ARMOR: case TV_HARD_ARMOR: { p += (a_ptr->ac + 4) / 5; p += (a_ptr->to_h + 1) / 2; p += (a_ptr->to_d + 1) / 2; if (a_ptr->weight != k_ptr->weight) p += (k_ptr->weight - a_ptr->weight) / 30; break; } } /* Other abilities are evaluated independent of the object type. */ p += (a_ptr->to_a + 3) / 4; if (a_ptr->to_a > 20) p += (a_ptr->to_a - 19) / 2; if (a_ptr->to_a > 30) p += (a_ptr->to_a - 29) / 2; if (a_ptr->to_a > 40) p += 20000; /* inhibit */ if (a_ptr->flags1 & TR1_STR) p += a_ptr->pval * a_ptr->pval; if (a_ptr->flags1 & TR1_INT) p += a_ptr->pval * a_ptr->pval; if (a_ptr->flags1 & TR1_WIS) p += a_ptr->pval * a_ptr->pval; if (a_ptr->flags1 & TR1_DEX) p += a_ptr->pval * a_ptr->pval; if (a_ptr->flags1 & TR1_CON) p += a_ptr->pval * a_ptr->pval; if (a_ptr->flags1 & TR1_CHR) p += a_ptr->pval; if (a_ptr->flags1 & TR1_STEALTH) p += 2 * a_ptr->pval; if (a_ptr->flags1 & TR1_INFRA) p += a_ptr->pval / 2; if (a_ptr->flags1 & TR1_SPEED) p += (a_ptr->pval * 3) / 2; if (a_ptr->flags2 & TR2_SUST_STR) p += 6; if (a_ptr->flags2 & TR2_SUST_INT) p += 4; if (a_ptr->flags2 & TR2_SUST_WIS) p += 4; if (a_ptr->flags2 & TR2_SUST_DEX) p += 4; if (a_ptr->flags2 & TR2_SUST_CON) p += 4; if (a_ptr->flags2 & TR2_SUST_CHR) p += 1; if (a_ptr->flags2 & TR2_IM_ACID) p += 20; if (a_ptr->flags2 & TR2_IM_ELEC) p += 20; if (a_ptr->flags2 & TR2_IM_FIRE) p += 30; if (a_ptr->flags2 & TR2_IM_COLD) p += 20; if (a_ptr->flags2 & TR2_FREE_ACT) p += 8; if (a_ptr->flags2 & TR2_HOLD_LIFE) p += 10; if (a_ptr->flags2 & TR2_RES_ACID) p += 6; if (a_ptr->flags2 & TR2_RES_ELEC) p += 6; if (a_ptr->flags2 & TR2_RES_FIRE) p += 6; if (a_ptr->flags2 & TR2_RES_COLD) p += 6; if (a_ptr->flags2 & TR2_RES_POIS) p += 12; if (a_ptr->flags2 & TR2_RES_LITE) p += 8; if (a_ptr->flags2 & TR2_RES_DARK) p += 10; if (a_ptr->flags2 & TR2_RES_BLIND) p += 10; if (a_ptr->flags2 & TR2_RES_CONF) p += 8; if (a_ptr->flags2 & TR2_RES_SOUND) p += 10; if (a_ptr->flags2 & TR2_RES_SHARDS) p += 8; if (a_ptr->flags2 & TR2_RES_NETHER) p += 12; if (a_ptr->flags2 & TR2_RES_NEXUS) p += 10; if (a_ptr->flags2 & TR2_RES_CHAOS) p += 12; if (a_ptr->flags2 & TR2_RES_DISEN) p += 12; if (a_ptr->flags3 & TR3_FEATHER) p += 2; if (a_ptr->flags3 & TR3_LITE) p += 2; if (a_ptr->flags3 & TR3_SEE_INVIS) p += 8; if (a_ptr->flags3 & TR3_TELEPATHY) p += 20; if (a_ptr->flags3 & TR3_SLOW_DIGEST) p += 4; if (a_ptr->flags3 & TR3_REGEN) p += 8; if (a_ptr->flags3 & TR3_DRAIN_EXP) p += 20; /* note */ if (a_ptr->flags3 & TR3_TELEPORT) p += 12; /* note */ if (a_ptr->flags3 & TR3_AGGRAVATE) p += 8; /* note */ if (a_ptr->flags3 & TR3_BLESSED) p += 4; if (a_ptr->flags3 & TR3_CURSED) p += 2; /* note */ if (a_ptr->flags3 & TR3_HEAVY_CURSE) p += 6; /* note */ if (a_ptr->flags3 & TR3_PERMA_CURSE) p += 10; /* note */ return p; } char *my_strdup (const char *s) { char *t = malloc (strlen (s) + 1); if (t) strcpy (t, s); return t; } #endif /* GJW_RANDART */