/* 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 group of monsters of race `r_idx` around * the given location. The number of monsters to place is `total`. * * 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.) */ static bool place_new_monster_group(struct cave *c, int y, int x, monster_race *r_ptr, bool sleep, int total, byte origin) { int n, i; int hack_n; /* x and y coordinates of the placed monsters */ byte hack_y[GROUP_MAX]; byte hack_x[GROUP_MAX]; assert(r_ptr); /* Start on the monster */ hack_n = 1; hack_x[0] = x; hack_y[0] = y; /* Puddle monsters, breadth first, up to total */ for (n = 0; (n < hack_n) && (hack_n < total); n++) { /* Grab the location */ int hx = hack_x[n]; int hy = hack_y[n]; /* Check each direction, up to total */ for (i = 0; (i < 8) && (hack_n < total); i++) { int mx = hx + ddx_ddd[i]; int my = hy + ddy_ddd[i]; /* Walls and Monsters block flow */ if (!cave_isempty(cave, my, mx)) continue; /* Attempt to place another monster */ if (place_new_monster_one(my, mx, r_ptr, sleep, origin)) { /* Add it to the "hack" set */ hack_y[hack_n] = my; hack_x[hack_n] = mx; hack_n++; } } } /* Success */ return (TRUE); }
/** * Picks a monster race, makes a new monster of that race, then attempts to * place it in the dungeon at least `dis` away from the player. The monster * race chosen will be appropriate for dungeon level equal to `depth`. * * If `sleep` is true, the monster is placed with its default sleep value, * which is given in monster.txt. * * Returns TRUE if we successfully place a monster. */ bool pick_and_place_distant_monster(struct cave *c, struct loc loc, int dis, bool sleep, int depth) { int py = loc.y; int px = loc.x; int y = 0, x = 0; int attempts_left = 10000; assert(c); /* Find a legal, distant, unoccupied, space */ while (--attempts_left) { /* Pick a location */ y = randint0(c->height); x = randint0(c->width); /* Require "naked" floor grid */ if (!cave_isempty(c, y, x)) continue; /* Accept far away grids */ if (distance(y, x, py, px) > dis) break; } if (!attempts_left) { if (OPT(cheat_xtra) || OPT(cheat_hear)) msg("Warning! Could not allocate a new monster."); return FALSE; } /* Attempt to place the monster, allow groups */ if (pick_and_place_monster(c, y, x, depth, sleep, TRUE, ORIGIN_DROP)) return (TRUE); /* Nope */ return (FALSE); }
/* * Summon a creature of the specified type * * This function is rather dangerous XXX XXX XXX */ static void do_cmd_wiz_named(monster_race *r, bool slp) { int py = p_ptr->py; int px = p_ptr->px; int i, x, y; /* Paranoia */ assert(r); /* Try 10 times */ for (i = 0; i < 10; i++) { int d = 1; /* Pick a location */ scatter(&y, &x, py, px, d, TRUE); /* Require empty grids */ if (!cave_isempty(cave, y, x)) continue; /* Place it (allow groups) */ if (place_new_monster(cave, y, x, r, slp, TRUE, ORIGIN_DROP_WIZARD)) break; } }
/** * 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); }