From 42323410f54ce4f5cc645044325f198c3318f33d Mon Sep 17 00:00:00 2001 From: "Christoph J. Scherr" Date: Mon, 22 Jul 2024 16:06:41 +0200 Subject: [PATCH] feat(solver): show the gamestate --- src/bin/solve/simple.rs | 31 +++++++++++++++++++++++++++---- src/game/evaluation.rs | 22 ++++++++++++++++++++++ src/game/mod.rs | 28 ++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 4 deletions(-) diff --git a/src/bin/solve/simple.rs b/src/bin/solve/simple.rs index c5573b1..d0d13cf 100644 --- a/src/bin/solve/simple.rs +++ b/src/bin/solve/simple.rs @@ -44,21 +44,31 @@ struct Cli { enum ReplCommand { /// 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 /// /// 'p' means present 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 { your_guess: String, evalutation: Evaluation, }, /// Let the solver make a guess Solve, + /// Show the current state of the game + Show, /// Leave the Repl Exit, } @@ -114,11 +124,24 @@ fn help_guess_interactive(cli: Cli) -> anyhow::Result<()> { // only None if the repl has not stepped yet match repl.command().to_owned().unwrap() { ReplCommand::Exit => break, + ReplCommand::Show => { + println!("{}", game); + } + ReplCommand::Solve => { + let best_guess = solver.guess_for(&game); + println!("best guess: {best_guess}"); + } ReplCommand::Guess { your_guess, 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!(), } diff --git a/src/game/evaluation.rs b/src/game/evaluation.rs index 5f3b778..1fa7603 100644 --- a/src/game/evaluation.rs +++ b/src/game/evaluation.rs @@ -1,6 +1,11 @@ use std::convert::Infallible; +use std::fmt::Display; use std::str::FromStr; +use libpt::cli::console::{style, StyledObject}; + +use crate::wlist::word::Word; + use super::response::Status; pub type EvaluationUnit = (char, Status); @@ -10,6 +15,23 @@ pub struct Evaluation { inner: Vec, } +impl Evaluation { + pub(crate) fn colorized_display(&self, guess: &Word) -> Vec> { + 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 { type Item = EvaluationUnit; type IntoIter = std::vec::IntoIter; diff --git a/src/game/mod.rs b/src/game/mod.rs index ec3f626..bcbfdb3 100644 --- a/src/game/mod.rs +++ b/src/game/mod.rs @@ -1,9 +1,11 @@ use core::panic; +use std::fmt::Display; use crate::error::*; use crate::wlist::word::{ManyWordsRef, Word, WordData}; use crate::wlist::WordList; +use libpt::cli::console::StyledObject; use libpt::log::{debug, trace}; pub mod response; @@ -13,6 +15,7 @@ pub mod evaluation; pub mod summary; +use self::evaluation::Evaluation; use self::response::Status; #[derive(Debug, Clone, PartialEq)] @@ -271,3 +274,28 @@ impl<'wl, WL: WordList> GameBuilder<'wl, WL> { 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(()) + } +}