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)
}
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)]

View file

@ -1,6 +1,6 @@
use std::sync::{
atomic::{AtomicU32, Ordering::SeqCst},
Arc, Mutex,
Arc, Mutex, MutexGuard,
};
use anyhow::Result;
@ -28,6 +28,7 @@ pub struct Stone {
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub enum GameState {
Placing,
Removing,
Main,
}
@ -37,11 +38,26 @@ pub enum PlayerColor {
Black,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub enum MillState {
White,
Black,
None,
}
impl PlayerColor {
pub fn swap(&mut self) {
*self = match *self {
PlayerColor::White => PlayerColor::Black,
PlayerColor::Black => PlayerColor::White,
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() {
Self::log("start game");
*me.state.lock().unwrap() = GameState::Placing;
*me.current_player.lock().unwrap() = PlayerColor::White;
*me.current_player.lock().unwrap() = PlayerColor::Black;
me.next_game_step()?;
}
@ -210,22 +228,13 @@ impl MillGame {
}
fn next_game_step(&self) -> Result<()> {
match *self.current_player.lock().unwrap() {
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)?;
}
}
Self::log("next_game_step");
{
let mut state = self.state.lock().unwrap();
Self::log(&format!("\tstate: {:?}", state));
match *state {
GameState::Placing => {
if !self
@ -241,34 +250,91 @@ impl MillGame {
.iter()
.any(|stones| stones.state == StoneState::ReadyToBePlaced)
{
Self::log("change state to Main");
*state = GameState::Main;
}
}
GameState::Main => {}
}
}
if *self.current_player.lock().unwrap() == self.simple_ai.player_color {
match self.simple_ai.player_color {
PlayerColor::White => self.simple_ai.step(
&mut *self.white_stones.lock().unwrap(),
self.board.lock().unwrap().slots(),
&mut *self.scene.lock().unwrap(),
)?,
PlayerColor::Black => self.simple_ai.step(
&mut *self.black_stones.lock().unwrap(),
self.board.lock().unwrap().slots(),
&mut *self.scene.lock().unwrap(),
)?,
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();
}
}
}
}
let player = *self.current_player.lock().unwrap();
Self::log(&format!("current player {:?}", player));
match player {
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)?;
}
}
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.next_game_step()?;
}
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]> {
Ok((0..9)
.map(|_| Self::init_stone(engine, color))
@ -327,9 +393,19 @@ impl MillGame {
player_color: PlayerColor,
scene: &mut Scene,
) -> Result<()> {
Self::log("place_stone");
match player_color {
PlayerColor::White => slot.state = BoardSlotState::White(stone.stone),
PlayerColor::Black => slot.state = BoardSlotState::Black(stone.stone),
PlayerColor::White => {
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;
@ -342,16 +418,115 @@ impl MillGame {
Ok(())
}
pub fn check_for_mill(&self) -> Result<bool> {
let slots = self.board.lock().unwrap().slots();
pub fn remove_stone(slot: &mut BoardSlot, scene: &mut Scene) -> Result<()> {
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 y 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,41 +553,62 @@ impl EngineObject for MillGame {
}
EngineEvent::MouseButtonDown(button) => match button {
MouseButton::Left => {
let state = *self.state.lock().unwrap();
Self::log(&format!("User click at state {:?}", state));
match state {
GameState::Placing => {
let mut placed = false;
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.check_mouse_click(|me, slot, scene| {
let current_player = *self.current_player.lock().unwrap();
if let Some(placable) = self
.black_stones
.lock()
.unwrap()
.stones(current_player)
.iter_mut()
.find(|stone| stone.state == StoneState::ReadyToBePlaced)
{
Self::place_stone(placable, slot, PlayerColor::Black, scene)?;
Self::place_stone(placable, slot, current_player, scene)?;
placed = true;
}
}
}
Ok(())
})?;
if placed {
self.current_player.lock().unwrap().swap();
self.next_game_step()?;
}
}
GameState::Removing => {
let mut removed = false;
self.check_mouse_click(|me, slot, scene| {
Self::log(&format!(
"state {:?} - player {:?}",
slot.state,
*self.current_player.lock().unwrap()
));
if match (slot.state, *self.current_player.lock().unwrap()) {
(BoardSlotState::Black(_), PlayerColor::White) => true,
(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::Right => (),
MouseButton::Forward => (),

View file

@ -1,6 +1,6 @@
use crate::{
board::{BoardSlot, BoardSlotState},
game::{MillGame, PlayerColor, Stone, StoneState},
game::{GameState, MillGame, PlayerColor, Stone, StoneState},
};
use anyhow::Result;
@ -20,7 +20,12 @@ impl SimpleAI {
stones: &mut [Stone; 9],
board: &mut [[[BoardSlot; 3]; 3]; 3],
scene: &mut SceneHandle,
state: GameState,
) -> Result<()> {
MillGame::log(&format!("AI at state {:?}", state));
match state {
GameState::Placing => {
if let Some(placable) = stones
.iter_mut()
.find(|stone| stone.state == StoneState::ReadyToBePlaced)
@ -42,6 +47,33 @@ impl SimpleAI {
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(())
}