/** * Lets the given monster attempt to reproduce. * * Note that "reproduction" REQUIRES empty space. * * Returns true if the monster successfully reproduced. */ bool multiply_monster(const struct monster *mon) { int i, y, x; bool result = false; /* Try up to 18 times */ for (i = 0; i < 18; i++) { int d = 1; /* Pick a location */ scatter(cave, &y, &x, mon->fy, mon->fx, d, true); /* Require an "empty" floor grid */ if (!square_isempty(cave, y, x)) continue; /* Create a new monster (awake, no groups) */ result = place_new_monster(cave, y, x, mon->race, false, false, ORIGIN_DROP_BREED); /* Done */ break; } /* Result */ return (result); }
/* * Summon a creature of the specified type * * This function is rather dangerous XXX XXX XXX */ static void do_cmd_wiz_named(int r_idx, bool slp) { int py = p_ptr->py; int px = p_ptr->px; int i, x, y; /* Paranoia */ if (!r_idx) return; if (r_idx >= z_info->r_max-1) return; /* Try 10 times */ for (i = 0; i < 10; i++) { int d = 1; /* Pick a location */ scatter(&y, &x, py, px, d, 0); /* Require empty grids */ if (!cave_empty_bold(y, x)) continue; /* Place it (allow groups) */ if (place_new_monster(cave, y, x, r_idx, slp, TRUE, ORIGIN_DROP_WIZARD)) break; } }
/** * Picks a monster race, makes a new monster of that race, then attempts to * place it in the dungeon. 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. * * If `group_okay` is true, we allow the placing of a group, if the chosen * monster appears with friends or an escort. * * `origin` is the item origin to use for any monster drops (e.g. ORIGIN_DROP, * ORIGIN_DROP_PIT, etc.) * * Returns TRUE if we successfully place a monster. */ bool pick_and_place_monster(struct cave *c, int y, int x, int depth, bool sleep, bool group_okay, byte origin) { /* Pick a monster race */ monster_race *race = get_mon_num(depth); if (!race) return (FALSE); /* Attempt to place the monster */ return (place_new_monster(c, y, x, race, sleep, group_okay, origin)); }
/** * Picks a monster race, makes a new monster of that race, then attempts to * place it in the dungeon. 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. * * If `group_okay` is true, we allow the placing of a group, if the chosen * monster appears with friends or an escort. * * `origin` is the item origin to use for any monster drops (e.g. ORIGIN_DROP, * ORIGIN_DROP_PIT, etc.) * * Returns true if we successfully place a monster. */ bool pick_and_place_monster(struct chunk *c, int y, int x, int depth, bool sleep, bool group_okay, byte origin) { /* Pick a monster race */ struct monster_race *race = get_mon_num(depth); if (race) { return place_new_monster(c, y, x, race, sleep, group_okay, origin); } else { return false; } }
/** * Picks a monster race, makes a new monster of that race, then attempts to * place it in the dungeon. 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. * * If `group_okay` is true, we allow the placing of a group, if the chosen * monster appears with friends or an escort. * * `origin` is the item origin to use for any monster drops (e.g. ORIGIN_DROP, * ORIGIN_DROP_PIT, etc.) * * Returns TRUE if we successfully place a monster. */ bool pick_and_place_monster(struct cave *c, int y, int x, int depth, bool sleep, bool group_okay, byte origin) { int r_idx; /* Pick a monster race */ r_idx = get_mon_num(depth); /* Handle failure */ if (!r_idx) return (FALSE); /* Attempt to place the monster */ return (place_new_monster(c, y, x, r_idx, sleep, group_okay, origin)); }
/* * 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; } }
/** * Places a monster (of the specified "type") near the given * location. Return the siummoned monster's level iff a monster was * actually summoned. * * We will attempt to place the monster up to 10 times before giving up. * * This function takes the "monster level" * of the summoning monster as a parameter, and use that, along with * the current dungeon level, to help determine the level of the * desired monster. Note that this is an upper bound, and also * tends to "prefer" monsters of that level. Currently, we use * the average of the dungeon and monster levels, and then add * five to allow slight increases in monster power. * * Note that we use the new "monster allocation table" creation code * to restrict the "get_mon_num()" function to the set of "legal" * monsters, making this function much faster and more reliable. * * Note that this function may not succeed, though this is very rare. */ int summon_specific(int y1, int x1, int lev, int type, bool delay, bool call) { int i, x = 0, y = 0; struct monster *mon; struct monster_race *race; /* Look for a location, allow up to 4 squares away */ for (i = 0; i < 60; ++i) { /* Pick a distance */ int d = (i / 15) + 1; /* Pick a location */ scatter(cave, &y, &x, y1, x1, d, true); /* Require "empty" floor grid */ if (!square_isempty(cave, y, x)) continue; /* No summon on glyphs */ if (square_iswarded(cave, y, x) || square_isdecoyed(cave, y, x)) { continue; } /* Okay */ break; } /* Failure */ if (i == 60) return (0); /* Save the "summon" type */ summon_specific_type = type; /* Use the new calling scheme if requested */ if (call && (type != summon_name_to_idx("UNIQUE")) && (type != summon_name_to_idx("WRAITH"))) { return (call_monster(y, x)); } /* Prepare allocation table */ get_mon_num_prep(summon_specific_okay); /* Pick a monster, using the level calculation */ race = get_mon_num((player->depth + lev) / 2 + 5); /* Prepare allocation table */ get_mon_num_prep(NULL); /* Handle failure */ if (!race) return (0); /* Attempt to place the monster (awake, don't allow groups) */ if (!place_new_monster(cave, y, x, race, false, false, ORIGIN_DROP_SUMMON)) return (0); /* Success, return the level of the monster */ mon = square_monster(cave, y, x); /* If delay, try to let the player act before the summoned monsters, * including slowing down faster monsters for one turn */ /* XXX should this now be hold monster for a turn? */ if (delay) { mon->energy = 0; if (mon->race->speed > player->state.speed) mon_inc_timed(mon, MON_TMD_SLOW, 1, MON_TMD_FLG_NOMESSAGE, false); } return (mon->race->level); }
/** * Generate a random level. * * Confusingly, this function also generate the town level (level 0). * \param c is the level we're going to end up with, in practice the global cave * \param p is the current player struct, in practice the global player */ void cave_generate(struct chunk **c, struct player *p) { const char *error = "no generation"; int y, x, tries = 0; struct chunk *chunk; assert(c); /* Generate */ for (tries = 0; tries < 100 && error; tries++) { struct dun_data dun_body; error = NULL; /* Mark the dungeon as being unready (to avoid artifact loss, etc) */ character_dungeon = FALSE; /* Allocate global data (will be freed when we leave the loop) */ dun = &dun_body; dun->cent = mem_zalloc(z_info->level_room_max * sizeof(struct loc)); dun->door = mem_zalloc(z_info->level_door_max * sizeof(struct loc)); dun->wall = mem_zalloc(z_info->wall_pierce_max * sizeof(struct loc)); dun->tunn = mem_zalloc(z_info->tunn_grid_max * sizeof(struct loc)); /* Choose a profile and build the level */ dun->profile = choose_profile(p->depth); chunk = dun->profile->builder(p); if (!chunk) { error = "Failed to find builder"; mem_free(dun->cent); mem_free(dun->door); mem_free(dun->wall); mem_free(dun->tunn); continue; } /* Ensure quest monsters */ if (is_quest(chunk->depth)) { int i; for (i = 1; i < z_info->r_max; i++) { monster_race *r_ptr = &r_info[i]; int y, x; /* The monster must be an unseen quest monster of this depth. */ if (r_ptr->cur_num > 0) continue; if (!rf_has(r_ptr->flags, RF_QUESTOR)) continue; if (r_ptr->level != chunk->depth) continue; /* Pick a location and place the monster */ find_empty(chunk, &y, &x); place_new_monster(chunk, y, x, r_ptr, TRUE, TRUE, ORIGIN_DROP); } } /* Clear generation flags. */ for (y = 0; y < chunk->height; y++) { for (x = 0; x < chunk->width; x++) { sqinfo_off(chunk->squares[y][x].info, SQUARE_WALL_INNER); sqinfo_off(chunk->squares[y][x].info, SQUARE_WALL_OUTER); sqinfo_off(chunk->squares[y][x].info, SQUARE_WALL_SOLID); sqinfo_off(chunk->squares[y][x].info, SQUARE_MON_RESTRICT); } } /* Regenerate levels that overflow their maxima */ if (cave_monster_max(chunk) >= z_info->level_monster_max) error = "too many monsters"; if (error) ROOM_LOG("Generation restarted: %s.", error); mem_free(dun->cent); mem_free(dun->door); mem_free(dun->wall); mem_free(dun->tunn); } if (error) quit_fmt("cave_generate() failed 100 times!"); /* Free the old cave, use the new one */ if (*c) cave_free(*c); *c = chunk; /* Place dungeon squares to trigger feeling (not in town) */ if (player->depth) place_feeling(*c); /* Save the town */ else if (!chunk_find_name("Town")) { struct chunk *town = chunk_write(0, 0, z_info->town_hgt, z_info->town_wid, FALSE, FALSE, FALSE); town->name = string_make("Town"); chunk_list_add(town); } (*c)->feeling = calc_obj_feeling(*c) + calc_mon_feeling(*c); /* Validate the dungeon (we could use more checks here) */ chunk_validate_objects(*c); /* The dungeon is ready */ character_dungeon = TRUE; /* Free old and allocate new known level */ if (cave_k) cave_free(cave_k); cave_k = cave_new(cave->height, cave->width); if (!cave->depth) cave_known(); (*c)->created_at = turn; }