master
Mark 2024-03-04 18:39:59 -08:00
parent 99b9ee975a
commit a35ba24a13
Signed by: Mark
GPG Key ID: C6D63995FE72FD80
6 changed files with 56 additions and 79 deletions

View File

@ -50,8 +50,8 @@ impl DiffuseAgent {
let mut max_dist = *dist.iter().max().unwrap(); let mut max_dist = *dist.iter().max().unwrap();
loop { loop {
for pos in 0..11 { for (pos, d) in dist.iter().enumerate() {
if dist[pos] >= max_dist { if *d >= max_dist {
let action = PlayerAction { symb, pos }; let action = PlayerAction { symb, pos };
if board.can_play(&action) { if board.can_play(&action) {
return action; return action;
@ -72,14 +72,13 @@ impl MinimizerAgent for DiffuseAgent {
fn step_min(&mut self, board: &Board) -> Result<PlayerAction> { fn step_min(&mut self, board: &Board) -> Result<PlayerAction> {
let symb = [Symb::Minus, Symb::Times, Symb::Plus, Symb::Div] let symb = [Symb::Minus, Symb::Times, Symb::Plus, Symb::Div]
.iter() .iter()
.filter(|x| !board.contains(**x)) .find(|x| !board.contains(**x));
.next();
if symb.is_none() { if let Some(symb) = symb {
Ok(self.step_symb(board, *symb))
} else {
// No symbols available, play a random number // No symbols available, play a random number
RandomAgent {}.step_min(board) RandomAgent {}.step_min(board)
} else {
Ok(self.step_symb(board, *symb.unwrap()))
} }
} }
} }

View File

@ -92,7 +92,7 @@ impl PlayerAgent {
self.symbol_selector.check(board); self.symbol_selector.check(board);
// Ask for input until we get a valid move // Ask for input until we get a valid move
'outer: loop { loop {
print!( print!(
"\r{}{}{} ╙{}{}{}{}{}╜", "\r{}{}{} ╙{}{}{}{}{}╜",
// Goal // Goal
@ -119,14 +119,22 @@ impl PlayerAgent {
Key::Char('q') => bail!("player ended game"), Key::Char('q') => bail!("player ended game"),
Key::Right => { Key::Right => {
self.cursor = cursor_max.min(self.cursor + 1); self.cursor = cursor_max.min(self.cursor + 1);
break;
} }
Key::Left => { Key::Left => {
if self.cursor != 0 { if self.cursor != 0 {
self.cursor -= 1; self.cursor -= 1;
} }
break;
}
Key::Up => {
self.symbol_selector.up(board);
break;
}
Key::Down => {
self.symbol_selector.down(board);
break;
} }
Key::Up => self.symbol_selector.up(board),
Key::Down => self.symbol_selector.down(board),
Key::Char('\n') => { Key::Char('\n') => {
let symb = Symb::from_char(self.symbol_selector.current()); let symb = Symb::from_char(self.symbol_selector.current());
if let Some(symb) = symb { if let Some(symb) = symb {
@ -138,6 +146,7 @@ impl PlayerAgent {
return Ok(action); return Ok(action);
} }
} }
break;
} }
Key::Char(c) => { Key::Char(c) => {
let symb = Symb::from_char(c); let symb = Symb::from_char(c);
@ -150,10 +159,10 @@ impl PlayerAgent {
return Ok(action); return Ok(action);
} }
} }
break;
} }
_ => {} _ => {}
}; };
continue 'outer;
} }
} }
} }

View File

