From e23c1d139b9eed12b4f160d37041aabd5d81cc0e Mon Sep 17 00:00:00 2001 From: Joel Therrien Date: Thu, 7 Sep 2023 19:44:07 -0700 Subject: [PATCH] Add capability to convert AI plays into PlayedTiles vector --- src/game.rs | 16 +++-------- src/player_interaction/ai.rs | 56 +++++++++++++++++++++++++++++++++--- 2 files changed, 56 insertions(+), 16 deletions(-) diff --git a/src/game.rs b/src/game.rs index 45b1251..751313e 100644 --- a/src/game.rs +++ b/src/game.rs @@ -33,11 +33,11 @@ pub struct PlayerState { pub tray: Tray } -#[derive(Deserialize, Tsify, Copy, Clone)] +#[derive(Deserialize, Tsify, Copy, Clone, Debug)] #[tsify(from_wasm_abi)] pub struct PlayedTile { - index: usize, - character: Option, + pub index: usize, + pub character: char, } #[derive(Debug, Serialize, Deserialize, Tsify)] @@ -164,15 +164,7 @@ impl Game { let coord = Coordinates::new_from_index(played_tile.index); if letter.is_blank { - match played_tile.character { - None => { - panic!("You can't play a blank character without providing a letter value") - } - Some(x) => { - // TODO - I should check that the character is a valid letter - letter.text = x; - } - } + letter.text = played_tile.character; } played_letters.push((letter, coord)); diff --git a/src/player_interaction/ai.rs b/src/player_interaction/ai.rs index ab34fd9..fb9aec1 100644 --- a/src/player_interaction/ai.rs +++ b/src/player_interaction/ai.rs @@ -3,6 +3,7 @@ use rand::Rng; use crate::board::{Board, CellType, Coordinates, Direction, Letter}; use crate::constants::GRID_LENGTH; use crate::dictionary::DictionaryImpl; +use crate::game::PlayedTile; use crate::player_interaction::Tray; const ALPHABET: [char; 26] = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']; @@ -51,6 +52,47 @@ pub struct CompleteMove { score: u32, } +impl CompleteMove { + + pub fn convert_to_play(&self, tray: &Tray) -> Vec> { + let mut played_tiles = Vec::with_capacity(tray.letters.len()); + let mut moves = self.moves.iter() + .map(|m| Some(m.clone())) + .collect::>>(); + + tray.letters.iter().for_each(|letter| { + match letter { + None => { + played_tiles.push(None); + } + Some(letter) => { + let mut found_match = false; + // see if we can find a match in moves + for m in moves.iter_mut() { + match m { + Some(x) => { + if letter.partial_match(&x.letter) { + played_tiles.push(Some(PlayedTile { + index: x.coordinates.map_to_index(), + character: x.letter.text, + })); + *m = None; + found_match = true; + break; + } + }, + None => {} + } + } + assert!(found_match); + } + } + }); + + played_tiles + } +} + #[derive(Clone)] struct MoveScoring { main_scoring: u32, @@ -827,7 +869,7 @@ mod tests { ephemeral: false, is_blank: false, }); - tray.letters[2] = Some(Letter{ + tray.letters[6] = Some(Letter{ text: 'A', points: 1, ephemeral: false, @@ -848,19 +890,25 @@ mod tests { assert!(end_of_boat.is_some()); assert_eq!(end_of_boat.as_ref().unwrap().len(), 1); - //let rng = SmallRng::seed_from_u64(123); - let moves = ai.find_all_moves(&tray, &board); println!("Moves are {:?}", moves); - // 2 possible moves - + // 3 possible moves - // 1. put 'S' at the end of 'BOAT' and form words 'SLAM' and 'BOATS' // 2. Put 'S' at end of 'BOAT' // 3. Put 'SL' to left of 'A' in 'BOAT' and then 'M' to right of it assert_eq!(moves.len(), 3); + let mut rng = SmallRng::seed_from_u64(123); + let best_move = ai.find_best_move(&tray, &board, &mut rng).unwrap(); + + assert_eq!(best_move.score, 23); + + let play = best_move.convert_to_play(&tray); + println!("Play is {:?}", play); + } #[test]