refact: client : extract game_runner

This commit is contained in:
Henri Bourcereau 2024-10-16 17:37:38 +02:00
parent c5321e6186
commit acab0b0593
6 changed files with 86 additions and 125 deletions

View file

@ -1 +1 @@
/nix/store/qp1vc91wm7s7vz337hpv6zimpc4gcvf0-pre-commit-config.json /nix/store/i4sgk0h4rjc84waf065w8xkrwvxlnhpw-pre-commit-config.json

View file

@ -1,79 +1,13 @@
use itertools::Itertools; use itertools::Itertools;
use bot::Bot; use crate::game_runner::Game;
use pretty_assertions::assert_eq; use store::{CheckerMove, GameEvent, GameState, PointsRules, Stage, TurnStage};
use store::{
CheckerMove, DiceRoller, GameEvent, GameState, PlayerId, PointsRules, Stage, TurnStage,
};
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct AppArgs { pub struct AppArgs {
pub seed: Option<u32>, pub seed: Option<u32>,
} }
// Application Game
#[derive(Debug, Default)]
pub struct Game {
pub state: GameState,
pub dice_roller: DiceRoller,
first_move: Option<CheckerMove>,
player_id: Option<PlayerId>,
bot: Bot,
}
impl Game {
// Constructs a new instance of [`App`].
pub fn new(schools_enabled: bool, seed: Option<u64>) -> Self {
let mut state = GameState::new(schools_enabled);
// local : player
let player_id: Option<PlayerId> = state.init_player("myself");
// bot
let bot_id: PlayerId = state.init_player("bot").unwrap();
let bot_color = state.player_color_by_id(&bot_id).unwrap();
let bot: Bot = Bot::new(bot_color, schools_enabled);
let mut game = Self {
state,
dice_roller: DiceRoller::new(seed),
first_move: None,
player_id,
bot,
};
game.handle_event(&GameEvent::BeginGame {
goes_first: player_id.unwrap(),
});
game
}
pub fn handle_event(&mut self, event: &GameEvent) -> Option<GameEvent> {
if !self.state.validate(event) {
return None;
}
// println!("consuming {:?}", event);
self.state.consume(event);
// chain all successive bot actions
let bot_event = self
.bot
.handle_event(event)
.and_then(|evt| self.handle_event(&evt));
// roll dice for bot if needed
if self.bot_needs_dice_roll() {
let dice = self.dice_roller.roll();
self.handle_event(&GameEvent::RollResult {
player_id: self.bot.player_id,
dice,
})
} else {
bot_event
}
}
fn bot_needs_dice_roll(&self) -> bool {
self.state.active_player_id == self.bot.player_id
&& self.state.turn_stage == TurnStage::RollWaiting
}
}
// Application. // Application.
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct App { pub struct App {
@ -256,6 +190,7 @@ impl App {
} }
} }
use pretty_assertions::assert_eq;
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View file

@ -0,0 +1,65 @@
use bot::Bot;
use store::{CheckerMove, DiceRoller, GameEvent, GameState, PlayerId, TurnStage};
// Application Game
#[derive(Debug, Default)]
pub struct Game {
pub state: GameState,
pub dice_roller: DiceRoller,
pub first_move: Option<CheckerMove>,
pub player_id: Option<PlayerId>,
bot: Bot,
}
impl Game {
// Constructs a new instance of [`App`].
pub fn new(schools_enabled: bool, seed: Option<u64>) -> Self {
let mut state = GameState::new(schools_enabled);
// local : player
let player_id: Option<PlayerId> = state.init_player("myself");
// bot
let bot_id: PlayerId = state.init_player("bot").unwrap();
let bot_color = state.player_color_by_id(&bot_id).unwrap();
let bot: Bot = Bot::new(bot_color, schools_enabled);
let mut game = Self {
state,
dice_roller: DiceRoller::new(seed),
first_move: None,
player_id,
bot,
};
game.handle_event(&GameEvent::BeginGame {
goes_first: player_id.unwrap(),
});
game
}
pub fn handle_event(&mut self, event: &GameEvent) -> Option<GameEvent> {
if !self.state.validate(event) {
return None;
}
// println!("consuming {:?}", event);
self.state.consume(event);
// chain all successive bot actions
let bot_event = self
.bot
.handle_event(event)
.and_then(|evt| self.handle_event(&evt));
// roll dice for bot if needed
if self.bot_needs_dice_roll() {
let dice = self.dice_roller.roll();
self.handle_event(&GameEvent::RollResult {
player_id: self.bot.player_id,
dice,
})
} else {
bot_event
}
}
fn bot_needs_dice_roll(&self) -> bool {
self.state.active_player_id == self.bot.player_id
&& self.state.turn_stage == TurnStage::RollWaiting
}
}

