mirror of
https://github.com/szymon-jozef/checkers.git
synced 2026-10-27 19:20:44 +01:00
feat: add moving pawn to game_master and add tests
This commit is contained in:
39
Cargo.lock
generated
39
Cargo.lock
generated
@@ -8,6 +8,7 @@ version = "0.0.1"
|
||||
dependencies = [
|
||||
"env_logger",
|
||||
"log",
|
||||
"rand",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
@@ -100,12 +101,32 @@ version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "chacha20"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "defmt"
|
||||
version = "1.1.1"
|
||||
@@ -205,6 +226,7 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"r-efi",
|
||||
"rand_core",
|
||||
"wasip2",
|
||||
"wasip3",
|
||||
]
|
||||
@@ -398,6 +420,23 @@ version = "6.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80"
|
||||
dependencies = [
|
||||
"chacha20",
|
||||
"getrandom",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.13.1"
|
||||
|
||||
@@ -12,6 +12,7 @@ edition = "2024"
|
||||
[dependencies]
|
||||
env_logger = "0.11.11"
|
||||
log = "0.4.33"
|
||||
rand = "0.10.2"
|
||||
|
||||
[dependencies.uuid]
|
||||
version = "1.24.0"
|
||||
|
||||
@@ -186,7 +186,11 @@ impl Board {
|
||||
}
|
||||
}
|
||||
|
||||
Some(available_moves)
|
||||
if available_moves.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(available_moves)
|
||||
}
|
||||
}
|
||||
|
||||
fn can_capture(
|
||||
@@ -197,19 +201,30 @@ impl Board {
|
||||
already_captured: &Vec<Position>,
|
||||
pawn: &Pawn,
|
||||
) -> bool {
|
||||
debug!("=== Checkinf if pawn can capture from: {} to {}", from, to);
|
||||
|
||||
if !self.is_player_owner_of_the_pawn(player, &pawn) {
|
||||
debug!("Player wasn't owner of the pawn...");
|
||||
return false;
|
||||
}
|
||||
|
||||
if !to.is_in_range(self.size) {
|
||||
debug!("Position was out of range...");
|
||||
return false;
|
||||
}
|
||||
|
||||
if already_captured.contains(&to) {
|
||||
debug!("Pawn was already captured...");
|
||||
return false;
|
||||
}
|
||||
|
||||
let Some(captured_pawn) = &self[to].pawn else {
|
||||
debug!("There was no pawn there...");
|
||||
return false;
|
||||
};
|
||||
|
||||
if self.is_player_owner_of_the_pawn(player, captured_pawn) {
|
||||
debug!("Player tried capturing his own pawn! Idiot");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -336,11 +351,13 @@ impl Board {
|
||||
Some(available_captures)
|
||||
}
|
||||
|
||||
pub fn capture(&mut self, path: &CapturePath, capturing_player: &Player) {
|
||||
pub fn capture(&mut self, path: &CapturePath, capturing_player: &Player) -> bool {
|
||||
/*
|
||||
debug!("Capturing: {}", path);
|
||||
*/
|
||||
|
||||
// TODO! Maybe return false ??
|
||||
|
||||
let mut from = path.from;
|
||||
|
||||
for (next_pos, enemy_path) in path.iter() {
|
||||
@@ -348,6 +365,8 @@ impl Board {
|
||||
self.move_pawn_anywhere(capturing_player, from, *next_pos);
|
||||
from = *next_pos;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
pub fn get_player_pawns_positions(&self, player: &Player) -> Vec<Position> {
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
use log::warn;
|
||||
|
||||
use crate::logic::{
|
||||
board::{
|
||||
board::Board,
|
||||
pawn::{CapturePath, MovePath},
|
||||
},
|
||||
math::position::Position,
|
||||
player::Player,
|
||||
};
|
||||
|
||||
@@ -82,9 +85,10 @@ impl GameMaster {
|
||||
let player_pawns = self.board.get_player_pawns_positions(player);
|
||||
|
||||
player_pawns.len() == 0
|
||||
|| player_pawns
|
||||
.iter()
|
||||
.all(|pos| self.board.get_available_moves(*pos, player).is_none())
|
||||
|| player_pawns.iter().all(|pos| {
|
||||
self.board.get_available_moves(*pos, player).is_none()
|
||||
&& self.board.get_available_captures(*pos, player).is_none()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_game_result(&self) -> Option<GameResult> {
|
||||
@@ -104,4 +108,101 @@ impl GameMaster {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn move_pawn(&mut self, from: Position, to: Position) -> bool {
|
||||
if self.get_current_player_moves().is_empty() {
|
||||
warn!(
|
||||
"Player: {} tried moving, but they don't have any moves available!",
|
||||
self.players.get_current_turn().id
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if !self.get_current_player_captures().is_empty() {
|
||||
warn!(
|
||||
"Player: {} tried moving, but he has captures available!",
|
||||
self.players.get_current_turn().id
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if self
|
||||
.board
|
||||
.move_pawn(self.players.get_current_turn(), from, to)
|
||||
{
|
||||
self.players.change_turn();
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn capture(&mut self, path: &CapturePath) -> bool {
|
||||
if self.get_current_player_captures().is_empty() {
|
||||
warn!(
|
||||
"Player: {} tried capturing, but he doesn't have any captures available!",
|
||||
self.players.get_current_turn().id
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if self.board.capture(path, self.players.get_current_turn()) {
|
||||
self.players.change_turn();
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use log::info;
|
||||
use rand::seq::IndexedMutRandom;
|
||||
use rand::seq::IndexedRandom;
|
||||
use rand::seq::SliceRandom;
|
||||
|
||||
#[test]
|
||||
fn test_game_flow() {
|
||||
let mut master: GameMaster = GameMaster::new("Morbius".to_string(), "Milo".to_string());
|
||||
let mut turns = 0;
|
||||
let max_turns = 2000;
|
||||
|
||||
while turns < max_turns {
|
||||
if let Some(result) = master.get_game_result() {
|
||||
match result {
|
||||
GameResult::Lost(loser_id) => {
|
||||
info!("Player: {} lost! Ending the loop", loser_id);
|
||||
}
|
||||
GameResult::Draw => {
|
||||
info!("Game ended in a draw! Ending the loop");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
let mut rng = rand::rng();
|
||||
|
||||
let available_captures = master.get_current_player_captures();
|
||||
|
||||
if !available_captures.is_empty() {
|
||||
let capture = available_captures.choose(&mut rng).unwrap();
|
||||
master.capture(capture);
|
||||
turns += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut available_moves = master.get_current_player_moves();
|
||||
if !available_moves.is_empty() {
|
||||
let path = available_moves.choose_mut(&mut rng).unwrap();
|
||||
let from = path.from;
|
||||
let to = path.available_steps.choose_mut(&mut rng).unwrap();
|
||||
|
||||
master.move_pawn(from, *to);
|
||||
turns += 1;
|
||||
}
|
||||
}
|
||||
|
||||
assert!(turns < max_turns);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user