/** * Deletes the monster, if any, at the given location. */ void delete_monster(int y, int x) { assert(cave_in_bounds(cave, y, x)); /* Delete the monster (if any) */ if (cave->m_idx[y][x] > 0) delete_monster_idx(cave->m_idx[y][x]); }
/* Places a trap. All traps are untyped until discovered. */ void place_trap(struct cave *c, int y, int x) { assert(cave_in_bounds(c, y, x)); assert(cave_isempty(c, y, x)); /* Place an invisible trap */ cave_set_feat(c, y, x, FEAT_INVIS); }
/** * Attempts to place a monster of the given race at the given location. * * If `sleep` is true, the monster is placed with its default sleep value, * which is given in monster.txt. * * `origin` is the item origin to use for any monster drops (e.g. ORIGIN_DROP, * ORIGIN_DROP_PIT, etc.) * * To give the player a sporting chance, some especially dangerous * monsters are marked as "FORCE_SLEEP" in monster.txt, which will * cause them to be placed with low energy. This helps ensure that * if such a monster suddenly appears in line-of-sight (due to a * summon, for instance), the player gets a chance to move before * they do. * * This routine refuses to place out-of-depth "FORCE_DEPTH" monsters. * * This is the only function which may place a monster in the dungeon, * except for the savefile loading code, which calls place_monster() * directly. */ static bool place_new_monster_one(int y, int x, monster_race *race, bool sleep, byte origin) { int i; struct monster *mon; struct monster monster_body; assert(cave_in_bounds(cave, y, x)); assert(race && race->name); /* Require empty space */ if (!cave_isempty(cave, y, x)) return (FALSE); /* No creation on glyph of warding */ if (cave_iswarded(cave, y, x)) return FALSE; /* "unique" monsters must be "unique" */ if (rf_has(race->flags, RF_UNIQUE) && race->cur_num >= race->max_num) return (FALSE); /* Depth monsters may NOT be created out of depth */ if (rf_has(race->flags, RF_FORCE_DEPTH) && p_ptr->depth < race->level) return (FALSE); /* Add to level feeling */ cave->mon_rating += race->power / 20; /* Check out-of-depth-ness */ if (race->level > p_ptr->depth) { if (rf_has(race->flags, RF_UNIQUE)) { /* OOD unique */ if (OPT(cheat_hear)) msg("Deep unique (%s).", race->name); } else { /* Normal monsters but OOD */ if (OPT(cheat_hear)) msg("Deep monster (%s).", race->name); } /* Boost rating by power per 10 levels OOD */ cave->mon_rating += (race->level - p_ptr->depth) * race->power / 200; } /* Note uniques for cheaters */ else if (rf_has(race->flags, RF_UNIQUE) && OPT(cheat_hear)) msg("Unique (%s).", race->name); /* Get local monster */ mon = &monster_body; /* Clean out the monster */ (void)WIPE(mon, monster_type); /* Save the race */ mon->race = race; /* Enforce sleeping if needed */ if (sleep && race->sleep) { int val = race->sleep; mon->m_timed[MON_TMD_SLEEP] = ((val * 2) + randint1(val * 10)); } /* Uniques get a fixed amount of HP */ if (rf_has(race->flags, RF_UNIQUE)) mon->maxhp = race->avg_hp; else { mon->maxhp = mon_hp(race, RANDOMISE); mon->maxhp = MAX(mon->maxhp, 1); } /* And start out fully healthy */ mon->hp = mon->maxhp; /* Extract the monster base speed */ mon->mspeed = race->speed; /* Hack -- small racial variety */ if (!rf_has(race->flags, RF_UNIQUE)) { /* Allow some small variation per monster */ i = extract_energy[race->speed] / 10; if (i) mon->mspeed += rand_spread(0, i); } /* Give a random starting energy */ mon->energy = (byte)randint0(50); /* Force monster to wait for player */ if (rf_has(race->flags, RF_FORCE_SLEEP)) mon->mflag |= (MFLAG_NICE); /* Radiate light? */ if (rf_has(race->flags, RF_HAS_LIGHT)) p_ptr->update |= PU_UPDATE_VIEW; /* Is this obviously a monster? (Mimics etc. aren't) */ if (rf_has(race->flags, RF_UNAWARE)) mon->unaware = TRUE; else mon->unaware = FALSE; /* Set the color if necessary */ if (rf_has(race->flags, RF_ATTR_RAND)) mon->attr = randint1(BASIC_COLORS - 1); /* Place the monster in the dungeon */ if (!place_monster(y, x, mon, origin)) return (FALSE); /* Success */ return (TRUE); }
/** * 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(int y, int x, monster_type *mon, byte origin) { s16b m_idx; monster_type *m_ptr; assert(cave_in_bounds(cave, y, x)); assert(!cave_monster_at(cave, y, x)); /* Get a new record */ m_idx = mon_pop(); if (!m_idx) return 0; /* Copy the monster */ m_ptr = cave_monster(cave, m_idx); COPY(m_ptr, mon, monster_type); /* Set the ID */ m_ptr->midx = m_idx; /* Set the location */ cave->m_idx[y][x] = m_ptr->midx; m_ptr->fy = y; m_ptr->fx = x; assert(cave_monster_at(cave, y, x) == m_ptr); update_mon(m_ptr, TRUE); /* Hack -- Count the number of "reproducers" */ if (rf_has(m_ptr->race->flags, RF_MULTIPLY)) num_repro++; /* Count racial occurrences */ m_ptr->race->cur_num++; /* Create the monster's drop, if any */ if (origin) (void)mon_create_drop(m_ptr, origin); /* Make mimics start mimicking */ if (origin && m_ptr->race->mimic_kinds) { object_type *i_ptr; object_type object_type_body; object_kind *kind = m_ptr->race->mimic_kinds->kind; struct monster_mimic *mimic_kind; int i = 1; /* Pick a random object kind to mimic */ for (mimic_kind = m_ptr->race->mimic_kinds; mimic_kind; mimic_kind = mimic_kind->next, i++) { if (one_in_(i)) kind = mimic_kind->kind; } i_ptr = &object_type_body; if (kind->tval == TV_GOLD) { make_gold(i_ptr, p_ptr->depth, kind->sval); } else { object_prep(i_ptr, kind, m_ptr->race->level, RANDOMISE); apply_magic(i_ptr, m_ptr->race->level, TRUE, FALSE, FALSE, FALSE); i_ptr->number = 1; } i_ptr->origin = origin; i_ptr->mimicking_m_idx = m_idx; m_ptr->mimicked_o_idx = floor_carry(cave, y, x, i_ptr); } /* Result */ return m_idx; }