generated from PlexSheep/rs-base
add interactive solver #4
|
@ -128,7 +128,7 @@ fn help_guess_interactive(cli: Cli) -> anyhow::Result<()> {
|
|||
println!("{}", game);
|
||||
}
|
||||
ReplCommand::Solve => {
|
||||
let best_guess = solver.guess_for(&game);
|
||||
let best_guess = solver.guess_for(&game)?;
|
||||
println!("best guess: {best_guess}");
|
||||
}
|
||||
ReplCommand::Guess {
|
||||
|
|
11
src/error.rs
11
src/error.rs
|
@ -13,6 +13,11 @@ pub enum Error {
|
|||
#[from]
|
||||
source: GameError,
|
||||
},
|
||||
#[error("Solver Error")]
|
||||
SolverError {
|
||||
#[from]
|
||||
source: SolverError,
|
||||
},
|
||||
#[error("Benchmark Error")]
|
||||
BenchError {
|
||||
#[from]
|
||||
|
@ -53,3 +58,9 @@ pub enum BenchError {
|
|||
#[error("Trying to modify a finished report")]
|
||||
ModifyFinishedReport,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Error)]
|
||||
pub enum SolverError {
|
||||
#[error("Wordlist has no matches for the gamestate")]
|
||||
NoMatches,
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ pub struct AtomicEvaluation {
|
|||
pub struct GuessResponse {
|
||||
guess: Word,
|
||||
evaluation: Evaluation,
|
||||
finish: bool,
|
||||
solution: Option<WordData>,
|
||||
step: usize,
|
||||
max_steps: usize,
|
||||
|
@ -50,10 +49,9 @@ impl From<char> for Status {
|
|||
|
||||
impl GuessResponse {
|
||||
pub(crate) fn new<WL: WordList>(guess: &Word, status: Evaluation, game: &Game<WL>) -> Self {
|
||||
let new = Self {
|
||||
let mut new = Self {
|
||||
guess: guess.to_owned(),
|
||||
evaluation: status,
|
||||
finish: game.step() > game.max_steps(),
|
||||
solution: game.solution().cloned(),
|
||||
step: game.step(),
|
||||
max_steps: game.max_steps(),
|
||||
|
@ -62,7 +60,7 @@ impl GuessResponse {
|
|||
}
|
||||
|
||||
pub fn finished(&self) -> bool {
|
||||
self.finish
|
||||
self.step() > self.max_steps() || self.won()
|
||||
}
|
||||
|
||||
pub fn won(&self) -> bool {
|
||||
|
|
|
@ -11,6 +11,7 @@ use crate::{
|
|||
|
||||
#[cfg(feature = "builtin")]
|
||||
pub mod naive;
|
||||
use libpt::log::debug;
|
||||
#[cfg(feature = "builtin")]
|
||||
pub use naive::NaiveSolver;
|
||||
#[cfg(feature = "builtin")]
|
||||
|
@ -44,14 +45,14 @@ pub trait Solver<'wl, WL: WordList>: Clone + std::fmt::Debug + Sized + Sync {
|
|||
///
|
||||
/// Each [Solver] needs to implement this method themselves, many other methods rely on this to
|
||||
/// play the [Game], such as [play](Solver::play) or [solve](Solver::solve).
|
||||
fn guess_for(&self, game: &Game<'wl, WL>) -> Word;
|
||||
fn guess_for(&self, game: &Game<'wl, WL>) -> WResult<Word>;
|
||||
/// Make a singular step for a [Game]
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function will return an error if [guess_for](Solver::guess_for) fails.
|
||||
fn make_a_move(&self, game: &mut Game<'wl, WL>) -> WResult<GuessResponse> {
|
||||
Ok(game.guess(self.guess_for(game), None)?)
|
||||
Ok(game.guess(self.guess_for(game)?, None)?)
|
||||
}
|
||||
/// Play a [Game] and return the last [GuessResponse].
|
||||
///
|
||||
|
@ -146,10 +147,11 @@ impl<'wl, WL: WordList> Solver<'wl, WL> for AnyBuiltinSolver<'wl, WL> {
|
|||
fn build(wordlist: &'wl WL) -> WResult<Self> {
|
||||
Ok(Self::Naive(NaiveSolver::build(wordlist)?))
|
||||
}
|
||||
fn guess_for(&self, game: &Game<'wl, WL>) -> Word {
|
||||
match self {
|
||||
Self::Naive(solver) => solver.guess_for(game),
|
||||
Self::Stupid(solver) => solver.guess_for(game),
|
||||
}
|
||||
fn guess_for(&self, game: &Game<'wl, WL>) -> WResult<Word> {
|
||||
debug!("solver: {self:?}");
|
||||
Ok(match self {
|
||||
Self::Naive(solver) => solver.guess_for(game)?,
|
||||
Self::Stupid(solver) => solver.guess_for(game)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use libpt::log::{info, trace};
|
||||
|
||||
use crate::error::{Error, SolverError, WResult};
|
||||
use crate::wlist::word::{ManyWordDatas, Word};
|
||||
use crate::wlist::WordList;
|
||||
|
||||
|
@ -15,7 +16,7 @@ impl<'wl, WL: WordList> Solver<'wl, WL> for NaiveSolver<'wl, WL> {
|
|||
info!("using naive solver");
|
||||
Ok(Self { wl: wordlist })
|
||||
}
|
||||
fn guess_for(&self, game: &crate::game::Game<WL>) -> Word {
|
||||
fn guess_for(&self, game: &crate::game::Game<WL>) -> WResult<Word> {
|
||||
// HACK: hardcoded length
|
||||
let mut pattern: String = String::from(".....");
|
||||
let mut other_chars: Vec<char> = Vec::new();
|
||||
|
@ -54,9 +55,10 @@ impl<'wl, WL: WordList> Solver<'wl, WL> for NaiveSolver<'wl, WL> {
|
|||
})
|
||||
.map(|v| v.to_owned())
|
||||
.collect();
|
||||
matches[0].0.to_owned() // FIXME: panicks in interactive solve, when I insert bullshit and
|
||||
// pretend that there is a solution #5 It also crashes in
|
||||
// non-interactive mode
|
||||
if matches.is_empty() {
|
||||
return Err(SolverError::NoMatches.into());
|
||||
}
|
||||
Ok(matches[0].0.to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use libpt::log::info;
|
||||
|
||||
use crate::error::WResult;
|
||||
use crate::wlist::word::Word;
|
||||
use crate::wlist::WordList;
|
||||
|
||||
|
@ -15,8 +16,8 @@ impl<'wl, WL: WordList> Solver<'wl, WL> for StupidSolver<'wl, WL> {
|
|||
info!("using stupid solver");
|
||||
Ok(Self { wl: wordlist })
|
||||
}
|
||||
fn guess_for(&self, game: &crate::game::Game<WL>) -> Word {
|
||||
self.wl.rand_word().0
|
||||
fn guess_for(&self, game: &crate::game::Game<WL>) -> WResult<Word> {
|
||||
Ok(self.wl.rand_word().0)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue