generated from PlexSheep/rs-base
add interactive solver #4
|
@ -44,21 +44,31 @@ struct Cli {
|
||||||
enum ReplCommand {
|
enum ReplCommand {
|
||||||
/// Let the user input the response to the last guess
|
/// Let the user input the response to the last guess
|
||||||
///
|
///
|
||||||
/// Format:
|
Response { encoded: String },
|
||||||
|
/// Let the user input a word and the response for that word
|
||||||
|
///
|
||||||
|
/// Evaluation Format:
|
||||||
///
|
///
|
||||||
/// 'x' means wrong character
|
/// 'x' means wrong character
|
||||||
///
|
///
|
||||||
/// 'p' means present character
|
/// 'p' means present character
|
||||||
///
|
///
|
||||||
/// 'c' means correct character
|
/// 'c' means correct character
|
||||||
Response { encoded: String },
|
///
|
||||||
/// Let the user input a word and the response for that word
|
/// Example:
|
||||||
|
///
|
||||||
|
/// 'xxxcc' means the first 3 chars are wrong but the second 2 chars are correct
|
||||||
|
///
|
||||||
|
/// 'xppxc' means the first character is wrong, the next two characters are present, the last
|
||||||
|
/// is correct
|
||||||
Guess {
|
Guess {
|
||||||
your_guess: String,
|
your_guess: String,
|
||||||
evalutation: Evaluation,
|
evalutation: Evaluation,
|
||||||
},
|
},
|
||||||
/// Let the solver make a guess
|
/// Let the solver make a guess
|
||||||
Solve,
|
Solve,
|
||||||
|
/// Show the current state of the game
|
||||||
|
Show,
|
||||||
/// Leave the Repl
|
/// Leave the Repl
|
||||||
Exit,
|
Exit,
|
||||||
}
|
}
|
||||||
|
@ -114,11 +124,24 @@ fn help_guess_interactive(cli: Cli) -> anyhow::Result<()> {
|
||||||
// only None if the repl has not stepped yet
|
// only None if the repl has not stepped yet
|
||||||
match repl.command().to_owned().unwrap() {
|
match repl.command().to_owned().unwrap() {
|
||||||
ReplCommand::Exit => break,
|
ReplCommand::Exit => break,
|
||||||
|
ReplCommand::Show => {
|
||||||
|
println!("{}", game);
|
||||||
|
}
|
||||||
|
ReplCommand::Solve => {
|
||||||
|
let best_guess = solver.guess_for(&game);
|
||||||
|
println!("best guess: {best_guess}");
|
||||||
|
}
|
||||||
ReplCommand::Guess {
|
ReplCommand::Guess {
|
||||||
your_guess,
|
your_guess,
|
||||||
evalutation,
|
evalutation,
|
||||||
} => {
|
} => {
|
||||||
println!("{}", game.guess(your_guess, Some(evalutation))?)
|
let guess = game.guess(your_guess, Some(evalutation));
|
||||||
|
if guess.is_err() {
|
||||||
|
eprintln!("{}", style(guess.unwrap_err()).red().bold());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
println!("{}", guess.unwrap());
|
||||||
|
debug!("current gamestate: {game:#?}");
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
use std::convert::Infallible;
|
use std::convert::Infallible;
|
||||||
|
use std::fmt::Display;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use libpt::cli::console::{style, StyledObject};
|
||||||
|
|
||||||
|
use crate::wlist::word::Word;
|
||||||
|
|
||||||
use super::response::Status;
|
use super::response::Status;
|
||||||
|
|
||||||
pub type EvaluationUnit = (char, Status);
|
pub type EvaluationUnit = (char, Status);
|
||||||
|
@ -10,6 +15,23 @@ pub struct Evaluation {
|
||||||
inner: Vec<EvaluationUnit>,
|
inner: Vec<EvaluationUnit>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Evaluation {
|
||||||
|
pub(crate) fn colorized_display(&self, guess: &Word) -> Vec<StyledObject<String>> {
|
||||||
|
assert_eq!(guess.len(), self.inner.len());
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
for (i, e) in self.inner.iter().enumerate() {
|
||||||
|
let mut c = style(guess.chars().nth(i).unwrap().to_string());
|
||||||
|
if e.1 == Status::Matched {
|
||||||
|
c = c.green();
|
||||||
|
} else if e.1 == Status::Exists {
|
||||||
|
c = c.yellow();
|
||||||
|
}
|
||||||
|
buf.push(c);
|
||||||
|
}
|
||||||
|
buf
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl IntoIterator for Evaluation {
|
impl IntoIterator for Evaluation {
|
||||||
type Item = EvaluationUnit;
|
type Item = EvaluationUnit;
|
||||||
type IntoIter = std::vec::IntoIter<Self::Item>;
|
type IntoIter = std::vec::IntoIter<Self::Item>;
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
use core::panic;
|
use core::panic;
|
||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
use crate::error::*;
|
use crate::error::*;
|
||||||
use crate::wlist::word::{ManyWordsRef, Word, WordData};
|
use crate::wlist::word::{ManyWordsRef, Word, WordData};
|
||||||
use crate::wlist::WordList;
|
use crate::wlist::WordList;
|
||||||
|
|
||||||
|
use libpt::cli::console::StyledObject;
|
||||||
use libpt::log::{debug, trace};
|
use libpt::log::{debug, trace};
|
||||||
|
|
||||||
pub mod response;
|
pub mod response;
|
||||||
|
@ -13,6 +15,7 @@ pub mod evaluation;
|
||||||
|
|
||||||
pub mod summary;
|
pub mod summary;
|
||||||
|
|
||||||
|
use self::evaluation::Evaluation;
|
||||||
use self::response::Status;
|
use self::response::Status;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
@ -271,3 +274,28 @@ impl<'wl, WL: WordList> GameBuilder<'wl, WL> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'wl, WL: WordList> Display for Game<'wl, WL> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
// TODO: make this actually useful
|
||||||
|
// TODO: make this actually fancy
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"turn:\t\t{}\nsolution:\t{:?}\nguesses:\t",
|
||||||
|
self.step(),
|
||||||
|
self.solution(),
|
||||||
|
)?;
|
||||||
|
for s in self
|
||||||
|
.responses()
|
||||||
|
.iter()
|
||||||
|
.map(|v| v.evaluation().to_owned().colorized_display(v.guess()))
|
||||||
|
{
|
||||||
|
write!(f, "\"")?;
|
||||||
|
for si in s {
|
||||||
|
write!(f, "{si}")?;
|
||||||
|
}
|
||||||
|
write!(f, "\", ")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue