/** * Creates the onbject a mimic is imitating. */ void mon_create_mimicked_object(struct chunk *c, struct monster *mon, int index) { struct object *obj; struct object_kind *kind = mon->race->mimic_kinds->kind; struct monster_mimic *mimic_kind; int i = 1; bool dummy = true; /* Pick a random object kind to mimic */ for (mimic_kind = mon->race->mimic_kinds; mimic_kind; mimic_kind = mimic_kind->next, i++) { if (one_in_(i)) { kind = mimic_kind->kind; } } if (tval_is_money_k(kind)) { obj = make_gold(player->depth, kind->name); } else { obj = object_new(); object_prep(obj, kind, mon->race->level, RANDOMISE); apply_magic(obj, mon->race->level, true, false, false, false); obj->number = 1; obj->origin = ORIGIN_DROP_MIMIC; obj->origin_depth = player->depth; } obj->mimicking_m_idx = index; mon->mimicked_obj = obj; /* Put the object on the floor if it goes, otherwise no mimicry */ if (floor_carry(c, mon->fy, mon->fx, obj, &dummy)) { list_object(c, obj); } else { /* Clear the mimicry */ obj->mimicking_m_idx = 0; mon->mimicked_obj = NULL; /* Give the object to the monster if appropriate */ if (rf_has(mon->race->flags, RF_MIMIC_INV)) { monster_carry(c, mon, obj); } else { /* Otherwise delete the mimicked object */ object_delete(&obj); } } }
/** * 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++) { struct object_kind *kind = &k_info[i]; /* Skip empty objects, unseen objects, and incorrect tvals */ if (!kind->name || kind->tval != tval) continue; if (!kind->aware) { /* can unaware ignore anything */ choice[num].kind = kind; choice[num++].aware = false; } if ((kind->everseen && !kf_has(kind->kind_flags, KF_INSTA_ART)) || tval_is_money_k(kind)) { /* 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 = kind; choice[num++].aware = true; } } if (num == 0) mem_free(choice); else *ch = choice; return num; }
/** * Attempts to place a copy of the given monster at the given position in * the dungeon. * * All of the monster placement routines eventually call this function. This * is what actually puts the monster in the dungeon (i.e., it notifies the cave * and sets the monsters position). The dungeon loading code also calls this * function directly. * * `origin` is the item origin to use for any monster drops (e.g. ORIGIN_DROP, * ORIGIN_DROP_PIT, etc.) The dungeon loading code calls this with origin = 0, * which prevents the monster's drops from being generated again. * * Returns the m_idx of the newly copied monster, or 0 if the placement fails. */ s16b place_monster(struct chunk *c, int y, int x, struct monster *mon, byte origin) { s16b m_idx; struct monster *new_mon; assert(square_in_bounds(c, y, x)); assert(!square_monster(c, y, x)); /* Get a new record */ m_idx = mon_pop(c); if (!m_idx) return 0; /* Copy the monster */ new_mon = cave_monster(c, m_idx); memcpy(new_mon, mon, sizeof(struct monster)); /* Set the ID */ new_mon->midx = m_idx; /* Set the location */ c->squares[y][x].mon = new_mon->midx; new_mon->fy = y; new_mon->fx = x; assert(square_monster(c, y, x) == new_mon); update_mon(new_mon, c, true); /* Hack -- Count the number of "reproducers" */ if (rf_has(new_mon->race->flags, RF_MULTIPLY)) num_repro++; /* Count racial occurrences */ new_mon->race->cur_num++; /* Create the monster's drop, if any */ if (origin) (void)mon_create_drop(c, new_mon, origin); /* Make mimics start mimicking */ if (origin && new_mon->race->mimic_kinds) { struct object *obj; struct object_kind *kind = new_mon->race->mimic_kinds->kind; struct monster_mimic *mimic_kind; int i = 1; /* Pick a random object kind to mimic */ for (mimic_kind = new_mon->race->mimic_kinds; mimic_kind; mimic_kind = mimic_kind->next, i++) { if (one_in_(i)) kind = mimic_kind->kind; } if (tval_is_money_k(kind)) { obj = make_gold(player->depth, kind->name); } else { obj = object_new(); object_prep(obj, kind, new_mon->race->level, RANDOMISE); apply_magic(obj, new_mon->race->level, true, false, false, false); obj->number = 1; obj->origin = ORIGIN_DROP_MIMIC; obj->origin_depth = player->depth; } obj->mimicking_m_idx = m_idx; new_mon->mimicked_obj = obj; /* Put the object on the floor if it goes, otherwise no mimicry */ if (floor_carry(c, y, x, obj, false)) { list_object(c, obj); } else { /* Clear the mimicry */ obj->mimicking_m_idx = 0; new_mon->mimicked_obj = NULL; /* Give the object to the monster if appropriate */ if (rf_has(new_mon->race->flags, RF_MIMIC_INV)) { monster_carry(c, new_mon, obj); } else { /* Otherwise delete the mimicked object */ object_delete(&obj); } } } /* Result */ return m_idx; }