feat(engine): playability improvements — input intelligence, audio, HUD, onboarding (#27–#30, #37, #39–#40, #44, #48–#49)
Task #27: Double-click auto-move — best_destination() finds optimal target (foundation over tableau); handle_double_click() fires MoveRequestEvent. Task #28: Hint system — find_hint() returns first legal from/to/count triple; H key tints the source stack HintHighlight (yellow pulse via tick_hint_highlight). Task #29: No-moves detection — has_legal_moves() checks stock/waste/all face-up cards; check_no_moves system fires InfoToastEvent("No moves available") once per stalemate (debounced so it fires only once until the state changes). Task #30: Forfeit — G key fires ForfeitEvent; StatsPlugin records abandoned game, persists stats, starts a new deal. Task #37: Mute-all (M) and mute-music (Shift+M) toggles; MuteState resource applied in apply_volume_on_change. Task #39: Daily challenge HUD constraint label (time limit / target score). Task #40: Undo-count HUD label; amber colour when undos > 0. Task #44: Win-streak and level line on pause screen. Task #48: Undo sound routes UndoRequestEvent → lib.flip audio channel. Task #49: Onboarding banner rich-text key highlights — D and H rendered as orange KeyHighlightSpan children so they stand out from body text. Also registers CursorPlugin in solitaire_app (tasks #31/#32 wire-up). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -244,4 +244,25 @@ mod tests {
|
||||
assert_eq!(fired.len(), 1);
|
||||
assert_eq!(fired[0].total_xp, total_xp);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zen_mode_win_awards_base_xp() {
|
||||
// Zen mode suppresses score display but XP is still awarded normally.
|
||||
// score=0 in the event (Zen keeps score at 0), time=300 (no speed bonus),
|
||||
// undo_count=0 so no-undo bonus applies: expected 50+25=75.
|
||||
let mut app = headless_app();
|
||||
app.world_mut()
|
||||
.resource_mut::<GameStateResource>()
|
||||
.0
|
||||
.mode = solitaire_core::game_state::GameMode::Zen;
|
||||
|
||||
app.world_mut().send_event(GameWonEvent {
|
||||
score: 0, // Zen mode keeps score at 0
|
||||
time_seconds: 300,
|
||||
});
|
||||
app.update();
|
||||
|
||||
let xp = app.world().resource::<ProgressResource>().0.total_xp;
|
||||
assert_eq!(xp, 75, "Zen win: base 50 + no-undo 25 = 75");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user