@ -5,11 +5,38 @@ use termion::color;
use super::{PlayerAction, TreeElement}; use super::{PlayerAction, TreeElement};
use crate::util::{Player, Symb}; use crate::util::{Player, Symb};
#[derive(Debug)]
enum InterTreeElement { enum InterTreeElement {
Unprocessed(Token), Unprocessed(Token),
Processed(TreeElement), Processed(TreeElement),
} }
impl InterTreeElement {
fn to_value(&self) -> TreeElement {
match self {
InterTreeElement::Processed(x) => x.clone(),
InterTreeElement::Unprocessed(Token::Value(s)) => {
if let Some(s) = s.strip_prefix('-') {
TreeElement::Neg {
r: {
if s.contains('_') {
Box::new(TreeElement::Partial(s.to_string()))
} else {
Box::new(TreeElement::Number(s.parse().unwrap()))
}
},
}
} else if s.contains('_') {
TreeElement::Partial(s.to_string())
} else {
TreeElement::Number(s.parse().unwrap())
}
}
_ => unreachable!(),
}
}
}
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
enum Token { enum Token {
Value(String), Value(String),
@ -71,13 +98,11 @@ impl Board {
} }
pub fn contains(&self, s: Symb) -> bool { pub fn contains(&self, s: Symb) -> bool {
for i in &self.board { for i in self.board.iter().flatten() {
if let Some(i) = i {
if i.0 == s { if i.0 == s {
return true; return true;
} }
} }
}
false false
} }
@ -233,56 +258,8 @@ impl Board {
_ => false, _ => false,
} { } {
did_something = true; did_something = true;
let l = &tree[i - 1]; let l = tree[i - 1].to_value();
let r = &tree[i + 1]; let r = tree[i + 1].to_value();
let l = match l {
InterTreeElement::Processed(x) => x.clone(),
InterTreeElement::Unprocessed(Token::Value(s)) => {
if s.starts_with('-') {
TreeElement::Neg {
r: {
if s.contains('_') {
Box::new(TreeElement::Partial(s[1..].to_string()))
} else {
Box::new(TreeElement::Number(s[1..].parse().unwrap()))
}
},
}
} else {
if s.contains('_') {
TreeElement::Partial(s.to_string())
} else {
TreeElement::Number(s.parse().unwrap())
}
}
}
_ => unreachable!(),
};
let r = match r {
InterTreeElement::Processed(x) => x.clone(),
InterTreeElement::Unprocessed(Token::Value(s)) => {
if s.starts_with('-') {
TreeElement::Neg {
r: {
if s.contains('_') {
Box::new(TreeElement::Partial(s[1..].to_string()))
} else {
Box::new(TreeElement::Number(s[1..].parse().unwrap()))
}
},
}
} else {
if s.contains('_') {
TreeElement::Partial(s.to_string())
} else {
TreeElement::Number(s.parse().unwrap())
}
}
}
_ => unreachable!(),
};
let v = match tree[i] { let v = match tree[i] {
InterTreeElement::Unprocessed(Token::OpAdd) => TreeElement::Add { InterTreeElement::Unprocessed(Token::OpAdd) => TreeElement::Add {
@ -318,7 +295,7 @@ impl Board {
match tree.into_iter().next().unwrap() { match tree.into_iter().next().unwrap() {
InterTreeElement::Processed(x) => x, InterTreeElement::Processed(x) => x,
_ => unreachable!(), x => x.to_value(),
} }
} }
@ -337,10 +314,8 @@ impl Board {
.filter_map(|c| { .filter_map(|c| {
if c == '_' { if c == '_' {
Some(None) Some(None)
} else if let Some(symb) = Symb::from_char(c) {
Some(Some((symb, current_player)))
} else { } else {
None Symb::from_char(c).map(|s| Some((s, current_player)))
} }
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();

View File

@ -1,3 +1,4 @@
#[allow(clippy::module_inception)]
mod board; mod board;
mod tree; mod tree;

View File

@ -132,11 +132,7 @@ impl TreeElement {
} }
Self::Neg { r } => { Self::Neg { r } => {
let r = r.evaluate(); let r = r.evaluate();
if let Some(r) = r { r.map(|r| -r)
Some(-r)
} else {
None
}
} }
} }
} }

View File

@ -62,10 +62,7 @@ impl Debug for Symb {
impl Symb { impl Symb {
/// Is this symbol a plain binary operator? /// Is this symbol a plain binary operator?
pub fn is_op(&self) -> bool { pub fn is_op(&self) -> bool {
match self { matches!(self, Symb::Div | Symb::Plus | Symb::Times | Symb::Minus)
Symb::Div | Symb::Plus | Symb::Times | Symb::Minus => true,
_ => false,
}
} }
pub fn is_minus(&self) -> bool { pub fn is_minus(&self) -> bool {