map.rs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. use rand::Rng;
  2. use specs::prelude::*;
  3. #[derive(PartialEq, Clone, Copy, Debug)]
  4. pub struct Cell {
  5. pub tile: TileType,
  6. pub seen: bool,
  7. }
  8. impl Cell {
  9. pub fn glyph(&self) -> carpet::CP437 {
  10. match self.tile {
  11. TileType::Wall => carpet::CP437::from_char('#'),
  12. TileType::Floor => carpet::CP437::from_u8(0),
  13. }
  14. }
  15. pub fn blocks_view(&self) -> bool {
  16. match self.tile {
  17. TileType::Wall => true,
  18. TileType::Floor => false,
  19. }
  20. }
  21. }
  22. #[derive(PartialEq, Clone, Copy, Debug)]
  23. pub enum TileType {
  24. Wall,
  25. Floor,
  26. }
  27. pub struct Map {
  28. pub tiles: carpet::Board<Cell>,
  29. pub rooms: Vec<carpet::Rect>,
  30. }
  31. impl Map {
  32. pub fn new() -> Map {
  33. let mut rng = rand::thread_rng();
  34. let mut map = Map {
  35. tiles: carpet::Board::new_with_default(
  36. 80,
  37. 50,
  38. Cell {
  39. tile: TileType::Wall,
  40. seen: false,
  41. },
  42. ),
  43. rooms: Vec::new(),
  44. };
  45. const MAX_ROOMS: usize = 30;
  46. const MIN_SIZE: usize = 6;
  47. const MAX_SIZE: usize = 10;
  48. for _ in 0..MAX_ROOMS {
  49. let w = rng.gen_range(MIN_SIZE..MAX_SIZE);
  50. let h = rng.gen_range(MIN_SIZE..MAX_SIZE);
  51. let x = rng.gen_range(1..80 - w);
  52. let y = rng.gen_range(1..50 - h);
  53. let room = carpet::Rect::new([x, y], [w, h]);
  54. if map.rooms.iter().any(|r| r.overlaps(room)) {
  55. continue;
  56. }
  57. map.carve(room);
  58. if let Some(prev) = map.rooms.first() {
  59. let c1 = room.center();
  60. let c2 = prev.center();
  61. let join = if rng.gen() {
  62. carpet::Coord { x: c1.x, y: c2.y }
  63. } else {
  64. carpet::Coord { x: c2.x, y: c1.y }
  65. };
  66. map.carve(carpet::Rect::from_points(c1, join));
  67. map.carve(carpet::Rect::from_points(join, c2));
  68. }
  69. map.rooms.push(room);
  70. }
  71. map
  72. }
  73. fn carve(&mut self, rect: carpet::Rect) {
  74. let iter = self
  75. .tiles
  76. .window_iter_mut(rect)
  77. .unwrap_or_else(|| panic!("Rect {:?} of map bounds", rect));
  78. for (_, _, t) in iter {
  79. t.tile = TileType::Floor;
  80. }
  81. }
  82. pub fn passable(&self, (x, y): (usize, usize)) -> bool {
  83. if let Some(cell) = self.tiles.get(x, y) {
  84. return cell.tile == TileType::Floor;
  85. }
  86. false
  87. }
  88. }
  89. #[derive(Component)]
  90. pub struct Viewshed {
  91. pub vs: carpet::Viewshed<Cell>,
  92. pub dirty: bool,
  93. }