Parser changes:
- Track num_players_expected from user input after 'How many players?'
- Create placeholder players ('Player N') on 'say me please' prompts
- Replace placeholder names when real names appear in roll lines
- Emit state during setup phase (was returning None)
- Include phase and numPlayersExpected in state JSON
UI changes:
- Empty slots shown as dashed/dimmed panels with '?' token
- Placeholder players shown as 'Registering...'
- Registered players shown with checkmark and ,500
- Status bar shows 'Setting up · 2/3 players registered'
Same top-banner pattern as the stale indicator but with red accent
and 'Connection lost — retrying every 2s...' message. Page gets
subtle greyscale/dim instead of a blocking overlay.
Subtle top banner with dimmed page (not a blocking overlay like the
full disconnect state). Shows elapsed time since last update.
Separate from the hard disconnect which triggers after 3 fetch failures.
Debug panel: added 'Stale' button to test.
- Zero state: bouncing dice + message when no game exists
- Disconnected: greyed overlay after 3 consecutive fetch failures,
with retry countdown
- Game over: gold banner with winner name + confetti animation,
detected from log ('WINS!') or single remaining player
- Debug panel: Ctrl+Shift+D toggles hidden panel with buttons to
test all four states (zero, playing, gameover, disconnected, reset)
- Also fixed player panel to use p.number for current-turn matching
and property ownership display
The C code picks a starting player via dice roll but doesn't reorder
the player array. The parser now tracks _first_player_idx and rotates
the players list in get_state() so the UI shows them in actual turn
order.
The root cause: checkpoint handler queued .trade via say_delayed, but
monop sends '-- Command:' before processing the trade. The old handler
reset in_trade and queued .roll, so both commands got sent.
Fix: checkpoint handler no longer sends commands. The -- Command:
prompt is where the bot decides to trade or roll, matching how monop
actually works (-- Command: is the interactive prompt).
Also: no trades while in jail (jail has no -- Command: before roll).
Updated all tests to reflect the new flow.
Added guard in jail turn handler to skip rolling when in_trade is True.
The roll happens later when '-- Command:' arrives after trade completes.
Added 5 regression tests for the exact failing sequence.
- Handle 'Which player do you wish to trade with?' prompt when
in_trade is True (was silently returning, causing bot to roll
during an active trade prompt)
- Simplify property trade offers to always say 'done' (cash-only
trades) to avoid getting stuck on property list prompts
Parser now accumulates log entries for key game events:
- Turn starts (checkpoint lines)
- Rolls, movement, passing GO
- Rent payments
- Card draws (with card text)
- Auctions, trades, resignations
- Jail (triple doubles, GO TO JAIL)
- Game start and winner
Log is capped at 100 entries in GameState, last 30 emitted in
get_state() to match what index.html expects.
Also synced plugin's monop_parser.py copy.
- Direct buy: set property_owner when buy confirmed via checkpoint
- Auction: set property_owner when 'It goes to' parsed
- Historical log replay still passes (1551/1553)
- Watches channel messages via @event('irc.privmsg')
- Feeds to MonopParser, writes game-state.json on state change
- Commands: .monop [status|players|board|owned]
- Bundled monop_parser.py in plugin dir
- Standalone test passes