View file

@ -1,5 +1,6 @@
// Application. // Application.
pub mod app; pub mod app;
mod game_runner;
use anyhow::Result; use anyhow::Result;
use app::{App, AppArgs}; use app::{App, AppArgs};

View file

@ -3,11 +3,10 @@
"devenv": { "devenv": {
"locked": { "locked": {
"dir": "src/modules", "dir": "src/modules",
"lastModified": 1698243190, "lastModified": 1729076865,
"narHash": "sha256-n+SbyNQRhUcaZoU00d+7wi17HJpw/kAUrXOL4zRcqE8=",
"owner": "cachix", "owner": "cachix",
"repo": "devenv", "repo": "devenv",
"rev": "86f476f7edb86159fd20764489ab4e4df6edb4b6", "rev": "9803535e5d124b502165e51d9caacf38b9dbe463",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -20,11 +19,10 @@
"flake-compat": { "flake-compat": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1673956053, "lastModified": 1696426674,
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"owner": "edolstra", "owner": "edolstra",
"repo": "flake-compat", "repo": "flake-compat",
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -33,24 +31,6 @@
"type": "github" "type": "github"
} }
}, },
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1685518550,
"narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"gitignore": { "gitignore": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@ -59,11 +39,10 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1660459072, "lastModified": 1709087332,
"narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
"owner": "hercules-ci", "owner": "hercules-ci",
"repo": "gitignore.nix", "repo": "gitignore.nix",
"rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", "rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -74,11 +53,10 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1698553279, "lastModified": 1728538411,
"narHash": "sha256-T/9P8yBSLcqo/v+FTOBK+0rjzjPMctVymZydbvR/Fak=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "90e85bc7c1a6fc0760a94ace129d3a1c61c3d035", "rev": "b69de56fac8c2b6f8fd27f2eca01dcda8e0a4221",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -90,16 +68,15 @@
}, },
"nixpkgs-stable": { "nixpkgs-stable": {
"locked": { "locked": {
"lastModified": 1685801374, "lastModified": 1728909085,
"narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "c37ca420157f4abc31e26f436c1145f8951ff373", "rev": "c0b1da36f7c34a7146501f684e9ebdf15d2bebf8",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "NixOS", "owner": "NixOS",
"ref": "nixos-23.05", "ref": "nixos-24.05",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
@ -107,7 +84,6 @@
"pre-commit-hooks": { "pre-commit-hooks": {
"inputs": { "inputs": {
"flake-compat": "flake-compat", "flake-compat": "flake-compat",
"flake-utils": "flake-utils",
"gitignore": "gitignore", "gitignore": "gitignore",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
@ -115,11 +91,10 @@
"nixpkgs-stable": "nixpkgs-stable" "nixpkgs-stable": "nixpkgs-stable"
}, },
"locked": { "locked": {
"lastModified": 1698227354, "lastModified": 1728778939,
"narHash": "sha256-Fi5H9jbaQLmLw9qBi/mkR33CoFjNbobo5xWdX4tKz1Q=",
"owner": "cachix", "owner": "cachix",
"repo": "pre-commit-hooks.nix", "repo": "pre-commit-hooks.nix",
"rev": "bd38df3d508dfcdff52cd243d297f218ed2257bf", "rev": "ff68f91754be6f3427e4986d7949e6273659be1d",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -134,21 +109,6 @@
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"pre-commit-hooks": "pre-commit-hooks" "pre-commit-hooks": "pre-commit-hooks"
} }
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
} }
}, },
"root": "root", "root": "root",

View file

@ -35,6 +35,6 @@ L'encyclopédie
## rêveries ## rêveries
Trictrac : un domaine grand et complexe, un univers dans lequel on peut s'absorber. Un jeu geek parfait. Qui a la noblesse d'avoir été populaire, qui a la noblesse de règles nécessitant apprentissage et presse companionage. Trictrac : un domaine grand et complexe, un univers dans lequel on peut s'absorber. Un jeu geek parfait. Qui a la noblesse d'avoir été populaire, qui a la noblesse de règles nécessitant apprentissage et presque companionage.
Pourquoi s'investir dans ce genre d'activité ? Toucher un absolu. Sauver de la mort une pépite. Entrer dans le monde des morts comme Orphée ou Ulysse ? Pourquoi s'investir dans ce genre d'activité ? Toucher un absolu. Sauver de la mort une pépite du passé. Entrer dans le monde des morts comme Orphée ou Ulysse ?
Et maîtriser un vocabulaire, des gestes, des règles de plus en plus fine, discutées au fil des siècles. Et maîtriser un vocabulaire, des gestes, des règles affinées au fil des siècles.