Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add example of getting random values, use them for creep name #36

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ edition = "2021"
crate-type = ["cdylib", "rlib"]

[dependencies]
fern = "0.6"
getrandom = { version = "0.2", features = ["custom"] }
js-sys = "0.3"
log = "0.4"
fern = "0.6"
rand = "0.8"
screeps-game-api = "0.10"
wasm-bindgen = "0.2"
web-sys = { version = "0.3", features = ["console"] }
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ cd screeps-starter-rust
cp example-screeps.toml screeps.toml
nano screeps.toml
# configure credentials (API key) if you'd like to upload directly,
# or a directory to copy to if you'd prepfer to use the game client to deploy
# or a directory to copy to if you'd prefer to use the game client to deploy

# build tool:
cargo screeps --help
Expand Down
50 changes: 29 additions & 21 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use std::cell::RefCell;
use std::collections::{HashMap, hash_map::Entry};
use std::collections::{hash_map::Entry, HashMap};

use getrandom::register_custom_getrandom;
use log::*;
use rand::prelude::*;
use screeps::{
find, game, prelude::*, Creep, ObjectId, Part, ResourceType, ReturnCode, RoomObjectProperties,
Source, StructureController, StructureObject,
Expand All @@ -10,6 +12,16 @@ use wasm_bindgen::prelude::*;

mod logging;

// implement a custom randomness generator for the getrandom crate,
// because the `js` feature expects the Node.js WebCrypto API to be available
// (it's not available in the Screeps Node.js environment)
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]
pub fn setup() {
Expand All @@ -22,7 +34,10 @@ thread_local! {
static CREEP_TARGETS: RefCell<HashMap<String, CreepTarget>> = RefCell::new(HashMap::new());
}

// 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
// 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)]
enum CreepTarget {
Upgrade(ObjectId<StructureController>),
Expand All @@ -38,40 +53,27 @@ pub fn game_loop() {
CREEP_TARGETS.with(|creep_targets_refcell| {
let mut creep_targets = creep_targets_refcell.borrow_mut();
debug!("running creeps");
// same type conversion (and type assumption) as the spawn loop
for creep in game::creeps().values() {
run_creep(&creep, &mut creep_targets);
}
});

debug!("running spawns");
// Game::spawns returns a `js_sys::Object`, which is a light reference to an
// object of any kind which is held on the javascript heap.
//
// Object::values returns a `js_sys::Array`, which contains the member spawn objects
// representing all the spawns you control.
//
// They are returned as wasm_bindgen::JsValue references, which we can safely
// assume are StructureSpawn objects as returned from js without checking first
let mut additional = 0;
for spawn in game::spawns().values() {
debug!("running spawn {}", String::from(spawn.name()));

let body = [Part::Move, Part::Move, Part::Carry, Part::Work];
if spawn.room().unwrap().energy_available() >= body.iter().map(|p| p.cost()).sum() {
// create a unique name, spawn.
let name_base = game::time();
let name = format!("{}-{}", name_base, additional);
let name = format!("{}-{}", name_base, random::<u8>());
// note that this bot has a fatal flaw; spawning a creep
// creates Memory.creeps[creep_name] which will build up forever;
// these memory entries should be prevented (todo doc link on how) or cleaned up
let res = spawn.spawn_creep(&body, &name);

// todo once fixed in branch this should be ReturnCode::Ok instead of this i8 grumble grumble
if res != ReturnCode::Ok {
warn!("couldn't spawn: {:?}", res);
} else {
additional += 1;
}
}
}
Expand All @@ -88,10 +90,12 @@ fn run_creep(creep: &Creep, creep_targets: &mut HashMap<String, CreepTarget>) {

let target = creep_targets.entry(name);
match target {
Entry::Occupied(entry) => {
Entry::Occupied(entry) => {
let creep_target = entry.get();
match creep_target {
CreepTarget::Upgrade(controller_id) if creep.store().get_used_capacity(Some(ResourceType::Energy)) > 0 => {
CreepTarget::Upgrade(controller_id)
if creep.store().get_used_capacity(Some(ResourceType::Energy)) > 0 =>
{
if let Some(controller) = controller_id.resolve() {
let r = creep.upgrade_controller(&controller);
if r == ReturnCode::NotInRange {
Expand All @@ -104,7 +108,9 @@ fn run_creep(creep: &Creep, creep_targets: &mut HashMap<String, CreepTarget>) {
entry.remove();
}
}
CreepTarget::Harvest(source_id) if creep.store().get_free_capacity(Some(ResourceType::Energy)) > 0 => {
CreepTarget::Harvest(source_id)
if creep.store().get_free_capacity(Some(ResourceType::Energy)) > 0 =>
{
if let Some(source) = source_id.resolve() {
if creep.pos().is_near_to(source.pos()) {
let r = creep.harvest(&source);
Expand All @@ -118,8 +124,10 @@ fn run_creep(creep: &Creep, creep_targets: &mut HashMap<String, CreepTarget>) {
} else {
entry.remove();
}
},
_ => { entry.remove(); }
}
_ => {
entry.remove();
}
};
}
Entry::Vacant(entry) => {
Expand Down