Fix removing in placing state

This commit is contained in:
hodasemi 2023-05-10 10:22:46 +02:00
parent 7a41b66aa6
commit 01afc6ccf1
2 changed files with 129 additions and 88 deletions

View file

@ -10,6 +10,10 @@ use crate::{game::MillGame, objects::Objects};
#[derive(Debug, PartialEq, Clone, Copy)] #[derive(Debug, PartialEq, Clone, Copy)]
pub struct BoardSlot { pub struct BoardSlot {
pub x: usize,
pub y: usize,
pub z: usize,
pub state: BoardSlotState, pub state: BoardSlotState,
pub position: Vector2<f32>, pub position: Vector2<f32>,
pub slot_marker: Option<Entity>, pub slot_marker: Option<Entity>,
@ -18,7 +22,13 @@ pub struct BoardSlot {
impl BoardSlot { impl BoardSlot {
pub const SLOT_MARKER_SIZE: f32 = 1.5; pub const SLOT_MARKER_SIZE: f32 = 1.5;
pub fn new(position: Vector2<f32>, scene: &mut Scene) -> Result<Self> { pub fn new(
x: usize,
y: usize,
z: usize,
position: Vector2<f32>,
scene: &mut Scene,
) -> Result<Self> {
let mut marker = scene.engine().assets().empty_entity(); let mut marker = scene.engine().assets().empty_entity();
let meshes = vec![Self::create_mesh(&scene.engine(), Color::Black)?]; let meshes = vec![Self::create_mesh(&scene.engine(), Color::Black)?];
@ -31,14 +41,22 @@ impl BoardSlot {
marker.insert_component(location); marker.insert_component(location);
Ok(Self { Ok(Self {
x,
y,
z,
state: BoardSlotState::default(), state: BoardSlotState::default(),
position, position,
slot_marker: Some(scene.add_entity(marker)?), slot_marker: Some(scene.add_entity(marker)?),
}) })
} }
pub fn invalid() -> Self { pub fn invalid(x: usize, y: usize, z: usize) -> Self {
Self { Self {
x,
y,
z,
state: BoardSlotState::Invalid, state: BoardSlotState::Invalid,
position: vec2(0.0, 0.0), position: vec2(0.0, 0.0),
slot_marker: None, slot_marker: None,
@ -147,53 +165,53 @@ impl Board {
slots = Some([ slots = Some([
[ [
[ [
BoardSlot::new(vec2(-15.0, -15.0), scene)?, // 0 0 0 BoardSlot::new(0, 0, 0, vec2(-15.0, -15.0), scene)?, // 0 0 0
BoardSlot::new(vec2(-10.0, -10.0), scene)?, // 0 0 1 BoardSlot::new(0, 0, 1, vec2(-10.0, -10.0), scene)?, // 0 0 1
BoardSlot::new(vec2(-5.0, -5.0), scene)?, // 0 0 2 BoardSlot::new(0, 0, 2, vec2(-5.0, -5.0), scene)?, // 0 0 2
], ],
[ [
BoardSlot::new(vec2(-15.0, 0.0), scene)?, // 0 1 0 BoardSlot::new(0, 1, 0, vec2(-15.0, 0.0), scene)?, // 0 1 0
BoardSlot::new(vec2(-10.0, 0.0), scene)?, // 0 1 1 BoardSlot::new(0, 1, 1, vec2(-10.0, 0.0), scene)?, // 0 1 1
BoardSlot::new(vec2(-5.0, 0.0), scene)?, // 0 1 2 BoardSlot::new(0, 1, 2, vec2(-5.0, 0.0), scene)?, // 0 1 2
], ],
[ [
BoardSlot::new(vec2(-15.0, 15.0), scene)?, // 0 2 0 BoardSlot::new(0, 2, 0, vec2(-15.0, 15.0), scene)?, // 0 2 0
BoardSlot::new(vec2(-10.0, 10.0), scene)?, // 0 2 1 BoardSlot::new(0, 2, 1, vec2(-10.0, 10.0), scene)?, // 0 2 1
BoardSlot::new(vec2(-5.0, 5.0), scene)?, // 0 2 2 BoardSlot::new(0, 2, 2, vec2(-5.0, 5.0), scene)?, // 0 2 2
], ],
], ],
[ [
[ [
BoardSlot::new(vec2(0.0, -15.0), scene)?, // 1 0 0 BoardSlot::new(1, 0, 0, vec2(0.0, -15.0), scene)?, // 1 0 0
BoardSlot::new(vec2(0.0, -10.0), scene)?, // 1 0 1 BoardSlot::new(1, 0, 1, vec2(0.0, -10.0), scene)?, // 1 0 1
BoardSlot::new(vec2(0.0, -5.0), scene)?, // 1 0 2 BoardSlot::new(1, 0, 2, vec2(0.0, -5.0), scene)?, // 1 0 2
], ],
[ [
BoardSlot::invalid(), // 1 1 0 BoardSlot::invalid(1, 1, 0), // 1 1 0
BoardSlot::invalid(), // 1 1 1 BoardSlot::invalid(1, 1, 1), // 1 1 1
BoardSlot::invalid(), // 1 1 2 BoardSlot::invalid(1, 1, 2), // 1 1 2
], ],
[ [
BoardSlot::new(vec2(0.0, 15.0), scene)?, // 1 2 0 BoardSlot::new(1, 2, 0, vec2(0.0, 15.0), scene)?, // 1 2 0
BoardSlot::new(vec2(0.0, 10.0), scene)?, // 1 2 1 BoardSlot::new(1, 2, 1, vec2(0.0, 10.0), scene)?, // 1 2 1
BoardSlot::new(vec2(0.0, 5.0), scene)?, // 1 2 2 BoardSlot::new(1, 2, 2, vec2(0.0, 5.0), scene)?, // 1 2 2
], ],
], ],
[ [
[ [
BoardSlot::new(vec2(15.0, -15.0), scene)?, // 2 0 0 BoardSlot::new(2, 0, 0, vec2(15.0, -15.0), scene)?, // 2 0 0
BoardSlot::new(vec2(10.0, -10.0), scene)?, // 2 0 1 BoardSlot::new(2, 0, 1, vec2(10.0, -10.0), scene)?, // 2 0 1
BoardSlot::new(vec2(5.0, -5.0), scene)?, // 2 0 2 BoardSlot::new(2, 0, 2, vec2(5.0, -5.0), scene)?, // 2 0 2
], ],
[ [
BoardSlot::new(vec2(15.0, 0.0), scene)?, // 2 1 0 BoardSlot::new(2, 1, 0, vec2(15.0, 0.0), scene)?, // 2 1 0
BoardSlot::new(vec2(10.0, 0.0), scene)?, // 2 1 1 BoardSlot::new(2, 1, 1, vec2(10.0, 0.0), scene)?, // 2 1 1
BoardSlot::new(vec2(5.0, 0.0), scene)?, // 2 1 2 BoardSlot::new(2, 1, 2, vec2(5.0, 0.0), scene)?, // 2 1 2
], ],
[ [
BoardSlot::new(vec2(15.0, 15.0), scene)?, // 2 2 0 BoardSlot::new(2, 2, 0, vec2(15.0, 15.0), scene)?, // 2 2 0
BoardSlot::new(vec2(10.0, 10.0), scene)?, // 2 2 1 BoardSlot::new(2, 2, 1, vec2(10.0, 10.0), scene)?, // 2 2 1
BoardSlot::new(vec2(5.0, 5.0), scene)?, // 2 2 2 BoardSlot::new(2, 2, 2, vec2(5.0, 5.0), scene)?, // 2 2 2
], ],
], ],
]); ]);

View file

@ -1,5 +1,5 @@
use std::sync::{ use std::sync::{
atomic::{AtomicU32, Ordering::SeqCst}, atomic::{AtomicBool, AtomicU32, Ordering::SeqCst},
Arc, Mutex, MutexGuard, Arc, Mutex, MutexGuard,
}; };
@ -76,6 +76,8 @@ pub struct MillGame {
mouse_x: AtomicU32, mouse_x: AtomicU32,
mouse_y: AtomicU32, mouse_y: AtomicU32,
turn_finished: AtomicBool,
simple_ai: SimpleAI, simple_ai: SimpleAI,
white_player_label: Arc<Label>, white_player_label: Arc<Label>,
@ -192,6 +194,8 @@ impl MillGame {
mouse_x: AtomicU32::new(0), mouse_x: AtomicU32::new(0),
mouse_y: AtomicU32::new(0), mouse_y: AtomicU32::new(0),
turn_finished: AtomicBool::new(false),
simple_ai: SimpleAI::new(PlayerColor::White), simple_ai: SimpleAI::new(PlayerColor::White),
grid: grid.clone(), grid: grid.clone(),
@ -217,7 +221,7 @@ impl MillGame {
*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;
me.next_game_step()?; me.turn_finished.store(true, SeqCst);
} }
Ok(()) Ok(())
@ -227,6 +231,15 @@ impl MillGame {
Ok(me) Ok(me)
} }
pub fn finish_turn(&self) {
Self::log(&format!(
"{:?} finised turn",
*self.current_player.lock().unwrap()
));
self.turn_finished.store(true, SeqCst);
}
fn next_game_step(&self) -> Result<()> { fn next_game_step(&self) -> Result<()> {
Self::log("next_game_step"); Self::log("next_game_step");
@ -254,12 +267,7 @@ impl MillGame {
*state = GameState::Main; *state = GameState::Main;
} }
if self.check_for_mill() != MillState::None { self.current_player.lock().unwrap().swap();
Self::log("change state to Removing");
*state = GameState::Removing;
} else {
self.current_player.lock().unwrap().swap();
}
} }
GameState::Removing => { GameState::Removing => {
if !self if !self
@ -285,12 +293,7 @@ impl MillGame {
self.current_player.lock().unwrap().swap(); self.current_player.lock().unwrap().swap();
} }
GameState::Main => { GameState::Main => {
if self.check_for_mill() != MillState::None { self.current_player.lock().unwrap().swap();
Self::log("change state to Removing");
*state = GameState::Removing;
} else {
self.current_player.lock().unwrap().swap();
}
} }
} }
} }
@ -322,9 +325,11 @@ impl MillGame {
*self.state.lock().unwrap(), *self.state.lock().unwrap(),
)?; )?;
self.next_game_step()?; self.finish_turn();
} }
Self::log("leave next_game_step");
Ok(()) Ok(())
} }
@ -454,46 +459,43 @@ impl MillGame {
MillState::None MillState::None
} }
pub fn check_for_mill(&self) -> MillState { pub fn check_for_mill(&self, slot: &BoardSlot, board: &[[[BoardSlot; 3]; 3]; 3]) -> MillState {
Self::log("check for mill"); Self::log("check for mill");
let mut board = self.board.lock().unwrap(); let state = Self::check_mill(
let slots = board.slots(); &board[slot.x][slot.y][0],
&board[slot.x][slot.y][1],
&board[slot.x][slot.y][2],
);
for x in 0..3 { if state != MillState::None {
for y in 0..3 { Self::log(&format!("mill found {:?}", state));
let state = Self::check_mill(&slots[x][y][0], &slots[x][y][1], &slots[x][y][2]);
if state != MillState::None { return state;
Self::log(&format!("mill found {:?}", state));
return state;
}
}
} }
for x in 0..3 { let state = Self::check_mill(
for z in 0..3 { &board[slot.x][0][slot.z],
let state = Self::check_mill(&slots[x][0][z], &slots[x][1][z], &slots[x][2][z]); &board[slot.x][1][slot.z],
&board[slot.x][2][slot.z],
);
if state != MillState::None { if state != MillState::None {
Self::log(&format!("mill found {:?}", state)); Self::log(&format!("mill found {:?}", state));
return state; return state;
}
}
} }
for y in 0..3 { let state = Self::check_mill(
for z in 0..3 { &board[0][slot.y][slot.z],
let state = Self::check_mill(&slots[0][y][z], &slots[1][y][z], &slots[2][y][z]); &board[1][slot.y][slot.z],
&board[2][slot.y][slot.z],
);
if state != MillState::None { if state != MillState::None {
Self::log(&format!("mill found {:?}", state)); Self::log(&format!("mill found {:?}", state));
return state; return state;
}
}
} }
MillState::None MillState::None
@ -501,7 +503,12 @@ impl MillGame {
fn check_mouse_click<F>(&self, f: F) -> Result<()> fn check_mouse_click<F>(&self, f: F) -> Result<()>
where where
F: FnOnce(&Self, &mut BoardSlot, &mut Scene) -> Result<()>, F: FnOnce(
&Self,
(usize, usize, usize),
&mut [[[BoardSlot; 3]; 3]; 3],
&mut Scene,
) -> Result<()>,
{ {
Self::log("check_mouse_click"); Self::log("check_mouse_click");
@ -509,15 +516,12 @@ impl MillGame {
if let Some(world_space) = if let Some(world_space) =
scene.screen_space_to_world(self.mouse_x.load(SeqCst), self.mouse_y.load(SeqCst))? scene.screen_space_to_world(self.mouse_x.load(SeqCst), self.mouse_y.load(SeqCst))?
{ {
if let Some(slot) = self let mut board = self.board.lock().unwrap();
.board
.lock() if let Some(slot) = board.close_to_marker(world_space.truncate()) {
.unwrap()
.close_to_marker(world_space.truncate())
{
Self::log("click is close to marker"); Self::log("click is close to marker");
f(self, slot, scene)?; f(self, (slot.x, slot.y, slot.z), board.slots(), scene)?;
} }
} }
@ -536,6 +540,11 @@ impl EngineObject for MillGame {
} }
fn update(&self) -> Result<()> { fn update(&self) -> Result<()> {
if self.turn_finished.load(SeqCst) {
self.turn_finished.store(false, SeqCst);
self.next_game_step()?;
}
Ok(()) Ok(())
} }
@ -553,14 +562,15 @@ impl EngineObject for MillGame {
} }
EngineEvent::MouseButtonDown(button) => match button { EngineEvent::MouseButtonDown(button) => match button {
MouseButton::Left => { MouseButton::Left => {
let state = *self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();
Self::log(&format!("User click at state {:?}", state)); Self::log(&format!("User click at state {:?}", state));
match state { match *state {
GameState::Placing => { GameState::Placing => {
let mut placed = false; let mut placed = false;
let mut mill_found = false;
self.check_mouse_click(|me, slot, scene| { self.check_mouse_click(|me, (x, y, z), board, scene| {
let current_player = *self.current_player.lock().unwrap(); let current_player = *self.current_player.lock().unwrap();
if let Some(placable) = self if let Some(placable) = self
@ -568,7 +578,18 @@ impl EngineObject for MillGame {
.iter_mut() .iter_mut()
.find(|stone| stone.state == StoneState::ReadyToBePlaced) .find(|stone| stone.state == StoneState::ReadyToBePlaced)
{ {
Self::place_stone(placable, slot, current_player, scene)?; Self::place_stone(
placable,
&mut board[x][y][z],
current_player,
scene,
)?;
if me.check_for_mill(&board[x][y][z], board) != MillState::None
{
mill_found = true;
*state = GameState::Removing;
}
placed = true; placed = true;
} }
@ -576,14 +597,16 @@ impl EngineObject for MillGame {
Ok(()) Ok(())
})?; })?;
if placed { if placed && !mill_found {
self.next_game_step()?; self.finish_turn();
} }
} }
GameState::Removing => { GameState::Removing => {
let mut removed = false; let mut removed = false;
self.check_mouse_click(|me, slot, scene| { self.check_mouse_click(|me, (x, y, z), board, scene| {
let slot = &mut board[x][y][z];
Self::log(&format!( Self::log(&format!(
"state {:?} - player {:?}", "state {:?} - player {:?}",
slot.state, slot.state,
@ -603,7 +626,7 @@ impl EngineObject for MillGame {
})?; })?;
if removed { if removed {
self.next_game_step()?; self.finish_turn();
} }
} }
GameState::Main => todo!(), GameState::Main => todo!(),