minsweeper_rs/solver/
mod.rs1pub mod mia;
2pub mod start;
3
4use std::collections::HashSet;
5use std::fmt::{Debug, Display};
6use std::rc::Rc;
7use std::sync::Arc;
8use crate::{GameState, GameStatus, Minsweeper};
9use crate::board::Point;
10
11pub trait Solver {
12
13 fn solve(&self, game_state: &GameState) -> Option<Move>;
14
15 fn solve_game(&self, minsweeper: &mut dyn Minsweeper) -> GameResult {
16 let mut state = minsweeper.gamestate();
17
18 while state.status == GameStatus::Playing {
19 let Some(Move { actions, ..}) = self.solve(state) else { break };
20
21 for action in actions {
22 state = minsweeper.action(action).into()
23 }
24 }
25
26 match state.status {
27 GameStatus::Won => GameResult::Won,
28 GameStatus::Lost => GameResult::Lost,
29 GameStatus::Playing => GameResult::Resigned,
30 _ => unreachable!()
31 }
32 }
33}
34
35impl<S: Solver + ?Sized> Solver for Box<S> {
36 fn solve(&self, game_state: &GameState) -> Option<Move> {
37 (**self).solve(game_state)
38 }
39 fn solve_game(&self, minsweeper: &mut dyn Minsweeper) -> GameResult {
40 (**self).solve_game(minsweeper)
41 }
42}
43impl<S: Solver + ?Sized> Solver for Arc<S> {
44 fn solve(&self, game_state: &GameState) -> Option<Move> {
45 (**self).solve(game_state)
46 }
47 fn solve_game(&self, minsweeper: &mut dyn Minsweeper) -> GameResult {
48 (**self).solve_game(minsweeper)
49 }
50}
51impl<S: Solver + ?Sized> Solver for Rc<S> {
52 fn solve(&self, game_state: &GameState) -> Option<Move> {
53 (**self).solve(game_state)
54 }
55 fn solve_game(&self, minsweeper: &mut dyn Minsweeper) -> GameResult {
56 (**self).solve_game(minsweeper)
57 }
58}
59impl Solver for &dyn Solver {
60 fn solve(&self, game_state: &GameState) -> Option<Move> {
61 (**self).solve(game_state)
62 }
63 fn solve_game(&self, minsweeper: &mut dyn Minsweeper) -> GameResult {
64 (**self).solve_game(minsweeper)
65 }
66}
67
68#[derive(Debug)]
69pub struct Move {
70 pub actions: HashSet<Action>,
71 pub reason: Option<Reason>
72}
73
74impl Move {
75 pub fn single(action: Action, reason: Option<Reason>) -> Self {
80 Self {
81 actions: HashSet::from([action]),
82 reason
83 }
84 }
85
86 pub const fn multi(actions: HashSet<Action>, reason: Option<Reason>) -> Self {
87 Self { actions, reason }
88 }
89}
90
91#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
92pub struct Action {
93 point: Point,
94 operation: Operation,
95}
96
97impl Action {
98 pub const fn new(point: Point, operation: Operation) -> Self {
99 Self { point, operation }
100 }
101}
102
103#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
104pub enum Operation {
105 Reveal,
106 Chord,
107 Flag
108}
109
110pub trait Actionable {
111 fn action(&mut self, action: Action) -> Result<&GameState, &GameState>;
112}
113
114impl<T: Minsweeper + ?Sized> Actionable for T {
115 fn action(&mut self, action: Action) -> Result<&GameState, &GameState> {
116 match action.operation {
117 Operation::Reveal => self.reveal(action.point),
118 Operation::Chord => self.clear_around(action.point),
119 Operation::Flag => self.toggle_flag(action.point)
120 }
121 }
122}
123
124#[derive(Debug)]
125pub struct Reason {
126 pub logic: Box<dyn Logic>,
127 pub related: HashSet<Point>
128}
129
130impl Reason {
131 pub fn new<T: Logic + 'static>(logic: T, related: HashSet<Point>) -> Self {
132 Self { logic: Box::new(logic), related }
133 }
134}
135
136pub trait Logic: Debug + Display {
137
138}
139
140#[derive(Copy, Clone, Debug, Eq, PartialEq)]
141pub enum GameResult {
142 Won, Lost, Resigned
143}