From 3bce3b01cab25b39d48247a959e4d8070dc59392 Mon Sep 17 00:00:00 2001 From: folkengine Date: Sat, 9 May 2026 11:03:32 -0700 Subject: [PATCH 1/2] =?UTF-8?q?Features=20/=20Changes=20(staged,=20not=20y?= =?UTF-8?q?et=20committed)=20=20=20-=20Cargo.toml=20/=20Cargo.lock=20?= =?UTF-8?q?=E2=80=94=20dependency=20updates=20=20=20-=20src/game/state.rs?= =?UTF-8?q?=20=E2=80=94=20game=20state=20changes=20=20=20-=20src/wasm=5Fap?= =?UTF-8?q?i.rs=20=E2=80=94=20WASM=20API=20modifications?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/game/state.rs | 17 +++++++++++++++++ src/wasm_api.rs | 28 +++++++++++++++++++++++++++- 4 files changed, 46 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5cc44cf..f658daa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -303,7 +303,7 @@ dependencies = [ [[package]] name = "gfcore" -version = "0.0.1" +version = "0.0.2" dependencies = [ "cardpack", "console_error_panic_hook", diff --git a/Cargo.toml b/Cargo.toml index 06a31c8..a59d9f1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "gfcore" description = "Go Fish card game engine" -version = "0.0.1" +version = "0.0.2" edition = "2024" rust-version = "1.85" license = "MIT OR Apache-2.0" diff --git a/src/game/state.rs b/src/game/state.rs index 245020a..dc7d781 100644 --- a/src/game/state.rs +++ b/src/game/state.rs @@ -401,6 +401,23 @@ impl Game { }) } + /// Like [`state`] but always reveals `observer`'s hand regardless of whose + /// turn it is. Used by the WASM layer so the human's hand stays visible + /// throughout bot turns. + pub fn state_as_observer(&self, observer: usize) -> Result { + let players = PlayerView::from_perspective(&self.players, observer)?; + + Ok(GameState { + phase: self.phase.clone(), + current_player: self.current_player, + players, + draw_pile_size: self.draw_pile.len(), + last_event: self.last_event.clone(), + winner: self.winner, + ask_log: self.ask_log.clone(), + }) + } + /// Returns the index of the player whose turn it is. /// /// # Examples diff --git a/src/wasm_api.rs b/src/wasm_api.rs index b11904f..71c09f0 100644 --- a/src/wasm_api.rs +++ b/src/wasm_api.rs @@ -301,6 +301,26 @@ pub fn get_state() -> String { }) } +/// Like [`get_state`] but always returns state from player 0's perspective so +/// the human hand remains visible during bot turns. +#[must_use] +#[wasm_bindgen] +pub fn get_human_state() -> String { + GAME.with(|cell| { + let borrow = cell.borrow(); + match borrow.as_ref() { + None => error_json("no game in progress"), + Some(game) => match game.state_as_observer(0) { + Ok(s) => match serde_json::to_string(&s) { + Ok(j) => j, + Err(e) => error_json(&e.to_string()), + }, + Err(e) => error_json(&e.to_string()), + }, + } + }) +} + /// If the current player is a bot, computes and applies their action. /// /// Returns: @@ -359,6 +379,12 @@ pub fn step_bot() -> String { profile.decide(&hand, &state.players, &state.ask_log) }; + // Serialize the action before it is consumed by game.act(). + let action_json = match serde_json::to_string(&action) { + Ok(j) => j, + Err(e) => return error_json(&e.to_string()), + }; + // Apply the action. let event_json = GAME.with(|cell| { let mut borrow = cell.borrow_mut(); @@ -383,7 +409,7 @@ pub fn step_bot() -> String { return event_json; } - format!("{{\"done\":false,\"event\":{event_json}}}") + format!("{{\"done\":false,\"player\":{current_player},\"action\":{action_json},\"event\":{event_json}}}") } /// Returns the full game history as YAML. From 8fc78d3167dd33ecfe1525f9e5d9a2be2ef4b0da Mon Sep 17 00:00:00 2001 From: folkengine Date: Sat, 9 May 2026 11:26:26 -0700 Subject: [PATCH 2/2] clippy and fmt --- src/game/state.rs | 6 +++++- src/wasm_api.rs | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/game/state.rs b/src/game/state.rs index dc7d781..74a71d5 100644 --- a/src/game/state.rs +++ b/src/game/state.rs @@ -401,9 +401,13 @@ impl Game { }) } - /// Like [`state`] but always reveals `observer`'s hand regardless of whose + /// Like [`Self::state`] but always reveals `observer`'s hand regardless of whose /// turn it is. Used by the WASM layer so the human's hand stays visible /// throughout bot turns. + /// + /// # Errors + /// + /// Returns [`GfError::InvalidTarget`] if `observer` is out of range for the current player list. pub fn state_as_observer(&self, observer: usize) -> Result { let players = PlayerView::from_perspective(&self.players, observer)?; diff --git a/src/wasm_api.rs b/src/wasm_api.rs index 71c09f0..ad6f40e 100644 --- a/src/wasm_api.rs +++ b/src/wasm_api.rs @@ -409,7 +409,9 @@ pub fn step_bot() -> String { return event_json; } - format!("{{\"done\":false,\"player\":{current_player},\"action\":{action_json},\"event\":{event_json}}}") + format!( + "{{\"done\":false,\"player\":{current_player},\"action\":{action_json},\"event\":{event_json}}}" + ) } /// Returns the full game history as YAML.