minsweeper_rs/solver/
mod.rs

1pub 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 const fn new(actions: HashSet<Action>, reason: Option<Reason<T>>) -> Self {
76    //     Self { actions, reason }
77    // }
78
79    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}