Make score keeping idempotent

Also add 'being captured' to capture flow.
main
Elijah C. Voigt 1 year ago
parent 620133a45c
commit 1a9c774ccf

@ -91,7 +91,7 @@ impl Plugin for Display3dPlugin {
pick_up.run_if(any_component_added::<game::Selected>()), pick_up.run_if(any_component_added::<game::Selected>()),
put_down.run_if(any_component_removed::<game::Selected>()), put_down.run_if(any_component_removed::<game::Selected>()),
dissolve_animation.run_if(any_with_component::<Dissolving>), dissolve_animation.run_if(any_with_component::<Dissolving>),
capture_piece.run_if(any_with_component::<game::Captured>), capture_piece.run_if(any_with_component::<game::BeingCaptured>),
monitor_animations monitor_animations
.run_if(in_state(GameState::Play)) .run_if(in_state(GameState::Play))
.run_if(any_component_changed::<AnimationPlayer>()), .run_if(any_component_changed::<AnimationPlayer>()),
@ -1164,10 +1164,10 @@ fn setup_dissolve_materials(
/// 3. Play the same "captured" animation in reverse /// 3. Play the same "captured" animation in reverse
/// The animation is like a 'beam me up scotty' sorta thing. /// The animation is like a 'beam me up scotty' sorta thing.
fn capture_piece( fn capture_piece(
events: Query<(Entity, &Dissolvable), (With<Display3d>, Added<game::Captured>)>, events: Query<(Entity, &Dissolvable), (With<Display3d>, Added<game::BeingCaptured>)>,
mut query: Query< mut query: Query<
(&mut Transform, &Side, &Dissolvable), (&mut Transform, &Side, &Dissolvable),
(With<Display3d>, With<game::Captured>), (With<Display3d>, With<game::BeingCaptured>),
>, >,
dissolving: Query<Entity, With<Dissolving>>, dissolving: Query<Entity, With<Dissolving>>,
mut state: Local<Option<game::CaptureFlow>>, mut state: Local<Option<game::CaptureFlow>>,
@ -1229,11 +1229,17 @@ fn capture_piece(
*state = s.next(); *state = s.next();
} }
game::CaptureFlow::FadeIn(_entity) => { game::CaptureFlow::FadeIn(entity) => {
// If we have completed the dissolve-in animation // If we have completed the dissolve-in animation
if dissolving.is_empty() { if dissolving.is_empty() {
debug!("Nothing dissolving, moving on to next step!"); debug!("Nothing dissolving, moving on to next step!");
// Update the 'BeingCaptured' -> 'Captured' status
commands
.entity(entity)
.insert(Captured)
.remove::<BeingCaptured>();
// Move to next state now that animation is done // Move to next state now that animation is done
*state = s.next(); *state = s.next();
} }

@ -126,6 +126,14 @@ impl Piece {
}) })
.collect() .collect()
} }
fn value(&self) -> usize {
match self {
Piece::Pawn => 1,
Piece::Drone => 2,
Piece::Queen => 3,
}
}
} }
#[derive(Debug, Component, Clone, PartialEq)] #[derive(Debug, Component, Clone, PartialEq)]
@ -153,6 +161,11 @@ pub(crate) struct BoardComponent;
#[derive(Debug, Component)] #[derive(Debug, Component)]
pub(crate) struct ValidMove; 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)] #[derive(Debug, Component)]
pub(crate) struct Captured; pub(crate) struct Captured;
@ -180,35 +193,17 @@ pub(crate) enum GameError {
/// Tracks the score of each side of the game /// Tracks the score of each side of the game
#[derive(Debug, Resource, Default)] #[derive(Debug, Resource, Default)]
pub(crate) struct Score { pub(crate) struct Score {
a: usize, score_a: usize,
b: usize, score_b: usize,
captures_a: usize, captures_a: usize,
captures_b: usize, captures_b: usize,
} }
impl Score { 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 { pub(crate) fn _get(&self, side: Side) -> usize {
match side { match side {
Side::A => self.a, Side::A => self.score_a,
Side::B => self.b, Side::B => self.score_b,
} }
} }
@ -633,10 +628,10 @@ impl Board {
} }
mod test { mod test {
use super::*;
#[test] #[test]
fn pawn_simple_moves() { fn pawn_simple_moves() {
use super::*;
let board = Board::from_ascii( let board = Board::from_ascii(
r#"........ r#"........
.#.#.... .#.#....
@ -652,6 +647,8 @@ mod test {
#[test] #[test]
fn drone_simple_moves() { fn drone_simple_moves() {
use super::*;
let board = Board::from_ascii( let board = Board::from_ascii(
r#"..#..... r#"..#.....
..#..... ..#.....
@ -674,6 +671,8 @@ mod test {
#[test] #[test]
fn queen_simple_moves() { fn queen_simple_moves() {
use super::*;
let board = Board::from_ascii( let board = Board::from_ascii(
r#"...###.. r#"...###..
####q### ####q###
@ -706,6 +705,8 @@ mod test {
#[test] #[test]
fn empty_moves() { fn empty_moves() {
use super::*;
let board = Board::from_ascii( let board = Board::from_ascii(
r#"........ r#"........
.p....q. .p....q.
@ -721,6 +722,8 @@ mod test {
/// When a piece is blocked on all sides by friendly, cannot move /// When a piece is blocked on all sides by friendly, cannot move
#[test] #[test]
fn blocking_friendly() { fn blocking_friendly() {
use super::*;
let board = Board::from_ascii( let board = Board::from_ascii(
r#"p....... r#"p.......
..dp.... ..dp....
@ -751,6 +754,8 @@ mod test {
/// When an enemy is on one side, can move to capture just that piece /// When an enemy is on one side, can move to capture just that piece
#[test] #[test]
fn case_01() { fn case_01() {
use super::*;
let board = Board::from_ascii( let board = Board::from_ascii(
r#"........ r#"........
........ ........
@ -789,6 +794,8 @@ mod test {
/// Can move up to but not over friendlies /// Can move up to but not over friendlies
#[test] #[test]
fn case_02() { fn case_02() {
use super::*;
let board = Board::from_ascii( let board = Board::from_ascii(
r#"..#...qq r#"..#...qq
dpp#d#d. dpp#d#d.
@ -819,6 +826,8 @@ mod test {
#[test] #[test]
fn case_03() { fn case_03() {
use super::*;
let board = Board::from_ascii( let board = Board::from_ascii(
r#".p.....q r#".p.....q
dp.p.pdq dp.p.pdq
@ -856,6 +865,8 @@ mod test {
// a disconnect between board logic and display plumbing // a disconnect between board logic and display plumbing
#[test] #[test]
fn case_04() { fn case_04() {
use super::*;
let mut board = Board::from_ascii( let mut board = Board::from_ascii(
r#".....dqq r#".....dqq
dpp..pdq dpp..pdq
@ -886,6 +897,8 @@ mod test {
#[test] #[test]
fn test_piece_moves_at() { fn test_piece_moves_at() {
use super::*;
let given = Piece::Drone.moves_at(&(4, 1).into()); let given = Piece::Drone.moves_at(&(4, 1).into());
let expected: HashSet<BoardIndex> = HashSet::from([ let expected: HashSet<BoardIndex> = HashSet::from([
(4, 0).into(), (2, 1).into(), (3, 1).into(), (5, 1).into(), (6, 1).into(), (4, 2).into(), (4, 3).into(), (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] #[test]
fn test_capture_01() { fn test_capture_01() {
use super::*;
let board = Board::from_ascii( let board = Board::from_ascii(
r#"...p.... r#"...p....
........ ........
@ -932,6 +947,8 @@ mod test {
#[test] #[test]
fn test_capture_02() { fn test_capture_02() {
use super::*;
let board = Board::from_ascii( let board = Board::from_ascii(
r#"........ r#"........
..p.p... ..p.p...
@ -1055,7 +1072,7 @@ pub(crate) fn update_board(
commands commands
.entity(entity) .entity(entity)
.remove::<BoardIndex>() .remove::<BoardIndex>()
.insert(Captured); .insert(BeingCaptured);
}, },
MoveType::Promotion(..) => { MoveType::Promotion(..) => {
commands commands
@ -1127,7 +1144,7 @@ fn set_endgame(
}, },
)); ));
parent.spawn(TextBundle::from_section( parent.spawn(TextBundle::from_section(
format!("BLUE {}", score.b), format!("BLUE {}", score.score_b),
TextStyle { TextStyle {
font_size: 32.0, font_size: 32.0,
color: Color::BLUE, color: Color::BLUE,
@ -1135,7 +1152,7 @@ fn set_endgame(
}, },
)); ));
parent.spawn(TextBundle::from_section( parent.spawn(TextBundle::from_section(
format!("RED {}", score.a), format!("RED {}", score.score_a),
TextStyle { TextStyle {
font_size: 32.0, font_size: 32.0,
color: Color::RED, color: Color::RED,
@ -1247,14 +1264,20 @@ fn clear_endgame(query: Query<Entity, With<Endgame>>, mut commands: Commands) {
/// * All captured pieces have their captured side preserved /// * All captured pieces have their captured side preserved
/// We can iterate over these pieces and calculate the score on the fly /// We can iterate over these pieces and calculate the score on the fly
fn manage_score( fn manage_score(
events: Query<(&Side, &Piece), (Added<Captured>, With<display3d::Display3d>)>, query: Query<(&Side, &Piece), (With<Captured>, With<display3d::Display3d>)>,
mut debug_info: ResMut<debug::DebugInfo>, mut debug_info: ResMut<debug::DebugInfo>,
mut score: ResMut<Score>, mut score: ResMut<Score>,
) { ) {
events.iter().for_each(|(side, piece)| { // Calculate number of captures performed by either side
score.increment(!*side, *piece); score.captures_a = query.iter().filter(|(s, _)| **s == Side::B).count();
debug_info.set("score".into(), format!("A:{}|B:{}", score.a, score.b)); 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( pub(crate) fn set_side(
@ -1429,7 +1452,7 @@ fn reset_game(
.for_each(|(e, (i, p))| { .for_each(|(e, (i, p))| {
commands.entity(e) commands.entity(e)
.insert((*i, *p, Visibility::Inherited)) .insert((*i, *p, Visibility::Inherited))
.remove::<(Captured, Promoted)>(); .remove::<(BeingCaptured, Captured, Promoted)>();
}); });
} }

@ -177,7 +177,6 @@ fn manage_scroll_text_animation(
animated_texts: Query<&ui::TextScroll>, animated_texts: Query<&ui::TextScroll>,
parents: Query<&Parent>, parents: Query<&Parent>,
children: Query<&Children>, children: Query<&Children>,
time: Res<Time>,
framecount: Res<FrameCount>, framecount: Res<FrameCount>,
mut next_state: ResMut<NextState<GameState>>, mut next_state: ResMut<NextState<GameState>>,
mut curr: ResMut<CurrentIntroParagraph>, mut curr: ResMut<CurrentIntroParagraph>,

@ -177,7 +177,7 @@ where
Box::new(move |buttons: Res<ButtonInput<T>>| -> bool { buttons.just_released(button) }) Box::new(move |buttons: Res<ButtonInput<T>>| -> bool { buttons.just_released(button) })
} }
pub(crate) fn pressed<T>(button: T) -> impl FnMut(Res<ButtonInput<T>>) -> bool + Clone pub(crate) fn _pressed<T>(button: T) -> impl FnMut(Res<ButtonInput<T>>) -> bool + Clone
where where
T: Copy + Eq + Hash + Send + Sync + 'static, T: Copy + Eq + Hash + Send + Sync + 'static,
{ {

Loading…
Cancel
Save