/* make a random new object, returning pointer */ Object* create_object(int itemlevel) { Object* newObject; int r; int ok = false; while (! ok) { newObject = ((Object*) checkmalloc(sizeof(Object))); r= random_range(135); if (r < 20) make_thing(newObject,-1); else if (r < 40) make_food(newObject,-1); else if (r < 50) make_scroll(newObject,-1); else if (r < 60) make_potion(newObject,-1); else if (r < 70) make_weapon(newObject,-1); else if (r < 80) make_armor(newObject,-1); else if (r < 90) make_shield(newObject,-1); else if (r < 100) make_stick(newObject,-1); else if (r < 110) make_boots(newObject,-1); else if (r < 120) make_cloak(newObject,-1); else if (r < 130) make_ring(newObject,-1); else make_artifact(newObject,-1); /* not ok if object is too good for level, or if unique and already made */ /* 1/100 chance of finding object if too good for level */ ok = ((newObject->uniqueness < UNIQUE_MADE) && ((newObject->level < itemlevel+random_range(3)) || (random_range(100)==23))); if (!ok) { free_obj( newObject, true ); } } if (newObject->uniqueness == UNIQUE_UNMADE) Objects[newObject->id].uniqueness=UNIQUE_MADE; return(newObject); }
/** * Attempt to make an object * * \param c is the current dungeon level. * \param j_ptr is the object struct to be populated. * \param lev is the creation level of the object (not necessarily == depth). * \param good is whether the object is to be good * \param great is whether the object is to be great * \param value is the value to be returned to the calling function * * Returns the whether or not creation worked. */ bool make_object(struct cave *c, object_type *j_ptr, int lev, bool good, bool great, s32b *value) { int base, art, div; object_kind *kind; /* Base level and artifact chance for the object */ if (great) { art = ART_GREAT; base = lev + 10 + m_bonus(5, lev); } else if (good) { art = ART_GOOD; base = lev + 5 + m_bonus(5, lev); } else { art = ART_NORMAL; base = lev; } /* Small hack to bring artifact frequencies at low depths in line with V */ div = 9 - p_ptr->depth; if (div < 1) div = 1; /* Try to make an artifact */ if (one_in_(art * div)) { if (make_artifact(j_ptr, lev)) { if (value) *value = object_value_real(j_ptr, 1, FALSE, TRUE); return TRUE; } } /* Get the object, prep it and apply magic */ kind = get_obj_num(base, good || great); if (!kind) return FALSE; object_prep(j_ptr, kind, base, RANDOMISE); apply_magic(j_ptr, base, FALSE, good, great); /* Generate multiple items */ if (kind->gen_mult_prob >= randint1(100)) j_ptr->number = randcalc(kind->stack_size, lev, RANDOMISE); if (j_ptr->number >= MAX_STACK_SIZE) j_ptr->number = MAX_STACK_SIZE - 1; /* Return value, increased for uncursed out-of-depth objects */ if (value) *value = object_value_real(j_ptr, j_ptr->number, FALSE, TRUE); if (!cursed_p(j_ptr->flags) && (kind->alloc_min > c->depth)) { if (value) *value = (kind->alloc_min - c->depth) * (*value / 5); } return TRUE; }
/** * Applying magic to an object, which includes creating ego-items, and applying * random bonuses, * * The `good` argument forces the item to be at least `good`, and the `great` * argument does likewise. Setting `allow_artifacts` to true allows artifacts * to be created here. * * If `good` or `great` are not set, then the `lev` argument controls the * quality of item. * * Returns 0 if a normal object, 1 if a good object, 2 if an ego item, 3 if an * artifact. */ int apply_magic(struct object *obj, int lev, bool allow_artifacts, bool good, bool great, bool extra_roll) { int i; s16b power = 0; /* Chance of being `good` and `great` */ /* This has changed over the years: * 3.0.0: good = MIN(75, lev + 10); great = MIN(20, lev / 2); * 3.3.0: good = (lev + 2) * 3; great = MIN(lev / 4 + lev, 50); * 3.4.0: good = (2 * lev) + 5 * 3.4 was in between 3.0 and 3.3, 3.5 attempts to keep the same * area under the curve as 3.4, but make the generation chances * flatter. This depresses good items overall since more items * are created deeper. * This change is meant to go in conjunction with the changes * to ego item allocation levels. (-fizzix) */ int good_chance = (33 + lev); int great_chance = 30; /* Roll for "good" */ if (good || (randint0(100) < good_chance)) { power = 1; /* Roll for "great" */ if (great || (randint0(100) < great_chance)) power = 2; } /* Roll for artifact creation */ if (allow_artifacts) { int rolls = 0; /* Get one roll if excellent */ if (power >= 2) rolls = 1; /* Get two rolls if forced great */ if (great) rolls = 2; /* Give some extra rolls for uniques and acq scrolls */ if (extra_roll) rolls += 2; /* Roll for artifacts if allowed */ for (i = 0; i < rolls; i++) if (make_artifact(obj)) return 3; } /* Try to make an ego item */ if (power == 2) make_ego_item(obj, lev); /* Apply magic */ if (tval_is_weapon(obj)) { apply_magic_weapon(obj, lev, power); } else if (tval_is_armor(obj)) { apply_magic_armour(obj, lev, power); } else if (tval_is_ring(obj)) { if (obj->sval == lookup_sval(obj->tval, "Speed")) { /* Super-charge the ring */ while (one_in_(2)) obj->modifiers[OBJ_MOD_SPEED]++; } } else if (tval_is_chest(obj)) { /* Hack -- skip ruined chests */ if (obj->kind->level > 0) { /* Hack -- pick a "difficulty" */ obj->pval = randint1(obj->kind->level); /* Never exceed "difficulty" of 55 to 59 */ if (obj->pval > 55) obj->pval = (s16b)(55 + randint0(5)); } } /* Apply minima from ego items if necessary */ ego_apply_minima(obj); return power; }
/* gain for an item */ void acquire(int blessing) { char otype; int index,id = ABORT; pob newthing; if (blessing < 0) { index = random_item(); if (index == ABORT) mprint("You feel fortunate."); else { print1("Smoke drifts out of your pack.... "); print2("Destroyed: "); nprint2(itemid(Player.possessions[index])); morewait(); dispose_lost_objects(1,Player.possessions[index]); } } else { newthing = ((pob) checkmalloc(sizeof(objtype))); /* DAG this assignment looks unneccessary */ newthing->id = -1; if (gamestatusp(CHEATED)) print1("Acquire which kind of item: !?][}{)/=%%\\& "); else print1("Acquire which kind of item: !?][}{)/=%%\\ "); otype = mgetc(); switch (otype) { case (POTION&0xff): if (blessing > 0) id = itemlist(POTIONID,NUMPOTIONS); else id = random_range(NUMPOTIONS); if (id < 0) print2("You feel stupid."); else make_potion(newthing,id); break; case (SCROLL&0xff): if (blessing > 0) id = itemlist(SCROLLID,NUMSCROLLS); else id = random_range(NUMSCROLLS); if (id < 0) print2("You feel stupid."); else make_scroll(newthing,id); break; case (RING&0xff): if (blessing > 0) id = itemlist(RINGID,NUMRINGS); else id = random_range(NUMRINGS); if (id < 0) print2("You feel stupid."); else make_ring(newthing,id); break; case (STICK&0xff): if (blessing > 0) id = itemlist(STICKID,NUMSTICKS); else id = random_range(NUMSTICKS); if (id < 0) print2("You feel stupid."); else make_stick(newthing,id); break; case (ARMOR&0xff): if (blessing > 0) id = itemlist(ARMORID,NUMARMOR); else id = random_range(NUMARMOR); if (id < 0) print2("You feel stupid."); else make_armor(newthing,id); break; case (SHIELD&0xff): if (blessing > 0) id = itemlist(SHIELDID,NUMSHIELDS); else id = random_range(NUMSHIELDS); if (id < 0) print2("You feel stupid."); else make_shield(newthing,id); break; case (WEAPON&0xff): if (blessing > 0) id = itemlist(WEAPONID,NUMWEAPONS); else id = random_range(NUMWEAPONS); if (id < 0) print2("You feel stupid."); else make_weapon(newthing,id); break; case (BOOTS&0xff): if (blessing > 0) id = itemlist(BOOTID,NUMBOOTS); else id = random_range(NUMBOOTS); if (id < 0) print2("You feel stupid."); else make_boots(newthing,id); break; case (CLOAK&0xff): if (blessing > 0) id = itemlist(CLOAKID,NUMCLOAKS); else id = random_range(NUMCLOAKS); if (id < 0) print2("You feel stupid."); else make_cloak(newthing,id); break; case (FOOD&0xff): if (blessing > 0) id = itemlist(FOODID,NUMFOODS); else id = random_range(NUMFOODS); if (id < 0) print2("You feel stupid."); else make_food(newthing,id); break; case (THING&0xff): if (blessing > 0) id = itemlist(THINGID,NUMTHINGS); else id = random_range(NUMTHINGS); if (id < 0) print2("You feel stupid."); else make_thing(newthing,id); break; case (ARTIFACT&0xff): if (gamestatusp(CHEATED)) id = itemlist(ARTIFACTID,NUMARTIFACTS); else id = -1; if (id < 0) print2("You feel stupid."); else make_artifact(newthing,id); break; default: print2("You feel stupid."); } xredraw(); if (id != ABORT) { if (blessing > 0) { newthing->known = 2; Objects[id].known = 1; } newthing->used = FALSE; gain_item(newthing); } else { /* DAG newthing allocated but was not freed... was YA memory leak */ /* use free() rather than free_obj() since newthing not initialized */ free( (char *) newthing ); } } }
/** * Applying magic to an object, which includes creating ego-items, and applying * random bonuses, * * The `good` argument forces the item to be at least `good`, and the `great` * argument does likewise. Setting `allow_artifacts` to TRUE allows artifacts * to be created here. * * If `good` or `great` are not set, then the `lev` argument controls the * quality of item. * * Returns 0 if a normal object, 1 if a good object, 2 if an ego item, 3 if an * artifact. */ s16b apply_magic(object_type *o_ptr, int lev, bool allow_artifacts, bool good, bool great, bool extra_roll) { int i; s16b power = 0; /* Chance of being `good` and `great` */ /* This has changed over the years: * 3.0.0: good = MIN(75, lev + 10); great = MIN(20, lev / 2); * 3.3.0: good = (lev + 2) * 3; great = MIN(lev / 4 + lev, 50); * 3.4.0: good = (2 * lev) + 5 * 3.4 was in between 3.0 and 3.3, 3.5 attempts to keep the same * area under the curve as 3.4, but make the generation chances * flatter. This depresses good items overall since more items * are created deeper. * This change is meant to go in conjunction with the changes * to ego item allocation levels. (-fizzix) */ int good_chance = (33 + lev); int great_chance = 30; /* Roll for "good" */ if (good || (randint0(100) < good_chance)) { power = 1; /* Roll for "great" */ if (great || (randint0(100) < great_chance)) power = 2; } /* Roll for artifact creation */ if (allow_artifacts) { int rolls = 0; /* Get one roll if excellent */ if (power >= 2) rolls = 1; /* Get two rolls if forced great */ if (great) rolls = 2; /* Give some extra rolls for uniques and acq scrolls */ if (extra_roll) rolls += 2; /* Roll for artifacts if allowed */ for (i = 0; i < rolls; i++) if (make_artifact(o_ptr)) return 3; } /* Try to make an ego item */ if (power == 2) make_ego_item(o_ptr, lev); /* Apply magic */ switch (o_ptr->tval) { case TV_DIGGING: case TV_HAFTED: case TV_POLEARM: case TV_SWORD: case TV_BOW: case TV_SHOT: case TV_ARROW: case TV_BOLT: apply_magic_weapon(o_ptr, lev, power); break; case TV_DRAG_ARMOR: case TV_HARD_ARMOR: case TV_SOFT_ARMOR: case TV_SHIELD: case TV_HELM: case TV_CROWN: case TV_CLOAK: case TV_GLOVES: case TV_BOOTS: apply_magic_armour(o_ptr, lev, power); break; case TV_RING: if (o_ptr->sval == SV_RING_SPEED) { /* Super-charge the ring */ while (one_in_(2)) o_ptr->pval[which_pval(o_ptr, OF_SPEED)]++; } break; case TV_CHEST: /* Hack -- skip ruined chests */ if (o_ptr->kind->level <= 0) break; /* Hack -- pick a "difficulty" */ o_ptr->pval[DEFAULT_PVAL] = randint1(o_ptr->kind->level); /* Never exceed "difficulty" of 55 to 59 */ if (o_ptr->pval[DEFAULT_PVAL] > 55) o_ptr->pval[DEFAULT_PVAL] = (s16b)(55 + randint0(5)); break; } /* Apply minima from ego items if necessary */ ego_apply_minima(o_ptr); return power; }
/** * Applying magic to an object, which includes creating ego-items, and applying * random bonuses, * * The `good` argument forces the item to be at least `good`, and the `great` * argument does likewise. Setting `allow_artifacts` to TRUE allows artifacts * to be created here. * * If `good` or `great` are not set, then the `lev` argument controls the * quality of item. * * Returns 0 if a normal object, 1 if a good object, 2 if an ego item, 3 if an * artifact. */ s16b apply_magic(object_type *o_ptr, int lev, bool allow_artifacts, bool good, bool great) { int i; s16b power = 0; /* Chance of being `good` and `great` */ /* This has changed over the years: * 3.0.0: good = MIN(75, lev + 10); great = MIN(20, lev / 2); * 3.3.0: good = (lev + 2) * 3; great = MIN(lev / 4 + lev, 50); * The calculations below are somewhere between the two. -AS- */ int good_chance = (2 * lev) + 5; int great_chance = MIN(40, (lev * 3) / 4); /* Roll for "good" */ if (good || (randint0(100) < good_chance)) { power = 1; /* Roll for "great" */ if (great || (randint0(100) < great_chance)) power = 2; } /* Roll for artifact creation */ if (allow_artifacts) { int rolls = 0; /* Get one roll if excellent */ if (power >= 2) rolls = 1; /* Get four rolls if forced great */ if (great) rolls = 4; /* Roll for artifacts if allowed */ for (i = 0; i < rolls; i++) if (make_artifact(o_ptr)) return 3; } /* Try to make an ego item */ if (power == 2) make_ego_item(o_ptr, lev); /* Apply magic */ switch (o_ptr->tval) { case TV_DIGGING: case TV_HAFTED: case TV_POLEARM: case TV_SWORD: case TV_BOW: case TV_SHOT: case TV_ARROW: case TV_BOLT: apply_magic_weapon(o_ptr, lev, power); break; case TV_DRAG_ARMOR: case TV_HARD_ARMOR: case TV_SOFT_ARMOR: case TV_SHIELD: case TV_HELM: case TV_CROWN: case TV_CLOAK: case TV_GLOVES: case TV_BOOTS: apply_magic_armour(o_ptr, lev, power); break; case TV_RING: if (o_ptr->sval == SV_RING_SPEED) { /* Super-charge the ring */ while (one_in_(2)) o_ptr->pval[which_pval(o_ptr, OF_SPEED)]++; } break; case TV_CHEST: /* Hack -- skip ruined chests */ if (o_ptr->kind->level <= 0) break; /* Hack -- pick a "difficulty" */ o_ptr->pval[DEFAULT_PVAL] = randint1(o_ptr->kind->level); /* Never exceed "difficulty" of 55 to 59 */ if (o_ptr->pval[DEFAULT_PVAL] > 55) o_ptr->pval[DEFAULT_PVAL] = (s16b)(55 + randint0(5)); break; } /* Apply minima from ego items if necessary */ ego_apply_minima(o_ptr); return power; }
/** * Complete object creation by applying magic to it. * * Magic includes rolling for random bonuses, applying flags to ego-items, * charging charged items, fuelling lights, and trapping chests. * * The `good` argument forces the item to be at least `good`, and the `great` * argument does likewise. Setting `allow_artifacts` to TRUE allows artifacts * to be created here. * * If `good` or `great` are not set, then the `lev` argument controls the * quality of item. See the function itself for the specifics of the * calculations involved. */ void apply_magic(object_type *o_ptr, int lev, bool allow_artifacts, bool good, bool great) { int power = 0; /*u32b xtra = 0;*/ /*bool new = FALSE;*/ /* Chance of being `good` and `great` */ int good_chance = (lev+2) * 3; int great_chance = MIN(lev/4 + lev, 50); /* Limit depth */ if (lev > MAX_DEPTH - 1) lev = MAX_DEPTH - 1; /* Roll for "good" */ if (good || (randint0(100) < good_chance)) { /* Assume "good" */ power = 1; /* Roll for "great" */ if (great || (randint0(100) < great_chance)) power = 2; } /* Roll for "cursed" */ else if (randint0(100) < good_chance) { /* Assume "cursed" */ power = -1; /* Roll for "broken" */ if (randint0(100) < great_chance) power = -2; } /* Roll for artifact creation */ if (allow_artifacts) { int i; int rolls = 0; /* Get one roll if excellent */ if (power >= 2) rolls = 1; /* Get four rolls if forced great */ if (great) rolls = 4; /* Roll for artifacts if allowed */ for (i = 0; i < rolls; i++) { if (make_artifact(o_ptr)) return; } } /* Apply magic */ switch (o_ptr->tval) { case TV_DIGGING: case TV_HAFTED: case TV_POLEARM: case TV_SWORD: case TV_BOW: case TV_SHOT: case TV_ARROW: case TV_BOLT: { if (power == 2 || power == -2) { int ego_power; ego_power = make_ego_item(o_ptr, lev, (bool)(power > 0)); if (ego_power) power = ego_power; } if (power) a_m_aux_1(o_ptr, lev, power); break; } case TV_DRAG_ARMOR: case TV_HARD_ARMOR: case TV_SOFT_ARMOR: case TV_SHIELD: case TV_HELM: case TV_CROWN: case TV_CLOAK: case TV_GLOVES: case TV_BOOTS: { if (power == 2 || power == -2) { int ego_power; ego_power = make_ego_item(o_ptr, lev, (bool)(power > 0)); if (ego_power) power = ego_power; } if (power) a_m_aux_2(o_ptr, lev, power); break; } case TV_RING: case TV_AMULET: { if (!power && (randint0(100) < 50)) power = -1; a_m_aux_3(o_ptr, lev, power); break; } case TV_LIGHT: { if (power == 2 || power == -2) make_ego_item(o_ptr, lev, (bool)(power > 0)); /* Fuel it */ a_m_aux_4(o_ptr, lev, power); break; } default: { a_m_aux_4(o_ptr, lev, power); break; } } /* Hack -- analyze ego-items */ if (o_ptr->name2) { ego_item_type *e_ptr = &e_info[o_ptr->name2]; bitflag flags[OF_SIZE]; object_flags(o_ptr, flags); /* Extra powers */ if (e_ptr->xtra == OBJECT_XTRA_TYPE_SUSTAIN) of_on(o_ptr->flags, get_new_attr(flags, ego_sustains, N_ELEMENTS(ego_sustains))); else if (e_ptr->xtra == OBJECT_XTRA_TYPE_RESIST) of_on(o_ptr->flags, get_new_attr(flags, ego_resists, N_ELEMENTS(ego_resists))); else if (e_ptr->xtra == OBJECT_XTRA_TYPE_POWER) of_on(o_ptr->flags, get_new_attr(flags, ego_powers, N_ELEMENTS(ego_powers))); /* Hack -- acquire "cursed" flags */ if (cursed_p(e_ptr)) { bitflag curse_flags[OF_SIZE]; of_copy(curse_flags, e_ptr->flags); flags_mask(curse_flags, OF_SIZE, OF_CURSE_MASK, FLAG_END); of_union(o_ptr->flags, curse_flags); } /* Hack -- apply extra penalties if needed */ if (cursed_p(o_ptr)) { /* Apply extra ego bonuses */ o_ptr->to_h -= randcalc(e_ptr->to_h, lev, RANDOMISE); o_ptr->to_d -= randcalc(e_ptr->to_d, lev, RANDOMISE); o_ptr->to_a -= randcalc(e_ptr->to_a, lev, RANDOMISE); /* Apply ego pval */ o_ptr->pval -= randcalc(e_ptr->pval, lev, RANDOMISE); /* Apply minimums */ if (o_ptr->to_h > -1 * e_ptr->min_to_h) o_ptr->to_h = -1 * e_ptr->min_to_h; if (o_ptr->to_d > -1 * e_ptr->min_to_d) o_ptr->to_d = -1 * e_ptr->min_to_d; if (o_ptr->to_a > -1 * e_ptr->min_to_a) o_ptr->to_a = -1 * e_ptr->min_to_a; if (o_ptr->pval > -1 * e_ptr->min_pval) o_ptr->pval = -1 * e_ptr->min_pval; } /* Hack -- apply extra bonuses if needed */ else { /* Apply extra ego bonuses */ o_ptr->to_h += randcalc(e_ptr->to_h, lev, RANDOMISE); o_ptr->to_d += randcalc(e_ptr->to_d, lev, RANDOMISE); o_ptr->to_a += randcalc(e_ptr->to_a, lev, RANDOMISE); /* Apply ego pval */ o_ptr->pval += randcalc(e_ptr->pval, lev, RANDOMISE); /* Apply minimums */ if (o_ptr->to_h < e_ptr->min_to_h) o_ptr->to_h = e_ptr->min_to_h; if (o_ptr->to_d < e_ptr->min_to_d) o_ptr->to_d = e_ptr->min_to_d; if (o_ptr->to_a < e_ptr->min_to_a) o_ptr->to_a = e_ptr->min_to_a; if (o_ptr->pval < e_ptr->min_pval) o_ptr->pval = e_ptr->min_pval; } /* Hack -- apply rating bonus */ rating += e_ptr->rating; /* Cheat -- describe the item */ if (OPT(cheat_peek)) object_mention(o_ptr); /* Done */ return; } /* Examine real objects */ if (o_ptr->k_idx) { object_kind *k_ptr = &k_info[o_ptr->k_idx]; /* Hack -- acquire "cursed" flag */ if (cursed_p(k_ptr)) { bitflag curse_flags[OF_SIZE]; of_copy(curse_flags, k_ptr->flags); flags_mask(curse_flags, OF_SIZE, OF_CURSE_MASK, FLAG_END); of_union(o_ptr->flags, curse_flags); } } }
/** * Applying magic to an object, which includes creating ego-items, and applying * random bonuses, * * The `good` and `great` arguments affect the number of affixes on the item. * Setting `allow_artifacts` to TRUE allows artifacts to be created here - * this is used if we call directly with a pre-specified object kind; it is * not used if we come via make_object. * * If `good` or `great` are not set, then the `lev` argument controls the * number of affixes on the item. * * Returns the number of affixes on the object: 0 for a normal object, * MAX_AFFIXES+1 for an artifact. */ s16b apply_magic(object_type *o_ptr, int lev, bool allow_artifacts, bool good, bool great) { int i, max_lev = 3, min_lev = 1, affixes; bool art = FALSE; /* Set the number and quality of affixes this item will have */ if (randint0(100) < 20 + lev) max_lev++; if (great || (good && one_in_(4))) max_lev++; if (great || good || randint0(100) < 10 + lev) min_lev++; if (great) min_lev++; affixes = randint0(3 + lev / 25); if (great) affixes += 2 + randint1(2); else if (good) affixes += randint1(2); if (of_has(o_ptr->flags, OF_GOOD)) affixes--; if (affixes > MAX_AFFIXES) affixes = MAX_AFFIXES; /* Roll for artifact creation - n.b. this is now only used if we were called directly and not via make_object */ if (allow_artifacts) { if (great && one_in_(ART_GREAT)) art = TRUE; else if (max_lev > 3 && one_in_(ART_GOOD)) art = TRUE; else if (one_in_(ART_NORMAL)) art = TRUE; if (art && make_artifact(o_ptr, lev)) return MAX_AFFIXES + 1; } /* Generate and apply affixes, stopping if we acquire a theme */ for (i = 0; i < affixes && !o_ptr->theme; i++) obj_add_affix(o_ptr, lev, max_lev, min_lev); /* Apply special-case magic */ switch (o_ptr->tval) { case TV_RING: if (o_ptr->sval == SV_RING_SPEED) { /* Super-charge the ring */ while (one_in_(2)) o_ptr->pval[which_pval(o_ptr, OF_SPEED)]++; } break; case TV_CHEST: /* Skip ruined chests */ if (o_ptr->kind->level <= 0) break; /* Pick a difficulty */ o_ptr->extent = randint1(o_ptr->kind->level); /* Never exceed difficulty of 55 to 59 */ if (o_ptr->extent > 55) o_ptr->extent = (s16b)(55 + randint0(5)); break; } return affixes; }