aboutsummaryrefslogtreecommitdiff
path: root/planetwars-localdev
diff options
context:
space:
mode:
Diffstat (limited to 'planetwars-localdev')
-rw-r--r--planetwars-localdev/README.md8
-rw-r--r--planetwars-localdev/assets/hex.json43
-rw-r--r--planetwars-localdev/assets/pw_project.toml10
-rw-r--r--planetwars-localdev/assets/simplebot.py33
-rw-r--r--planetwars-localdev/src/lib.rs40
5 files changed, 132 insertions, 2 deletions
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<String>,
}
+#[derive(Parser)]
+struct InitProjectCommand {
+ /// project root directory
+ path: String,
+}
+
#[derive(Serialize, Deserialize, Debug)]
struct ProjectConfig {
bots: HashMap<String, BotConfig>,
@@ -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(())
+}