Print game state differences to log
This commit is contained in:
parent
9b0b9d5680
commit
4ad7a022dc
2 changed files with 224 additions and 21 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
||||||
/target
|
/target
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
|
*.log
|
242
src/game.rs
242
src/game.rs
|
@ -1,4 +1,6 @@
|
||||||
use std::{
|
use std::{
|
||||||
|
fs::OpenOptions,
|
||||||
|
io::Write,
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{AtomicBool, AtomicU32, Ordering::SeqCst},
|
atomic::{AtomicBool, AtomicU32, Ordering::SeqCst},
|
||||||
Arc, Mutex, MutexGuard,
|
Arc, Mutex, MutexGuard,
|
||||||
|
@ -8,7 +10,10 @@ use std::{
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use assetpath::AssetPath;
|
use assetpath::AssetPath;
|
||||||
use engine::prelude::{cgmath::vec3, *};
|
use engine::prelude::{
|
||||||
|
cgmath::{vec3, Vector2},
|
||||||
|
*,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
board::{Board, BoardSlot, BoardSlotState},
|
board::{Board, BoardSlot, BoardSlotState},
|
||||||
|
@ -49,12 +54,14 @@ pub enum MillState {
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum LogSeverity {
|
pub enum LogSeverity {
|
||||||
Basic,
|
Basic,
|
||||||
Debug,
|
Debug,
|
||||||
}
|
}
|
||||||
|
|
||||||
const LOG_SEVERITY: LogSeverity = LogSeverity::Debug;
|
const LOG_SEVERITY: LogSeverity = LogSeverity::Basic;
|
||||||
|
const LOG_FILE: &str = "millgame.log";
|
||||||
|
|
||||||
impl PlayerColor {
|
impl PlayerColor {
|
||||||
pub fn swap(&mut self) {
|
pub fn swap(&mut self) {
|
||||||
|
@ -80,6 +87,135 @@ impl PlayerColor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug)]
|
||||||
|
struct TurnState {
|
||||||
|
white_infos: Vec<(StoneState, Entity, Option<Vector2<f32>>)>,
|
||||||
|
black_infos: Vec<(StoneState, Entity, Option<Vector2<f32>>)>,
|
||||||
|
board_infos: Vec<((usize, usize, usize), Vector2<f32>, BoardSlotState)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TurnState {
|
||||||
|
pub fn new(game: &MillGame) -> Result<Self> {
|
||||||
|
let mut white_infos = Vec::new();
|
||||||
|
let mut black_infos = Vec::new();
|
||||||
|
|
||||||
|
game.scene.lock().unwrap().on_scene(|scene| {
|
||||||
|
for white_stone in game.white_stones.lock().unwrap().iter() {
|
||||||
|
let pos = match white_stone.state {
|
||||||
|
StoneState::ReadyToBePlaced => None,
|
||||||
|
StoneState::Placed => Some(
|
||||||
|
scene
|
||||||
|
.entity(white_stone.stone)?
|
||||||
|
.get_component::<Location>()?
|
||||||
|
.position()
|
||||||
|
.truncate(),
|
||||||
|
),
|
||||||
|
StoneState::Dead => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
white_infos.push((white_stone.state, white_stone.stone, pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
for black_stone in game.black_stones.lock().unwrap().iter() {
|
||||||
|
let pos = match black_stone.state {
|
||||||
|
StoneState::ReadyToBePlaced => None,
|
||||||
|
StoneState::Placed => Some(
|
||||||
|
scene
|
||||||
|
.entity(black_stone.stone)?
|
||||||
|
.get_component::<Location>()?
|
||||||
|
.position()
|
||||||
|
.truncate(),
|
||||||
|
),
|
||||||
|
StoneState::Dead => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
black_infos.push((black_stone.state, black_stone.stone, pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let board_infos: Vec<((usize, usize, usize), Vector2<f32>, BoardSlotState)> = game
|
||||||
|
.board
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.slots()
|
||||||
|
.iter()
|
||||||
|
.flatten()
|
||||||
|
.flatten()
|
||||||
|
.map(|slot| ((slot.x, slot.y, slot.z), slot.position, slot.state()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
white_infos,
|
||||||
|
black_infos,
|
||||||
|
board_infos,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn diff(&self, other: &Self) -> (Self, Self) {
|
||||||
|
let mut my_diffs = Self::default();
|
||||||
|
let mut other_diffs = Self::default();
|
||||||
|
|
||||||
|
for my_info in self.white_infos.iter() {
|
||||||
|
let other_info = other.white_infos.iter().find(|o| my_info.1 == o.1).unwrap();
|
||||||
|
|
||||||
|
if my_info.0 != other_info.0 || my_info.2 != other_info.2 {
|
||||||
|
my_diffs.white_infos.push(*my_info);
|
||||||
|
other_diffs.white_infos.push(*other_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for my_info in self.black_infos.iter() {
|
||||||
|
let other_info = other.black_infos.iter().find(|o| my_info.1 == o.1).unwrap();
|
||||||
|
|
||||||
|
if my_info.0 != other_info.0 || my_info.2 != other_info.2 {
|
||||||
|
my_diffs.black_infos.push(*my_info);
|
||||||
|
other_diffs.black_infos.push(*other_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for my_slot in self.board_infos.iter() {
|
||||||
|
let other_slot = other.board_infos.iter().find(|o| my_slot.0 == o.0).unwrap();
|
||||||
|
|
||||||
|
if my_slot.2 != other_slot.2 {
|
||||||
|
my_diffs.board_infos.push(*my_slot);
|
||||||
|
other_diffs.board_infos.push(*other_slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(my_diffs, other_diffs)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn log(&self, severity: LogSeverity) {
|
||||||
|
if !self.white_infos.is_empty() {
|
||||||
|
MillGame::log(" == WHITE STONES ==", severity);
|
||||||
|
|
||||||
|
for white_info in self.white_infos.iter() {
|
||||||
|
MillGame::log(&format!("{:?}", white_info), severity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.black_infos.is_empty() {
|
||||||
|
MillGame::log(" == BLACK STONES ==", severity);
|
||||||
|
|
||||||
|
for black_info in self.black_infos.iter() {
|
||||||
|
MillGame::log(&format!("{:?}", black_info), severity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MillGame::log(" == BOARD ==", severity);
|
||||||
|
|
||||||
|
for board_info in self.board_infos.iter() {
|
||||||
|
MillGame::log(&format!("{:?}", board_info), severity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.white_infos.is_empty() && self.black_infos.is_empty() && self.board_infos.is_empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct MillGame {
|
pub struct MillGame {
|
||||||
engine: Arc<Engine>,
|
engine: Arc<Engine>,
|
||||||
last_turn_timing: Mutex<Duration>,
|
last_turn_timing: Mutex<Duration>,
|
||||||
|
@ -98,6 +234,7 @@ pub struct MillGame {
|
||||||
mouse_y: AtomicU32,
|
mouse_y: AtomicU32,
|
||||||
|
|
||||||
turn_finished: AtomicBool,
|
turn_finished: AtomicBool,
|
||||||
|
turn_states: Mutex<Vec<TurnState>>,
|
||||||
|
|
||||||
selected_field: Mutex<Option<(usize, usize, usize)>>,
|
selected_field: Mutex<Option<(usize, usize, usize)>>,
|
||||||
|
|
||||||
|
@ -105,10 +242,10 @@ pub struct MillGame {
|
||||||
|
|
||||||
white_player_label: Arc<Label>,
|
white_player_label: Arc<Label>,
|
||||||
black_player_label: Arc<Label>,
|
black_player_label: Arc<Label>,
|
||||||
start_button: Arc<Button>,
|
_start_button: Arc<Button>,
|
||||||
grid: Arc<Grid>,
|
_grid: Arc<Grid>,
|
||||||
|
|
||||||
gui: Arc<GuiBuilder>,
|
_gui: Arc<GuiBuilder>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MillGame {
|
impl MillGame {
|
||||||
|
@ -222,17 +359,18 @@ impl MillGame {
|
||||||
mouse_y: AtomicU32::new(0),
|
mouse_y: AtomicU32::new(0),
|
||||||
|
|
||||||
turn_finished: AtomicBool::new(false),
|
turn_finished: AtomicBool::new(false),
|
||||||
|
turn_states: Mutex::default(),
|
||||||
|
|
||||||
selected_field: Mutex::default(),
|
selected_field: Mutex::default(),
|
||||||
|
|
||||||
simple_ai: SimpleAI::new(PlayerColor::White),
|
simple_ai: SimpleAI::new(PlayerColor::White),
|
||||||
|
|
||||||
grid: grid.clone(),
|
_grid: grid.clone(),
|
||||||
white_player_label,
|
white_player_label,
|
||||||
black_player_label,
|
black_player_label,
|
||||||
start_button: start_button.clone(),
|
_start_button: start_button.clone(),
|
||||||
|
|
||||||
gui,
|
_gui: gui,
|
||||||
});
|
});
|
||||||
|
|
||||||
start_button.set_callback({
|
start_button.set_callback({
|
||||||
|
@ -245,7 +383,7 @@ impl MillGame {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(me) = weak_self.upgrade() {
|
if let Some(me) = weak_self.upgrade() {
|
||||||
Self::log("start game", LogSeverity::Debug);
|
Self::log(" ===== START GAME =====", LogSeverity::Basic);
|
||||||
|
|
||||||
*me.state.lock().unwrap() = GameState::Placing;
|
*me.state.lock().unwrap() = GameState::Placing;
|
||||||
*me.current_player.lock().unwrap() = PlayerColor::Black;
|
*me.current_player.lock().unwrap() = PlayerColor::Black;
|
||||||
|
@ -271,15 +409,46 @@ impl MillGame {
|
||||||
self.turn_finished.store(true, SeqCst);
|
self.turn_finished.store(true, SeqCst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_game_state(&self, severity: LogSeverity, log_state: bool) -> Result<()> {
|
||||||
|
let current_turn_state = TurnState::new(self)?;
|
||||||
|
|
||||||
|
// verity that last turn actually something happened
|
||||||
|
debug_assert!(!current_turn_state.is_empty());
|
||||||
|
|
||||||
|
if log_state {
|
||||||
|
current_turn_state.log(severity);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut turn_states = self.turn_states.lock().unwrap();
|
||||||
|
|
||||||
|
if !turn_states.is_empty() {
|
||||||
|
let (new_diff, old_diff) = current_turn_state.diff(turn_states.last().unwrap());
|
||||||
|
|
||||||
|
Self::log(" ===== OLD DIFF =====", severity);
|
||||||
|
old_diff.log(severity);
|
||||||
|
Self::log(" ===== NEW DIFF =====", severity);
|
||||||
|
new_diff.log(severity);
|
||||||
|
}
|
||||||
|
|
||||||
|
turn_states.push(current_turn_state);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn next_game_step(&self) -> Result<()> {
|
fn next_game_step(&self) -> Result<()> {
|
||||||
{
|
{
|
||||||
let mut state = self.state.lock().unwrap();
|
let mut state = self.state.lock().unwrap();
|
||||||
|
|
||||||
Self::log(
|
Self::log(
|
||||||
&format!(" ===== NEW TURN ({:?}) =====", state),
|
&format!(
|
||||||
|
" =========================== NEW TURN ({:?}) ===========================",
|
||||||
|
state
|
||||||
|
),
|
||||||
LogSeverity::Basic,
|
LogSeverity::Basic,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
self.print_game_state(LogSeverity::Basic, false)?;
|
||||||
|
|
||||||
match *state {
|
match *state {
|
||||||
GameState::Placing => {
|
GameState::Placing => {
|
||||||
if !self
|
if !self
|
||||||
|
@ -440,7 +609,11 @@ impl MillGame {
|
||||||
match player_color {
|
match player_color {
|
||||||
PlayerColor::White => {
|
PlayerColor::White => {
|
||||||
Self::log(
|
Self::log(
|
||||||
&format!(" ==> white stone placed at {:?}", (x, y, z)),
|
&format!(
|
||||||
|
" ==> white stone ({:?}) placed at {:?}",
|
||||||
|
stone.stone,
|
||||||
|
(x, y, z)
|
||||||
|
),
|
||||||
LogSeverity::Basic,
|
LogSeverity::Basic,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -448,7 +621,11 @@ impl MillGame {
|
||||||
}
|
}
|
||||||
PlayerColor::Black => {
|
PlayerColor::Black => {
|
||||||
Self::log(
|
Self::log(
|
||||||
&format!(" ==> black stone placed at {:?}", (x, y, z)),
|
&format!(
|
||||||
|
" ==> black stone ({:?}) placed at {:?}",
|
||||||
|
stone.stone,
|
||||||
|
(x, y, z)
|
||||||
|
),
|
||||||
LogSeverity::Basic,
|
LogSeverity::Basic,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -507,7 +684,8 @@ impl MillGame {
|
||||||
BoardSlotState::Black(e) => {
|
BoardSlotState::Black(e) => {
|
||||||
Self::log(
|
Self::log(
|
||||||
&format!(
|
&format!(
|
||||||
" ==> black stone moved from {:?} to {:?}",
|
" ==> black stone ({:?}) moved from {:?} to {:?}",
|
||||||
|
e,
|
||||||
(x, y, z),
|
(x, y, z),
|
||||||
(tx, ty, tz)
|
(tx, ty, tz)
|
||||||
),
|
),
|
||||||
|
@ -519,7 +697,8 @@ impl MillGame {
|
||||||
BoardSlotState::White(e) => {
|
BoardSlotState::White(e) => {
|
||||||
Self::log(
|
Self::log(
|
||||||
&format!(
|
&format!(
|
||||||
" ==> white stone moved from {:?} to {:?}",
|
" ==> white stone ({:?}) moved from {:?} to {:?}",
|
||||||
|
e,
|
||||||
(x, y, z),
|
(x, y, z),
|
||||||
(tx, ty, tz)
|
(tx, ty, tz)
|
||||||
),
|
),
|
||||||
|
@ -556,7 +735,8 @@ impl MillGame {
|
||||||
BoardSlotState::Black(e) => {
|
BoardSlotState::Black(e) => {
|
||||||
Self::log(
|
Self::log(
|
||||||
&format!(
|
&format!(
|
||||||
" ==> white player removes black stone at {:?}",
|
" ==> white player removes black stone ({:?}) at {:?}",
|
||||||
|
e,
|
||||||
(slot.x, slot.y, slot.z)
|
(slot.x, slot.y, slot.z)
|
||||||
),
|
),
|
||||||
LogSeverity::Basic,
|
LogSeverity::Basic,
|
||||||
|
@ -567,7 +747,8 @@ impl MillGame {
|
||||||
BoardSlotState::White(e) => {
|
BoardSlotState::White(e) => {
|
||||||
Self::log(
|
Self::log(
|
||||||
&format!(
|
&format!(
|
||||||
" ==> black player removes white stone at {:?}",
|
" ==> black player removes white stone ({:?}) at {:?}",
|
||||||
|
e,
|
||||||
(slot.x, slot.y, slot.z)
|
(slot.x, slot.y, slot.z)
|
||||||
),
|
),
|
||||||
LogSeverity::Basic,
|
LogSeverity::Basic,
|
||||||
|
@ -693,10 +874,16 @@ impl MillGame {
|
||||||
|
|
||||||
pub fn log(s: &str, log_severity: LogSeverity) {
|
pub fn log(s: &str, log_severity: LogSeverity) {
|
||||||
match (LOG_SEVERITY, log_severity) {
|
match (LOG_SEVERITY, log_severity) {
|
||||||
(LogSeverity::Basic, LogSeverity::Basic) => println!("{}", s),
|
(LogSeverity::Basic, LogSeverity::Basic) => Self::write(s),
|
||||||
(LogSeverity::Basic, LogSeverity::Debug) => (),
|
(LogSeverity::Basic, LogSeverity::Debug) => (),
|
||||||
(LogSeverity::Debug, LogSeverity::Basic) => println!("{}", s),
|
(LogSeverity::Debug, LogSeverity::Basic) => Self::write(s),
|
||||||
(LogSeverity::Debug, LogSeverity::Debug) => println!("{}", s),
|
(LogSeverity::Debug, LogSeverity::Debug) => Self::write(s),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(s: &str) {
|
||||||
|
if let Ok(mut file) = OpenOptions::new().append(true).create(true).open(&LOG_FILE) {
|
||||||
|
if let Err(_) = file.write_all(format!("{}\n", s.to_string()).as_bytes()) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -842,6 +1029,11 @@ impl EngineObject for MillGame {
|
||||||
) {
|
) {
|
||||||
(BoardSlotState::Black(_), PlayerColor::Black)
|
(BoardSlotState::Black(_), PlayerColor::Black)
|
||||||
| (BoardSlotState::White(_), PlayerColor::White) => {
|
| (BoardSlotState::White(_), PlayerColor::White) => {
|
||||||
|
Self::log(
|
||||||
|
&format!("Selected ({:?})", (tx, ty, tz)),
|
||||||
|
LogSeverity::Basic,
|
||||||
|
);
|
||||||
|
|
||||||
*selected_slot = Some((tx, ty, tz));
|
*selected_slot = Some((tx, ty, tz));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -857,7 +1049,17 @@ impl EngineObject for MillGame {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MouseButton::Middle => self.camera_controls.lock().unwrap().hold(),
|
MouseButton::Middle => self.camera_controls.lock().unwrap().hold(),
|
||||||
MouseButton::Right => (),
|
MouseButton::Right => {
|
||||||
|
let mut selected_slot = self.selected_field.lock().unwrap();
|
||||||
|
|
||||||
|
if selected_slot.is_some() {
|
||||||
|
Self::log(
|
||||||
|
&format!("Released selection ({:?})", selected_slot.unwrap()),
|
||||||
|
LogSeverity::Basic,
|
||||||
|
);
|
||||||
|
*selected_slot = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
MouseButton::Forward => (),
|
MouseButton::Forward => (),
|
||||||
MouseButton::Backward => (),
|
MouseButton::Backward => (),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue