Fied evaluator bug

master
Mark 2024-03-03 21:48:41 -08:00
parent a5e3998727
commit 7a3249e766
Signed by: Mark
GPG Key ID: C6D63995FE72FD80
1 changed files with 93 additions and 15 deletions

View File

@ -1,4 +1,4 @@
use std::fmt::Display;
use std::{fmt::Display, num::NonZeroU8};
use termion::color;
use crate::{Player, Symb};
@ -47,6 +47,7 @@ impl Display for Board {
}
}
#[allow(dead_code)]
impl Board {
pub fn new(current_player: Player) -> Self {
Self {
@ -56,6 +57,14 @@ impl Board {
}
}
pub fn iter(&self) -> impl Iterator<Item = &Option<(Symb, Player)>> {
self.board.iter()
}
pub fn get(&self, idx: usize) -> Option<&Option<(Symb, Player)>> {
self.board.get(idx)
}
pub fn current_player(&self) -> Player {
self.current_player
}
@ -68,6 +77,18 @@ impl Board {
self.board.len()
}
pub fn contains(&self, s: Symb) -> bool {
for i in &self.board {
if let Some(i) = i {
if i.0 == s {
return true;
}
}
}
false
}
// Place the marked symbol at the given position.
// Returns true for valid moves and false otherwise.
pub fn play(&mut self, cursor: usize, symb: Symb) -> bool {
@ -75,13 +96,9 @@ impl Board {
Some(_) => return false,
None => {
// Check for duplicate symbols
for i in &self.board {
if let Some(i) = i {
if i.0 == symb {
if self.contains(symb) {
return false;
}
}
}
// Check syntax
match symb {
@ -91,7 +108,7 @@ impl Board {
}
let r = &self.board[cursor + 1];
if r.is_some_and(|(s, _)| s.is_binop()) {
if r.is_some_and(|(s, _)| s.is_op() && !s.is_minus()) {
return false;
}
}
@ -117,9 +134,7 @@ impl Board {
return false;
}
if l.is_some_and(|s| s.is_binop() || s.is_minus())
|| r.is_some_and(|s| s.is_binop())
{
if l.is_some_and(|s| s.is_op()) {
return false;
}
}
@ -192,13 +207,21 @@ impl Board {
tokens.push(Token::Number(current_num * current_sgn));
for op in [Token::OpMult, Token::OpDiv, Token::OpAdd, Token::OpSub] {
let mut priority_level = 0;
let mut did_something;
while tokens.len() > 1 {
did_something = false;
for i in 0..tokens.len() {
if tokens[i] == op {
if match priority_level {
0 => matches!(tokens[i], Token::OpMult | Token::OpDiv),
1 => matches!(tokens[i], Token::OpAdd | Token::OpSub),
_ => false,
} {
did_something = true;
let l = &tokens[i - 1];
let r = &tokens[i + 1];
let v = match op {
let v = match tokens[i] {
Token::OpAdd => l.val() + r.val(),
Token::OpDiv => l.val() / r.val(),
Token::OpSub => l.val() - r.val(),
@ -212,8 +235,63 @@ impl Board {
break;
}
}
if !did_something {
priority_level += 1;
}
}
return Some(tokens[0].val());
Some(tokens[0].val())
}
/// Hacky method to parse a board from a string
pub fn from_string(s: &str, current_player: Player) -> Option<Self> {
if s.len() != 11 {
return None;
}
let x = s
.chars()
.filter_map(|c| {
let symb = match c {
'+' => Symb::Plus,
'-' => Symb::Minus,
'*' => Symb::Times,
'/' => Symb::Div,
'0' => Symb::Zero,
'1' => Symb::Number(NonZeroU8::new(1).unwrap()),
'2' => Symb::Number(NonZeroU8::new(2).unwrap()),
'3' => Symb::Number(NonZeroU8::new(3).unwrap()),
'4' => Symb::Number(NonZeroU8::new(4).unwrap()),
'5' => Symb::Number(NonZeroU8::new(5).unwrap()),
'6' => Symb::Number(NonZeroU8::new(6).unwrap()),
'7' => Symb::Number(NonZeroU8::new(7).unwrap()),
'8' => Symb::Number(NonZeroU8::new(8).unwrap()),
'9' => Symb::Number(NonZeroU8::new(9).unwrap()),
'_' => return Some(None),
_ => return None,
};
Some(Some((symb, current_player)))
})
.collect::<Vec<_>>();
if x.len() != 11 {
return None;
}
let mut free_spots = 11;
let mut board = [None; 11];
for i in 0..x.len() {
board[i] = x[i];
if x[i].is_some() {
free_spots -= 1;
}
}
Some(Self {
board,
free_spots,
current_player,
})
}
}