Merge pull request 'refactor(engine): first ambiguity burn-down batch — 302 → 198 pairs' (#146) from refactor/ambiguity-burndown into master
This commit was merged in pull request #146.
This commit is contained in:
@@ -570,8 +570,8 @@ impl Plugin for CardPlugin {
|
|||||||
tick_flip_anim,
|
tick_flip_anim,
|
||||||
update_drag_shadow,
|
update_drag_shadow,
|
||||||
update_card_shadows_on_drag.after(sync_cards_on_change),
|
update_card_shadows_on_drag.after(sync_cards_on_change),
|
||||||
tick_hint_highlight,
|
tick_hint_highlight.after(GameMutation),
|
||||||
handle_right_click,
|
handle_right_click.after(GameMutation),
|
||||||
tick_right_click_highlights,
|
tick_right_click_highlights,
|
||||||
clear_right_click_highlights_on_state_change.after(GameMutation),
|
clear_right_click_highlights_on_state_change.after(GameMutation),
|
||||||
clear_right_click_highlights_on_pause,
|
clear_right_click_highlights_on_pause,
|
||||||
@@ -580,7 +580,9 @@ impl Plugin for CardPlugin {
|
|||||||
.after(GameMutation)
|
.after(GameMutation)
|
||||||
.run_if(resource_changed::<GameStateResource>),
|
.run_if(resource_changed::<GameStateResource>),
|
||||||
collect_resize_events.after(LayoutSystem::UpdateOnResize),
|
collect_resize_events.after(LayoutSystem::UpdateOnResize),
|
||||||
snap_cards_on_window_resize.after(collect_resize_events),
|
snap_cards_on_window_resize
|
||||||
|
.after(collect_resize_events)
|
||||||
|
.after(GameMutation),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,18 @@ pub struct GameOverScreen;
|
|||||||
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct GameMutation;
|
pub struct GameMutation;
|
||||||
|
|
||||||
|
/// System set for every writer of [`crate::events::NewGameRequestEvent`].
|
||||||
|
///
|
||||||
|
/// Many UI entry points fire this trigger (buttons, keyboard, modals,
|
||||||
|
/// mode pickers). Their relative append order within a frame is
|
||||||
|
/// meaningless — consumers drain the whole queue — so members are
|
||||||
|
/// registered `.in_set(NewGameRequestWriters).ambiguous_with(NewGameRequestWriters)`
|
||||||
|
/// to declare writer-vs-writer order irrelevant instead of leaving it as an
|
||||||
|
/// ambiguity (#143). Only ever combine with `.ambiguous_with` on the same
|
||||||
|
/// set; do NOT hang ordering edges off this set.
|
||||||
|
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct NewGameRequestWriters;
|
||||||
|
|
||||||
/// Persistence path for the in-progress game state file. `None` disables I/O.
|
/// Persistence path for the in-progress game state file. `None` disables I/O.
|
||||||
#[derive(Resource, Debug, Clone)]
|
#[derive(Resource, Debug, Clone)]
|
||||||
pub struct GameStatePath(pub Option<PathBuf>);
|
pub struct GameStatePath(pub Option<PathBuf>);
|
||||||
@@ -208,7 +220,13 @@ impl Plugin for GamePlugin {
|
|||||||
.add_message::<AppLifecycle>()
|
.add_message::<AppLifecycle>()
|
||||||
// add_message is idempotent; SettingsPlugin also registers this.
|
// add_message is idempotent; SettingsPlugin also registers this.
|
||||||
.add_message::<crate::settings_plugin::SettingsChangedEvent>()
|
.add_message::<crate::settings_plugin::SettingsChangedEvent>()
|
||||||
.add_systems(Update, poll_pending_new_game_seed.before(GameMutation))
|
.add_systems(
|
||||||
|
Update,
|
||||||
|
poll_pending_new_game_seed
|
||||||
|
.before(GameMutation)
|
||||||
|
.in_set(NewGameRequestWriters)
|
||||||
|
.ambiguous_with(NewGameRequestWriters),
|
||||||
|
)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Update,
|
Update,
|
||||||
(handle_new_game, handle_draw, handle_move, handle_undo)
|
(handle_new_game, handle_draw, handle_move, handle_undo)
|
||||||
@@ -217,19 +235,40 @@ impl Plugin for GamePlugin {
|
|||||||
)
|
)
|
||||||
.add_systems(Update, check_no_moves.after(GameMutation))
|
.add_systems(Update, check_no_moves.after(GameMutation))
|
||||||
.add_systems(Update, record_replay_on_win.after(GameMutation))
|
.add_systems(Update, record_replay_on_win.after(GameMutation))
|
||||||
.add_systems(Update, handle_confirm_input.after(GameMutation))
|
.add_systems(
|
||||||
.add_systems(Update, handle_confirm_button_input.after(GameMutation))
|
Update,
|
||||||
.add_systems(Update, handle_game_over_input.after(GameMutation))
|
(
|
||||||
.add_systems(Update, handle_game_over_button_input.after(GameMutation))
|
handle_confirm_input,
|
||||||
|
handle_confirm_button_input,
|
||||||
|
handle_game_over_input,
|
||||||
|
handle_game_over_button_input,
|
||||||
|
)
|
||||||
|
.after(GameMutation)
|
||||||
|
.in_set(NewGameRequestWriters)
|
||||||
|
.ambiguous_with(NewGameRequestWriters),
|
||||||
|
)
|
||||||
// Restore prompt: spawn the modal once the splash is gone,
|
// Restore prompt: spawn the modal once the splash is gone,
|
||||||
// route Continue / New Game intents back into the existing
|
// route Continue / New Game intents back into the existing
|
||||||
// GameMutation flow.
|
// GameMutation flow.
|
||||||
.add_systems(Update, spawn_restore_prompt_if_pending)
|
.add_systems(Update, spawn_restore_prompt_if_pending)
|
||||||
.add_systems(Update, handle_restore_prompt.before(GameMutation))
|
// All three pre-mutation game-state writers are chained: elapsed
|
||||||
.add_systems(Update, sync_settings_to_game.before(GameMutation))
|
// time ticks first, settings sync next, then the restore prompt —
|
||||||
|
// a deterministic spine instead of three unordered ResMut holders
|
||||||
|
// (ambiguity burn-down, #143).
|
||||||
|
.add_systems(
|
||||||
|
Update,
|
||||||
|
(
|
||||||
|
tick_elapsed_time,
|
||||||
|
sync_settings_to_game,
|
||||||
|
handle_restore_prompt
|
||||||
|
.in_set(NewGameRequestWriters)
|
||||||
|
.ambiguous_with(NewGameRequestWriters),
|
||||||
|
)
|
||||||
|
.chain()
|
||||||
|
.before(GameMutation),
|
||||||
|
)
|
||||||
.init_resource::<AutoSaveTimer>()
|
.init_resource::<AutoSaveTimer>()
|
||||||
.add_systems(Update, tick_elapsed_time)
|
.add_systems(Update, auto_save_game_state.after(GameMutation))
|
||||||
.add_systems(Update, auto_save_game_state)
|
|
||||||
.add_systems(Last, save_game_state_on_exit);
|
.add_systems(Last, save_game_state_on_exit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ use crate::events::{
|
|||||||
UndoRequestEvent, WinStreakMilestoneEvent,
|
UndoRequestEvent, WinStreakMilestoneEvent,
|
||||||
};
|
};
|
||||||
use crate::font_plugin::FontResource;
|
use crate::font_plugin::FontResource;
|
||||||
use crate::game_plugin::GameMutation;
|
use crate::game_plugin::{GameMutation, NewGameRequestWriters};
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
use crate::input_plugin::TouchDragSet;
|
use crate::input_plugin::TouchDragSet;
|
||||||
use crate::layout::HUD_BAND_HEIGHT;
|
use crate::layout::HUD_BAND_HEIGHT;
|
||||||
@@ -478,10 +478,12 @@ impl Plugin for HudPlugin {
|
|||||||
.add_systems(Update, announce_auto_complete.after(GameMutation))
|
.add_systems(Update, announce_auto_complete.after(GameMutation))
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Update,
|
Update,
|
||||||
update_selection_hud.run_if(
|
update_selection_hud
|
||||||
resource_exists_and_changed::<SelectionState>
|
.after(GameMutation)
|
||||||
.or(resource_exists_and_changed::<GameStateResource>),
|
.run_if(
|
||||||
),
|
resource_exists_and_changed::<SelectionState>
|
||||||
|
.or(resource_exists_and_changed::<GameStateResource>),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.add_systems(Update, update_hud_typography)
|
.add_systems(Update, update_hud_typography)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
@@ -503,13 +505,17 @@ impl Plugin for HudPlugin {
|
|||||||
.add_systems(
|
.add_systems(
|
||||||
Update,
|
Update,
|
||||||
(
|
(
|
||||||
handle_new_game_button,
|
handle_new_game_button
|
||||||
|
.in_set(NewGameRequestWriters)
|
||||||
|
.ambiguous_with(NewGameRequestWriters),
|
||||||
handle_undo_button,
|
handle_undo_button,
|
||||||
handle_pause_button,
|
handle_pause_button,
|
||||||
handle_help_button,
|
handle_help_button,
|
||||||
handle_hint_button,
|
handle_hint_button.after(GameMutation),
|
||||||
handle_modes_button,
|
handle_modes_button,
|
||||||
handle_mode_option_click,
|
handle_mode_option_click
|
||||||
|
.in_set(NewGameRequestWriters)
|
||||||
|
.ambiguous_with(NewGameRequestWriters),
|
||||||
handle_modes_backdrop_click,
|
handle_modes_backdrop_click,
|
||||||
close_modes_popover_on_escape,
|
close_modes_popover_on_escape,
|
||||||
handle_menu_button,
|
handle_menu_button,
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ mod tests {
|
|||||||
/// ordering edge — add `.before`/`.after` (order matters) or
|
/// ordering edge — add `.before`/`.after` (order matters) or
|
||||||
/// `.ambiguous_with` (provably order-independent) at the registration
|
/// `.ambiguous_with` (provably order-independent) at the registration
|
||||||
/// site. When triage lowers the real count, lower this constant too.
|
/// site. When triage lowers the real count, lower this constant too.
|
||||||
const AMBIGUITY_BASELINE: usize = 302;
|
const AMBIGUITY_BASELINE: usize = 198;
|
||||||
|
|
||||||
fn cluster_app() -> App {
|
fn cluster_app() -> App {
|
||||||
let mut app = App::new();
|
let mut app = App::new();
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ use solitaire_core::{FOUNDATIONS, TABLEAUS};
|
|||||||
use solitaire_core::Suit;
|
use solitaire_core::Suit;
|
||||||
|
|
||||||
use crate::events::{HintVisualEvent, StateChangedEvent};
|
use crate::events::{HintVisualEvent, StateChangedEvent};
|
||||||
|
use crate::game_plugin::GameMutation;
|
||||||
use crate::hud_plugin::HudVisibility;
|
use crate::hud_plugin::HudVisibility;
|
||||||
use crate::layout::{
|
use crate::layout::{
|
||||||
Layout, LayoutResource, LayoutSystem, TABLE_COLOUR, apply_dynamic_tableau_fan, compute_layout,
|
Layout, LayoutResource, LayoutSystem, TABLE_COLOUR, apply_dynamic_tableau_fan, compute_layout,
|
||||||
@@ -103,7 +104,7 @@ impl Plugin for TablePlugin {
|
|||||||
apply_theme_on_settings_change,
|
apply_theme_on_settings_change,
|
||||||
apply_hint_pile_highlight,
|
apply_hint_pile_highlight,
|
||||||
tick_hint_pile_highlights,
|
tick_hint_pile_highlights,
|
||||||
sync_pile_marker_visibility,
|
sync_pile_marker_visibility.after(GameMutation),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user