Add solver
This commit is contained in:
parent
4c740aef31
commit
d6119de05a
@ -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() {
|
||||
|
@ -1,4 +1,7 @@
|
||||
#[allow(unused)]
|
||||
mod engine;
|
||||
|
||||
#[allow(unused)]
|
||||
mod solver;
|
||||
|
||||
fn main() {}
|
||||
|
1
src/solver/mod.rs
Normal file
1
src/solver/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub(crate) mod solver;
|
110
src/solver/solver.rs
Normal file
110
src/solver/solver.rs
Normal 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());
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user