# Design: Match Logic & Game Rules (M5) **Goal:** Implement a high-level match management system to handle scoring, game timing, and state transitions (Playing, Goal Pause, Match Ended). **Architecture:** Introduction of a `MatchManager` component that acts as a controller over the `World`. The `World` remains responsible for physics and AI, while the `MatchManager` handles the "rules of the sport". --- ## 1. Components ### MatchManager The central authority for the match state. - **GameState**: `Playing`, `GoalPause`, `MatchEnded`. - **Score**: `ScoreRed`, `ScoreBlue` (integers). - **Match Timer**: `MatchDuration` (total time) and `CurrentTime` (elapsed). - **Pause Timer**: `PauseDuration` (fixed duration for goal celebration) and `PauseTimer` (countdown). - **Reference**: Pointer to `World`. ### World (Extensions) - **`CheckGoal() (team entities.Team, scored bool)`**: Checks if the puck has crossed the goal lines (X < 0 or X > WorldWidth). - **`ResetPositions()`**: Resets the puck to the center and all players to their `HomePosition`, zeroing out all velocities. --- ## 2. File Structure - **`internal/game/match_manager.go` (New)**: - Definition of `GameState` and `MatchManager` struct. - `Update()` method to drive the match lifecycle. - **`internal/game/world.go` (Modified)**: - Implementation of `CheckGoal()` and `ResetPositions()`. - **`cmd/game/main.go` (Modified)**: - Replace `World` with `MatchManager` in the `Game` struct. - Update `Update()` and `Draw()` calls to go through `MatchManager`. --- ## 3. Data Flow ### Main Loop $\rightarrow$ MatchManager `Game.Update()` $\rightarrow$ `MatchManager.Update()`: 1. **If `Playing`**: - Call `World.CheckGoal()`. - If goal $\rightarrow$ transition to `GoalPause`, increment score, start `PauseTimer`. - If no goal $\rightarrow$ call `World.Update()` (physics/AI) and increment `CurrentTime`. - If `CurrentTime >= MatchDuration` $\rightarrow$ transition to `MatchEnded`. 2. **If `GoalPause`**: - Decrement `PauseTimer`. - If `PauseTimer <= 0` $\rightarrow$ call `World.ResetPositions()` and transition to `Playing`. - `World.Update()` is skipped (game is frozen). 3. **If `MatchEnded`**: - `World.Update()` is skipped. ### World $\rightarrow$ MatchManager (Goal Detection) - `X < 0` $\rightarrow$ `(TeamBlue, true)` - `X > WorldWidth` $\rightarrow$ `(TeamRed, true)` - Otherwise $\rightarrow$ `(_, false)` --- ## 4. Edge Cases & Handling - **Double Scoring**: The `GoalPause` state prevents `CheckGoal` from being called repeatedly until the world is reset. - **Reset Collisions**: `ResetPositions` explicitly sets `Velocity = 0` for all entities to prevent immediate "explosions" from anti-clumping logic. - **Boundary Stuck**: `CheckGoal` is evaluated before physics clamping to ensure goals are registered even at high speeds. - **Last-second Goal**: Goals are processed before the match timer check, ensuring a goal on the final frame is counted. --- ## 5. Success Criteria - Puck crossing the boundary increments the correct team's score. - The game freezes for a few seconds after a goal. - All entities return to starting positions after the pause. - The match stops automatically when the timer reaches the limit.