dla.rs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. use super::{MapBuilder, Map,
  2. TileType, Position, spawner, SHOW_MAPGEN_VISUALIZER,
  3. remove_unreachable_areas_returning_most_distant, generate_voronoi_spawn_regions};
  4. use rltk::RandomNumberGenerator;
  5. use specs::prelude::*;
  6. use std::collections::HashMap;
  7. pub struct DLABuilder {
  8. map : Map,
  9. starting_position : Position,
  10. depth: i32,
  11. history: Vec<Map>,
  12. noise_areas : HashMap<i32, Vec<usize>>
  13. }
  14. impl MapBuilder for DLABuilder {
  15. fn get_map(&self) -> Map {
  16. self.map.clone()
  17. }
  18. fn get_starting_position(&self) -> Position {
  19. self.starting_position.clone()
  20. }
  21. fn get_snapshot_history(&self) -> Vec<Map> {
  22. self.history.clone()
  23. }
  24. fn build_map(&mut self) {
  25. self.build();
  26. }
  27. fn spawn_entities(&mut self, ecs : &mut World) {
  28. for area in self.noise_areas.iter() {
  29. spawner::spawn_region(ecs, area.1, self.depth);
  30. }
  31. }
  32. fn take_snapshot(&mut self) {
  33. if SHOW_MAPGEN_VISUALIZER {
  34. let mut snapshot = self.map.clone();
  35. for v in snapshot.revealed_tiles.iter_mut() {
  36. *v = true;
  37. }
  38. self.history.push(snapshot);
  39. }
  40. }
  41. }
  42. impl DLABuilder {
  43. pub fn new(new_depth : i32) -> DLABuilder {
  44. DLABuilder{
  45. map : Map::new(new_depth),
  46. starting_position : Position{ x: 0, y : 0 },
  47. depth : new_depth,
  48. history: Vec::new(),
  49. noise_areas : HashMap::new()
  50. }
  51. }
  52. #[allow(clippy::map_entry)]
  53. fn build(&mut self) {
  54. let mut rng = RandomNumberGenerator::new();
  55. // Carve a starting seed
  56. self.starting_position = Position{ x: self.map.width/2, y : self.map.height/2 };
  57. let start_idx = self.map.xy_idx(self.starting_position.x, self.starting_position.y);
  58. self.take_snapshot();
  59. self.map.tiles[start_idx] = TileType::Floor;
  60. self.map.tiles[start_idx-1] = TileType::Floor;
  61. self.map.tiles[start_idx+1] = TileType::Floor;
  62. self.map.tiles[start_idx-self.map.width as usize] = TileType::Floor;
  63. self.map.tiles[start_idx+self.map.width as usize] = TileType::Floor;
  64. // Random walker
  65. let total_tiles = self.map.width * self.map.height;
  66. let desired_floor_tiles = (total_tiles / 4) as usize;
  67. let mut floor_tile_count = self.map.tiles.iter().filter(|a| **a == TileType::Floor).count();
  68. while floor_tile_count < desired_floor_tiles {
  69. let mut digger_x = rng.roll_dice(1, self.map.width - 3) + 1;
  70. let mut digger_y = rng.roll_dice(1, self.map.height - 3) + 1;
  71. let mut prev_x = digger_x;
  72. let mut prev_y = digger_y;
  73. let mut digger_idx = self.map.xy_idx(digger_x, digger_y);
  74. while self.map.tiles[digger_idx] == TileType::Wall {
  75. prev_x = digger_x;
  76. prev_y = digger_y;
  77. let stagger_direction = rng.roll_dice(1, 4);
  78. match stagger_direction {
  79. 1 => { if digger_x > 2 { digger_x -= 1; } }
  80. 2 => { if digger_x < self.map.width-2 { digger_x += 1; } }
  81. 3 => { if digger_y > 2 { digger_y -=1; } }
  82. _ => { if digger_y < self.map.height-2 { digger_y += 1; } }
  83. }
  84. digger_idx = self.map.xy_idx(digger_x, digger_y);
  85. }
  86. let prev_idx = self.map.xy_idx(prev_x, prev_y);
  87. self.map.tiles[prev_idx] = TileType::Floor;
  88. self.take_snapshot();
  89. floor_tile_count = self.map.tiles.iter().filter(|a| **a == TileType::Floor).count();
  90. }
  91. // Find all tiles we can reach from the starting point
  92. let exit_tile = remove_unreachable_areas_returning_most_distant(&mut self.map, start_idx);
  93. self.take_snapshot();
  94. // Place the stairs
  95. self.map.tiles[exit_tile] = TileType::DownStairs;
  96. self.take_snapshot();
  97. // Now we build a noise map for use in spawning entities later
  98. self.noise_areas = generate_voronoi_spawn_regions(&self.map, &mut rng);
  99. }
  100. }