/** * Generate a random level. * * Confusingly, this function also generate the town level (level 0). */ public static void cave_generate(Cave c, Player.Player p) { string error = "no generation"; Misc.assert(c != null); c.depth = p.depth; /* Generate */ for (int tries = 0; tries < 100 && error != null; tries++) { dun_data dun_body = new dun_data(); error = null; cave_clear(c, p); /* Mark the dungeon as being unready (to avoid artifact loss, etc) */ Player.Player.character_dungeon = false; /* Allocate global data (will be freed when we leave the loop) */ dun = dun_body; clear_dun_data(dun); if (p.depth == 0) { dun.profile = town_profile; dun.profile.builder(c, p); } else { int perc = Random.randint0(100); int last = Cave.NUM_CAVE_PROFILES - 1; int i; for (i = 0; i < NUM_CAVE_PROFILES; i++) { bool ok; cave_profile profile; profile = dun.profile = cave_profiles[i]; if (i < last && profile.cutoff < perc) continue; ok = dun.profile.builder(c, p); if (ok) break; } } /* Ensure quest monsters */ if (is_quest(c.depth)) { int i; for (i = 1; i < Misc.z_info.r_max; i++) { Monster_Race r_ptr = Misc.r_info[i]; if(r_ptr == null) continue; int y, x; /* The monster must be an unseen quest monster of this depth. */ if (r_ptr.cur_num > 0) continue; if (!r_ptr.flags.has(Monster_Flag.QUESTOR.value)) continue; if (r_ptr.level != c.depth) continue; /* Pick a location and place the monster */ find_empty(c, out y, out x); Monster_Make.place_new_monster(c, y, x, i, true, true, Object.Origin.DROP); } } /* Place dungeon squares to trigger feeling */ place_feeling(c); c.feeling = (byte)(calc_obj_feeling(c) + calc_mon_feeling(c)); /* Regenerate levels that overflow their maxima */ if (Misc.o_max >= Misc.z_info.o_max) error = "too many objects"; if (Cave.cave_monster_max(cave) >= Misc.z_info.m_max) error = "too many monsters"; if (error != null) ROOM_LOG("Generation restarted: " + error + "."); } //FREE(cave_squares); cave_squares = null; if (error != null) Utilities.quit("cave_generate() failed 100 times!"); /* The dungeon is ready */ Player.Player.character_dungeon = true; c.created_at = Misc.turn; }
static void clear_dun_data(dun_data d) { int bx, by; for (by = 0; by < MAX_ROOMS_ROW; by++) { for (bx = 0; bx < MAX_ROOMS_COL; bx++) { d.room_map[by, bx] = false; } } }