From 30d19ed9d92c981f06f095d5ca46775129cb1fdf Mon Sep 17 00:00:00 2001 From: Tao Tien <29749622+taotien@users.noreply.github.com> Date: Tue, 13 Jan 2026 00:01:38 -0800 Subject: [PATCH] simplify game setup --- src/game/hand.rs | 53 ++++------------ src/game/mod.rs | 137 ++++++++++++++++++----------------------- src/game/player.rs | 7 +-- src/game/round.rs | 42 +++++++++++++ src/game/wall.rs | 19 ------ src/tiles.rs | 12 ++-- src/tui/mod.rs | 10 +-- src/tui/render/hand.rs | 36 +++++------ 8 files changed, 145 insertions(+), 171 deletions(-) create mode 100644 src/game/round.rs diff --git a/src/game/hand.rs b/src/game/hand.rs index 424d9b4..713ef61 100644 --- a/src/game/hand.rs +++ b/src/game/hand.rs @@ -1,58 +1,29 @@ use bevy::prelude::*; use crate::{ - game::{player::Player, wall::WallTiles}, + game::{player::Player /* wall::WallTiles */}, tiles::Tile, }; #[derive(Component)] pub struct Hand; -#[derive(Component)] -#[relationship(relationship_target = HandTiles)] -pub struct InHand(pub Entity); +// #[derive(Component, Default)] +// enum SortHand { +// #[default] +// Unsorted, +// Sort, +// Manual, +// } -#[derive(Component)] -#[relationship_target(relationship = InHand, linked_spawn)] -pub struct HandTiles(Vec); - -pub(crate) fn deal_hands( - mut commands: Commands, - walltiles: Single<&WallTiles>, - walltiles_entity: Single>, - players: Populated>, -) -> Result { - let mut wall = walltiles.iter().collect::>(); - - for player_entity in players { - let hand = wall.split_off(13); - - commands - .get_entity(*walltiles_entity)? - .remove_children(&hand); - - let handtiles = commands.spawn((Hand, HandTiles(hand))).id(); - - commands - .get_entity(player_entity)? - .add_children(&[handtiles]); - } - - trace!("dealt hands"); - Ok(()) -} - -#[allow(clippy::type_complexity)] pub(crate) fn sort_hands( - mut commands: Commands, tiles: Populated<&Tile>, - mut hands: Populated<&mut Children, Changed>, + mut hands: Populated<&mut Children, (With, Changed)>, ) -> Result { - for (mut children) in hands { - children.sort_unstable_by_key(|e| tiles.get(*e).unwrap().suit); - trace!("sorted a hand") + for mut hand in hands { + hand.sort_unstable_by_key(|e| tiles.get(*e).unwrap().suit); + debug!("sorted: {hand:?}") } - trace!("sort_hands"); Ok(()) } diff --git a/src/game/mod.rs b/src/game/mod.rs index 6b3b83f..09c0e36 100644 --- a/src/game/mod.rs +++ b/src/game/mod.rs @@ -1,12 +1,17 @@ use bevy::prelude::*; use crate::{ - game::player::MainPlayer, + game::{ + hand::Hand, + player::{MainPlayer, Player}, + wall::Wall, + }, tiles::{self, *}, }; pub mod hand; pub mod player; +pub mod round; pub mod wall; #[derive(States, Default, Hash, Clone, Eq, Debug, PartialEq, Copy)] @@ -14,98 +19,76 @@ pub enum GameState { #[default] None, Setup, - // Deal, + Deal, Play, - Score, } pub struct Riichi; impl Plugin for Riichi { fn build(&self, app: &mut App) { - app.init_resource::() - .add_systems(Startup, init_match) - .add_systems(Startup, tiles::init_tiles) + app + // start stopper .init_state::() - .add_systems(OnEnter(GameState::Setup), (wall::build_wall, hand::deal_hands, setup_done).chain()) - .add_systems(Update, (hand::sort_hands).run_if(in_state(GameState::Play))) + .init_resource::() + .init_resource::() + .add_systems(Startup, tiles::init_tiles) + .add_systems(OnEnter(GameState::Setup), setup) + .add_systems(OnEnter(GameState::Deal), shuffle_deal) + .add_systems(Update, hand::sort_hands.run_if(in_state(GameState::Play))) // semicolon stopper ; } } -fn setup_done(mut next: ResMut>) { - next.set(GameState::Play); - trace!("setup_done"); +fn shuffle_deal( + mut commands: Commands, + tiles: Query>, + players: Populated>, + wall_ent: Single>, + mut next_gamestate: ResMut>, +) -> Result { + use rand::seq::SliceRandom; + + let mut rng = rand::rng(); + let mut wall: Vec<_> = tiles.iter().collect(); + wall.shuffle(&mut rng); + + commands.get_entity(*wall_ent)?.replace_children(&wall); + + for player_ent in players { + let handtiles = wall.split_off(13); + commands.get_entity(*wall_ent)?.remove_children(&handtiles); + let hand = commands.spawn(Hand).add_children(&handtiles).id(); + commands.get_entity(player_ent)?.replace_children(&[hand]); + } + + next_gamestate.set(GameState::Play); + Ok(()) } -#[derive(Component)] -pub(crate) struct Dice(u8, u8); +pub(crate) fn setup( + mut commands: Commands, + matchsettings: Res, + // mut compass: ResMut + tiles: Query>, + mut next_gamestate: ResMut>, +) { + for i in 1..=matchsettings.player_count { + let player = player::Player { + name: format!("Player {}", i), + }; + let points = player::Points(matchsettings.starting_points); -#[derive(Resource)] -pub(crate) struct Compass { - pub(crate) prevalent_wind: Wind, - pub(crate) round: u8, - pub(crate) dealer_wind: Wind, - pub(crate) riichi: usize, - pub(crate) honba: usize, -} + let bundle = (player, points, Hand); -impl Default for Compass { - fn default() -> Self { - Self { - prevalent_wind: Wind::Ton, - round: 1, - dealer_wind: Wind::Ton, - riichi: 0, - honba: 0, + if i == 1 { + commands.spawn((bundle, MainPlayer)); + } else { + commands.spawn(bundle); } } -} - -#[derive(Resource)] -pub(crate) struct MatchSettings { - pub(crate) starting_points: isize, - pub(crate) player_count: u8, -} - -pub(crate) fn next_round(_compass: Res) {} - -pub(crate) fn init_match( - mut commands: Commands, - // mut compass: ResMut -) { - let starting = 25000; - let player_count = 4; - - commands.insert_resource(MatchSettings { - starting_points: starting, - player_count, - }); - - let players = (2..=player_count) - .map(|i| { - ( - player::Player { - name: format!("Player {i}"), - }, - player::Points(starting), - ) - }) - .collect::>(); - commands.spawn_batch(players); - let main_player = ( - player::Player { - name: format!("Player {}", 1), - }, - player::Points(starting), - ); - commands.spawn((main_player, MainPlayer)); - - // *compass = Compass { - // prevalent_wind: Wind::Ton, - // round: 1, - // dealer_wind: todo!(), - // riichi: 0, - // honba: 0, - // } + + commands.spawn(Wall); + + next_gamestate.set(GameState::Deal); } diff --git a/src/game/player.rs b/src/game/player.rs index a99e5cd..7a928be 100644 --- a/src/game/player.rs +++ b/src/game/player.rs @@ -1,11 +1,6 @@ use bevy::prelude::*; -use crate::{ - game::wall::{InWall, Wall}, - tiles::Tile, -}; - -#[derive(Component)] +#[derive(Component, Debug)] pub struct Player { pub name: String, } diff --git a/src/game/round.rs b/src/game/round.rs new file mode 100644 index 0000000..fa4873b --- /dev/null +++ b/src/game/round.rs @@ -0,0 +1,42 @@ +use bevy::prelude::*; + +use crate::tiles::*; + +#[derive(Component)] +pub(crate) struct Dice(u8, u8); + +#[derive(Resource)] +pub(crate) struct Compass { + pub(crate) prevalent_wind: Wind, + pub(crate) round: u8, + pub(crate) dealer_wind: Wind, + pub(crate) riichi: usize, + pub(crate) honba: usize, +} + +impl Default for Compass { + fn default() -> Self { + Self { + prevalent_wind: Wind::Ton, + round: 1, + dealer_wind: Wind::Ton, + riichi: 0, + honba: 0, + } + } +} + +#[derive(Resource)] +pub(crate) struct MatchSettings { + pub(crate) starting_points: isize, + pub(crate) player_count: u8, +} + +impl Default for MatchSettings { + fn default() -> Self { + Self { + starting_points: 25000, + player_count: 4, + } + } +} diff --git a/src/game/wall.rs b/src/game/wall.rs index 69e4fd7..4463c26 100644 --- a/src/game/wall.rs +++ b/src/game/wall.rs @@ -5,22 +5,3 @@ use crate::tiles::Tile; #[derive(Component)] pub struct Wall; - -#[derive(Component)] -#[relationship_target(relationship = InWall, linked_spawn)] -pub struct WallTiles(Vec); - -#[derive(Component)] -#[relationship(relationship_target = WallTiles)] -pub struct InWall(pub Entity); - -pub(crate) fn build_wall(mut commands: Commands, tiles: Query>) { - let mut rng = rand::rng(); - - let mut shuffled = tiles.iter().collect::>(); - shuffled.shuffle(&mut rng); - - commands.spawn((Wall, WallTiles(shuffled))); - - trace!("build_wall"); -} diff --git a/src/tiles.rs b/src/tiles.rs index 5147233..40879fe 100644 --- a/src/tiles.rs +++ b/src/tiles.rs @@ -37,27 +37,29 @@ pub enum Dragon { pub struct Dora; pub fn init_tiles(mut commands: Commands) { + let mut tiles = vec![]; for _ in 0..4 { for i in 1..=9 { - commands.spawn(Tile { + tiles.push(Tile { suit: Suit::Pin(Rank(i)), }); - commands.spawn(Tile { + tiles.push(Tile { suit: Suit::Sou(Rank(i)), }); - commands.spawn(Tile { + tiles.push(Tile { suit: Suit::Man(Rank(i)), }); } for i in 0..4 { - commands.spawn(Tile { + tiles.push(Tile { suit: Suit::Wind(Wind::from_repr(i).unwrap()), }); } for i in 0..3 { - commands.spawn(Tile { + tiles.push(Tile { suit: Suit::Dragon(Dragon::from_repr(i).unwrap()), }); } } + commands.spawn_batch(tiles); } diff --git a/src/tui/mod.rs b/src/tui/mod.rs index cde1cf2..e3bccf9 100644 --- a/src/tui/mod.rs +++ b/src/tui/mod.rs @@ -6,9 +6,9 @@ use bevy_ratatui::event::KeyMessage; use ratatui::{text::ToSpan, widgets::Paragraph}; use jong::game::GameState; -use jong::game::wall::InWall; +// use jong::game::wall::InWall; -use crate::tui::console::ConsoleState; +use crate::tui::{console::ConsoleState, menu::draw_mainmenu, render::ingame::draw_ingame}; mod console; mod menu; @@ -54,7 +54,7 @@ impl Plugin for RiichiTui { // console .init_state::() - .add_systems(Update, console::draw_console.run_if(in_state(console::ConsoleState::Open))) + .add_systems(Update, console::draw_console.after_ignore_deferred(draw_mainmenu).after_ignore_deferred(draw_ingame).run_if(in_state(console::ConsoleState::Open))) // general setup .init_state::() @@ -67,7 +67,7 @@ impl Plugin for RiichiTui { // gaming .init_resource::() .add_systems(Update, render::ingame::draw_ingame.run_if(in_state(InGame))) - .add_systems(Update, render::hand::render_changed_hand.run_if(in_state(InGame).and(in_state(GameState::Play)))) + // .add_systems(Update, render::hand::render_changed_hand.run_if(in_state(InGame).and(in_state(GameState::Play)))) // semicolon stopper ; @@ -119,7 +119,7 @@ pub(crate) fn input_system( } _ => {} }, - GameState::Score => todo!(), + _ => todo!(), _ => unreachable!("TuiState::InGame but GameState invalid") }, } diff --git a/src/tui/render/hand.rs b/src/tui/render/hand.rs index d2fcc69..f76e933 100644 --- a/src/tui/render/hand.rs +++ b/src/tui/render/hand.rs @@ -1,7 +1,7 @@ use bevy::prelude::*; use ratatui::widgets::Paragraph; -use jong::game::hand::HandTiles; +// use jong::game::hand::HandTiles; use jong::tiles::Tile; use crate::tui::render::tiles; @@ -9,24 +9,24 @@ use crate::tui::render::tiles; #[derive(Resource, Default)] pub(crate) struct RenderedHand(pub(crate) Vec>>); -pub(crate) fn render_changed_hand( - hands: Populated<&Children, Changed>, - tiles: Populated<&Tile>, - mut target: ResMut, -) -> Result { - let mut rendered = vec![]; +// pub(crate) fn render_changed_hand( +// hands: Populated<&Children, Changed>, +// tiles: Populated<&Tile>, +// mut target: ResMut, +// ) -> Result { +// let mut rendered = vec![]; - for hand in hands { - let tiles = hand - .iter() - .map(|inhand| tiles.get(inhand).map(tiles::draw_tile).unwrap()) - .collect(); +// for hand in hands { +// let tiles = hand +// .iter() +// .map(|inhand| tiles.get(inhand).map(tiles::draw_tile).unwrap()) +// .collect(); - rendered.push(tiles); - } +// rendered.push(tiles); +// } - target.0 = rendered; +// target.0 = rendered; - trace!("render_changed_hand"); - Ok(()) -} +// trace!("render_changed_hand"); +// Ok(()) +// }