# Copilot Rules — Spacetris (SDL3 / C++20)

These rules define **non-negotiable constraints** for all AI-assisted changes.
They exist to preserve determinism, performance, and architecture.

If these rules conflict with `.github/copilot-instructions.md`,
**follow `.github/copilot-instructions.md`.**

---

## Project Constraints (Non-Negotiable)

- Language: **C++20**
- Runtime: **SDL3** + **SDL3_ttf**
- Build system: **CMake**
- Dependencies via **vcpkg**
- Assets must use **relative paths only**
- Deterministic gameplay logic is mandatory

Do not rewrite or refactor working systems unless explicitly requested.

---

## Repo Layout & Responsibilities

- Core gameplay loop/state: `src/Game.*`
- Entry point: `src/main.cpp`
- Text/TTF: `src/Font.*`
- Audio: `src/Audio.*`, `src/SoundEffect.*`
- Effects: `src/LineEffect.*`, `src/Starfield*.cpp`
- High scores: `src/Scores.*`
- Packaging: `build-production.ps1`

When adding a module:
- Place it under `src/` (or an established subfolder)
- Register it in `CMakeLists.txt`
- Avoid circular includes
- Keep headers minimal

---

## Build & Verification

Prefer existing scripts:

- Debug: `cmake --build build-msvc --config Debug`
- Release:
  - Configure: `cmake -S . -B build-release -DCMAKE_BUILD_TYPE=Release`
  - Build: `cmake --build build-release --config Release`
- Packaging (Windows): `./build-production.ps1`

Before finalizing changes:
- Debug build must succeed
- Packaging must succeed if assets or DLLs are touched

Do not introduce new build steps unless required.

---

## Coding & Architecture Rules

- Match local file style (naming, braces, spacing)
- Avoid large refactors
- Prefer small, testable helpers
- Avoid floating-point math in core gameplay state
- Game logic must be deterministic
- Rendering code must not mutate game state

---

## Rendering & Performance Rules

- Do not allocate memory per frame
- Do not load assets during rendering
- No blocking calls in render loop
- Visual effects must be time-based (`deltaTime`)
- Rendering must not contain gameplay logic

---

## Threading Rules

- SDL main thread:
  - Rendering
  - Input
  - Game simulation
- Networking must be **non-blocking** from the SDL main loop
  - Either run networking on a separate thread, or poll ENet frequently with a 0 timeout
  - Never wait/spin for remote inputs on the render thread
- Cross-thread communication via queues or buffers only

---

## Assets, Fonts, and Paths

- Runtime expects adjacent `assets/` directory
- `FreeSans.ttf` must remain at repo root
- New assets:
  - Go under `assets/`
  - Must be included in `build-production.ps1`

Never hardcode machine-specific paths.

---

## AI Partner (COOPERATE Mode)

- AI is **supportive**, not competitive
- AI must respect sync timing and shared grid logic
- AI must not “cheat” or see hidden future pieces
- AI behavior must be deterministic per seed/difficulty

---

## Networking (COOPERATE Network Mode)

Follow `docs/ai/cooperate_network.md`.
If `network_cooperate_multiplayer.md` exists, keep it consistent with the canonical doc.

Mandatory model:
- **Input lockstep**
- Transmit inputs only (no board state replication)

Determinism requirements:
- Fixed tick (e.g. 60 Hz)
- Shared RNG seed
- Deterministic gravity, rotation, locking, scoring

Technology:
- Use **ENet**
- Do NOT use SDL_net or TCP-only networking

Architecture:
- Networking must be isolated (e.g. `src/network/NetSession.*`)
- Game logic must not care if partner is local, AI, or network

Robustness:
- Input delay buffer (4–6 ticks)
- Periodic desync hashing
- Graceful disconnect handling

Do NOT implement:
- Rollback
- Full state sync
- Server-authoritative sim
- Matchmaking SDKs
- Versus mechanics

---

## Agent Behavior Rules (IMPORTANT)

- Always read relevant markdown specs **before coding**
- Treat markdown specs as authoritative
- Do not invent APIs
- Do not assume external libraries exist
- Generate code **file by file**, not everything at once
- Ask before changing architecture or ownership boundaries

---

## When to Ask Before Proceeding

Ask the maintainer if unclear:
- UX or menu flow decisions
- Adding dependencies
- Refactors vs local patches
- Platform-specific behavior
