Add widgets, proper resources.rs

This commit is contained in:
cool-mist
2026-01-23 19:23:45 +05:30
parent 96a4f007cc
commit 04b39e53a4
18 changed files with 675 additions and 538 deletions
+62 -1
View File
@@ -19,7 +19,7 @@ use square::{Square, SquarePair};
use crate::generator::Puzzle;
#[derive(Clone)]
#[derive(Clone, Default)]
pub struct Board {
pub cells: [[Option<Piece>; BOARD_SIZE]; BOARD_SIZE],
pub legal_moves: HashSet<CMove>,
@@ -37,6 +37,12 @@ pub enum BoardState {
Won,
}
impl Default for BoardState {
fn default() -> Self {
BoardState::NotStarted
}
}
impl Board {
pub fn new() -> Self {
let cells = [[None; BOARD_SIZE]; BOARD_SIZE];
@@ -714,4 +720,59 @@ mod tests {
validate_board!(board2, "..NB", "....", "RQ.K", "P...");
}
macro_rules! sq {
($sq:literal) => {
Square::parse($sq)
};
}
#[test]
fn solver_smoke() {
let mut board = Board::new();
// . R . .
// R . . P
// B . B N
// P . N .
board.set(sq!("Pa1"));
board.set(sq!("Ba2"));
board.set(sq!("Ra3"));
board.set(sq!("Rb4"));
board.set(sq!("Nc1"));
board.set(sq!("Bc2"));
board.set(sq!("Nd2"));
board.set(sq!("Pd3"));
let solutions = board.solve().solutions;
for solution in solutions {
let mut board = board.clone();
solution
.into_iter()
.for_each(|m| assert!(board.make_move(m).is_some()));
assert_eq!(BoardState::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!("Pa1"));
board.set(sq!("Ba2"));
board.set(sq!("Ra3"));
board.set(sq!("Rb4"));
board.set(sq!("Nc1"));
board.set(sq!("Bc2"));
board.set(sq!("Nd2"));
let solutions = board.solve().solutions;
assert_eq!(0, solutions.len());
}
}
+29 -18
View File
@@ -1,12 +1,31 @@
use std::fmt::Display;
use crate::board::{cmove::CMove, piece::Piece, Board};
use crate::board::{Board, cmove::CMove, piece::Piece};
pub trait RandomRange {
fn gen_range(&self, min: usize, max: usize) -> usize;
}
pub fn generate(num_pieces: u32, num_solutions: u32, rand: &impl RandomRange) -> GenerateStats {
#[derive(Default)]
pub struct Puzzle {
pub board: Board,
pub solutions: Vec<Vec<CMove>>,
pub solved: bool,
}
pub struct GenerateStats {
piece_total: u32,
piece_success: u32,
total: u32,
board: Option<Board>,
solutions: Vec<Vec<CMove>>,
}
pub fn generate_weighted_random(
num_pieces: u32,
num_solutions: u32,
rand: &impl RandomRange,
) -> GenerateStats {
let candidate_pieces = vec![
Piece::Pawn,
Piece::Pawn,
@@ -47,20 +66,6 @@ pub fn generate(num_pieces: u32, num_solutions: u32, rand: &impl RandomRange) ->
overall_stats
}
pub struct Puzzle {
pub board: Board,
pub solutions: Vec<Vec<CMove>>,
pub solved: bool,
}
pub struct GenerateStats {
piece_total: u32,
piece_success: u32,
total: u32,
board: Option<Board>,
solutions: Vec<Vec<CMove>>,
}
impl GenerateStats {
fn new(
piece_total: u32,
@@ -153,7 +158,13 @@ fn try_generate(
if puzzle.solutions.len() > num_solutions as usize {
GenerateStats::new(piece_total, piece_success, 1, None, vec![])
} else {
GenerateStats::new(piece_total, piece_success, 1, Some(puzzle.board), puzzle.solutions)
GenerateStats::new(
piece_total,
piece_success,
1,
Some(puzzle.board),
puzzle.solutions,
)
}
}
@@ -175,7 +186,7 @@ mod tests {
#[test]
fn generator_smoke() {
for _ in 0..10 {
let gen_stats = generate(5, 5, &TestRandom);
let gen_stats = generate_weighted_random(5, 5, &TestRandom);
let board = gen_stats.board.expect("No puzzle was generated");
assert_eq!(board.game_state, BoardState::InProgress);
-1
View File
@@ -1,3 +1,2 @@
pub mod board;
pub mod generator;
pub mod solver;
-62
View File
@@ -1,62 +0,0 @@
// #[cfg(test)]
// mod tests {
// use super::*;
// use crate::board::{square::Square, Board};
//
// macro_rules! sq {
// ($sq:literal) => {
// Square::parse($sq)
// };
// }
//
// #[test]
// fn solver_smoke() {
// let mut board = Board::new();
// // . R . .
// // R . . P
// // B . B N
// // P . N .
//
// board.set(sq!("Pa1"));
// board.set(sq!("Ba2"));
// board.set(sq!("Ra3"));
// board.set(sq!("Rb4"));
// board.set(sq!("Nc1"));
// board.set(sq!("Bc2"));
// board.set(sq!("Nd2"));
// board.set(sq!("Pd3"));
//
// let solver = Solver::new(board.clone());
// let solutions = solver.solve();
//
// for solution in solutions {
// let mut board = board.clone();
// solution
// .into_iter()
// .for_each(|m| assert!(board.make_move(m).is_some()));
// assert_eq!(BoardState::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!("Pa1"));
// board.set(sq!("Ba2"));
// board.set(sq!("Ra3"));
// board.set(sq!("Rb4"));
// board.set(sq!("Nc1"));
// board.set(sq!("Bc2"));
// board.set(sq!("Nd2"));
//
// let solver = Solver::new(board.clone());
// let solutions = solver.solve();
//
// assert_eq!(0, solutions.len());
// }
// }