From 92a13bac9289fd00a6fa2c70129490fa22ef0661 Mon Sep 17 00:00:00 2001 From: Ilion Beyst Date: Sat, 25 Dec 2021 15:36:23 +0100 Subject: [PATCH] add init-project command --- planetwars-localdev/README.md | 8 +++- planetwars-localdev/assets/hex.json | 43 ++++++++++++++++++++++ planetwars-localdev/assets/pw_project.toml | 10 +++++ planetwars-localdev/assets/simplebot.py | 33 +++++++++++++++++ planetwars-localdev/src/lib.rs | 40 +++++++++++++++++++- planetwars-rules/src/config.rs | 3 +- 6 files changed, 134 insertions(+), 3 deletions(-) create mode 100644 planetwars-localdev/assets/hex.json create mode 100644 planetwars-localdev/assets/pw_project.toml create mode 100644 planetwars-localdev/assets/simplebot.py diff --git a/planetwars-localdev/README.md b/planetwars-localdev/README.md index 1e923b9..3263508 100644 --- a/planetwars-localdev/README.md +++ b/planetwars-localdev/README.md @@ -1,3 +1,9 @@ # planetwars-localdev -Tools for developping planetwars bots locally. \ No newline at end of file +Tools for developping planetwars bots locally. + +## Getting started + +1. Initialize your project directory: `pwcli init-project my_project` +2. Enter your fresh project: `cd my_project` +3. Run an example match: `pwcli run-match hex simplebot simplebot` diff --git a/planetwars-localdev/assets/hex.json b/planetwars-localdev/assets/hex.json new file mode 100644 index 0000000..5ef4f31 --- /dev/null +++ b/planetwars-localdev/assets/hex.json @@ -0,0 +1,43 @@ +{ + "planets": [ + { + "name": "protos", + "x": -6, + "y": 0, + "owner": 1, + "ship_count": 6 + }, + { + "name": "duteros", + "x": -3, + "y": 5, + "ship_count": 6 + }, + { + "name": "tritos", + "x": 3, + "y": 5, + "ship_count": 6 + }, + { + "name": "tetartos", + "x": 6, + "y": 0, + "owner": 2, + "ship_count": 6 + }, + { + "name": "pemptos", + "x": 3, + "y": -5, + "ship_count": 6 + }, + { + "name": "extos", + "x": -3, + "y": -5, + "ship_count": 6 + } + ] +} + diff --git a/planetwars-localdev/assets/pw_project.toml b/planetwars-localdev/assets/pw_project.toml new file mode 100644 index 0000000..85a4ab6 --- /dev/null +++ b/planetwars-localdev/assets/pw_project.toml @@ -0,0 +1,10 @@ +[bots] + +# define a bot called simplebot +[bots.simplebot] + +# The working directory for the bot. +path = "./bots/simplebot" + +# What command to use for running the bot +argv = ["python", "simplebot.py"] \ No newline at end of file diff --git a/planetwars-localdev/assets/simplebot.py b/planetwars-localdev/assets/simplebot.py new file mode 100644 index 0000000..b2a6b8f --- /dev/null +++ b/planetwars-localdev/assets/simplebot.py @@ -0,0 +1,33 @@ +import sys, json + +def move(command): + """ print a command record to stdout """ + moves = [] + if command is not None: + moves.append(command) + + print(json.dumps({ 'moves': moves })) + # flush the buffer, so that the gameserver can receive the json-encoded line. + sys.stdout.flush() + + +for line in sys.stdin: + state = json.loads(line) + # you are always player 1. + my_planets = [p for p in state['planets'] if p['owner'] == 1] + other_planets = [p for p in state['planets'] if p['owner'] != 1] + + if not my_planets or not other_planets: + # we don't own any planets, so we can't make any moves. + move(None) + else: + # find my planet that has the most ships + planet = max(my_planets, key=lambda p: p['ship_count']) + # find enemy planet that has the least ships + destination = min(other_planets, key=lambda p: p['ship_count']) + # attack! + move({ + 'origin': planet['name'], + 'destination': destination['name'], + 'ship_count': planet['ship_count'] - 1 + }) diff --git a/planetwars-localdev/src/lib.rs b/planetwars-localdev/src/lib.rs index 3b77efb..562e9a6 100644 --- a/planetwars-localdev/src/lib.rs +++ b/planetwars-localdev/src/lib.rs @@ -22,6 +22,8 @@ struct Cli { #[derive(Subcommand)] enum Commands { + /// Initialize a new project + InitProject(InitProjectCommand), /// Run a match RunMatch(RunMatchCommand), } @@ -34,6 +36,12 @@ struct RunMatchCommand { bots: Vec, } +#[derive(Parser)] +struct InitProjectCommand { + /// project root directory + path: String, +} + #[derive(Serialize, Deserialize, Debug)] struct ProjectConfig { bots: HashMap, @@ -49,6 +57,7 @@ pub async fn run() { let matches = Cli::parse(); let res = match matches.command { Commands::RunMatch(command) => run_match(command).await, + Commands::InitProject(command) => init_project(command), }; if let Err(err) = res { eprintln!("{}", err); @@ -89,7 +98,10 @@ async fn run_match(command: RunMatchCommand) -> io::Result<()> { }; match_runner::run_match(match_config).await; - + println!("match completed successfully"); + // TODO: don't hardcode match path. + // maybe print the match result as well? + println!("wrote match log to matches/{}.log", timestamp); Ok(()) } @@ -101,3 +113,29 @@ fn resolve_bot_config(project_dir: &Path, config: BotConfig) -> BotConfig { argv: config.argv, } } + +macro_rules! copy_asset { + ($path:expr, $file_name:literal) => { + ::std::fs::write( + $path.join($file_name), + include_bytes!(concat!("../assets/", $file_name)), + )?; + }; +} + +fn init_project(command: InitProjectCommand) -> io::Result<()> { + let path = PathBuf::from(&command.path); + + // create directories + std::fs::create_dir_all(&path)?; + std::fs::create_dir(path.join("maps"))?; + std::fs::create_dir(path.join("matches"))?; + std::fs::create_dir_all(path.join("bots/simplebot"))?; + + // create files + copy_asset!(path, "pw_project.toml"); + copy_asset!(path.join("maps"), "hex.json"); + copy_asset!(path.join("bots/simplebot"), "simplebot.py"); + + Ok(()) +} diff --git a/planetwars-rules/src/config.rs b/planetwars-rules/src/config.rs index 32c23f5..57c77eb 100644 --- a/planetwars-rules/src/config.rs +++ b/planetwars-rules/src/config.rs @@ -1,6 +1,7 @@ use std::fs::File; use std::io; use std::io::Read; +use std::path::PathBuf; use serde_json; @@ -9,7 +10,7 @@ use super::rules::*; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Config { - pub map_file: String, + pub map_file: PathBuf, pub max_turns: u64, }