diff --git a/gsd-framework/.planning/REQUIREMENTS.md b/gsd-framework/.planning/REQUIREMENTS.md index f472803..098920b 100644 --- a/gsd-framework/.planning/REQUIREMENTS.md +++ b/gsd-framework/.planning/REQUIREMENTS.md @@ -13,16 +13,16 @@ Requirements for initial release. Each maps to roadmap phases. - [x] **CORE-02**: Player can click/tap to select a tile (highlighted when selected) - [x] **CORE-03**: Player can click/tap a second tile to attempt a match - [x] **CORE-04**: Two matching tiles connect if a valid path exists with 3 or fewer straight lines -- [ ] **CORE-05**: Connected matching tiles disappear from the board -- [ ] **CORE-06**: Player receives points when tiles are matched and cleared -- [ ] **CORE-07**: Cleared tiles become passable space for future connections +- [x] **CORE-05**: Connected matching tiles disappear from the board +- [x] **CORE-06**: Player receives points when tiles are matched and cleared +- [x] **CORE-07**: Cleared tiles become passable space for future connections - [ ] **CORE-08**: Game detects when no valid moves remain on the board - [ ] **CORE-09**: Game detects win condition when all tiles are cleared ### Board & Scoring - [ ] **BOARD-01**: Player can shuffle remaining tiles when no moves available -- [ ] **BOARD-02**: Score is displayed and updates in real-time +- [x] **BOARD-02**: Score is displayed and updates in real-time ### Visual & UX @@ -71,13 +71,13 @@ Which phases cover which requirements. Updated during roadmap creation. | CORE-02 | Phase 2 | Complete | | CORE-03 | Phase 2 | Complete | | CORE-04 | Phase 3 | Complete | -| CORE-05 | Phase 3 | Pending | -| CORE-06 | Phase 3 | Pending | -| CORE-07 | Phase 3 | Pending | +| CORE-05 | Phase 3 | Complete | +| CORE-06 | Phase 3 | Complete | +| CORE-07 | Phase 3 | Complete | | CORE-08 | Phase 4 | Pending | | CORE-09 | Phase 4 | Pending | | BOARD-01 | Phase 5 | Pending | -| BOARD-02 | Phase 3 | Pending | +| BOARD-02 | Phase 3 | Complete | | UX-01 | Phase 6 | Pending | | UX-02 | Phase 6 | Pending | | UX-03 | Phase 6 | Pending | diff --git a/gsd-framework/.planning/ROADMAP.md b/gsd-framework/.planning/ROADMAP.md index c4f3dba..dc77230 100644 --- a/gsd-framework/.planning/ROADMAP.md +++ b/gsd-framework/.planning/ROADMAP.md @@ -128,7 +128,7 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 |-------|----------------|--------|-----------| | 1. Core Foundation | 3/3 | Complete | 01-01, 01-02, 01-03 | | 2. Grid and Input | 3/3 | Complete | 02-01, 02-02, 02-03 | -| 3. Core Matching Mechanics | 1/3 | In Progress| | +| 3. Core Matching Mechanics | 2/3 | In Progress| | | 4. Game State Management | 0/3 | Not started | - | | 5. Board Generation and Recovery | 0/3 | Not started | - | | 6. Polish and UX | 0/4 | Not started | - | diff --git a/gsd-framework/.planning/STATE.md b/gsd-framework/.planning/STATE.md index 62d25ec..90ac13f 100644 --- a/gsd-framework/.planning/STATE.md +++ b/gsd-framework/.planning/STATE.md @@ -3,14 +3,14 @@ gsd_state_version: 1.0 milestone: v1.0 milestone_name: milestone status: in_progress -stopped_at: Completed 03-01-PLAN.md (Path-Finding Algorithm) -last_updated: "2026-03-11T04:37:58.757Z" +stopped_at: Completed 03-02-PLAN.md (Match Engine and Scoring System) +last_updated: "2026-03-11T04:42:32.824Z" last_activity: 2026-03-11 — Completed 02-03-PLAN.md (Game Integration with Input Handling) progress: total_phases: 6 completed_phases: 2 total_plans: 10 - completed_plans: 8 + completed_plans: 9 --- --- @@ -68,6 +68,7 @@ Progress: [████████░] 100% of Phase 2 *Updated after each plan completion* | Phase 02-grid-and-input P03 | 3 | 3 tasks | 1 files | | Phase 03 P01 | 206 | 2 tasks | 3 files | +| Phase 03 P02 | 2 minutes | 5 tasks | 8 files | ## Accumulated Context @@ -103,6 +104,10 @@ Recent decisions affecting current work: - [Phase 03]: State key includes direction for visited tracking - [Phase 03]: Turn counting: direction changes only, not first move - [Phase 03]: Static method pattern for PathFinder.findPath +- [Phase 03]: Fail-fast validation: Type check before pathfinding +- [Phase 03]: Score calculation: Base + complexity bonus (0-turn: 150, 1-turn: 125, 2-turn: 100) +- [Phase 03]: Score display: HTML overlay over canvas text +- [Phase 03]: Event-driven match handling with tilesMatched and matchFailed events ### Pending Todos @@ -119,8 +124,8 @@ None yet. ## Session Continuity -Last session: 2026-03-11T04:37:58.739Z -Stopped at: Completed 03-01-PLAN.md (Path-Finding Algorithm) +Last session: 2026-03-11T04:42:32.806Z +Stopped at: Completed 03-02-PLAN.md (Match Engine and Scoring System) Resume file: None ## Phase 2 Complete diff --git a/gsd-framework/.planning/phases/03-core-matching-mechanics/03-02-SUMMARY.md b/gsd-framework/.planning/phases/03-core-matching-mechanics/03-02-SUMMARY.md new file mode 100644 index 0000000..edd31ec --- /dev/null +++ b/gsd-framework/.planning/phases/03-core-matching-mechanics/03-02-SUMMARY.md @@ -0,0 +1,343 @@ +--- +phase: 03-core-matching-mechanics +plan: 02 +title: Match Engine and Scoring System +subsystem: Matching Logic +tags: [match-validation, scoring, event-driven, game-integration] +status: complete +completed_date: 2026-03-11 + +dependency_graph: + requires: + - "Phase 1: Core Foundation (EventEmitter, types, config)" + - "Phase 2: Grid and Input (GridManager, Tile model, Game.ts)" + - "Plan 03-01: Path-Finding Algorithm (PathFinder.findPath)" + provides: + - "Scoring.calculate: Score calculation with complexity bonus" + - "MatchEngine.validateMatch: Multi-stage match validation pipeline" + - "GridManager.clearTiles: Tile clearing with event emission" + - "Game match handling: tilesSelected → validate → clear/score" + - "Score HTML overlay: Real-time score display" + affects: + - "Plan 03-03: Visual feedback will use match events for animations" + - "Game.ts: Match validation integrated into event flow" + +tech_stack: + added: + - "Scoring system: Static utility with base score + complexity bonus" + - "MatchEngine: Validation pipeline (type → position → pathfinding)" + - "Event types: tilesMatched, matchFailed for match result communication" + - "Score overlay: HTML absolute positioning with semi-transparent background" + patterns: + - "Fail-fast validation: Type check before expensive pathfinding" + - "Event-driven match handling: tilesSelected → validate → clear/score" + - "Static method pattern: Scoring.calculate, MatchEngine constructor" + - "HTML overlay for UI: Canvas for game, DOM for score display" + +key_files: + created: + - path: "src/matching/Scoring.ts" + lines: 37 + description: "Score calculation with complexity bonus" + exports: ["Scoring.calculate"] + - path: "src/__tests__/Scoring.test.ts" + lines: 33 + description: "Test coverage for Scoring system" + test_count: 5 + - path: "src/matching/MatchEngine.ts" + lines: 70 + description: "Match validation pipeline with fail-fast optimization" + exports: ["MatchEngine.validateMatch"] + - path: "src/__tests__/MatchEngine.test.ts" + lines: 159 + description: "Comprehensive test coverage for MatchEngine" + test_count: 8 + modified: + - path: "src/managers/GridManager.ts" + lines_added: 14 + description: "Added clearTiles method with event emission" + - path: "index.html" + lines_added: 13 + description: "Added score display overlay with styling" + - path: "src/game/Game.ts" + lines_added: 40 + description: "Integrated MatchEngine, match handling, score tracking" + - path: "src/types/index.ts" + lines_added: 2 + description: "Extended GameEvents with tilesMatched and matchFailed" + +decisions: + - id: "03-02-001" + summary: "Fail-fast validation: Type check before pathfinding" + rationale: "Pathfinding is expensive (BFS algorithm). Checking tile types first avoids unnecessary computation on invalid pairs (different types)." + outcome: "MatchEngine.validateMatch returns immediately for different-type matches, only runs BFS for same-type tiles" + - id: "03-02-002" + summary: "Score calculation: Base + complexity bonus" + rationale: "Reward skill-based gameplay. Finding 0-turn paths (same row/col) is harder than 2-turn paths." + outcome: "0-turn: 150 points (50% bonus), 1-turn: 125 points (25% bonus), 2-turn: 100 points (base)" + - id: "03-02-003" + summary: "Score display: HTML overlay over canvas text" + rationale: "HTML is easier to style, position responsively, and make accessible than canvas text rendering." + outcome: "Absolute positioned div in top-right corner, semi-transparent background, updates via DOM manipulation" + - id: "03-02-004" + summary: "Event-driven match handling" + rationale: "Consistent with Phase 1/2 architecture. Decouples validation logic from UI updates." + outcome: "tilesSelected → MatchEngine.validateMatch → tilesMatched/matchFailed → clear/score/deselect" + +metrics: + duration: "2 minutes" + tasks_completed: 5 + files_created: 4 + files_modified: 4 + total_lines: 366 + test_coverage: "13 test cases (5 Scoring + 8 MatchEngine)" + commits: 5 +--- + +# Phase 3 Plan 2: Match Engine and Scoring System - Summary + +## One-Liner + +Match validation pipeline with multi-stage checking (type → position → path), score calculation rewarding path complexity, and real-time HTML score display integrated into Game event flow. + +## Overview + +Implemented the core match validation and scoring system that powers the game's matching mechanics. The system uses a fail-fast pipeline: cheap checks (type, position) happen before expensive pathfinding (BFS). Successful matches clear tiles, update score, and emit events. Failed matches provide feedback and deselect tiles after a short delay. + +This completes CORE-05 (tiles disappear), CORE-06 (player receives points), CORE-07 (cleared tiles become passable), and BOARD-02 (real-time score display). + +## What Was Built + +### 1. Scoring System (Task 1) + +**File:** `src/matching/Scoring.ts` (37 lines) + +Implemented score calculation with complexity bonus: +- **Base score:** 100 points per match +- **Complexity bonus:** Fewer turns = higher score + - 0 turns (same row/col): 150 points (50% bonus) + - 1 turn (L-shape): 125 points (25% bonus) + - 2 turns (Z-shape): 100 points (base) +- **Invalid turn counts:** Default to base score +- **Integer scores:** Uses `Math.floor()` to ensure integer results + +**Design:** Follows CONFIG-like pattern with private static readonly constants (`BASE_SCORE`, `BONUS_MULTIPLIERS`). Static method pattern for clean API: `Scoring.calculate(turns)`. + +### 2. MatchEngine Validation Pipeline (Task 2) + +**File:** `src/matching/MatchEngine.ts` (70 lines) + +Implemented multi-stage match validation with fail-fast optimization: + +**Stage 1: Type Check** (cheap) +- Returns `{ valid: false, reason: 'different-type' }` immediately +- Avoids expensive BFS on invalid pairs + +**Stage 2: Position Check** (cheap) +- Returns `{ valid: false, reason: 'same-tile' }` if same tile +- Prevents matching a tile with itself + +**Stage 3: Pathfinding** (expensive) +- Calls `PathFinder.findPath(tile1, tile2, grid, 2)` only if types match +- Returns `{ valid: false, reason: 'no-path' }` if no valid path +- Returns `{ valid: false, reason: 'too-many-turns', turns: N }` if path has 3+ turns + +**Stage 4: Success** +- Calculates score using `Scoring.calculate(turns)` +- Returns `{ valid: true, path, turns, score }` + +**Integration:** Injects GridManager and TypedEventEmitter dependencies in constructor. Uses PathFinder from 03-01. + +### 3. Tile Clearing (Task 3) + +**File:** `src/managers/GridManager.ts` (+14 lines) + +Added `clearTiles` method: +- Input: Array of tiles to clear +- Action: Sets `tile.cleared = true` for each tile +- Events: Emits `tile:cleared` event for each tile with `{ tile }` +- Cleanup: Calls `deselectAll()` after clearing + +**Purpose:** Enables CORE-05 (connected tiles disappear) and CORE-07 (cleared tiles become passable for pathfinding). + +### 4. Score HTML Overlay (Task 4) + +**File:** `index.html` (+13 lines) + +Added score display element: +```html +