add init-project command
This commit is contained in:
parent
d0a0fcfded
commit
92a13bac92
6 changed files with 134 additions and 3 deletions
|
@ -1,3 +1,9 @@
|
||||||
# planetwars-localdev
|
# planetwars-localdev
|
||||||
|
|
||||||
Tools for developping planetwars bots locally.
|
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`
|
||||||
|
|
43
planetwars-localdev/assets/hex.json
Normal file
43
planetwars-localdev/assets/hex.json
Normal file
|
@ -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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
10
planetwars-localdev/assets/pw_project.toml
Normal file
10
planetwars-localdev/assets/pw_project.toml
Normal file
|
@ -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"]
|
33
planetwars-localdev/assets/simplebot.py
Normal file
33
planetwars-localdev/assets/simplebot.py
Normal file
|
@ -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
|
||||||
|
})
|
|
@ -22,6 +22,8 @@ struct Cli {
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
enum Commands {
|
enum Commands {
|
||||||
|
/// Initialize a new project
|
||||||
|
InitProject(InitProjectCommand),
|
||||||
/// Run a match
|
/// Run a match
|
||||||
RunMatch(RunMatchCommand),
|
RunMatch(RunMatchCommand),
|
||||||
}
|
}
|
||||||
|
@ -34,6 +36,12 @@ struct RunMatchCommand {
|
||||||
bots: Vec<String>,
|
bots: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Parser)]
|
||||||
|
struct InitProjectCommand {
|
||||||
|
/// project root directory
|
||||||
|
path: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
struct ProjectConfig {
|
struct ProjectConfig {
|
||||||
bots: HashMap<String, BotConfig>,
|
bots: HashMap<String, BotConfig>,
|
||||||
|
@ -49,6 +57,7 @@ pub async fn run() {
|
||||||
let matches = Cli::parse();
|
let matches = Cli::parse();
|
||||||
let res = match matches.command {
|
let res = match matches.command {
|
||||||
Commands::RunMatch(command) => run_match(command).await,
|
Commands::RunMatch(command) => run_match(command).await,
|
||||||
|
Commands::InitProject(command) => init_project(command),
|
||||||
};
|
};
|
||||||
if let Err(err) = res {
|
if let Err(err) = res {
|
||||||
eprintln!("{}", err);
|
eprintln!("{}", err);
|
||||||
|
@ -89,7 +98,10 @@ async fn run_match(command: RunMatchCommand) -> io::Result<()> {
|
||||||
};
|
};
|
||||||
|
|
||||||
match_runner::run_match(match_config).await;
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,3 +113,29 @@ fn resolve_bot_config(project_dir: &Path, config: BotConfig) -> BotConfig {
|
||||||
argv: config.argv,
|
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(())
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use serde_json;
|
use serde_json;
|
||||||
|
|
||||||
|
@ -9,7 +10,7 @@ use super::rules::*;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub map_file: String,
|
pub map_file: PathBuf,
|
||||||
pub max_turns: u64,
|
pub max_turns: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue