From 042975e561fcc5d222948f90f986b1eeb7ddc5b8 Mon Sep 17 00:00:00 2001 From: Tao Tien <29749622+taotien@users.noreply.github.com> Date: Fri, 13 Feb 2026 10:11:17 -0800 Subject: [PATCH 1/2] begin jiang --- Cargo.lock | 8 ++++ Cargo.toml | 2 +- jiang/Cargo.toml | 7 ++++ jiang/src/lib.rs | 68 ++++++++++++++++++++++++++++++++ jong-types/src/lib.rs | 59 ++++++++++++++++++++------- jong/src/game.rs | 4 +- spacetimedb/src/tables/player.rs | 2 + 7 files changed, 134 insertions(+), 16 deletions(-) create mode 100644 jiang/Cargo.toml create mode 100644 jiang/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index fa24bf0..1a86ab2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1229,6 +1229,7 @@ dependencies = [ "bitflags 2.10.0", "color-eyre", "ratatui", + "smol_str", "tracing", ] @@ -3710,6 +3711,13 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +[[package]] +name = "jiang" +version = "0.1.0" +dependencies = [ + "jong-types", +] + [[package]] name = "jni" version = "0.21.1" diff --git a/Cargo.toml b/Cargo.toml index eb2e720..753b960 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace] resolver = "3" -members = ["jong", "jong-types", "spacetimedb"] +members = ["jiang","jong", "jong-types", "spacetimedb"] [workspace.dependencies] jong = { version = "0.1.0", path = "jong" } diff --git a/jiang/Cargo.toml b/jiang/Cargo.toml new file mode 100644 index 0000000..eb1b523 --- /dev/null +++ b/jiang/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "jiang" +version = "0.1.0" +edition = "2024" + +[dependencies] +jong-types.workspace = true diff --git a/jiang/src/lib.rs b/jiang/src/lib.rs new file mode 100644 index 0000000..89010fc --- /dev/null +++ b/jiang/src/lib.rs @@ -0,0 +1,68 @@ +use std::collections::HashMap; + +use jong_types::*; + +// pub fn check_valid() {} + +pub enum Meldable { + Ron, + Chii(Tile, Tile), + Pon, + Kan, +} + +pub fn find_meldables(hand: &[Tile], dealt: Tile) -> Vec { + let counts = hand.iter().fold(HashMap::new(), |mut m, t| { + let e = m.entry(t).or_insert(0); + *e += 1; + m + }); + + let mut calls = vec![]; + + // find pon & kan + if let Some(&count) = counts.get(&dealt) { + if count == 3 { + calls.push(Meldable::Kan) + } else if count == 2 { + calls.push(Meldable::Pon) + } + } + + // find chii + if let Some(next_outer) = dealt.next_rank() { + if let Some(next_inner) = next_outer.next_rank() + && counts.contains_key(&next_outer) + && counts.contains_key(&next_inner) + { + calls.push(Meldable::Chii(next_outer, next_inner)); + } + if let Some(prev_inner) = next_outer.prev_rank() + && counts.contains_key(&next_outer) + && counts.contains_key(&prev_inner) + { + calls.push(Meldable::Chii(next_outer, prev_inner)); + } + } + if let Some(prev_outer) = dealt.prev_rank() + && let Some(prev_inner) = prev_outer.prev_rank() + && counts.contains_key(&prev_outer) + && counts.contains_key(&prev_inner) + { + calls.push(Meldable::Chii(prev_outer, prev_inner)); + } + + // find ron + + calls +} + +fn count_shapes(hand: &[Tile]) { + let hand = if !hand.is_sorted() { + let mut hand = hand.to_vec(); + hand.sort(); + &hand + } else { + hand + }; +} diff --git a/jong-types/src/lib.rs b/jong-types/src/lib.rs index 535a9cd..5b2ad19 100644 --- a/jong-types/src/lib.rs +++ b/jong-types/src/lib.rs @@ -4,7 +4,7 @@ mod derive_alias { Eq = ::core::cmp::PartialEq, ::core::cmp::Eq; Ord = ..Eq, ::core::cmp::PartialOrd, ::core::cmp::PartialEq, ::core::cmp::Ord; - Base = ::core::fmt::Debug, ..Copy, ..Ord; + Base = ::core::fmt::Debug, ..Copy, ..Ord, ::core::hash::Hash; } } use derive_aliases::derive; @@ -13,7 +13,7 @@ use bevy::prelude::*; use spacetimedb::SpacetimeType; use strum::{EnumCount, FromRepr}; -#[derive(..Base, Hash, Default, FromRepr)] +#[derive(..Base, Default, FromRepr)] #[derive(States, SpacetimeType)] pub enum GameState { #[default] @@ -41,18 +41,6 @@ pub enum Suit { Dragon(Dragon), } -impl Suit { - pub fn rank(&self) -> Option { - match self { - Suit::Man(rank) => Some(*rank), - Suit::Pin(rank) => Some(*rank), - Suit::Sou(rank) => Some(*rank), - // Suit::Wind(wind) | Suit::Dragon(dragon) => None, - _ => None, - } - } -} - #[derive( ..Base, Deref, @@ -63,6 +51,49 @@ pub struct Rank { pub number: u8, } +impl Tile { + pub fn next_rank(self) -> Option { + match self.suit { + Suit::Man(rank) if rank.number < 9 => Some(Tile { + suit: Suit::Man(Rank { + number: rank.number + 1, + }), + }), + Suit::Pin(rank) if rank.number < 9 => Some(Tile { + suit: Suit::Pin(Rank { + number: rank.number + 1, + }), + }), + Suit::Sou(rank) if rank.number < 9 => Some(Tile { + suit: Suit::Sou(Rank { + number: rank.number + 1, + }), + }), + _ => None, + } + } + pub fn prev_rank(self) -> Option { + match self.suit { + Suit::Man(rank) if rank.number > 1 => Some(Tile { + suit: Suit::Man(Rank { + number: rank.number - 1, + }), + }), + Suit::Pin(rank) if rank.number > 1 => Some(Tile { + suit: Suit::Pin(Rank { + number: rank.number - 1, + }), + }), + Suit::Sou(rank) if rank.number > 1 => Some(Tile { + suit: Suit::Sou(Rank { + number: rank.number - 1, + }), + }), + _ => None, + } + } +} + #[derive( ..Base, FromRepr, diff --git a/jong/src/game.rs b/jong/src/game.rs index 4f947ba..ded0db7 100644 --- a/jong/src/game.rs +++ b/jong/src/game.rs @@ -227,7 +227,9 @@ fn on_lobby_insert_update( } stdb::TurnState::Menzen => todo!(), stdb::TurnState::RiichiKan => todo!(), - stdb::TurnState::Discard => todo!(), + stdb::TurnState::Discard => { + // TODO check if can call reducer here maybe? + } stdb::TurnState::RonChiiPonKan => todo!(), stdb::TurnState::End => todo!(), } diff --git a/spacetimedb/src/tables/player.rs b/spacetimedb/src/tables/player.rs index f0b2f8a..6b873a0 100644 --- a/spacetimedb/src/tables/player.rs +++ b/spacetimedb/src/tables/player.rs @@ -4,6 +4,7 @@ use spacetimedb::{SpacetimeType, table}; use super::DbTile; // FIXME this shant be public, use views +// TODO split up tables so we aren't sending this over the wire every update, or is differencial handled already #[table(name = player, public)] #[derive(Debug)] pub struct Player { @@ -26,6 +27,7 @@ pub struct Player { pub pond: Vec, pub drawn_tile: Option, + pub actionable: Option<()>, } #[table(name = bot)] From 3143e5964b2025edaafa998941108ca36e681c84 Mon Sep 17 00:00:00 2001 From: Tao Tien <29749622+taotien@users.noreply.github.com> Date: Sat, 14 Feb 2026 20:05:04 -0800 Subject: [PATCH 2/2] --- Cargo.lock | 8 +++++++- jiang/Cargo.toml | 1 + jiang/src/lib.rs | 16 +++++----------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1a86ab2..8df40c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1229,7 +1229,6 @@ dependencies = [ "bitflags 2.10.0", "color-eyre", "ratatui", - "smol_str", "tracing", ] @@ -3338,6 +3337,12 @@ dependencies = [ "byteorder", ] +[[package]] +name = "hashbag" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7040a10f52cba493ddb09926e15d10a9d8a28043708a405931fe4c6f19fac064" + [[package]] name = "hashbrown" version = "0.12.3" @@ -3715,6 +3720,7 @@ checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" name = "jiang" version = "0.1.0" dependencies = [ + "hashbag", "jong-types", ] diff --git a/jiang/Cargo.toml b/jiang/Cargo.toml index eb1b523..eeb2ed3 100644 --- a/jiang/Cargo.toml +++ b/jiang/Cargo.toml @@ -4,4 +4,5 @@ version = "0.1.0" edition = "2024" [dependencies] +hashbag = "0.1.13" jong-types.workspace = true diff --git a/jiang/src/lib.rs b/jiang/src/lib.rs index 89010fc..2a698f7 100644 --- a/jiang/src/lib.rs +++ b/jiang/src/lib.rs @@ -1,11 +1,11 @@ use std::collections::HashMap; +use hashbag::HashBag; use jong_types::*; // pub fn check_valid() {} pub enum Meldable { - Ron, Chii(Tile, Tile), Pon, Kan, @@ -52,17 +52,11 @@ pub fn find_meldables(hand: &[Tile], dealt: Tile) -> Vec { calls.push(Meldable::Chii(prev_outer, prev_inner)); } - // find ron - calls } -fn count_shapes(hand: &[Tile]) { - let hand = if !hand.is_sorted() { - let mut hand = hand.to_vec(); - hand.sort(); - &hand - } else { - hand - }; +pub fn check_ron(hand: &[Tile], melds: &[&[Tile]]) { + let bag: HashBag = HashBag::from_iter(hand.iter().cloned()); + + }