2026-02-08 18:15:09 -08:00
|
|
|
mod derive_alias {
|
|
|
|
|
derive_aliases::define! {
|
|
|
|
|
Copy = ::core::clone::Clone, ::core::marker::Copy;
|
|
|
|
|
Eq = ::core::cmp::PartialEq, ::core::cmp::Eq;
|
|
|
|
|
Ord = ..Eq, ::core::cmp::PartialOrd, ::core::cmp::PartialEq, ::core::cmp::Ord;
|
|
|
|
|
|
|
|
|
|
Base = ::core::fmt::Debug, ..Copy, ..Ord;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
use derive_aliases::derive;
|
|
|
|
|
|
2026-02-07 17:46:03 -08:00
|
|
|
use bevy::prelude::*;
|
|
|
|
|
use spacetimedb::SpacetimeType;
|
2026-02-10 01:40:13 -08:00
|
|
|
use strum::{EnumCount, FromRepr};
|
2026-02-07 17:46:03 -08:00
|
|
|
|
2026-02-08 18:15:09 -08:00
|
|
|
#[derive(..Base, Hash, Default)]
|
|
|
|
|
#[derive(States, SpacetimeType)]
|
|
|
|
|
pub enum GameState {
|
|
|
|
|
#[default]
|
|
|
|
|
None,
|
|
|
|
|
Setup,
|
|
|
|
|
Deal,
|
|
|
|
|
Play,
|
|
|
|
|
Exit,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(..Base)]
|
|
|
|
|
#[derive(Component, SpacetimeType)]
|
2026-02-07 17:46:03 -08:00
|
|
|
pub struct Tile {
|
|
|
|
|
pub suit: Suit,
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-08 18:15:09 -08:00
|
|
|
#[derive(..Base)]
|
|
|
|
|
#[derive(SpacetimeType)]
|
2026-02-07 17:46:03 -08:00
|
|
|
pub enum Suit {
|
|
|
|
|
Man(Rank),
|
|
|
|
|
Pin(Rank),
|
|
|
|
|
Sou(Rank),
|
|
|
|
|
Wind(Wind),
|
|
|
|
|
Dragon(Dragon),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Suit {
|
|
|
|
|
pub fn rank(&self) -> Option<Rank> {
|
|
|
|
|
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,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-08 18:15:09 -08:00
|
|
|
#[derive(
|
|
|
|
|
..Base,
|
|
|
|
|
Deref,
|
|
|
|
|
DerefMut,
|
|
|
|
|
)]
|
|
|
|
|
#[derive(SpacetimeType)]
|
2026-02-07 17:46:03 -08:00
|
|
|
pub struct Rank {
|
|
|
|
|
pub number: u8,
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-08 18:15:09 -08:00
|
|
|
#[derive(
|
|
|
|
|
..Base,
|
|
|
|
|
FromRepr,
|
|
|
|
|
)]
|
|
|
|
|
#[derive(SpacetimeType)]
|
2026-02-07 17:46:03 -08:00
|
|
|
pub enum Wind {
|
|
|
|
|
Ton,
|
|
|
|
|
Nan,
|
|
|
|
|
Shaa,
|
|
|
|
|
Pei,
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-08 18:15:09 -08:00
|
|
|
#[derive(
|
|
|
|
|
..Base,
|
|
|
|
|
FromRepr,
|
|
|
|
|
)]
|
|
|
|
|
#[derive(SpacetimeType)]
|
2026-02-07 17:46:03 -08:00
|
|
|
pub enum Dragon {
|
|
|
|
|
Haku,
|
|
|
|
|
Hatsu,
|
|
|
|
|
Chun,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn tiles() -> Vec<Tile> {
|
|
|
|
|
let mut tiles = vec![];
|
|
|
|
|
for _ in 0..4 {
|
|
|
|
|
for i in 1..=9 {
|
|
|
|
|
tiles.push(Tile {
|
|
|
|
|
suit: Suit::Pin(Rank { number: i }),
|
|
|
|
|
});
|
|
|
|
|
tiles.push(Tile {
|
|
|
|
|
suit: Suit::Sou(Rank { number: i }),
|
|
|
|
|
});
|
|
|
|
|
tiles.push(Tile {
|
|
|
|
|
suit: Suit::Man(Rank { number: i }),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
for i in 0..4 {
|
|
|
|
|
tiles.push(Tile {
|
|
|
|
|
suit: Suit::Wind(Wind::from_repr(i).unwrap()),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
for i in 0..3 {
|
|
|
|
|
tiles.push(Tile {
|
|
|
|
|
suit: Suit::Dragon(Dragon::from_repr(i).unwrap()),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
tiles
|
|
|
|
|
}
|
2026-02-10 01:40:13 -08:00
|
|
|
|
|
|
|
|
#[derive(
|
|
|
|
|
Default,
|
|
|
|
|
..Copy,
|
|
|
|
|
PartialEq,
|
|
|
|
|
Eq,
|
|
|
|
|
Hash,
|
|
|
|
|
Debug,
|
|
|
|
|
)]
|
|
|
|
|
#[derive(SubStates, FromRepr, EnumCount, SpacetimeType)]
|
|
|
|
|
#[source(GameState = GameState::Play)]
|
|
|
|
|
pub enum TurnState {
|
|
|
|
|
#[default]
|
|
|
|
|
None,
|
|
|
|
|
Tsumo,
|
|
|
|
|
Menzen,
|
|
|
|
|
RiichiKan,
|
|
|
|
|
Discard,
|
|
|
|
|
RonChiiPonKan,
|
|
|
|
|
End,
|
|
|
|
|
}
|