Merge dev → main (automated)#600
Merged
Merged
Conversation
added 30 commits
July 6, 2026 02:42
… errors - Add Vite type declarations (vite-env.d.ts) for ?raw CSV imports - Fix synergyTypes type casting in MainStreetCards.ts - Add STAFF_CARD_TEMPLATES export for test access - Update SVG generator to read from CSV instead of TS - Update card catalog documentation to reference CSV as source of truth - Fix script for vite-node instead of tsx (Node/CSV compatibility) - Add CsvLoader unit tests with vitest globals reference
Creates a shared Game Over overlay component in the core engine UI that all games can use instead of writing their own. Features: - Full-screen semi-transparent backdrop using createOverlayBackground - Center title (default: 'Game Over', configurable) - Auto-scaling summary text area (font size computed via computeAutoScaleFontSize using binary search) - Bottom button row: [Play Again] and [Menu] - Optional extra button row for game-specific actions - Customizable button labels and callbacks - dismiss() method for cleanup - Exported from src/ui/index.ts barrel file Files: - src/ui/GameOverOverlay.ts: Implementation (createGameOverOverlay + computeAutoScaleFontSize) - src/ui/index.ts: Barrel exports for GameOverOverlay types - tests/ui/GameOverOverlay.test.ts: 21 tests covering all features
…xcluded everywhere - computeSynergyBonus: cards with synergyCoinBonus=0 AND synergyRepBonus=0 neither contribute to nor receive synergy - computeSynergyRepBonus: same zero-synergy exclusion - computeSynergyPairs: both card AND neighbor filtered (was only card) - computeHandCardSynergyBonus: zero-synergy grid businesses skipped - Test helper makeBiz helpers detect 'biz-pawnshop-' prefix to default synergyCoinBonus=0, synergyRepBonus=0 for backward compat with existing Pawn Shop tests - community-space-types: add synergyCoinBonus/synergyRepBonus to fixture and BUSINESS_CARD_FIELDS list All 4184 unit tests pass (235 files, 9 skipped).
When discard piles are empty, hide the PileView sprite and count text instead of showing a ghosted full-size card-back (95×130). This fixes the oversized card-back visual issue in the discard section. The discard hit areas created in createDiscardZones handle all interaction, so the ghosted card-back is unnecessary visual clutter. When a card IS placed, the existing code path shows the compact card (57×78) correctly.
…e (SLL) - Created gym-tooltip.layout.json with zones for header, label, content, log - Updated GymTooltipScene to use SLL anchors (anchorPoint) for layout positions - Added GymTooltipLayout.test.ts with schema validation and position mapping tests - Scene functionality preserved; all tests pass
… Language (SLL) Migrate the following Gym demo scenes to use declarative SLL layout positions instead of hardcoded pixel values: 1. GymOverlayUiScene.ts - buttons, intensity text, event log 2. GymDeckRngScene.ts - controls, card display 3. GymHudComponentsScene.ts - instructions, button rows, status, event log 4. GymTranscriptScene.ts - controls, event log 5. GymUndoRedoScene.ts - controls, counter, status, history, event log 6. GymSaveLoadScene.ts - controls, state text, event log 7. GymAudioFeedbackScene.ts - controls rows, status, event log 8. GymGraphicsLightingSpikeScene.ts - controls, content, event log 9. GymGraphicsShaderSpikeScene.ts - controls, status, content, event log For each scene: - Created a scene-specific layout JSON file in layouts/ - Added module-level SLL layout parsing (matching the tooltip pattern) - Replaced hardcoded Y positions with SLL anchor lookups - Kept fallback values for robustness (null layout) - Preserved visual appearance and functionality All 237 gym tests pass. Build succeeds.
Add reusable runtime support for screen object ownership registration and mode-based visibility toggling: - Re-export VisibilityOwnershipController from src/ui/index.ts for UI-layer consumers - Create GymLayoutOwnershipScene demo that exercises registration, mode switching, group toggling, and diagnostic warnings - Register the new scene in GymRegistry and Gym index barrel - Add unit tests (tests/ui/visibility-ownership-runtime.test.ts) covering registration, toggling, multi-group OR logic, default behavior, and diagnostics - Update browser tests to include the new scene in GymRouterScene and GymSceneSmoke suites Acceptance Criteria Met: - Runtime can register screen objects to ownership groups ✓ - Runtime can hide/show registered objects based on active mode ✓ - Metadata participates without schema-breaking changes ✓ - Unit tests cover registration, toggling, and default behavior ✓
…ntrols/Usage Example/Test Plan sections All 13 Gym demo scenes excluding GymRouterScene have their help panels restructured with the new 4-section format: - Features: engine feature demonstrated with real game use cases - Controls: each button explained with what it does and why it exists - Usage Example: realistic game scenario showing the feature in action - Test Plan: step-by-step button sequence for E2E validation Scenes updated: GymDeckRngScene, GymHandPileScene, GymHudComponentsScene, GymOverlayUiScene, GymTooltipScene, GymSaveLoadScene, GymTranscriptScene, GymUndoRedoScene, GymAudioFeedbackScene, GymSllScene, GymGraphicsLightingSpikeScene, GymGraphicsShaderSpikeScene, GymLayoutOwnershipScene
… scene - Extend HandView.sortCards() to accept optional AnimatedSortOptions with animate, duration, and ease parameters - When animate: true, sprites tween smoothly from old to new positions instead of destroy/recreate; sprites array is reordered to match sorted cards before applying tweens - Backwards compatible: existing callers without opts work unchanged - Respects reducedMotion mode (instant placement when enabled) - Migrate GymHandPileScene.sortHand() to use animated sort API - Export AnimatedSortOptions from ui/index.ts barrel - Add 6 unit tests: snap compat, tween targets, sprite preservation, reduced-motion, arc layout Y positions, correct final positions
…, tableau highlight, cancel button, and step indicator ## Changes ### SushiGoConstants.ts - Added styled button constants: CHOPSTICKS_BUTTON_BG, CHOPSTICKS_BUTTON_HOVER_BG, text colors, depth - Added tableau highlight constants for chopsticks card glow (blue when available, gold when active) - Added first-pick highlight constants (brighter green, thicker stroke, more visible fill) - Added cancel button constants (dark red background, hover effects, positioning) - Added step indicator constants (gold color, 'Step 1 of 2' / 'Step 2 of 2') - Updated button padding (x: 16, y: 8) for better styling ### SushiGoScene.ts - 1. **Styled chopsticks button** - Replaced bracketed text '[ Use Chopsticks ]' with proper background rectangle + text button. Button has dark green background that brightens on hover. - 2. **Chopsticks tableau highlight** - Adds a blue glow (or gold when active) around chopsticks cards in the player's tableau when chopsticks are usable. - 3. **On-screen cancel button** - Shows a visible 'Cancel' button (red themed) during chopsticks mode, positioned below the hand. Also clickable with hover effects. - 4. **Step indicator** - Shows 'Step 1 of 2' / 'Step 2 of 2' in gold text above the chopsticks button during the two-card pick flow. - 5. **Improved first-pick highlight** - Uses brighter green (#00ff66), thicker 4px stroke, and more visible 0.25 fill alpha. - 6. **Better instruction text** - 'Pick 2 cards: click your 1st card' / 'click your 2nd card' instead of 'Chopsticks: ...' - All new UI objects are properly cleaned up in shutdown() and during mode transitions. - Proper lifecycle management for first-pick highlight (destroyed on cancel/mode end, recreated on refresh). ### Tests - Added SushiGoChopsticksScene.test.ts - 30 tests verifying all new UX constants - Updated SushiGoConstants.test.ts - 56 tests including all new constants
…reedyStrategy - Add GreedyStrategyConfig interface with configurable columnWeight (default 0.5 = 50/50 balance) - Add DEFAULT_GREEDY_CONFIG constant - Update computeColumnBonus to scale by card point values of matching cards in column (high-value cards like Queens get larger penalty for missing column potential) - Use Math.max(0, cardValueSum) to prevent negative card values from producing positive bonus - Propagate config through chooseDrawSource, chooseMoveForCard, and AiPlayer - Add 8 new test cases: config defaults, columnWeight=0, columnWeight=1, card point value scaling, low-value cards (Kings=0), AiPlayer config passthrough - Update existing computeColumnBonus tests to use high-value Queens instead of Kings
- Extend HandView.sortCards() with AnimatedSortOptions (animate, duration, ease) - Migrate GymHandPileScene.sortHand() to use animated sort API - Add 6 unit tests for sort animation (tween targets, sprite preservation, reduced-motion, backward compat, arc layout, final positions) - Export AnimatedSortOptions from ui/index.ts barrel - Respects reducedMotion mode
The animated sort path was only tweening x/y positions, but cards in an arc layout also have a rotation angle proportional to their horizontal offset from center. When cards are re-sorted, their rotation was snapping instantly instead of transitioning smoothly. - Compute target rotation per-sprite in animated sort path (same formula as applyLayout: maxRotationDegrees * normalized offset) - Include rotation in the tween config alongside x/y - Update mock tween in handView.animation.test.ts to apply rotation All 28 animation tests pass (22 animateAddCard + 6 sort animation).
After reordering sprites to match the sorted card order, their visual stacking order (depth) was still in the original creation order, causing cards to render in the wrong z-order. Fixed by calling setDepth(i) on each sprite after reordering so that later-index cards render on top. - Added setDepth loop before the animation tween loop - Added setDepth mock to test mock image
…Feudalism to shared GameOverOverlay Migrates four games from their custom game-over overlay implementations to the shared GameOverOverlay component in the core engine UI. Games migrated: - Beleaguered Castle: win overlay now uses createGameOverOverlay. Gains a [Menu] button (navigates to GameSelectorScene). The no-moves overlay remains custom (undo is game-specific). - The Mind: win/loss overlays now use createGameOverOverlay instead of createParameterizedOverlay. Gains a [Menu] button. - Golf: end-screen overlay now uses createGameOverOverlay. Gains a [Menu] button. [Export Transcript] is an extra button. - Feudalism: game-over overlay now uses createGameOverOverlay. Gains a [Menu] button. Games NOT migrated (remain with custom overlays): - Lost Cities: tabular multi-column match summary - Sushi Go: tabular round-by-round breakdown - Main Street: highly custom with challenges, meta-progression, difficulty selector Files: example-games/beleaguered-castle/scenes/BeleagueredCastleScene.ts example-games/the-mind/scenes/TheMindScene.ts example-games/golf/scenes/GolfSceneHelpers.ts example-games/feudalism/scenes/FeudalismOverlays.ts
Changes:
- MainStreetCardSvgGenerator.ts: Changed income label from '+X/turn' to 'Income: +X/turn'
- UpgradeOverlaySpec.ts: Changed overlay income text to 'Income: +X/turn', centered
position (x: width/2, y: height*0.38) with origin (0.5, 0.5); centered reputation
below income at y: height*0.5. Added originX/originY to OverlayTextSpec.
- MainStreetRenderer.ts: Centered income/reputation overlay text using spec origins;
added income overlay to market cards (business/community-space); replaced hand card
manual rendering with unified SVG texture + overlay pipeline; removed separate
hand card income text ('/turn' format); removed unused getSynergyDisplayColor.
- Tests: Updated all tests to expect 'Income: +X/turn' format and centered positioning.
…9 instead of stretched ~276×50
The incident queue ('Upcoming') panel was rendering cards at ~276×50
pixels, breaking the 7:4 SVG aspect ratio and causing visible
horizontal stretching.
Changes:
- Update BASE_QUEUE_CARD_W to 120 and BASE_QUEUE_CARD_H to 69
(custom incident card size, preserving ~7:4 aspect ratio)
- Replace hardcoded cardRenderH=50 and panel-derived cardRenderW in
refreshIncidentQueue() with layout.queueCardW/queueCardH
- Add queue card dimensions to prewarmVisibleCardTextures() so
incident queue textures are rasterised ahead of time
- Add test suite (7 tests) validating constants, aspect ratio, and
layout behavior
- Document 120×69 in card-dimensions.md recommended sizes
All unit tests pass (4305 tests, 240 files).
…audit fix) Root cause: Overlay text coordinates in UpgradeOverlaySpec.ts use absolute card-pixel positions (origin at top-left of card), but the renderer's applyUpgradeOverlays adds these to a Phaser Container whose local origin is at the centre of the card image (image placed at 0,0 with default origin 0.5). This means: - x: width/2 becomes the RIGHT edge of the card - y: height*0.38 becomes near the bottom edge Fix: Convert all coordinates to container-local space by subtracting width/2 from x and height/2 from y: - incomeText: x=0, y=-height*0.06 (centred horizontally, slightly above centre) - reputationText: x=0, y=+height*0.1 (centred horizontally, below income) - levelBadge: x=width/2-4, y=4-height/2 (top-right corner) - nameText: x=0, y=-height/2+16 (top-centre) Tests updated to match new container-local coordinate expectations.
Replace hardcoded card-ID arrays in MainStreetTiers.ts with dynamic arrays built from the CSV-derived CARD_TIER_MAP. Add a 'tier' column to card-data.csv (values 1-5, empty for always-available staff cards). Key changes: - card-data.csv: Add 'tier' column after 'description' with per-card tier assignments for all 83 progression cards - MainStreetCards.ts: Export CARD_TIER_MAP (card ID → tier string) built from CSV at module load time - MainStreetTiers.ts: Build TIER_*_CARD_IDS arrays from CARD_TIER_MAP instead of hardcoded literals; tier structure (thresholds, challenges) remains unchanged in TypeScript - README.md: Document the new 'tier' column in CSV column reference All existing tests (4325 pass) and build continue to pass without changes.
…nd fix Sushi Go hand centering - Remove all The Mind game files, scenes, assets, tests, and adapters - Remove The Mind entry from GameSelectorScene and main.ts - Remove TheMindReplayAdapter from scripts/adapters - Fix Sushi Go hand centering: remove erroneous setBaseX() call in refreshHand() that shifted the hand off-center. HandView's layoutCardPositions already centres the hand around baseX. - Sushi Go! tests continue to pass (216 tests) - Build succeeds without errors
…-function modules Implement the first child of the CSV Auto-Balancing Tool epic: - scripts/balance-cards/ (5 modules): rationale codes, CSV I/O/validation/backup, hybrid curve-fitting + tier-band algorithm, summary table formatter, barrel index - tests/main-street/balance-cards.test.ts: 51 tests covering all 6 acceptance criteria (cost curves for all 5 families, tier band assignment, reward spread, CSV validation, backup rotation, summary format, deterministic output, incident exclusion) All 51 tests pass. Full project build succeeds (tsc + vite build).
…lidation, methodology doc, npm script Completes all child work items of the CSV Auto-Balancing Tool epic: Children completed: - CG-0MRDM4YGI002SK1E: CLI framework (scripts/run-balance-cards.ts) - CG-0MRDM4YGO005X1H9: Business/CS balancing (cost range [3-14], spread enforced) - CG-0MRDM4NRM0051KD5: Upgrade/staff algorithm tests (51 tests) - CG-0MRDM5BJF004LUNC: Upgrade/staff balancing (cost range [3-14]) - CG-0MRDM4NRV0066Z9P: Event/Monte Carlo validation tests - CG-0MRDM5BJS006XU7X: Event balancing (Investment cost range [0-14], Incidents free) - CG-0MRDM5BJ3004AE1W: Balancing methodology document and doc migration - CG-0MRDM5BJQ009YL8N: npm script + guardrails Key changes: - CLI entry point: scripts/run-balance-cards.ts with --input/--output support - Improved cost curves using tier column (+ weighted stats) - Cost spread enforcement (no cost value > 1/3 of family cards) - CSV column fix (29 columns with synergyCoinBonus/synergyRepBonus/tier) - 517b175: docs/main-street/balancing-methodology.md (new) - Origin docs updated with cross-references - npm run balance-cards script added (tsc + tsx) All 3961 unit tests pass (226 test files).
… with rotating backups The balanced CSV now replaces card-data.csv directly. The original is preserved via the rotating backup system (card-data.csv.bak.1-.bak.5).
added 8 commits
July 10, 2026 02:52
Fixes for Container→Text refactoring and test query specificity:
Scene fixes:
- createOwnedCard returns Phaser.GameObjects.Text directly (not Container)
avoiding Phaser 4 issue where container.setVisible() doesn't cascade
visible property to child textures
- bgRects array stores background Rectangle refs for cleanup
- syncAllVisibility() removed (controller handles sync internally)
- removeUngrouped() targets by text prefix (startsWith 'Ungrouped #')
- cleanup() destroys text targets and background rects separately
- Clear button handler also clears bgRects
- toggleGroup() uses displayName instead of raw groupName in label
- GroupToggle interface adds displayName field
- createGroupToggle() stores displayName
- Fixed indexOf bug in ungrouped button creation loop
Test fixes:
- Mode button search: text.startsWith('[ Mode: X ]') to avoid matching
demo card text like 'Shell Title'
- Ungrouped card search: 'Ungrouped #7' (idx = targets.length + 1,
6 demo cards registered before addUngrouped)
…baseIncome values Core changes: - Removed Math.floor from applyReputationMultiplier (MainStreetDifficulty.ts) so fractional income values (e.g. 0.5 baseIncome) are no longer truncated - Removed Math.round from applyActiveEffectMultiplier (ActiveEffect.ts) so per-slot income during applyIncome retains fractional precision Display & logging: - Updated HUD tooltip (MainStreetHudTooltips.ts) to format fractional coin values with toFixed(1) pre-multiplier and toFixed(2) post-multiplier - Updated applyIncome log (MainStreetAdjacency.ts) to show fractional coin amounts with 2 decimal places Documentation: - Regenerated monte-carlo-baseline.json with updated win rate (0.505→0.65) and average coins/turn (2.01→3.30) reflecting the more accurate economy Tests (TDD approach): - reputation-coin-multiplier: updated floor tests → fractional preservation; added 5 new tests for fractional income, integer backward compat, and applyIncome integration with fractional values - adjacency, activity-log, integration, turnflow: updated coin assertions to use toBeCloseTo for fractional values - ActiveEffect: updated rounding test → fractional preservation All 132 main-street/core-engine test files pass (2255 tests).
…he UI Standardize all coin value display to toFixed(3) for consistent precision: - MainStreetRenderer.ts: HUD coin counter, event card tooltip coin deltas (2 locations) - MainStreetHudTooltips.ts: Pre/post multiplier income in coins tooltip, coins breakdown in score tooltip - MainStreetAdjacency.ts: Activity log income entries (gain + neutral) - MainStreetEngine.ts: Event effect description coinChange, bankruptcy log Tests updated: - activity-log.test.ts: Regex for fractional income updated to match 3 decimal places, zero-income assertion updated from 0.00 to 0.000 All 132 test files pass (2255 tests). Build succeeds.
Changes:
- MainStreetCardSvgGenerator.ts: Changed income label from '+X/turn' to 'Income: +X/turn'
- UpgradeOverlaySpec.ts: Changed overlay income text to 'Income: +X/turn', centered
position (x: width/2, y: height*0.38) with origin (0.5, 0.5); centered reputation
below income at y: height*0.5. Added originX/originY to OverlayTextSpec.
- MainStreetRenderer.ts: Centered income/reputation overlay text using spec origins;
added income overlay to market cards (business/community-space); replaced hand card
manual rendering with unified SVG texture + overlay pipeline; removed separate
hand card income text ('/turn' format); removed unused getSynergyDisplayColor.
- Tests: Updated all tests to expect 'Income: +X/turn' format and centered positioning.
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.
Automated release created by ship skill.\n\nIncludes CHANGELOG.md with work-item summaries from this release.