Continue fixing (finish)

This commit is contained in:
Michael Huebner 2025-03-25 14:59:44 +01:00
parent fabcff5a65
commit 50cc8c2cfe
4 changed files with 106 additions and 131 deletions

View file

@ -16,7 +16,7 @@ pub struct BoardSlot {
state: BoardSlotState,
pub position: Vector2<f32>,
pub slot_marker: Option<Entity>,
pub _slot_marker: Option<Entity>,
}
impl BoardSlot {
@ -40,9 +40,8 @@ impl BoardSlot {
let draw = Draw::new(meshes);
marker.insert_component(draw);
let mut location = Location::from_entity(&mut marker);
let location = Location::new_and_setup(&mut marker)?;
location.set_position(position.extend(MillGame::OFFSET_TO_BOARD));
marker.insert_component(location);
Ok(Self {
x,
@ -51,7 +50,7 @@ impl BoardSlot {
state: BoardSlotState::default(),
position,
slot_marker: Some(world.add_entity(marker)?),
_slot_marker: Some(world.add_entity(marker)?),
})
}
@ -63,7 +62,7 @@ impl BoardSlot {
state: BoardSlotState::Invalid,
position: vec2(0.0, 0.0),
slot_marker: None,
_slot_marker: None,
}
}
@ -169,9 +168,7 @@ impl Board {
let draw = Draw::new(meshes);
board_entity.insert_component(draw);
let location = Location::from_entity(&mut board_entity);
board_entity.insert_component(location);
Location::new_and_setup(&mut board_entity)?;
let board = world.add_entity(board_entity)?;
@ -234,14 +231,14 @@ impl Board {
let white_start_slots = (16..=16)
.step_by(4)
.map(|x| vec2(x as f32, distance))
.collect()
.collect::<Vec<_>>()
.try_into()
.unwrap();
let black_start_slots = (16..=16)
.step_by(4)
.map(|x| vec2(x as f32, -distance))
.collect()
.collect::<Vec<_>>()
.try_into()
.unwrap();
@ -546,9 +543,8 @@ impl Board {
}]);
lines.insert_component(draw);
let mut location = Location::from_entity(&mut lines);
let location = Location::new_and_setup(&mut lines)?;
location.set_offset(vec3(0.0, 0.0, MillGame::OFFSET_TO_BOARD));
lines.insert_component(location);
entities.push(world.add_entity(lines)?);

View file

@ -325,8 +325,7 @@ impl MillGame {
me.state = GameState::Placing;
me.current_player = PlayerColor::Black;
me.finish_turn(world);
me.last_turn_timing = now;
me.finish_turn(now);
Ok(())
}
@ -365,13 +364,13 @@ impl MillGame {
Ok(())
}
pub fn finish_turn(&mut self, world: &World) {
pub fn finish_turn(&mut self, now: Duration) {
Self::log(
&format!("{:?} finished turn", self.current_player),
LogSeverity::Debug,
);
self.last_turn_timing = world.now();
self.last_turn_timing = now;
self.turn_finished = true;
self.selected_field = None;
}
@ -406,7 +405,7 @@ impl MillGame {
Ok(())
}
fn next_game_step(&mut self, world: &World) -> Result<()> {
fn next_game_step(&mut self, world: &mut World) -> Result<()> {
Self::log(
&format!(
" =========================== NEW TURN ({:?}) ===========================",
@ -492,7 +491,7 @@ impl MillGame {
LogSeverity::Debug,
);
let mut resources = world.resources.multi_mut();
let mut resources = unsafe { remove_life_time_mut(world) }.resources.multi_mut();
let gui_handler = resources.get::<GuiHandler>();
let simple_ai = resources.get::<SimpleAI>();
@ -515,13 +514,13 @@ impl MillGame {
Self::log("current player is AI", LogSeverity::Debug);
simple_ai.step(
&mut self.stones(simple_ai.player_color),
self.board.slots_mut(),
&mut *self.scene.lock().unwrap(),
unsafe { remove_life_time_mut(self.stones_mut(simple_ai.player_color)) },
unsafe { remove_life_time_mut(self.board.slots_mut()) },
world,
&mut self.state,
)?;
self.finish_turn(world);
self.finish_turn(world.now());
}
Self::log("leave next_game_step", LogSeverity::Debug);
@ -529,10 +528,10 @@ impl MillGame {
Ok(())
}
fn stones(&self, player_color: PlayerColor) -> &[Stone; 9] {
fn stones_mut(&mut self, player_color: PlayerColor) -> &mut [Stone; 9] {
match player_color {
PlayerColor::White => &self.white_stones,
PlayerColor::Black => &self.black_stones,
PlayerColor::White => &mut self.white_stones,
PlayerColor::Black => &mut self.black_stones,
}
}
@ -586,8 +585,7 @@ impl MillGame {
}]);
marker.insert_component(draw);
let location = Location::from_entity(&mut marker);
marker.insert_component(location);
Location::new_and_setup(&mut marker)?;
Ok(marker)
}
@ -664,7 +662,7 @@ impl MillGame {
LogSeverity::Debug,
);
let slot = &mut board[x][y][z];
let slot = unsafe { remove_life_time_mut(&mut board[x][y][z]) };
let neighbour = &mut board[tx][ty][tz];
if neighbour.state() != BoardSlotState::Empty
@ -829,15 +827,20 @@ impl MillGame {
fn check_mouse_click<F>(&mut self, scene: &Scene, f: F) -> Result<()>
where
F: FnOnce(&Self, (usize, usize, usize), &mut [[[BoardSlot; 3]; 3]; 3]) -> Result<()>,
F: FnOnce(&mut Self, (usize, usize, usize), &mut [[[BoardSlot; 3]; 3]; 3]) -> Result<()>,
{
Self::log("check_mouse_click", LogSeverity::Debug);
if let Some(world_space) = scene.screen_space_to_world(self.mouse_x, self.mouse_y)? {
if let Some(slot) = self.board.close_to_marker(world_space.truncate()) {
if let Some(slot) = unsafe { remove_life_time(self) }
.board
.close_to_marker(world_space.truncate())
{
Self::log("click is close to marker", LogSeverity::Debug);
f(self, (slot.x, slot.y, slot.z), self.board.slots_mut())?;
let slots = unsafe { remove_life_time_mut(self.board.slots_mut()) };
f(self, (slot.x, slot.y, slot.z), slots)?;
}
}
@ -886,7 +889,7 @@ impl MillGame {
pub fn update(world: &mut World) -> Result<bool> {
let now = world.now();
let me = world.resources.get_mut::<Self>();
let me = world.resources.get_mut_unchecked::<Self>();
if me.turn_finished {
if (me.last_turn_timing + Self::TURN_WAIT_TIME) < now {
@ -921,15 +924,14 @@ impl EventConsumer for MillGame {
match self.state {
GameState::Placing => {
let mut resources = world.resources.multi_mut();
self.check_mouse_click(
resources.get::<Scene>(),
world.resources.get_unchecked::<Scene>(),
|me, (x, y, z), board| {
if let Some(placable) = me
.stones(me.current_player)
.iter_mut()
.find(|stone| stone.state == StoneState::ReadyToBePlaced)
if let Some(placable) = unsafe {
remove_life_time_mut(me.stones_mut(me.current_player))
}
.iter_mut()
.find(|stone| stone.state == StoneState::ReadyToBePlaced)
{
if board[x][y][z].is_empty() {
if Self::place_stone(
@ -938,10 +940,10 @@ impl EventConsumer for MillGame {
board,
me.current_player,
world,
&mut self.state,
&mut me.state,
)? == MillState::None
{
me.finish_turn(world);
me.finish_turn(world.now());
}
} else {
Self::log(
@ -960,10 +962,8 @@ impl EventConsumer for MillGame {
)?;
}
GameState::Removing => {
let mut resources = world.resources.multi_mut();
self.check_mouse_click(
resources.get::<Scene>(),
world.resources.get_unchecked::<Scene>(),
|me, (x, y, z), board| {
let slot = &mut board[x][y][z];
@ -981,9 +981,8 @@ impl EventConsumer for MillGame {
(BoardSlotState::White(_), PlayerColor::Black) => true,
_ => false,
} {
let mut stones = self.stones(me.current_player.other());
let stone = stones
let stone = me
.stones_mut(me.current_player.other())
.iter_mut()
.find(|s| {
s.stone
@ -997,7 +996,7 @@ impl EventConsumer for MillGame {
Self::remove_stone(stone, slot, world)?;
me.finish_turn(world);
me.finish_turn(world.now());
}
Ok(())
@ -1005,17 +1004,15 @@ impl EventConsumer for MillGame {
)?;
}
GameState::Main => {
let mut resources = world.resources.multi_mut();
self.check_mouse_click(resources.get::<Scene>() , |me, (tx, ty, tz), board| {
self.check_mouse_click(world.resources.get_unchecked::<Scene>() , |me, (tx, ty, tz), board| {
match me.selected_field {
Some((x, y, z)) => {
if Self::is_neighbour((x, y, z), (tx, ty, tz)) {
if let Some(millstate)
= Self::move_stone((x,y,z), (tx,ty,tz), world, board, &mut self.state)? {
= Self::move_stone((x,y,z), (tx,ty,tz), world, board, &mut me.state)? {
if let MillState::None = millstate {
me.selected_field = None;
self.finish_turn(world);
me.finish_turn(world.now());
}
}
}

View file

@ -14,7 +14,10 @@ fn main() -> Result<()> {
create_engine(&mut world_builder)?;
world_builder.add_system(MillGame::update);
world_builder.build().run()
let mut world = world_builder.build();
MillGame::new(&mut world)?;
world.run()
}
fn create_engine(world_builder: &mut WorldBuilder) -> Result<()> {
@ -39,7 +42,5 @@ fn create_engine(world_builder: &mut WorldBuilder) -> Result<()> {
create_info.enable_keyboard = true;
create_info.enable_mouse = true;
let engine = Engine::new::<MillGame>(create_info, world_builder)?;
Ok(())
Engine::new::<MillGame>(create_info, world_builder)
}

View file

@ -47,21 +47,17 @@ impl SimpleAI {
(slot.x, slot.y, slot.z)
};
scene.on_scene(|scene| {
if MillGame::place_stone(
placable,
(x, y, z),
board,
self.player_color,
scene,
state,
)? != MillState::None
{
found_a_mill = true;
}
Ok(())
})?;
if MillGame::place_stone(
placable,
(x, y, z),
board,
self.player_color,
world,
state,
)? != MillState::None
{
found_a_mill = true;
}
}
}
GameState::Removing => {
@ -95,82 +91,67 @@ impl SimpleAI {
MillGame::log("[AI] remove stone", LogSeverity::Debug);
scene.on_scene(|scene| {
MillGame::remove_stone(stone, slot, scene)?;
Ok(())
})?;
MillGame::remove_stone(stone, slot, world)?;
}
GameState::Main => {
scene.on_scene(|scene| {
loop {
let same_color: Vec<&BoardSlot> = board
.iter()
.flatten()
.flatten()
.filter(|slot| match (slot.state(), self.player_color) {
(BoardSlotState::White(_), PlayerColor::White) => true,
(BoardSlotState::Black(_), PlayerColor::Black) => true,
_ => false,
})
.collect();
GameState::Main => loop {
let same_color: Vec<&BoardSlot> = board
.iter()
.flatten()
.flatten()
.filter(|slot| match (slot.state(), self.player_color) {
(BoardSlotState::White(_), PlayerColor::White) => true,
(BoardSlotState::Black(_), PlayerColor::Black) => true,
_ => false,
})
.collect();
let len = same_color.len();
let slot = &same_color[Random::range(0, len as u32) as usize];
let n = Board::get_neighbours(slot, board);
let neighbours: Vec<&&BoardSlot> = n
.iter()
.filter(|n| n.state() == BoardSlotState::Empty)
.collect();
let len = same_color.len();
let slot = &same_color[Random::range(0, len as u32) as usize];
let n = Board::get_neighbours(slot, board);
let neighbours: Vec<&&BoardSlot> = n
.iter()
.filter(|n| n.state() == BoardSlotState::Empty)
.collect();
if !neighbours.is_empty() {
let neighbour =
&neighbours[Random::range(0, neighbours.len() as u32) as usize];
if !neighbours.is_empty() {
let neighbour = &neighbours[Random::range(0, neighbours.len() as u32) as usize];
if neighbour.state() == BoardSlotState::Empty {
let (x, y, z) = (slot.x, slot.y, slot.z);
let (tx, ty, tz) = (neighbour.x, neighbour.y, neighbour.z);
if neighbour.state() == BoardSlotState::Empty {
let (x, y, z) = (slot.x, slot.y, slot.z);
let (tx, ty, tz) = (neighbour.x, neighbour.y, neighbour.z);
let mut successful_move = false;
let mut successful_move = false;
MillGame::log("[AI] going to make a move", LogSeverity::Debug);
MillGame::log("[AI] going to make a move", LogSeverity::Debug);
if let Some(millstate) = MillGame::move_stone(
(x, y, z),
(tx, ty, tz),
scene,
board,
state,
)? {
MillGame::log("[AI] successful move", LogSeverity::Debug);
if let Some(millstate) =
MillGame::move_stone((x, y, z), (tx, ty, tz), world, board, state)?
{
MillGame::log("[AI] successful move", LogSeverity::Debug);
if MillState::None != millstate {
MillGame::log("[AI] found a mill", LogSeverity::Debug);
if MillState::None != millstate {
MillGame::log("[AI] found a mill", LogSeverity::Debug);
found_a_mill = true;
}
successful_move = true;
} else {
MillGame::log("[AI] move failed", LogSeverity::Debug);
}
if successful_move {
break;
}
found_a_mill = true;
}
successful_move = true;
} else {
MillGame::log("[AI] move failed", LogSeverity::Debug);
}
if successful_move {
break;
}
}
Ok(())
})?;
}
}
},
GameState::Waiting => unreachable!(),
GameState::Won(_) => (),
}
if found_a_mill {
self.step(stones, board, scene, state)?;
self.step(stones, board, world, state)?;
}
MillGame::log("finish AI", LogSeverity::Debug);