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
|
||||
|
||||
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)]
|
||||
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(())
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue