Continue fixing (part 2)
This commit is contained in:
parent
e5d94f32f0
commit
fabcff5a65
2 changed files with 257 additions and 276 deletions
36
src/board.rs
36
src/board.rs
|
@ -1,4 +1,4 @@
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::Arc;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use engine::prelude::{
|
use engine::prelude::{
|
||||||
|
@ -14,7 +14,7 @@ pub struct BoardSlot {
|
||||||
pub y: usize,
|
pub y: usize,
|
||||||
pub z: usize,
|
pub z: usize,
|
||||||
|
|
||||||
state: Mutex<BoardSlotState>,
|
state: BoardSlotState,
|
||||||
pub position: Vector2<f32>,
|
pub position: Vector2<f32>,
|
||||||
pub slot_marker: Option<Entity>,
|
pub slot_marker: Option<Entity>,
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ impl BoardSlot {
|
||||||
y,
|
y,
|
||||||
z,
|
z,
|
||||||
|
|
||||||
state: Mutex::new(BoardSlotState::default()),
|
state: BoardSlotState::default(),
|
||||||
position,
|
position,
|
||||||
slot_marker: Some(world.add_entity(marker)?),
|
slot_marker: Some(world.add_entity(marker)?),
|
||||||
})
|
})
|
||||||
|
@ -61,7 +61,7 @@ impl BoardSlot {
|
||||||
y,
|
y,
|
||||||
z,
|
z,
|
||||||
|
|
||||||
state: Mutex::new(BoardSlotState::Invalid),
|
state: BoardSlotState::Invalid,
|
||||||
position: vec2(0.0, 0.0),
|
position: vec2(0.0, 0.0),
|
||||||
slot_marker: None,
|
slot_marker: None,
|
||||||
}
|
}
|
||||||
|
@ -106,30 +106,30 @@ impl BoardSlot {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn state(&self) -> BoardSlotState {
|
pub fn state(&self) -> BoardSlotState {
|
||||||
*self.state.lock().unwrap()
|
self.state
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_state(&self, state: BoardSlotState) {
|
pub fn set_state(&mut self, state: BoardSlotState) {
|
||||||
*self.state.lock().unwrap() = state;
|
self.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn valid(&self) -> bool {
|
pub fn valid(&self) -> bool {
|
||||||
*self.state.lock().unwrap() != BoardSlotState::Invalid
|
self.state != BoardSlotState::Invalid
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
*self.state.lock().unwrap() == BoardSlotState::Empty
|
self.state == BoardSlotState::Empty
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn white(&self) -> bool {
|
pub fn white(&self) -> bool {
|
||||||
match *self.state.lock().unwrap() {
|
match self.state {
|
||||||
BoardSlotState::White(_) => true,
|
BoardSlotState::White(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn black(&self) -> bool {
|
pub fn black(&self) -> bool {
|
||||||
match *self.state.lock().unwrap() {
|
match self.state {
|
||||||
BoardSlotState::Black(_) => true,
|
BoardSlotState::Black(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
@ -277,13 +277,13 @@ impl Board {
|
||||||
&mut self.slots
|
&mut self.slots
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn close_to_marker(&mut self, position: Vector2<f32>) -> Option<&mut BoardSlot> {
|
pub fn close_to_marker(&self, position: Vector2<f32>) -> Option<&BoardSlot> {
|
||||||
const DISTANCE: f32 = 1.25;
|
const DISTANCE: f32 = 1.25;
|
||||||
|
|
||||||
for outer in self.slots.iter_mut() {
|
for outer in self.slots.iter() {
|
||||||
for inner in outer.iter_mut() {
|
for inner in outer.iter() {
|
||||||
for slot in inner.iter_mut() {
|
for slot in inner.iter() {
|
||||||
if *slot.state.lock().unwrap() != BoardSlotState::Invalid {
|
if slot.state != BoardSlotState::Invalid {
|
||||||
if (slot.position - position).magnitude() <= DISTANCE {
|
if (slot.position - position).magnitude() <= DISTANCE {
|
||||||
return Some(slot);
|
return Some(slot);
|
||||||
}
|
}
|
||||||
|
@ -349,9 +349,7 @@ impl Board {
|
||||||
|
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
} {
|
} {
|
||||||
let neighbour_state = neighbour.state.lock().unwrap();
|
match neighbour.state {
|
||||||
|
|
||||||
match *neighbour_state {
|
|
||||||
BoardSlotState::Empty => {
|
BoardSlotState::Empty => {
|
||||||
neighbours.push(neighbour);
|
neighbours.push(neighbour);
|
||||||
}
|
}
|
||||||
|
|
281
src/game.rs
281
src/game.rs
|
@ -244,13 +244,6 @@ impl MillGame {
|
||||||
sun_light.set_position(vec3(0.0, 0.0, 100.0))?;
|
sun_light.set_position(vec3(0.0, 0.0, 100.0))?;
|
||||||
sun_light.set_power(10000000000.0)?;
|
sun_light.set_power(10000000000.0)?;
|
||||||
|
|
||||||
let scene = world.resources.get_mut::<Scene>();
|
|
||||||
scene.add_light(sun_light)?;
|
|
||||||
|
|
||||||
let view = scene.view_mut();
|
|
||||||
view.camera_mut().set_center(board.center());
|
|
||||||
view.update_buffer()?;
|
|
||||||
|
|
||||||
let white_stones = Self::init_nine_stones(world, Color::White)?
|
let white_stones = Self::init_nine_stones(world, Color::White)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
|
@ -283,29 +276,38 @@ impl MillGame {
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap_or_else(|_: Vec<Stone>| unreachable!("create array from vec from an array"));
|
.unwrap_or_else(|_: Vec<Stone>| unreachable!("create array from vec from an array"));
|
||||||
|
|
||||||
let mut camera_control = TopDownCameraControl::new(&mut scene)?;
|
let scene = world.resources.get_mut::<Scene>();
|
||||||
|
scene.add_light(sun_light)?;
|
||||||
|
|
||||||
|
let view = scene.view_mut();
|
||||||
|
view.camera_mut().set_center(board.center());
|
||||||
|
view.update_buffer()?;
|
||||||
|
|
||||||
|
let mut camera_control = TopDownCameraControl::new(view)?;
|
||||||
camera_control.set_zoom_levels(
|
camera_control.set_zoom_levels(
|
||||||
(3..60).into_iter().rev().map(|z| z as f32).collect(),
|
(3..60).into_iter().rev().map(|z| z as f32).collect(),
|
||||||
5,
|
5,
|
||||||
&mut scene,
|
view,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
world.resources.insert(camera_control);
|
world.resources.insert(camera_control);
|
||||||
|
|
||||||
let gui = GuiBuilder::new(
|
let path = AssetPath::from((
|
||||||
engine.gui_handler(),
|
world
|
||||||
&AssetPath::from((
|
.resources
|
||||||
engine.settings().resource_base_path.as_str(),
|
.get::<EngineSettings>()
|
||||||
|
.resource_base_path
|
||||||
|
.as_str(),
|
||||||
"mainmenu.xml",
|
"mainmenu.xml",
|
||||||
)),
|
));
|
||||||
)?;
|
let gui = GuiBuilder::new(world, &path)?;
|
||||||
|
|
||||||
let grid: Arc<Grid> = gui.element("grid")?;
|
let grid: Arc<Grid> = gui.element("grid")?;
|
||||||
let white_player_label: Arc<Label> = gui.element("white_player_label")?;
|
let white_player_label: Arc<Label> = gui.element("white_player_label")?;
|
||||||
let black_player_label: Arc<Label> = gui.element("black_player_label")?;
|
let black_player_label: Arc<Label> = gui.element("black_player_label")?;
|
||||||
let start_button: Arc<Button> = gui.element("start")?;
|
let start_button: Arc<Button> = gui.element("start")?;
|
||||||
|
|
||||||
gui.enable(world.resources.get_mut::<GuiHandler>())?;
|
gui.enable(world)?;
|
||||||
|
|
||||||
start_button.set_callback({
|
start_button.set_callback({
|
||||||
let weak_grid = Arc::downgrade(&grid);
|
let weak_grid = Arc::downgrade(&grid);
|
||||||
|
@ -323,7 +325,7 @@ impl MillGame {
|
||||||
me.state = GameState::Placing;
|
me.state = GameState::Placing;
|
||||||
me.current_player = PlayerColor::Black;
|
me.current_player = PlayerColor::Black;
|
||||||
|
|
||||||
me.finish_turn();
|
me.finish_turn(world);
|
||||||
me.last_turn_timing = now;
|
me.last_turn_timing = now;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -346,7 +348,7 @@ impl MillGame {
|
||||||
mouse_y: 0,
|
mouse_y: 0,
|
||||||
|
|
||||||
turn_finished: false,
|
turn_finished: false,
|
||||||
turn_states: TurnState::default(),
|
turn_states: Vec::new(),
|
||||||
|
|
||||||
selected_field: None,
|
selected_field: None,
|
||||||
|
|
||||||
|
@ -363,28 +365,31 @@ impl MillGame {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn finish_turn(&mut self) {
|
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 = self.engine.time();
|
self.last_turn_timing = world.now();
|
||||||
self.turn_finished = true;
|
self.turn_finished = true;
|
||||||
self.selected_field = None;
|
self.selected_field = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_game_state(&self, severity: LogSeverity, log_state: bool) -> Result<()> {
|
fn print_game_state(
|
||||||
let current_turn_state = TurnState::new(self)?;
|
&mut self,
|
||||||
|
world: &World,
|
||||||
|
severity: LogSeverity,
|
||||||
|
log_state: bool,
|
||||||
|
) -> Result<()> {
|
||||||
|
let current_turn_state = TurnState::new(world, self)?;
|
||||||
|
|
||||||
if log_state {
|
if log_state {
|
||||||
current_turn_state.log(severity);
|
current_turn_state.log(severity);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut turn_states = self.turn_states.lock().unwrap();
|
if !self.turn_states.is_empty() {
|
||||||
|
let (new_diff, old_diff) = current_turn_state.diff(self.turn_states.last().unwrap());
|
||||||
if !turn_states.is_empty() {
|
|
||||||
let (new_diff, old_diff) = current_turn_state.diff(turn_states.last().unwrap());
|
|
||||||
|
|
||||||
// verity that last turn actually something happened
|
// verity that last turn actually something happened
|
||||||
debug_assert!(!new_diff.is_empty());
|
debug_assert!(!new_diff.is_empty());
|
||||||
|
@ -396,136 +401,127 @@ impl MillGame {
|
||||||
new_diff.log(severity);
|
new_diff.log(severity);
|
||||||
}
|
}
|
||||||
|
|
||||||
turn_states.push(current_turn_state);
|
self.turn_states.push(current_turn_state);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_game_step(&self) -> Result<()> {
|
fn next_game_step(&mut self, world: &World) -> Result<()> {
|
||||||
{
|
|
||||||
let mut state = self.state.lock().unwrap();
|
|
||||||
|
|
||||||
Self::log(
|
Self::log(
|
||||||
&format!(
|
&format!(
|
||||||
" =========================== NEW TURN ({:?}) ===========================",
|
" =========================== NEW TURN ({:?}) ===========================",
|
||||||
state
|
self.state
|
||||||
),
|
),
|
||||||
LogSeverity::Basic,
|
LogSeverity::Basic,
|
||||||
);
|
);
|
||||||
|
|
||||||
self.print_game_state(LogSeverity::Basic, false)?;
|
self.print_game_state(world, LogSeverity::Basic, false)?;
|
||||||
|
|
||||||
match *state {
|
match self.state {
|
||||||
GameState::Placing => {
|
GameState::Placing => {
|
||||||
// check if all stones are placed
|
// check if all stones are placed
|
||||||
if !self
|
if !self
|
||||||
.black_stones
|
.black_stones
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.iter()
|
.iter()
|
||||||
.any(|stones| stones.state == StoneState::ReadyToBePlaced)
|
.any(|stones| stones.state == StoneState::ReadyToBePlaced)
|
||||||
&& !self
|
&& !self
|
||||||
.white_stones
|
.white_stones
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.iter()
|
.iter()
|
||||||
.any(|stones| stones.state == StoneState::ReadyToBePlaced)
|
.any(|stones| stones.state == StoneState::ReadyToBePlaced)
|
||||||
{
|
{
|
||||||
Self::log("change state to Main", LogSeverity::Debug);
|
Self::log("change state to Main", LogSeverity::Debug);
|
||||||
*state = GameState::Main;
|
self.state = GameState::Main;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.current_player.lock().unwrap().swap();
|
self.current_player.swap();
|
||||||
}
|
}
|
||||||
GameState::Removing => {
|
GameState::Removing => {
|
||||||
// check if all stones are placed, then decide whether main or placing is next state
|
// check if all stones are placed, then decide whether main or placing is next state
|
||||||
if !self
|
if !self
|
||||||
.black_stones
|
.black_stones
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.iter()
|
.iter()
|
||||||
.any(|stones| stones.state == StoneState::ReadyToBePlaced)
|
.any(|stones| stones.state == StoneState::ReadyToBePlaced)
|
||||||
&& !self
|
&& !self
|
||||||
.white_stones
|
.white_stones
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.iter()
|
.iter()
|
||||||
.any(|stones| stones.state == StoneState::ReadyToBePlaced)
|
.any(|stones| stones.state == StoneState::ReadyToBePlaced)
|
||||||
{
|
{
|
||||||
Self::log("change state to Main", LogSeverity::Debug);
|
Self::log("change state to Main", LogSeverity::Debug);
|
||||||
*state = GameState::Main;
|
self.state = GameState::Main;
|
||||||
} else {
|
} else {
|
||||||
Self::log("change state to Placing", LogSeverity::Debug);
|
Self::log("change state to Placing", LogSeverity::Debug);
|
||||||
*state = GameState::Placing;
|
self.state = GameState::Placing;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.current_player.lock().unwrap().swap();
|
self.current_player.swap();
|
||||||
}
|
}
|
||||||
GameState::Main => {
|
GameState::Main => {
|
||||||
// check if each player has enough stones to play
|
// check if each player has enough stones to play
|
||||||
if self
|
if self
|
||||||
.white_stones
|
.white_stones
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|stone| stone.state != StoneState::Dead)
|
.filter(|stone| stone.state != StoneState::Dead)
|
||||||
.collect::<Vec<&Stone>>()
|
.collect::<Vec<&Stone>>()
|
||||||
.len()
|
.len()
|
||||||
<= 3
|
<= 3
|
||||||
{
|
{
|
||||||
*state = GameState::Won(PlayerColor::Black);
|
self.state = GameState::Won(PlayerColor::Black);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if self
|
if self
|
||||||
.black_stones
|
.black_stones
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|stone| stone.state != StoneState::Dead)
|
.filter(|stone| stone.state != StoneState::Dead)
|
||||||
.collect::<Vec<&Stone>>()
|
.collect::<Vec<&Stone>>()
|
||||||
.len()
|
.len()
|
||||||
<= 3
|
<= 3
|
||||||
{
|
{
|
||||||
*state = GameState::Won(PlayerColor::White);
|
self.state = GameState::Won(PlayerColor::White);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.current_player.lock().unwrap().swap();
|
self.current_player.swap();
|
||||||
}
|
}
|
||||||
GameState::Waiting => unreachable!(),
|
GameState::Waiting => unreachable!(),
|
||||||
GameState::Won(_) => (),
|
GameState::Won(_) => (),
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let player = *self.current_player.lock().unwrap();
|
Self::log(
|
||||||
|
&format!("current player {:?}", self.current_player),
|
||||||
|
LogSeverity::Debug,
|
||||||
|
);
|
||||||
|
|
||||||
Self::log(&format!("current player {:?}", player), LogSeverity::Debug);
|
let mut resources = world.resources.multi_mut();
|
||||||
|
let gui_handler = resources.get::<GuiHandler>();
|
||||||
|
let simple_ai = resources.get::<SimpleAI>();
|
||||||
|
|
||||||
match player {
|
match self.current_player {
|
||||||
PlayerColor::White => {
|
PlayerColor::White => {
|
||||||
self.black_player_label
|
self.black_player_label
|
||||||
.set_background(Color::try_from("#9b9292")?)?;
|
.set_background(gui_handler, Color::try_from("#9b9292")?)?;
|
||||||
self.white_player_label.set_background(Color::Yellow)?;
|
self.white_player_label
|
||||||
|
.set_background(gui_handler, Color::Yellow)?;
|
||||||
}
|
}
|
||||||
PlayerColor::Black => {
|
PlayerColor::Black => {
|
||||||
self.white_player_label
|
self.white_player_label
|
||||||
.set_background(Color::try_from("#9b9292")?)?;
|
.set_background(gui_handler, Color::try_from("#9b9292")?)?;
|
||||||
self.black_player_label.set_background(Color::Yellow)?;
|
self.black_player_label
|
||||||
|
.set_background(gui_handler, Color::Yellow)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if player == self.simple_ai.player_color {
|
if self.current_player == simple_ai.player_color {
|
||||||
Self::log("current player is AI", LogSeverity::Debug);
|
Self::log("current player is AI", LogSeverity::Debug);
|
||||||
|
|
||||||
self.simple_ai.step(
|
simple_ai.step(
|
||||||
&mut self.stones(self.simple_ai.player_color),
|
&mut self.stones(simple_ai.player_color),
|
||||||
self.board.lock().unwrap().slots(),
|
self.board.slots_mut(),
|
||||||
&mut *self.scene.lock().unwrap(),
|
&mut *self.scene.lock().unwrap(),
|
||||||
&mut *self.state.lock().unwrap(),
|
&mut self.state,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.finish_turn();
|
self.finish_turn(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::log("leave next_game_step", LogSeverity::Debug);
|
Self::log("leave next_game_step", LogSeverity::Debug);
|
||||||
|
@ -601,12 +597,12 @@ impl MillGame {
|
||||||
(x, y, z): (usize, usize, usize),
|
(x, y, z): (usize, usize, usize),
|
||||||
board: &mut [[[BoardSlot; 3]; 3]; 3],
|
board: &mut [[[BoardSlot; 3]; 3]; 3],
|
||||||
player_color: PlayerColor,
|
player_color: PlayerColor,
|
||||||
scene: &mut Scene,
|
world: &mut World,
|
||||||
state: &mut GameState,
|
state: &mut GameState,
|
||||||
) -> Result<MillState> {
|
) -> Result<MillState> {
|
||||||
Self::log("place_stone", LogSeverity::Debug);
|
Self::log("place_stone", LogSeverity::Debug);
|
||||||
|
|
||||||
let slot = &board[x][y][z];
|
let slot = &mut board[x][y][z];
|
||||||
|
|
||||||
match player_color {
|
match player_color {
|
||||||
PlayerColor::White => {
|
PlayerColor::White => {
|
||||||
|
@ -637,7 +633,7 @@ impl MillGame {
|
||||||
|
|
||||||
stone.state = StoneState::Placed;
|
stone.state = StoneState::Placed;
|
||||||
|
|
||||||
let entity = scene.entity_mut(stone.stone)?;
|
let entity = world.entity_mut(stone.stone)?;
|
||||||
|
|
||||||
let location = entity.get_component_mut::<Location>()?;
|
let location = entity.get_component_mut::<Location>()?;
|
||||||
location.set_position(slot.position.extend(0.0));
|
location.set_position(slot.position.extend(0.0));
|
||||||
|
@ -659,7 +655,7 @@ impl MillGame {
|
||||||
pub fn move_stone(
|
pub fn move_stone(
|
||||||
(x, y, z): (usize, usize, usize),
|
(x, y, z): (usize, usize, usize),
|
||||||
(tx, ty, tz): (usize, usize, usize),
|
(tx, ty, tz): (usize, usize, usize),
|
||||||
scene: &mut Scene,
|
world: &mut World,
|
||||||
board: &mut [[[BoardSlot; 3]; 3]; 3],
|
board: &mut [[[BoardSlot; 3]; 3]; 3],
|
||||||
state: &mut GameState,
|
state: &mut GameState,
|
||||||
) -> Result<Option<MillState>> {
|
) -> Result<Option<MillState>> {
|
||||||
|
@ -668,8 +664,8 @@ impl MillGame {
|
||||||
LogSeverity::Debug,
|
LogSeverity::Debug,
|
||||||
);
|
);
|
||||||
|
|
||||||
let slot = &board[x][y][z];
|
let slot = &mut board[x][y][z];
|
||||||
let neighbour = &board[tx][ty][tz];
|
let neighbour = &mut board[tx][ty][tz];
|
||||||
|
|
||||||
if neighbour.state() != BoardSlotState::Empty
|
if neighbour.state() != BoardSlotState::Empty
|
||||||
|| !Self::is_neighbour((x, y, z), (tx, ty, tz))
|
|| !Self::is_neighbour((x, y, z), (tx, ty, tz))
|
||||||
|
@ -681,7 +677,7 @@ impl MillGame {
|
||||||
neighbour.set_state(slot.state());
|
neighbour.set_state(slot.state());
|
||||||
slot.set_state(BoardSlotState::Empty);
|
slot.set_state(BoardSlotState::Empty);
|
||||||
|
|
||||||
scene
|
world
|
||||||
.entity_mut(match neighbour.state() {
|
.entity_mut(match neighbour.state() {
|
||||||
BoardSlotState::Black(e) => {
|
BoardSlotState::Black(e) => {
|
||||||
Self::log(
|
Self::log(
|
||||||
|
@ -730,7 +726,7 @@ impl MillGame {
|
||||||
Ok(Some(millstate))
|
Ok(Some(millstate))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_stone(stone: &mut Stone, slot: &mut BoardSlot, scene: &mut Scene) -> Result<()> {
|
pub fn remove_stone(stone: &mut Stone, slot: &mut BoardSlot, world: &mut World) -> Result<()> {
|
||||||
Self::log("remove_stone", LogSeverity::Debug);
|
Self::log("remove_stone", LogSeverity::Debug);
|
||||||
|
|
||||||
let entity = match slot.state() {
|
let entity = match slot.state() {
|
||||||
|
@ -761,7 +757,7 @@ impl MillGame {
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
scene.remove_entity(entity)?;
|
world.remove_entity(entity);
|
||||||
|
|
||||||
assert_ne!(stone.state, StoneState::Dead);
|
assert_ne!(stone.state, StoneState::Dead);
|
||||||
stone.state = StoneState::Dead;
|
stone.state = StoneState::Dead;
|
||||||
|
@ -831,30 +827,21 @@ impl MillGame {
|
||||||
MillState::None
|
MillState::None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_mouse_click<F>(&self, f: F) -> Result<()>
|
fn check_mouse_click<F>(&mut self, scene: &Scene, f: F) -> Result<()>
|
||||||
where
|
where
|
||||||
F: FnOnce(
|
F: FnOnce(&Self, (usize, usize, usize), &mut [[[BoardSlot; 3]; 3]; 3]) -> Result<()>,
|
||||||
&Self,
|
|
||||||
(usize, usize, usize),
|
|
||||||
&mut [[[BoardSlot; 3]; 3]; 3],
|
|
||||||
&mut Scene,
|
|
||||||
) -> Result<()>,
|
|
||||||
{
|
{
|
||||||
Self::log("check_mouse_click", LogSeverity::Debug);
|
Self::log("check_mouse_click", LogSeverity::Debug);
|
||||||
|
|
||||||
self.scene.lock().unwrap().on_scene(|scene| {
|
|
||||||
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)? {
|
||||||
let mut board = self.board.lock().unwrap();
|
if let Some(slot) = self.board.close_to_marker(world_space.truncate()) {
|
||||||
|
|
||||||
if let Some(slot) = 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);
|
||||||
|
|
||||||
f(self, (slot.x, slot.y, slot.z), board.slots(), scene)?;
|
f(self, (slot.x, slot.y, slot.z), self.board.slots_mut())?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_neighbour((x, y, z): (usize, usize, usize), (tx, ty, tz): (usize, usize, usize)) -> bool {
|
fn is_neighbour((x, y, z): (usize, usize, usize), (tx, ty, tz): (usize, usize, usize)) -> bool {
|
||||||
|
@ -904,7 +891,7 @@ impl MillGame {
|
||||||
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 {
|
||||||
me.turn_finished = false;
|
me.turn_finished = false;
|
||||||
me.next_game_step()?;
|
me.next_game_step(world)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -919,28 +906,28 @@ impl EventConsumer for MillGame {
|
||||||
self.mouse_x = x;
|
self.mouse_x = x;
|
||||||
self.mouse_y = y;
|
self.mouse_y = y;
|
||||||
|
|
||||||
self.camera_controls.lock().unwrap().mouse_move(
|
let mut resources = world.resources.multi_mut();
|
||||||
x,
|
let camera_controls = resources.get::<TopDownCameraControl>();
|
||||||
y,
|
let scene = resources.get::<Scene>();
|
||||||
&mut *self.scene.lock().unwrap(),
|
|
||||||
)?;
|
camera_controls.mouse_move(x, y, scene.view_mut())?;
|
||||||
}
|
}
|
||||||
EngineEvent::MouseButtonDown(button) => {
|
EngineEvent::MouseButtonDown(button) => match button {
|
||||||
match button {
|
|
||||||
MouseButton::Left => {
|
MouseButton::Left => {
|
||||||
let mut state = self.state.lock().unwrap();
|
|
||||||
Self::log(
|
Self::log(
|
||||||
&format!("User click at state {:?}", state),
|
&format!("User click at state {:?}", self.state),
|
||||||
LogSeverity::Debug,
|
LogSeverity::Debug,
|
||||||
);
|
);
|
||||||
|
|
||||||
match *state {
|
match self.state {
|
||||||
GameState::Placing => {
|
GameState::Placing => {
|
||||||
self.check_mouse_click(|me, (x, y, z), board, scene| {
|
let mut resources = world.resources.multi_mut();
|
||||||
let current_player = *me.current_player.lock().unwrap();
|
|
||||||
|
|
||||||
|
self.check_mouse_click(
|
||||||
|
resources.get::<Scene>(),
|
||||||
|
|me, (x, y, z), board| {
|
||||||
if let Some(placable) = me
|
if let Some(placable) = me
|
||||||
.stones(current_player)
|
.stones(me.current_player)
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|stone| stone.state == StoneState::ReadyToBePlaced)
|
.find(|stone| stone.state == StoneState::ReadyToBePlaced)
|
||||||
{
|
{
|
||||||
|
@ -949,12 +936,12 @@ impl EventConsumer for MillGame {
|
||||||
placable,
|
placable,
|
||||||
(x, y, z),
|
(x, y, z),
|
||||||
board,
|
board,
|
||||||
current_player,
|
me.current_player,
|
||||||
scene,
|
world,
|
||||||
&mut *state,
|
&mut self.state,
|
||||||
)? == MillState::None
|
)? == MillState::None
|
||||||
{
|
{
|
||||||
me.finish_turn();
|
me.finish_turn(world);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Self::log(
|
Self::log(
|
||||||
|
@ -969,28 +956,32 @@ impl EventConsumer for MillGame {
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
},
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
GameState::Removing => {
|
GameState::Removing => {
|
||||||
self.check_mouse_click(|me, (x, y, z), board, scene| {
|
let mut resources = world.resources.multi_mut();
|
||||||
|
|
||||||
|
self.check_mouse_click(
|
||||||
|
resources.get::<Scene>(),
|
||||||
|
|me, (x, y, z), board| {
|
||||||
let slot = &mut board[x][y][z];
|
let slot = &mut board[x][y][z];
|
||||||
|
|
||||||
Self::log(
|
Self::log(
|
||||||
&format!(
|
&format!(
|
||||||
"state {:?} - player {:?}",
|
"state {:?} - player {:?}",
|
||||||
slot.state(),
|
slot.state(),
|
||||||
*me.current_player.lock().unwrap()
|
me.current_player
|
||||||
),
|
),
|
||||||
LogSeverity::Debug,
|
LogSeverity::Debug,
|
||||||
);
|
);
|
||||||
|
|
||||||
if match (slot.state(), *me.current_player.lock().unwrap()) {
|
if match (slot.state(), me.current_player) {
|
||||||
(BoardSlotState::Black(_), PlayerColor::White) => true,
|
(BoardSlotState::Black(_), PlayerColor::White) => true,
|
||||||
(BoardSlotState::White(_), PlayerColor::Black) => true,
|
(BoardSlotState::White(_), PlayerColor::Black) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
} {
|
} {
|
||||||
let mut stones =
|
let mut stones = self.stones(me.current_player.other());
|
||||||
self.stones(me.current_player.lock().unwrap().other());
|
|
||||||
|
|
||||||
let stone = stones
|
let stone = stones
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
|
@ -1004,28 +995,27 @@ impl EventConsumer for MillGame {
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
Self::remove_stone(stone, slot, scene)?;
|
Self::remove_stone(stone, slot, world)?;
|
||||||
|
|
||||||
me.finish_turn();
|
me.finish_turn(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
},
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
GameState::Main => {
|
GameState::Main => {
|
||||||
self.check_mouse_click(|me, (tx, ty, tz), board, scene| {
|
let mut resources = world.resources.multi_mut();
|
||||||
let mut selected_slot = me.selected_field.lock().unwrap();
|
|
||||||
|
|
||||||
match *selected_slot {
|
self.check_mouse_click(resources.get::<Scene>() , |me, (tx, ty, tz), board| {
|
||||||
|
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), scene, board, &mut 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 {
|
||||||
*selected_slot = None;
|
me.selected_field = None;
|
||||||
drop(selected_slot);
|
self.finish_turn(world);
|
||||||
|
|
||||||
self.finish_turn();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1035,7 +1025,7 @@ impl EventConsumer for MillGame {
|
||||||
|
|
||||||
match (
|
match (
|
||||||
slot.state(),
|
slot.state(),
|
||||||
*me.current_player.lock().unwrap(),
|
me.current_player,
|
||||||
) {
|
) {
|
||||||
(BoardSlotState::Black(_), PlayerColor::Black)
|
(BoardSlotState::Black(_), PlayerColor::Black)
|
||||||
| (BoardSlotState::White(_), PlayerColor::White) => {
|
| (BoardSlotState::White(_), PlayerColor::White) => {
|
||||||
|
@ -1044,7 +1034,7 @@ impl EventConsumer for MillGame {
|
||||||
LogSeverity::Basic,
|
LogSeverity::Basic,
|
||||||
);
|
);
|
||||||
|
|
||||||
*selected_slot = Some((tx, ty, tz));
|
me.selected_field = Some((tx, ty, tz));
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => (),
|
_ => (),
|
||||||
|
@ -1058,43 +1048,36 @@ impl EventConsumer for MillGame {
|
||||||
GameState::Waiting | GameState::Won(_) => (),
|
GameState::Waiting | GameState::Won(_) => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MouseButton::Middle => self.camera_controls.lock().unwrap().hold(),
|
MouseButton::Middle => world.resources.get_mut::<TopDownCameraControl>().hold(),
|
||||||
MouseButton::Right => {
|
MouseButton::Right => {
|
||||||
let mut selected_slot = self.selected_field.lock().unwrap();
|
if self.selected_field.is_some() {
|
||||||
|
|
||||||
if selected_slot.is_some() {
|
|
||||||
Self::log(
|
Self::log(
|
||||||
&format!("Released selection ({:?})", selected_slot.unwrap()),
|
&format!("Released selection ({:?})", self.selected_field.unwrap()),
|
||||||
LogSeverity::Basic,
|
LogSeverity::Basic,
|
||||||
);
|
);
|
||||||
*selected_slot = None;
|
|
||||||
|
self.selected_field = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MouseButton::Forward => (),
|
MouseButton::Forward => (),
|
||||||
MouseButton::Backward => (),
|
MouseButton::Backward => (),
|
||||||
}
|
},
|
||||||
}
|
|
||||||
EngineEvent::MouseButtonUp(button) => match button {
|
EngineEvent::MouseButtonUp(button) => match button {
|
||||||
MouseButton::Left => (),
|
MouseButton::Left => (),
|
||||||
MouseButton::Middle => self.camera_controls.lock().unwrap().release(),
|
MouseButton::Middle => world.resources.get_mut::<TopDownCameraControl>().release(),
|
||||||
MouseButton::Right => (),
|
MouseButton::Right => (),
|
||||||
MouseButton::Forward => (),
|
MouseButton::Forward => (),
|
||||||
MouseButton::Backward => (),
|
MouseButton::Backward => (),
|
||||||
},
|
},
|
||||||
EngineEvent::MouseWheel(_x, y, direction) => self
|
EngineEvent::MouseWheel(_x, y, direction) => {
|
||||||
.camera_controls
|
let mut resources = world.resources.multi_mut();
|
||||||
.lock()
|
let camera_controls = resources.get::<TopDownCameraControl>();
|
||||||
.unwrap()
|
let scene = resources.get::<Scene>();
|
||||||
.scroll_wheel(y, direction, &mut *self.scene.lock().unwrap())?,
|
|
||||||
|
|
||||||
EngineEvent::KeyDown(_) => (),
|
camera_controls.scroll_wheel(y, direction, scene.view_mut())?;
|
||||||
EngineEvent::KeyUp(_) => (),
|
}
|
||||||
EngineEvent::ButtonDown(_) => (),
|
|
||||||
EngineEvent::ButtonUp(_) => (),
|
_ => (),
|
||||||
EngineEvent::ControllerAxis(_) => (),
|
|
||||||
EngineEvent::ControllerAdded(_) => (),
|
|
||||||
EngineEvent::ControllerRemoved(_) => (),
|
|
||||||
EngineEvent::FileDrop(_) => (),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Reference in a new issue