Start removing state

This commit is contained in:
hodasemi 2023-05-10 07:47:10 +02:00
parent 686dae95bf
commit 7a41b66aa6
3 changed files with 321 additions and 75 deletions

View file

@ -81,6 +81,24 @@ impl BoardSlot {
Ok(mesh) Ok(mesh)
} }
pub fn valid(&self) -> bool {
self.state != BoardSlotState::Invalid
}
pub fn white(&self) -> bool {
match self.state {
BoardSlotState::White(_) => true,
_ => false,
}
}
pub fn black(&self) -> bool {
match self.state {
BoardSlotState::Black(_) => true,
_ => false,
}
}
} }
#[derive(Debug, PartialEq, Eq, Clone, Copy)] #[derive(Debug, PartialEq, Eq, Clone, Copy)]

View file

@ -1,6 +1,6 @@
use std::sync::{ use std::sync::{
atomic::{AtomicU32, Ordering::SeqCst}, atomic::{AtomicU32, Ordering::SeqCst},
Arc, Mutex, Arc, Mutex, MutexGuard,
}; };
use anyhow::Result; use anyhow::Result;
@ -28,6 +28,7 @@ pub struct Stone {
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub enum GameState { pub enum GameState {
Placing, Placing,
Removing,
Main, Main,
} }
@ -37,11 +38,26 @@ pub enum PlayerColor {
Black, Black,
} }
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub enum MillState {
White,
Black,
None,
}
impl PlayerColor { impl PlayerColor {
pub fn swap(&mut self) { pub fn swap(&mut self) {
*self = match *self { *self = match *self {
PlayerColor::White => PlayerColor::Black, PlayerColor::White => {
PlayerColor::Black => PlayerColor::White, MillGame::log("swapped to black player");
PlayerColor::Black
}
PlayerColor::Black => {
MillGame::log("swapped to white player");
PlayerColor::White
}
} }
} }
} }
@ -196,8 +212,10 @@ impl MillGame {
} }
if let Some(me) = weak_self.upgrade() { if let Some(me) = weak_self.upgrade() {
Self::log("start game");
*me.state.lock().unwrap() = GameState::Placing; *me.state.lock().unwrap() = GameState::Placing;
*me.current_player.lock().unwrap() = PlayerColor::White; *me.current_player.lock().unwrap() = PlayerColor::Black;
me.next_game_step()?; me.next_game_step()?;
} }
@ -210,22 +228,13 @@ impl MillGame {
} }
fn next_game_step(&self) -> Result<()> { fn next_game_step(&self) -> Result<()> {
match *self.current_player.lock().unwrap() { Self::log("next_game_step");
PlayerColor::White => {
self.black_player_label
.set_background(Color::try_from("#9b9292")?)?;
self.white_player_label.set_background(Color::Yellow)?;
}
PlayerColor::Black => {
self.white_player_label
.set_background(Color::try_from("#9b9292")?)?;
self.black_player_label.set_background(Color::Yellow)?;
}
}
{ {
let mut state = self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();
Self::log(&format!("\tstate: {:?}", state));
match *state { match *state {
GameState::Placing => { GameState::Placing => {
if !self if !self
@ -241,34 +250,91 @@ impl MillGame {
.iter() .iter()
.any(|stones| stones.state == StoneState::ReadyToBePlaced) .any(|stones| stones.state == StoneState::ReadyToBePlaced)
{ {
Self::log("change state to Main");
*state = GameState::Main; *state = GameState::Main;
} }
if self.check_for_mill() != MillState::None {
Self::log("change state to Removing");
*state = GameState::Removing;
} else {
self.current_player.lock().unwrap().swap();
}
}
GameState::Removing => {
if !self
.black_stones
.lock()
.unwrap()
.iter()
.any(|stones| stones.state == StoneState::ReadyToBePlaced)
&& !self
.white_stones
.lock()
.unwrap()
.iter()
.any(|stones| stones.state == StoneState::ReadyToBePlaced)
{
Self::log("change state to Main");
*state = GameState::Main;
} else {
Self::log("change state to Placing");
*state = GameState::Placing;
}
self.current_player.lock().unwrap().swap();
}
GameState::Main => {
if self.check_for_mill() != MillState::None {
Self::log("change state to Removing");
*state = GameState::Removing;
} else {
self.current_player.lock().unwrap().swap();
}
} }
GameState::Main => {}
} }
} }
if *self.current_player.lock().unwrap() == self.simple_ai.player_color { let player = *self.current_player.lock().unwrap();
match self.simple_ai.player_color {
PlayerColor::White => self.simple_ai.step( Self::log(&format!("current player {:?}", player));
&mut *self.white_stones.lock().unwrap(),
self.board.lock().unwrap().slots(), match player {
&mut *self.scene.lock().unwrap(), PlayerColor::White => {
)?, self.black_player_label
PlayerColor::Black => self.simple_ai.step( .set_background(Color::try_from("#9b9292")?)?;
&mut *self.black_stones.lock().unwrap(), self.white_player_label.set_background(Color::Yellow)?;
self.board.lock().unwrap().slots(), }
&mut *self.scene.lock().unwrap(), PlayerColor::Black => {
)?, self.white_player_label
} .set_background(Color::try_from("#9b9292")?)?;
self.black_player_label.set_background(Color::Yellow)?;
}
}
if player == self.simple_ai.player_color {
Self::log("current player is AI");
self.simple_ai.step(
&mut self.stones(self.simple_ai.player_color),
self.board.lock().unwrap().slots(),
&mut *self.scene.lock().unwrap(),
*self.state.lock().unwrap(),
)?;
self.current_player.lock().unwrap().swap();
self.next_game_step()?; self.next_game_step()?;
} }
Ok(()) Ok(())
} }
fn stones(&self, player_color: PlayerColor) -> MutexGuard<'_, [Stone; 9]> {
match player_color {
PlayerColor::White => self.white_stones.lock().unwrap(),
PlayerColor::Black => self.black_stones.lock().unwrap(),
}
}
fn init_nine_stones(engine: &Arc<Engine>, color: Color) -> Result<[EntityObject; 9]> { fn init_nine_stones(engine: &Arc<Engine>, color: Color) -> Result<[EntityObject; 9]> {
Ok((0..9) Ok((0..9)
.map(|_| Self::init_stone(engine, color)) .map(|_| Self::init_stone(engine, color))
@ -327,9 +393,19 @@ impl MillGame {
player_color: PlayerColor, player_color: PlayerColor,
scene: &mut Scene, scene: &mut Scene,
) -> Result<()> { ) -> Result<()> {
Self::log("place_stone");
match player_color { match player_color {
PlayerColor::White => slot.state = BoardSlotState::White(stone.stone), PlayerColor::White => {
PlayerColor::Black => slot.state = BoardSlotState::Black(stone.stone), Self::log(&format!("place white stone"));
slot.state = BoardSlotState::White(stone.stone);
}
PlayerColor::Black => {
Self::log(&format!("place black stone"));
slot.state = BoardSlotState::Black(stone.stone);
}
} }
stone.state = StoneState::Placed; stone.state = StoneState::Placed;
@ -342,16 +418,115 @@ impl MillGame {
Ok(()) Ok(())
} }
pub fn check_for_mill(&self) -> Result<bool> { pub fn remove_stone(slot: &mut BoardSlot, scene: &mut Scene) -> Result<()> {
let slots = self.board.lock().unwrap().slots(); Self::log("remove_stone");
let entity = match slot.state {
BoardSlotState::Black(e) => {
Self::log(&format!("\tremove black stone"));
e
}
BoardSlotState::White(e) => {
Self::log(&format!("\tremove white stone"));
e
}
_ => unreachable!(),
};
scene.remove_entity(entity)?;
slot.state = BoardSlotState::Empty;
Ok(())
}
fn check_mill(s1: &BoardSlot, s2: &BoardSlot, s3: &BoardSlot) -> MillState {
if s1.valid() && s2.valid() && s3.valid() {
if s1.white() && s2.white() && s3.white() {
return MillState::White;
} else if s1.black() && s2.black() && s3.black() {
return MillState::Black;
}
}
MillState::None
}
pub fn check_for_mill(&self) -> MillState {
Self::log("check for mill");
let mut board = self.board.lock().unwrap();
let slots = board.slots();
for x in 0..3 { for x in 0..3 {
for y in 0..3 { for y in 0..3 {
for z in 0..3 { let state = Self::check_mill(&slots[x][y][0], &slots[x][y][1], &slots[x][y][2]);
//
if state != MillState::None {
Self::log(&format!("mill found {:?}", state));
return state;
} }
} }
} }
for x in 0..3 {
for z in 0..3 {
let state = Self::check_mill(&slots[x][0][z], &slots[x][1][z], &slots[x][2][z]);
if state != MillState::None {
Self::log(&format!("mill found {:?}", state));
return state;
}
}
}
for y in 0..3 {
for z in 0..3 {
let state = Self::check_mill(&slots[0][y][z], &slots[1][y][z], &slots[2][y][z]);
if state != MillState::None {
Self::log(&format!("mill found {:?}", state));
return state;
}
}
}
MillState::None
}
fn check_mouse_click<F>(&self, f: F) -> Result<()>
where
F: FnOnce(&Self, &mut BoardSlot, &mut Scene) -> Result<()>,
{
Self::log("check_mouse_click");
self.scene.lock().unwrap().on_scene(|scene| {
if let Some(world_space) =
scene.screen_space_to_world(self.mouse_x.load(SeqCst), self.mouse_y.load(SeqCst))?
{
if let Some(slot) = self
.board
.lock()
.unwrap()
.close_to_marker(world_space.truncate())
{
Self::log("click is close to marker");
f(self, slot, scene)?;
}
}
Ok(())
})
}
pub fn log(s: &str) {
println!("{}", s);
} }
} }
@ -378,39 +553,60 @@ impl EngineObject for MillGame {
} }
EngineEvent::MouseButtonDown(button) => match button { EngineEvent::MouseButtonDown(button) => match button {
MouseButton::Left => { MouseButton::Left => {
let mut placed = false; let state = *self.state.lock().unwrap();
Self::log(&format!("User click at state {:?}", state));
match state {
GameState::Placing => {
let mut placed = false;
self.check_mouse_click(|me, slot, scene| {
let current_player = *self.current_player.lock().unwrap();
self.scene.lock().unwrap().on_scene(|scene| {
if let Some(world_space) = scene.screen_space_to_world(
self.mouse_x.load(SeqCst),
self.mouse_y.load(SeqCst),
)? {
if let Some(slot) = self
.board
.lock()
.unwrap()
.close_to_marker(world_space.truncate())
{
if let Some(placable) = self if let Some(placable) = self
.black_stones .stones(current_player)
.lock()
.unwrap()
.iter_mut() .iter_mut()
.find(|stone| stone.state == StoneState::ReadyToBePlaced) .find(|stone| stone.state == StoneState::ReadyToBePlaced)
{ {
Self::place_stone(placable, slot, PlayerColor::Black, scene)?; Self::place_stone(placable, slot, current_player, scene)?;
placed = true; placed = true;
} }
Ok(())
})?;
if placed {
self.next_game_step()?;
} }
} }
GameState::Removing => {
let mut removed = false;
Ok(()) self.check_mouse_click(|me, slot, scene| {
})?; Self::log(&format!(
"state {:?} - player {:?}",
slot.state,
*self.current_player.lock().unwrap()
));
if placed { if match (slot.state, *self.current_player.lock().unwrap()) {
self.current_player.lock().unwrap().swap(); (BoardSlotState::Black(_), PlayerColor::White) => true,
self.next_game_step()?; (BoardSlotState::White(_), PlayerColor::Black) => true,
_ => false,
} {
removed = true;
Self::remove_stone(slot, scene)?;
}
Ok(())
})?;
if removed {
self.next_game_step()?;
}
}
GameState::Main => todo!(),
} }
} }
MouseButton::Middle => self.camera_controls.lock().unwrap().hold(), MouseButton::Middle => self.camera_controls.lock().unwrap().hold(),

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
board::{BoardSlot, BoardSlotState}, board::{BoardSlot, BoardSlotState},
game::{MillGame, PlayerColor, Stone, StoneState}, game::{GameState, MillGame, PlayerColor, Stone, StoneState},
}; };
use anyhow::Result; use anyhow::Result;
@ -20,29 +20,61 @@ impl SimpleAI {
stones: &mut [Stone; 9], stones: &mut [Stone; 9],
board: &mut [[[BoardSlot; 3]; 3]; 3], board: &mut [[[BoardSlot; 3]; 3]; 3],
scene: &mut SceneHandle, scene: &mut SceneHandle,
state: GameState,
) -> Result<()> { ) -> Result<()> {
if let Some(placable) = stones MillGame::log(&format!("AI at state {:?}", state));
.iter_mut()
.find(|stone| stone.state == StoneState::ReadyToBePlaced)
{
let mut free_slots: Vec<&mut BoardSlot> = board
.iter_mut()
.flatten()
.flatten()
.filter(|slot| slot.state == BoardSlotState::Empty)
.collect();
let len = free_slots.len(); match state {
GameState::Placing => {
if let Some(placable) = stones
.iter_mut()
.find(|stone| stone.state == StoneState::ReadyToBePlaced)
{
let mut free_slots: Vec<&mut BoardSlot> = board
.iter_mut()
.flatten()
.flatten()
.filter(|slot| slot.state == BoardSlotState::Empty)
.collect();
let slot = &mut free_slots[Random::range(0, len as u32) as usize]; let len = free_slots.len();
scene.on_scene(|scene| { let slot = &mut free_slots[Random::range(0, len as u32) as usize];
MillGame::place_stone(placable, slot, self.player_color, scene)?;
Ok(()) scene.on_scene(|scene| {
})?; MillGame::place_stone(placable, slot, self.player_color, scene)?;
Ok(())
})?;
}
}
GameState::Removing => {
let mut other_color: Vec<&mut BoardSlot> = board
.iter_mut()
.flatten()
.flatten()
.filter(|slot| match (slot.state, self.player_color) {
(BoardSlotState::Black(_), PlayerColor::White) => true,
(BoardSlotState::White(_), PlayerColor::Black) => true,
_ => false,
})
.collect();
let len = other_color.len();
let slot = &mut other_color[Random::range(0, len as u32) as usize];
scene.on_scene(|scene| {
MillGame::remove_stone(slot, scene)?;
Ok(())
})?;
}
GameState::Main => todo!(),
} }
MillGame::log("finish AI");
Ok(()) Ok(())
} }
} }