Skip to content

Show short game pauses through the front-end - #129

Merged
dmccoystephenson merged 2 commits into
mainfrom
fix/busy-primitive-and-tavern-fixes
Jul 27, 2026
Merged

Show short game pauses through the front-end#129
dmccoystephenson merged 2 commits into
mainfrom
fix/busy-primitive-and-tavern-fixes

Conversation

@dmccoystephenson

@dmccoystephenson dmccoystephenson commented Jul 27, 2026

Copy link
Copy Markdown
Member

Summary

Adds a showBusy(message, seconds) primitive to BaseUserInterface and routes the game's two short pauses through it.

Docks.fish and Tavern.getDrunk used to print() their flavour text and time.sleep() directly, bypassing the UI contract. On the console that read fine; on the other two front-ends the text went to the terminal and the player just saw the previous screen frozen for 1-3 seconds. (getDrunk also called lotsOfSpace()/divider() first, which on pygame fills the surface without ever flipping the display, and on web are documented no-ops — so nothing was drawn either.)

Implemented in all three front-ends:

  • console — prints the message, then a dot row per second waited (the old "... " animation).
  • pygame — draws the wrapped message and flips every frame, pumping events (including QUIT and resize) so the window stays responsive rather than looking hung.
  • web — publishes a busy screen the client renders, and consumes no input; the next screen supersedes it.
  • The base implementation is concrete (just the pause), so a future front-end still works without changing it — the abstract primitive list is unchanged, and README.md's "implement BaseUserInterface + a UIType + a factory branch" instruction still holds as written.

Closes #125

Note: this branch originally also carried fixes for #126 and #127, which landed independently in #128 while it was in review. It has been rebased onto that work, taking main's version of both; what remains is only the showBusy change.

Test plan

  • python3 -m compileall -q src tests
  • SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy python3 -m pytest --verbose -vv --cov=src --cov-report=term-missing --cov-report=xml:cov.xml388 passed, coverage 95%
  • All three front-ends touched and covered: new tests for the console (test_userInterface.py), pygame (test_pygameUserInterface.py — the message is drawn, a keypress neither ends the pause nor rewrites the prompt, and an over-wide message wraps), web (test_webUserInterface.py — the busy screen is presented, no input is consumed, and the client page has a matching render branch), and the inherited default (test_baseUserInterface.py).
  • Call-site tests updated: test_docks.py/test_tavern.py stub showBusy instead of patching print/sys.stdout.flush/time.sleep, and assert the pause is announced through the UI.
  • No Player/Stats/TimeService field changed, so schemas/*.json and the *JsonReaderWriters are correctly untouched; README.md/PLANNING.md describe nothing that changed here.

This PR description was drafted during a Gardener session (Stephenson-Software/gardener).

@dmccoystephenson

Copy link
Copy Markdown
Member Author

Self-review

Reviewed the full diff against this repo's conventions — front-end parity, the schema/reader-writer contract, test coverage on new public methods, and doc drift. No blocking findings. One weak test was found and fixed in this branch before posting (5f8cb4a). Notes below, in path:line — finding form.

Fixed during review

tests/ui/test_pygameUserInterface.py:494 — test_showBusy_takes_no_input_and_leaves_the_prompt_alone stubbed time.time with [0.0, 5.0], so the wait loop exited on its first condition check and pygame.event.get() was never reached. The injected keypress was never read, meaning the test proved only that the prompt was untouched — not the "takes no input" half of its name. Rewritten as test_showBusy_ignores_keypresses_and_leaves_the_prompt_alone, running two frames with the keypress in the first and asserting a second frame was still drawn afterward.

Verified, no change needed

src/ui/baseUserInterface.py:93 — showBusy is concrete, not abstract. Deliberate: tests/ui/test_baseUserInterface.py's RecordingUserInterface and any external front-end implement only the seven abstract primitives, so making this an eighth would break them. The abstract list is unchanged and README.md's "implement BaseUserInterface + a UIType + a factory branch" instruction still holds as written. All three in-repo front-ends override it anyway.

src/ui/webUserInterface.py:339 — showBusy leaves anything already in the input queue for the next screen. Considered and accepted: the client can't send during a busy screen — there is no button, and the keydown handler only acts on options/dialogue/timed, so a busy screen falls through it. tests/ui/test_webUserInterface.py pins that behaviour rather than leaving it implicit.

src/ui/webUserInterface.py:160 — the busy screen carries no header, so the status chips disappear during the pause. That matches the existing dialogue, prompt, and timed screens, which also omit header, and the console/pygame front-ends likewise drop the status block on non-menu screens. Consistent, so left alone.

src/location/tavern.py:152 — getDrunk now spends the $10 before the pause rather than after clearing the screen. No behavioural difference: the charge still lands before increaseDay() rolls the day over, and run() still gates the call on canAfford(10).

src/location/docks.py:333 — fish() can still return early ("You're too tired to fish!") after the pause has been shown. Unchanged from before this PR, where the print/sleep ran in exactly the same position.

src/location/tavern.py:242 — the < 1 check runs after int(amount), so 0.5 and -0.5 both truncate to 0 and are rejected. Covered by test_changeBet_rejects_a_bet_rounding_down_to_zero, with test_changeBet_accepts_the_smallest_valid_bet pinning that $1 still goes through.

src/ui/userInterface.py:133 — console dot placement changed slightly (message first, then one dot row per second, where the docks previously printed "Fishing... " with the dots inline and no trailing row). Cosmetic, and it makes the two call sites consistent with each other.

Contract checks

  • Front-end parity: implemented in all three UIs plus a base default; each has its own test.
  • Schema / reader-writer: no Player/Stats/TimeService field added, renamed, or retyped, so schemas/*.json and the *JsonReaderWriters are correctly untouched.
  • Docs: README.md and PLANNING.md describe nothing that changed here (neither mentions the dice payout or the pauses); re-checked both.
  • Build: python3 -m compileall -q src tests clean; pytest --cov 386 passed, 94%.

dmccoystephenson and others added 2 commits July 27, 2026 08:39
Adds a showBusy primitive to BaseUserInterface and routes the "Fishing..."
and drinking pauses through it, so all three front-ends show them. Also
corrects Old Tom's stale description of the dice payout and rejects sub-$1
gambling bets up front.

Closes #125
Closes #126
Closes #127

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The previous version's clock stub exited the wait loop before any event
was read, so it never showed a keypress is ignored - only that the prompt
was left alone. It now runs two frames, with the keypress in the first.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@dmccoystephenson
dmccoystephenson force-pushed the fix/busy-primitive-and-tavern-fixes branch from 5f8cb4a to f56c83e Compare July 27, 2026 09:02
@dmccoystephenson dmccoystephenson changed the title Show short game pauses through the front-end, and fix two tavern bugs Show short game pauses through the front-end Jul 27, 2026
@dmccoystephenson

Copy link
Copy Markdown
Member Author

Rebase note (scope reduced)

#128 landed on main while this was in review and fixed #126 and #127 independently. This branch has been rebased onto it, taking main's version of both — its dialogue wording ("you'll win 5x your money!") and its bare < 1 guard without my explanatory comment — and dropping my duplicate regression tests in favour of the ones #128 already added (test_npc_tavern_dialogue_matches_dice_win_multiplier, test_changeBet_negative_amount_rejected, test_changeBet_zero_amount_rejected). What remains here is only the showBusy work for #125.

Two incidental changes came out of the rebase, both worth calling out:

Suite re-run after the rebase: 388 passed, coverage 95%.

@dmccoystephenson
dmccoystephenson merged commit 13776bc into main Jul 27, 2026
1 check passed
@dmccoystephenson
dmccoystephenson deleted the fix/busy-primitive-and-tavern-fixes branch July 27, 2026 09:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fishing and getting drunk print flavour text to stdout, freezing the pygame and web front-ends

1 participant