static enum parser_error parse_prefs_q(struct parser *p) { struct prefs_data *d = parser_priv(p); assert(d != NULL); if (d->bypass) return PARSE_ERROR_NONE; if (parser_hasval(p, "sval") && parser_hasval(p, "flag")) { object_kind *kind; int tvi, svi, idx; tvi = tval_find_idx(parser_getsym(p, "n")); if (tvi < 0) return PARSE_ERROR_UNRECOGNISED_TVAL; svi = lookup_sval(tvi, parser_getsym(p, "sval")); if (svi < 0) return PARSE_ERROR_UNRECOGNISED_SVAL; idx = lookup_kind(tvi, svi); if (idx < 0) return PARSE_ERROR_UNRECOGNISED_SVAL; kind = &k_info[idx]; kind->squelch = parser_getint(p, "flag"); } return PARSE_ERROR_NONE; }
static enum parser_error parse_r_drop(struct parser *p) { struct monster_race *r = parser_priv(p); struct monster_drop *d; int tval, sval; if (!r) return PARSE_ERROR_MISSING_RECORD_HEADER; tval = tval_find_idx(parser_getsym(p, "tval")); if (tval < 0) return PARSE_ERROR_UNRECOGNISED_TVAL; sval = lookup_sval(tval, parser_getsym(p, "sval")); if (sval < 0) return PARSE_ERROR_UNRECOGNISED_SVAL; if (parser_getuint(p, "min") > 99 || parser_getuint(p, "max") > 99) return PARSE_ERROR_INVALID_ITEM_NUMBER; d = mem_zalloc(sizeof *d); d->kind = objkind_get(tval, sval); d->percent_chance = parser_getuint(p, "chance"); d->min = parser_getuint(p, "min"); d->max = parser_getuint(p, "max"); d->next = r->drops; r->drops = d; return PARSE_ERROR_NONE; }
static enum parser_error parse_prefs_k(struct parser *p) { int tvi, svi, idx; object_kind *kind; struct prefs_data *d = parser_priv(p); assert(d != NULL); if (d->bypass) return PARSE_ERROR_NONE; tvi = tval_find_idx(parser_getsym(p, "tval")); if (tvi < 0) return PARSE_ERROR_UNRECOGNISED_TVAL; svi = lookup_sval(tvi, parser_getsym(p, "sval")); if (svi < 0) return PARSE_ERROR_UNRECOGNISED_SVAL; idx = lookup_kind(tvi, svi); if (idx < 0) return PARSE_ERROR_UNRECOGNISED_SVAL; kind = &k_info[idx]; kind->x_attr = (byte) parser_getint(p, "attr"); kind->x_char = (wchar_t) parser_getint(p, "char"); return PARSE_ERROR_NONE; }
static enum parser_error parse_r_mimic(struct parser *p) { struct monster_race *r = parser_priv(p); int tval, sval; object_kind *kind; if (!r) return PARSE_ERROR_MISSING_RECORD_HEADER; tval = tval_find_idx(parser_getsym(p, "tval")); if (tval < 0) return PARSE_ERROR_UNRECOGNISED_TVAL; sval = lookup_sval(tval, parser_getsym(p, "sval")); if (sval < 0) return PARSE_ERROR_UNRECOGNISED_SVAL; kind = objkind_get(tval, sval); if (!kind) return PARSE_ERROR_GENERIC; r->mimic_kind = kind; return PARSE_ERROR_NONE; }
static enum parser_error parse_always(struct parser *p) { struct store *s = parser_priv(p); int tval = tval_find_idx(parser_getsym(p, "tval")); int sval = lookup_sval(tval, parser_getsym(p, "sval")); object_kind *kind = lookup_kind(tval, sval); if (!kind) return PARSE_ERROR_UNRECOGNISED_SVAL; /* Expand if necessary */ if (!s->always_num) { s->always_size = 8; s->always_table = mem_zalloc(s->always_size * sizeof *s->always_table); } else if (s->always_num >= s->always_size) { s->always_size += 8; s->always_table = mem_realloc(s->always_table, s->always_size * sizeof *s->always_table); } s->always_table[s->always_num++] = kind; return PARSE_ERROR_NONE; }
/** * 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; }
/** * Format the object name so that the prefix is right aligned to a common * column. * * This uses the default logic of object_desc() in order to handle flavors, * artifacts, vowels and so on. It was easier to do this and then use strtok() * to break it up than to do anything else. * * \param entry is the object list entry that has a name to be formatted. * \param line_buffer is the buffer to format into. * \param size is the size of line_buffer. */ void object_list_format_name(const object_list_entry_t *entry, char *line_buffer, size_t size) { char name[80]; const char *chunk; char *source; bool has_singular_prefix; bool los = false; int field; byte old_number; struct loc pgrid = player->grid; struct object *base_obj; struct loc grid; bool object_is_recognized_artifact; if (entry == NULL || entry->object == NULL || entry->object->kind == NULL) return; base_obj = cave->objects[entry->object->oidx]; grid = entry->object->grid; object_is_recognized_artifact = object_is_known_artifact(base_obj); /* Hack - these don't have a prefix when there is only one, so just pad * with a space. */ switch (entry->object->kind->tval) { case TV_SOFT_ARMOR: if (object_is_recognized_artifact) has_singular_prefix = true; else if (base_obj->kind->sval == lookup_sval(TV_SOFT_ARMOR, "Robe")) has_singular_prefix = true; else has_singular_prefix = false; break; case TV_HARD_ARMOR: case TV_DRAG_ARMOR: if (object_is_recognized_artifact) has_singular_prefix = true; else has_singular_prefix = false; break; default: has_singular_prefix = true; break; } if (entry->object->kind != base_obj->kind) has_singular_prefix = true; /* Work out if the object is in view */ los = projectable(cave, pgrid, grid, PROJECT_NONE) || loc_eq(grid, pgrid); field = los ? OBJECT_LIST_SECTION_LOS : OBJECT_LIST_SECTION_NO_LOS; /* * Because each entry points to a specific object and not something more * general, the number of similar objects we counted has to be swapped in. * This isn't an ideal way to do this, but it's the easiest way until * object_desc is more flexible. */ old_number = entry->object->number; entry->object->number = entry->count[field]; object_desc(name, sizeof(name), base_obj, ODESC_PREFIX | ODESC_FULL); entry->object->number = old_number; /* The source string for strtok() needs to be set properly, depending on * when we use it. */ if (!has_singular_prefix && entry->count[field] == 1) { chunk = " "; source = name; } else { chunk = strtok(name, " "); source = NULL; } /* Right alight the prefix and clip. */ strnfmt(line_buffer, size, "%3.3s ", chunk); /* Get the rest of the name and clip it to fit the max width. */ chunk = strtok(source, "\0"); my_strcat(line_buffer, chunk, size); }
/** * Read an object. */ static struct object *rd_item(void) { struct object *obj = object_new(); byte tmp8u; u16b tmp16u; byte effect; size_t i; char buf[128]; byte ver = 1; rd_u16b(&tmp16u); rd_byte(&ver); if (tmp16u != 0xffff) return NULL; rd_u16b(&obj->oidx); /* Location */ rd_byte(&obj->iy); rd_byte(&obj->ix); /* Type/Subtype */ rd_string(buf, sizeof(buf)); if (buf[0]) { obj->tval = tval_find_idx(buf); } rd_string(buf, sizeof(buf)); if (buf[0]) { obj->sval = lookup_sval(obj->tval, buf); } rd_s16b(&obj->pval); rd_byte(&obj->number); rd_s16b(&obj->weight); rd_string(buf, sizeof(buf)); if (buf[0]) { obj->artifact = lookup_artifact_name(buf); if (!obj->artifact) { note(format("Couldn't find artifact %s!", buf)); return NULL; } } rd_string(buf, sizeof(buf)); if (buf[0]) { obj->ego = lookup_ego_item(buf, obj->tval, obj->sval); if (!obj->ego) { note(format("Couldn't find ego item %s!", buf)); return NULL; } } rd_byte(&effect); rd_s16b(&obj->timeout); rd_s16b(&obj->to_h); rd_s16b(&obj->to_d); rd_s16b(&obj->to_a); rd_s16b(&obj->ac); rd_byte(&obj->dd); rd_byte(&obj->ds); rd_byte(&obj->origin); rd_byte(&obj->origin_depth); rd_string(buf, sizeof(buf)); if (buf[0]) { obj->origin_race = lookup_monster(buf); } rd_byte(&obj->notice); for (i = 0; i < of_size; i++) rd_byte(&obj->flags[i]); for (i = 0; i < obj_mod_max; i++) { rd_s16b(&obj->modifiers[i]); } /* Read brands */ rd_byte(&tmp8u); if (tmp8u) { obj->brands = mem_zalloc(z_info->brand_max * sizeof(bool)); for (i = 0; i < brand_max; i++) { rd_byte(&tmp8u); obj->brands[i] = tmp8u ? true : false; } } /* Read slays */ rd_byte(&tmp8u); if (tmp8u) { obj->slays = mem_zalloc(z_info->slay_max * sizeof(bool)); for (i = 0; i < slay_max; i++) { rd_byte(&tmp8u); obj->slays[i] = tmp8u ? true : false; } } /* Read curses */ rd_byte(&tmp8u); if (tmp8u) { obj->curses = mem_zalloc(z_info->curse_max * sizeof(struct curse_data)); for (i = 0; i < curse_max; i++) { rd_byte(&tmp8u); obj->curses[i].power = tmp8u; rd_u16b(&tmp16u); obj->curses[i].timeout = tmp16u; } } for (i = 0; i < elem_max; i++) { rd_s16b(&obj->el_info[i].res_level); rd_byte(&obj->el_info[i].flags); } /* Monster holding object */ rd_s16b(&obj->held_m_idx); rd_s16b(&obj->mimicking_m_idx); /* Activation */ rd_u16b(&tmp16u); if (tmp16u) obj->activation = &activations[tmp16u]; rd_u16b(&tmp16u); obj->time.base = tmp16u; rd_u16b(&tmp16u); obj->time.dice = tmp16u; rd_u16b(&tmp16u); obj->time.sides = tmp16u; /* Save the inscription */ rd_string(buf, sizeof(buf)); if (buf[0]) obj->note = quark_add(buf); /* Lookup item kind */ obj->kind = lookup_kind(obj->tval, obj->sval); /* Check we have a kind */ if ((!obj->tval && !obj->sval) || !obj->kind) { object_delete(&obj); return NULL; } /* Set effect */ if (effect && obj->ego) obj->effect = obj->ego->effect; if (effect && !obj->effect) obj->effect = obj->kind->effect; /* Success */ return obj; }