track player status and return player outcomes from match
This commit is contained in:
parent
b7bcbdd3a6
commit
2a37b96da2
2 changed files with 67 additions and 47 deletions
|
@ -14,7 +14,6 @@ use futures::{stream::FuturesOrdered, StreamExt};
|
||||||
use match_context::MatchCtx;
|
use match_context::MatchCtx;
|
||||||
use match_log::{create_log_sink, MatchLogger};
|
use match_log::{create_log_sink, MatchLogger};
|
||||||
use planetwars_rules::PwConfig;
|
use planetwars_rules::PwConfig;
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
pub use self::match_context::{EventBus, PlayerHandle};
|
pub use self::match_context::{EventBus, PlayerHandle};
|
||||||
|
|
||||||
|
@ -25,18 +24,6 @@ pub struct MatchConfig {
|
||||||
pub players: Vec<MatchPlayer>,
|
pub players: Vec<MatchPlayer>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct MatchMeta {
|
|
||||||
pub map_name: String,
|
|
||||||
pub timestamp: chrono::DateTime<chrono::Local>,
|
|
||||||
pub players: Vec<PlayerInfo>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct PlayerInfo {
|
|
||||||
pub name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct MatchPlayer {
|
pub struct MatchPlayer {
|
||||||
pub bot_spec: Box<dyn BotSpec>,
|
pub bot_spec: Box<dyn BotSpec>,
|
||||||
}
|
}
|
||||||
|
@ -53,6 +40,12 @@ pub trait BotSpec: Send + Sync {
|
||||||
|
|
||||||
pub struct MatchOutcome {
|
pub struct MatchOutcome {
|
||||||
pub winner: Option<usize>,
|
pub winner: Option<usize>,
|
||||||
|
pub player_outcomes: Vec<PlayerOutcome>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PlayerOutcome {
|
||||||
|
pub had_errors: bool,
|
||||||
|
pub crashed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run_match(config: MatchConfig) -> MatchOutcome {
|
pub async fn run_match(config: MatchConfig) -> MatchOutcome {
|
||||||
|
@ -86,36 +79,31 @@ pub async fn run_match(config: MatchConfig) -> MatchOutcome {
|
||||||
|
|
||||||
let match_ctx = MatchCtx::new(event_bus, players, match_logger);
|
let match_ctx = MatchCtx::new(event_bus, players, match_logger);
|
||||||
|
|
||||||
// TODO: is this still needed?
|
let mut match_instance = pw_match::PwMatch::create(match_ctx, pw_config);
|
||||||
// assemble the math meta struct
|
match_instance.run().await;
|
||||||
// let match_meta = MatchMeta {
|
match_instance.match_ctx.shutdown().await;
|
||||||
// map_name: config.map_name.clone(),
|
|
||||||
// timestamp: chrono::Local::now(),
|
|
||||||
// players: config
|
|
||||||
// .players
|
|
||||||
// .iter()
|
|
||||||
// .map(|bot| PlayerInfo {
|
|
||||||
// name: bot.name.clone(),
|
|
||||||
// })
|
|
||||||
// .collect(),
|
|
||||||
// };
|
|
||||||
// write!(
|
|
||||||
// log_file,
|
|
||||||
// "{}\n",
|
|
||||||
// serde_json::to_string(&match_meta).unwrap()
|
|
||||||
// )
|
|
||||||
// .unwrap();
|
|
||||||
|
|
||||||
let final_state = pw_match::PwMatch::create(match_ctx, pw_config).run().await;
|
let survivors = match_instance.match_state.state().living_players();
|
||||||
|
|
||||||
let survivors = final_state.state().living_players();
|
|
||||||
let winner = if survivors.len() == 1 {
|
let winner = if survivors.len() == 1 {
|
||||||
Some(survivors[0])
|
Some(survivors[0])
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
MatchOutcome { winner }
|
let player_outcomes = (1..=config.players.len())
|
||||||
|
.map(|player_id| {
|
||||||
|
let player_status = &match_instance.player_status[&player_id];
|
||||||
|
PlayerOutcome {
|
||||||
|
had_errors: player_status.had_command_errors,
|
||||||
|
crashed: player_status.terminated,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
MatchOutcome {
|
||||||
|
winner,
|
||||||
|
player_outcomes,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// writing this as a closure causes lifetime inference errors
|
// writing this as a closure causes lifetime inference errors
|
||||||
|
|
|
@ -9,6 +9,7 @@ use tokio::time::Duration;
|
||||||
|
|
||||||
use serde_json;
|
use serde_json;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
pub use planetwars_rules::config::{Config, Map};
|
pub use planetwars_rules::config::{Config, Map};
|
||||||
|
@ -17,30 +18,43 @@ use planetwars_rules::protocol as proto;
|
||||||
use planetwars_rules::serializer as pw_serializer;
|
use planetwars_rules::serializer as pw_serializer;
|
||||||
use planetwars_rules::{PlanetWars, PwConfig};
|
use planetwars_rules::{PlanetWars, PwConfig};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct MatchConfig {
|
|
||||||
pub map_name: String,
|
|
||||||
pub max_turns: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PwMatch {
|
pub struct PwMatch {
|
||||||
pub match_ctx: MatchCtx,
|
pub match_ctx: MatchCtx,
|
||||||
pub match_state: PlanetWars,
|
pub match_state: PlanetWars,
|
||||||
|
pub player_status: HashMap<usize, PlayerStatus>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PlayerStatus {
|
||||||
|
pub had_command_errors: bool,
|
||||||
|
pub terminated: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PwMatch {
|
impl PwMatch {
|
||||||
pub fn create(match_ctx: MatchCtx, config: PwConfig) -> Self {
|
pub fn create(match_ctx: MatchCtx, config: PwConfig) -> Self {
|
||||||
// TODO: this is kind of hacked together at the moment
|
// TODO: this is kind of hacked together at the moment
|
||||||
let match_state = PlanetWars::create(config, match_ctx.players().len());
|
let match_state = PlanetWars::create(config, match_ctx.players().len());
|
||||||
|
let player_status = match_ctx
|
||||||
|
.players()
|
||||||
|
.into_iter()
|
||||||
|
.map(|player_id| {
|
||||||
|
(
|
||||||
|
player_id as usize,
|
||||||
|
PlayerStatus {
|
||||||
|
had_command_errors: false,
|
||||||
|
terminated: false,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
PwMatch {
|
PwMatch {
|
||||||
match_state,
|
match_state,
|
||||||
match_ctx,
|
match_ctx,
|
||||||
|
player_status,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run(mut self) -> PlanetWars {
|
pub async fn run(&mut self) {
|
||||||
// log initial state
|
// log initial state
|
||||||
self.log_game_state();
|
self.log_game_state();
|
||||||
|
|
||||||
|
@ -49,14 +63,12 @@ impl PwMatch {
|
||||||
|
|
||||||
for (player_id, turn) in player_messages {
|
for (player_id, turn) in player_messages {
|
||||||
let player_action = self.execute_action(player_id, turn);
|
let player_action = self.execute_action(player_id, turn);
|
||||||
|
self.update_player_status(player_id, &player_action);
|
||||||
self.log_player_action(player_id, player_action);
|
self.log_player_action(player_id, player_action);
|
||||||
}
|
}
|
||||||
self.match_state.step();
|
self.match_state.step();
|
||||||
self.log_game_state();
|
self.log_game_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.match_ctx.shutdown().await;
|
|
||||||
self.match_state
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn prompt_players(&mut self) -> Vec<(usize, RequestResult<Vec<u8>>)> {
|
async fn prompt_players(&mut self) -> Vec<(usize, RequestResult<Vec<u8>>)> {
|
||||||
|
@ -145,6 +157,26 @@ impl PwMatch {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn update_player_status(&mut self, player_id: usize, player_action: &PlayerAction) {
|
||||||
|
let player_status = self.player_status.get_mut(&player_id).unwrap();
|
||||||
|
match player_action {
|
||||||
|
PlayerAction::Commands(dispatches) => {
|
||||||
|
if dispatches.iter().any(|d| d.error.is_some()) {
|
||||||
|
player_status.had_command_errors = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PlayerAction::ParseError { .. } => {
|
||||||
|
player_status.had_command_errors = true;
|
||||||
|
}
|
||||||
|
PlayerAction::Timeout => {
|
||||||
|
player_status.had_command_errors = true;
|
||||||
|
}
|
||||||
|
PlayerAction::Terminated => {
|
||||||
|
player_status.terminated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
|
Loading…
Reference in a new issue