chore: add is_movable

This commit is contained in:
2026-08-12 22:17:38 +02:00
parent f8c4a2029a
commit 7d76c77d01
3 changed files with 130 additions and 9 deletions

View File

@@ -1,4 +1,9 @@
use crate::logic::{field::Field, pawn::Pawn, player::Player, utils::Position}; use crate::logic::{
field::Field,
pawn::{Pawn, PawnState},
player::Player,
utils::{DeltaPosition, Position},
};
use std::ops::{Index, IndexMut}; use std::ops::{Index, IndexMut};
use log::{debug, info, warn}; use log::{debug, info, warn};
@@ -14,8 +19,12 @@ impl Board {
let size = size.unwrap_or(8); let size = size.unwrap_or(8);
info!("Creating new board of size: {}", size); info!("Creating new board of size: {}", size);
player1.end_row = size - 1; player1.end_row = Some(size - 1);
player2.end_row = 0; player1.vertical_direction = Some(crate::logic::utils::DeltaPosition { row: 1, column: 0 });
player2.end_row = Some(0);
player2.vertical_direction =
Some(crate::logic::utils::DeltaPosition { row: -1, column: 0 });
let p1_ref: &Player = &*player1; let p1_ref: &Player = &*player1;
let p2_ref: &Player = &*player2; let p2_ref: &Player = &*player2;
@@ -76,6 +85,55 @@ impl Board {
player.id == pawn.owner player.id == pawn.owner
} }
fn is_movable(&self, pos: Position, player: &Player) -> bool {
if !pos.is_in_range(self.size) {
debug!(
"Tried checking if pos: {} is movable, but it's out of bounds!",
pos
);
return false;
}
let Some(pawn) = &self[pos].pawn else {
return false;
};
let Some(direction) = player.vertical_direction else {
debug!(
"Tried checking if player: {} can move his pawn, but their direction is not yet set!",
player.id
);
return false;
};
let left_up: DeltaPosition = DeltaPosition { row: 0, column: -1 } + direction;
let right_up: DeltaPosition = DeltaPosition { row: 0, column: 1 } + direction;
match pawn.state {
PawnState::Man => {
if let Some(left_pos) = pos.checked_add(&left_up)
&& left_pos.is_in_range(self.size)
&& self[left_pos].pawn.is_none()
{
return true;
}
if let Some(right_pos) = pos.checked_add(&right_up)
&& right_pos.is_in_range(self.size)
&& self[right_pos].pawn.is_none()
{
return true;
}
false
}
PawnState::Dame => {
todo!();
}
PawnState::Captured => false,
}
}
fn get_player_pawns_positions(&self, player: &Player) -> Vec<Position> { fn get_player_pawns_positions(&self, player: &Player) -> Vec<Position> {
self.board self.board
.iter() .iter()
@@ -104,10 +162,18 @@ impl Board {
return false; return false;
} }
let Some(end_row) = player.end_row else {
warn!(
"Tried moving pawn of player {}, who wasn't initialized by the board!",
player.id
);
return false;
};
// we can safely unwrap, because if there's not pawn function returns false earlier // we can safely unwrap, because if there's not pawn function returns false earlier
let mut mowing_pawn: Pawn = self[from].pawn.take().unwrap(); let mut mowing_pawn: Pawn = self[from].pawn.take().unwrap();
if to.row == player.end_row { if to.row == end_row {
mowing_pawn.state = super::pawn::PawnState::Dame; mowing_pawn.state = super::pawn::PawnState::Dame;
} }
@@ -304,4 +370,23 @@ mod tests {
test_board.get_player_pawns_positions(&p1) test_board.get_player_pawns_positions(&p1)
); );
} }
#[test]
fn test_is_movable() {
init_logger();
let mut p1: Player = Player::new("Morbius".to_string());
let mut p2: Player = Player::new("Milo".to_string());
let test_board: Board = Board::new(&mut p1, &mut p2, None);
assert!(test_board.is_movable(Position { row: 2, column: 1 }, &p1));
assert!(!test_board.is_movable(
Position {
row: 10,
column: 12
},
&p1
));
assert!(!test_board.is_movable(Position { row: 0, column: 0 }, &p1));
}
} }

View File

@@ -2,11 +2,13 @@ use std::fmt::Display;
use uuid::Uuid; use uuid::Uuid;
use crate::logic::utils::DeltaPosition;
pub struct Player { pub struct Player {
pub name: String, pub name: String,
pub id: Uuid, pub id: Uuid,
/// Row where players pawns turn into dames pub vertical_direction: Option<DeltaPosition>,
pub end_row: usize, pub end_row: Option<usize>,
} }
impl Player { impl Player {
@@ -14,17 +16,28 @@ impl Player {
Player { Player {
name, name,
id: Uuid::new_v4(), id: Uuid::new_v4(),
end_row: 0, end_row: None,
vertical_direction: None,
} }
} }
} }
impl Display for Player { impl Display for Player {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let end_row_str = match self.end_row {
Some(row) => row.to_string(),
None => "None".to_string(),
};
let direction_str = match &self.vertical_direction {
Some(direction) => direction.to_string(),
None => "None".to_string(),
};
write!( write!(
f, f,
"(name: {}, id: {}, end_row: {})", "(name: {}, id: {}, end_row: {}, vertical_direction: {})",
self.name, self.id, self.end_row self.name, self.id, end_row_str, direction_str
) )
} }
} }

View File

@@ -1,4 +1,5 @@
use core::fmt; use core::fmt;
use std::ops::Add;
use log::debug; use log::debug;
@@ -29,14 +30,36 @@ impl Position {
column: new_column, column: new_column,
}) })
} }
pub fn is_in_range(&self, range: usize) -> bool {
self.row < range && self.column < range
}
} }
/// Vector for moving `Position` /// Vector for moving `Position`
#[derive(Debug, Copy, Clone)]
pub struct DeltaPosition { pub struct DeltaPosition {
pub row: i8, pub row: i8,
pub column: i8, pub column: i8,
} }
impl fmt::Display for DeltaPosition {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "({}, {})", self.row, self.column)
}
}
impl Add for DeltaPosition {
type Output = DeltaPosition;
fn add(self, rhs: DeltaPosition) -> Self::Output {
DeltaPosition {
row: self.row + rhs.row,
column: self.column + rhs.column,
}
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;