Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use crate::ToggleMap2D::ToggleMap2D;
- use std::collections::btree_map::Entry;
- use std::collections::BTreeMap;
- use screeps::StructureType;
- use screeps::objects::Room;
- use screeps::RoomPosition;
- use screeps::find;
- use screeps::ReturnCode;
- use screeps::objects::HasPosition;
- use log::*;
- use crate::map::Map;
- use crate::MovementCostMap::*;
- const TILE_NEW: u8 = 0;
- const TILE_OPEN: u8 = 1;
- const TILE_CLOSED: u8 = 2;
- const ROW_LENGTH: u8 = 50;
- struct MapList<K, V> {
- inner: BTreeMap<K, Vec<V>>
- }
- impl <K, V> MapList<K, V>
- where K:
- std::cmp::Ord + Copy
- {
- pub fn new() -> Self {
- MapList {
- inner: BTreeMap::new()
- }
- }
- pub fn insert(&mut self, key: K, value: V) {
- self.inner.entry(key).or_insert(Vec::new()).push(value);
- }
- pub fn pop_front(&mut self) -> V {
- let key = self.get_low_key();
- if let Entry::Occupied(mut entry) = self.inner.entry(key) {
- let list = entry.get_mut();
- let value = list.remove(0);
- if list.is_empty() {
- entry.remove_entry();
- }
- return value;
- }
- panic!("This should never happen.");
- }
- pub fn is_empty(&self) -> bool {
- self.inner.is_empty()
- }
- fn get_low_key(&self) -> K {
- let min = self.inner.iter().next();
- let (k, _) = min.unwrap();
- *k
- }
- }
- pub struct RoomPlanner {
- room: Room,
- map: Map,
- movement_cost: MovementCostMap,
- open_list: MapList<u32, RoomPosition>,
- tiles: ToggleMap2D
- }
- impl RoomPlanner {
- pub fn new(room: Room) -> Self {
- let mut map = Map::new();
- map.index(room.clone());
- let start_pos = RoomPlanner::select_start_pos(&room);
- let mut result = RoomPlanner {
- room: room.clone(),
- movement_cost: MovementCostMap::new(&room, &map, start_pos),
- map: map,
- open_list: MapList::new(),
- tiles: ToggleMap2D::new(2500, 2, 50)
- };
- result.open_list.insert(0, start_pos);
- result.tiles.set(start_pos.x() as usize, start_pos.y() as usize, TILE_OPEN);
- result
- }
- pub fn place_site(&mut self, structure_type: StructureType, template: &[&[char]]) {
- let mut found = false;
- while !found && !self.open_list.is_empty() {
- let value = self.open_list.pop_front();
- self.set_closed(value);
- self.add_adjacent_tiles(value);
- found = self.can_build(value, template);
- if found {
- self.build(value, structure_type, template);
- }
- }
- }
- fn select_start_pos(room: &Room) -> RoomPosition {
- let spawn = &room.find(find::MY_SPAWNS)[0];
- spawn.pos()
- }
- fn add_adjacent_tiles(&mut self, pos: RoomPosition) {
- let start_x: i32 = (pos.x() as i32 - 1).max(0);
- let start_y: i32 = (pos.y() as i32 - 1).max(0);
- for y in start_y..pos.y() as i32 + 2 {
- for x in start_x..pos.x() as i32 + 2 {
- if y >= ROW_LENGTH as i32 || x >= ROW_LENGTH as i32 { continue; }
- if x == pos.x() as i32 && y == pos.y() as i32 { continue; }
- let p = self.room.get_position_at(x as u32, y as u32).unwrap();
- let weight = self.movement_cost.get_weight(p.clone()) as u32;
- if self.get_tile_state(p) == TILE_NEW {
- self.set_open(p);
- self.open_list.insert(weight, p);
- }
- }
- }
- }
- fn set_open(&mut self, pos: RoomPosition) {
- self.tiles.set(pos.x() as usize, pos.y() as usize, TILE_OPEN);
- }
- fn set_closed(&mut self, pos: RoomPosition) {
- self.tiles.set(pos.x() as usize, pos.y() as usize, TILE_CLOSED);
- }
- fn get_tile_state(&self, pos: RoomPosition) -> u8 {
- self.tiles.get(pos.x() as usize, pos.y() as usize)
- }
- fn can_build(&self, pos: RoomPosition, template: &[&[char]]) -> bool {
- for r in 0..template.len() {
- for c in 0..template[r].len() {
- let x = pos.x() as usize + c;
- let y = pos.y() as usize + r;
- let mask = template[r][c];
- match mask {
- 'Y' => continue,
- 'R' => if !self.map.is_buildable(x, y) { return false },
- _ => if !self.map.is_buildable(x, y) || self.map.is_road(x, y) { return false; }
- }
- }
- }
- true
- }
- fn build(&self, pos: RoomPosition, _structure_type: StructureType, template: &[&[char]]) {
- for r in 0..template.len() {
- for c in 0..template[r].len() {
- let x = pos.x() as usize + c;
- let y = pos.y() as usize + r;
- let mask = template[r][c];
- if mask == 'Y' || mask == 'N' || mask == 'R' { continue; }
- let struc_type = RoomPlanner::mask_to_structure_type(mask);
- let pos = self.room.get_position_at(x as u32, y as u32).unwrap();
- let result;
- match struc_type {
- Some(t) => result = self.room.create_construction_site(&pos, t),
- None => { return; }
- }
- match result {
- ReturnCode::Ok => info!("Successfully created site at ({}, {})", x, y),
- _ => info!("Error creating site at ({}, {}): {}", x, y, result as i16)
- }
- }
- }
- }
- fn mask_to_structure_type(mask: char) -> Option<StructureType> {
- match mask {
- 'E' => return Some(StructureType::Extension),
- 'T' => return Some(StructureType::Tower),
- 'C' => return Some(StructureType::Container),
- 'X' => return Some(StructureType::Extractor),
- 'L' => return Some(StructureType::Lab),
- 'I' => return Some(StructureType::Link),
- 'U' => return Some(StructureType::Nuker),
- 'O' => return Some(StructureType::Observer),
- 'P' => return Some(StructureType::PowerSpawn),
- 'A' => return Some(StructureType::Rampart),
- 'R' => return Some(StructureType::Road),
- 'S' => return Some(StructureType::Spawn),
- _ => return None
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement