Repository navigation
fix: drain quest events between commands in _execute_cheat - #86
Merged
Merged
Conversation
The cheat sequence completes the entire golden path in one call, which means items like Rare Flower are taken AND given away before the frontend ever calls pollQuestEvents(). Because _execute_cheat never called next_activated_quest / next_completed_quest between commands, the 'Oh deer, oh deer' quest was never activated during the cheat, and by the time the frontend drained quest events afterward, check_completion returned False (the flower was already with Mira). Fix: add the same quest-draining loop that dev_execute_commands already uses, inside _execute_cheat — one pass after each command. Also add DummyGameState stub to test_CommandParser.py so the three existing cheat unit tests still compile and pass. Test: test_cheat_act_1_completes_oh_deer_oh_deer_quest (new, in test_Integration.py) fails before the fix and passes after.
…only main quest remains active
… quest - Add 'search', 'take faded photograph', 'examine faded photograph' and 'give faded photograph to grandmother' to the Act 1 cheat command list so the Faded Photograph quest is triggered and completed by cheat act 1 - Remove the unimplemented LostLetter quest (class, story flags, Act1 registration) whose trigger/completion flags were never set by any game action - Update the integration test to expect The Faded Photograph in completed side quests and drop the LostLetter import / exclusion note
…tion
When a command completes an act, automatically drive the transition
from ACT_TRANSITION -> ACT_INTRO -> ACT_RUNNING and show the transition
message and new act intro as popup modals (same UX as game startup).
Previously the game would silently block input with no visual feedback,
requiring the user to press Enter (not possible on mobile with a readonly
input field) twice to advance - causing the game to appear stuck.
The fix:
- Add triggerActTransitionModals() that calls b.advanceToRunning() to
collect both the 'Act Complete!' text and new act intro text, then
queues them as modals ('🏆 Act Complete!' + '📖 Act Intro')
- Sets pendingLookOnDismiss so look() + quest activation fires after
the intro modal is dismissed (same as game startup)
- Hook is called from submitCommand() when acceptInput becomes false
and no modal is showing (direct transition, no quest events)
- Hook is also called from dismissModal() when the last quest-completion
modal is dismissed but input is still blocked (transition after quests)
- Add isActRunning(): boolean and advanceToRunning(): string[] to the
GameBridge interface (already in useBridge.ts and mock)
- 5 new unit tests covering all transition scenarios
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes a cheat-mode quest progression bug by ensuring quest activation/update/completion events are drained between each cheat command, so quest state stays consistent with mid-sequence inventory/story changes (Fixes #85).
Changes:
- Drain
next_activated_quest()/next_updated_quest()/next_completed_quest()between commands inCommandParser._execute_cheat(). - Add web-store handling + tests for act-transition modal sequencing via new bridge methods (
isActRunning,advanceToRunning). - Remove the Act 1 “Lost Letter” quest and its story flags/references.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| web/src/stores/useGameStore.ts | Adds act-transition detection and modal queuing driven by bridge state. |
| web/src/stores/useGameStore.test.ts | Adds unit tests for act transition modal flow and look-on-dismiss behavior. |
| src/retroquest/engine/CommandParser.py | Drains quest events after each cheat command; adjusts Act 1 cheat command sequence. |
| tests/retroquest/engine/test_CommandParser.py | Extends test stub game state so cheat parsing continues to work in unit tests. |
| tests/retroquest/act1/test_Integration.py | Adds integration coverage asserting cheat act 1 completes side quests as expected. |
| src/retroquest/act1/quests/LostLetter.py | Removes the Lost Letter quest implementation. |
| src/retroquest/act1/Act1StoryFlags.py | Removes Lost Letter-related flags. |
| src/retroquest/act1/Act1.py | Removes LostLetterQuest from Act 1 quest registration. |
- Add data-testid='side-panel' to SidePanel.vue so the sidebar visibility test has a specific locator (the generic .max-md:hidden class now matches 6 elements, causing a strict-mode violation) - Add data-testid='top-bar' to TopBar.vue so toolbar-button tests can be scoped to the TopBar; the Quick Action Bar in CommandInput also has an always-visible Help button with the same text - Use try/finally in MobileDrawer.emitAndClose so the drawer always closes even if the action handler (e.g. store.saveGame) throws (bridge not initialized in e2e mock context) - Update e2e/game.spec.ts tests 1-3 to use the new data-testid selectors and scoped getByRole queries All 35 e2e + 259 unit + 472 Python tests pass. Formatting constraints verified.
- Act1StoryFlags.py: update module docstring to remove reference to 'finding the lost letter' (those flags were removed in this PR); replace with 'faded photograph' which is the actual discovery flag - test_Integration.py: derive expected_side_quests from act.quests filtered by is_main() instead of a hard-coded list, so the test stays in sync automatically when quests are added or renamed; capture before cheat execution since act.quests is drained during cheat
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #85.
Problem
CommandParser._execute_cheat()ran all cheat commands in one pass without ever callingnext_activated_quest()/next_updated_quest()/next_completed_quest()between commands.The Act 1 cheat sequence takes the Rare Flower and later gives it to Mira, all within the same batch. Because no quest processing happened mid-sequence,
OhDeerOhDeerQueststayed innon_activated_quests. When the web frontend'spollQuestEvents()finally ran after the cheat, it activated the quest butcheck_completionreturnedFalse— the flower was no longer in the inventory or any room.Changes
Python engine
CommandParser._execute_cheat): drainnext_activated_quest / next_updated_quest / next_completed_questafter each command, matching the behaviour ofdev_execute_commands.search,take faded photograph,examine faded photograph,give faded photograph to grandmotherso the Faded Photograph side quest is also completed bycheat act 1.LostLetterQuest(and its flags inAct1StoryFlags.py) were a dead stub whose trigger/completion flags were never set by any game code. Removed to avoid confusion.Web frontend
useGameStore.ts): when a command finishes an act (acceptInputbecomes false),triggerActTransitionModals()is now called automatically, drivingACT_TRANSITION → ACT_INTRO → ACT_RUNNINGand showing the transition text and new act intro as popup modals — the same UX as game startup. Previously the game silently blocked input with no visual feedback (not fixable on mobile where the input field is read-only).isActRunning(): booleanandadvanceToRunning(): string[]to theGameBridgeinterface.E2E / mobile
emitAndClosenow uses try/finally so the drawer always closes even if a handler throws.data-testidtoSidePanelandTopBarto support stable selectors.test-results/andplaywright-report/to the root.gitignore.Tests
test_cheat_act_1_completes_all_side_quests_and_leaves_main_active— verifies every side quest defined inact.questsis completed and only the main quest remains active aftercheat act 1.DummyGameStatestub added totest_CommandParser.pyso unit tests compile after_execute_cheatstarted accessingself.game.state.useGameStore.test.ts.Formatting constraints verified