From 1a9c774ccfcb84ab52c19d86a990dd0e9c7a2392 Mon Sep 17 00:00:00 2001 From: "Elijah C. Voigt" Date: Sat, 11 May 2024 22:13:06 -0700 Subject: [PATCH] Make score keeping idempotent Also add 'being captured' to capture flow. --- src/display3d.rs | 14 +++++--- src/game.rs | 89 ++++++++++++++++++++++++++++++------------------ src/intro.rs | 1 - src/main.rs | 2 +- 4 files changed, 67 insertions(+), 39 deletions(-) diff --git a/src/display3d.rs b/src/display3d.rs index d00058c..522a1e4 100644 --- a/src/display3d.rs +++ b/src/display3d.rs @@ -91,7 +91,7 @@ impl Plugin for Display3dPlugin { pick_up.run_if(any_component_added::()), put_down.run_if(any_component_removed::()), dissolve_animation.run_if(any_with_component::), - capture_piece.run_if(any_with_component::), + capture_piece.run_if(any_with_component::), monitor_animations .run_if(in_state(GameState::Play)) .run_if(any_component_changed::()), @@ -1164,10 +1164,10 @@ fn setup_dissolve_materials( /// 3. Play the same "captured" animation in reverse /// The animation is like a 'beam me up scotty' sorta thing. fn capture_piece( - events: Query<(Entity, &Dissolvable), (With, Added)>, + events: Query<(Entity, &Dissolvable), (With, Added)>, mut query: Query< (&mut Transform, &Side, &Dissolvable), - (With, With), + (With, With), >, dissolving: Query>, mut state: Local>, @@ -1229,11 +1229,17 @@ fn capture_piece( *state = s.next(); } - game::CaptureFlow::FadeIn(_entity) => { + game::CaptureFlow::FadeIn(entity) => { // If we have completed the dissolve-in animation if dissolving.is_empty() { debug!("Nothing dissolving, moving on to next step!"); + // Update the 'BeingCaptured' -> 'Captured' status + commands + .entity(entity) + .insert(Captured) + .remove::(); + // Move to next state now that animation is done *state = s.next(); } diff --git a/src/game.rs b/src/game.rs index 7288690..7eeab63 100644 --- a/src/game.rs +++ b/src/game.rs @@ -126,6 +126,14 @@ impl Piece { }) .collect() } + + fn value(&self) -> usize { + match self { + Piece::Pawn => 1, + Piece::Drone => 2, + Piece::Queen => 3, + } + } } #[derive(Debug, Component, Clone, PartialEq)] @@ -153,6 +161,11 @@ pub(crate) struct BoardComponent; #[derive(Debug, Component)] pub(crate) struct ValidMove; +/// Marker for entity being captured +#[derive(Debug, Component)] +pub(crate) struct BeingCaptured; + +/// Marker for component which is captured #[derive(Debug, Component)] pub(crate) struct Captured; @@ -180,35 +193,17 @@ pub(crate) enum GameError { /// Tracks the score of each side of the game #[derive(Debug, Resource, Default)] pub(crate) struct Score { - a: usize, - b: usize, + score_a: usize, + score_b: usize, captures_a: usize, captures_b: usize, } impl Score { - fn increment(&mut self, side: Side, piece: Piece) { - let i = match piece { - Piece::Queen => 3, - Piece::Drone => 2, - Piece::Pawn => 1, - }; - match side { - Side::A => { - self.captures_a += 1; - self.a += i; - } - Side::B => { - self.captures_b += 1; - self.b += i; - } - } - } - pub(crate) fn _get(&self, side: Side) -> usize { match side { - Side::A => self.a, - Side::B => self.b, + Side::A => self.score_a, + Side::B => self.score_b, } } @@ -633,10 +628,10 @@ impl Board { } mod test { - use super::*; - #[test] fn pawn_simple_moves() { + use super::*; + let board = Board::from_ascii( r#"........ .#.#.... @@ -652,6 +647,8 @@ mod test { #[test] fn drone_simple_moves() { + use super::*; + let board = Board::from_ascii( r#"..#..... ..#..... @@ -674,6 +671,8 @@ mod test { #[test] fn queen_simple_moves() { + use super::*; + let board = Board::from_ascii( r#"...###.. ####q### @@ -706,6 +705,8 @@ mod test { #[test] fn empty_moves() { + use super::*; + let board = Board::from_ascii( r#"........ .p....q. @@ -721,6 +722,8 @@ mod test { /// When a piece is blocked on all sides by friendly, cannot move #[test] fn blocking_friendly() { + use super::*; + let board = Board::from_ascii( r#"p....... ..dp.... @@ -751,6 +754,8 @@ mod test { /// When an enemy is on one side, can move to capture just that piece #[test] fn case_01() { + use super::*; + let board = Board::from_ascii( r#"........ ........ @@ -789,6 +794,8 @@ mod test { /// Can move up to but not over friendlies #[test] fn case_02() { + use super::*; + let board = Board::from_ascii( r#"..#...qq dpp#d#d. @@ -819,6 +826,8 @@ mod test { #[test] fn case_03() { + use super::*; + let board = Board::from_ascii( r#".p.....q dp.p.pdq @@ -856,6 +865,8 @@ mod test { // a disconnect between board logic and display plumbing #[test] fn case_04() { + use super::*; + let mut board = Board::from_ascii( r#".....dqq dpp..pdq @@ -886,6 +897,8 @@ mod test { #[test] fn test_piece_moves_at() { + use super::*; + let given = Piece::Drone.moves_at(&(4, 1).into()); let expected: HashSet = HashSet::from([ (4, 0).into(), (2, 1).into(), (3, 1).into(), (5, 1).into(), (6, 1).into(), (4, 2).into(), (4, 3).into(), @@ -896,6 +909,8 @@ mod test { #[test] fn test_capture_01() { + use super::*; + let board = Board::from_ascii( r#"...p.... ........ @@ -932,6 +947,8 @@ mod test { #[test] fn test_capture_02() { + use super::*; + let board = Board::from_ascii( r#"........ ..p.p... @@ -1055,7 +1072,7 @@ pub(crate) fn update_board( commands .entity(entity) .remove::() - .insert(Captured); + .insert(BeingCaptured); }, MoveType::Promotion(..) => { commands @@ -1127,7 +1144,7 @@ fn set_endgame( }, )); parent.spawn(TextBundle::from_section( - format!("BLUE {}", score.b), + format!("BLUE {}", score.score_b), TextStyle { font_size: 32.0, color: Color::BLUE, @@ -1135,7 +1152,7 @@ fn set_endgame( }, )); parent.spawn(TextBundle::from_section( - format!("RED {}", score.a), + format!("RED {}", score.score_a), TextStyle { font_size: 32.0, color: Color::RED, @@ -1247,14 +1264,20 @@ fn clear_endgame(query: Query>, mut commands: Commands) { /// * All captured pieces have their captured side preserved /// We can iterate over these pieces and calculate the score on the fly fn manage_score( - events: Query<(&Side, &Piece), (Added, With)>, + query: Query<(&Side, &Piece), (With, With)>, mut debug_info: ResMut, mut score: ResMut, ) { - events.iter().for_each(|(side, piece)| { - score.increment(!*side, *piece); - debug_info.set("score".into(), format!("A:{}|B:{}", score.a, score.b)); - }); + // Calculate number of captures performed by either side + score.captures_a = query.iter().filter(|(s, _)| **s == Side::B).count(); + score.captures_b = query.iter().filter(|(s, _)| **s == Side::A).count(); + + // Calculate score based on the piece values + score.score_a = query.iter().filter(|(s, _)| **s == Side::B).fold(0, |acc, (_, piece)| acc + piece.value()); + score.score_b = query.iter().filter(|(s, _)| **s == Side::A).fold(0, |acc, (_, piece)| acc + piece.value()); + + // Debug this for good measure + debug_info.set("score".into(), format!("A:{}|B:{}", score.score_a, score.score_b)); } pub(crate) fn set_side( @@ -1429,7 +1452,7 @@ fn reset_game( .for_each(|(e, (i, p))| { commands.entity(e) .insert((*i, *p, Visibility::Inherited)) - .remove::<(Captured, Promoted)>(); + .remove::<(BeingCaptured, Captured, Promoted)>(); }); } diff --git a/src/intro.rs b/src/intro.rs index b066381..a4cbe2e 100644 --- a/src/intro.rs +++ b/src/intro.rs @@ -177,7 +177,6 @@ fn manage_scroll_text_animation( animated_texts: Query<&ui::TextScroll>, parents: Query<&Parent>, children: Query<&Children>, - time: Res