From ca5ab097c57938c2fb275d9d4e38953baa2d0568 Mon Sep 17 00:00:00 2001 From: Joel Therrien Date: Tue, 22 Aug 2023 20:52:03 -0700 Subject: [PATCH] Add basic tile exchange support Still need to support handling if the player reordered their tray --- src/game.rs | 98 +++++++++++++++++++++++++++++++-------------- src/wasm.rs | 28 ++++++++++++- ui/src/elements.tsx | 44 +++++++++++++++++--- 3 files changed, 132 insertions(+), 38 deletions(-) diff --git a/src/game.rs b/src/game.rs index a76108f..a45dda5 100644 --- a/src/game.rs +++ b/src/game.rs @@ -47,10 +47,42 @@ pub struct WordResult { score: u32, } +pub struct PlayerStates(pub Vec); +impl PlayerStates { + pub fn get_player_state(&self, name: &str) -> Option<&PlayerState> { + self.0.iter() + .filter(|state| state.player.get_name().eq(name)) + .nth(0) + + } + + pub fn get_player_state_mut(&mut self, name: &str) -> Option<&mut PlayerState> { + self.0.iter_mut() + .filter(|state| state.player.get_name().eq(name)) + .nth(0) + + } + + pub fn get_tray(&self, name: &str) -> Option<&Tray> { + let player = self.get_player_state(name)?; + + Some(&player.tray) + + } + + pub fn get_tray_mut(&mut self, name: &str) -> Option<&mut Tray> { + let player = self.get_player_state_mut(name)?; + + Some(&mut player.tray) + + } +} + pub struct Game{ pub tile_pool: Vec, + rng: SmallRng, board: Board, - pub player_states: Vec, + pub player_states: PlayerStates, dictionary: DictionaryImpl, } @@ -85,39 +117,14 @@ impl Game { Game { tile_pool: letters, + rng, board: Board::new(), - player_states, + player_states: PlayerStates(player_states), dictionary: DictionaryImpl::create_from_str(dictionary_text) } } - pub fn get_player_state(&self, name: &str) -> Option<&PlayerState> { - self.player_states.iter() - .filter(|state| state.player.get_name().eq(name)) - .nth(0) - } - - pub fn get_player_state_mut(&mut self, name: &str) -> Option<&mut PlayerState> { - self.player_states.iter_mut() - .filter(|state| state.player.get_name().eq(name)) - .nth(0) - - } - - pub fn get_tray(&self, name: &str) -> Option<&Tray> { - let player = self.get_player_state(name)?; - - Some(&player.tray) - - } - - pub fn get_tray_mut(&mut self, name: &str) -> Option<&mut Tray> { - let player = self.get_player_state_mut(name)?; - - Some(&mut player.tray) - - } pub fn get_board(&self) -> &Board {&self.board} @@ -126,7 +133,7 @@ impl Game { } pub fn fill_trays(&mut self){ - for state in self.player_states.iter_mut() { + for state in self.player_states.0.iter_mut() { let tray = &mut state.tray; tray.fill(&mut self.tile_pool); } @@ -139,7 +146,7 @@ impl Game { pub fn receive_play(&mut self, player: &str, tray_tile_locations: Vec>, commit_move: bool) -> Result, String> { let mut board_instance = self.get_board().clone(); - let mut tray = self.get_tray(player).unwrap().clone(); + let mut tray = self.player_states.get_tray(player).unwrap().clone(); let mut played_letters: Vec<(Letter, Coordinates)> = Vec::new(); for (i, played_tile) in tray_tile_locations.iter().enumerate() { @@ -181,7 +188,7 @@ impl Game { .collect(); if commit_move { - let mut player_state = self.get_player_state_mut(player).unwrap(); + let mut player_state = self.player_states.get_player_state_mut(player).unwrap(); player_state.score += x.1; player_state.tray = tray; @@ -193,4 +200,33 @@ impl Game { Ok(words) } + pub fn exchange_tiles(&mut self, player: &str, tray_tile_locations: Vec) -> Result { + let tray = match self.player_states.get_tray_mut(player) { + None => {return Err(format!("Player {} not found", player))} + Some(x) => {x} + }; + + if tray.letters.len() != tray_tile_locations.len() { + return Err("Incoming tray and existing tray have different lengths".to_string()); + } + + let tile_pool = &mut self.tile_pool; + + for (i, played_tile) in tray_tile_locations.iter().enumerate() { + if *played_tile { + let letter = tray.letters.get_mut(i).unwrap(); + if letter.is_some() { + tile_pool.push(letter.unwrap().clone()); + *letter = None; + } + } + } + + tile_pool.shuffle(&mut self.rng); + tray.fill(&mut self.tile_pool); + + Ok(tray.clone()) + + } + } \ No newline at end of file diff --git a/src/wasm.rs b/src/wasm.rs index 1e803cb..40c3b8e 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -34,7 +34,7 @@ impl GameWasm { } pub fn get_tray(&self, name: &str) -> Result { - let tray = self.0.get_tray(name); + let tray = self.0.player_states.get_tray(name); serde_wasm_bindgen::to_value(&tray) } @@ -91,7 +91,7 @@ impl GameWasm { score: u32, } - let scores: Vec = self.0.player_states.iter() + let scores: Vec = self.0.player_states.0.iter() .map(|player_state| { PlayerAndScore { name: player_state.player.get_name().to_string(), @@ -103,4 +103,28 @@ impl GameWasm { Ok(serde_wasm_bindgen::to_value(&scores)?) } + + pub fn exchange_tiles(&mut self, player: &str, tray_tile_locations: JsValue) -> Result{ + + let tray_tile_locations: Vec = serde_wasm_bindgen::from_value(tray_tile_locations)?; + + match self.0.exchange_tiles(player, tray_tile_locations) { + Ok(tray) => { + serde_wasm_bindgen::to_value(&MyResult { + response_type: ResponseType::OK, + value: tray + }) + }, + Err(e) => { + serde_wasm_bindgen::to_value(&MyResult { + response_type: ResponseType::ERR, + value: e + }) + } + } + + + } + + } \ No newline at end of file diff --git a/ui/src/elements.tsx b/ui/src/elements.tsx index 1db9dd2..1f3b69b 100644 --- a/ui/src/elements.tsx +++ b/ui/src/elements.tsx @@ -211,11 +211,35 @@ export function Game(props: {wasm: GameWasm, settings: Settings}) { } }, [logInfo]) + function exchangeFunction(selectedArray: Array) { + let numSelected = 0; + selectedArray.forEach((x) => { + if (x){ + numSelected++; + } + }) + + const result: MyResult = props.wasm.exchange_tiles("Player", selectedArray); + console.log({result}); + + if(result.response_type === "ERR") { + logDispatch(
{(result.value as string)}
); + } else { + logDispatch(
You exchanged {numSelected} tiles.
); + setTurnCount(turnCount + 1); + } + + } return <> - +
@@ -275,7 +299,9 @@ export function Game(props: {wasm: GameWasm, settings: Settings}) { }}>{confirmedScorePoints > -1 ? `Score ${confirmedScorePoints} points ✅` : "Check"} - + ; @@ -470,7 +496,12 @@ function Scores(props: {playerScores: Array}){
} -function TileExchangeModal(props: {playerLetters: PlayableLetterData[], isOpen: boolean, setOpen: (isOpen: boolean) => void}) { +function TileExchangeModal(props: { + playerLetters: PlayableLetterData[], + isOpen: boolean, + setOpen: (isOpen: boolean) => void, + exchangeFunction: (selectedArray: Array) => void + }) { function clearExchangeTiles() { const array: boolean[] = []; @@ -479,6 +510,9 @@ function TileExchangeModal(props: {playerLetters: PlayableLetterData[], isOpen: } const [tilesToExchange, setTilesToExchange] = useState(clearExchangeTiles); + useEffect(() => { + setTilesToExchange(clearExchangeTiles()); + }, [props.playerLetters]) let tilesExchangedSelected = 0; for (let i of tilesToExchange) { @@ -518,8 +552,8 @@ function TileExchangeModal(props: {playerLetters: PlayableLetterData[], isOpen: props.setOpen(false); }}>Cancel