From 632ccaa84b7ca60bb3d6da68267df2044df10adf Mon Sep 17 00:00:00 2001 From: InfinityDevTech <47366052+InfinityDevTech@users.noreply.github.com> Date: Tue, 22 Aug 2023 11:29:01 -0400 Subject: [PATCH 01/13] Started updating and refactoring stuffs to a top-down approach --- .vscode/settings.json | 3 + javascript/main.js | 4 +- src/building/roads.rs | 2 +- src/industries/mining.rs | 45 +++++++++++ src/industries/mod.rs | 1 + src/lib.rs | 149 ++++++----------------------------- src/memory.rs | 42 ++++++---- src/movement/creep.rs | 28 +++---- src/movement/move_target.rs | 5 +- src/roles/local/builder.rs | 7 +- src/roles/local/harvester.rs | 6 +- src/roles/local/hauler.rs | 20 +++++ src/roles/local/mod.rs | 3 +- src/roles/local/upgrader.rs | 17 +--- src/room/local.rs | 9 +-- src/room/mod.rs | 3 +- src/room/spawning.rs | 22 ++++++ 17 files changed, 178 insertions(+), 188 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 src/industries/mining.rs create mode 100644 src/industries/mod.rs create mode 100644 src/roles/local/hauler.rs create mode 100644 src/room/spawning.rs diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..4d9636b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "rust-analyzer.showUnlinkedFileNotification": false +} \ No newline at end of file diff --git a/javascript/main.js b/javascript/main.js index 14f5f3a..a951e2b 100644 --- a/javascript/main.js +++ b/javascript/main.js @@ -2,7 +2,7 @@ let wasm_module; // replace this with the name of your module -const MODULE_NAME = "screeps"; +const MODULE_NAME = "crustacean"; let EXECUTION_PAUSED = false; let RED_BUTTON = false; @@ -50,6 +50,8 @@ module.exports.loop = function () { if (wasm_module) { if (RED_BUTTON) { wasm_module.red_button(); + RED_BUTTON = false; + EXECUTION_PAUSED = false; } if (!EXECUTION_PAUSED) { wasm_module.loop(); diff --git a/src/building/roads.rs b/src/building/roads.rs index f5c63fc..426934f 100644 --- a/src/building/roads.rs +++ b/src/building/roads.rs @@ -1,5 +1,5 @@ use log::info; -use screeps::{Source, StructureSpawn, HasPosition, pathfinder::{SearchOptions, MultiRoomCostResult, self}, RoomName, LocalCostMatrix, game, StructureType, find, StructureProperties, look, ConstructionSite}; +use screeps::{Source, StructureSpawn, HasPosition, pathfinder::{SearchOptions, MultiRoomCostResult, self}, RoomName, LocalCostMatrix, game, StructureType, find, StructureProperties, look}; pub fn source_to_spawn(source: &Source, spawn: &StructureSpawn) { let opts = SearchOptions::new(road_callback).max_ops(100000000).plain_cost(2).swamp_cost(5).max_rooms(1); diff --git a/src/industries/mining.rs b/src/industries/mining.rs new file mode 100644 index 0000000..73171bf --- /dev/null +++ b/src/industries/mining.rs @@ -0,0 +1,45 @@ +use std::collections::HashMap; + +use screeps::game; + +use crate::memory::{Careers, ScreepsMemory, CreepMemory}; + +pub fn pre_market(memory: &mut ScreepsMemory) -> &mut ScreepsMemory { + // This is done as to not affect the actual memory. + let creeps_iter = memory.creeps.clone().into_iter(); + let workers: HashMap = creeps_iter.filter(|(_, memory)| { + memory.work.is_some() && memory.work.as_ref().unwrap().career == Careers::Mining + }).collect(); + + for (name, mut creepmem) in workers { + let creep = game::creeps().get(name); + let task = &creepmem.work.clone().unwrap().task; + if creep.is_none() {continue}; + match task { + Some(task) =>{ + match task { + crate::memory::Task::Miner(source_id) => { + if let Some(source) = source_id.resolve() { + crate::roles::local::harvester::harvest(&creep.unwrap(), &mut creepmem, source) + } else { + creepmem.work = None; + } + }, + crate::memory::Task::Hauler(building_id) => { + if let Some(building) = building_id.resolve() { + crate::roles::local::hauler::haul(&creep.unwrap(), &mut creepmem, building) + } else { + creepmem.work = None; + } + }, + _ => { + creepmem.work = None; + } + } + }, + None => todo!(), + } + } + + memory +} diff --git a/src/industries/mod.rs b/src/industries/mod.rs new file mode 100644 index 0000000..07b0768 --- /dev/null +++ b/src/industries/mod.rs @@ -0,0 +1 @@ +pub mod mining; \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 4fd2aa0..d6a1206 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,22 +1,16 @@ use std::collections::HashMap; use log::*; -use movement::creep; -use screeps::ConstructionSite; use screeps::{ - constants::{Part, ResourceType}, - enums::StructureObject, find, game, - local::ObjectId, - objects::{Creep, Source, StructureController}, - prelude::*, + prelude::* }; -use serde::{Deserialize, Serialize}; use wasm_bindgen::prelude::*; -use crate::memory::{CreepMemory, ScreepsMemory}; +use crate::memory::ScreepsMemory; mod building; +mod industries; mod logging; mod memory; mod movement; @@ -29,137 +23,45 @@ pub fn setup() { logging::setup_logging(logging::Info); } -// this enum will represent a creep's lock on a specific target object, storing a js reference -// to the object id so that we can grab a fresh reference to the object each successive tick, -// since screeps game objects become 'stale' and shouldn't be used beyond the tick they were fetched -#[derive(Clone, Serialize, Deserialize, Debug)] -pub enum CreepTarget { - Upgrade(ObjectId), - Harvest(ObjectId), - Build(ObjectId), - Rename(ObjectId) -} - // to use a reserved name as a function name, use `js_name`: #[wasm_bindgen(js_name = loop)] pub fn game_loop() { debug!("Loop starting! CPU: {}", game::cpu::get_used()); let mut memory = ScreepsMemory::init_memory(); - let mut ran_creeps: Vec = Vec::new(); - for name in game::creeps().keys() { - let creep = game::creeps().get(name.clone()); - if creep.is_none() { - // Remove creep that no longer exists from memory - memory.creeps.remove(&name); - } else { - match memory.creeps.get_mut(&name) { - Some(creepmem) => { - run_creep(&creep.unwrap(), creepmem); - } + industries::mining::pre_market(&mut memory); + + // This is done so infrequently for a few reasons: + // 1. Im too lazy to figure out a way to iterate creeps in the main loop + // 2. Because it doesnt use much decrease modulo as bot succeeds. + // 3. Because fuck you thats why + let mut detected_creeps: Vec = Vec::new(); + if game::time() % 20 == 0 { + for creep in game::creeps().keys() { + match memory.creeps.get_mut(&creep) { + Some(_) => { + detected_creeps.push(creep); + }, None => { - // This creep is new, add it to memory - memory.create_creep(&name); - } + memory.create_creep(&creep, game::creeps().get(creep.clone()).unwrap().room().unwrap()); + detected_creeps.push(creep); + }, } - ran_creeps.push(name.clone()); } } - // Remove creeps that have died from memory - memory.creeps.retain(|name, _| ran_creeps.contains(name)); + memory.creeps.retain(|x, _| detected_creeps.contains(x)); - let mut additional = 0; - for spawn in game::spawns().values() { - // Default body for now, will be sorted out later. - let body = [Part::Move, Part::Move, Part::Carry, Part::Work]; - if spawn.room().unwrap().energy_available() >= body.iter().map(|p| p.cost()).sum() { - let name = format!("{}-{}", game::time(), additional); - match spawn.spawn_creep(&body, &name) { - Ok(()) => { - additional += 1; - memory.create_creep(&name); - } - Err(e) => warn!("Couldn't spawn: {:?}", e), - } - } - } + room::spawning::run_spawns(&mut memory); // Bot is finished, write the local copy of memory. - // This should be only executed ONCE per tick, as it is quite expensive. + // This is run only once per tick as it serializes the memory. + // This is done like this because its basically MemHack for you JS people. memory.write_memory(); info!("Done! Cpu used: {}", game::cpu::get_used()); } -fn run_creep(creep: &Creep, creepmem: &mut CreepMemory) { - if creep.spawning() { - return; - } - - let target = &creepmem.work; - match target { - Some(target) => { - let creep_target = target; - match creep_target { - CreepTarget::Upgrade(controller_id) - if creep.store().get_used_capacity(Some(ResourceType::Energy)) > 0 => - { - if let Some(controller) = controller_id.resolve() { - roles::local::upgrader::upgrade(creep, creepmem, controller); - } else { - creepmem.set_work(None); - } - } - CreepTarget::Harvest(source_id) - if creep.store().get_free_capacity(Some(ResourceType::Energy)) > 0 => - { - if let Some(source) = source_id.resolve() { - roles::local::harvester::harvest(creep, creepmem, source); - } else { - creepmem.set_work(None); - } - } - CreepTarget::Build(site_id) => { - if let Some(site) = site_id.resolve() { - if creep.pos().is_near_to(site.pos()) { - roles::local::builder::build(creep, creepmem, site); - } else { - let _ = creep.move_to(&site); - } - } else { - creepmem.work = None; - } - } - CreepTarget::Rename(controller_id) => { - if let Some(controller) = controller_id.resolve() { - if creep.pos().is_near_to(controller.pos()) { - let _ = creep.sign_controller(&controller, "Ferris FTW!"); - creepmem.work = None; - } else { - creep::move_to(&creep.name(), creepmem, controller.pos()); - } - } else { - creepmem.work = None; - } - } - _ => { - creepmem.set_work(None); - } - }; - } - None => { - // Should never fail. - let room = creep.room().unwrap(); - if creep.store().get_used_capacity(Some(ResourceType::Energy)) > 0 { - creepmem.set_work(Some(CreepTarget::Upgrade(room.controller().unwrap().id()))); - } else if let Some(source) = room.find(find::SOURCES_ACTIVE, None).get(0) { - creepmem.set_work(Some(CreepTarget::Harvest(source.id()))); - } - } - } -} - #[wasm_bindgen(js_name = red_button)] pub fn big_red_button() { for creep in game::creeps().values() { @@ -167,8 +69,7 @@ pub fn big_red_button() { let _ = creep.suicide(); } for room in game::rooms().values() { - match room.controller() { - Some(controller) => { + if let Some(controller) = room.controller() { for structure in room.find(find::MY_STRUCTURES, None) { let _ = structure.destroy(); } @@ -176,8 +77,6 @@ pub fn big_red_button() { let _ = csite.remove(); } let _ = controller.unclaim(); - }, - None => {}, } } let mut memory = memory::ScreepsMemory::init_memory(); diff --git a/src/memory.rs b/src/memory.rs index 1cb85f4..88bbf45 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -1,10 +1,28 @@ use std::collections::HashMap; use log::error; +use screeps::{ObjectId, Source, StructureController, StructureSpawn, Room, find, HasTypedId}; use serde::{Deserialize, Serialize}; use js_sys::JsString; +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] +pub enum Careers { + Mining, + Odd +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] +pub enum Task { + // Mining industry + Miner(ObjectId), + Hauler(ObjectId), + + // Odd industry + Rename(ObjectId) +} + + structstruck::strike! { #[strikethrough[derive(Serialize, Deserialize, Debug, Clone)]] pub struct CreepMemory{ @@ -17,7 +35,10 @@ pub struct CreepMemory{ pub path: String, pub room: String }>, - pub work: Option, + pub work: Option, + }> } } @@ -48,7 +69,7 @@ impl ScreepsMemory { pub fn init_memory() -> Self { let memory_jsstring = screeps::raw_memory::get(); let memory_string = memory_jsstring.as_string().unwrap(); - if memory_string == "" { + if memory_string.is_empty() { let memory = ScreepsMemory { creeps: HashMap::new(), rooms: HashMap::new(), @@ -75,12 +96,15 @@ impl ScreepsMemory { screeps::raw_memory::set(&js_serialized); } - pub fn create_creep(&mut self, name: &str) { + pub fn create_creep(&mut self, name: &str, room: Room) { self.creeps.insert( name.to_string(), CreepMemory { movement: None, - work: None, + work: Some(Work { + career: Careers::Mining, + task: Some(Task::Miner(room.find(find::SOURCES, None).first().unwrap().id())) + }), }, ); } @@ -95,13 +119,3 @@ impl ScreepsMemory { ); } } - -impl CreepMemory { - pub fn set_movement(&mut self, movement: Option) { - self.movement = movement; - } - - pub fn set_work(&mut self, work: Option) { - self.work = work; - } -} diff --git a/src/movement/creep.rs b/src/movement/creep.rs index f2f6442..38e270c 100644 --- a/src/movement/creep.rs +++ b/src/movement/creep.rs @@ -1,5 +1,5 @@ use log::info; -use screeps::{game, Direction, HasPosition, Creep, RoomPosition, Position}; +use screeps::{game, Direction, HasPosition, Position}; use crate::memory::{Movement, CreepMemory}; @@ -40,14 +40,14 @@ pub fn move_by_path(creep_name: String, path: Movement, memory: &mut CreepMemory let serialized_vec = serialized_vec[1..].to_vec(); let serialized_path = serialized_vec.iter().map(|x| x.to_string()).collect::>().join(""); - if serialized_vec.len() == 0 { - memory.set_movement(None); + if serialized_vec.is_empty() { + memory.movement = None; } else { - memory.set_movement(Some(Movement { + memory.movement = Some(Movement { dest: path.dest, path: serialized_path, room: path.room, - })); + }); } let mut points = vec![]; @@ -55,7 +55,7 @@ pub fn move_by_path(creep_name: String, path: Movement, memory: &mut CreepMemory for step in serialized_vec { let dir = num_to_dir(step); let (x, y) = dir_to_coords(dir, cursor.0, cursor.1); - points.push((x as f32, y as f32)); + points.push((x, y)); cursor = (x, y); } } @@ -76,13 +76,13 @@ pub fn num_to_dir(num: u8) -> Direction { pub fn dir_to_coords(dir: Direction, x: f32, y: f32) -> (f32, f32) { match dir { - Direction::Top => (x, y - 1 as f32), - Direction::TopRight => (x + 1 as f32, y - 1 as f32), - Direction::Right => (x + 1 as f32, y), - Direction::BottomRight => (x + 1 as f32, y + 1 as f32), - Direction::Bottom => (x, y + 1 as f32), - Direction::BottomLeft => (x - 1 as f32, y + 1 as f32), - Direction::Left => (x - 1 as f32, y), - Direction::TopLeft => (x - 1 as f32, y - 1 as f32), + Direction::Top => (x, y - 1_f32), + Direction::TopRight => (x + 1_f32, y - 1_f32), + Direction::Right => (x + 1_f32, y), + Direction::BottomRight => (x + 1_f32, y + 1_f32), + Direction::Bottom => (x, y + 1_f32), + Direction::BottomLeft => (x - 1_f32, y + 1_f32), + Direction::Left => (x - 1_f32, y), + Direction::TopLeft => (x - 1_f32, y - 1_f32), } } diff --git a/src/movement/move_target.rs b/src/movement/move_target.rs index 0ab0fa5..95e096a 100644 --- a/src/movement/move_target.rs +++ b/src/movement/move_target.rs @@ -1,7 +1,6 @@ use log::warn; use screeps::{ - pathfinder::{self, MultiRoomCostResult, SearchOptions}, - Direction, HasPosition, LocalCostMatrix, OwnedStructureProperties, Position, + pathfinder::{self, MultiRoomCostResult, SearchOptions}, HasPosition, LocalCostMatrix, OwnedStructureProperties, Position, RoomName, StructureObject, find }; @@ -37,7 +36,7 @@ impl MoveTarget { if pos.room_name() == cur_pos.room_name() { match pos.get_direction_to(cur_pos) { Some(dir) => { - steps.push(Direction::from(-dir)); + steps.push(-dir); } None => { warn!("Couldn't get direction to {:?} from {:?}", pos, cur_pos); diff --git a/src/roles/local/builder.rs b/src/roles/local/builder.rs index bcdb56e..aea497d 100644 --- a/src/roles/local/builder.rs +++ b/src/roles/local/builder.rs @@ -10,11 +10,6 @@ pub fn build(creep: &Creep, creepmem: &mut CreepMemory, site: ConstructionSite) creepmem.work = None; }); } else { - let movet = movement::move_target::MoveTarget { - pos: site.pos(), - range: 3 - }.find_path_to(creep.pos()); - creepmem.movement = Some(movet.clone()); - movement::creep::move_by_path(creep.name(), movet, creepmem); + movement::creep::move_to(&creep.name(), creepmem, site.pos()); } } diff --git a/src/roles/local/harvester.rs b/src/roles/local/harvester.rs index a35b375..c261640 100644 --- a/src/roles/local/harvester.rs +++ b/src/roles/local/harvester.rs @@ -1,14 +1,18 @@ use log::warn; -use screeps::{Source, HasPosition, Creep, SharedCreepProperties}; +use screeps::{Source, HasPosition, Creep, SharedCreepProperties, ResourceType}; use crate::{memory::CreepMemory, movement}; pub fn harvest(creep: &Creep, creepmem: &mut CreepMemory, source: Source) { let name = creep.name(); if creep.pos().is_near_to(source.pos()) { + if creep.store().get_free_capacity(Some(ResourceType::Energy)) == 0 { + let _ = creep.drop(ResourceType::Energy, Some(creep.store().get_used_capacity(Some(ResourceType::Energy)))); + } else { creep.harvest(&source).unwrap_or_else(|e| { warn!("couldn't harvest: {:?}", e); }); + } } else { movement::creep::move_to(&name, creepmem, source.pos()) } diff --git a/src/roles/local/hauler.rs b/src/roles/local/hauler.rs new file mode 100644 index 0000000..a83d686 --- /dev/null +++ b/src/roles/local/hauler.rs @@ -0,0 +1,20 @@ +use screeps::{Creep, SharedCreepProperties, HasPosition, find, ResourceType, StructureSpawn}; + +use crate::{memory::CreepMemory, movement}; + +pub fn haul(creep: &Creep, creepmem: &mut CreepMemory, deposit: StructureSpawn) { + let name = creep.name(); + let inventory = creep.store(); + if inventory.get_free_capacity(None) > inventory.get_used_capacity(Some(ResourceType::Energy)) as i32 { + let closest_energy = creep.pos().find_closest_by_path(find::DROPPED_RESOURCES, None); + if let Some(energy) = closest_energy { + if creep.pos().is_near_to(energy.clone().pos()) { + let _ = creep.pickup(&energy); + } else { + movement::creep::move_to(&name, creepmem, energy.pos()) + } + } + } else if creep.pos().is_near_to(deposit.pos()) { + let _ = creep.transfer(&deposit, ResourceType::Energy, Some(inventory.get_used_capacity(Some(ResourceType::Energy)))); + } +} diff --git a/src/roles/local/mod.rs b/src/roles/local/mod.rs index f5828ac..fcf80d9 100644 --- a/src/roles/local/mod.rs +++ b/src/roles/local/mod.rs @@ -1,3 +1,4 @@ pub mod builder; pub mod harvester; -pub mod upgrader; \ No newline at end of file +pub mod upgrader; +pub mod hauler; \ No newline at end of file diff --git a/src/roles/local/upgrader.rs b/src/roles/local/upgrader.rs index e575ba7..8fde06a 100644 --- a/src/roles/local/upgrader.rs +++ b/src/roles/local/upgrader.rs @@ -1,7 +1,7 @@ use log::warn; use screeps::{Creep, ErrorCode, SharedCreepProperties, StructureController, HasPosition}; -use crate::memory::CreepMemory; +use crate::{memory::CreepMemory, movement}; pub fn upgrade(creep: &Creep, creepmem: &mut CreepMemory, controller: StructureController) { let name = creep.name(); @@ -9,20 +9,7 @@ pub fn upgrade(creep: &Creep, creepmem: &mut CreepMemory, controller: StructureC .upgrade_controller(&controller) .unwrap_or_else(|e| match e { ErrorCode::NotInRange => { - match &creepmem.movement { - Some(path) => { - crate::movement::creep::move_by_path(name.clone(), path.clone(), creepmem); - } - None => { - let path = crate::movement::move_target::MoveTarget { - pos: controller.pos(), - range: 1 - } - .find_path_to(creep.pos()); - creepmem.movement = Some(path.clone()); - crate::movement::creep::move_by_path(name.clone(), path, creepmem); - } - }; + movement::creep::move_to(&name, creepmem, controller.pos()); } _ => { let _ = creep.say("🚧", false); diff --git a/src/room/local.rs b/src/room/local.rs index e194461..9a6c884 100644 --- a/src/room/local.rs +++ b/src/room/local.rs @@ -1,17 +1,14 @@ use screeps::{Room, find, HasPosition}; -use crate::memory::{RoomMemory, self}; +use crate::memory::RoomMemory; pub fn run_rom(room: Room, roommem: RoomMemory) { let controller = room.controller().unwrap(); match controller.sign() { Some(sign) => { if sign.text() != "Ferris FTW!" { - match controller.pos().find_closest_by_range(find::MY_CREEPS) { - Some(creep) => { - - }, - None => {} + if let Some(creep) = controller.pos().find_closest_by_range(find::MY_CREEPS) { + } } }, diff --git a/src/room/mod.rs b/src/room/mod.rs index 178b08d..4a9aa0c 100644 --- a/src/room/mod.rs +++ b/src/room/mod.rs @@ -1 +1,2 @@ -pub mod local; \ No newline at end of file +pub mod local; +pub mod spawning; \ No newline at end of file diff --git a/src/room/spawning.rs b/src/room/spawning.rs new file mode 100644 index 0000000..f298328 --- /dev/null +++ b/src/room/spawning.rs @@ -0,0 +1,22 @@ +use log::warn; +use screeps::{game, Part}; + +use crate::memory::ScreepsMemory; + +pub fn run_spawns(memory: &mut ScreepsMemory) { + let mut additional = 0; + for spawn in game::spawns().values() { + // Default body for now, will be sorted out later. + let body = [Part::Move, Part::Move, Part::Carry, Part::Work]; + if spawn.room().unwrap().energy_available() >= body.iter().map(|p| p.cost()).sum() { + let name = format!("{}-{}", game::time(), additional); + match spawn.spawn_creep(&body, &name) { + Ok(()) => { + additional += 1; + memory.create_creep(&name, spawn.room().unwrap()); + } + Err(e) => warn!("Couldn't spawn: {:?}", e), + } + } + } +} \ No newline at end of file From 5e86c16c62399081d475da92aa7531ded27ee33c Mon Sep 17 00:00:00 2001 From: InfinityDevTech <47366052+InfinityDevTech@users.noreply.github.com> Date: Thu, 24 Aug 2023 20:54:20 -0400 Subject: [PATCH 02/13] Semi-working version. HAs a LOT of bugs --- Cargo.lock | 71 +++++++++++++++++ Cargo.toml | 3 + src/industries/mining.rs | 45 ----------- src/lib.rs | 103 +++++++++++++++--------- src/memory.rs | 46 +++++++---- src/roles/local/harvester.rs | 2 +- src/roles/local/hauler.rs | 19 ++++- src/{ => room}/building/mod.rs | 0 src/{ => room}/building/roads.rs | 0 src/room/democracy.rs | 133 +++++++++++++++++++++++++++++++ src/room/industries/mining.rs | 38 +++++++++ src/{ => room}/industries/mod.rs | 0 src/room/local.rs | 17 ---- src/room/mod.rs | 5 +- src/room/spawning.rs | 22 ----- src/visual/map.rs | 12 +++ src/visual/mod.rs | 1 + 17 files changed, 375 insertions(+), 142 deletions(-) delete mode 100644 src/industries/mining.rs rename src/{ => room}/building/mod.rs (100%) rename src/{ => room}/building/roads.rs (100%) create mode 100644 src/room/democracy.rs create mode 100644 src/room/industries/mining.rs rename src/{ => room}/industries/mod.rs (100%) delete mode 100644 src/room/local.rs delete mode 100644 src/room/spawning.rs create mode 100644 src/visual/map.rs create mode 100644 src/visual/mod.rs diff --git a/Cargo.lock b/Cargo.lock index bc16adf..8691d86 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,12 +41,15 @@ name = "crustacean" version = "0.0.0" dependencies = [ "fern", + "getrandom", "js-sys", "log", + "rand", "screeps-game-api", "serde", "serde_json", "structstruck", + "uuid", "wasm-bindgen", "wasm-bindgen-test", "web-sys", @@ -93,6 +96,17 @@ dependencies = [ "log", ] +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "heck" version = "0.4.1" @@ -114,6 +128,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "libc" +version = "0.2.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + [[package]] name = "log" version = "0.4.19" @@ -146,6 +166,12 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + [[package]] name = "proc-macro2" version = "1.0.66" @@ -164,6 +190,36 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + [[package]] name = "ryu" version = "1.0.15" @@ -277,6 +333,15 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +[[package]] +name = "uuid" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +dependencies = [ + "getrandom", +] + [[package]] name = "venial" version = "0.5.0" @@ -287,6 +352,12 @@ dependencies = [ "quote", ] +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "wasm-bindgen" version = "0.2.87" diff --git a/Cargo.toml b/Cargo.toml index e221013..d4cfe24 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,9 @@ web-sys = { version = "0.3", features = ["console"] } structstruck = "0.4.1" serde_json = "1.0.104" serde = { version = "1.0.183", features = ["derive"] } +uuid = { version = "1.4.1", features = ["v4"] } +getrandom = { version = "0.2.10", features = ["custom"] } +rand = "0.8.5" [dev-dependencies] wasm-bindgen-test = "0.3" diff --git a/src/industries/mining.rs b/src/industries/mining.rs deleted file mode 100644 index 73171bf..0000000 --- a/src/industries/mining.rs +++ /dev/null @@ -1,45 +0,0 @@ -use std::collections::HashMap; - -use screeps::game; - -use crate::memory::{Careers, ScreepsMemory, CreepMemory}; - -pub fn pre_market(memory: &mut ScreepsMemory) -> &mut ScreepsMemory { - // This is done as to not affect the actual memory. - let creeps_iter = memory.creeps.clone().into_iter(); - let workers: HashMap = creeps_iter.filter(|(_, memory)| { - memory.work.is_some() && memory.work.as_ref().unwrap().career == Careers::Mining - }).collect(); - - for (name, mut creepmem) in workers { - let creep = game::creeps().get(name); - let task = &creepmem.work.clone().unwrap().task; - if creep.is_none() {continue}; - match task { - Some(task) =>{ - match task { - crate::memory::Task::Miner(source_id) => { - if let Some(source) = source_id.resolve() { - crate::roles::local::harvester::harvest(&creep.unwrap(), &mut creepmem, source) - } else { - creepmem.work = None; - } - }, - crate::memory::Task::Hauler(building_id) => { - if let Some(building) = building_id.resolve() { - crate::roles::local::hauler::haul(&creep.unwrap(), &mut creepmem, building) - } else { - creepmem.work = None; - } - }, - _ => { - creepmem.work = None; - } - } - }, - None => todo!(), - } - } - - memory -} diff --git a/src/lib.rs b/src/lib.rs index d6a1206..513a663 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,58 +1,90 @@ -use std::collections::HashMap; +use std::{collections::HashMap, str::FromStr}; +use getrandom::register_custom_getrandom; use log::*; -use screeps::{ - find, game, - prelude::* -}; +use rand::{rngs::StdRng, SeedableRng, RngCore}; +use screeps::{find, game, prelude::*, RoomName}; use wasm_bindgen::prelude::*; use crate::memory::ScreepsMemory; -mod building; -mod industries; mod logging; mod memory; mod movement; mod roles; mod room; +mod visual; + +fn custom_getrandom(buf: &mut [u8]) -> Result<(), getrandom::Error> { + let mut rng = StdRng::seed_from_u64(js_sys::Math::random().to_bits()); + rng.fill_bytes(buf); + Ok(()) +} + +register_custom_getrandom!(custom_getrandom); -// add wasm_bindgen to any function you would like to expose for call from js #[wasm_bindgen(js_name = setup)] pub fn setup() { logging::setup_logging(logging::Info); } -// to use a reserved name as a function name, use `js_name`: +pub fn recently_respawned(memory: &mut ScreepsMemory) -> bool { + if memory.spawn_tick || game::time() == 0 { + return true; + } + + let creeps = game::creeps().keys().collect::>(); + if !creeps.is_empty() { + return false; + } + + let names: Vec = game::rooms().keys().collect(); + if names.len() != 1 { + return false; + } + + // check for controller, progress and safe mode + let room = game::rooms().get(names[0]).unwrap(); + let controller = room.controller(); + if controller.is_none()|| !controller.clone().unwrap().my() || controller.clone().unwrap().level() != 1 || controller.clone().unwrap().progress() > 0 || + controller.clone().unwrap().safe_mode().is_none() { + return false; + } + + let spawns: Vec = game::spawns().keys().collect(); + if spawns.len() != 1 { + return false; + } + + memory.spawn_tick = true; + true +} + #[wasm_bindgen(js_name = loop)] pub fn game_loop() { debug!("Loop starting! CPU: {}", game::cpu::get_used()); let mut memory = ScreepsMemory::init_memory(); - industries::mining::pre_market(&mut memory); - - // This is done so infrequently for a few reasons: - // 1. Im too lazy to figure out a way to iterate creeps in the main loop - // 2. Because it doesnt use much decrease modulo as bot succeeds. - // 3. Because fuck you thats why - let mut detected_creeps: Vec = Vec::new(); - if game::time() % 20 == 0 { - for creep in game::creeps().keys() { - match memory.creeps.get_mut(&creep) { - Some(_) => { - detected_creeps.push(creep); - }, - None => { - memory.create_creep(&creep, game::creeps().get(creep.clone()).unwrap().room().unwrap()); - detected_creeps.push(creep); - }, + if recently_respawned(&mut memory) { + for room in game::rooms().keys() { + let room = game::rooms().get(room).unwrap(); + if memory.rooms.get(&room.name().to_string()).is_some() { + continue; + } + if let Some(controller) = room.controller() { + if controller.my() { + memory.create_room(&room.name().to_string()); + } } } + memory.spawn_tick = false } - memory.creeps.retain(|x, _| detected_creeps.contains(x)); + for room in memory.clone().rooms.values() { + room::democracy::start_government(game::rooms().get(RoomName::from_str(&room.name).unwrap()).unwrap(), &mut memory); + } - room::spawning::run_spawns(&mut memory); + visual::map::classify_rooms(&memory); // Bot is finished, write the local copy of memory. // This is run only once per tick as it serializes the memory. @@ -70,17 +102,16 @@ pub fn big_red_button() { } for room in game::rooms().values() { if let Some(controller) = room.controller() { - for structure in room.find(find::MY_STRUCTURES, None) { - let _ = structure.destroy(); - } - for csite in room.find(find::MY_CONSTRUCTION_SITES, None) { - let _ = csite.remove(); - } - let _ = controller.unclaim(); + for structure in room.find(find::MY_STRUCTURES, None) { + let _ = structure.destroy(); + } + for csite in room.find(find::MY_CONSTRUCTION_SITES, None) { + let _ = csite.remove(); + } + let _ = controller.unclaim(); } } let mut memory = memory::ScreepsMemory::init_memory(); - memory.creeps = HashMap::new(); memory.rooms = HashMap::new(); memory.write_memory(); } diff --git a/src/memory.rs b/src/memory.rs index 88bbf45..c88d3a1 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -1,28 +1,29 @@ use std::collections::HashMap; -use log::error; -use screeps::{ObjectId, Source, StructureController, StructureSpawn, Room, find, HasTypedId}; +use log::{error, info}; +use screeps::{ObjectId, Source, StructureController, Structure}; use serde::{Deserialize, Serialize}; use js_sys::JsString; + + #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] pub enum Careers { Mining, - Odd + Odd, } #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] pub enum Task { // Mining industry Miner(ObjectId), - Hauler(ObjectId), + Hauler(ObjectId), // Odd industry - Rename(ObjectId) + Rename(ObjectId), } - structstruck::strike! { #[strikethrough[derive(Serialize, Deserialize, Debug, Clone)]] pub struct CreepMemory{ @@ -45,7 +46,9 @@ pub struct CreepMemory{ structstruck::strike! { #[strikethrough[derive(Serialize, Deserialize, Debug, Clone)]] pub struct RoomMemory{ - room_type: String, + pub name: String, + pub room_type: String, + pub creeps: HashMap, pub sources: HashMap }>, + pub creep_count: pub struct { + pub miner: u8, + pub hauler: u8 + } } } structstruck::strike! { #[strikethrough[derive(Serialize, Deserialize, Debug, Clone)]] pub struct ScreepsMemory { - pub creeps: HashMap, - pub rooms: HashMap + pub rooms: HashMap, + + pub spawn_tick: bool } } @@ -71,8 +79,8 @@ impl ScreepsMemory { let memory_string = memory_jsstring.as_string().unwrap(); if memory_string.is_empty() { let memory = ScreepsMemory { - creeps: HashMap::new(), rooms: HashMap::new(), + spawn_tick: true, }; memory.write_memory(); memory @@ -83,38 +91,46 @@ impl ScreepsMemory { error!("Error parsing memory: {}", e); error!("This is a critical error, memory MUST be reset to default state."); ScreepsMemory { - creeps: HashMap::new(), rooms: HashMap::new(), + spawn_tick: true } } } } } pub fn write_memory(&self) { + info!("Writing memory"); let serialized = serde_json::to_string(&self).unwrap(); let js_serialized = JsString::from(serialized); screeps::raw_memory::set(&js_serialized); } - pub fn create_creep(&mut self, name: &str, room: Room) { - self.creeps.insert( - name.to_string(), + pub fn create_creep(&mut self, room_name: &str, creep_name: &str, task: Task) { + self.rooms.get_mut(room_name).unwrap().creeps.insert( + creep_name.to_string(), CreepMemory { movement: None, work: Some(Work { career: Careers::Mining, - task: Some(Task::Miner(room.find(find::SOURCES, None).first().unwrap().id())) + task: Some(task), }), }, ); + info!("Created creep"); } pub fn create_room(&mut self, name: &str) { self.rooms.insert( name.to_string(), RoomMemory { + name: name.to_string(), room_type: "local".to_string(), + creeps: HashMap::new(), sources: HashMap::new(), + creep_count: CreepCount { + miner: 0, + hauler: 0, + }, }, ); } diff --git a/src/roles/local/harvester.rs b/src/roles/local/harvester.rs index c261640..2b979bd 100644 --- a/src/roles/local/harvester.rs +++ b/src/roles/local/harvester.rs @@ -6,7 +6,7 @@ use crate::{memory::CreepMemory, movement}; pub fn harvest(creep: &Creep, creepmem: &mut CreepMemory, source: Source) { let name = creep.name(); if creep.pos().is_near_to(source.pos()) { - if creep.store().get_free_capacity(Some(ResourceType::Energy)) == 0 { + if creep.store().get_free_capacity(Some(ResourceType::Energy)) > creep.store().get_used_capacity(Some(ResourceType::Energy)) as i32 { let _ = creep.drop(ResourceType::Energy, Some(creep.store().get_used_capacity(Some(ResourceType::Energy)))); } else { creep.harvest(&source).unwrap_or_else(|e| { diff --git a/src/roles/local/hauler.rs b/src/roles/local/hauler.rs index a83d686..202e481 100644 --- a/src/roles/local/hauler.rs +++ b/src/roles/local/hauler.rs @@ -1,8 +1,8 @@ -use screeps::{Creep, SharedCreepProperties, HasPosition, find, ResourceType, StructureSpawn}; +use screeps::{Creep, SharedCreepProperties, HasPosition, find, ResourceType, Structure, StructureObject}; use crate::{memory::CreepMemory, movement}; -pub fn haul(creep: &Creep, creepmem: &mut CreepMemory, deposit: StructureSpawn) { +pub fn haul(creep: &Creep, creepmem: &mut CreepMemory, deposit: Structure) { let name = creep.name(); let inventory = creep.store(); if inventory.get_free_capacity(None) > inventory.get_used_capacity(Some(ResourceType::Energy)) as i32 { @@ -14,7 +14,18 @@ pub fn haul(creep: &Creep, creepmem: &mut CreepMemory, deposit: StructureSpawn) movement::creep::move_to(&name, creepmem, energy.pos()) } } - } else if creep.pos().is_near_to(deposit.pos()) { - let _ = creep.transfer(&deposit, ResourceType::Energy, Some(inventory.get_used_capacity(Some(ResourceType::Energy)))); + } else { + //let structure_object = StructureObject::from(deposit); + //if let Some(structure) = structure_object.as_transferable() { + // let _ = creep.transfer(structure, ResourceType::Energy, Some(inventory.get_used_capacity(Some(ResourceType::Energy)))); + //} + let csite = creep.pos().find_closest_by_range(find::CONSTRUCTION_SITES); + if let Some(site) = csite { + if creep.pos().is_near_to(site.pos()) { + let _ = creep.build(&site); + } else { + movement::creep::move_to(&name, creepmem, site.pos()) + } + } } } diff --git a/src/building/mod.rs b/src/room/building/mod.rs similarity index 100% rename from src/building/mod.rs rename to src/room/building/mod.rs diff --git a/src/building/roads.rs b/src/room/building/roads.rs similarity index 100% rename from src/building/roads.rs rename to src/room/building/roads.rs diff --git a/src/room/democracy.rs b/src/room/democracy.rs new file mode 100644 index 0000000..ea300fe --- /dev/null +++ b/src/room/democracy.rs @@ -0,0 +1,133 @@ +use std::str::FromStr; + +use log::info; +use screeps::{find, game, HasPosition, HasTypedId, ObjectId, Part, Room}; + +use crate::memory::{ScreepsMemory, Task}; + +use super::industries; + +const MINER_COUNT: u8 = 2; +const HAULER_COUNT: u8 = 2; + +pub fn start_government(room: Room, memory: &mut ScreepsMemory) { + let mut creeps = Vec::new(); + let mut to_remove = Vec::new(); + + // Horray, i did it better. + for name in memory + .rooms + .get_mut(&room.name().to_string()) + .unwrap() + .creeps + .clone() + .keys() + { + for creep_name in memory.clone().rooms.get_mut(&room.name().to_string()).unwrap().creeps.keys() { + info!("Name, {}", creep_name); + if let Some(creep) = game::creeps().get(creep_name.to_string()) { + info!("Found Crep"); + if creep.spawning() {continue;} + + creeps.push(name.to_string()); + } else if game::creeps().get(creep_name.to_string()).is_none() { + let t = &memory.clone().rooms.get_mut(&room.name().to_string()).unwrap().creeps.get_mut(creep_name).unwrap().work.clone().unwrap().task.unwrap(); + match t { + Task::Miner(_) => { + info!("Subtract 1"); + memory.rooms.get_mut(&room.name().to_string()).unwrap().creep_count.miner -= 1; + }, + Task::Hauler(_) => { + info!("Subtract 1 -2 "); + memory.rooms.get_mut(&room.name().to_string()).unwrap().creep_count.hauler -= 1; + }, + _ => {}, + } + to_remove.push(creep_name.to_string()); + } + } + } + memory + .rooms + .get_mut(&room.name().to_string()) + .unwrap() + .creeps + .retain(|x, _| !to_remove.contains(x)); + + industries::mining::pre_market(&room, creeps, memory); + + info!("Post market"); + + if memory + .rooms + .get_mut(&room.name().to_string()) + .unwrap() + .creep_count + .miner + < MINER_COUNT + { + let spawners = room.find(find::MY_SPAWNS, None); + let n = &uuid::Uuid::new_v4().to_string(); + let spawn = spawners + .first() + .unwrap() + .spawn_creep(&[Part::Move, Part::Work, Part::Work], n); + if let Ok(res) = spawn + { + info!("Ron"); + memory + .rooms + .get_mut(&room.name().to_string()) + .unwrap() + .creep_count + .miner += 1; + memory.create_creep( + &room.name().to_string(), + n, + Task::Miner( + spawners + .first() + .unwrap() + .pos() + .find_closest_by_range(find::SOURCES) + .unwrap() + .id() + ), + ); + } else if let Err(e) = spawn { + info!("Error spawning creep: {:?}", e); + } + } else if memory + .rooms + .get_mut(&room.name().to_string()) + .unwrap() + .creep_count + .hauler + < HAULER_COUNT + { + let spawners = room.find(find::MY_SPAWNS, None); + let n = &uuid::Uuid::new_v4().to_string(); + let spawn = spawners + .first() + .unwrap() + .spawn_creep(&[Part::Move, Part::Move, Part::Carry, Part::Work], n); + if let Ok(res) = spawn { + info!("Sub 1"); + memory + .rooms + .get_mut(&room.name().to_string()) + .unwrap() + .creep_count + .hauler += 1; + memory.create_creep( + &room.name().to_string(), + n, + Task::Hauler( + ObjectId::from_str(&spawners.first().unwrap().id().to_string()).unwrap(), + ), + ) + } else if let Err(e) = spawn { + info!("Error spawning creep: {:?}", e); + } + } +} diff --git a/src/room/industries/mining.rs b/src/room/industries/mining.rs new file mode 100644 index 0000000..55a89b3 --- /dev/null +++ b/src/room/industries/mining.rs @@ -0,0 +1,38 @@ +use log::info; +use screeps::{game, Room}; + +use crate::memory::ScreepsMemory; + +pub fn pre_market( + room: &Room, + creeps: Vec, + memory: &mut ScreepsMemory, +) { + let roommem = memory.rooms.get_mut(&room.name().to_string()).unwrap(); + + for name in creeps { + let creepmem = roommem.creeps.get_mut(&name).unwrap(); + if let Some(work) = &creepmem.work { + if let Some(task) = &work.task { + let creep = game::creeps().get(name).unwrap(); + match task { + crate::memory::Task::Miner(source_id) => { + if let Some(source) = source_id.resolve() { + info!("Run harvester"); + crate::roles::local::harvester::harvest(&creep, creepmem, source) + } else { + creepmem.work = None; + } + } + crate::memory::Task::Hauler(building_id) => { + if let Some(building) = building_id.resolve() { + info!("Run hauler"); + crate::roles::local::hauler::haul(&creep, creepmem, building) + } + } + crate::memory::Task::Rename(_) => {}, + } + } + } + } +} diff --git a/src/industries/mod.rs b/src/room/industries/mod.rs similarity index 100% rename from src/industries/mod.rs rename to src/room/industries/mod.rs diff --git a/src/room/local.rs b/src/room/local.rs deleted file mode 100644 index 9a6c884..0000000 --- a/src/room/local.rs +++ /dev/null @@ -1,17 +0,0 @@ -use screeps::{Room, find, HasPosition}; - -use crate::memory::RoomMemory; - -pub fn run_rom(room: Room, roommem: RoomMemory) { - let controller = room.controller().unwrap(); - match controller.sign() { - Some(sign) => { - if sign.text() != "Ferris FTW!" { - if let Some(creep) = controller.pos().find_closest_by_range(find::MY_CREEPS) { - - } - } - }, - None => todo!(), - } -} \ No newline at end of file diff --git a/src/room/mod.rs b/src/room/mod.rs index 4a9aa0c..2ea5fcc 100644 --- a/src/room/mod.rs +++ b/src/room/mod.rs @@ -1,2 +1,3 @@ -pub mod local; -pub mod spawning; \ No newline at end of file +pub mod democracy; +pub mod building; +pub mod industries; \ No newline at end of file diff --git a/src/room/spawning.rs b/src/room/spawning.rs deleted file mode 100644 index f298328..0000000 --- a/src/room/spawning.rs +++ /dev/null @@ -1,22 +0,0 @@ -use log::warn; -use screeps::{game, Part}; - -use crate::memory::ScreepsMemory; - -pub fn run_spawns(memory: &mut ScreepsMemory) { - let mut additional = 0; - for spawn in game::spawns().values() { - // Default body for now, will be sorted out later. - let body = [Part::Move, Part::Move, Part::Carry, Part::Work]; - if spawn.room().unwrap().energy_available() >= body.iter().map(|p| p.cost()).sum() { - let name = format!("{}-{}", game::time(), additional); - match spawn.spawn_creep(&body, &name) { - Ok(()) => { - additional += 1; - memory.create_creep(&name, spawn.room().unwrap()); - } - Err(e) => warn!("Couldn't spawn: {:?}", e), - } - } - } -} \ No newline at end of file diff --git a/src/visual/map.rs b/src/visual/map.rs new file mode 100644 index 0000000..38de630 --- /dev/null +++ b/src/visual/map.rs @@ -0,0 +1,12 @@ +use std::str::FromStr; + +use screeps::{RoomVisual, RoomName, TextStyle}; + +use crate::memory::ScreepsMemory; + +pub fn classify_rooms(memory: &ScreepsMemory) { + for name in memory.rooms.keys() { + RoomVisual::new(Some(RoomName::from_str(name).unwrap())) + .text(2_f32, 2_f32, "Nerd".to_string(), Some(TextStyle::default().color("#ffffff"))) + } +} \ No newline at end of file diff --git a/src/visual/mod.rs b/src/visual/mod.rs new file mode 100644 index 0000000..36c02b6 --- /dev/null +++ b/src/visual/mod.rs @@ -0,0 +1 @@ +pub mod map; \ No newline at end of file From 8f1eceb3517c4ed181153566ce7f822290ab80b3 Mon Sep 17 00:00:00 2001 From: InfinityDevTech <47366052+InfinityDevTech@users.noreply.github.com> Date: Thu, 24 Aug 2023 21:51:37 -0400 Subject: [PATCH 03/13] Before clippy --- src/memory.rs | 7 +- src/movement/move_target.rs | 4 +- src/roles/local/hauler.rs | 68 ++++++++--- src/roles/local/upgrader.rs | 31 ++++-- src/room/democracy.rs | 167 +++++++++++++++------------- src/room/industries/construction.rs | 32 ++++++ src/room/industries/mining.rs | 5 +- src/room/industries/mod.rs | 3 +- 8 files changed, 201 insertions(+), 116 deletions(-) create mode 100644 src/room/industries/construction.rs diff --git a/src/memory.rs b/src/memory.rs index c88d3a1..5b95eae 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -20,6 +20,9 @@ pub enum Task { Miner(ObjectId), Hauler(ObjectId), + // Construction industry + Upgrader(ObjectId), + // Odd industry Rename(ObjectId), } @@ -59,7 +62,8 @@ pub struct RoomMemory{ }>, pub creep_count: pub struct { pub miner: u8, - pub hauler: u8 + pub hauler: u8, + pub upgrader: u8, } } } @@ -130,6 +134,7 @@ impl ScreepsMemory { creep_count: CreepCount { miner: 0, hauler: 0, + upgrader: 0 }, }, ); diff --git a/src/movement/move_target.rs b/src/movement/move_target.rs index 95e096a..4053a42 100644 --- a/src/movement/move_target.rs +++ b/src/movement/move_target.rs @@ -14,8 +14,8 @@ pub struct MoveTarget { impl MoveTarget { pub fn find_path_to(&mut self, from: Position) -> memory::Movement { let opts = SearchOptions::new(path_call) - .plain_cost(1) - .swamp_cost(1) + .plain_cost(2) + .swamp_cost(5) .max_rooms(1) .max_ops(100000); let search = pathfinder::search(from, self.pos, self.range, Some(opts)); diff --git a/src/roles/local/hauler.rs b/src/roles/local/hauler.rs index 202e481..da9a748 100644 --- a/src/roles/local/hauler.rs +++ b/src/roles/local/hauler.rs @@ -1,30 +1,64 @@ -use screeps::{Creep, SharedCreepProperties, HasPosition, find, ResourceType, Structure, StructureObject}; +use std::cmp::min; + +use log::info; +use screeps::{ + find, Creep, HasPosition, ResourceType, SharedCreepProperties, Structure, StructureObject, +}; use crate::{memory::CreepMemory, movement}; pub fn haul(creep: &Creep, creepmem: &mut CreepMemory, deposit: Structure) { let name = creep.name(); let inventory = creep.store(); - if inventory.get_free_capacity(None) > inventory.get_used_capacity(Some(ResourceType::Energy)) as i32 { - let closest_energy = creep.pos().find_closest_by_path(find::DROPPED_RESOURCES, None); + if inventory.get_free_capacity(None) + > inventory.get_used_capacity(Some(ResourceType::Energy)) as i32 + { + let closest_energy = creep + .pos() + .find_closest_by_path(find::DROPPED_RESOURCES, None); if let Some(energy) = closest_energy { - if creep.pos().is_near_to(energy.clone().pos()) { - let _ = creep.pickup(&energy); - } else { - movement::creep::move_to(&name, creepmem, energy.pos()) - } + if creep.pos().is_near_to(energy.clone().pos()) { + let _ = creep.pickup(&energy); + } else { + movement::creep::move_to(&name, creepmem, energy.pos()) } + } } else { - //let structure_object = StructureObject::from(deposit); - //if let Some(structure) = structure_object.as_transferable() { - // let _ = creep.transfer(structure, ResourceType::Energy, Some(inventory.get_used_capacity(Some(ResourceType::Energy)))); - //} - let csite = creep.pos().find_closest_by_range(find::CONSTRUCTION_SITES); - if let Some(site) = csite { - if creep.pos().is_near_to(site.pos()) { - let _ = creep.build(&site); + let structure_object = StructureObject::from(deposit); + if let Some(structure) = structure_object.as_transferable() { + if structure_object + .as_has_store() + .unwrap() + .store() + .get_free_capacity(Some(ResourceType::Energy)) + > 0 + { + info!("Running haul."); + if creep.pos().is_near_to(structure.pos()) { + let _ = creep.transfer( + structure, + ResourceType::Energy, + Some(min( + inventory.get_used_capacity(Some(ResourceType::Energy)), + structure_object + .as_has_store() + .unwrap() + .store() + .get_free_capacity(Some(ResourceType::Energy)) as u32, + ))); + } else { + movement::creep::move_to(&name, creepmem, structure.pos()); + } } else { - movement::creep::move_to(&name, creepmem, site.pos()) + info!("Running construction."); + let csite = creep.pos().find_closest_by_range(find::CONSTRUCTION_SITES); + if let Some(site) = csite { + if creep.pos().is_near_to(site.pos()) { + let _ = creep.build(&site); + } else { + movement::creep::move_to(&name, creepmem, site.pos()) + } + } } } } diff --git a/src/roles/local/upgrader.rs b/src/roles/local/upgrader.rs index 8fde06a..d372800 100644 --- a/src/roles/local/upgrader.rs +++ b/src/roles/local/upgrader.rs @@ -1,19 +1,26 @@ -use log::warn; -use screeps::{Creep, ErrorCode, SharedCreepProperties, StructureController, HasPosition}; +use screeps::{Creep, SharedCreepProperties, StructureController, HasPosition, ResourceType, find}; use crate::{memory::CreepMemory, movement}; pub fn upgrade(creep: &Creep, creepmem: &mut CreepMemory, controller: StructureController) { let name = creep.name(); - creep - .upgrade_controller(&controller) - .unwrap_or_else(|e| match e { - ErrorCode::NotInRange => { - movement::creep::move_to(&name, creepmem, controller.pos()); + let inventory = creep.store(); + if inventory.get_free_capacity(None) + > inventory.get_used_capacity(Some(ResourceType::Energy)) as i32 + { + let closest_energy = creep + .pos() + .find_closest_by_path(find::DROPPED_RESOURCES, None); + if let Some(energy) = closest_energy { + if creep.pos().is_near_to(energy.clone().pos()) { + let _ = creep.pickup(&energy); + } else { + movement::creep::move_to(&name, creepmem, energy.pos()) } - _ => { - let _ = creep.say("🚧", false); - warn!("Error upgrading controller: {:?}", e); - } - }); + } + } else if creep.pos().is_near_to(controller.pos()) { + let _ = creep.upgrade_controller(&controller); + } else { + movement::creep::move_to(&name, creepmem, controller.pos()) + } } diff --git a/src/room/democracy.rs b/src/room/democracy.rs index ea300fe..01886f0 100644 --- a/src/room/democracy.rs +++ b/src/room/democracy.rs @@ -3,19 +3,28 @@ use std::str::FromStr; use log::info; use screeps::{find, game, HasPosition, HasTypedId, ObjectId, Part, Room}; -use crate::memory::{ScreepsMemory, Task}; +use crate::{memory::{ScreepsMemory, Task}, movement::creep}; use super::industries; const MINER_COUNT: u8 = 2; const HAULER_COUNT: u8 = 2; +const UPGRADER_COUNT: u8 = 2; pub fn start_government(room: Room, memory: &mut ScreepsMemory) { - let mut creeps = Vec::new(); - let mut to_remove = Vec::new(); - // Horray, i did it better. - for name in memory + let creeps = get_creeps_and_clean(memory, &room); + + industries::mining::pre_market(&room, creeps.clone(), memory); + industries::construction::pre_market(&room, creeps.clone(), memory); + + do_spawning(memory, &room); +} + +pub fn get_creeps_and_clean(memory: &mut ScreepsMemory, room: &Room) -> Vec { + let mut to_remove = Vec::new(); + let mut creeps = Vec::new(); + for creep_name in memory .rooms .get_mut(&room.name().to_string()) .unwrap() @@ -23,28 +32,50 @@ pub fn start_government(room: Room, memory: &mut ScreepsMemory) { .clone() .keys() { - for creep_name in memory.clone().rooms.get_mut(&room.name().to_string()).unwrap().creeps.keys() { - info!("Name, {}", creep_name); - if let Some(creep) = game::creeps().get(creep_name.to_string()) { - info!("Found Crep"); - if creep.spawning() {continue;} + info!("Name, {}", creep_name); + if let Some(creep) = game::creeps().get(creep_name.to_string()) { + info!("Found Crep"); + if creep.spawning() { + continue; + } - creeps.push(name.to_string()); - } else if game::creeps().get(creep_name.to_string()).is_none() { - let t = &memory.clone().rooms.get_mut(&room.name().to_string()).unwrap().creeps.get_mut(creep_name).unwrap().work.clone().unwrap().task.unwrap(); - match t { - Task::Miner(_) => { - info!("Subtract 1"); - memory.rooms.get_mut(&room.name().to_string()).unwrap().creep_count.miner -= 1; - }, - Task::Hauler(_) => { - info!("Subtract 1 -2 "); - memory.rooms.get_mut(&room.name().to_string()).unwrap().creep_count.hauler -= 1; - }, - _ => {}, - } - to_remove.push(creep_name.to_string()); + creeps.push(creep_name.to_string()); + } else if game::creeps().get(creep_name.to_string()).is_none() { + let t = &memory + .clone() + .rooms + .get_mut(&room.name().to_string()) + .unwrap() + .creeps + .get_mut(creep_name) + .unwrap() + .work + .clone() + .unwrap() + .task + .unwrap(); + match t { + Task::Miner(_) => { + info!("Subtract 1"); + memory + .rooms + .get_mut(&room.name().to_string()) + .unwrap() + .creep_count + .miner -= 1; + } + Task::Hauler(_) => { + info!("Subtract 1 -2 "); + memory + .rooms + .get_mut(&room.name().to_string()) + .unwrap() + .creep_count + .hauler -= 1; + } + _ => {} } + to_remove.push(creep_name.to_string()); } } memory @@ -53,81 +84,57 @@ pub fn start_government(room: Room, memory: &mut ScreepsMemory) { .unwrap() .creeps .retain(|x, _| !to_remove.contains(x)); + creeps +} - industries::mining::pre_market(&room, creeps, memory); - - info!("Post market"); - - if memory +pub fn do_spawning(memory: &mut ScreepsMemory, room: &Room) { + let creep_count = &mut memory .rooms .get_mut(&room.name().to_string()) .unwrap() - .creep_count - .miner - < MINER_COUNT - { - let spawners = room.find(find::MY_SPAWNS, None); + .creep_count; + + let spawner = room.find(find::MY_SPAWNS, None); + let spawner = spawner.first().unwrap(); + info!("test {:?}", creep_count); + if creep_count.miner < MINER_COUNT { let n = &uuid::Uuid::new_v4().to_string(); - let spawn = spawners - .first() - .unwrap() - .spawn_creep(&[Part::Move, Part::Work, Part::Work], n); - if let Ok(res) = spawn - { - info!("Ron"); - memory - .rooms - .get_mut(&room.name().to_string()) - .unwrap() - .creep_count - .miner += 1; + let spawn = spawner.spawn_creep(&[Part::Move, Part::Work, Part::Work], n); + if spawn.is_ok() { + creep_count.miner += 1; memory.create_creep( &room.name().to_string(), n, Task::Miner( - spawners - .first() - .unwrap() + spawner .pos() .find_closest_by_range(find::SOURCES) .unwrap() - .id() + .id(), ), ); - } else if let Err(e) = spawn { - info!("Error spawning creep: {:?}", e); } - } else if memory - .rooms - .get_mut(&room.name().to_string()) - .unwrap() - .creep_count - .hauler - < HAULER_COUNT - { - let spawners = room.find(find::MY_SPAWNS, None); + } else if creep_count.hauler < HAULER_COUNT { let n = &uuid::Uuid::new_v4().to_string(); - let spawn = spawners - .first() - .unwrap() - .spawn_creep(&[Part::Move, Part::Move, Part::Carry, Part::Work], n); - if let Ok(res) = spawn { - info!("Sub 1"); - memory - .rooms - .get_mut(&room.name().to_string()) - .unwrap() - .creep_count - .hauler += 1; + let spawn = spawner.spawn_creep(&[Part::Move, Part::Move, Part::Carry, Part::Work], n); + if spawn.is_ok() { + creep_count.hauler += 1; memory.create_creep( &room.name().to_string(), n, - Task::Hauler( - ObjectId::from_str(&spawners.first().unwrap().id().to_string()).unwrap(), - ), + Task::Hauler(ObjectId::from_str(&spawner.id().to_string()).unwrap()), + ) + } + } else if creep_count.upgrader < UPGRADER_COUNT { + let n = &uuid::Uuid::new_v4().to_string(); + let spawn = spawner.spawn_creep(&[Part::Move, Part::Move, Part::Carry, Part::Work], n); + if spawn.is_ok() { + creep_count.upgrader += 1; + memory.create_creep( + &room.name().to_string(), + n, + Task::Upgrader(ObjectId::from_str(&room.controller().unwrap().id().to_string()).unwrap()), ) - } else if let Err(e) = spawn { - info!("Error spawning creep: {:?}", e); } } } diff --git a/src/room/industries/construction.rs b/src/room/industries/construction.rs new file mode 100644 index 0000000..1ec58f5 --- /dev/null +++ b/src/room/industries/construction.rs @@ -0,0 +1,32 @@ +use log::info; +use screeps::{game, Room}; + +use crate::memory::ScreepsMemory; + +pub fn pre_market( + room: &Room, + creeps: Vec, + memory: &mut ScreepsMemory, +) { + let roommem = memory.rooms.get_mut(&room.name().to_string()).unwrap(); + info!("{}", creeps.len()); + + for name in creeps { + let creepmem = roommem.creeps.get_mut(&name).unwrap(); + if let Some(work) = &creepmem.work { + if let Some(task) = &work.task { + let creep = game::creeps().get(name).unwrap(); + match task { + crate::memory::Task::Upgrader(controller_id) => { + if let Some(controller) = controller_id.resolve() { + crate::roles::local::upgrader::upgrade(&creep, creepmem, controller) + } else { + creepmem.work = None; + } + }, + _ => {} + } + } + } + } +} diff --git a/src/room/industries/mining.rs b/src/room/industries/mining.rs index 55a89b3..e2aade7 100644 --- a/src/room/industries/mining.rs +++ b/src/room/industries/mining.rs @@ -9,6 +9,7 @@ pub fn pre_market( memory: &mut ScreepsMemory, ) { let roommem = memory.rooms.get_mut(&room.name().to_string()).unwrap(); + info!("{}", creeps.len()); for name in creeps { let creepmem = roommem.creeps.get_mut(&name).unwrap(); @@ -18,7 +19,6 @@ pub fn pre_market( match task { crate::memory::Task::Miner(source_id) => { if let Some(source) = source_id.resolve() { - info!("Run harvester"); crate::roles::local::harvester::harvest(&creep, creepmem, source) } else { creepmem.work = None; @@ -26,11 +26,10 @@ pub fn pre_market( } crate::memory::Task::Hauler(building_id) => { if let Some(building) = building_id.resolve() { - info!("Run hauler"); crate::roles::local::hauler::haul(&creep, creepmem, building) } } - crate::memory::Task::Rename(_) => {}, + _ => {}, } } } diff --git a/src/room/industries/mod.rs b/src/room/industries/mod.rs index 07b0768..98cb259 100644 --- a/src/room/industries/mod.rs +++ b/src/room/industries/mod.rs @@ -1 +1,2 @@ -pub mod mining; \ No newline at end of file +pub mod mining; +pub mod construction; \ No newline at end of file From f9f91cdcf7894a6493f7f6c0d278d633e4d51fb6 Mon Sep 17 00:00:00 2001 From: InfinityDevTech <47366052+InfinityDevTech@users.noreply.github.com> Date: Thu, 24 Aug 2023 21:53:22 -0400 Subject: [PATCH 04/13] After clippy --- src/roles/local/builder.rs | 1 + src/room/building/roads.rs | 2 ++ src/room/democracy.rs | 2 +- src/room/industries/construction.rs | 21 +++++++-------------- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/roles/local/builder.rs b/src/roles/local/builder.rs index aea497d..4847532 100644 --- a/src/roles/local/builder.rs +++ b/src/roles/local/builder.rs @@ -1,3 +1,4 @@ +#![allow(dead_code)] use log::warn; use screeps::{ConstructionSite, Creep, HasPosition, SharedCreepProperties}; diff --git a/src/room/building/roads.rs b/src/room/building/roads.rs index 426934f..7555033 100644 --- a/src/room/building/roads.rs +++ b/src/room/building/roads.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] + use log::info; use screeps::{Source, StructureSpawn, HasPosition, pathfinder::{SearchOptions, MultiRoomCostResult, self}, RoomName, LocalCostMatrix, game, StructureType, find, StructureProperties, look}; diff --git a/src/room/democracy.rs b/src/room/democracy.rs index 01886f0..0e60c72 100644 --- a/src/room/democracy.rs +++ b/src/room/democracy.rs @@ -3,7 +3,7 @@ use std::str::FromStr; use log::info; use screeps::{find, game, HasPosition, HasTypedId, ObjectId, Part, Room}; -use crate::{memory::{ScreepsMemory, Task}, movement::creep}; +use crate::memory::{ScreepsMemory, Task}; use super::industries; diff --git a/src/room/industries/construction.rs b/src/room/industries/construction.rs index 1ec58f5..4bdf0d3 100644 --- a/src/room/industries/construction.rs +++ b/src/room/industries/construction.rs @@ -3,11 +3,7 @@ use screeps::{game, Room}; use crate::memory::ScreepsMemory; -pub fn pre_market( - room: &Room, - creeps: Vec, - memory: &mut ScreepsMemory, -) { +pub fn pre_market(room: &Room, creeps: Vec, memory: &mut ScreepsMemory) { let roommem = memory.rooms.get_mut(&room.name().to_string()).unwrap(); info!("{}", creeps.len()); @@ -16,15 +12,12 @@ pub fn pre_market( if let Some(work) = &creepmem.work { if let Some(task) = &work.task { let creep = game::creeps().get(name).unwrap(); - match task { - crate::memory::Task::Upgrader(controller_id) => { - if let Some(controller) = controller_id.resolve() { - crate::roles::local::upgrader::upgrade(&creep, creepmem, controller) - } else { - creepmem.work = None; - } - }, - _ => {} + if let crate::memory::Task::Upgrader(controller_id) = task { + if let Some(controller) = controller_id.resolve() { + crate::roles::local::upgrader::upgrade(&creep, creepmem, controller) + } else { + creepmem.work = None; + } } } } From 74c9f7565d51075be8fe271281fdf3f5a694544b Mon Sep 17 00:00:00 2001 From: InfinityDevTech <47366052+InfinityDevTech@users.noreply.github.com> Date: Fri, 25 Aug 2023 23:26:17 -0400 Subject: [PATCH 05/13] Changed miner spawning! --- Cargo.lock | 71 ---------- Cargo.toml | 7 +- javascript/main.js | 11 ++ src/lib.rs | 28 ++-- src/memory.rs | 91 +++++++------ src/movement/creep.rs | 18 +-- src/movement/move_target.rs | 14 +- src/roles/local/builder.rs | 1 - src/roles/local/hauler.rs | 1 - src/room/democracy.rs | 203 ++++++++++++++++------------ src/room/industries/construction.rs | 20 ++- src/room/industries/mining.rs | 12 +- src/room/mod.rs | 1 + src/room/population.rs | 100 ++++++++++++++ src/visual/map.rs | 14 +- 15 files changed, 325 insertions(+), 267 deletions(-) create mode 100644 src/room/population.rs diff --git a/Cargo.lock b/Cargo.lock index 8691d86..bc16adf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,15 +41,12 @@ name = "crustacean" version = "0.0.0" dependencies = [ "fern", - "getrandom", "js-sys", "log", - "rand", "screeps-game-api", "serde", "serde_json", "structstruck", - "uuid", "wasm-bindgen", "wasm-bindgen-test", "web-sys", @@ -96,17 +93,6 @@ dependencies = [ "log", ] -[[package]] -name = "getrandom" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - [[package]] name = "heck" version = "0.4.1" @@ -128,12 +114,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "libc" -version = "0.2.147" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - [[package]] name = "log" version = "0.4.19" @@ -166,12 +146,6 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - [[package]] name = "proc-macro2" version = "1.0.66" @@ -190,36 +164,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - [[package]] name = "ryu" version = "1.0.15" @@ -333,15 +277,6 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" -[[package]] -name = "uuid" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" -dependencies = [ - "getrandom", -] - [[package]] name = "venial" version = "0.5.0" @@ -352,12 +287,6 @@ dependencies = [ "quote", ] -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - [[package]] name = "wasm-bindgen" version = "0.2.87" diff --git a/Cargo.toml b/Cargo.toml index d4cfe24..c66974c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,9 +17,6 @@ web-sys = { version = "0.3", features = ["console"] } structstruck = "0.4.1" serde_json = "1.0.104" serde = { version = "1.0.183", features = ["derive"] } -uuid = { version = "1.4.1", features = ["v4"] } -getrandom = { version = "0.2.10", features = ["custom"] } -rand = "0.8.5" [dev-dependencies] wasm-bindgen-test = "0.3" @@ -33,14 +30,14 @@ lto = true # Replace the following to enable wasm-opt optimization # wasm-pack will try to install wasm-opt automatically, but it must be installed by hand on some # operating systems. -wasm-opt = false +#wasm-opt = true # See wasm-opt for full available options; handy examples: # -O4 - optimize aggressively for performance # -Oz - optimize aggressively for code size # -g - leave debug info in place, allowing for more descriptive stack traces on panic # --disable-sign-ext - prevents opcodes that the screeps servers can't load (see # https://github.com/rustyscreeps/screeps-game-api/issues/391) -#wasm-opt = ["-O4", "--disable-sign-ext"] +wasm-opt = ["-O4", "--disable-sign-ext"] [features] default = [] diff --git a/javascript/main.js b/javascript/main.js index a951e2b..94a6e8e 100644 --- a/javascript/main.js +++ b/javascript/main.js @@ -5,6 +5,7 @@ let wasm_module; const MODULE_NAME = "crustacean"; let EXECUTION_PAUSED = false; let RED_BUTTON = false; +let WIPE_MEMORY = false; function console_error(...args) { console.log(...args); @@ -29,6 +30,11 @@ global.big_red_button = function (input) { } }; +global.wipe_memory = function () { + EXECUTION_PAUSED = true; + console.log("Wiping memory"); +} + global.toggle_exec = function () { EXECUTION_PAUSED = !EXECUTION_PAUSED return `Successfully toggled execution pause to: ${EXECUTION_PAUSED}` @@ -53,6 +59,11 @@ module.exports.loop = function () { RED_BUTTON = false; EXECUTION_PAUSED = false; } + if (WIPE_MEMORY) { + wasm_module.wipe_memory(); + WIPE_MEMORY = false; + EXECUTION_PAUSED = false; + } if (!EXECUTION_PAUSED) { wasm_module.loop(); } diff --git a/src/lib.rs b/src/lib.rs index 513a663..3120058 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,6 @@ use std::{collections::HashMap, str::FromStr}; -use getrandom::register_custom_getrandom; use log::*; -use rand::{rngs::StdRng, SeedableRng, RngCore}; use screeps::{find, game, prelude::*, RoomName}; use wasm_bindgen::prelude::*; @@ -15,14 +13,6 @@ mod roles; mod room; mod visual; -fn custom_getrandom(buf: &mut [u8]) -> Result<(), getrandom::Error> { - let mut rng = StdRng::seed_from_u64(js_sys::Math::random().to_bits()); - rng.fill_bytes(buf); - Ok(()) -} - -register_custom_getrandom!(custom_getrandom); - #[wasm_bindgen(js_name = setup)] pub fn setup() { logging::setup_logging(logging::Info); @@ -62,7 +52,7 @@ pub fn recently_respawned(memory: &mut ScreepsMemory) -> bool { #[wasm_bindgen(js_name = loop)] pub fn game_loop() { - debug!("Loop starting! CPU: {}", game::cpu::get_used()); + info!("---------------- CURRENT TICK - {} ----------------", game::time()); let mut memory = ScreepsMemory::init_memory(); if recently_respawned(&mut memory) { @@ -81,7 +71,7 @@ pub fn game_loop() { } for room in memory.clone().rooms.values() { - room::democracy::start_government(game::rooms().get(RoomName::from_str(&room.name).unwrap()).unwrap(), &mut memory); + room::democracy::start_government(game::rooms().get(RoomName::from_str(&room.n).unwrap()).unwrap(), &mut memory); } visual::map::classify_rooms(&memory); @@ -91,7 +81,19 @@ pub fn game_loop() { // This is done like this because its basically MemHack for you JS people. memory.write_memory(); - info!("Done! Cpu used: {}", game::cpu::get_used()); + info!("[DICTATOR] Government ran and memory written... Here are some stats!"); + info!("CPU used: {}. Bucket: {}", game::cpu::get_used(), game::cpu::bucket()); + info!("GCL level {}. Next level: {} / {}", game::gcl::level(), game::gcl::progress(), game::gcl::progress_total()); + info!("Market credits: {}", game::market::credits()); +} + +#[wasm_bindgen(js_name = wipe_memory)] +pub fn wipe_memory() { + let mut memory = ScreepsMemory::init_memory(); + memory.rooms = HashMap::new(); + memory.creeps = HashMap::new(); + memory.spawn_tick = true; + memory.write_memory(); } #[wasm_bindgen(js_name = red_button)] diff --git a/src/memory.rs b/src/memory.rs index 5b95eae..96fc646 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -30,37 +30,39 @@ pub enum Task { structstruck::strike! { #[strikethrough[derive(Serialize, Deserialize, Debug, Clone)]] pub struct CreepMemory{ - pub movement: Option, - pub work: Option, - }> + // Owning room + pub o_r: String, + // Path + pub p: Option, + // Career + pub c: Careers, + // Task + pub t: Option, } } structstruck::strike! { #[strikethrough[derive(Serialize, Deserialize, Debug, Clone)]] pub struct RoomMemory{ - pub name: String, - pub room_type: String, - pub creeps: HashMap, - pub sources: HashMap + // Name + pub n: String, + // Room type + pub r_t: String, + // Creeps + pub cs: Vec, + // Creeps made + pub c_m: u64, + // Initialised + pub init: bool, + // Available mining spots, makes my life easier. + pub avs: u8, + // Mining stuffs + pub mine: HashMap, pub struct { + pub s: u8, + pub u: u8, }>, - pub creep_count: pub struct { + // Creep Count + pub c_c: pub struct { pub miner: u8, pub hauler: u8, pub upgrader: u8, @@ -72,7 +74,7 @@ structstruck::strike! { #[strikethrough[derive(Serialize, Deserialize, Debug, Clone)]] pub struct ScreepsMemory { pub rooms: HashMap, - + pub creeps: HashMap, pub spawn_tick: bool } } @@ -84,6 +86,7 @@ impl ScreepsMemory { if memory_string.is_empty() { let memory = ScreepsMemory { rooms: HashMap::new(), + creeps: HashMap::new(), spawn_tick: true, }; memory.write_memory(); @@ -96,30 +99,29 @@ impl ScreepsMemory { error!("This is a critical error, memory MUST be reset to default state."); ScreepsMemory { rooms: HashMap::new(), - spawn_tick: true + creeps: HashMap::new(), + spawn_tick: true, } } } } } pub fn write_memory(&self) { - info!("Writing memory"); let serialized = serde_json::to_string(&self).unwrap(); let js_serialized = JsString::from(serialized); screeps::raw_memory::set(&js_serialized); } - pub fn create_creep(&mut self, room_name: &str, creep_name: &str, task: Task) { - self.rooms.get_mut(room_name).unwrap().creeps.insert( - creep_name.to_string(), - CreepMemory { - movement: None, - work: Some(Work { - career: Careers::Mining, - task: Some(task), - }), - }, - ); + pub fn create_creep(&mut self, room_name: &str, creep_name: &str, career: Careers, task: Option) { + let room = self.rooms.get_mut(room_name).unwrap(); + let creep = CreepMemory { + p: None, + o_r: room_name.to_string(), + c: career, + t: task, + }; + room.cs.push(creep_name.to_string()); + self.creeps.insert(creep_name.to_string(), creep); info!("Created creep"); } @@ -127,11 +129,14 @@ impl ScreepsMemory { self.rooms.insert( name.to_string(), RoomMemory { - name: name.to_string(), - room_type: "local".to_string(), - creeps: HashMap::new(), - sources: HashMap::new(), - creep_count: CreepCount { + n: name.to_string(), + r_t: "local".to_string(), + init: false, + cs: Vec::new(), + c_m: 0, + avs: 0, + mine: HashMap::new(), + c_c: CC { miner: 0, hauler: 0, upgrader: 0 diff --git a/src/movement/creep.rs b/src/movement/creep.rs index 38e270c..316342c 100644 --- a/src/movement/creep.rs +++ b/src/movement/creep.rs @@ -1,13 +1,13 @@ use log::info; use screeps::{game, Direction, HasPosition, Position}; -use crate::memory::{Movement, CreepMemory}; +use crate::memory::CreepMemory; use super::move_target::MoveTarget; pub fn move_to(creep_name: &String, creep_memory: &mut CreepMemory, target: Position) { let creep = game::creeps().get(creep_name.to_string()).unwrap(); - match &creep_memory.movement { + match &creep_memory.p { Some(path) => { move_by_path(creep_name.to_string(), path.clone(), creep_memory) } @@ -16,20 +16,20 @@ pub fn move_to(creep_name: &String, creep_memory: &mut CreepMemory, target: Posi pos: target, range: 1, }.find_path_to(creep.pos()); - creep_memory.movement = Some(target.clone()); + creep_memory.p = Some(target.clone()); move_by_path(creep_name.to_string(), target, creep_memory); } } } -pub fn move_by_path(creep_name: String, path: Movement, memory: &mut CreepMemory) { +pub fn move_by_path(creep_name: String, path: String, memory: &mut CreepMemory) { let creep = game::creeps().get(creep_name).unwrap(); if creep.fatigue() > 0 { return; } - let serialized_path = path.path; + let serialized_path = path; let serialized_vec = serialized_path.split("").filter(|x| x != &"").map(|x| x.parse::().unwrap()).collect::>(); let step_dir = num_to_dir(serialized_vec[0]); @@ -41,13 +41,9 @@ pub fn move_by_path(creep_name: String, path: Movement, memory: &mut CreepMemory let serialized_vec = serialized_vec[1..].to_vec(); let serialized_path = serialized_vec.iter().map(|x| x.to_string()).collect::>().join(""); if serialized_vec.is_empty() { - memory.movement = None; + memory.p = None } else { - memory.movement = Some(Movement { - dest: path.dest, - path: serialized_path, - room: path.room, - }); + memory.p = Some(serialized_path); } let mut points = vec![]; diff --git a/src/movement/move_target.rs b/src/movement/move_target.rs index 4053a42..9e90ba3 100644 --- a/src/movement/move_target.rs +++ b/src/movement/move_target.rs @@ -4,15 +4,13 @@ use screeps::{ RoomName, StructureObject, find }; -use crate::memory; - pub struct MoveTarget { pub pos: Position, pub range: u32 } impl MoveTarget { - pub fn find_path_to(&mut self, from: Position) -> memory::Movement { + pub fn find_path_to(&mut self, from: Position) -> String { let opts = SearchOptions::new(path_call) .plain_cost(2) .swamp_cost(5) @@ -52,15 +50,7 @@ impl MoveTarget { let intstring = int.to_string(); steps_string = steps_string + &intstring; } - memory::Movement { - dest: memory::Dest { - x: self.pos.x().into(), - y: self.pos.y().into(), - room: self.pos.room_name().to_string(), - }, - path: steps_string, - room: self.pos.room_name().to_string(), - } + steps_string } } diff --git a/src/roles/local/builder.rs b/src/roles/local/builder.rs index 4847532..4447d33 100644 --- a/src/roles/local/builder.rs +++ b/src/roles/local/builder.rs @@ -8,7 +8,6 @@ pub fn build(creep: &Creep, creepmem: &mut CreepMemory, site: ConstructionSite) if creep.pos().is_near_to(site.pos()) { creep.build(&site).unwrap_or_else(|e| { warn!("couldn't build: {:?}", e); - creepmem.work = None; }); } else { movement::creep::move_to(&creep.name(), creepmem, site.pos()); diff --git a/src/roles/local/hauler.rs b/src/roles/local/hauler.rs index da9a748..9801683 100644 --- a/src/roles/local/hauler.rs +++ b/src/roles/local/hauler.rs @@ -33,7 +33,6 @@ pub fn haul(creep: &Creep, creepmem: &mut CreepMemory, deposit: Structure) { .get_free_capacity(Some(ResourceType::Energy)) > 0 { - info!("Running haul."); if creep.pos().is_near_to(structure.pos()) { let _ = creep.transfer( structure, diff --git a/src/room/democracy.rs b/src/room/democracy.rs index 0e60c72..a735868 100644 --- a/src/room/democracy.rs +++ b/src/room/democracy.rs @@ -1,19 +1,63 @@ -use std::str::FromStr; +use std::{collections::HashMap, str::FromStr}; use log::info; -use screeps::{find, game, HasPosition, HasTypedId, ObjectId, Part, Room}; +use screeps::{ + find, game, + look::{self, LookResult}, + HasPosition, HasTypedId, ObjectId, Part, Room, +}; -use crate::memory::{ScreepsMemory, Task}; +use crate::{ + memory::{Mine, ScreepsMemory, Task}, + room::population, +}; use super::industries; -const MINER_COUNT: u8 = 2; -const HAULER_COUNT: u8 = 2; -const UPGRADER_COUNT: u8 = 2; +const HAULER_COUNT: u8 = 4; +const UPGRADER_COUNT: u8 = 4; pub fn start_government(room: Room, memory: &mut ScreepsMemory) { // Horray, i did it better. - let creeps = get_creeps_and_clean(memory, &room); + let creeps = get_room_creeps_and_clean(memory, &room); + let roommem_readonly = memory.rooms.get(&room.name().to_string()).unwrap(); + + if !roommem_readonly.init { + if game::cpu::bucket() >= 100 { + info!("Initialising room: {}", room.name().to_string()); + let sources = room.find(find::SOURCES, None); + let mut mining_spots = HashMap::new(); + for spot in sources { + let x = spot.pos().x().u8(); + let y = spot.pos().y().u8(); + let areas = room.look_for_at_area(look::TERRAIN, y - 1, x - 1, y + 1, x + 1); + let mut available_spots = 0; + for area in areas { + if let LookResult::Terrain(screeps::Terrain::Plain) = area.look_result { + available_spots += 1; + } else if let LookResult::Terrain(screeps::Terrain::Swamp) = area.look_result { + available_spots += 1; + } + } + mining_spots.insert( + spot.id(), + Mine { + u: 0, + s: available_spots, + }, + ); + } + memory.rooms.get_mut(&room.name().to_string()).unwrap().avs = mining_spots.len() as u8; + memory.rooms.get_mut(&room.name().to_string()).unwrap().mine = mining_spots; + memory.rooms.get_mut(&room.name().to_string()).unwrap().init = true; + } else { + info!( + "CPU bucket is too low to initialise room: {}", + room.name().to_string() + ); + return; + } + } industries::mining::pre_market(&room, creeps.clone(), memory); industries::construction::pre_market(&room, creeps.clone(), memory); @@ -21,120 +65,99 @@ pub fn start_government(room: Room, memory: &mut ScreepsMemory) { do_spawning(memory, &room); } -pub fn get_creeps_and_clean(memory: &mut ScreepsMemory, room: &Room) -> Vec { - let mut to_remove = Vec::new(); +pub fn get_room_creeps_and_clean(memory: &mut ScreepsMemory, room: &Room) -> Vec { let mut creeps = Vec::new(); - for creep_name in memory + let mut removed_creeps = 0; + for creep_name in &memory + .clone() .rooms .get_mut(&room.name().to_string()) .unwrap() - .creeps - .clone() - .keys() + .cs { - info!("Name, {}", creep_name); if let Some(creep) = game::creeps().get(creep_name.to_string()) { - info!("Found Crep"); if creep.spawning() { continue; } creeps.push(creep_name.to_string()); } else if game::creeps().get(creep_name.to_string()).is_none() { - let t = &memory - .clone() - .rooms - .get_mut(&room.name().to_string()) - .unwrap() - .creeps - .get_mut(creep_name) - .unwrap() - .work - .clone() - .unwrap() - .task - .unwrap(); - match t { + removed_creeps += 1; + let t = &memory.creeps.get(&creep_name.to_string()).unwrap().t; + match t.clone().unwrap() { Task::Miner(_) => { - info!("Subtract 1"); - memory - .rooms - .get_mut(&room.name().to_string()) - .unwrap() - .creep_count - .miner -= 1; + population::miner_died(memory, creep_name, &room.name().to_string()) } Task::Hauler(_) => { - info!("Subtract 1 -2 "); - memory - .rooms - .get_mut(&room.name().to_string()) - .unwrap() - .creep_count - .hauler -= 1; + population::hauler_died(memory, creep_name, &room.name().to_string()) + } + Task::Upgrader(_) => { + population::upgrader_died(memory, creep_name, &room.name().to_string()) } _ => {} } - to_remove.push(creep_name.to_string()); } } - memory - .rooms - .get_mut(&room.name().to_string()) - .unwrap() - .creeps - .retain(|x, _| !to_remove.contains(x)); + info!("Removed {} creeps this tick.", removed_creeps); creeps } pub fn do_spawning(memory: &mut ScreepsMemory, room: &Room) { - let creep_count = &mut memory - .rooms - .get_mut(&room.name().to_string()) - .unwrap() - .creep_count; + let binding = memory.clone(); + let roommem_readonly = binding.rooms.get(&room.name().to_string()).unwrap(); + let binding = room.find(find::MY_SPAWNS, None); + let spawn = binding.first().unwrap(); - let spawner = room.find(find::MY_SPAWNS, None); - let spawner = spawner.first().unwrap(); - info!("test {:?}", creep_count); - if creep_count.miner < MINER_COUNT { - let n = &uuid::Uuid::new_v4().to_string(); - let spawn = spawner.spawn_creep(&[Part::Move, Part::Work, Part::Work], n); - if spawn.is_ok() { - creep_count.miner += 1; + if population::create_miner(memory, room.clone()) { + } else if roommem_readonly.c_c.hauler < HAULER_COUNT { + let name = format!("h-{}", roommem_readonly.c_m); + let body = [Part::Move, Part::Move, Part::Carry, Part::Work]; + let spawn_res = spawn.spawn_creep(&body, &name); + if spawn_res.is_ok() { memory.create_creep( &room.name().to_string(), - n, - Task::Miner( - spawner - .pos() - .find_closest_by_range(find::SOURCES) - .unwrap() - .id(), - ), + &name, + crate::memory::Careers::Mining, + Some(Task::Hauler( + ObjectId::from_str( + &room + .find(find::MY_SPAWNS, None) + .first() + .unwrap() + .id() + .to_string(), + ) + .unwrap(), + )), ); + memory + .rooms + .get_mut(&room.name().to_string()) + .unwrap() + .c_c + .hauler += 1; + memory.rooms.get_mut(&room.name().to_string()).unwrap().c_m += 1; } - } else if creep_count.hauler < HAULER_COUNT { - let n = &uuid::Uuid::new_v4().to_string(); - let spawn = spawner.spawn_creep(&[Part::Move, Part::Move, Part::Carry, Part::Work], n); - if spawn.is_ok() { - creep_count.hauler += 1; - memory.create_creep( - &room.name().to_string(), - n, - Task::Hauler(ObjectId::from_str(&spawner.id().to_string()).unwrap()), - ) - } - } else if creep_count.upgrader < UPGRADER_COUNT { - let n = &uuid::Uuid::new_v4().to_string(); - let spawn = spawner.spawn_creep(&[Part::Move, Part::Move, Part::Carry, Part::Work], n); - if spawn.is_ok() { - creep_count.upgrader += 1; + } else if roommem_readonly.c_c.upgrader < UPGRADER_COUNT { + let name = format!("u-{}", roommem_readonly.c_m); + let body = [Part::Move, Part::Carry, Part::Carry, Part::Work]; + let spawn_res = spawn.spawn_creep(&body, &name); + if spawn_res.is_ok() { memory.create_creep( &room.name().to_string(), - n, - Task::Upgrader(ObjectId::from_str(&room.controller().unwrap().id().to_string()).unwrap()), - ) + &name, + crate::memory::Careers::Mining, + Some(Task::Upgrader( + ObjectId::from_str(&room.controller().unwrap().id().to_string()).unwrap(), + )), + ); + memory + .rooms + .get_mut(&room.name().to_string()) + .unwrap() + .c_c + .upgrader += 1; + memory.rooms.get_mut(&room.name().to_string()).unwrap().c_m += 1; } } } diff --git a/src/room/industries/construction.rs b/src/room/industries/construction.rs index 4bdf0d3..0798d11 100644 --- a/src/room/industries/construction.rs +++ b/src/room/industries/construction.rs @@ -4,21 +4,19 @@ use screeps::{game, Room}; use crate::memory::ScreepsMemory; pub fn pre_market(room: &Room, creeps: Vec, memory: &mut ScreepsMemory) { - let roommem = memory.rooms.get_mut(&room.name().to_string()).unwrap(); - info!("{}", creeps.len()); + info!("[INDUSTRIES] Running construction industry"); for name in creeps { - let creepmem = roommem.creeps.get_mut(&name).unwrap(); - if let Some(work) = &creepmem.work { - if let Some(task) = &work.task { - let creep = game::creeps().get(name).unwrap(); - if let crate::memory::Task::Upgrader(controller_id) = task { - if let Some(controller) = controller_id.resolve() { - crate::roles::local::upgrader::upgrade(&creep, creepmem, controller) - } else { - creepmem.work = None; + let creepmem = memory.creeps.get_mut(&name).unwrap(); + if let Some(task) = &creepmem.t { + let creep = game::creeps().get(name).unwrap(); + match task { + crate::memory::Task::Upgrader(controller_id) => { + if let Some(building) = controller_id.resolve() { + crate::roles::local::upgrader::upgrade(&creep, creepmem, building) } } + _ => {} } } } diff --git a/src/room/industries/mining.rs b/src/room/industries/mining.rs index e2aade7..01eef2d 100644 --- a/src/room/industries/mining.rs +++ b/src/room/industries/mining.rs @@ -8,20 +8,19 @@ pub fn pre_market( creeps: Vec, memory: &mut ScreepsMemory, ) { - let roommem = memory.rooms.get_mut(&room.name().to_string()).unwrap(); - info!("{}", creeps.len()); + + info!("[INDUSTRIES] Running mining industry..."); for name in creeps { - let creepmem = roommem.creeps.get_mut(&name).unwrap(); - if let Some(work) = &creepmem.work { - if let Some(task) = &work.task { + let creepmem = memory.creeps.get_mut(&name).unwrap(); + if let Some(task) = &creepmem.t { let creep = game::creeps().get(name).unwrap(); match task { crate::memory::Task::Miner(source_id) => { if let Some(source) = source_id.resolve() { crate::roles::local::harvester::harvest(&creep, creepmem, source) } else { - creepmem.work = None; + creepmem.t = None; } } crate::memory::Task::Hauler(building_id) => { @@ -31,7 +30,6 @@ pub fn pre_market( } _ => {}, } - } } } } diff --git a/src/room/mod.rs b/src/room/mod.rs index 2ea5fcc..49a03d9 100644 --- a/src/room/mod.rs +++ b/src/room/mod.rs @@ -1,3 +1,4 @@ pub mod democracy; +pub mod population; pub mod building; pub mod industries; \ No newline at end of file diff --git a/src/room/population.rs b/src/room/population.rs new file mode 100644 index 0000000..b0ec9ea --- /dev/null +++ b/src/room/population.rs @@ -0,0 +1,100 @@ +use screeps::{Room, Part, find}; + +use crate::memory::{ScreepsMemory, Task}; + +pub fn create_miner(memory: &mut ScreepsMemory, room: Room) -> bool { + let sources = memory.clone().rooms.get(&room.name().to_string()).unwrap().mine.clone(); + let mut selected_source = None; + for (source_id, source_mem) in sources { + if selected_source.is_none() && source_mem.s > source_mem.u { + selected_source = Some(source_id); + } else { + continue; + } + } + if let Some(source) = selected_source { + let name = format!("m-{}", memory.rooms.get(&room.name().to_string()).unwrap().c_m); + let body = [Part::Move, Part::Work, Part::Work]; + let spawn_res = room.find(find::MY_SPAWNS, None).first().unwrap().spawn_creep(&body, &name); + if spawn_res.is_ok() { + memory.create_creep( + &room.name().to_string(), + &name, + crate::memory::Careers::Mining, + Some(Task::Miner(source)), + ); + memory.rooms.get_mut(&room.name().to_string()).unwrap().c_c.miner += 1; + memory.rooms.get_mut(&room.name().to_string()).unwrap().c_m += 1; + memory.rooms.get_mut(&room.name().to_string()).unwrap().mine.get_mut(&source).unwrap().u += 1; + true + } else { + false + } + } else { + false + } +} + +pub fn miner_died(memory: &mut ScreepsMemory, name: &str, room: &str) { + // Remove from rooms creep count and from room creep list + memory.rooms.get_mut(room).unwrap().c_c.miner -= 1; + memory.rooms.get_mut(room).unwrap().cs = memory + .rooms + .get_mut(room) + .unwrap() + .cs + .iter() + .filter(|x| x != &&name.to_string()) + .map(|x| x.to_string()) + .collect(); + + // Downtick the counters for used sources + let mining_source_id = memory.creeps.get(name).unwrap().t.clone().unwrap(); + if let Task::Miner(source_id) = mining_source_id { + memory + .rooms + .get_mut(room) + .unwrap() + .mine + .get_mut(&source_id) + .unwrap() + .u -= 1; + } + + // Remove said creep from memory + memory.creeps.remove(name); +} + +pub fn hauler_died(memory: &mut ScreepsMemory, name: &str, room: &str) { + // Remove from rooms creep count and from room creep list + memory.rooms.get_mut(room).unwrap().c_c.hauler -= 1; + memory.rooms.get_mut(room).unwrap().cs = memory + .rooms + .get_mut(room) + .unwrap() + .cs + .iter() + .filter(|x| x != &&name.to_string()) + .map(|x| x.to_string()) + .collect(); + + // Remove said creep from memory + memory.creeps.remove(name); +} + +pub fn upgrader_died(memory: &mut ScreepsMemory, name: &str, room: &str) { + // Remove from rooms creep count and from room creep list + memory.rooms.get_mut(room).unwrap().c_c.hauler -= 1; + memory.rooms.get_mut(room).unwrap().cs = memory + .rooms + .get_mut(room) + .unwrap() + .cs + .iter() + .filter(|x| x != &&name.to_string()) + .map(|x| x.to_string()) + .collect(); + + // Remove said creep from memory + memory.creeps.remove(name); +} \ No newline at end of file diff --git a/src/visual/map.rs b/src/visual/map.rs index 38de630..a5e3806 100644 --- a/src/visual/map.rs +++ b/src/visual/map.rs @@ -1,12 +1,22 @@ use std::str::FromStr; -use screeps::{RoomVisual, RoomName, TextStyle}; +use screeps::{RoomVisual, RoomName, TextStyle, game}; use crate::memory::ScreepsMemory; pub fn classify_rooms(memory: &ScreepsMemory) { for name in memory.rooms.keys() { + let roommem = memory.rooms.get(name).unwrap(); RoomVisual::new(Some(RoomName::from_str(name).unwrap())) - .text(2_f32, 2_f32, "Nerd".to_string(), Some(TextStyle::default().color("#ffffff"))) + .text(1_f32, 1_f32, "Stats".to_string(), Some(TextStyle::default().color("#ffffff").align(screeps::TextAlign::Left))); + + RoomVisual::new(Some(RoomName::from_str(name).unwrap())) + .text(1_f32, 2_f32, format!("Miners: {}", roommem.c_c.miner), Some(TextStyle::default().color("#ffffff").align(screeps::TextAlign::Left))); + + RoomVisual::new(Some(RoomName::from_str(name).unwrap())) + .text(1_f32, 3_f32, format!("Haulers: {}", roommem.c_c.hauler), Some(TextStyle::default().color("#ffffff").align(screeps::TextAlign::Left))); + + RoomVisual::new(Some(RoomName::from_str(name).unwrap())) + .text(1_f32, 4_f32, format!("Upgraders: {}", roommem.c_c.upgrader), Some(TextStyle::default().color("#ffffff").align(screeps::TextAlign::Left))); } } \ No newline at end of file From 5e21397d49bc5a810eae56f1eac704381fa906a0 Mon Sep 17 00:00:00 2001 From: InfinityDevTech <47366052+InfinityDevTech@users.noreply.github.com> Date: Sat, 26 Aug 2023 22:52:06 -0400 Subject: [PATCH 06/13] Sync --- src/lib.rs | 23 ++++++++++++++++++++--- src/logging.rs | 3 +-- src/memory.rs | 5 +++++ src/roles/local/hauler.rs | 22 ++++++++++++++++++++-- src/room/democracy.rs | 8 +++++--- src/room/population.rs | 1 + 6 files changed, 52 insertions(+), 10 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 3120058..a02826b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,7 +4,7 @@ use log::*; use screeps::{find, game, prelude::*, RoomName}; use wasm_bindgen::prelude::*; -use crate::memory::ScreepsMemory; +use crate::memory::{ScreepsMemory, Stats}; mod logging; mod memory; @@ -70,21 +70,38 @@ pub fn game_loop() { memory.spawn_tick = false } + if game::time() % 10 == 0 { + for room in game::rooms().values() { + if let Some(controller) = room.controller() { + if controller.my() && !memory.rooms.get(&room.name().to_string()).unwrap().init { + memory.create_room(&room.name().to_string()); + } + } + } + } + for room in memory.clone().rooms.values() { room::democracy::start_government(game::rooms().get(RoomName::from_str(&room.n).unwrap()).unwrap(), &mut memory); } visual::map::classify_rooms(&memory); - // Bot is finished, write the local copy of memory. + // Bot is finished, write the stats and local copy of memory. // This is run only once per tick as it serializes the memory. // This is done like this because its basically MemHack for you JS people. - memory.write_memory(); info!("[DICTATOR] Government ran and memory written... Here are some stats!"); info!("CPU used: {}. Bucket: {}", game::cpu::get_used(), game::cpu::bucket()); info!("GCL level {}. Next level: {} / {}", game::gcl::level(), game::gcl::progress(), game::gcl::progress_total()); info!("Market credits: {}", game::market::credits()); + if memory.stats.is_some() { + info!("Creeps removed this tick: {}", memory.stats.as_mut().unwrap().crm); + memory.stats = Some(Stats { + crm: 0, + }); + } + + memory.write_memory(); } #[wasm_bindgen(js_name = wipe_memory)] diff --git a/src/logging.rs b/src/logging.rs index 3554dad..9579620 100644 --- a/src/logging.rs +++ b/src/logging.rs @@ -31,9 +31,8 @@ pub fn setup_logging(verbosity: log::LevelFilter) { .level(verbosity) .format(|out, message, record| { out.finish(format_args!( - "({}) {}: {}", + "({}) {}", record.level(), - record.target(), message )) }) diff --git a/src/memory.rs b/src/memory.rs index 96fc646..710f16e 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -75,6 +75,9 @@ structstruck::strike! { pub struct ScreepsMemory { pub rooms: HashMap, pub creeps: HashMap, + pub stats: Option, pub spawn_tick: bool } } @@ -87,6 +90,7 @@ impl ScreepsMemory { let memory = ScreepsMemory { rooms: HashMap::new(), creeps: HashMap::new(), + stats: None, spawn_tick: true, }; memory.write_memory(); @@ -100,6 +104,7 @@ impl ScreepsMemory { ScreepsMemory { rooms: HashMap::new(), creeps: HashMap::new(), + stats: None, spawn_tick: true, } } diff --git a/src/roles/local/hauler.rs b/src/roles/local/hauler.rs index 9801683..a142e4f 100644 --- a/src/roles/local/hauler.rs +++ b/src/roles/local/hauler.rs @@ -5,7 +5,7 @@ use screeps::{ find, Creep, HasPosition, ResourceType, SharedCreepProperties, Structure, StructureObject, }; -use crate::{memory::CreepMemory, movement}; +use crate::{memory::CreepMemory, movement::{self, creep}}; pub fn haul(creep: &Creep, creepmem: &mut CreepMemory, deposit: Structure) { let name = creep.name(); @@ -24,6 +24,25 @@ pub fn haul(creep: &Creep, creepmem: &mut CreepMemory, deposit: Structure) { } } } else { + if let Some(sign) = creep.room().unwrap().controller().unwrap().sign() { + if sign.text() != "Ferris FTW!" { + let controller = creep.room().unwrap().controller().unwrap(); + if creep.pos().is_near_to(controller.pos()) { + let _ = creep.sign_controller(&controller, "Ferris FTW!"); + } else { + movement::creep::move_to(&name, creepmem, controller.pos()); + } + return; + } + } else { + let controller = creep.room().unwrap().controller().unwrap(); + if creep.pos().is_near_to(controller.pos()) { + let _ = creep.sign_controller(&controller, "Ferris FTW!"); + } else { + movement::creep::move_to(&name, creepmem, controller.pos()); + } + return; + } let structure_object = StructureObject::from(deposit); if let Some(structure) = structure_object.as_transferable() { if structure_object @@ -49,7 +68,6 @@ pub fn haul(creep: &Creep, creepmem: &mut CreepMemory, deposit: Structure) { movement::creep::move_to(&name, creepmem, structure.pos()); } } else { - info!("Running construction."); let csite = creep.pos().find_closest_by_range(find::CONSTRUCTION_SITES); if let Some(site) = csite { if creep.pos().is_near_to(site.pos()) { diff --git a/src/room/democracy.rs b/src/room/democracy.rs index a735868..d3abae4 100644 --- a/src/room/democracy.rs +++ b/src/room/democracy.rs @@ -98,7 +98,9 @@ pub fn get_room_creeps_and_clean(memory: &mut ScreepsMemory, room: &Room) -> Vec } } } - info!("Removed {} creeps this tick.", removed_creeps); + if memory.stats.is_some() { + memory.stats.as_mut().unwrap().crm += removed_creeps; + } creeps } @@ -109,7 +111,7 @@ pub fn do_spawning(memory: &mut ScreepsMemory, room: &Room) { let spawn = binding.first().unwrap(); if population::create_miner(memory, room.clone()) { - } else if roommem_readonly.c_c.hauler < HAULER_COUNT { + } else if memory.rooms.get(&room.name().to_string()).unwrap().c_c.hauler < (memory.rooms.get(&room.name().to_string()).unwrap().c_c.miner / 2) { let name = format!("h-{}", roommem_readonly.c_m); let body = [Part::Move, Part::Move, Part::Carry, Part::Work]; let spawn_res = spawn.spawn_creep(&body, &name); @@ -138,7 +140,7 @@ pub fn do_spawning(memory: &mut ScreepsMemory, room: &Room) { .hauler += 1; memory.rooms.get_mut(&room.name().to_string()).unwrap().c_m += 1; } - } else if roommem_readonly.c_c.upgrader < UPGRADER_COUNT { + } else if memory.rooms.get(&room.name().to_string()).unwrap().c_c.upgrader < UPGRADER_COUNT { let name = format!("u-{}", roommem_readonly.c_m); let body = [Part::Move, Part::Carry, Part::Carry, Part::Work]; let spawn_res = spawn.spawn_creep(&body, &name); diff --git a/src/room/population.rs b/src/room/population.rs index b0ec9ea..ff71af3 100644 --- a/src/room/population.rs +++ b/src/room/population.rs @@ -3,6 +3,7 @@ use screeps::{Room, Part, find}; use crate::memory::{ScreepsMemory, Task}; pub fn create_miner(memory: &mut ScreepsMemory, room: Room) -> bool { + if memory.rooms.get(&room.name().to_string()).unwrap().c_c.miner >= 1 && memory.rooms.get(&room.name().to_string()).unwrap().c_c.hauler < 1 {return false;} let sources = memory.clone().rooms.get(&room.name().to_string()).unwrap().mine.clone(); let mut selected_source = None; for (source_id, source_mem) in sources { From 3ff51d541d1ad1fd94646304c042ae8c9e7005fe Mon Sep 17 00:00:00 2001 From: InfinityDevTech <47366052+InfinityDevTech@users.noreply.github.com> Date: Sun, 27 Aug 2023 12:53:10 -0400 Subject: [PATCH 07/13] fix --- src/lib.rs | 2 +- src/roles/local/hauler.rs | 3 +-- src/room/democracy.rs | 1 - src/room/planning/mod.rs | 0 src/visual/map.rs | 22 ---------------- src/visual/mod.rs | 2 +- src/visual/room.rs | 54 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 57 insertions(+), 27 deletions(-) create mode 100644 src/room/planning/mod.rs delete mode 100644 src/visual/map.rs create mode 100644 src/visual/room.rs diff --git a/src/lib.rs b/src/lib.rs index a02826b..ba3afe3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -84,7 +84,7 @@ pub fn game_loop() { room::democracy::start_government(game::rooms().get(RoomName::from_str(&room.n).unwrap()).unwrap(), &mut memory); } - visual::map::classify_rooms(&memory); + visual::room::classify_rooms(&memory); // Bot is finished, write the stats and local copy of memory. // This is run only once per tick as it serializes the memory. diff --git a/src/roles/local/hauler.rs b/src/roles/local/hauler.rs index a142e4f..90ebd12 100644 --- a/src/roles/local/hauler.rs +++ b/src/roles/local/hauler.rs @@ -1,11 +1,10 @@ use std::cmp::min; -use log::info; use screeps::{ find, Creep, HasPosition, ResourceType, SharedCreepProperties, Structure, StructureObject, }; -use crate::{memory::CreepMemory, movement::{self, creep}}; +use crate::{memory::CreepMemory, movement}; pub fn haul(creep: &Creep, creepmem: &mut CreepMemory, deposit: Structure) { let name = creep.name(); diff --git a/src/room/democracy.rs b/src/room/democracy.rs index d3abae4..69855c3 100644 --- a/src/room/democracy.rs +++ b/src/room/democracy.rs @@ -14,7 +14,6 @@ use crate::{ use super::industries; -const HAULER_COUNT: u8 = 4; const UPGRADER_COUNT: u8 = 4; pub fn start_government(room: Room, memory: &mut ScreepsMemory) { diff --git a/src/room/planning/mod.rs b/src/room/planning/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/visual/map.rs b/src/visual/map.rs deleted file mode 100644 index a5e3806..0000000 --- a/src/visual/map.rs +++ /dev/null @@ -1,22 +0,0 @@ -use std::str::FromStr; - -use screeps::{RoomVisual, RoomName, TextStyle, game}; - -use crate::memory::ScreepsMemory; - -pub fn classify_rooms(memory: &ScreepsMemory) { - for name in memory.rooms.keys() { - let roommem = memory.rooms.get(name).unwrap(); - RoomVisual::new(Some(RoomName::from_str(name).unwrap())) - .text(1_f32, 1_f32, "Stats".to_string(), Some(TextStyle::default().color("#ffffff").align(screeps::TextAlign::Left))); - - RoomVisual::new(Some(RoomName::from_str(name).unwrap())) - .text(1_f32, 2_f32, format!("Miners: {}", roommem.c_c.miner), Some(TextStyle::default().color("#ffffff").align(screeps::TextAlign::Left))); - - RoomVisual::new(Some(RoomName::from_str(name).unwrap())) - .text(1_f32, 3_f32, format!("Haulers: {}", roommem.c_c.hauler), Some(TextStyle::default().color("#ffffff").align(screeps::TextAlign::Left))); - - RoomVisual::new(Some(RoomName::from_str(name).unwrap())) - .text(1_f32, 4_f32, format!("Upgraders: {}", roommem.c_c.upgrader), Some(TextStyle::default().color("#ffffff").align(screeps::TextAlign::Left))); - } -} \ No newline at end of file diff --git a/src/visual/mod.rs b/src/visual/mod.rs index 36c02b6..64a5b51 100644 --- a/src/visual/mod.rs +++ b/src/visual/mod.rs @@ -1 +1 @@ -pub mod map; \ No newline at end of file +pub mod room; \ No newline at end of file diff --git a/src/visual/room.rs b/src/visual/room.rs new file mode 100644 index 0000000..bf873eb --- /dev/null +++ b/src/visual/room.rs @@ -0,0 +1,54 @@ +use std::str::FromStr; + +use screeps::{control, game, HasPosition, RoomName, RoomVisual, TextStyle}; + +use crate::memory::ScreepsMemory; + +pub fn classify_rooms(memory: &ScreepsMemory) { + for name in memory.rooms.keys() { + let roommem = memory.rooms.get(name).unwrap(); + if let Some(room) = game::rooms().get(RoomName::from_str(name).unwrap()) { + let roomvis = RoomVisual::new(Some(RoomName::from_str(name).unwrap())); + let white_left = Some( + TextStyle::default() + .color("#ffffff") + .align(screeps::TextAlign::Left), + ); + // Creep counters + roomvis.text(1_f32, 1_f32, "Stats".to_string(), white_left.clone()); + roomvis.text( + 1_f32, + 2_f32, + format!("Miners: {}", roommem.c_c.miner), + white_left.clone(), + ); + roomvis.text( + 1_f32, + 3_f32, + format!("Haulers: {}", roommem.c_c.hauler), + white_left.clone(), + ); + roomvis.text( + 1_f32, + 4_f32, + format!("Upgraders: {}", roommem.c_c.upgrader), + white_left.clone(), + ); + + let controller = room.controller().unwrap(); + roomvis.text( + controller.pos().x().u8() as f32, + (controller.pos().y().u8() + 1) as f32, + format!( + "% {:.2}", + (controller.progress() * 100) / controller.progress_total() + ), + Some( + TextStyle::default() + .color("#ffffff") + .align(screeps::TextAlign::Center), + ), + ); + } + } +} From d999616c55ff984d7b4905f1635767fb8191a197 Mon Sep 17 00:00:00 2001 From: InfinityDevTech <47366052+InfinityDevTech@users.noreply.github.com> Date: Sun, 27 Aug 2023 13:37:39 -0400 Subject: [PATCH 08/13] Added screeps.toml --- .gitignore | 2 +- screeps.toml | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 screeps.toml diff --git a/.gitignore b/.gitignore index 387ab4e..c6e922c 100644 --- a/.gitignore +++ b/.gitignore @@ -33,4 +33,4 @@ nbproject *.iws *.sublime-project *.sublime-workspace -screeps.toml +#screeps.toml diff --git a/screeps.toml b/screeps.toml new file mode 100644 index 0000000..505bd49 --- /dev/null +++ b/screeps.toml @@ -0,0 +1,33 @@ +default_deploy_mode = "upload" + +[build] +# options to allow building code against rust versions >=1.70 without opcodes +# incompatible with screeps server environments; requires nightly rust. See +# https://github.com/rustyscreeps/screeps-game-api/issues/391 +extra_options = ["--config", "build.rustflags=['-Ctarget-cpu=mvp']", "-Z", "build-std=std,panic_abort", "-Z", "build-std-features=panic_immediate_abort"] + +[upload] +auth_token = "fbfeb887-6c37-4ef9-922f-01eea5b927f0" +[upload.build] + build-target="release" + +[ptr] +auth_token = "your screeps.com auth token" +prefix = "ptr" + +[copy] +destination = "/home/jwjoh/.config/Screeps/scripts/vps_bezoka_pl___21025" +#destination = "/home/jwjoh/.config/Screeps/scripts/127_0_0_1___21025" +[copy.build] + # set the sim feature to allow for use with the coordinates in the simulation room + extra_options = ["--features=sim", "--config", "build.rustflags=['-Ctarget-cpu=mvp']", "-Z", "build-std=std,panic_abort", "-Z", "build-std-features=panic_immediate_abort"] + build-target = "release" + +[season] +auth_token = "your screeps.com auth token" +prefix = "season" + [season.build] + extra_options = ["--features=my-crate-season-1-feature", "--config", "build.rustflags=['-Ctarget-cpu=mvp']", "-Z", "build-std=std,panic_abort", "-Z", "build-std-features=panic_immediate_abort"] + +# for full syntax and available options, see +# https://github.com/rustyscreeps/screeps-game-api/blob/master/screeps-defaults.toml \ No newline at end of file From b7bf3593941bd136ba648936a7ce33658a1dabba Mon Sep 17 00:00:00 2001 From: InfinityDevTech <47366052+InfinityDevTech@users.noreply.github.com> Date: Mon, 28 Aug 2023 23:51:02 -0400 Subject: [PATCH 09/13] Changed a bit, idk if it works. --- Cargo.toml | 15 ++--- javascript/main.js | 7 ++- screeps.toml | 5 +- src/lib.rs | 51 +++++++++++----- src/memory.rs | 76 +++++++++++++++++++---- src/movement/creep.rs | 84 -------------------------- src/movement/mod.rs | 4 +- src/movement/move_target.rs | 1 + src/movement/utils.rs | 68 +++++++++++++++++++++ src/roles/local/builder.rs | 53 ++++++++++++---- src/roles/local/harvester.rs | 14 +++-- src/roles/local/hauler.rs | 94 ++++++++++++++++------------- src/roles/local/upgrader.rs | 9 ++- src/room/democracy.rs | 89 ++++++++++++++++++--------- src/room/industries/construction.rs | 10 ++- src/room/industries/mining.rs | 10 +-- src/room/population.rs | 48 ++++++++++----- src/traits/creep.rs | 73 ++++++++++++++++++++++ src/traits/mod.rs | 2 + src/traits/room.rs | 9 +++ src/visual/room.rs | 12 +++- 21 files changed, 493 insertions(+), 241 deletions(-) delete mode 100644 src/movement/creep.rs create mode 100644 src/movement/utils.rs create mode 100644 src/traits/creep.rs create mode 100644 src/traits/mod.rs create mode 100644 src/traits/room.rs diff --git a/Cargo.toml b/Cargo.toml index c66974c..41a5875 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,23 +21,24 @@ serde = { version = "1.0.183", features = ["derive"] } [dev-dependencies] wasm-bindgen-test = "0.3" -[profile.release] -panic = "abort" -opt-level = 3 -lto = true +#[profile.release] +#panic = "abort" +#opt-level = 3 +#lto = true [package.metadata.wasm-pack.profile.release] # Replace the following to enable wasm-opt optimization # wasm-pack will try to install wasm-opt automatically, but it must be installed by hand on some # operating systems. -#wasm-opt = true +#wasm-opt = false # See wasm-opt for full available options; handy examples: # -O4 - optimize aggressively for performance # -Oz - optimize aggressively for code size # -g - leave debug info in place, allowing for more descriptive stack traces on panic -# --disable-sign-ext - prevents opcodes that the screeps servers can't load (see +# --disable-sign-ext - prevents opcodes that the screeps servers can't load (see # https://github.com/rustyscreeps/screeps-game-api/issues/391) -wasm-opt = ["-O4", "--disable-sign-ext"] +#wasm-opt = ["-O4", "--disable-sign-ext"] +wasm-opt = ["-g", "--disable-sign-ext"] [features] default = [] diff --git a/javascript/main.js b/javascript/main.js index 94a6e8e..32c1f88 100644 --- a/javascript/main.js +++ b/javascript/main.js @@ -32,6 +32,7 @@ global.big_red_button = function (input) { global.wipe_memory = function () { EXECUTION_PAUSED = true; + WIPE_MEMORY = true; console.log("Wiping memory"); } @@ -54,6 +55,9 @@ module.exports.loop = function () { global.Memory = {}; try { if (wasm_module) { + if (!EXECUTION_PAUSED) { + wasm_module.loop(); + } if (RED_BUTTON) { wasm_module.red_button(); RED_BUTTON = false; @@ -64,9 +68,6 @@ module.exports.loop = function () { WIPE_MEMORY = false; EXECUTION_PAUSED = false; } - if (!EXECUTION_PAUSED) { - wasm_module.loop(); - } } else { // attempt to load the wasm only if there's enough bucket to do a bunch of work this tick if (Game.cpu.bucket < 500) { diff --git a/screeps.toml b/screeps.toml index 505bd49..c627e8a 100644 --- a/screeps.toml +++ b/screeps.toml @@ -16,12 +16,13 @@ auth_token = "your screeps.com auth token" prefix = "ptr" [copy] -destination = "/home/jwjoh/.config/Screeps/scripts/vps_bezoka_pl___21025" +#destination = "/home/jwjoh/.config/Screeps/scripts/vps_bezoka_pl___21025" #destination = "/home/jwjoh/.config/Screeps/scripts/127_0_0_1___21025" +destination = "/home/jwjoh/.config/Screeps/scripts/super_directconnect_wyatt_world___21025" [copy.build] # set the sim feature to allow for use with the coordinates in the simulation room extra_options = ["--features=sim", "--config", "build.rustflags=['-Ctarget-cpu=mvp']", "-Z", "build-std=std,panic_abort", "-Z", "build-std-features=panic_immediate_abort"] - build-target = "release" + #build-target = "release" [season] auth_token = "your screeps.com auth token" diff --git a/src/lib.rs b/src/lib.rs index ba3afe3..1d6ae9a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,7 +4,7 @@ use log::*; use screeps::{find, game, prelude::*, RoomName}; use wasm_bindgen::prelude::*; -use crate::memory::{ScreepsMemory, Stats}; +use crate::{memory::ScreepsMemory, traits::room::RoomExtensions}; mod logging; mod memory; @@ -12,6 +12,7 @@ mod movement; mod roles; mod room; mod visual; +mod traits; #[wasm_bindgen(js_name = setup)] pub fn setup() { @@ -53,17 +54,23 @@ pub fn recently_respawned(memory: &mut ScreepsMemory) -> bool { #[wasm_bindgen(js_name = loop)] pub fn game_loop() { info!("---------------- CURRENT TICK - {} ----------------", game::time()); + let before_memory = game::cpu::get_used(); let mut memory = ScreepsMemory::init_memory(); + memory.stats.cpu.memory += game::cpu::get_used() - before_memory; + memory.stats.cpu.rooms = 0.0; + memory.stats.cpu.memory = 0.0; + memory.stats.cpu.total = 0.0; + memory.stats.cpu.bucket = 0; if recently_respawned(&mut memory) { for room in game::rooms().keys() { let room = game::rooms().get(room).unwrap(); - if memory.rooms.get(&room.name().to_string()).is_some() { + if memory.rooms.get(&room.name_str()).is_some() { continue; } if let Some(controller) = room.controller() { if controller.my() { - memory.create_room(&room.name().to_string()); + memory.create_room(&room.name_str()); } } } @@ -73,11 +80,26 @@ pub fn game_loop() { if game::time() % 10 == 0 { for room in game::rooms().values() { if let Some(controller) = room.controller() { - if controller.my() && !memory.rooms.get(&room.name().to_string()).unwrap().init { - memory.create_room(&room.name().to_string()); + if controller.my() && !memory.get_room(&room.name_str()).init { + memory.create_room(&room.name_str()); } } } + for creep in memory.clone().creeps.keys() { + if game::creeps().get(creep.clone()).is_none() { + memory.creeps.remove(creep); + } + } + for room in memory.clone().rooms.values() { + let mut to_remove = Vec::new(); + for creep_name in room.cs.clone() { + if game::creeps().get(creep_name.clone()).is_none() { + to_remove.push(creep_name); + } + } + memory.get_room(&room.n).cs = room.cs.clone().into_iter().filter(|x| !to_remove.contains(x)).collect(); + } + } for room in memory.clone().rooms.values() { @@ -89,19 +111,19 @@ pub fn game_loop() { // Bot is finished, write the stats and local copy of memory. // This is run only once per tick as it serializes the memory. // This is done like this because its basically MemHack for you JS people. + memory.stats.cpu.total = game::cpu::get_used(); + memory.stats.cpu.bucket = game::cpu::bucket(); + memory.write_memory(); info!("[DICTATOR] Government ran and memory written... Here are some stats!"); - info!("CPU used: {}. Bucket: {}", game::cpu::get_used(), game::cpu::bucket()); info!("GCL level {}. Next level: {} / {}", game::gcl::level(), game::gcl::progress(), game::gcl::progress_total()); info!("Market credits: {}", game::market::credits()); - if memory.stats.is_some() { - info!("Creeps removed this tick: {}", memory.stats.as_mut().unwrap().crm); - memory.stats = Some(Stats { - crm: 0, - }); - } - - memory.write_memory(); + info!("Creeps removed this tick: {}", memory.stats.cpu.rooms); + info!("CPU Usage:"); + info!(" Rooms: {}", memory.stats.cpu.rooms); + info!(" Memory: {}", memory.stats.cpu.rooms); + info!(" Total: {}", game::cpu::get_used()); + info!(" Bucket: {}", game::cpu::bucket()); } #[wasm_bindgen(js_name = wipe_memory)] @@ -111,6 +133,7 @@ pub fn wipe_memory() { memory.creeps = HashMap::new(); memory.spawn_tick = true; memory.write_memory(); + info!("Memory wiped and written!"); } #[wasm_bindgen(js_name = red_button)] diff --git a/src/memory.rs b/src/memory.rs index 710f16e..c316519 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -1,13 +1,11 @@ use std::collections::HashMap; use log::{error, info}; -use screeps::{ObjectId, Source, StructureController, Structure}; +use screeps::{game, ObjectId, Source, Structure, StructureController}; use serde::{Deserialize, Serialize}; use js_sys::JsString; - - #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] pub enum Careers { Mining, @@ -22,6 +20,7 @@ pub enum Task { // Construction industry Upgrader(ObjectId), + Builder(), // Odd industry Rename(ObjectId), @@ -38,9 +37,12 @@ pub struct CreepMemory{ pub c: Careers, // Task pub t: Option, + // State + pub s: String, } } + structstruck::strike! { #[strikethrough[derive(Serialize, Deserialize, Debug, Clone)]] pub struct RoomMemory{ @@ -66,6 +68,7 @@ pub struct RoomMemory{ pub miner: u8, pub hauler: u8, pub upgrader: u8, + pub builder: u8, } } } @@ -75,46 +78,67 @@ structstruck::strike! { pub struct ScreepsMemory { pub rooms: HashMap, pub creeps: HashMap, - pub stats: Option, + pub stats: pub struct { + pub cpu: pub struct { + pub memory: f64, + pub rooms: f64, + pub total: f64, + pub bucket: i32, + }, + pub rooms: HashMap, + }, pub spawn_tick: bool } } impl ScreepsMemory { pub fn init_memory() -> Self { + let memory_jsstring = screeps::raw_memory::get(); let memory_string = memory_jsstring.as_string().unwrap(); if memory_string.is_empty() { - let memory = ScreepsMemory { + let mut memory = ScreepsMemory { rooms: HashMap::new(), creeps: HashMap::new(), - stats: None, + stats: Stats { cpu: Cpu { memory: 0.0, rooms: 0.0, total: 0.0, bucket: 0 }, rooms: HashMap::new() }, spawn_tick: true, }; memory.write_memory(); memory } else { - match serde_json::from_str(&memory_string) { - Ok(memory) => memory, + match serde_json::from_str::(&memory_string) { + Ok(memory) => { + memory + }, Err(e) => { error!("Error parsing memory: {}", e); error!("This is a critical error, memory MUST be reset to default state."); + ScreepsMemory { rooms: HashMap::new(), creeps: HashMap::new(), - stats: None, + stats: Stats { cpu: Cpu { memory: 0.0, rooms: 0.0, total: 0.0, bucket: 0 }, rooms: HashMap::new() }, spawn_tick: true, } } } } } - pub fn write_memory(&self) { + + pub fn write_memory(&mut self) { + let starting_cpu = game::cpu::get_used(); + self.stats.cpu.memory += game::cpu::get_used() - starting_cpu; let serialized = serde_json::to_string(&self).unwrap(); let js_serialized = JsString::from(serialized); screeps::raw_memory::set(&js_serialized); + self.stats.cpu.memory += game::cpu::get_used() - starting_cpu; } pub fn create_creep(&mut self, room_name: &str, creep_name: &str, career: Careers, task: Option) { @@ -124,6 +148,7 @@ impl ScreepsMemory { o_r: room_name.to_string(), c: career, t: task, + s: "energy".to_string(), }; room.cs.push(creep_name.to_string()); self.creeps.insert(creep_name.to_string(), creep); @@ -144,9 +169,34 @@ impl ScreepsMemory { c_c: CC { miner: 0, hauler: 0, - upgrader: 0 + upgrader: 0, + builder: 0, }, }, ); } + + pub fn get_room(&mut self, name: &str) -> &mut RoomMemory { + self.rooms.get_mut(&name.to_string()).unwrap() + } + + pub fn get_creep(&mut self, name: &str) -> &mut CreepMemory { + self.creeps.get_mut(&name.to_string()).unwrap() + } } + +impl Stats { + pub fn create_room(&mut self, name: &str, rcl: u8) { + self.rooms.insert( + name.to_string(), + Rooms { + creeps_made: 0, + mining: 0.0, + construction: 0.0, + rcl, + creeps_removed: 0, + cpu: 0.0, + } + ); + } +} \ No newline at end of file diff --git a/src/movement/creep.rs b/src/movement/creep.rs deleted file mode 100644 index 316342c..0000000 --- a/src/movement/creep.rs +++ /dev/null @@ -1,84 +0,0 @@ -use log::info; -use screeps::{game, Direction, HasPosition, Position}; - -use crate::memory::CreepMemory; - -use super::move_target::MoveTarget; - -pub fn move_to(creep_name: &String, creep_memory: &mut CreepMemory, target: Position) { - let creep = game::creeps().get(creep_name.to_string()).unwrap(); - match &creep_memory.p { - Some(path) => { - move_by_path(creep_name.to_string(), path.clone(), creep_memory) - } - None => { - let target = MoveTarget { - pos: target, - range: 1, - }.find_path_to(creep.pos()); - creep_memory.p = Some(target.clone()); - move_by_path(creep_name.to_string(), target, creep_memory); - } - - } -} - -pub fn move_by_path(creep_name: String, path: String, memory: &mut CreepMemory) { - let creep = game::creeps().get(creep_name).unwrap(); - - if creep.fatigue() > 0 { - return; - } - let serialized_path = path; - let serialized_vec = serialized_path.split("").filter(|x| x != &"").map(|x| x.parse::().unwrap()).collect::>(); - let step_dir = num_to_dir(serialized_vec[0]); - - match creep.move_direction(step_dir) { - Ok(_) => {}, - Err(e) => info!("Creep move failed, {:?}", e), - }; - - let serialized_vec = serialized_vec[1..].to_vec(); - let serialized_path = serialized_vec.iter().map(|x| x.to_string()).collect::>().join(""); - if serialized_vec.is_empty() { - memory.p = None - } else { - memory.p = Some(serialized_path); - } - - let mut points = vec![]; - let mut cursor = (creep.pos().x().u8() as f32, creep.pos().y().u8() as f32); - for step in serialized_vec { - let dir = num_to_dir(step); - let (x, y) = dir_to_coords(dir, cursor.0, cursor.1); - points.push((x, y)); - cursor = (x, y); - } -} - -pub fn num_to_dir(num: u8) -> Direction { - match num { - 1 => Direction::Top, - 2 => Direction::TopRight, - 3 => Direction::Right, - 4 => Direction::BottomRight, - 5 => Direction::Bottom, - 6 => Direction::BottomLeft, - 7 => Direction::Left, - 8 => Direction::TopLeft, - _ => Direction::Top, - } -} - -pub fn dir_to_coords(dir: Direction, x: f32, y: f32) -> (f32, f32) { - match dir { - Direction::Top => (x, y - 1_f32), - Direction::TopRight => (x + 1_f32, y - 1_f32), - Direction::Right => (x + 1_f32, y), - Direction::BottomRight => (x + 1_f32, y + 1_f32), - Direction::Bottom => (x, y + 1_f32), - Direction::BottomLeft => (x - 1_f32, y + 1_f32), - Direction::Left => (x - 1_f32, y), - Direction::TopLeft => (x - 1_f32, y - 1_f32), - } -} diff --git a/src/movement/mod.rs b/src/movement/mod.rs index 920f6a8..e993586 100644 --- a/src/movement/mod.rs +++ b/src/movement/mod.rs @@ -1,2 +1,2 @@ -pub mod creep; -pub mod move_target; \ No newline at end of file +pub mod move_target; +pub mod utils; \ No newline at end of file diff --git a/src/movement/move_target.rs b/src/movement/move_target.rs index 9e90ba3..0bb9bf7 100644 --- a/src/movement/move_target.rs +++ b/src/movement/move_target.rs @@ -48,6 +48,7 @@ impl MoveTarget { for dirint in steps { let int = dirint as u8; let intstring = int.to_string(); + steps_string = steps_string + &intstring; } steps_string diff --git a/src/movement/utils.rs b/src/movement/utils.rs new file mode 100644 index 0000000..1559b91 --- /dev/null +++ b/src/movement/utils.rs @@ -0,0 +1,68 @@ +use screeps::{Direction, game, RoomName, PolyStyle, RectStyle}; + +pub fn visualise_path(path: String, room_name: String, starting_pos: (f32, f32)) { + let room = game::rooms() + .get(RoomName::new(&room_name).unwrap()) + .unwrap(); + let room_vis = room.visual(); + let mut points = vec![]; + let mut cursor = starting_pos; + + for step in path.split("") { + if step.is_empty() || step == " " { + continue; + } + let dir = num_to_dir(step.parse::().unwrap()); + points.push((cursor.0, cursor.1)); + let (x, y) = dir_to_coords(dir, cursor.0, cursor.1); + cursor = (x, y); + } + points.push((cursor.0, cursor.1)); + room_vis.poly( + points, + Some( + PolyStyle::default() + .stroke("#ff0000") + .line_style(screeps::LineDrawStyle::Dashed), + ), + ); + room_vis.rect( + cursor.0 - 0.5, + cursor.1 - 0.5, + 1.0, + 1.0, + Some( + RectStyle::default() + .stroke("#ff0000") + .fill("#ff0000") + .opacity(0.2), + ), + ); +} + +pub fn num_to_dir(num: u8) -> Direction { + match num { + 1 => Direction::Top, + 2 => Direction::TopRight, + 3 => Direction::Right, + 4 => Direction::BottomRight, + 5 => Direction::Bottom, + 6 => Direction::BottomLeft, + 7 => Direction::Left, + 8 => Direction::TopLeft, + _ => Direction::Top, + } +} + +pub fn dir_to_coords(dir: Direction, x: f32, y: f32) -> (f32, f32) { + match dir { + Direction::Top => (x, y - 1_f32), + Direction::TopRight => (x + 1_f32, y - 1_f32), + Direction::Right => (x + 1_f32, y), + Direction::BottomRight => (x + 1_f32, y + 1_f32), + Direction::Bottom => (x, y + 1_f32), + Direction::BottomLeft => (x - 1_f32, y + 1_f32), + Direction::Left => (x - 1_f32, y), + Direction::TopLeft => (x - 1_f32, y - 1_f32), + } +} \ No newline at end of file diff --git a/src/roles/local/builder.rs b/src/roles/local/builder.rs index 4447d33..df4305e 100644 --- a/src/roles/local/builder.rs +++ b/src/roles/local/builder.rs @@ -1,15 +1,44 @@ #![allow(dead_code)] -use log::warn; -use screeps::{ConstructionSite, Creep, HasPosition, SharedCreepProperties}; - -use crate::{memory::CreepMemory, movement}; - -pub fn build(creep: &Creep, creepmem: &mut CreepMemory, site: ConstructionSite) { - if creep.pos().is_near_to(site.pos()) { - creep.build(&site).unwrap_or_else(|e| { - warn!("couldn't build: {:?}", e); - }); - } else { - movement::creep::move_to(&creep.name(), creepmem, site.pos()); +use screeps::{find, Creep, HasPosition, ResourceType}; + +use crate::{memory::CreepMemory, traits::creep::CreepExtensions}; + +pub fn run_creep(creep: &Creep, creepmem: &mut CreepMemory) { + if creepmem.s == "energy" { + find_energy(creep, creepmem); + } else if creepmem.s == "work" { + build(creep, creepmem); } } + +pub fn build(creep: &Creep, creepmem: &mut CreepMemory) { + let closest_site = creep.pos().find_closest_by_range(find::CONSTRUCTION_SITES); + if let Some(site) = closest_site { + if creep.pos().is_near_to(site.clone().pos()) { + let _ = creep.build(&site); + } else { + creep.better_move_to(creepmem, site.pos(), 1) + } + } + if creep.store().get_used_capacity(Some(ResourceType::Energy)) == 0 { + creepmem.s = "energy".to_string(); + find_energy(creep, creepmem); + } +} + +pub fn find_energy(creep: &Creep, creepmem: &mut CreepMemory) { + let closest_energy = creep + .pos() + .find_closest_by_range(find::DROPPED_RESOURCES); + if let Some(energy) = closest_energy { + if creep.pos().is_near_to(energy.clone().pos()) { + let _ = creep.pickup(&energy); + } else { + creep.better_move_to(creepmem, energy.pos(), 1) + } + } + if creep.store().get_free_capacity(Some(ResourceType::Energy)) == 0 { + creepmem.s = "work".to_string(); + build(creep, creepmem); + } +} diff --git a/src/roles/local/harvester.rs b/src/roles/local/harvester.rs index 2b979bd..ea648e8 100644 --- a/src/roles/local/harvester.rs +++ b/src/roles/local/harvester.rs @@ -1,19 +1,25 @@ use log::warn; -use screeps::{Source, HasPosition, Creep, SharedCreepProperties, ResourceType}; +use screeps::{Source, HasPosition, Creep, ResourceType}; -use crate::{memory::CreepMemory, movement}; +use crate::{memory::CreepMemory, traits::creep::CreepExtensions}; pub fn harvest(creep: &Creep, creepmem: &mut CreepMemory, source: Source) { - let name = creep.name(); if creep.pos().is_near_to(source.pos()) { + if creep.store().get_free_capacity(Some(ResourceType::Energy)) > creep.store().get_used_capacity(Some(ResourceType::Energy)) as i32 { + let _ = creep.drop(ResourceType::Energy, Some(creep.store().get_used_capacity(Some(ResourceType::Energy)))); + } else { + creep.harvest(&source).unwrap_or_else(|e| { warn!("couldn't harvest: {:?}", e); }); + } } else { - movement::creep::move_to(&name, creepmem, source.pos()) + + creep.better_move_to(creepmem, source.pos(), 1) + } } \ No newline at end of file diff --git a/src/roles/local/hauler.rs b/src/roles/local/hauler.rs index 90ebd12..a701229 100644 --- a/src/roles/local/hauler.rs +++ b/src/roles/local/hauler.rs @@ -4,45 +4,42 @@ use screeps::{ find, Creep, HasPosition, ResourceType, SharedCreepProperties, Structure, StructureObject, }; -use crate::{memory::CreepMemory, movement}; +use crate::{memory::CreepMemory, traits::creep::CreepExtensions}; -pub fn haul(creep: &Creep, creepmem: &mut CreepMemory, deposit: Structure) { - let name = creep.name(); - let inventory = creep.store(); - if inventory.get_free_capacity(None) - > inventory.get_used_capacity(Some(ResourceType::Energy)) as i32 - { - let closest_energy = creep +pub fn run_creep(creep: &Creep, creepmem: &mut CreepMemory, deposit: Structure) { + if creepmem.s == "energy" { + get_energy(creep, creepmem); + if creep.store().get_free_capacity(Some(ResourceType::Energy)) == 0 { + creepmem.s = "work".to_string(); + haul_energy(creep, creepmem, deposit); + } + } else if creepmem.s == "work" && rename(creep, creepmem) { + haul_energy(creep, creepmem, deposit); + if creep.store().get_used_capacity(Some(ResourceType::Energy)) == 0 { + creepmem.s = "energy".to_string(); + get_energy(creep, creepmem); + } + } +} + +pub fn get_energy(creep: &Creep, creepmem: &mut CreepMemory) { + let closest_energy = creep .pos() - .find_closest_by_path(find::DROPPED_RESOURCES, None); + .find_closest_by_range(find::DROPPED_RESOURCES); if let Some(energy) = closest_energy { if creep.pos().is_near_to(energy.clone().pos()) { let _ = creep.pickup(&energy); } else { - movement::creep::move_to(&name, creepmem, energy.pos()) + creep.better_move_to(creepmem, energy.pos(), 1) } } - } else { - if let Some(sign) = creep.room().unwrap().controller().unwrap().sign() { - if sign.text() != "Ferris FTW!" { - let controller = creep.room().unwrap().controller().unwrap(); - if creep.pos().is_near_to(controller.pos()) { - let _ = creep.sign_controller(&controller, "Ferris FTW!"); - } else { - movement::creep::move_to(&name, creepmem, controller.pos()); - } - return; - } - } else { - let controller = creep.room().unwrap().controller().unwrap(); - if creep.pos().is_near_to(controller.pos()) { - let _ = creep.sign_controller(&controller, "Ferris FTW!"); - } else { - movement::creep::move_to(&name, creepmem, controller.pos()); - } - return; + if creep.store().get_free_capacity(Some(ResourceType::Energy)) == 0 { + creepmem.s = "work".to_string(); } - let structure_object = StructureObject::from(deposit); +} + +pub fn haul_energy(creep: &Creep, creepmem: &mut CreepMemory, deposit: Structure) { + let structure_object = StructureObject::from(deposit); if let Some(structure) = structure_object.as_transferable() { if structure_object .as_has_store() @@ -56,7 +53,7 @@ pub fn haul(creep: &Creep, creepmem: &mut CreepMemory, deposit: Structure) { structure, ResourceType::Energy, Some(min( - inventory.get_used_capacity(Some(ResourceType::Energy)), + creep.store().get_used_capacity(Some(ResourceType::Energy)), structure_object .as_has_store() .unwrap() @@ -64,18 +61,33 @@ pub fn haul(creep: &Creep, creepmem: &mut CreepMemory, deposit: Structure) { .get_free_capacity(Some(ResourceType::Energy)) as u32, ))); } else { - movement::creep::move_to(&name, creepmem, structure.pos()); + creep.better_move_to(creepmem, structure.pos(), 1); } + } + } +} + +pub fn rename(creep: &Creep, creepmem: &mut CreepMemory) -> bool { + if let Some(sign) = creep.room().unwrap().controller().unwrap().sign() { + if sign.text() != "Ferris FTW!" { + let controller = creep.room().unwrap().controller().unwrap(); + if creep.pos().is_near_to(controller.pos()) { + let _ = creep.sign_controller(&controller, "Ferris FTW!"); + return false; } else { - let csite = creep.pos().find_closest_by_range(find::CONSTRUCTION_SITES); - if let Some(site) = csite { - if creep.pos().is_near_to(site.pos()) { - let _ = creep.build(&site); - } else { - movement::creep::move_to(&name, creepmem, site.pos()) - } - } + creep.better_move_to(creepmem, controller.pos(), 1); + return false; } } + true + } else { + let controller = creep.room().unwrap().controller().unwrap(); + if creep.pos().is_near_to(controller.pos()) { + let _ = creep.sign_controller(&controller, "Ferris FTW!"); + false + } else { + creep.better_move_to(creepmem, controller.pos(), 1); + false + } } -} +} \ No newline at end of file diff --git a/src/roles/local/upgrader.rs b/src/roles/local/upgrader.rs index d372800..47071a2 100644 --- a/src/roles/local/upgrader.rs +++ b/src/roles/local/upgrader.rs @@ -1,9 +1,8 @@ -use screeps::{Creep, SharedCreepProperties, StructureController, HasPosition, ResourceType, find}; +use screeps::{Creep, StructureController, HasPosition, ResourceType, find}; -use crate::{memory::CreepMemory, movement}; +use crate::{memory::CreepMemory, traits::creep::CreepExtensions}; pub fn upgrade(creep: &Creep, creepmem: &mut CreepMemory, controller: StructureController) { - let name = creep.name(); let inventory = creep.store(); if inventory.get_free_capacity(None) > inventory.get_used_capacity(Some(ResourceType::Energy)) as i32 @@ -15,12 +14,12 @@ pub fn upgrade(creep: &Creep, creepmem: &mut CreepMemory, controller: StructureC if creep.pos().is_near_to(energy.clone().pos()) { let _ = creep.pickup(&energy); } else { - movement::creep::move_to(&name, creepmem, energy.pos()) + creep.better_move_to(creepmem, energy.pos(), 1); } } } else if creep.pos().is_near_to(controller.pos()) { let _ = creep.upgrade_controller(&controller); } else { - movement::creep::move_to(&name, creepmem, controller.pos()) + creep.better_move_to(creepmem, controller.pos(), 2) } } diff --git a/src/room/democracy.rs b/src/room/democracy.rs index 69855c3..f571b9d 100644 --- a/src/room/democracy.rs +++ b/src/room/democracy.rs @@ -9,19 +9,24 @@ use screeps::{ use crate::{ memory::{Mine, ScreepsMemory, Task}, - room::population, + room::population, traits::room::RoomExtensions, }; use super::industries; -const UPGRADER_COUNT: u8 = 4; +const UPGRADER_COUNT: u8 = 8; +const BUILDER_COUNT: u8 = 4; pub fn start_government(room: Room, memory: &mut ScreepsMemory) { + let starting_cpu = game::cpu::get_used(); + if memory.stats.rooms.get(&room.name_str()).is_none() { + memory.stats.create_room(&room.name_str(), room.controller().unwrap().level()); + } // Horray, i did it better. let creeps = get_room_creeps_and_clean(memory, &room); - let roommem_readonly = memory.rooms.get(&room.name().to_string()).unwrap(); + let roommem = memory.get_room(&room.name_str()); - if !roommem_readonly.init { + if !roommem.init { if game::cpu::bucket() >= 100 { info!("Initialising room: {}", room.name().to_string()); let sources = room.find(find::SOURCES, None); @@ -46,9 +51,9 @@ pub fn start_government(room: Room, memory: &mut ScreepsMemory) { }, ); } - memory.rooms.get_mut(&room.name().to_string()).unwrap().avs = mining_spots.len() as u8; - memory.rooms.get_mut(&room.name().to_string()).unwrap().mine = mining_spots; - memory.rooms.get_mut(&room.name().to_string()).unwrap().init = true; + roommem.avs = mining_spots.len() as u8; + roommem.mine = mining_spots; + roommem.init = true; } else { info!( "CPU bucket is too low to initialise room: {}", @@ -62,6 +67,8 @@ pub fn start_government(room: Room, memory: &mut ScreepsMemory) { industries::construction::pre_market(&room, creeps.clone(), memory); do_spawning(memory, &room); + memory.stats.cpu.rooms += game::cpu::get_used() - starting_cpu; + memory.stats.rooms.get_mut(&room.name_str()).unwrap().cpu += game::cpu::get_used() - starting_cpu; } pub fn get_room_creeps_and_clean(memory: &mut ScreepsMemory, room: &Room) -> Vec { @@ -70,7 +77,7 @@ pub fn get_room_creeps_and_clean(memory: &mut ScreepsMemory, room: &Room) -> Vec for creep_name in &memory .clone() .rooms - .get_mut(&room.name().to_string()) + .get_mut(&room.name_str()) .unwrap() .cs { @@ -82,41 +89,51 @@ pub fn get_room_creeps_and_clean(memory: &mut ScreepsMemory, room: &Room) -> Vec creeps.push(creep_name.to_string()); } else if game::creeps().get(creep_name.to_string()).is_none() { removed_creeps += 1; - let t = &memory.creeps.get(&creep_name.to_string()).unwrap().t; - match t.clone().unwrap() { + match &memory + .creeps + .get(&creep_name.to_string()) + .unwrap() + .t + .clone() + .unwrap() + { Task::Miner(_) => { - population::miner_died(memory, creep_name, &room.name().to_string()) + population::miner_died(memory, creep_name, &room.name_str()) } Task::Hauler(_) => { - population::hauler_died(memory, creep_name, &room.name().to_string()) + population::hauler_died(memory, creep_name, &room.name_str()) } Task::Upgrader(_) => { - population::upgrader_died(memory, creep_name, &room.name().to_string()) + population::upgrader_died(memory, creep_name, &room.name_str()) + } + Task::Builder() => { + population::builder_died(memory, creep_name, &room.name_str()) } _ => {} } } } - if memory.stats.is_some() { - memory.stats.as_mut().unwrap().crm += removed_creeps; - } + memory.stats.rooms.get_mut(&room.name_str()).unwrap().creeps_removed += removed_creeps; creeps } pub fn do_spawning(memory: &mut ScreepsMemory, room: &Room) { let binding = memory.clone(); - let roommem_readonly = binding.rooms.get(&room.name().to_string()).unwrap(); + let roommem_readonly = binding.rooms.get(&room.name_str()).unwrap(); let binding = room.find(find::MY_SPAWNS, None); let spawn = binding.first().unwrap(); + let room_name = &room.name_str(); if population::create_miner(memory, room.clone()) { - } else if memory.rooms.get(&room.name().to_string()).unwrap().c_c.hauler < (memory.rooms.get(&room.name().to_string()).unwrap().c_c.miner / 2) { + } else if memory.get_room(&room.name_str()).c_c.hauler + <= ((memory.get_room(&room.name_str()).c_c.miner / 2) as f32).round() as u8 + { let name = format!("h-{}", roommem_readonly.c_m); let body = [Part::Move, Part::Move, Part::Carry, Part::Work]; let spawn_res = spawn.spawn_creep(&body, &name); if spawn_res.is_ok() { memory.create_creep( - &room.name().to_string(), + room_name, &name, crate::memory::Careers::Mining, Some(Task::Hauler( @@ -131,21 +148,17 @@ pub fn do_spawning(memory: &mut ScreepsMemory, room: &Room) { .unwrap(), )), ); - memory - .rooms - .get_mut(&room.name().to_string()) - .unwrap() - .c_c - .hauler += 1; - memory.rooms.get_mut(&room.name().to_string()).unwrap().c_m += 1; + memory.get_room(&room.name_str()).c_c.hauler += 1; + memory.get_room(&room.name_str()).c_m += 1; + memory.stats.rooms.get_mut(&room.name_str()).unwrap().creeps_made += 1; } - } else if memory.rooms.get(&room.name().to_string()).unwrap().c_c.upgrader < UPGRADER_COUNT { + } else if memory.get_room(&room.name_str()).c_c.upgrader < UPGRADER_COUNT { let name = format!("u-{}", roommem_readonly.c_m); let body = [Part::Move, Part::Carry, Part::Carry, Part::Work]; let spawn_res = spawn.spawn_creep(&body, &name); if spawn_res.is_ok() { memory.create_creep( - &room.name().to_string(), + room_name, &name, crate::memory::Careers::Mining, Some(Task::Upgrader( @@ -154,11 +167,27 @@ pub fn do_spawning(memory: &mut ScreepsMemory, room: &Room) { ); memory .rooms - .get_mut(&room.name().to_string()) + .get_mut(&room.name_str()) .unwrap() .c_c .upgrader += 1; - memory.rooms.get_mut(&room.name().to_string()).unwrap().c_m += 1; + memory.get_room(&room.name_str()).c_m += 1; + memory.stats.rooms.get_mut(&room.name_str()).unwrap().creeps_made += 1; + } + } else if memory.get_room(&room.name_str()).c_c.builder < BUILDER_COUNT { + let name = format!("b-{}", roommem_readonly.c_m); + let body = [Part::Move, Part::Carry, Part::Carry, Part::Work]; + let spawn_res = spawn.spawn_creep(&body, &name); + if spawn_res.is_ok() { + memory.create_creep( + room_name, + &name, + crate::memory::Careers::Mining, + Some(Task::Builder()), + ); + memory.get_room(&room.name_str()).c_c.builder += 1; + memory.get_room(&room.name_str()).c_m += 1; + memory.stats.rooms.get_mut(&room.name_str()).unwrap().creeps_made += 1; } } } diff --git a/src/room/industries/construction.rs b/src/room/industries/construction.rs index 0798d11..05191cb 100644 --- a/src/room/industries/construction.rs +++ b/src/room/industries/construction.rs @@ -1,13 +1,14 @@ use log::info; use screeps::{game, Room}; -use crate::memory::ScreepsMemory; +use crate::{memory::ScreepsMemory, traits::room::RoomExtensions}; pub fn pre_market(room: &Room, creeps: Vec, memory: &mut ScreepsMemory) { + let starting_cpu = game::cpu::get_used(); info!("[INDUSTRIES] Running construction industry"); for name in creeps { - let creepmem = memory.creeps.get_mut(&name).unwrap(); + let creepmem = memory.get_creep(&name); if let Some(task) = &creepmem.t { let creep = game::creeps().get(name).unwrap(); match task { @@ -16,8 +17,13 @@ pub fn pre_market(room: &Room, creeps: Vec, memory: &mut ScreepsMemory) crate::roles::local::upgrader::upgrade(&creep, creepmem, building) } } + crate::memory::Task::Builder() => { + crate::roles::local::builder::run_creep(&creep, creepmem); + } _ => {} } } } + + memory.stats.rooms.get_mut(&room.name_str()).unwrap().construction += game::cpu::get_used() - starting_cpu; } diff --git a/src/room/industries/mining.rs b/src/room/industries/mining.rs index 01eef2d..e9b0ada 100644 --- a/src/room/industries/mining.rs +++ b/src/room/industries/mining.rs @@ -1,18 +1,18 @@ use log::info; use screeps::{game, Room}; -use crate::memory::ScreepsMemory; +use crate::{memory::ScreepsMemory, traits::room::RoomExtensions}; pub fn pre_market( room: &Room, creeps: Vec, memory: &mut ScreepsMemory, ) { - + let starting_cpu = game::cpu::get_used(); info!("[INDUSTRIES] Running mining industry..."); for name in creeps { - let creepmem = memory.creeps.get_mut(&name).unwrap(); + let creepmem = memory.get_creep(&name); if let Some(task) = &creepmem.t { let creep = game::creeps().get(name).unwrap(); match task { @@ -25,11 +25,13 @@ pub fn pre_market( } crate::memory::Task::Hauler(building_id) => { if let Some(building) = building_id.resolve() { - crate::roles::local::hauler::haul(&creep, creepmem, building) + crate::roles::local::hauler::run_creep(&creep, creepmem, building) } } _ => {}, } } } + + memory.stats.rooms.get_mut(&room.name_str()).unwrap().mining += game::cpu::get_used() - starting_cpu; } diff --git a/src/room/population.rs b/src/room/population.rs index ff71af3..b325bdc 100644 --- a/src/room/population.rs +++ b/src/room/population.rs @@ -1,10 +1,10 @@ use screeps::{Room, Part, find}; -use crate::memory::{ScreepsMemory, Task}; +use crate::{memory::{ScreepsMemory, Task}, traits::room::RoomExtensions}; pub fn create_miner(memory: &mut ScreepsMemory, room: Room) -> bool { - if memory.rooms.get(&room.name().to_string()).unwrap().c_c.miner >= 1 && memory.rooms.get(&room.name().to_string()).unwrap().c_c.hauler < 1 {return false;} - let sources = memory.clone().rooms.get(&room.name().to_string()).unwrap().mine.clone(); + if memory.get_room(&room.name_str()).c_c.miner >= 1 && memory.get_room(&room.name_str()).c_c.hauler < 1 {return false;} + let sources = memory.clone().rooms.get(&room.name_str()).unwrap().mine.clone(); let mut selected_source = None; for (source_id, source_mem) in sources { if selected_source.is_none() && source_mem.s > source_mem.u { @@ -14,19 +14,20 @@ pub fn create_miner(memory: &mut ScreepsMemory, room: Room) -> bool { } } if let Some(source) = selected_source { - let name = format!("m-{}", memory.rooms.get(&room.name().to_string()).unwrap().c_m); + let name = format!("m-{}", memory.get_room(&room.name_str()).c_m); let body = [Part::Move, Part::Work, Part::Work]; let spawn_res = room.find(find::MY_SPAWNS, None).first().unwrap().spawn_creep(&body, &name); if spawn_res.is_ok() { memory.create_creep( - &room.name().to_string(), + &room.name_str(), &name, crate::memory::Careers::Mining, Some(Task::Miner(source)), ); - memory.rooms.get_mut(&room.name().to_string()).unwrap().c_c.miner += 1; - memory.rooms.get_mut(&room.name().to_string()).unwrap().c_m += 1; - memory.rooms.get_mut(&room.name().to_string()).unwrap().mine.get_mut(&source).unwrap().u += 1; + memory.get_room(&room.name_str()).c_c.miner += 1; + memory.get_room(&room.name_str()).c_m += 1; + memory.get_room(&room.name_str()).mine.get_mut(&source).unwrap().u += 1; + memory.stats.rooms.get_mut(&room.name_str()).unwrap().creeps_made += 1; true } else { false @@ -38,8 +39,8 @@ pub fn create_miner(memory: &mut ScreepsMemory, room: Room) -> bool { pub fn miner_died(memory: &mut ScreepsMemory, name: &str, room: &str) { // Remove from rooms creep count and from room creep list - memory.rooms.get_mut(room).unwrap().c_c.miner -= 1; - memory.rooms.get_mut(room).unwrap().cs = memory + memory.get_room(name).c_c.miner -= 1; + memory.get_room(name).cs = memory .rooms .get_mut(room) .unwrap() @@ -50,7 +51,7 @@ pub fn miner_died(memory: &mut ScreepsMemory, name: &str, room: &str) { .collect(); // Downtick the counters for used sources - let mining_source_id = memory.creeps.get(name).unwrap().t.clone().unwrap(); + let mining_source_id = memory.get_creep(name).t.clone().unwrap(); if let Task::Miner(source_id) = mining_source_id { memory .rooms @@ -68,8 +69,8 @@ pub fn miner_died(memory: &mut ScreepsMemory, name: &str, room: &str) { pub fn hauler_died(memory: &mut ScreepsMemory, name: &str, room: &str) { // Remove from rooms creep count and from room creep list - memory.rooms.get_mut(room).unwrap().c_c.hauler -= 1; - memory.rooms.get_mut(room).unwrap().cs = memory + memory.get_room(name).c_c.hauler -= 1; + memory.get_room(name).cs = memory .rooms .get_mut(room) .unwrap() @@ -85,8 +86,25 @@ pub fn hauler_died(memory: &mut ScreepsMemory, name: &str, room: &str) { pub fn upgrader_died(memory: &mut ScreepsMemory, name: &str, room: &str) { // Remove from rooms creep count and from room creep list - memory.rooms.get_mut(room).unwrap().c_c.hauler -= 1; - memory.rooms.get_mut(room).unwrap().cs = memory + memory.get_room(name).c_c.upgrader -= 1; + memory.get_room(name).cs = memory + .rooms + .get_mut(room) + .unwrap() + .cs + .iter() + .filter(|x| x != &&name.to_string()) + .map(|x| x.to_string()) + .collect(); + + // Remove said creep from memory + memory.creeps.remove(name); +} + +pub fn builder_died(memory: &mut ScreepsMemory, name: &str, room: &str) { + // Remove from rooms creep count and from room creep list + memory.get_room(name).c_c.builder -= 1; + memory.get_room(name).cs = memory .rooms .get_mut(room) .unwrap() diff --git a/src/traits/creep.rs b/src/traits/creep.rs new file mode 100644 index 0000000..0c245f8 --- /dev/null +++ b/src/traits/creep.rs @@ -0,0 +1,73 @@ +use log::info; +use screeps::{HasPosition, Position}; + +use crate::{memory::CreepMemory, movement::{utils::{dir_to_coords, num_to_dir, visualise_path}, move_target::MoveTarget}}; + +pub trait CreepExtensions { + // Movement + fn better_move_by_path(&self, path: String, memory: &mut CreepMemory); + fn better_move_to(&self, creep_memory: &mut CreepMemory, target: Position, range: u16); +} + +impl CreepExtensions for screeps::Creep { + // Movement + fn better_move_by_path(&self, path: String, memory: &mut CreepMemory) { + let creep = self; + + if creep.fatigue() > 0 { + return; + } + let serialized_path = path; + let serialized_vec = serialized_path.split("").filter(|x| x != &"").map(|x| x.parse::().unwrap()).collect::>(); + let step_dir = num_to_dir(serialized_vec[0]); + + match creep.move_direction(step_dir) { + Ok(_) => {}, + Err(e) => info!("Creep move failed, {:?}", e), + }; + + let serialized_vec = serialized_vec[1..].to_vec(); + let serialized_path = serialized_vec.iter().map(|x| x.to_string()).collect::>().join(""); + if serialized_vec.is_empty() { + memory.p = None + } else { + memory.p = Some(serialized_path); + } + + let mut points = vec![]; + let mut cursor = (creep.pos().x().u8() as f32, creep.pos().y().u8() as f32); + for step in serialized_vec { + let dir = num_to_dir(step); + let (x, y) = dir_to_coords(dir, cursor.0, cursor.1); + points.push((x, y)); + cursor = (x, y); + } + } + fn better_move_to(&self, creep_memory: &mut CreepMemory, target: Position, range: u16) { + let creep = self; + match creep_memory.clone().p { + Some(path) => { + visualise_path( + path.clone().to_string(), + creep.clone().room().unwrap().name().to_string(), + (creep.pos().x().u8() as f32, creep.pos().y().u8() as f32), + ); + self.better_move_by_path(path.clone(), creep_memory); + } + None => { + let target = MoveTarget { + pos: target, + range: range.into(), + } + .find_path_to(creep.pos()); + creep_memory.p = Some(target.clone()); + visualise_path( + target.clone().to_string(), + creep.clone().room().unwrap().name().to_string(), + (creep.pos().x().u8() as f32, creep.pos().y().u8() as f32), + ); + self.better_move_by_path(target.clone(), creep_memory); + } + } + } +} \ No newline at end of file diff --git a/src/traits/mod.rs b/src/traits/mod.rs new file mode 100644 index 0000000..6b0f332 --- /dev/null +++ b/src/traits/mod.rs @@ -0,0 +1,2 @@ +pub mod creep; +pub mod room; \ No newline at end of file diff --git a/src/traits/room.rs b/src/traits/room.rs new file mode 100644 index 0000000..e6095d1 --- /dev/null +++ b/src/traits/room.rs @@ -0,0 +1,9 @@ +pub trait RoomExtensions { + fn name_str(&self) -> String; +} + +impl RoomExtensions for screeps::Room { + fn name_str(&self) -> String { + self.name().to_string() + } +} \ No newline at end of file diff --git a/src/visual/room.rs b/src/visual/room.rs index bf873eb..dc770fe 100644 --- a/src/visual/room.rs +++ b/src/visual/room.rs @@ -1,6 +1,6 @@ use std::str::FromStr; -use screeps::{control, game, HasPosition, RoomName, RoomVisual, TextStyle}; +use screeps::{game, HasPosition, RoomName, RoomVisual, TextStyle}; use crate::memory::ScreepsMemory; @@ -34,14 +34,20 @@ pub fn classify_rooms(memory: &ScreepsMemory) { format!("Upgraders: {}", roommem.c_c.upgrader), white_left.clone(), ); + roomvis.text( + 1_f32, + 5_f32, + format!("Builders: {}", roommem.c_c.builder), + white_left.clone(), + ); let controller = room.controller().unwrap(); roomvis.text( controller.pos().x().u8() as f32, - (controller.pos().y().u8() + 1) as f32, + (controller.pos().y().u8() - 1) as f32, format!( "% {:.2}", - (controller.progress() * 100) / controller.progress_total() + controller.progress() as f64 / controller.progress_total() as f64 * 100.0 ), Some( TextStyle::default() From cfb24c9b57904029fed789381bd53adc7e1c4816 Mon Sep 17 00:00:00 2001 From: InfinityDevTech <47366052+InfinityDevTech@users.noreply.github.com> Date: Wed, 30 Aug 2023 19:47:37 -0400 Subject: [PATCH 10/13] te --- Cargo.lock | 45 ++++++++++ Cargo.toml | 9 +- javascript/main.js | 7 ++ screeps.toml | 4 +- src/lib.rs | 37 ++++---- src/memory.rs | 18 +++- src/movement/move_target.rs | 35 +++++--- src/roles/local/harvester.rs | 18 ++-- src/roles/local/hauler.rs | 10 ++- src/roles/local/mod.rs | 3 +- src/roles/local/scout.rs | 12 +++ src/roles/local/upgrader.rs | 21 +++-- src/room/democracy.rs | 9 +- src/room/industries/construction.rs | 16 +++- src/room/industries/mining.rs | 2 +- src/room/population.rs | 111 ++++++++++++------------ src/traits/creep.rs | 80 ++++++++++++----- src/traits/room.rs | 129 +++++++++++++++++++++++++++- src/visual/room.rs | 25 +++++- temp.js | 106 +++++++++++++++++++++++ 20 files changed, 557 insertions(+), 140 deletions(-) create mode 100644 src/roles/local/scout.rs create mode 100644 temp.js diff --git a/Cargo.lock b/Cargo.lock index bc16adf..d261d54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aho-corasick" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a" +dependencies = [ + "memchr", +] + [[package]] name = "arrayvec" version = "0.7.4" @@ -43,6 +52,7 @@ dependencies = [ "fern", "js-sys", "log", + "regex", "screeps-game-api", "serde", "serde_json", @@ -120,6 +130,12 @@ version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +[[package]] +name = "memchr" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76fc44e2588d5b436dbc3c6cf62aef290f90dab6235744a93dfe1cc18f451e2c" + [[package]] name = "num-derive" version = "0.4.0" @@ -164,6 +180,35 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "regex" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + [[package]] name = "ryu" version = "1.0.15" diff --git a/Cargo.toml b/Cargo.toml index 41a5875..61c4e1b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,14 +17,15 @@ web-sys = { version = "0.3", features = ["console"] } structstruck = "0.4.1" serde_json = "1.0.104" serde = { version = "1.0.183", features = ["derive"] } +regex = "1.9.4" [dev-dependencies] wasm-bindgen-test = "0.3" -#[profile.release] -#panic = "abort" -#opt-level = 3 -#lto = true +[profile.release] +panic = "abort" +opt-level = 3 +lto = true [package.metadata.wasm-pack.profile.release] # Replace the following to enable wasm-opt optimization diff --git a/javascript/main.js b/javascript/main.js index 32c1f88..ff1076b 100644 --- a/javascript/main.js +++ b/javascript/main.js @@ -41,6 +41,13 @@ global.toggle_exec = function () { return `Successfully toggled execution pause to: ${EXECUTION_PAUSED}` } +global.suicide_all = function() { + for (creep in Game.creeps) { + let c = Game.creeps[creep]; + c.suicide() + } +} + module.exports.loop = function () { // Replace the Memory object (which gets populated into our global each tick) with an empty // object, so that accesses to it from within the driver that we can't prevent (such as diff --git a/screeps.toml b/screeps.toml index c627e8a..753cbd9 100644 --- a/screeps.toml +++ b/screeps.toml @@ -21,8 +21,8 @@ prefix = "ptr" destination = "/home/jwjoh/.config/Screeps/scripts/super_directconnect_wyatt_world___21025" [copy.build] # set the sim feature to allow for use with the coordinates in the simulation room - extra_options = ["--features=sim", "--config", "build.rustflags=['-Ctarget-cpu=mvp']", "-Z", "build-std=std,panic_abort", "-Z", "build-std-features=panic_immediate_abort"] - #build-target = "release" + extra_options = ["--features=sim", "--config", "build.rustflags=['-Ctarget-cpu=mvp']", "-Z", "build-std=std,panic_abort", "-Z", "build-std-features=panic_immediate_abort", "--debug"] + build-target = "release" [season] auth_token = "your screeps.com auth token" diff --git a/src/lib.rs b/src/lib.rs index 1d6ae9a..aaec310 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -62,22 +62,12 @@ pub fn game_loop() { memory.stats.cpu.total = 0.0; memory.stats.cpu.bucket = 0; - if recently_respawned(&mut memory) { - for room in game::rooms().keys() { - let room = game::rooms().get(room).unwrap(); - if memory.rooms.get(&room.name_str()).is_some() { - continue; - } - if let Some(controller) = room.controller() { - if controller.my() { - memory.create_room(&room.name_str()); - } + if game::time() % 10 == 0 { + for creep in memory.clone().creeps.keys() { + if game::creeps().get(creep.clone()).is_none() { + memory.creeps.remove(creep); } } - memory.spawn_tick = false - } - - if game::time() % 10 == 0 { for room in game::rooms().values() { if let Some(controller) = room.controller() { if controller.my() && !memory.get_room(&room.name_str()).init { @@ -85,11 +75,6 @@ pub fn game_loop() { } } } - for creep in memory.clone().creeps.keys() { - if game::creeps().get(creep.clone()).is_none() { - memory.creeps.remove(creep); - } - } for room in memory.clone().rooms.values() { let mut to_remove = Vec::new(); for creep_name in room.cs.clone() { @@ -99,7 +84,21 @@ pub fn game_loop() { } memory.get_room(&room.n).cs = room.cs.clone().into_iter().filter(|x| !to_remove.contains(x)).collect(); } + } + if recently_respawned(&mut memory) { + for room in game::rooms().keys() { + let room = game::rooms().get(room).unwrap(); + if memory.rooms.get(&room.name_str()).is_some() { + continue; + } + if let Some(controller) = room.controller() { + if controller.my() { + memory.create_room(&room.name_str()); + } + } + } + memory.spawn_tick = false } for room in memory.clone().rooms.values() { diff --git a/src/memory.rs b/src/memory.rs index c316519..5c0a964 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -24,6 +24,8 @@ pub enum Task { // Odd industry Rename(ObjectId), + + Scout(), } structstruck::strike! { @@ -92,7 +94,10 @@ structstruck::strike! { pub rcl: u8, pub creeps_made: u64, pub creeps_removed: u64, + pub energy_harvested: u64, + pub energy_harvested_total: u64, }>, + pub energy_harvested: u64, }, pub spawn_tick: bool } @@ -100,14 +105,13 @@ structstruck::strike! { impl ScreepsMemory { pub fn init_memory() -> Self { - let memory_jsstring = screeps::raw_memory::get(); let memory_string = memory_jsstring.as_string().unwrap(); if memory_string.is_empty() { let mut memory = ScreepsMemory { rooms: HashMap::new(), creeps: HashMap::new(), - stats: Stats { cpu: Cpu { memory: 0.0, rooms: 0.0, total: 0.0, bucket: 0 }, rooms: HashMap::new() }, + stats: Stats { cpu: Cpu { memory: 0.0, rooms: 0.0, total: 0.0, bucket: 0 }, rooms: HashMap::new(), energy_harvested: 0 }, spawn_tick: true, }; memory.write_memory(); @@ -124,7 +128,7 @@ impl ScreepsMemory { ScreepsMemory { rooms: HashMap::new(), creeps: HashMap::new(), - stats: Stats { cpu: Cpu { memory: 0.0, rooms: 0.0, total: 0.0, bucket: 0 }, rooms: HashMap::new() }, + stats: Stats { cpu: Cpu { memory: 0.0, rooms: 0.0, total: 0.0, bucket: 0 }, rooms: HashMap::new(), energy_harvested: 0 }, spawn_tick: true, } } @@ -177,7 +181,7 @@ impl ScreepsMemory { } pub fn get_room(&mut self, name: &str) -> &mut RoomMemory { - self.rooms.get_mut(&name.to_string()).unwrap() + self.rooms.get_mut(&name.to_string()).expect("Failed to get room from memory, attempted room name") } pub fn get_creep(&mut self, name: &str) -> &mut CreepMemory { @@ -196,7 +200,13 @@ impl Stats { rcl, creeps_removed: 0, cpu: 0.0, + energy_harvested: 0, + energy_harvested_total: 0, } ); } + + pub fn get_room(&mut self, name: &str) -> &mut Rooms { + self.rooms.get_mut(&name.to_string()).expect("Failed to get room from stats") + } } \ No newline at end of file diff --git a/src/movement/move_target.rs b/src/movement/move_target.rs index 0bb9bf7..538f807 100644 --- a/src/movement/move_target.rs +++ b/src/movement/move_target.rs @@ -1,7 +1,7 @@ use log::warn; use screeps::{ pathfinder::{self, MultiRoomCostResult, SearchOptions}, HasPosition, LocalCostMatrix, OwnedStructureProperties, Position, - RoomName, StructureObject, find + RoomName, StructureObject, find, StructureType }; pub struct MoveTarget { @@ -19,12 +19,12 @@ impl MoveTarget { let search = pathfinder::search(from, self.pos, self.range, Some(opts)); if search.incomplete() { - warn!( - "Incomplete pathfinding search {} {} {}", - search.ops(), - search.cost(), - self.pos - ); + //warn!( + // "Incomplete pathfinding search {} {} {}", + // search.ops(), + // search.cost(), + // self.pos + //); } let mut cur_pos = from; @@ -45,8 +45,9 @@ impl MoveTarget { cur_pos = pos; } let mut steps_string = "".to_string(); + let steps = &steps[0..std::cmp::min(steps.len(), 5)]; for dirint in steps { - let int = dirint as u8; + let int = *dirint as u8; let intstring = int.to_string(); steps_string = steps_string + &intstring; @@ -58,9 +59,10 @@ impl MoveTarget { pub fn path_call(room_name: RoomName) -> MultiRoomCostResult { let mut matrix = LocalCostMatrix::new(); if let Some(room) = screeps::game::rooms().get(room_name) { - let objects = room.find(find::STRUCTURES, None); + let structures = room.find(find::STRUCTURES, None); + let constructions = room.find(find::CONSTRUCTION_SITES, None); let creeps = room.find(find::CREEPS, None); - for structure in objects { + for structure in structures { let pos = structure.pos(); match structure { StructureObject::StructureContainer(_) => matrix.set(pos.xy(), 1), @@ -79,6 +81,19 @@ pub fn path_call(room_name: RoomName) -> MultiRoomCostResult { } } + for csite in constructions { + let pos = csite.pos(); + match csite.structure_type() { + StructureType::Container => matrix.set(pos.xy(), 1), + StructureType::Rampart => matrix.set(pos.xy(), 1), + StructureType::Road => matrix.set(pos.xy(), 1), + StructureType::Wall => matrix.set(pos.xy(), 255), + _ => { + matrix.set(pos.xy(), 255); + } + } + } + for creep in creeps { let pos = creep.pos(); matrix.set(pos.xy(), 255); diff --git a/src/roles/local/harvester.rs b/src/roles/local/harvester.rs index ea648e8..b6736d9 100644 --- a/src/roles/local/harvester.rs +++ b/src/roles/local/harvester.rs @@ -1,9 +1,9 @@ -use log::warn; -use screeps::{Source, HasPosition, Creep, ResourceType}; +use screeps::{Source, HasPosition, Creep, ResourceType, Part, SharedCreepProperties}; -use crate::{memory::CreepMemory, traits::creep::CreepExtensions}; +use crate::{memory::ScreepsMemory, traits::creep::CreepExtensions}; -pub fn harvest(creep: &Creep, creepmem: &mut CreepMemory, source: Source) { +pub fn harvest(creep: &Creep, memory: &mut ScreepsMemory, source: Source) { + let owning_room = memory.get_creep(&creep.name()).o_r.clone(); if creep.pos().is_near_to(source.pos()) { if creep.store().get_free_capacity(Some(ResourceType::Energy)) > creep.store().get_used_capacity(Some(ResourceType::Energy)) as i32 { @@ -12,14 +12,16 @@ pub fn harvest(creep: &Creep, creepmem: &mut CreepMemory, source: Source) { } else { - creep.harvest(&source).unwrap_or_else(|e| { - warn!("couldn't harvest: {:?}", e); - }); + creep.harvest(&source).unwrap_or(()); + let energy_harvested = std::cmp::min(creep.body().iter().filter(|b| b.part() == Part::Work).count() as u32 * 2, source.energy()) as u64; + memory.stats.get_room(&owning_room).energy_harvested += energy_harvested; + memory.stats.get_room(&owning_room).energy_harvested_total += energy_harvested; + memory.stats.energy_harvested += energy_harvested; } } else { - creep.better_move_to(creepmem, source.pos(), 1) + creep.better_move_to(memory.get_creep(&creep.name()), source.pos(), 1) } } \ No newline at end of file diff --git a/src/roles/local/hauler.rs b/src/roles/local/hauler.rs index a701229..bd43f86 100644 --- a/src/roles/local/hauler.rs +++ b/src/roles/local/hauler.rs @@ -1,10 +1,10 @@ use std::cmp::min; use screeps::{ - find, Creep, HasPosition, ResourceType, SharedCreepProperties, Structure, StructureObject, + find, Creep, HasPosition, ResourceType, SharedCreepProperties, Structure, StructureObject, HasTypedId, }; -use crate::{memory::CreepMemory, traits::creep::CreepExtensions}; +use crate::{memory::{CreepMemory, Task}, traits::creep::CreepExtensions}; pub fn run_creep(creep: &Creep, creepmem: &mut CreepMemory, deposit: Structure) { if creepmem.s == "energy" { @@ -63,6 +63,12 @@ pub fn haul_energy(creep: &Creep, creepmem: &mut CreepMemory, deposit: Structure } else { creep.better_move_to(creepmem, structure.pos(), 1); } + } else { + let find_res = creep.room().unwrap().find(find::MY_STRUCTURES, None); + let new_target = find_res.iter().filter(|s| s.as_transferable().is_some()).find(|s| s.as_has_store().unwrap().store().get_free_capacity(Some(ResourceType::Energy)) > 0); + if let Some(new_target) = new_target { + creepmem.t = Some(Task::Hauler(new_target.as_structure().id())); + } } } } diff --git a/src/roles/local/mod.rs b/src/roles/local/mod.rs index fcf80d9..96d98f9 100644 --- a/src/roles/local/mod.rs +++ b/src/roles/local/mod.rs @@ -1,4 +1,5 @@ pub mod builder; pub mod harvester; pub mod upgrader; -pub mod hauler; \ No newline at end of file +pub mod hauler; +pub mod scout; \ No newline at end of file diff --git a/src/roles/local/scout.rs b/src/roles/local/scout.rs new file mode 100644 index 0000000..79c0f64 --- /dev/null +++ b/src/roles/local/scout.rs @@ -0,0 +1,12 @@ +use screeps::{Creep, game, Position, RoomCoordinate}; + +use crate::{memory::CreepMemory, traits::creep::CreepExtensions}; + +pub fn scout(creep: &Creep, creepmem: &mut CreepMemory) { + let creep_room = creep.room().unwrap(); + let exits = game::map::describe_exits(creep_room.name()); + + let exit_to_use = exits.values().next().unwrap(); + creep.better_move_to(creepmem, Position::new(RoomCoordinate::new(25).unwrap(), RoomCoordinate::new(25).unwrap(), exit_to_use), 25); + +} \ No newline at end of file diff --git a/src/roles/local/upgrader.rs b/src/roles/local/upgrader.rs index 47071a2..59e0a98 100644 --- a/src/roles/local/upgrader.rs +++ b/src/roles/local/upgrader.rs @@ -4,9 +4,7 @@ use crate::{memory::CreepMemory, traits::creep::CreepExtensions}; pub fn upgrade(creep: &Creep, creepmem: &mut CreepMemory, controller: StructureController) { let inventory = creep.store(); - if inventory.get_free_capacity(None) - > inventory.get_used_capacity(Some(ResourceType::Energy)) as i32 - { + if creepmem.s == "energy" { let closest_energy = creep .pos() .find_closest_by_path(find::DROPPED_RESOURCES, None); @@ -17,9 +15,20 @@ pub fn upgrade(creep: &Creep, creepmem: &mut CreepMemory, controller: StructureC creep.better_move_to(creepmem, energy.pos(), 1); } } - } else if creep.pos().is_near_to(controller.pos()) { - let _ = creep.upgrade_controller(&controller); } else { - creep.better_move_to(creepmem, controller.pos(), 2) + match creep.upgrade_controller(&controller) { + Ok(_) => {}, + Err(test) => { + if let screeps::ErrorCode::NotInRange = test { + creep.better_move_to(creepmem, controller.pos(), 2); + } + }, + } + } + if inventory.get_used_capacity(Some(ResourceType::Energy)) == 0 { + creepmem.s = "energy".to_string(); + } + if inventory.get_free_capacity(Some(ResourceType::Energy)) == 0 { + creepmem.s = "work".to_string(); } } diff --git a/src/room/democracy.rs b/src/room/democracy.rs index f571b9d..fc8e3d8 100644 --- a/src/room/democracy.rs +++ b/src/room/democracy.rs @@ -22,6 +22,10 @@ pub fn start_government(room: Room, memory: &mut ScreepsMemory) { if memory.stats.rooms.get(&room.name_str()).is_none() { memory.stats.create_room(&room.name_str(), room.controller().unwrap().level()); } + memory.stats.get_room(&room.name_str()).cpu = 0.0; + memory.stats.get_room(&room.name_str()).mining = 0.0; + memory.stats.get_room(&room.name_str()).construction = 0.0; + memory.stats.get_room(&room.name_str()).energy_harvested = 0; // Horray, i did it better. let creeps = get_room_creeps_and_clean(memory, &room); let roommem = memory.get_room(&room.name_str()); @@ -87,7 +91,7 @@ pub fn get_room_creeps_and_clean(memory: &mut ScreepsMemory, room: &Room) -> Vec } creeps.push(creep_name.to_string()); - } else if game::creeps().get(creep_name.to_string()).is_none() { + } else { removed_creeps += 1; match &memory .creeps @@ -111,6 +115,7 @@ pub fn get_room_creeps_and_clean(memory: &mut ScreepsMemory, room: &Room) -> Vec } _ => {} } + memory.creeps.remove(creep_name); } } memory.stats.rooms.get_mut(&room.name_str()).unwrap().creeps_removed += removed_creeps; @@ -154,7 +159,7 @@ pub fn do_spawning(memory: &mut ScreepsMemory, room: &Room) { } } else if memory.get_room(&room.name_str()).c_c.upgrader < UPGRADER_COUNT { let name = format!("u-{}", roommem_readonly.c_m); - let body = [Part::Move, Part::Carry, Part::Carry, Part::Work]; + let body = [Part::Move, Part::Move, Part::Carry, Part::Carry, Part::Work]; let spawn_res = spawn.spawn_creep(&body, &name); if spawn_res.is_ok() { memory.create_creep( diff --git a/src/room/industries/construction.rs b/src/room/industries/construction.rs index 05191cb..da96b11 100644 --- a/src/room/industries/construction.rs +++ b/src/room/industries/construction.rs @@ -1,5 +1,5 @@ use log::info; -use screeps::{game, Room}; +use screeps::{game, Room, HasPosition, TextStyle}; use crate::{memory::ScreepsMemory, traits::room::RoomExtensions}; @@ -25,5 +25,19 @@ pub fn pre_market(room: &Room, creeps: Vec, memory: &mut ScreepsMemory) } } + if game::cpu::bucket() > 500 { + for room in game::rooms().values() { + let controller = room.controller().unwrap().pos(); + let result = room.flood_fill(vec![(controller.x().u8(), controller.y().u8())]); + for x in 0..=50 { + for y in 0..=50 { + let text = result.get(x, y); + + room.visual().text(x as f32, y as f32 + 0.25, format!("{}", text), Some(TextStyle::default().color("#ffffff").align(screeps::TextAlign::Center).font(0.5))); + } + } + } + } + memory.stats.rooms.get_mut(&room.name_str()).unwrap().construction += game::cpu::get_used() - starting_cpu; } diff --git a/src/room/industries/mining.rs b/src/room/industries/mining.rs index e9b0ada..a65da0c 100644 --- a/src/room/industries/mining.rs +++ b/src/room/industries/mining.rs @@ -18,7 +18,7 @@ pub fn pre_market( match task { crate::memory::Task::Miner(source_id) => { if let Some(source) = source_id.resolve() { - crate::roles::local::harvester::harvest(&creep, creepmem, source) + crate::roles::local::harvester::harvest(&creep, memory, source) } else { creepmem.t = None; } diff --git a/src/room/population.rs b/src/room/population.rs index b325bdc..26fc833 100644 --- a/src/room/population.rs +++ b/src/room/population.rs @@ -1,10 +1,19 @@ -use screeps::{Room, Part, find}; +use screeps::{find, Part, Room}; -use crate::{memory::{ScreepsMemory, Task}, traits::room::RoomExtensions}; +use crate::{ + memory::{ScreepsMemory, Task}, + traits::room::RoomExtensions, +}; pub fn create_miner(memory: &mut ScreepsMemory, room: Room) -> bool { - if memory.get_room(&room.name_str()).c_c.miner >= 1 && memory.get_room(&room.name_str()).c_c.hauler < 1 {return false;} - let sources = memory.clone().rooms.get(&room.name_str()).unwrap().mine.clone(); + if memory.get_room(&room.name_str()).c_c.miner >= 1 + && memory.get_room(&room.name_str()).c_c.hauler < 1 + { + return false; + } + let sources = memory.get_room(&room.name_str()) + .mine + .clone(); let mut selected_source = None; for (source_id, source_mem) in sources { if selected_source.is_none() && source_mem.s > source_mem.u { @@ -16,7 +25,11 @@ pub fn create_miner(memory: &mut ScreepsMemory, room: Room) -> bool { if let Some(source) = selected_source { let name = format!("m-{}", memory.get_room(&room.name_str()).c_m); let body = [Part::Move, Part::Work, Part::Work]; - let spawn_res = room.find(find::MY_SPAWNS, None).first().unwrap().spawn_creep(&body, &name); + let spawn_res = room + .find(find::MY_SPAWNS, None) + .first() + .unwrap() + .spawn_creep(&body, &name); if spawn_res.is_ok() { memory.create_creep( &room.name_str(), @@ -26,8 +39,18 @@ pub fn create_miner(memory: &mut ScreepsMemory, room: Room) -> bool { ); memory.get_room(&room.name_str()).c_c.miner += 1; memory.get_room(&room.name_str()).c_m += 1; - memory.get_room(&room.name_str()).mine.get_mut(&source).unwrap().u += 1; - memory.stats.rooms.get_mut(&room.name_str()).unwrap().creeps_made += 1; + memory + .get_room(&room.name_str()) + .mine + .get_mut(&source) + .unwrap() + .u += 1; + memory + .stats + .rooms + .get_mut(&room.name_str()) + .unwrap() + .creeps_made += 1; true } else { false @@ -37,83 +60,63 @@ pub fn create_miner(memory: &mut ScreepsMemory, room: Room) -> bool { } } -pub fn miner_died(memory: &mut ScreepsMemory, name: &str, room: &str) { +pub fn miner_died(memory: &mut ScreepsMemory, creep_name: &str, room_name: &str) { // Remove from rooms creep count and from room creep list - memory.get_room(name).c_c.miner -= 1; - memory.get_room(name).cs = memory - .rooms - .get_mut(room) - .unwrap() - .cs - .iter() - .filter(|x| x != &&name.to_string()) - .map(|x| x.to_string()) - .collect(); + memory.get_room(room_name).c_c.miner -= 1; + + memory.get_room(room_name).cs = memory.get_room(room_name).cs.iter().filter(|x| x != &&creep_name.to_string()).map(|x| x.to_string()).collect(); // Downtick the counters for used sources - let mining_source_id = memory.get_creep(name).t.clone().unwrap(); + let mining_source_id = memory.get_creep(creep_name).t.clone().expect("Failed to get creep task from memory"); + if let Task::Miner(source_id) = mining_source_id { - memory - .rooms - .get_mut(room) - .unwrap() - .mine - .get_mut(&source_id) - .unwrap() - .u -= 1; + + memory.get_room(room_name).mine.get_mut(&source_id).expect("Failed to get source from memory").u -= 1; + } - // Remove said creep from memory - memory.creeps.remove(name); + // Remove said creep from memory + memory.creeps.remove(creep_name); } -pub fn hauler_died(memory: &mut ScreepsMemory, name: &str, room: &str) { +pub fn hauler_died(memory: &mut ScreepsMemory, creep_name: &str, room_name: &str) { // Remove from rooms creep count and from room creep list - memory.get_room(name).c_c.hauler -= 1; - memory.get_room(name).cs = memory - .rooms - .get_mut(room) - .unwrap() + memory.get_room(room_name).c_c.hauler -= 1; + memory.get_room(room_name).cs = memory.get_room(room_name) .cs .iter() - .filter(|x| x != &&name.to_string()) + .filter(|x| x != &&creep_name.to_string()) .map(|x| x.to_string()) .collect(); // Remove said creep from memory - memory.creeps.remove(name); + memory.creeps.remove(creep_name); } -pub fn upgrader_died(memory: &mut ScreepsMemory, name: &str, room: &str) { +pub fn upgrader_died(memory: &mut ScreepsMemory, creep_name: &str, room_name: &str) { // Remove from rooms creep count and from room creep list - memory.get_room(name).c_c.upgrader -= 1; - memory.get_room(name).cs = memory - .rooms - .get_mut(room) - .unwrap() + memory.get_room(room_name).c_c.upgrader -= 1; + memory.get_room(room_name).cs = memory.get_room(room_name) .cs .iter() - .filter(|x| x != &&name.to_string()) + .filter(|x| x != &&creep_name.to_string()) .map(|x| x.to_string()) .collect(); // Remove said creep from memory - memory.creeps.remove(name); + memory.creeps.remove(creep_name); } -pub fn builder_died(memory: &mut ScreepsMemory, name: &str, room: &str) { +pub fn builder_died(memory: &mut ScreepsMemory, creep_name: &str, room_name: &str) { // Remove from rooms creep count and from room creep list - memory.get_room(name).c_c.builder -= 1; - memory.get_room(name).cs = memory - .rooms - .get_mut(room) - .unwrap() + memory.get_room(room_name).c_c.builder -= 1; + memory.get_room(room_name).cs = memory.get_room(room_name) .cs .iter() - .filter(|x| x != &&name.to_string()) + .filter(|x| x != &&creep_name.to_string()) .map(|x| x.to_string()) .collect(); // Remove said creep from memory - memory.creeps.remove(name); -} \ No newline at end of file + memory.creeps.remove(creep_name); +} diff --git a/src/traits/creep.rs b/src/traits/creep.rs index 0c245f8..3fc1bf7 100644 --- a/src/traits/creep.rs +++ b/src/traits/creep.rs @@ -1,12 +1,20 @@ use log::info; use screeps::{HasPosition, Position}; -use crate::{memory::CreepMemory, movement::{utils::{dir_to_coords, num_to_dir, visualise_path}, move_target::MoveTarget}}; +use crate::{ + memory::CreepMemory, + movement::{ + move_target::MoveTarget, + utils::{dir_to_coords, num_to_dir, visualise_path}, + }, +}; pub trait CreepExtensions { // Movement fn better_move_by_path(&self, path: String, memory: &mut CreepMemory); fn better_move_to(&self, creep_memory: &mut CreepMemory, target: Position, range: u16); + + fn better_is_near(&self, x: u8, y: u8) -> u8; } impl CreepExtensions for screeps::Creep { @@ -18,30 +26,49 @@ impl CreepExtensions for screeps::Creep { return; } let serialized_path = path; - let serialized_vec = serialized_path.split("").filter(|x| x != &"").map(|x| x.parse::().unwrap()).collect::>(); + let serialized_vec = serialized_path + .split("") + .filter(|x| x != &"") + .map(|x| { + x.parse::() + .expect(&format!("Failed to parse character as u8 {}", x)) + }) + .collect::>(); + if serialized_vec.is_empty() { + memory.p = None; + return; + } let step_dir = num_to_dir(serialized_vec[0]); - + match creep.move_direction(step_dir) { - Ok(_) => {}, - Err(e) => info!("Creep move failed, {:?}", e), + Ok(_) => { + let serialized_vec = serialized_vec[1..].to_vec(); + let serialized_path = serialized_vec + .iter() + .map(|x| x.to_string()) + .collect::>() + .join(""); + if serialized_vec.is_empty() { + memory.p = None; + return; + } else { + memory.p = Some(serialized_path); + } + + let mut points = vec![]; + let mut cursor = (creep.pos().x().u8() as f32, creep.pos().y().u8() as f32); + for step in serialized_vec { + let dir = num_to_dir(step); + let (x, y) = dir_to_coords(dir, cursor.0, cursor.1); + points.push((x, y)); + cursor = (x, y); + } + } + Err(e) => { + memory.p = None; + info!("Creep move failed, {:?}", e) + } }; - - let serialized_vec = serialized_vec[1..].to_vec(); - let serialized_path = serialized_vec.iter().map(|x| x.to_string()).collect::>().join(""); - if serialized_vec.is_empty() { - memory.p = None - } else { - memory.p = Some(serialized_path); - } - - let mut points = vec![]; - let mut cursor = (creep.pos().x().u8() as f32, creep.pos().y().u8() as f32); - for step in serialized_vec { - let dir = num_to_dir(step); - let (x, y) = dir_to_coords(dir, cursor.0, cursor.1); - points.push((x, y)); - cursor = (x, y); - } } fn better_move_to(&self, creep_memory: &mut CreepMemory, target: Position, range: u16) { let creep = self; @@ -70,4 +97,11 @@ impl CreepExtensions for screeps::Creep { } } } -} \ No newline at end of file + + fn better_is_near(&self, x: u8, y: u8) -> u8 { + let creep_x = self.pos().x().u8(); + let creep_y = self.pos().y().u8(); + let int = (creep_x - x).pow(2) + (creep_y - y).pow(2); + (((int as f64).sqrt() * 10.0).round() / 10.0) as u8 + } +} diff --git a/src/traits/room.rs b/src/traits/room.rs index e6095d1..e8ecbbf 100644 --- a/src/traits/room.rs +++ b/src/traits/room.rs @@ -1,9 +1,136 @@ +use log::info; +use regex::Regex; +use screeps::{CostMatrix, Terrain}; + pub trait RoomExtensions { fn name_str(&self) -> String; + + fn split_room_name(&self) -> (String, u32, String, u32); + + fn is_highway(&self) -> bool; + fn is_intersection(&self) -> bool; + fn is_source_keeper(&self) -> bool; + + fn flood_fill(&self, seeds: Vec<(u8, u8)>) -> CostMatrix; } impl RoomExtensions for screeps::Room { fn name_str(&self) -> String { self.name().to_string() } -} \ No newline at end of file + + fn split_room_name(&self) -> (String, u32, String, u32) { + let room_regex = Regex::new("^([WE]{1})([0-9]{1,2})([NS]{1})([0-9]{1,2})$").unwrap(); + let room_name = self.name_str(); + + let captures = room_regex.captures(&room_name).unwrap(); + + ( + captures[1].to_string(), + captures[2].to_string().parse::().unwrap(), + captures[3].to_string(), + captures[4].to_string().parse::().unwrap(), + ) + } + + fn is_highway(&self) -> bool { + let split_name = self.split_room_name(); + let east_west_distance = split_name.1; + let north_south_distance = split_name.3; + + if east_west_distance % 10 == 0 || north_south_distance % 10 == 0 { + return true; + } + false + } + + fn is_intersection(&self) -> bool { + let split_name = self.split_room_name(); + let east_west_distance = split_name.1; + let north_south_distance = split_name.3; + + if east_west_distance % 10 == 0 && north_south_distance % 10 == 0 { + return true; + } + false + } + + fn is_source_keeper(&self) -> bool { + let split_name = self.split_room_name(); + let east_west_distance = split_name.1; + let north_south_distance = split_name.3; + + if east_west_distance % 10 == 5 + && north_south_distance % 10 == 5 + && !north_south_distance % 10 == 0 + && !east_west_distance % 10 == 0 + { + return true; + } + false + } + + fn flood_fill(&self, seeds: Vec<(u8, u8)>) -> CostMatrix { + let flood_cm = CostMatrix::new(); + let terrain = self.get_terrain(); + let visited_cms = CostMatrix::new(); + + let mut depth = 0; + let mut this_gen = seeds.clone(); + let mut next_gen = Vec::new(); + for (x, y) in &seeds { + visited_cms.set(*x, *y, 1); + info!("Seed: {}, {}", x, y); + } + + while !this_gen.is_empty() { + info!("Ruinning"); + next_gen.clear(); + + for (x, y) in &this_gen.clone() { + info!("Checking {}, {}", x, y); + if depth != 0 { + if terrain.get(*x, *y) == Terrain::Wall { + continue; + } + + flood_cm.set(*x, *y, depth); + } + + let rect = (x - 1, y - 1, x + 1, y + 1); + let adjacent_psoitions = find_pos_in_rect(rect); + + for (x2, y2) in adjacent_psoitions { + if visited_cms.get(x2, y2) == 1 { + continue; + } + + visited_cms.set(x2, y2, 1); + + next_gen.push((x2, y2)); + } + } + this_gen.clear(); + this_gen = next_gen.clone(); + info!("Set"); + depth += 1; + } + + flood_cm + } +} + +pub fn find_pos_in_rect(rect: (u8, u8, u8, u8)) -> Vec<(u8, u8)> { + let mut positions = Vec::new(); + + for x in rect.0..=rect.2 { + for y in rect.1..=rect.3 { + if x >= 50 || y >= 50 { + continue; + } + positions.push((x, y)); + } + } + + positions +} diff --git a/src/visual/room.rs b/src/visual/room.rs index dc770fe..2c6b681 100644 --- a/src/visual/room.rs +++ b/src/visual/room.rs @@ -1,8 +1,8 @@ use std::str::FromStr; -use screeps::{game, HasPosition, RoomName, RoomVisual, TextStyle}; +use screeps::{game, HasPosition, RoomName, RoomVisual, TextStyle, MapVisual, Position, RoomCoordinate}; -use crate::memory::ScreepsMemory; +use crate::{memory::ScreepsMemory, traits::room::RoomExtensions}; pub fn classify_rooms(memory: &ScreepsMemory) { for name in memory.rooms.keys() { @@ -57,4 +57,25 @@ pub fn classify_rooms(memory: &ScreepsMemory) { ); } } + + for room in game::rooms().values() { + let pos = Position::new(RoomCoordinate::new(25).unwrap(), RoomCoordinate::new(3).unwrap(), room.name()); + MapVisual::text(pos, get_room_type(&room.name_str()), Some(TextStyle::default().color("#ffffff").align(screeps::TextAlign::Center))); + } } + +pub fn get_room_type(name: &str) -> String { + if let Some(room) = game::rooms().get(RoomName::from_str(name).unwrap()) { + if room.is_highway() { + "highway".to_string() + } else if room.is_intersection() { + return "intersection".to_string(); + } else if room.is_source_keeper() { + return "source_keeper".to_string(); + } else { + return "normal".to_string(); + } + } else { + "none".to_string() + } +} \ No newline at end of file diff --git a/temp.js b/temp.js new file mode 100644 index 0000000..b0d8fca --- /dev/null +++ b/temp.js @@ -0,0 +1,106 @@ +const roomDimensions = 50 + +findPositionsInsideRect = function(rect) { + + const positions = [] + + for (let x = rect.x1; x <= rect.x2; x++) { + for (let y = rect.y1; y <= rect.y2; y++) { + + // Iterate if the pos doesn't map onto a room + + if (x < 0 || x >= roomDimensions || + y < 0 || y >= roomDimensions) continue + + // Otherwise ass the x and y to positions + + positions.push({ x, y }) + } + } + + return positions +} + +Room.prototype.floodFill = function(seeds) { + + const room = this + + const floodCM = new PathFinder.CostMatrix() + let terrain = room.getTerrain() + let visitedCM = new PathFinder.CostMatrix() + + let depth = 0 + let thisGeneration = seeds + let nextGeneration = [] + + for (const pos of seeds) { + + visitedCM.set(pos.x, pos.y, 1) + } + + // So long as there are positions in this gen + + while (thisGeneration.length) { + + // Reset next gen + + nextGeneration = [] + + // Iterate through positions of this gen + + for (const pos of thisGeneration) { + + // If the depth isn't 0 + + if (depth != 0) { + + // Iterate if the terrain is a wall + + if (terrain.get(pos.x, pos.y) == TERRAIN_MASK_WALL) continue + + // Otherwise so long as the pos isn't a wall record its depth in the flood cost matrix + + floodCM.set(pos.x, pos.y, depth) + + // If visuals are enabled, show the depth on the pos + + if (Memory.roomVisuals) room.visual.rect(pos.x - 0.5, pos.y - 0.5, 1, 1, { + fill: 'hsl(' + 200 + depth * 2 + ', 100%, 60%)', + opacity: 0.4, + }) + } + + // Construct a rect and get the positions in a range of 1 + + const rect = { x1: pos.x - 1, y1: pos.y - 1, x2: pos.x + 1, y2: pos.y + 1 }, + adjacentPositions = findPositionsInsideRect(rect) + + // Loop through adjacent positions + + for (const adjacentPos of adjacentPositions) { + + // Iterate if the adjacent pos has been visited or isn't a tile + + if (visitedCM.get(adjacentPos.x, adjacentPos.y) == 1) continue + + // Otherwise record that it has been visited + + visitedCM.set(adjacentPos.x, adjacentPos.y, 1) + + // Add it to the next gen + + nextGeneration.push(adjacentPos) + } + } + + // Set this gen to next gen + + thisGeneration = nextGeneration + + // Increment depth + + depth++ + } + + return floodCM +} \ No newline at end of file From 91351d9b7fdd98e3704e870b75c96058231af173 Mon Sep 17 00:00:00 2001 From: InfinityDevTech <47366052+InfinityDevTech@users.noreply.github.com> Date: Thu, 31 Aug 2023 19:55:04 -0400 Subject: [PATCH 11/13] 0.9 Versions! --- Cargo.toml | 4 +- javascript/main.js | 2 +- src/lib.rs | 36 ++---- src/memory.rs | 48 ++++---- src/roles/mod.rs | 1 - src/{roles => room/creeps}/local/builder.rs | 0 src/{roles => room/creeps}/local/harvester.rs | 2 +- src/{roles => room/creeps}/local/hauler.rs | 0 src/{roles => room/creeps}/local/mod.rs | 0 src/{roles => room/creeps}/local/scout.rs | 0 src/{roles => room/creeps}/local/upgrader.rs | 2 +- src/room/creeps/market.rs | 51 +++++++++ src/room/creeps/mod.rs | 2 + src/room/democracy.rs | 88 +++------------ src/room/industries/construction.rs | 43 ------- src/room/industries/mining.rs | 37 ------ src/room/industries/mod.rs | 2 - src/room/mod.rs | 2 +- src/room/population.rs | 90 ++++----------- src/visual/room.rs | 43 ++++--- temp.js | 106 ------------------ 21 files changed, 159 insertions(+), 400 deletions(-) delete mode 100644 src/roles/mod.rs rename src/{roles => room/creeps}/local/builder.rs (100%) rename src/{roles => room/creeps}/local/harvester.rs (93%) rename src/{roles => room/creeps}/local/hauler.rs (100%) rename src/{roles => room/creeps}/local/mod.rs (100%) rename src/{roles => room/creeps}/local/scout.rs (100%) rename src/{roles => room/creeps}/local/upgrader.rs (92%) create mode 100644 src/room/creeps/market.rs create mode 100644 src/room/creeps/mod.rs delete mode 100644 src/room/industries/construction.rs delete mode 100644 src/room/industries/mining.rs delete mode 100644 src/room/industries/mod.rs delete mode 100644 temp.js diff --git a/Cargo.toml b/Cargo.toml index 61c4e1b..ee0a694 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,8 +38,8 @@ lto = true # -g - leave debug info in place, allowing for more descriptive stack traces on panic # --disable-sign-ext - prevents opcodes that the screeps servers can't load (see # https://github.com/rustyscreeps/screeps-game-api/issues/391) -#wasm-opt = ["-O4", "--disable-sign-ext"] -wasm-opt = ["-g", "--disable-sign-ext"] +wasm-opt = ["-O4", "--disable-sign-ext"] +#wasm-opt = ["-g", "--disable-sign-ext"] [features] default = [] diff --git a/javascript/main.js b/javascript/main.js index ff1076b..29be45a 100644 --- a/javascript/main.js +++ b/javascript/main.js @@ -42,7 +42,7 @@ global.toggle_exec = function () { } global.suicide_all = function() { - for (creep in Game.creeps) { + for (let creep in Game.creeps) { let c = Game.creeps[creep]; c.suicide() } diff --git a/src/lib.rs b/src/lib.rs index aaec310..2e66307 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,6 @@ use crate::{memory::ScreepsMemory, traits::room::RoomExtensions}; mod logging; mod memory; mod movement; -mod roles; mod room; mod visual; mod traits; @@ -35,7 +34,7 @@ pub fn recently_respawned(memory: &mut ScreepsMemory) -> bool { } // check for controller, progress and safe mode - let room = game::rooms().get(names[0]).unwrap(); + let room = game::rooms().get(names[0]).expect("Failed to get room"); let controller = room.controller(); if controller.is_none()|| !controller.clone().unwrap().my() || controller.clone().unwrap().level() != 1 || controller.clone().unwrap().progress() > 0 || controller.clone().unwrap().safe_mode().is_none() { @@ -63,11 +62,6 @@ pub fn game_loop() { memory.stats.cpu.bucket = 0; if game::time() % 10 == 0 { - for creep in memory.clone().creeps.keys() { - if game::creeps().get(creep.clone()).is_none() { - memory.creeps.remove(creep); - } - } for room in game::rooms().values() { if let Some(controller) = room.controller() { if controller.my() && !memory.get_room(&room.name_str()).init { @@ -75,15 +69,6 @@ pub fn game_loop() { } } } - for room in memory.clone().rooms.values() { - let mut to_remove = Vec::new(); - for creep_name in room.cs.clone() { - if game::creeps().get(creep_name.clone()).is_none() { - to_remove.push(creep_name); - } - } - memory.get_room(&room.n).cs = room.cs.clone().into_iter().filter(|x| !to_remove.contains(x)).collect(); - } } if recently_respawned(&mut memory) { @@ -102,7 +87,7 @@ pub fn game_loop() { } for room in memory.clone().rooms.values() { - room::democracy::start_government(game::rooms().get(RoomName::from_str(&room.n).unwrap()).unwrap(), &mut memory); + room::democracy::start_government(game::rooms().get(RoomName::from_str(&room.name).unwrap()).unwrap(), &mut memory); } visual::room::classify_rooms(&memory); @@ -115,14 +100,15 @@ pub fn game_loop() { memory.write_memory(); info!("[DICTATOR] Government ran and memory written... Here are some stats!"); - info!("GCL level {}. Next level: {} / {}", game::gcl::level(), game::gcl::progress(), game::gcl::progress_total()); - info!("Market credits: {}", game::market::credits()); - info!("Creeps removed this tick: {}", memory.stats.cpu.rooms); - info!("CPU Usage:"); - info!(" Rooms: {}", memory.stats.cpu.rooms); - info!(" Memory: {}", memory.stats.cpu.rooms); - info!(" Total: {}", game::cpu::get_used()); - info!(" Bucket: {}", game::cpu::bucket()); + info!("[STATS] Statistics are as follows: "); + info!(" GCL {}. Next: {} / {}", game::gcl::level(), game::gcl::progress(), game::gcl::progress_total()); + //info!(" Credits: {}", game::market::credits()); + info!(" Creeps removed this tick: {}", memory.stats.rooms.values().map(|x| x.creeps_removed).sum::()); + info!(" CPU Usage:"); + info!(" Rooms: {}", memory.stats.cpu.rooms); + info!(" Memory: {}", memory.stats.cpu.rooms); + info!(" Total: {}", game::cpu::get_used()); + info!(" Bucket: {}", game::cpu::bucket()); } #[wasm_bindgen(js_name = wipe_memory)] diff --git a/src/memory.rs b/src/memory.rs index 5c0a964..db19d42 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -44,34 +44,26 @@ pub struct CreepMemory{ } } - structstruck::strike! { #[strikethrough[derive(Serialize, Deserialize, Debug, Clone)]] pub struct RoomMemory{ // Name - pub n: String, + pub name: String, // Room type - pub r_t: String, - // Creeps - pub cs: Vec, + pub room_type: String, // Creeps made - pub c_m: u64, + pub creeps_made: u64, // Initialised pub init: bool, // Available mining spots, makes my life easier. - pub avs: u8, + pub available_mining: u8, // Mining stuffs pub mine: HashMap, pub struct { pub s: u8, pub u: u8, }>, - // Creep Count - pub c_c: pub struct { - pub miner: u8, - pub hauler: u8, - pub upgrader: u8, - pub builder: u8, - } + // Creeps by role + pub creeps: HashMap } } @@ -96,6 +88,8 @@ structstruck::strike! { pub creeps_removed: u64, pub energy_harvested: u64, pub energy_harvested_total: u64, + pub energy_available: u64, + pub energy_capacity_available: u64 }>, pub energy_harvested: u64, }, @@ -146,7 +140,6 @@ impl ScreepsMemory { } pub fn create_creep(&mut self, room_name: &str, creep_name: &str, career: Careers, task: Option) { - let room = self.rooms.get_mut(room_name).unwrap(); let creep = CreepMemory { p: None, o_r: room_name.to_string(), @@ -154,7 +147,6 @@ impl ScreepsMemory { t: task, s: "energy".to_string(), }; - room.cs.push(creep_name.to_string()); self.creeps.insert(creep_name.to_string(), creep); info!("Created creep"); } @@ -163,19 +155,13 @@ impl ScreepsMemory { self.rooms.insert( name.to_string(), RoomMemory { - n: name.to_string(), - r_t: "local".to_string(), + name: name.to_string(), + room_type: "local".to_string(), init: false, - cs: Vec::new(), - c_m: 0, - avs: 0, + creeps_made: 0, + available_mining: 0, mine: HashMap::new(), - c_c: CC { - miner: 0, - hauler: 0, - upgrader: 0, - builder: 0, - }, + creeps: HashMap::new(), }, ); } @@ -189,6 +175,12 @@ impl ScreepsMemory { } } +impl RoomMemory { + pub fn get_creeps_by_role(&self, role: &str) -> Vec { + self.creeps.clone().into_iter().filter(|x| x.1 == *role).map(|x| x.0).collect() + } +} + impl Stats { pub fn create_room(&mut self, name: &str, rcl: u8) { self.rooms.insert( @@ -202,6 +194,8 @@ impl Stats { cpu: 0.0, energy_harvested: 0, energy_harvested_total: 0, + energy_available: 0, + energy_capacity_available: 0 } ); } diff --git a/src/roles/mod.rs b/src/roles/mod.rs deleted file mode 100644 index 178b08d..0000000 --- a/src/roles/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod local; \ No newline at end of file diff --git a/src/roles/local/builder.rs b/src/room/creeps/local/builder.rs similarity index 100% rename from src/roles/local/builder.rs rename to src/room/creeps/local/builder.rs diff --git a/src/roles/local/harvester.rs b/src/room/creeps/local/harvester.rs similarity index 93% rename from src/roles/local/harvester.rs rename to src/room/creeps/local/harvester.rs index b6736d9..c73944a 100644 --- a/src/roles/local/harvester.rs +++ b/src/room/creeps/local/harvester.rs @@ -2,7 +2,7 @@ use screeps::{Source, HasPosition, Creep, ResourceType, Part, SharedCreepPropert use crate::{memory::ScreepsMemory, traits::creep::CreepExtensions}; -pub fn harvest(creep: &Creep, memory: &mut ScreepsMemory, source: Source) { +pub fn run_creep(creep: &Creep, memory: &mut ScreepsMemory, source: Source) { let owning_room = memory.get_creep(&creep.name()).o_r.clone(); if creep.pos().is_near_to(source.pos()) { diff --git a/src/roles/local/hauler.rs b/src/room/creeps/local/hauler.rs similarity index 100% rename from src/roles/local/hauler.rs rename to src/room/creeps/local/hauler.rs diff --git a/src/roles/local/mod.rs b/src/room/creeps/local/mod.rs similarity index 100% rename from src/roles/local/mod.rs rename to src/room/creeps/local/mod.rs diff --git a/src/roles/local/scout.rs b/src/room/creeps/local/scout.rs similarity index 100% rename from src/roles/local/scout.rs rename to src/room/creeps/local/scout.rs diff --git a/src/roles/local/upgrader.rs b/src/room/creeps/local/upgrader.rs similarity index 92% rename from src/roles/local/upgrader.rs rename to src/room/creeps/local/upgrader.rs index 59e0a98..e500c5f 100644 --- a/src/roles/local/upgrader.rs +++ b/src/room/creeps/local/upgrader.rs @@ -2,7 +2,7 @@ use screeps::{Creep, StructureController, HasPosition, ResourceType, find}; use crate::{memory::CreepMemory, traits::creep::CreepExtensions}; -pub fn upgrade(creep: &Creep, creepmem: &mut CreepMemory, controller: StructureController) { +pub fn run_creep(creep: &Creep, creepmem: &mut CreepMemory, controller: StructureController) { let inventory = creep.store(); if creepmem.s == "energy" { let closest_energy = creep diff --git a/src/room/creeps/market.rs b/src/room/creeps/market.rs new file mode 100644 index 0000000..baebbf2 --- /dev/null +++ b/src/room/creeps/market.rs @@ -0,0 +1,51 @@ +use log::info; +use screeps::{Room, game}; + +use crate::{memory::ScreepsMemory, traits::room::RoomExtensions, room::population}; + +use super::local; + +pub fn run_creeps(room: &Room, memory: &mut ScreepsMemory) { + info!("[CREEPS] Running creeps in room: {}", room.name_str()); + let creeps = memory.get_room(&room.name_str()).creeps.clone(); + for (creep_name, _job) in creeps { + if game::creeps().get(creep_name.clone()).is_none() { + let creep_mem = memory.get_creep(&creep_name); + if let crate::memory::Task::Miner(_source) = creep_mem.t.clone().expect("Failed to get creep task from memory") { + population::miner_died(memory, &creep_name, &room.name_str()); + } + memory.creeps.remove(&creep_name); + memory.get_room(&room.name_str()).creeps.remove(&creep_name); + continue; + } + + let creep_memory = memory.get_creep(&creep_name); + let creep = game::creeps().get(creep_name.clone()).expect("Failed to get creep from game!"); + + if creep.spawning() { + continue; + } + + if let Some(task) = &creep_memory.t { + match task { + crate::memory::Task::Miner(source_id) => { + if let Some(source) = source_id.resolve() { + local::harvester::run_creep(&creep, memory, source) + } + }, + crate::memory::Task::Hauler(structure_id) => { + if let Some(structure) = structure_id.resolve() { + local::hauler::run_creep(&creep, creep_memory, structure) + } + }, + crate::memory::Task::Upgrader(structure_id) => { + if let Some(structure) = structure_id.resolve() { + local::upgrader::run_creep(&creep, creep_memory, structure) + } + }, + crate::memory::Task::Builder() => local::builder::run_creep(&creep, creep_memory), + _ => {} + } + } + } +} \ No newline at end of file diff --git a/src/room/creeps/mod.rs b/src/room/creeps/mod.rs new file mode 100644 index 0000000..c437612 --- /dev/null +++ b/src/room/creeps/mod.rs @@ -0,0 +1,2 @@ +pub mod market; +pub mod local; \ No newline at end of file diff --git a/src/room/democracy.rs b/src/room/democracy.rs index fc8e3d8..e5d3648 100644 --- a/src/room/democracy.rs +++ b/src/room/democracy.rs @@ -12,7 +12,7 @@ use crate::{ room::population, traits::room::RoomExtensions, }; -use super::industries; +use super::creeps; const UPGRADER_COUNT: u8 = 8; const BUILDER_COUNT: u8 = 4; @@ -26,8 +26,9 @@ pub fn start_government(room: Room, memory: &mut ScreepsMemory) { memory.stats.get_room(&room.name_str()).mining = 0.0; memory.stats.get_room(&room.name_str()).construction = 0.0; memory.stats.get_room(&room.name_str()).energy_harvested = 0; + memory.stats.get_room(&room.name_str()).energy_available = room.energy_available() as u64; + memory.stats.get_room(&room.name_str()).energy_capacity_available = room.energy_capacity_available() as u64; // Horray, i did it better. - let creeps = get_room_creeps_and_clean(memory, &room); let roommem = memory.get_room(&room.name_str()); if !roommem.init { @@ -55,7 +56,7 @@ pub fn start_government(room: Room, memory: &mut ScreepsMemory) { }, ); } - roommem.avs = mining_spots.len() as u8; + roommem.available_mining = mining_spots.len() as u8; roommem.mine = mining_spots; roommem.init = true; } else { @@ -67,61 +68,13 @@ pub fn start_government(room: Room, memory: &mut ScreepsMemory) { } } - industries::mining::pre_market(&room, creeps.clone(), memory); - industries::construction::pre_market(&room, creeps.clone(), memory); + creeps::market::run_creeps(&room, memory); do_spawning(memory, &room); memory.stats.cpu.rooms += game::cpu::get_used() - starting_cpu; memory.stats.rooms.get_mut(&room.name_str()).unwrap().cpu += game::cpu::get_used() - starting_cpu; } -pub fn get_room_creeps_and_clean(memory: &mut ScreepsMemory, room: &Room) -> Vec { - let mut creeps = Vec::new(); - let mut removed_creeps = 0; - for creep_name in &memory - .clone() - .rooms - .get_mut(&room.name_str()) - .unwrap() - .cs - { - if let Some(creep) = game::creeps().get(creep_name.to_string()) { - if creep.spawning() { - continue; - } - - creeps.push(creep_name.to_string()); - } else { - removed_creeps += 1; - match &memory - .creeps - .get(&creep_name.to_string()) - .unwrap() - .t - .clone() - .unwrap() - { - Task::Miner(_) => { - population::miner_died(memory, creep_name, &room.name_str()) - } - Task::Hauler(_) => { - population::hauler_died(memory, creep_name, &room.name_str()) - } - Task::Upgrader(_) => { - population::upgrader_died(memory, creep_name, &room.name_str()) - } - Task::Builder() => { - population::builder_died(memory, creep_name, &room.name_str()) - } - _ => {} - } - memory.creeps.remove(creep_name); - } - } - memory.stats.rooms.get_mut(&room.name_str()).unwrap().creeps_removed += removed_creeps; - creeps -} - pub fn do_spawning(memory: &mut ScreepsMemory, room: &Room) { let binding = memory.clone(); let roommem_readonly = binding.rooms.get(&room.name_str()).unwrap(); @@ -130,10 +83,10 @@ pub fn do_spawning(memory: &mut ScreepsMemory, room: &Room) { let room_name = &room.name_str(); if population::create_miner(memory, room.clone()) { - } else if memory.get_room(&room.name_str()).c_c.hauler - <= ((memory.get_room(&room.name_str()).c_c.miner / 2) as f32).round() as u8 + } else if memory.get_room(&room.name_str()).get_creeps_by_role("hauler").len() as u8 + <= memory.get_room(&room.name_str()).get_creeps_by_role("harvester").len() as u8 { - let name = format!("h-{}", roommem_readonly.c_m); + let name = format!("h-{}", roommem_readonly.creeps_made); let body = [Part::Move, Part::Move, Part::Carry, Part::Work]; let spawn_res = spawn.spawn_creep(&body, &name); if spawn_res.is_ok() { @@ -153,12 +106,12 @@ pub fn do_spawning(memory: &mut ScreepsMemory, room: &Room) { .unwrap(), )), ); - memory.get_room(&room.name_str()).c_c.hauler += 1; - memory.get_room(&room.name_str()).c_m += 1; + memory.get_room(&room.name_str()).creeps.insert(name.to_string(), "hauler".to_string()); + memory.get_room(&room.name_str()).creeps_made += 1; memory.stats.rooms.get_mut(&room.name_str()).unwrap().creeps_made += 1; } - } else if memory.get_room(&room.name_str()).c_c.upgrader < UPGRADER_COUNT { - let name = format!("u-{}", roommem_readonly.c_m); + } else if (memory.get_room(&room.name_str()).get_creeps_by_role("upgrader").len() as u8) < UPGRADER_COUNT { + let name = format!("u-{}", roommem_readonly.creeps_made); let body = [Part::Move, Part::Move, Part::Carry, Part::Carry, Part::Work]; let spawn_res = spawn.spawn_creep(&body, &name); if spawn_res.is_ok() { @@ -170,17 +123,12 @@ pub fn do_spawning(memory: &mut ScreepsMemory, room: &Room) { ObjectId::from_str(&room.controller().unwrap().id().to_string()).unwrap(), )), ); - memory - .rooms - .get_mut(&room.name_str()) - .unwrap() - .c_c - .upgrader += 1; - memory.get_room(&room.name_str()).c_m += 1; + memory.get_room(&room.name().to_string()).creeps.insert(name.to_string(), "upgrader".to_string()); + memory.get_room(&room.name_str()).creeps_made += 1; memory.stats.rooms.get_mut(&room.name_str()).unwrap().creeps_made += 1; } - } else if memory.get_room(&room.name_str()).c_c.builder < BUILDER_COUNT { - let name = format!("b-{}", roommem_readonly.c_m); + } else if (memory.get_room(&room.name_str()).get_creeps_by_role("builder").len() as u8) < BUILDER_COUNT { + let name = format!("b-{}", roommem_readonly.creeps_made); let body = [Part::Move, Part::Carry, Part::Carry, Part::Work]; let spawn_res = spawn.spawn_creep(&body, &name); if spawn_res.is_ok() { @@ -190,8 +138,8 @@ pub fn do_spawning(memory: &mut ScreepsMemory, room: &Room) { crate::memory::Careers::Mining, Some(Task::Builder()), ); - memory.get_room(&room.name_str()).c_c.builder += 1; - memory.get_room(&room.name_str()).c_m += 1; + memory.get_room(&room.name_str()).creeps.insert(name.to_string(), "builder".to_string()); + memory.get_room(&room.name_str()).creeps_made += 1; memory.stats.rooms.get_mut(&room.name_str()).unwrap().creeps_made += 1; } } diff --git a/src/room/industries/construction.rs b/src/room/industries/construction.rs deleted file mode 100644 index da96b11..0000000 --- a/src/room/industries/construction.rs +++ /dev/null @@ -1,43 +0,0 @@ -use log::info; -use screeps::{game, Room, HasPosition, TextStyle}; - -use crate::{memory::ScreepsMemory, traits::room::RoomExtensions}; - -pub fn pre_market(room: &Room, creeps: Vec, memory: &mut ScreepsMemory) { - let starting_cpu = game::cpu::get_used(); - info!("[INDUSTRIES] Running construction industry"); - - for name in creeps { - let creepmem = memory.get_creep(&name); - if let Some(task) = &creepmem.t { - let creep = game::creeps().get(name).unwrap(); - match task { - crate::memory::Task::Upgrader(controller_id) => { - if let Some(building) = controller_id.resolve() { - crate::roles::local::upgrader::upgrade(&creep, creepmem, building) - } - } - crate::memory::Task::Builder() => { - crate::roles::local::builder::run_creep(&creep, creepmem); - } - _ => {} - } - } - } - - if game::cpu::bucket() > 500 { - for room in game::rooms().values() { - let controller = room.controller().unwrap().pos(); - let result = room.flood_fill(vec![(controller.x().u8(), controller.y().u8())]); - for x in 0..=50 { - for y in 0..=50 { - let text = result.get(x, y); - - room.visual().text(x as f32, y as f32 + 0.25, format!("{}", text), Some(TextStyle::default().color("#ffffff").align(screeps::TextAlign::Center).font(0.5))); - } - } - } - } - - memory.stats.rooms.get_mut(&room.name_str()).unwrap().construction += game::cpu::get_used() - starting_cpu; -} diff --git a/src/room/industries/mining.rs b/src/room/industries/mining.rs deleted file mode 100644 index a65da0c..0000000 --- a/src/room/industries/mining.rs +++ /dev/null @@ -1,37 +0,0 @@ -use log::info; -use screeps::{game, Room}; - -use crate::{memory::ScreepsMemory, traits::room::RoomExtensions}; - -pub fn pre_market( - room: &Room, - creeps: Vec, - memory: &mut ScreepsMemory, -) { - let starting_cpu = game::cpu::get_used(); - info!("[INDUSTRIES] Running mining industry..."); - - for name in creeps { - let creepmem = memory.get_creep(&name); - if let Some(task) = &creepmem.t { - let creep = game::creeps().get(name).unwrap(); - match task { - crate::memory::Task::Miner(source_id) => { - if let Some(source) = source_id.resolve() { - crate::roles::local::harvester::harvest(&creep, memory, source) - } else { - creepmem.t = None; - } - } - crate::memory::Task::Hauler(building_id) => { - if let Some(building) = building_id.resolve() { - crate::roles::local::hauler::run_creep(&creep, creepmem, building) - } - } - _ => {}, - } - } - } - - memory.stats.rooms.get_mut(&room.name_str()).unwrap().mining += game::cpu::get_used() - starting_cpu; -} diff --git a/src/room/industries/mod.rs b/src/room/industries/mod.rs deleted file mode 100644 index 98cb259..0000000 --- a/src/room/industries/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod mining; -pub mod construction; \ No newline at end of file diff --git a/src/room/mod.rs b/src/room/mod.rs index 49a03d9..4c50b54 100644 --- a/src/room/mod.rs +++ b/src/room/mod.rs @@ -1,4 +1,4 @@ pub mod democracy; pub mod population; pub mod building; -pub mod industries; \ No newline at end of file +pub mod creeps; \ No newline at end of file diff --git a/src/room/population.rs b/src/room/population.rs index 26fc833..da9b25c 100644 --- a/src/room/population.rs +++ b/src/room/population.rs @@ -6,14 +6,11 @@ use crate::{ }; pub fn create_miner(memory: &mut ScreepsMemory, room: Room) -> bool { - if memory.get_room(&room.name_str()).c_c.miner >= 1 - && memory.get_room(&room.name_str()).c_c.hauler < 1 - { + if !memory.get_room(&room.name_str()).get_creeps_by_role("miner").is_empty() && memory.get_room(&room.name_str()).get_creeps_by_role("hauler").is_empty() { return false; } - let sources = memory.get_room(&room.name_str()) - .mine - .clone(); + + let sources = memory.get_room(&room.name_str()).mine.clone(); let mut selected_source = None; for (source_id, source_mem) in sources { if selected_source.is_none() && source_mem.s > source_mem.u { @@ -23,7 +20,7 @@ pub fn create_miner(memory: &mut ScreepsMemory, room: Room) -> bool { } } if let Some(source) = selected_source { - let name = format!("m-{}", memory.get_room(&room.name_str()).c_m); + let name = format!("m-{}", memory.get_room(&room.name_str()).creeps_made); let body = [Part::Move, Part::Work, Part::Work]; let spawn_res = room .find(find::MY_SPAWNS, None) @@ -37,20 +34,10 @@ pub fn create_miner(memory: &mut ScreepsMemory, room: Room) -> bool { crate::memory::Careers::Mining, Some(Task::Miner(source)), ); - memory.get_room(&room.name_str()).c_c.miner += 1; - memory.get_room(&room.name_str()).c_m += 1; - memory - .get_room(&room.name_str()) - .mine - .get_mut(&source) - .unwrap() - .u += 1; - memory - .stats - .rooms - .get_mut(&room.name_str()) - .unwrap() - .creeps_made += 1; + memory.get_room(&room.name_str()).creeps.insert(name, "miner".to_string()); + memory.get_room(&room.name_str()).creeps_made += 1; + memory.get_room(&room.name_str()).mine.get_mut(&source).unwrap().u += 1; + memory.stats.rooms.get_mut(&room.name_str()).unwrap().creeps_made += 1; true } else { false @@ -62,61 +49,24 @@ pub fn create_miner(memory: &mut ScreepsMemory, room: Room) -> bool { pub fn miner_died(memory: &mut ScreepsMemory, creep_name: &str, room_name: &str) { // Remove from rooms creep count and from room creep list - memory.get_room(room_name).c_c.miner -= 1; - - memory.get_room(room_name).cs = memory.get_room(room_name).cs.iter().filter(|x| x != &&creep_name.to_string()).map(|x| x.to_string()).collect(); + memory.get_room(room_name).creeps.remove(&creep_name.to_string()); // Downtick the counters for used sources - let mining_source_id = memory.get_creep(creep_name).t.clone().expect("Failed to get creep task from memory"); + let mining_source_id = memory + .get_creep(creep_name) + .t + .clone() + .expect("Failed to get creep task from memory"); if let Task::Miner(source_id) = mining_source_id { - - memory.get_room(room_name).mine.get_mut(&source_id).expect("Failed to get source from memory").u -= 1; - + memory + .get_room(room_name) + .mine + .get_mut(&source_id) + .expect("Failed to get source from memory") + .u -= 1; } // Remove said creep from memory memory.creeps.remove(creep_name); } - -pub fn hauler_died(memory: &mut ScreepsMemory, creep_name: &str, room_name: &str) { - // Remove from rooms creep count and from room creep list - memory.get_room(room_name).c_c.hauler -= 1; - memory.get_room(room_name).cs = memory.get_room(room_name) - .cs - .iter() - .filter(|x| x != &&creep_name.to_string()) - .map(|x| x.to_string()) - .collect(); - - // Remove said creep from memory - memory.creeps.remove(creep_name); -} - -pub fn upgrader_died(memory: &mut ScreepsMemory, creep_name: &str, room_name: &str) { - // Remove from rooms creep count and from room creep list - memory.get_room(room_name).c_c.upgrader -= 1; - memory.get_room(room_name).cs = memory.get_room(room_name) - .cs - .iter() - .filter(|x| x != &&creep_name.to_string()) - .map(|x| x.to_string()) - .collect(); - - // Remove said creep from memory - memory.creeps.remove(creep_name); -} - -pub fn builder_died(memory: &mut ScreepsMemory, creep_name: &str, room_name: &str) { - // Remove from rooms creep count and from room creep list - memory.get_room(room_name).c_c.builder -= 1; - memory.get_room(room_name).cs = memory.get_room(room_name) - .cs - .iter() - .filter(|x| x != &&creep_name.to_string()) - .map(|x| x.to_string()) - .collect(); - - // Remove said creep from memory - memory.creeps.remove(creep_name); -} diff --git a/src/visual/room.rs b/src/visual/room.rs index 2c6b681..da6a3a3 100644 --- a/src/visual/room.rs +++ b/src/visual/room.rs @@ -1,6 +1,8 @@ use std::str::FromStr; -use screeps::{game, HasPosition, RoomName, RoomVisual, TextStyle, MapVisual, Position, RoomCoordinate}; +use screeps::{ + game, HasPosition, MapVisual, Position, RoomCoordinate, RoomName, RoomVisual, TextStyle, +}; use crate::{memory::ScreepsMemory, traits::room::RoomExtensions}; @@ -15,29 +17,32 @@ pub fn classify_rooms(memory: &ScreepsMemory) { .align(screeps::TextAlign::Left), ); // Creep counters - roomvis.text(1_f32, 1_f32, "Stats".to_string(), white_left.clone()); + roomvis.text(0_f32, 1_f32, "Stats".to_string(), white_left.clone()); roomvis.text( - 1_f32, + 0_f32, 2_f32, - format!("Miners: {}", roommem.c_c.miner), + format!("Miners: {}", roommem.get_creeps_by_role("miner").len()), white_left.clone(), ); roomvis.text( - 1_f32, + 0_f32, 3_f32, - format!("Haulers: {}", roommem.c_c.hauler), + format!("Haulers: {}", roommem.get_creeps_by_role("hauler").len()), white_left.clone(), ); roomvis.text( - 1_f32, + 0_f32, 4_f32, - format!("Upgraders: {}", roommem.c_c.upgrader), + format!( + "Upgraders: {}", + roommem.get_creeps_by_role("upgrader").len() + ), white_left.clone(), ); roomvis.text( - 1_f32, + 0_f32, 5_f32, - format!("Builders: {}", roommem.c_c.builder), + format!("Builders: {}", roommem.get_creeps_by_role("builder").len()), white_left.clone(), ); @@ -59,8 +64,20 @@ pub fn classify_rooms(memory: &ScreepsMemory) { } for room in game::rooms().values() { - let pos = Position::new(RoomCoordinate::new(25).unwrap(), RoomCoordinate::new(3).unwrap(), room.name()); - MapVisual::text(pos, get_room_type(&room.name_str()), Some(TextStyle::default().color("#ffffff").align(screeps::TextAlign::Center))); + let pos = Position::new( + RoomCoordinate::new(25).unwrap(), + RoomCoordinate::new(3).unwrap(), + room.name(), + ); + MapVisual::text( + pos, + get_room_type(&room.name_str()), + Some( + TextStyle::default() + .color("#ffffff") + .align(screeps::TextAlign::Center), + ), + ); } } @@ -78,4 +95,4 @@ pub fn get_room_type(name: &str) -> String { } else { "none".to_string() } -} \ No newline at end of file +} diff --git a/temp.js b/temp.js deleted file mode 100644 index b0d8fca..0000000 --- a/temp.js +++ /dev/null @@ -1,106 +0,0 @@ -const roomDimensions = 50 - -findPositionsInsideRect = function(rect) { - - const positions = [] - - for (let x = rect.x1; x <= rect.x2; x++) { - for (let y = rect.y1; y <= rect.y2; y++) { - - // Iterate if the pos doesn't map onto a room - - if (x < 0 || x >= roomDimensions || - y < 0 || y >= roomDimensions) continue - - // Otherwise ass the x and y to positions - - positions.push({ x, y }) - } - } - - return positions -} - -Room.prototype.floodFill = function(seeds) { - - const room = this - - const floodCM = new PathFinder.CostMatrix() - let terrain = room.getTerrain() - let visitedCM = new PathFinder.CostMatrix() - - let depth = 0 - let thisGeneration = seeds - let nextGeneration = [] - - for (const pos of seeds) { - - visitedCM.set(pos.x, pos.y, 1) - } - - // So long as there are positions in this gen - - while (thisGeneration.length) { - - // Reset next gen - - nextGeneration = [] - - // Iterate through positions of this gen - - for (const pos of thisGeneration) { - - // If the depth isn't 0 - - if (depth != 0) { - - // Iterate if the terrain is a wall - - if (terrain.get(pos.x, pos.y) == TERRAIN_MASK_WALL) continue - - // Otherwise so long as the pos isn't a wall record its depth in the flood cost matrix - - floodCM.set(pos.x, pos.y, depth) - - // If visuals are enabled, show the depth on the pos - - if (Memory.roomVisuals) room.visual.rect(pos.x - 0.5, pos.y - 0.5, 1, 1, { - fill: 'hsl(' + 200 + depth * 2 + ', 100%, 60%)', - opacity: 0.4, - }) - } - - // Construct a rect and get the positions in a range of 1 - - const rect = { x1: pos.x - 1, y1: pos.y - 1, x2: pos.x + 1, y2: pos.y + 1 }, - adjacentPositions = findPositionsInsideRect(rect) - - // Loop through adjacent positions - - for (const adjacentPos of adjacentPositions) { - - // Iterate if the adjacent pos has been visited or isn't a tile - - if (visitedCM.get(adjacentPos.x, adjacentPos.y) == 1) continue - - // Otherwise record that it has been visited - - visitedCM.set(adjacentPos.x, adjacentPos.y, 1) - - // Add it to the next gen - - nextGeneration.push(adjacentPos) - } - } - - // Set this gen to next gen - - thisGeneration = nextGeneration - - // Increment depth - - depth++ - } - - return floodCM -} \ No newline at end of file From 28bb6a5b00eff5b9af7f73f95609dbeed142862b Mon Sep 17 00:00:00 2001 From: InfinityDevTech <47366052+InfinityDevTech@users.noreply.github.com> Date: Thu, 31 Aug 2023 21:17:36 -0400 Subject: [PATCH 12/13] Added towers, tweaked and fixed some bugs. Works. --- src/room/democracy.rs | 7 +++---- src/room/mod.rs | 3 ++- src/room/tower.rs | 16 ++++++++++++++++ 3 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 src/room/tower.rs diff --git a/src/room/democracy.rs b/src/room/democracy.rs index e5d3648..a4d9506 100644 --- a/src/room/democracy.rs +++ b/src/room/democracy.rs @@ -12,7 +12,7 @@ use crate::{ room::population, traits::room::RoomExtensions, }; -use super::creeps; +use super::{creeps, tower}; const UPGRADER_COUNT: u8 = 8; const BUILDER_COUNT: u8 = 4; @@ -69,6 +69,7 @@ pub fn start_government(room: Room, memory: &mut ScreepsMemory) { } creeps::market::run_creeps(&room, memory); + tower::run_towers(&room); do_spawning(memory, &room); memory.stats.cpu.rooms += game::cpu::get_used() - starting_cpu; @@ -83,9 +84,7 @@ pub fn do_spawning(memory: &mut ScreepsMemory, room: &Room) { let room_name = &room.name_str(); if population::create_miner(memory, room.clone()) { - } else if memory.get_room(&room.name_str()).get_creeps_by_role("hauler").len() as u8 - <= memory.get_room(&room.name_str()).get_creeps_by_role("harvester").len() as u8 - { + } else if memory.get_room(&room.name_str()).get_creeps_by_role("hauler").len() < 5 { let name = format!("h-{}", roommem_readonly.creeps_made); let body = [Part::Move, Part::Move, Part::Carry, Part::Work]; let spawn_res = spawn.spawn_creep(&body, &name); diff --git a/src/room/mod.rs b/src/room/mod.rs index 4c50b54..69ebecd 100644 --- a/src/room/mod.rs +++ b/src/room/mod.rs @@ -1,4 +1,5 @@ pub mod democracy; pub mod population; pub mod building; -pub mod creeps; \ No newline at end of file +pub mod creeps; +pub mod tower; \ No newline at end of file diff --git a/src/room/tower.rs b/src/room/tower.rs new file mode 100644 index 0000000..e367ab2 --- /dev/null +++ b/src/room/tower.rs @@ -0,0 +1,16 @@ +use screeps::{Room, find, StructureType, StructureProperties, StructureObject}; + +pub fn run_towers(room: &Room) { + let towers = room.find(find::MY_STRUCTURES, None).into_iter().filter(|s| s.structure_type() == StructureType::Tower).collect::>(); + if !towers.is_empty() { + let enemies = room.find(find::HOSTILE_CREEPS, None); + if enemies.is_empty() { + return; + } + for tower_obj in towers { + if let StructureObject::StructureTower(tower) = tower_obj { + let _ = tower.attack(enemies.first().unwrap()); + } + } + } +} \ No newline at end of file From 2fd8ae2bd4934f8ada3d416dbb75445647afc498 Mon Sep 17 00:00:00 2001 From: InfinityDevTech <47366052+InfinityDevTech@users.noreply.github.com> Date: Fri, 1 Sep 2023 08:20:13 -0400 Subject: [PATCH 13/13] t --- src/room/creeps/local/scout.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/room/creeps/local/scout.rs b/src/room/creeps/local/scout.rs index 79c0f64..4d03bd0 100644 --- a/src/room/creeps/local/scout.rs +++ b/src/room/creeps/local/scout.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] + use screeps::{Creep, game, Position, RoomCoordinate}; use crate::{memory::CreepMemory, traits::creep::CreepExtensions};