Add solver

This commit is contained in:
cool-mist 2025-01-04 19:29:22 +05:30
parent 4c740aef31
commit d6119de05a
4 changed files with 120 additions and 5 deletions

View File

@ -7,14 +7,15 @@ use super::{
square::{sq, Square},
};
#[derive(Clone)]
pub(crate) struct Board {
pub(crate) cells: [[Square; 4]; 4],
legal_moves: HashSet<Move>,
pieces_remaining: i8,
game_state: GameState,
pub(crate) legal_moves: HashSet<Move>,
pub(crate) game_state: GameState,
pieces_remaining: u8,
}
#[derive(PartialEq, Eq, Debug)]
#[derive(PartialEq, Eq, Debug, Clone)]
pub enum GameState {
NotStarted,
InProgress,
@ -256,7 +257,7 @@ impl Board {
if (start.rank < 3 && start.file > 0) {
let mut south = start.rank;
let mut west = start.file;
while south < 4 && west != 0 {
while south < 3 && west != 0 {
south += 1;
west -= 1;
if let Some(piece) = self.cells[west][south].occupied() {

View File

@ -1,4 +1,7 @@
#[allow(unused)]
mod engine;
#[allow(unused)]
mod solver;
fn main() {}

1
src/solver/mod.rs Normal file
View File

@ -0,0 +1 @@
pub(crate) mod solver;

110
src/solver/solver.rs Normal file
View File

@ -0,0 +1,110 @@
use crate::engine::{
board::{Board, GameState},
r#move::Move,
};
pub(crate) struct Solver {
pub(crate) board: Board,
moves: Vec<Move>,
}
impl Solver {
pub(crate) fn new(board: Board) -> Solver {
Solver {
board,
moves: vec![],
}
}
fn clone(&self, m: Move) -> Self {
let mut moves = self.moves.clone();
let mut board = self.board.clone();
moves.push(m.clone());
board.make_move(m);
Solver { board, moves }
}
pub(crate) fn solve(&self) -> Vec<Vec<Move>> {
let mut solutions = Vec::new();
if let GameState::Won = self.board.game_state {
solutions.push(self.moves.clone());
return solutions;
}
let GameState::InProgress = self.board.game_state else {
return solutions;
};
self.board.legal_moves.iter().for_each(|m| {
let mut solver = self.clone(m.clone());
let more_solutions = solver.solve();
solutions.extend(more_solutions);
});
solutions
}
}
#[cfg(test)]
mod tests {
use crate::engine::{
coord::{at, Coord},
piece::{p, Piece},
square::{sq, Square},
};
use super::*;
#[test]
fn solver_smoke() {
let mut board = Board::new();
// . R . .
// R . . P
// B . B N
// P . N .
board.set(sq!("P", "a1"));
board.set(sq!("B", "a2"));
board.set(sq!("R", "a3"));
board.set(sq!("R", "b4"));
board.set(sq!("N", "c1"));
board.set(sq!("B", "c2"));
board.set(sq!("N", "d2"));
board.set(sq!("P", "d3"));
let solver = Solver::new(board.clone());
let solutions = solver.solve();
assert_eq!(10, solutions.len());
for solution in solutions {
let mut board = board.clone();
solution.iter().for_each(|m| {
board.make_move(m.clone());
});
assert_eq!(GameState::Won, board.game_state);
}
}
#[test]
fn solver_smoke_no_solution() {
// . R . .
// R . . .
// B . B N
// P . N .
let mut board = Board::new();
board.set(sq!("P", "a1"));
board.set(sq!("B", "a2"));
board.set(sq!("R", "a3"));
board.set(sq!("R", "b4"));
board.set(sq!("N", "c1"));
board.set(sq!("B", "c2"));
board.set(sq!("N", "d2"));
let solver = Solver::new(board.clone());
let solutions = solver.solve();
assert_eq!(0, solutions.len());
}
}