use crate::{Connection, Map}; use factorio_core::{ beltoptions::Beltspeed, prelude::*, visualize::{Visualization, Visualize}, }; use std::collections::HashSet; pub struct HashMapMap { map: HashSet, size: Position, } impl HashMapMap { fn new(size: impl Into) -> Self { Self { map: HashSet::new(), size: size.into(), } } fn set_blocked_range( &mut self, min_pos: impl Into, max_pos: impl Into, block: bool, ) { let min_pos = min_pos.into(); let max_pos = max_pos.into(); for x in min_pos.x..=max_pos.x { for y in min_pos.y..=max_pos.y { self.set_blocked(Position::new(x, y), block); } } } fn set_blocked(&mut self, pos: impl Into, block: bool) { let pos = pos.into(); if block { self.map.insert(pos); } else { self.map.remove(&pos); } } } impl Visualize for HashMapMap { fn visualize(&self) -> factorio_core::visualize::Visualization { let mut v = Visualization::new(self.size); for &p in &self.map { v.add_symbol(p, factorio_core::visualize::Symbol::Block, None, None); } v } } impl Map for HashMapMap { fn get_position(&self, pos: Position) -> bool { if pos.x < 0 || pos.y < 0 || pos.x >= self.size.x || pos.y >= self.size.y { false } else { !self.map.contains(&pos) } } fn area(&self) -> (Position, Position) { (Position::new(0, 0), self.size) } } pub fn simple() -> (Vec, HashMapMap) { let mut m = HashMapMap::new((5, 3)); m.set_blocked_range((2, 0), (2, 2), true); ( vec![Connection { start_pos: Position::new(0, 1), start_dir: Direction::Right, end_pos: Position::new(4, 1), end_dir: Direction::Right, beltspeed: Beltspeed::Normal, lanes: 1, }], m, ) } pub fn belt_madness_level_1() -> (Vec, HashMapMap) { let mut m = HashMapMap::new((17, 13)); m.set_blocked((0, 3), true); m.set_blocked((1, 4), true); m.set_blocked((2, 4), true); m.set_blocked((1, 5), true); m.set_blocked((2, 5), true); m.set_blocked((1, 7), true); m.set_blocked((2, 7), true); m.set_blocked((1, 8), true); m.set_blocked((2, 8), true); m.set_blocked((0, 9), true); m.set_blocked((16, 3), true); m.set_blocked((14, 4), true); m.set_blocked((15, 4), true); m.set_blocked((14, 5), true); m.set_blocked((15, 5), true); m.set_blocked((14, 7), true); m.set_blocked((15, 7), true); m.set_blocked((14, 8), true); m.set_blocked((15, 8), true); m.set_blocked((16, 9), true); ( vec![ Connection { start_pos: Position::new(2, 7), start_dir: Direction::Right, end_pos: Position::new(13, 4), end_dir: Direction::Right, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(2, 8), start_dir: Direction::Right, end_pos: Position::new(13, 5), end_dir: Direction::Right, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(2, 4), start_dir: Direction::Right, end_pos: Position::new(13, 8), end_dir: Direction::Right, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(2, 5), start_dir: Direction::Right, end_pos: Position::new(13, 7), end_dir: Direction::Right, beltspeed: Beltspeed::Normal, lanes: 1, }, ], m, ) } pub fn belt_madness_level_2() -> (Vec, HashMapMap) { let mut m = HashMapMap::new((17, 13)); m.set_blocked((0, 3), true); m.set_blocked_range((1, 2), (2, 5), true); m.set_blocked_range((1, 7), (2, 10), true); m.set_blocked((0, 9), true); m.set_blocked((16, 3), true); m.set_blocked_range((14, 2), (15, 5), true); m.set_blocked_range((14, 7), (15, 10), true); m.set_blocked((16, 9), true); ( vec![ Connection { start_pos: Position::new(2, 4), start_dir: Direction::Right, end_pos: Position::new(13, 2), end_dir: Direction::Right, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(2, 7), start_dir: Direction::Right, end_pos: Position::new(13, 3), end_dir: Direction::Right, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(2, 10), start_dir: Direction::Right, end_pos: Position::new(13, 4), end_dir: Direction::Right, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(2, 9), start_dir: Direction::Right, end_pos: Position::new(13, 5), end_dir: Direction::Right, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(2, 2), start_dir: Direction::Right, end_pos: Position::new(13, 7), end_dir: Direction::Right, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(2, 3), start_dir: Direction::Right, end_pos: Position::new(13, 8), end_dir: Direction::Right, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(2, 5), start_dir: Direction::Right, end_pos: Position::new(13, 9), end_dir: Direction::Right, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(2, 8), start_dir: Direction::Right, end_pos: Position::new(13, 10), end_dir: Direction::Right, beltspeed: Beltspeed::Normal, lanes: 1, }, ], m, ) } pub fn belt_madness_level_3() -> (Vec, HashMapMap) { let mut m = HashMapMap::new((33, 13)); m.set_blocked_range((1, 3), (2, 5), true); m.set_blocked_range((1, 7), (2, 9), true); m.set_blocked((0, 3), true); m.set_blocked((0, 8), true); m.set_blocked_range((10, 0), (21, 2), true); m.set_blocked_range((10, 5), (21, 7), true); m.set_blocked_range((10, 10), (21, 12), true); m.set_blocked_range((30, 3), (31, 5), true); m.set_blocked_range((30, 7), (31, 9), true); m.set_blocked((32, 3), true); m.set_blocked((32, 9), true); ( vec![ Connection { start_pos: Position::new(2, 3), start_dir: Direction::Right, end_pos: Position::new(29, 7), end_dir: Direction::Right, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(2, 4), start_dir: Direction::Right, end_pos: Position::new(29, 9), end_dir: Direction::Right, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(2, 5), start_dir: Direction::Right, end_pos: Position::new(29, 8), end_dir: Direction::Right, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(2, 7), start_dir: Direction::Right, end_pos: Position::new(29, 3), end_dir: Direction::Right, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(2, 8), start_dir: Direction::Right, end_pos: Position::new(29, 5), end_dir: Direction::Right, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(2, 9), start_dir: Direction::Right, end_pos: Position::new(29, 4), end_dir: Direction::Right, beltspeed: Beltspeed::Normal, lanes: 1, }, ], m, ) } pub fn belt_madness_level_5() -> (Vec, HashMapMap) { let mut m = HashMapMap::new((31, 29)); // power stations m.set_blocked_range((8, 8), (9, 9), true); m.set_blocked_range((21, 8), (22, 9), true); m.set_blocked_range((8, 19), (9, 20), true); m.set_blocked_range((21, 19), (22, 20), true); // solar panels m.set_blocked_range((12, 11), (14, 13), true); m.set_blocked_range((16, 11), (18, 13), true); m.set_blocked_range((12, 15), (14, 17), true); m.set_blocked_range((16, 15), (18, 17), true); // Top m.set_blocked_range((7, 0), (8, 2), true); m.set_blocked((8, 3), true); m.set_blocked((9, 4), true); m.set_blocked_range((10, 5), (20, 5), true); m.set_blocked((21, 4), true); m.set_blocked((22, 3), true); m.set_blocked_range((22, 0), (23, 2), true); m.set_blocked_range((2, 1), (2, 2), true); m.set_blocked_range((4, 1), (4, 2), true); m.set_blocked_range((1, 4), (2, 4), true); m.set_blocked_range((12, 1), (12, 2), true); m.set_blocked_range((14, 1), (14, 2), true); m.set_blocked_range((16, 1), (16, 2), true); m.set_blocked_range((18, 1), (18, 2), true); m.set_blocked_range((28, 4), (29, 4), true); m.set_blocked_range((26, 1), (26, 2), true); m.set_blocked_range((28, 1), (28, 2), true); // Bottom m.set_blocked_range((7, 26), (8, 28), true); m.set_blocked((8, 25), true); m.set_blocked((9, 24), true); m.set_blocked_range((10, 23), (20, 23), true); m.set_blocked((21, 24), true); m.set_blocked((22, 25), true); m.set_blocked_range((22, 26), (23, 28), true); m.set_blocked_range((1, 26), (2, 26), true); m.set_blocked_range((4, 26), (4, 27), true); m.set_blocked_range((1, 24), (2, 24), true); m.set_blocked_range((12, 26), (12, 27), true); m.set_blocked_range((14, 26), (14, 27), true); m.set_blocked_range((16, 26), (16, 27), true); m.set_blocked_range((18, 26), (18, 27), true); m.set_blocked_range((28, 24), (29, 24), true); m.set_blocked_range((26, 26), (26, 27), true); m.set_blocked_range((28, 26), (29, 26), true); // Left m.set_blocked_range((0, 7), (2, 8), true); m.set_blocked((3, 8), true); m.set_blocked((4, 9), true); m.set_blocked_range((5, 10), (5, 18), true); m.set_blocked((4, 19), true); m.set_blocked((3, 20), true); m.set_blocked_range((0, 20), (2, 21), true); m.set_blocked_range((1, 11), (2, 11), true); m.set_blocked_range((1, 13), (2, 13), true); m.set_blocked_range((1, 15), (2, 15), true); m.set_blocked_range((1, 17), (2, 17), true); // Right m.set_blocked_range((28, 7), (30, 8), true); m.set_blocked((27, 8), true); m.set_blocked((26, 9), true); m.set_blocked_range((25, 10), (25, 18), true); m.set_blocked((26, 19), true); m.set_blocked((27, 20), true); m.set_blocked_range((28, 20), (30, 21), true); m.set_blocked_range((28, 11), (29, 11), true); m.set_blocked_range((28, 13), (29, 13), true); m.set_blocked_range((28, 15), (29, 15), true); m.set_blocked_range((28, 17), (29, 17), true); // Path ( vec![ Connection { start_pos: Position::new(4, 2), start_dir: Direction::Down, end_pos: Position::new(26, 25), end_dir: Direction::Down, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(12, 2), start_dir: Direction::Down, end_pos: Position::new(18, 25), end_dir: Direction::Down, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(14, 2), start_dir: Direction::Down, end_pos: Position::new(3, 26), end_dir: Direction::Left, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(16, 2), start_dir: Direction::Down, end_pos: Position::new(14, 25), end_dir: Direction::Down, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(2, 4), start_dir: Direction::Right, end_pos: Position::new(27, 24), end_dir: Direction::Right, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(2, 11), start_dir: Direction::Right, end_pos: Position::new(27, 17), end_dir: Direction::Right, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(2, 13), start_dir: Direction::Right, end_pos: Position::new(27, 26), end_dir: Direction::Right, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(2, 15), start_dir: Direction::Right, end_pos: Position::new(27, 13), end_dir: Direction::Right, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(28, 15), start_dir: Direction::Left, end_pos: Position::new(2, 3), end_dir: Direction::Up, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(2, 17), start_dir: Direction::Right, end_pos: Position::new(18, 3), end_dir: Direction::Up, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(2, 24), start_dir: Direction::Right, end_pos: Position::new(26, 3), end_dir: Direction::Up, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(4, 26), start_dir: Direction::Up, end_pos: Position::new(27, 4), end_dir: Direction::Right, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(12, 26), start_dir: Direction::Up, end_pos: Position::new(27, 11), end_dir: Direction::Right, beltspeed: Beltspeed::Normal, lanes: 1, }, Connection { start_pos: Position::new(16, 26), start_dir: Direction::Up, end_pos: Position::new(28, 3), end_dir: Direction::Up, beltspeed: Beltspeed::Normal, lanes: 1, }, ], m, ) }