/** * Collect all tvals in the big ignore_choice array */ static int ignore_collect_kind(int tval, ignore_choice **ch) { ignore_choice *choice; int num = 0; int i; /* Create the array, with entries both for aware and unaware ignore */ choice = mem_alloc(2 * z_info->k_max * sizeof *choice); for (i = 1; i < z_info->k_max; i++) { object_kind *k_ptr = &k_info[i]; /* Skip empty objects, unseen objects, and incorrect tvals */ if (!k_ptr->name || k_ptr->tval != tval) continue; if (!k_ptr->aware) { /* can unaware ignore anything */ choice[num].kind = k_ptr; choice[num++].aware = FALSE; } if ((k_ptr->everseen && !kf_has(k_ptr->kind_flags, KF_INSTA_ART)) || tval_is_money_k(k_ptr)) { /* Do not display the artifact base kinds in this list * aware ignore requires everseen * do not require awareness for aware ignore, so people can set * at game start */ choice[num].kind = k_ptr; choice[num++].aware = TRUE; } } if (num == 0) mem_free(choice); else *ch = choice; return num; }
/* * Display known objects */ void textui_browse_object_knowledge(const char *name, int row) { group_funcs kind_f = { TV_GOLD, FALSE, kind_name, o_cmp_tval, obj2gid, 0 }; member_funcs obj_f = { display_object, desc_obj_fake, o_xchar, o_xattr, o_xtra_prompt, o_xtra_act, 0 }; int *objects; int o_count = 0; int i; object_kind *k_ptr; objects = C_ZNEW(z_info->k_max, int); for (i = 0; i < z_info->k_max; i++) { k_ptr = &k_info[i]; /* It's in the list if we've ever seen it, or it has a flavour, and * either it's not one of the special artifacts, or if it is, we're not * aware of it yet. This way the flavour appears in the list until it * is found. */ if ((k_ptr->everseen || k_ptr->flavor || OPT(cheat_xtra)) && (!kf_has(k_ptr->flags_kind, KF_INSTA_ART) || !artifact_is_known(get_artifact_from_kind(k_ptr)))) { int c = obj_group_order[k_info[i].tval]; if (c >= 0) objects[o_count++] = i; } } display_knowledge("known objects", objects, o_count, kind_f, obj_f, "Squelch Inscribed Sym"); FREE(objects); }
/* * Display the objects in a group. */ static void display_object(int col, int row, bool cursor, int oid) { int k_idx = oid; object_kind *k_ptr = &k_info[k_idx]; const char *inscrip = get_autoinscription(oid); char o_name[80]; /* Choose a color */ bool aware = (!k_ptr->flavor || k_ptr->aware); byte attr = curs_attrs[(int) aware][(int) cursor]; /* Find graphics bits -- versions of the object_char and object_attr * defines */ bool use_flavour = (k_ptr->flavor) && !(aware && k_ptr->tval == TV_SCROLL); byte a = use_flavour ? flavor_info[k_ptr->flavor].x_attr : k_ptr->x_attr; wchar_t c = use_flavour ? flavor_info[k_ptr->flavor].x_char : k_ptr->x_char; /* Display known artifacts differently */ if (kf_has(k_ptr->flags_kind, KF_INSTA_ART) && artifact_is_known(get_artifact_from_kind(k_ptr))) { get_artifact_display_name(o_name, sizeof(o_name), get_artifact_from_kind(k_ptr)); } else { object_kind_name(o_name, sizeof(o_name), k_idx, OPT(cheat_know)); } /* If the type is "tried", display that */ if (k_ptr->tried && !aware) my_strcat(o_name, " {tried}", sizeof(o_name)); /* Display the name */ c_prt(attr, o_name, row, col); /* Object recall window */ if (cursor) { character_icky--; character_icky--; p_ptr->object_kind_idx = k_idx; p_ptr->redraw |= PR_OBJECT; handle_stuff(p_ptr); character_icky++; character_icky++; } /* Show autoinscription if around */ if (aware && inscrip) c_put_str(TERM_YELLOW, inscrip, row, 55); /* Hack - don't use if double tile */ if ((tile_width > 1) || (tile_height > 1)) return; /* Display symbol */ big_pad(76, row, a, c); }
/** * Attempt to change an object into an artifact. If the object is already * set to be an artifact, use that, or otherwise use a suitable randomly- * selected artifact. * * This routine should only be called by "apply_magic()" * * Note -- see "make_artifact_special()" and "apply_magic()" */ static bool make_artifact(struct object *obj) { int i; bool art_ok = true; /* Make sure birth no artifacts isn't set */ if (OPT(birth_no_artifacts)) art_ok = false; /* Special handling of quest artifacts */ if (kf_has(obj->kind->kind_flags, KF_QUEST_ART)) art_ok = true; if (!art_ok) return (false); /* No artifacts in the town */ if (!player->depth) return (false); /* Paranoia -- no "plural" artifacts */ if (obj->number != 1) return (false); /* Check the artifact list (skip the "specials") */ for (i = 0; !obj->artifact && i < z_info->a_max; i++) { struct artifact *art = &a_info[i]; struct object_kind *kind = lookup_kind(art->tval, art->sval); /* Skip "empty" items */ if (!art->name) continue; /* Make sure the kind was found */ if (!kind) continue; /* Skip special artifacts */ if (kf_has(kind->kind_flags, KF_INSTA_ART)) continue; /* Cannot make an artifact twice */ if (art->created) continue; /* Must have the correct fields */ if (art->tval != obj->tval) continue; if (art->sval != obj->sval) continue; /* XXX XXX Enforce minimum "depth" (loosely) */ if (art->alloc_min > player->depth) { /* Get the "out-of-depth factor" */ int d = (art->alloc_min - player->depth) * 2; /* Roll for out-of-depth creation */ if (randint0(d) != 0) continue; } /* Enforce maximum depth (strictly) */ if (art->alloc_max < player->depth) continue; /* We must make the "rarity roll" */ if (randint1(100) > art->alloc_prob) continue; /* Mark the item as an artifact */ obj->artifact = art; } if (obj->artifact) { copy_artifact_data(obj, obj->artifact); obj->artifact->created = true; return true; } return false; }
/** * Mega-Hack -- Attempt to create one of the "Special Objects". * * We are only called from "make_object()" * * Note -- see "make_artifact()" and "apply_magic()". * * We *prefer* to create the special artifacts in order, but this is * normally outweighed by the "rarity" rolls for those artifacts. */ static struct object *make_artifact_special(int level) { int i; struct object *new_obj; /* No artifacts, do nothing */ if (OPT(birth_no_artifacts)) return NULL; /* No artifacts in the town */ if (!player->depth) return NULL; /* Check the special artifacts */ for (i = 0; i < z_info->a_max; ++i) { struct artifact *art = &a_info[i]; struct object_kind *kind = lookup_kind(art->tval, art->sval); /* Skip "empty" artifacts */ if (!art->name) continue; /* Make sure the kind was found */ if (!kind) continue; /* Skip non-special artifacts */ if (!kf_has(kind->kind_flags, KF_INSTA_ART)) continue; /* Cannot make an artifact twice */ if (art->created) continue; /* Enforce minimum "depth" (loosely) */ if (art->alloc_min > player->depth) { /* Get the "out-of-depth factor" */ int d = (art->alloc_min - player->depth) * 2; /* Roll for out-of-depth creation */ if (randint0(d) != 0) continue; } /* Enforce maximum depth (strictly) */ if (art->alloc_max < player->depth) continue; /* Artifact "rarity roll" */ if (randint1(100) > art->alloc_prob) continue; /* Enforce minimum "object" level (loosely) */ if (kind->level > level) { /* Get the "out-of-depth factor" */ int d = (kind->level - level) * 5; /* Roll for out-of-depth creation */ if (randint0(d) != 0) continue; } /* Assign the template */ new_obj = object_new(); object_prep(new_obj, kind, art->alloc_min, RANDOMISE); /* Mark the item as an artifact */ new_obj->artifact = art; /* Copy across all the data from the artifact struct */ copy_artifact_data(new_obj, art); /* Mark the artifact as "created" */ art->created = true; /* Success */ return new_obj; } /* Failure */ return NULL; }
/** * Apply generation magic to an ego-item. */ void ego_apply_magic(struct object *obj, int level) { int i, x, resist = 0, pick = 0; bitflag newf[OF_SIZE]; /* Resist or power? */ if (kf_has(obj->ego->kind_flags, KF_RAND_RES_POWER)) pick = randint1(3); /* Extra powers */ if (kf_has(obj->ego->kind_flags, KF_RAND_SUSTAIN)) { create_mask(newf, false, OFT_SUST, OFT_MAX); of_on(obj->flags, get_new_attr(obj->flags, newf)); } else if (kf_has(obj->ego->kind_flags, KF_RAND_POWER) || (pick == 1)) { create_mask(newf, false, OFT_PROT, OFT_MISC, OFT_MAX); of_on(obj->flags, get_new_attr(obj->flags, newf)); } else if (kf_has(obj->ego->kind_flags, KF_RAND_BASE_RES) || (pick > 1)) { /* Get a base resist if available, mark it as random */ if (random_base_resist(obj, &resist)) { obj->el_info[resist].res_level = 1; obj->el_info[resist].flags |= EL_INFO_RANDOM; } } else if (kf_has(obj->ego->kind_flags, KF_RAND_HI_RES)) { /* Get a high resist if available, mark it as random */ if (random_high_resist(obj, &resist)) { obj->el_info[resist].res_level = 1; obj->el_info[resist].flags |= EL_INFO_RANDOM; } } /* Apply extra obj->ego bonuses */ obj->to_h += randcalc(obj->ego->to_h, level, RANDOMISE); obj->to_d += randcalc(obj->ego->to_d, level, RANDOMISE); obj->to_a += randcalc(obj->ego->to_a, level, RANDOMISE); /* Apply modifiers */ for (i = 0; i < OBJ_MOD_MAX; i++) { x = randcalc(obj->ego->modifiers[i], level, RANDOMISE); obj->modifiers[i] += x; } /* Apply flags */ of_union(obj->flags, obj->ego->flags); of_diff(obj->flags, obj->ego->flags_off); /* Add slays and brands */ copy_slay(&obj->slays, obj->ego->slays); copy_brand(&obj->brands, obj->ego->brands); /* Add resists */ for (i = 0; i < ELEM_MAX; i++) { /* Take the larger of ego and base object resist levels */ obj->el_info[i].res_level = MAX(obj->ego->el_info[i].res_level, obj->el_info[i].res_level); /* Union of flags so as to know when ignoring is notable */ obj->el_info[i].flags |= obj->ego->el_info[i].flags; } /* Add effect (ego effect will trump object effect, when there are any) */ if (obj->ego->effect) { obj->effect = obj->ego->effect; obj->time = obj->ego->time; } return; }
/** * Apply slightly randomised percentage resistances -NRM- * Also add element proofing flags where appropriate */ void apply_resistances(object_type * o_ptr, int lev, bitflag *flags) { int i, res = 0; /* Get the ego type resists */ if (o_ptr->name2) { ego_item_type *e_ptr = &e_info[o_ptr->name2]; for (i = 0; i < MAX_P_RES; i++) { /* Get the resistance value */ if (e_ptr->percent_res[i] != RES_LEVEL_BASE) { res = o_ptr->percent_res[i] * e_ptr->percent_res[i] / 100; o_ptr->percent_res[i] = res; } } } /* Add extra resists */ /* Vulnerability */ if (kf_has(flags, KF_RAND_RES_NEG)) { int roll = 0; /* This gets done more often as we go deeper */ while (roll < 2) { /* Low resists more likely at low levels */ int k = randint0(128); bool low = (k < (128 - lev)); k = (low ? randint0(4) : randint0(10) + 4); o_ptr->percent_res[k] += 10 + randint0(5) + m_bonus(30, lev); roll = randint0(10 - (lev / 30)); } } /* Rings of Protection, etc */ if (kf_has(flags, KF_RAND_RES_SML)) { int roll = 0; /* This gets done more often as we go deeper */ while (roll < 2) { /* Low resists more likely at low levels */ int k = randint0(128); bool low = (k < (128 - lev)); k = (low ? randint0(4) : randint0(10) + 4); o_ptr->percent_res[k] -= 4 + randint0(8) + m_bonus(10, lev); /* Twice as many of these */ k = randint0(128); low = (k < (128 - lev)); k = (low ? randint0(4) : randint0(10) + 4); o_ptr->percent_res[k] -= 4 + randint0(8) + m_bonus(10, lev); /* Occasionally reverse one */ if (randint0(3) == 0) o_ptr->percent_res[k] = RES_LEVEL_MAX - o_ptr->percent_res[k]; roll = randint0(10 - (lev / 30)); } } /* Armour of Resistance etc */ if (kf_has(flags, KF_RAND_RES)) { int roll = 0; /* This gets done more often as we go deeper */ while (roll < 2) { /* Low resists more likely at low levels */ int k = randint0(128); bool low = (k < (128 - lev)); k = (low ? randint0(4) : randint0(10) + 4); o_ptr->percent_res[k] -= 20 + randint0(5) + m_bonus(20, lev); roll = randint0(10 - (lev / 30)); } } /* Former one high resist objects */ if (kf_has(flags, KF_RAND_RES_XTRA)) { int roll = 0; /* This gets done more often as we go deeper */ while (roll < 2) { /* Low resists less likely here */ int k = ((randint0(10) == 0) ? randint0(4) : randint0(10) + 4); o_ptr->percent_res[k] -= 30 + randint0(5) + m_bonus(20, lev); roll = randint0(10 - (lev / 30)); } } /* Randomise a bit */ for (i = 0; i < MAX_P_RES; i++) { res = 100 - o_ptr->percent_res[i]; /* Only randomise proper resistances */ if ((res > 0) && (res < 100)) { if (randint0(2) == 0) o_ptr->percent_res[i] -= randint0(res >> 2); else o_ptr->percent_res[i] += randint0(res >> 2); } /* Enforce bounds - no item gets better than 80% resistance */ if (o_ptr->percent_res[i] < RES_CAP_ITEM) o_ptr->percent_res[i] = RES_CAP_ITEM; if (o_ptr->percent_res[i] > RES_LEVEL_MAX) o_ptr->percent_res[i] = RES_LEVEL_MAX; }
/** * Attempt to change an object into an ego-item -MWK- * Better only called by apply_magic(). * The return value says if we picked a cursed item (if allowed) and is * passed on to a_m_aux1/2(). * If no legal ego item is found, this routine returns 0, resulting in * an unenchanted item. * * Modified for Oangband to specifically create cursed/non-cursed egos. * This is to keep the probabilities separate between cursed and * non-cursed ego types. */ static int make_ego_item(object_type * o_ptr, int power) { int i, j, level; int e_idx; long value, total; ego_item_type *e_ptr; alloc_entry *table = alloc_ego_table; /* Fail if object already is ego or artifact */ if (o_ptr->name1) return (FALSE); if (o_ptr->name2) return (FALSE); level = object_level; /* Boost level (like with object base types) */ if (level > 0) { /* Occasional "boost" */ if (randint0(GREAT_EGO) == 0) { /* The bizarre calculation again */ level = 1 + (level * MAX_DEPTH / randint1(MAX_DEPTH)); } } /* Reset total */ total = 0L; /* Process probabilities */ for (i = 0; i < alloc_ego_size; i++) { /* Default */ table[i].prob3 = 0; /* Objects are sorted by depth */ if (table[i].level > level) continue; /* Get the index */ e_idx = table[i].index; /* Get the actual kind */ e_ptr = &e_info[e_idx]; /* If we force good/great, don't create cursed */ if ((power > 0) && (!good_ego(e_ptr))) continue; /* If we force cursed, don't create good */ if ((power < 0) && good_ego(e_ptr)) continue; /* Test if this is a legal ego-item type for this object */ for (j = 0; j < EGO_TVALS_MAX; j++) { /* Require identical base type */ if (o_ptr->tval == e_ptr->tval[j]) { /* Require sval in bounds, lower */ if (o_ptr->sval >= e_ptr->min_sval[j]) { /* Require sval in bounds, upper */ if (o_ptr->sval <= e_ptr->max_sval[j]) { /* Accept */ table[i].prob3 = table[i].prob2; } } } } /* Total */ total += table[i].prob3; } /* No legal ego-items -- create a normal unenchanted one */ if (total == 0) return (0); /* Pick an ego-item */ value = randint0(total); /* Find the object */ for (i = 0; i < alloc_ego_size; i++) { /* Found the entry */ if (value < table[i].prob3) break; /* Decrement */ value = value - table[i].prob3; } /* We have one */ e_idx = (byte) table[i].index; o_ptr->name2 = e_idx; return ((!cf_is_empty(e_info[e_idx].flags_curse) || kf_has(e_info[e_idx].flags_kind, KF_RAND_CURSE)) ? -2 : 2); }
/* * This will get data on an object * It gets a lot of stuff, pretty much everything that I * thought was reasonable to get. However, you might have * a much different opinion. Luckily, I tried to make it * trivial to add new items to log. */ static void get_obj_data(const struct object *obj, int y, int x, bool mon, bool uniq) { bool vault = square_isvault(cave, y, x); int number = obj->number; static int lvl; struct artifact *art; double gold_temp = 0; assert(obj->kind); /* get player depth */ lvl = player->depth; /* check for some stuff that we will use regardless of type */ /* originally this was armor, but I decided to generalize it */ /* has free action (hack: don't include Inertia)*/ if (of_has(obj->flags, OF_FREE_ACT) && !((obj->tval == TV_AMULET) && (!strstr(obj->kind->name, "Inertia")))) { /* add the stats */ add_stats(ST_FA_EQUIPMENT, vault, mon, number); /* record first level */ first_find(ST_FF_FA); } /* has see invis */ if (of_has(obj->flags, OF_SEE_INVIS)){ add_stats(ST_SI_EQUIPMENT, vault, mon, number); first_find(ST_FF_SI); } /* has at least one basic resist */ if ((obj->el_info[ELEM_ACID].res_level == 1) || (obj->el_info[ELEM_ELEC].res_level == 1) || (obj->el_info[ELEM_COLD].res_level == 1) || (obj->el_info[ELEM_FIRE].res_level == 1)){ add_stats(ST_RESIST_EQUIPMENT, vault, mon, number); } /* has rbase */ if ((obj->el_info[ELEM_ACID].res_level == 1) && (obj->el_info[ELEM_ELEC].res_level == 1) && (obj->el_info[ELEM_COLD].res_level == 1) && (obj->el_info[ELEM_FIRE].res_level == 1)) add_stats(ST_RBASE_EQUIPMENT, vault, mon, number); /* has resist poison */ if (obj->el_info[ELEM_POIS].res_level == 1){ add_stats(ST_RPOIS_EQUIPMENT, vault, mon, number); first_find(ST_FF_RPOIS); } /* has resist nexus */ if (obj->el_info[ELEM_NEXUS].res_level == 1){ add_stats(ST_RNEXUS_EQUIPMENT, vault, mon, number); first_find(ST_FF_RNEXUS); } /* has resist blind */ if (of_has(obj->flags, OF_PROT_BLIND)){ add_stats(ST_RBLIND_EQUIPMENT, vault, mon, number); first_find(ST_FF_RBLIND); } /* has resist conf */ if (of_has(obj->flags, OF_PROT_CONF)){ add_stats(ST_RCONF_EQUIPMENT, vault, mon, number); first_find(ST_FF_RCONF); } /* has speed */ if (obj->modifiers[OBJ_MOD_SPEED] != 0) add_stats(ST_SPEED_EQUIPMENT, vault, mon, number); /* has telepathy */ if (of_has(obj->flags, OF_TELEPATHY)){ add_stats(ST_TELEP_EQUIPMENT, vault, mon, number); first_find(ST_FF_TELEP); } switch(obj->tval){ /* armor */ 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: case TV_DRAG_ARMOR:{ /* do not include artifacts */ if (obj->artifact) break; /* add to armor total */ add_stats(ST_ARMORS, vault, mon, number); /* check if bad, good, or average */ if (obj->to_a < 0) add_stats(ST_BAD_ARMOR, vault, mon, number); if (obj->to_h == 0) add_stats(ST_AVERAGE_ARMOR, vault, mon, number); if (obj->to_h > 0) add_stats(ST_GOOD_ARMOR, vault, mon, number); /* has str boost */ if (obj->modifiers[OBJ_MOD_STR] != 0) add_stats(ST_STR_ARMOR, vault, mon, number); /* has dex boost */ if (obj->modifiers[OBJ_MOD_DEX] != 0) add_stats(ST_DEX_ARMOR, vault, mon, number); /* has int boost */ if (obj->modifiers[OBJ_MOD_INT] != 0) add_stats(ST_INT_ARMOR, vault, mon, number); if (obj->modifiers[OBJ_MOD_WIS] != 0) add_stats(ST_WIS_ARMOR, vault, mon, number); if (obj->modifiers[OBJ_MOD_CON] != 0) add_stats(ST_CON_ARMOR, vault, mon, number); if (of_has(obj->flags, OF_LIGHT_CURSE)) add_stats(ST_CURSED_ARMOR, vault, mon, number); break; } /* weapons */ case TV_DIGGING: case TV_HAFTED: case TV_POLEARM: case TV_SWORD:{ /* do not include artifacts */ if (obj->artifact) break; /* add to weapon total */ add_stats(ST_WEAPONS, vault, mon, number); /* check if bad, good, or average */ if ((obj->to_h < 0) && (obj->to_d < 0)) add_stats(ST_BAD_WEAPONS, vault, mon, number); if ((obj->to_h == 0) && (obj->to_d == 0)) add_stats(ST_AVERAGE_WEAPONS, vault, mon, number); if ((obj->to_h > 0) && (obj->to_d > 0)) add_stats(ST_GOOD_WEAPONS, vault, mon, number); /* Egos by name - changes results a little */ if (obj->ego) { /* slay evil */ if (strstr(obj->ego->name, "of Slay Evil")) add_stats(ST_SLAYEVIL_WEAPONS, vault, mon, number); /* slay weapons */ else if (strstr(obj->ego->name, "of Slay")) add_stats(ST_SLAY_WEAPONS, vault, mon, number); /* kill flag */ if (strstr(obj->ego->name, "of *Slay")) add_stats(ST_KILL_WEAPONS, vault, mon, number); /* determine westernesse by flags */ if (strstr(obj->ego->name, "Westernesse")) add_stats(ST_WESTERNESSE_WEAPONS, vault, mon, number); /* determine defender by flags */ if (strstr(obj->ego->name, "Defender")) add_stats(ST_DEFENDER_WEAPONS, vault, mon, number); /* determine gondolin by flags */ if (strstr(obj->ego->name, "Gondolin")) add_stats(ST_GONDOLIN_WEAPONS, vault, mon, number); /* determine holy avenger by flags */ if (strstr(obj->ego->name, "Avenger")) add_stats(ST_HOLY_WEAPONS, vault, mon, number); /* is morgul */ if (strstr(obj->ego->name, "Morgul")) add_stats(ST_MORGUL_WEAPONS, vault, mon, number); } /* branded weapons */ if (obj->brands) add_stats(ST_BRAND_WEAPONS, vault, mon, number); /* extra blows */ if (obj->modifiers[OBJ_MOD_BLOWS] > 0) add_stats(ST_XTRABLOWS_WEAPONS, vault, mon, number); /* telepathy */ if (of_has(obj->flags, OF_TELEPATHY)) add_stats(ST_TELEP_WEAPONS, vault, mon, number); /* is a top of the line weapon */ if (((obj->tval == TV_HAFTED) && (!strstr(obj->kind->name, "Disruption"))) || ((obj->tval == TV_POLEARM) && (!strstr(obj->kind->name, "Slicing"))) || ((obj->tval == TV_SWORD) && (!strstr(obj->kind->name, "Chaos")))) { add_stats(ST_HUGE_WEAPONS, vault, mon, number); /* is uber need to fix ACB if ((of_has(obj->flags, OF_SLAY_EVIL)) || (obj->modifiers[OBJ_MOD_BLOWS] > 0)) add_stats(ST_UBWE, vault, mon, number); */ } break; } /* launchers */ case TV_BOW:{ /* do not include artifacts */ if (obj->artifact) break; /* add to launcher total */ add_stats(ST_BOWS, vault, mon, number); /* check if bad, average, good, or very good */ if ((obj->to_h < 0) && (obj->to_d < 0)) add_stats(ST_BAD_BOWS, vault, mon, number); if ((obj->to_h == 0) && (obj->to_d == 0)) add_stats(ST_AVERAGE_BOWS, vault, mon, number); if ((obj->to_h > 0) && (obj->to_d > 0)) add_stats(ST_GOOD_BOWS, vault, mon, number); if ((obj->to_h > 15) || (obj->to_d > 15)) add_stats(ST_VERYGOOD_BOWS, vault, mon, number); /* check long bows and xbows for xtra might and/or shots */ if (obj->pval > 2) { if (obj->modifiers[OBJ_MOD_SHOTS] > 0) add_stats(ST_XTRASHOTS_BOWS, vault, mon, number); if (obj->modifiers[OBJ_MOD_MIGHT] > 0) add_stats(ST_XTRAMIGHT_BOWS, vault, mon, number); } /* check for buckland */ if ((obj->pval == 2) && kf_has(obj->kind->kind_flags, KF_SHOOTS_SHOTS) && (obj->modifiers[OBJ_MOD_MIGHT] > 0) && (obj->modifiers[OBJ_MOD_SHOTS] > 0)) add_stats(ST_BUCKLAND_BOWS, vault, mon, number); /* has telep */ if (of_has(obj->flags, OF_TELEPATHY)) add_stats(ST_TELEP_BOWS, vault, mon, number); /* is cursed */ if (of_has(obj->flags, OF_LIGHT_CURSE)) add_stats(ST_CURSED_BOWS, vault, mon, number); break; } /* potion */ case TV_POTION:{ /* Add total amounts */ add_stats(ST_POTIONS, vault, mon, number); /* Stat gain */ if (strstr(obj->kind->name, "Strength") || strstr(obj->kind->name, "Intelligence") || strstr(obj->kind->name, "Wisdom") || strstr(obj->kind->name, "Dexterity") || strstr(obj->kind->name, "Constitution")) { add_stats(ST_GAINSTAT_POTIONS, vault, mon, number); } else if (strstr(obj->kind->name, "Augmentation")) { /* Augmentation counts as 5 stat gain pots */ add_stats(ST_GAINSTAT_POTIONS, vault, mon, number * 5); } else if (strstr(obj->kind->name, "*Enlightenment*")) { /* *Enlight* counts as 2 stat pots */ add_stats(ST_GAINSTAT_POTIONS, vault, mon, number * 2); } else if (strstr(obj->kind->name, "Restore Mana")) { add_stats(ST_RESTOREMANA_POTIONS, vault, mon, number); } else if ((strstr(obj->kind->name, "Life")) || (strstr(obj->kind->name, "*Healing*"))) { add_stats(ST_ELVEN_RINGS, vault, mon, number); } else if (strstr(obj->kind->name, "Healing")) { add_stats(ST_HEALING_POTIONS, vault, mon, number); } break; } /* scrolls */ case TV_SCROLL:{ /* add total amounts */ add_stats(ST_SCROLLS, vault, mon, number); if (strstr(obj->kind->name, "Banishment") || strstr(obj->kind->name, "Mass Banishment") || strstr(obj->kind->name, "Rune of Protection") || strstr(obj->kind->name, "*Destruction*")) { add_stats(ST_ENDGAME_SCROLLS, vault, mon, number); } else if (strstr(obj->kind->name, "Acquirement")) { add_stats(ST_ACQUIRE_SCROLLS, vault, mon, number); } else if (strstr(obj->kind->name, "*Acquirement*")) { /* do the effect of 2 acquires */ add_stats(ST_ACQUIRE_SCROLLS, vault, mon, number * 2); } break; } /* rods */ case TV_ROD:{ /* add to total */ add_stats(ST_RODS, vault, mon, number); if (strstr(obj->kind->name, "Trap Detection") || strstr(obj->kind->name, "Treasure Detection") || strstr(obj->kind->name, "Door/Stair Location") || strstr(obj->kind->name, "Illumination") || strstr(obj->kind->name, "Light")) { add_stats(ST_UTILITY_RODS, vault, mon, number); } else if (strstr(obj->kind->name, "Teleport Other")) { add_stats(ST_TELEPOTHER_RODS, vault, mon, number); } else if (strstr(obj->kind->name, "Detection")) { add_stats(ST_DETECTALL_RODS, vault, mon, number); } else if (strstr(obj->kind->name, "Speed") || strstr(obj->kind->name, "Healing")) { add_stats(ST_ENDGAME_RODS, vault, mon, number); } break; } /* staves */ case TV_STAFF:{ add_stats(ST_STAVES, vault, mon, number); if (strstr(obj->kind->name, "Speed")) { add_stats(ST_SPEED_STAVES, vault, mon, number); } else if (strstr(obj->kind->name, "*Destruction*")) { add_stats(ST_DESTRUCTION_STAVES, vault, mon, number); } else if (strstr(obj->kind->name, "Dispel Evil") || strstr(obj->kind->name, "Power") || strstr(obj->kind->name, "Holiness")) { add_stats(ST_KILL_STAVES, vault, mon, number); } else if (strstr(obj->kind->name, "Healing") || strstr(obj->kind->name, "Banishment") || strstr(obj->kind->name, "the Magi")) { add_stats(ST_ENDGAME_STAVES, vault, mon, number); } break; } case TV_WAND:{ add_stats(ST_WANDS, vault, mon, number); if (strstr(obj->kind->name, "Teleport Other")) add_stats(ST_TELEPOTHER_WANDS, vault, mon, number); break; } case TV_RING:{ add_stats(ST_RINGS, vault, mon, number); /* is it cursed */ if (of_has(obj->flags,OF_LIGHT_CURSE)) add_stats(ST_CURSED_RINGS, vault, mon, number); if (strstr(obj->kind->name, "Speed")) { add_stats(ST_SPEEDS_RINGS, vault, mon, number); } else if ((strstr(obj->kind->name, "Strength")) || (strstr(obj->kind->name, "Intelligence")) || (strstr(obj->kind->name, "Dexterity")) || (strstr(obj->kind->name, "Constitution"))) { add_stats(ST_STAT_RINGS, vault, mon, number); } else if (strstr(obj->kind->name, "Resist Poison")) { add_stats(ST_RPOIS_RINGS, vault, mon, number); } else if (strstr(obj->kind->name, "Free Action")) { add_stats(ST_FA_RINGS, vault, mon, number); } else if (strstr(obj->kind->name, "See invisible")) { add_stats(ST_SI_RINGS, vault, mon, number); } else if ((strstr(obj->kind->name, "Flames")) || (strstr(obj->kind->name, "Ice")) || (strstr(obj->kind->name, "Acid")) || (strstr(obj->kind->name, "Lightning"))) { add_stats(ST_BRAND_RINGS, vault, mon, number); } else if ((strstr(obj->kind->name, "Fire")) || (strstr(obj->kind->name, "Adamant")) || (strstr(obj->kind->name, "Firmament"))) { add_stats(ST_ELVEN_RINGS, vault, mon, number); } else if (strstr(obj->kind->name, "Power")) { add_stats(ST_ONE_RINGS, vault, mon, number); } break; } case TV_AMULET:{ add_stats(ST_AMULETS, vault, mon, number); if (strstr(obj->kind->name, "Wisdom")) { add_stats(ST_WIS_AMULETS, vault, mon, number); } else if ((strstr(obj->kind->name, "Magi")) || (strstr(obj->kind->name, "Trickery")) || (strstr(obj->kind->name, "Weaponmastery"))) { add_stats(ST_ENDGAME_AMULETS, vault, mon, number); } else if (strstr(obj->kind->name, "ESP")) { add_stats(ST_TELEP_AMULETS, vault, mon, number); } /* is cursed */ if (of_has(obj->flags, OF_LIGHT_CURSE)) add_stats(ST_CURSED_AMULETS, vault, mon, number); break; } case TV_SHOT: case TV_ARROW: case TV_BOLT:{ add_stats(ST_AMMO, vault, mon, number); /* check if bad, average, good */ if ((obj->to_h < 0) && (obj->to_d < 0)) add_stats(ST_BAD_AMMO, vault, mon, number); if ((obj->to_h == 0) && (obj->to_d == 0)) add_stats(ST_AVERAGE_AMMO, vault, mon, number); if ((obj->to_h > 0) && (obj->to_d > 0)) add_stats(ST_GOOD_AMMO, vault, mon, number); if (obj->ego) add_stats(ST_BRANDSLAY_AMMO, vault, mon, number); if (strstr(obj->kind->name, "Seeker") || strstr(obj->kind->name, "Mithril")) { /* Mithril and seeker ammo */ add_stats(ST_VERYGOOD_AMMO, vault, mon, number); /* Ego mithril and seeker ammo */ if (obj->ego) { add_stats(ST_AWESOME_AMMO, vault, mon, number); if (strstr(obj->ego->name, "of Slay Evil")) add_stats(ST_SLAYEVIL_AMMO, vault, mon, number); if (strstr(obj->ego->name, "of Holy Might")) add_stats(ST_HOLY_AMMO, vault, mon, number); } } break; } /* prayer books and magic books have the same probability only track one of them */ case TV_MAGIC_BOOK:{ switch(obj->sval){ /* svals begin at 0 and end at 8 */ case 0:{ add_stats(ST_1ST_BOOKS, vault, mon, number); first_find(ST_FF_BOOK1); break; } case 1:{ add_stats(ST_2ND_BOOKS, vault, mon, number); first_find(ST_FF_BOOK2); break; } case 2:{ add_stats(ST_3RD_BOOKS, vault, mon, number); first_find(ST_FF_BOOK3); break; } case 3:{ add_stats(ST_4TH_BOOKS, vault, mon, number); first_find(ST_FF_BOOK4); break; } case 4:{ add_stats(ST_5TH_BOOKS, vault, mon, number); first_find(ST_FF_BOOK5); break; } case 5:{ add_stats(ST_6TH_BOOKS, vault, mon, number); first_find(ST_FF_BOOK6); break; } case 6:{ add_stats(ST_7TH_BOOKS, vault, mon, number); first_find(ST_FF_BOOK7); break; } case 7:{ add_stats(ST_8TH_BOOKS, vault, mon, number); first_find(ST_FF_BOOK8); break; } case 8:{ add_stats(ST_9TH_BOOKS, vault, mon, number); first_find(ST_FF_BOOK9); break; } } break; } } /* check to see if we have an artifact */ if (obj->artifact){ /* add to artifact level total */ art_total[lvl] += addval; /* add to the artifact iteration total */ if (iter < TRIES_SIZE) art_it[iter]++; /* Obtain the artifact info */ art = obj->artifact; //debugging, print out that we found the artifact //msg_format("Found artifact %s",art->name); /* artifact is shallow */ if (art->alloc_min < (player->depth - 20)) art_shal[lvl] += addval; /* artifact is close to the player depth */ if ((art->alloc_min >= player->depth - 20) && (art->alloc_min <= player->depth )) art_ave[lvl] += addval; /* artifact is out of depth */ if (art->alloc_min > (player->depth)) art_ood[lvl] += addval; /* check to see if it's a special artifact */ if ((obj->tval == TV_LIGHT) || (obj->tval == TV_AMULET) || (obj->tval == TV_RING)){ /* increment special artifact counter */ art_spec[lvl] += addval; } else { /* increment normal artifacts */ art_norm[lvl] += addval; /* did it come from a monster? */ if (mon) art_mon[lvl] += addval; /* did it come from a unique? */ if (uniq) art_uniq[lvl] += addval; /* was it in a vault? */ if (vault){ /* did a monster drop it ?*/ if ((mon) || (uniq)) art_mon_vault[lvl] += addval; else art_vault[lvl] += addval; } else { /* was it just lyin' on the floor? */ if ((!uniq) && (!mon)) art_floor[lvl] += addval; } } /* preserve the artifact */ if (!(clearing)) art->created = FALSE; } /* Get info on gold. */ if (obj->tval == TV_GOLD){ int temp = obj->pval; gold_temp = temp; gold_total[lvl] += (gold_temp / tries); /*From a monster? */ if ((mon) || (uniq)) gold_mon[lvl] += (gold_temp / tries); else gold_floor[lvl] += (gold_temp / tries); } }
/* * Describe an object's effect, if any. */ static bool describe_effect(textblock * tb, const object_type * o_ptr, oinfo_detail_t mode) { const object_kind *k_ptr = &k_info[o_ptr->k_idx]; const char *desc; random_value timeout = { 0, 0, 0, 0 }; bool full = mode & OINFO_FULL; bool subjective = mode & OINFO_SUBJ; bool terse = mode & OINFO_TERSE; int effect = 0, fail; if (wearable_p(o_ptr)) { /* Wearable + effect <=> activates */ if ((o_ptr->ident & IDENT_WORN) || full) { effect = o_ptr->effect; timeout = o_ptr->time; } else if (object_effect(o_ptr)) { textblock_append(tb, "It can be activated.\n"); return TRUE; } } else { /* Sometimes only print activation info */ if (terse) return FALSE; if ((object_aware_p(o_ptr) && kf_has(k_ptr->flags_kind, KF_EASY_KNOW)) || full) { effect = o_ptr->effect; timeout = o_ptr->time; } else if (object_effect(o_ptr)) { if (effect_aim(k_ptr->effect)) textblock_append(tb, "It can be aimed.\n"); else if (o_ptr->tval == TV_FOOD) textblock_append(tb, "It can be eaten.\n"); else if (o_ptr->tval == TV_POTION) textblock_append(tb, "It can be drunk.\n"); else if (o_ptr->tval == TV_SCROLL) textblock_append(tb, "It can be read.\n"); else textblock_append(tb, "It can be activated.\n"); return TRUE; } } /* Forget it without an effect */ if (!effect) return FALSE; /* Obtain the description */ desc = effect_desc(effect); if (!desc) return FALSE; if (effect_aim(effect)) textblock_append(tb, "When aimed, it "); else if (o_ptr->tval == TV_FOOD) textblock_append(tb, "When eaten, it "); else if (o_ptr->tval == TV_POTION) textblock_append(tb, "When drunk, it "); else if (o_ptr->tval == TV_SCROLL) textblock_append(tb, "When read, it "); else textblock_append(tb, "When activated, it "); /* Print a colourised description */ do { if (isdigit((unsigned char) *desc)) textblock_append_c(tb, TERM_L_GREEN, "%c", *desc); else textblock_append(tb, "%c", *desc); } while (*desc++); textblock_append(tb, ".\n"); if (randcalc(timeout, 0, MAXIMISE) > 0) { int min_time, max_time; /* Sometimes adjust for player speed */ int multiplier = extract_energy[p_ptr->state.pspeed]; if (!subjective) multiplier = 10; textblock_append(tb, "Takes "); /* Correct for player speed */ min_time = randcalc(timeout, 0, MINIMISE) * multiplier / 10; max_time = randcalc(timeout, 0, MAXIMISE) * multiplier / 10; textblock_append_c(tb, TERM_L_GREEN, "%d", min_time); if (min_time != max_time) { textblock_append(tb, " to "); textblock_append_c(tb, TERM_L_GREEN, "%d", max_time); } textblock_append(tb, " turns to recharge"); if (subjective && p_ptr->state.pspeed != 110) textblock_append(tb, " at your current speed"); textblock_append(tb, ".\n"); } if (!subjective || o_ptr->tval == TV_FOOD || o_ptr->tval == TV_POTION || o_ptr->tval == TV_SCROLL) { return TRUE; } else { fail = get_use_device_chance(o_ptr); textblock_append(tb, "Your chance of success is %d.%d%%\n", (1000 - fail) / 10, (1000 - fail) % 10); } return TRUE; }
/** * Creates a specific monster's drop, including any drops specified * in the monster.txt file. * * Returns true if anything is created, false if nothing is. */ static bool mon_create_drop(struct chunk *c, struct monster *mon, byte origin) { struct monster_drop *drop; bool great, good, gold_ok, item_ok; bool extra_roll = false; bool any = false; int number = 0, level, j, monlevel; struct object *obj; assert(mon); great = (rf_has(mon->race->flags, RF_DROP_GREAT)); good = great || (rf_has(mon->race->flags, RF_DROP_GOOD)); gold_ok = (!rf_has(mon->race->flags, RF_ONLY_ITEM)); item_ok = (!rf_has(mon->race->flags, RF_ONLY_GOLD)); /* Determine how much we can drop */ number = mon_create_drop_count(mon->race, false); /* Give added bonus for unique monters */ monlevel = mon->race->level; if (rf_has(mon->race->flags, RF_UNIQUE)) { monlevel = MIN(monlevel + 15, monlevel * 2); extra_roll = true; } /* Take the best of (average of monster level and current depth) and (monster level) - to reward fighting OOD monsters */ level = MAX((monlevel + player->depth) / 2, monlevel); level = MIN(level, 100); /* Morgoth currently drops all artifacts with the QUEST_ART flag */ if (rf_has(mon->race->flags, RF_QUESTOR) && (mon->race->level == 100)) { /* Search all the artifacts */ for (j = 1; j < z_info->a_max; j++) { struct artifact *art = &a_info[j]; struct object_kind *kind = lookup_kind(art->tval, art->sval); if (!kf_has(kind->kind_flags, KF_QUEST_ART)) { continue; } /* Allocate by hand, prep, apply magic */ obj = mem_zalloc(sizeof(*obj)); object_prep(obj, kind, 100, RANDOMISE); obj->artifact = art; copy_artifact_data(obj, obj->artifact); obj->artifact->created = true; /* Set origin details */ obj->origin = origin; obj->origin_depth = player->depth; obj->origin_race = mon->race; obj->number = 1; /* Try to carry */ if (monster_carry(c, mon, obj)) { any = true; } else { obj->artifact->created = false; object_wipe(obj); mem_free(obj); } } } /* Specified drops */ for (drop = mon->race->drops; drop; drop = drop->next) { if ((unsigned int)randint0(100) >= drop->percent_chance) continue; /* Allocate by hand, prep, apply magic */ obj = mem_zalloc(sizeof(*obj)); object_prep(obj, drop->kind, level, RANDOMISE); apply_magic(obj, level, true, good, great, extra_roll); /* Set origin details */ obj->origin = origin; obj->origin_depth = player->depth; obj->origin_race = mon->race; obj->number = randint0(drop->max - drop->min) + drop->min; /* Try to carry */ if (monster_carry(c, mon, obj)) { any = true; } else { object_wipe(obj); mem_free(obj); } } /* Make some objects */ for (j = 0; j < number; j++) { if (gold_ok && (!item_ok || (randint0(100) < 50))) { obj = make_gold(level, "any"); } else { obj = make_object(c, level, good, great, extra_roll, NULL, 0); if (!obj) continue; } /* Set origin details */ obj->origin = origin; obj->origin_depth = player->depth; obj->origin_race = mon->race; /* Try to carry */ if (monster_carry(c, mon, obj)) { any = true; } else { obj->artifact->created = false; object_wipe(obj); mem_free(obj); } } return any; }
/** * Create a spoiler file for items */ static void spoil_obj_desc(const char *fname) { int i, k, s, t, n = 0; u16b who[200]; char buf[1024]; char wgt[80]; char dam[80]; const char *format = "%-51s %7s%6s%4s%9s\n"; /* Open the file */ path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname); fh = file_open(buf, MODE_WRITE, FTYPE_TEXT); /* Oops */ if (!fh) { msg("Cannot create spoiler file."); return; } /* Header */ file_putf(fh, "Spoiler File -- Basic Items (%s)\n\n\n", buildid); /* More Header */ file_putf(fh, format, "Description", "Dam/AC", "Wgt", "Lev", "Cost"); file_putf(fh, format, "----------------------------------------", "------", "---", "---", "----"); /* List the groups */ for (i = 0; true; i++) { /* Write out the group title */ if (group_item[i].name) { /* Hack -- bubble-sort by cost and then level */ for (s = 0; s < n - 1; s++) { for (t = 0; t < n - 1; t++) { int i1 = t; int i2 = t + 1; int e1; int e2; s32b t1; s32b t2; kind_info(NULL, 0, NULL, 0, NULL, 0, &e1, &t1, who[i1]); kind_info(NULL, 0, NULL, 0, NULL, 0, &e2, &t2, who[i2]); if ((t1 > t2) || ((t1 == t2) && (e1 > e2))) { int tmp = who[i1]; who[i1] = who[i2]; who[i2] = tmp; } } } /* Spoil each item */ for (s = 0; s < n; s++) { int e; s32b v; /* Describe the kind */ kind_info(buf, sizeof(buf), dam, sizeof(dam), wgt, sizeof(wgt), &e, &v, who[s]); /* Dump it */ file_putf(fh, " %-51s%7s%6s%4d%9ld\n", buf, dam, wgt, e, (long)(v)); } /* Start a new set */ n = 0; /* Notice the end */ if (!group_item[i].tval) break; /* Start a new set */ file_putf(fh, "\n\n%s\n\n", group_item[i].name); } /* Get legal item types */ for (k = 1; k < z_info->k_max; k++) { struct object_kind *kind = &k_info[k]; /* Skip wrong tvals */ if (kind->tval != group_item[i].tval) continue; /* Hack -- Skip instant-artifacts */ if (kf_has(kind->kind_flags, KF_INSTA_ART)) continue; /* Save the index */ who[n++] = k; } } /* Check for errors */ if (!file_close(fh)) { msg("Cannot close spoiler file."); return; } /* Message */ msg("Successfully created a spoiler file."); }
bool wiz_create_item_action(menu_type * m, const ui_event * e, int oid) { ui_event ret; menu_type *menu; int choice[60]; int n_choices; int i; char buf[60]; if (e->type != EVT_SELECT) return TRUE; /* Artifacts */ if (choose_artifact) { struct tval_desc *a_tvals = menu_priv(m); /* ...We have to search the whole artifact list. */ for (n_choices = 0, i = 1; (n_choices < 60) && (i < z_info->a_max); i++) { artifact_type *a_ptr = &a_info[i]; /* Analyze matching items */ if (a_ptr->tval == a_tvals[oid].tval) { /* Remember the artifact index */ choice[n_choices++] = i; } } } /* Regular objects */ else { for (n_choices = 0, i = 1; (n_choices < 60) && (i < z_info->k_max); i++) { object_kind *kind = &k_info[i]; if (kind->tval != tvals[oid].tval || kf_has(kind->flags_kind, KF_INSTA_ART)) continue; choice[n_choices++] = i; } } screen_save(); clear_from(0); menu = menu_new(MN_SKIN_COLUMNS, &wiz_create_item_submenu); menu->selections = all_letters; if (m->count == N_ELEMENTS(tvals)) strnfmt(buf, sizeof(buf), "What kind of %s?", tvals[oid].desc); else strnfmt(buf, sizeof(buf), "Which artifact %s? ", tvals[oid].desc); menu->title = buf; menu_setpriv(menu, n_choices, choice); menu_layout(menu, &wiz_create_item_area); ret = menu_select(menu, 0, FALSE); screen_load(); return (ret.type == EVT_ESCAPE); }