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();
loop {
for pos in 0..11 {
if dist[pos] >= max_dist {
for (pos, d) in dist.iter().enumerate() {
if *d >= max_dist {
let action = PlayerAction { symb, pos };
if board.can_play(&action) {
return action;
@ -72,14 +72,13 @@ impl MinimizerAgent for DiffuseAgent {
fn step_min(&mut self, board: &Board) -> Result<PlayerAction> {
let symb = [Symb::Minus, Symb::Times, Symb::Plus, Symb::Div]
.iter()
.filter(|x| !board.contains(**x))
.next();
.find(|x| !board.contains(**x));
if symb.is_none() {
if let Some(symb) = symb {
Ok(self.step_symb(board, *symb))
} else {
// No symbols available, play a random number
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);
// Ask for input until we get a valid move
'outer: loop {
loop {
print!(
"\r{}{}{} ╙{}{}{}{}{}╜",
// Goal
@ -119,14 +119,22 @@ impl PlayerAgent {
Key::Char('q') => bail!("player ended game"),
Key::Right => {
self.cursor = cursor_max.min(self.cursor + 1);
break;
}
Key::Left => {
if self.cursor != 0 {
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') => {
let symb = Symb::from_char(self.symbol_selector.current());
if let Some(symb) = symb {
@ -138,6 +146,7 @@ impl PlayerAgent {
return Ok(action);
}
}
break;
}
Key::Char(c) => {
let symb = Symb::from_char(c);
@ -150,10 +159,10 @@ impl PlayerAgent {
return Ok(action);
}
}
break;
}
_ => {}
};
continue 'outer;
}
}
}

View File

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

View File

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

View File

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

View File

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