From 7a3249e7668faf9b665f0d8c8f9f8843cab410ae Mon Sep 17 00:00:00 2001 From: Mark Date: Sun, 3 Mar 2024 21:48:41 -0800 Subject: [PATCH] Fied evaluator bug --- src/board.rs | 108 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 93 insertions(+), 15 deletions(-) diff --git a/src/board.rs b/src/board.rs index 90b226d..a0afe73 100644 --- a/src/board.rs +++ b/src/board.rs @@ -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> { + 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,12 +96,8 @@ impl Board { Some(_) => return false, None => { // Check for duplicate symbols - for i in &self.board { - if let Some(i) = i { - if i.0 == symb { - return false; - } - } + if self.contains(symb) { + return false; } // Check syntax @@ -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 { + 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::>(); + + 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, + }) } }