Compare commits

..

No commits in common. "84dbd488b4374b55b4e099ac143060be7723c0b1" and "fabcff5a65d273d4255c1af942eb4e365b6db54d" have entirely different histories.

4 changed files with 138 additions and 108 deletions

View file

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

View file

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

View file

@ -4,6 +4,7 @@ mod objects;
mod simple_ai; mod simple_ai;
use anyhow::Result; use anyhow::Result;
use assetpath::AssetPath;
use engine::prelude::*; use engine::prelude::*;
use game::MillGame; use game::MillGame;
@ -13,10 +14,7 @@ fn main() -> Result<()> {
create_engine(&mut world_builder)?; create_engine(&mut world_builder)?;
world_builder.add_system(MillGame::update); world_builder.add_system(MillGame::update);
let mut world = world_builder.build(); world_builder.build().run()
MillGame::new(&mut world)?;
world.run()
} }
fn create_engine(world_builder: &mut WorldBuilder) -> Result<()> { fn create_engine(world_builder: &mut WorldBuilder) -> Result<()> {
@ -24,6 +22,10 @@ fn create_engine(world_builder: &mut WorldBuilder) -> Result<()> {
create_info.resource_base_path = "resources".to_string(); create_info.resource_base_path = "resources".to_string();
create_info.gui_info.font = Font::Path(AssetPath::from(("resources", "ExportedFont.png")));
create_info.gui_info.resource_directory =
AssetPath::from((create_info.resource_base_path.as_str(), "")).into();
create_info.graphics_info.render_scale = 1.0; create_info.graphics_info.render_scale = 1.0;
create_info.graphics_info.vsync = true; create_info.graphics_info.vsync = true;
create_info.graphics_info.sample_count = VK_SAMPLE_COUNT_4_BIT; create_info.graphics_info.sample_count = VK_SAMPLE_COUNT_4_BIT;
@ -37,5 +39,7 @@ fn create_engine(world_builder: &mut WorldBuilder) -> Result<()> {
create_info.enable_keyboard = true; create_info.enable_keyboard = true;
create_info.enable_mouse = true; create_info.enable_mouse = true;
Engine::new::<MillGame>(create_info, world_builder) let engine = Engine::new::<MillGame>(create_info, world_builder)?;
Ok(())
} }

View file

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