use std::any::Any; use rand::prelude::SliceRandom; use rand::Rng; use crate::level::{Level, LevelElement, RoomType}; use crate::position::Position; const ROOMS_VERTICAL: usize = 7; const ROOMS_HORIZONTAL: usize = 4; const ROOM_WIDTH: usize = 7; const ROOM_HEIGHT: usize = 6; #[derive(Copy, Clone, Debug, PartialEq)] struct Room { pub kind: RoomType, pub offset_x: usize, pub offset_y: usize, pub width: usize, pub height: usize, pub connection_down: bool, pub connection_right: bool, pub connected: bool, } impl Room { fn new() -> Self { Self { kind: RoomType::EmptyRoom, offset_x: 0, offset_y: 0, width: 0, height: 0, connection_down: false, connection_right: false, connected: false, } } } #[derive(Debug)] pub struct LevelGenerator { rooms: [[Room; ROOMS_HORIZONTAL]; ROOMS_VERTICAL], } impl LevelGenerator { pub fn generate(level: usize) -> Self { let mut room_types: Vec = Vec::with_capacity(ROOMS_HORIZONTAL * ROOMS_VERTICAL); if level > 0 { room_types.push(RoomType::StairUp); } else { room_types.push(RoomType::Start); } if level < 24 { room_types.push(RoomType::StairDown); } else { room_types.push(RoomType::End); } let mut rng = rand::thread_rng(); for _ in room_types.len()..ROOMS_HORIZONTAL * ROOMS_VERTICAL { match rng.gen_range(1..=6) { 1..=3 => { room_types.push(RoomType::EmptyRoom) } _ => { room_types.push(RoomType::BasicRoom) } } } room_types.shuffle(&mut rng); let mut rooms = [[Room::new(); ROOMS_HORIZONTAL]; ROOMS_VERTICAL]; for r in 0..ROOMS_VERTICAL { for c in 0..ROOMS_HORIZONTAL { rooms[r][c].kind = room_types.pop().unwrap(); if rooms[r][c].kind != RoomType::EmptyRoom { let width = rng.gen_range(3..6); let height = rng.gen_range(3..5); rooms[r][c].width = width; rooms[r][c].height = height; rooms[r][c].offset_x = rng.gen_range(0..(ROOM_WIDTH - width)); rooms[r][c].offset_y = rng.gen_range(0..(ROOM_HEIGHT - height)); } if r == ROOMS_HORIZONTAL - 1 || c == ROOMS_HORIZONTAL - 1 { continue; } match rng.gen_range(0..3) { 0 => { rooms[r][c].connection_down = true } 1 => { rooms[r][c].connection_right = true } 2 => { rooms[r][c].connection_down = true; rooms[r][c].connection_down = true } _ => {} } } } let mut unconnected_rooms = 0;//ROOMS_HORIZONTAL * ROOMS_VERTICAL - 1; rooms[0][0].connected = true; for r in 0..ROOMS_VERTICAL { for c in 0..ROOMS_HORIZONTAL { if !rooms[r][c].connected { continue; } if rooms[r][c].connection_right { rooms[r][c + 1].connected = true; } if rooms[r][c].connection_down { rooms[r + 1][c].connected = true; } } } println!("Unconnected: {}", unconnected_rooms); LevelGenerator { rooms } } pub fn render(&self) -> Level { let mut rng = rand::thread_rng(); let mut s = [[LevelElement::Wall; 1 + ROOMS_HORIZONTAL * ROOM_HEIGHT]; 1 + ROOMS_VERTICAL * ROOM_WIDTH]; let mut start_x: usize = 0; let mut start_y: usize = 0; for c in 0..ROOMS_VERTICAL { for r in 0..ROOMS_HORIZONTAL { let top = 1 + r * ROOM_HEIGHT; let left = 1 + c * ROOM_WIDTH; let room = self.rooms[c][r]; for x in 0..room.width { for y in 0..room.height { s[left + room.offset_x + x][top + room.offset_y + y] = LevelElement::Floor; } } if room.kind == RoomType::StairDown { s[left + room.offset_x + rng.gen_range(0..room.width)][top + room.offset_y + rng.gen_range(0..room.height)] = LevelElement::StairDown; } if room.kind == RoomType::Start || room.kind == RoomType::StairUp { start_x = left + room.offset_x + rng.gen_range(0..room.width); start_y = top + room.offset_y + rng.gen_range(0..room.height); } if room.kind == RoomType::StairUp { s[start_x][start_y] = LevelElement::StairUp; } } } Level { structure: s, start_x, start_y, } } } #[test] fn test_level_gen() { let level = LevelGenerator::generate(0); println!("{:?}", level); assert_eq!(1, 2); }