# 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.
