# ARCHITECTURAL REPORT: BOSS GATE CONTROLLER & VISUAL SEAL STATE MACHINE

> **Module**: `client/webapp/js/engine/boss_gate_controller.js`  
> **Author**: Explorer M3 2 (`explorer_m3_2`)  
> **Target**: Orchestrator 11, M3 Worker, and Downstream Subagents  
> **Reference**: `ORIGINAL_REQUEST.md § R3 & § R5`, `PROJECT.md § Feature 16, 21, 22, 32`  
> **Status**: Architecture Designed & Validated (199 Lines, $\le 200$ Budget Verified)

---

## 1. Executive Summary & System Overview

In the FreeExile PoE2-style procedural wilderness map architecture, the **Boss Gate** serves as the critical milestone gate separating the open wilderness exploration zones from the sealed Boss Arena chamber.

`BossGateController` orchestrates five interconnected game systems:
1. **Procedural Grid Ingestion**: Resolves gate coordinates $(gx, gy)$ either from server binary header metadata (`currentMapMetadata.bossGate`) or via automated fallback tile scan for `TileType.BOSS_GATE` (code 10 / 15).
2. **State Machine Lifecycle**: Maintains strict state flow: `LOCKED` $\rightarrow$ `UNLOCKED` $\rightarrow$ `BREACHED`.
3. **Collision Enforcement**: Seamlessly integrates with `CollisionEngine.isPositionBlocked` to project an impassable obstacle at $(gx, gy)$ while `LOCKED`, with zero dynamic allocations.
4. **Dynamic Tile Mutation & Chunk Cache Invalidation**: Upon fulfilling kill conditions (e.g. defeating 3 monster packs), mutates map grid at $(gx, gy)$ from `BOSS_GATE` to `FLOOR` (code 1 / 0) via `window.setTileAt` and triggers `TileMapRenderer.markChunkDirty(gx, gy)` to re-bake the $16 \times 16$ offscreen chunk canvas.
5. **Visual Seal VFX & Proximity Lore**: Renders a 2.5D isometric glowing cyan/gold rotating seal rune over the locked threshold and displays an immersive wuxia lore popup when the player ventures within 3 tiles of the gate.

---

## 2. Boss Gate State Machine Lifecycle

```mermaid
stateDiagram-v2
    [*] --> LOCKED: Map Loaded / Init
    LOCKED --> UNLOCKED: Kill Threshold Met (Kills >= requiredKills)<br/>or unlock() triggered
    UNLOCKED --> BREACHED: Player enters gate (dist < 0.8 tiles)<br/>or breach() triggered
    BREACHED --> [*]: Arena Encounter Active

    state LOCKED {
        [*] --> Sealed
        Sealed: Tile blocked in CollisionEngine
        Sealed: Rotating cyan/gold seal rune rendered
        Sealed: Proximity lore popup within 3 tiles
    }

    state UNLOCKED {
        [*] --> Dissolving
        Dissolving: Tile mutated to FLOOR via setTileAt()
        Dissolving: TileMapRenderer.markChunkDirty() called
        Dissolving: Collision cleared at (gx, gy)
        Dissolving: Aura fades to faint green/cyan glow
        Dissolving: Proximity shows "Phong Ấn Đã Giải"
    }

    state BREACHED {
        [*] --> ArenaActive
        ArenaActive: Seal completely deactivated
        ArenaActive: Proximity popup dismissed
        ArenaActive: CustomEvent 'bossgate:breached' dispatched
    }
```

### State Definitions & Invariants

| State | Collision Behavior | Tile in `currentMapGrid` | Visual Hook | Proximity Lore Popup |
| :--- | :--- | :--- | :--- | :--- |
| **`LOCKED`** | Blocked (`isPositionBlocked` = `true` within gate tile bounding box) | `10` (`BOSS_GATE`) | Full cyan core + gold outer ring rotating and pulsating | Shows remaining packs to kill and seal warning |
| **`UNLOCKED`** | Passable (`isPositionBlocked` = `false`) | `1` (`FLOOR`) | Reduced intensity aura (20% alpha), rune rings dissipate | Shows gate open notification ("Phong Ấn Đã Giải") |
| **`BREACHED`** | Passable (`isPositionBlocked` = `false`) | `1` (`FLOOR`) | Fully suppressed / dormant | Popup hidden, arena engagement active |

---

## 3. Subsystem Integration & Contracts

### 3.1. Collision Integration (`collision_engine.js`)
`CollisionEngine.isPositionBlocked(wx, wy, radius = 0.35)` checks gate obstruction in $O(1)$ without allocating memory:
```javascript
// Inside BossGateController:
isPositionBlocked(wx, wy, radius = 0.35) {
  if (this.state !== BossGateState.LOCKED || this.gateX === null || this.gateY === null) return false;
  const minTx = Math.floor(wx - radius), maxTx = Math.floor(wx + radius);
  const minTy = Math.floor(wy - radius), maxTy = Math.floor(wy + radius);
  return this.gateX >= minTx && this.gateX <= maxTx && this.gateY >= minTy && this.gateY <= maxTy;
}
```
In `collision_engine.js`:
```javascript
if (window.bossGateController && window.bossGateController.isPositionBlocked(wx, wy, radius)) {
  return true;
}
```

### 3.2. Dynamic Tile Mutation & Chunk Re-baking (`tile_map_renderer.js`)
When `unlock(floorTileCode = 1)` is called:
1. Coordinates $(gx, gy)$ are updated via `window.setTileAt(this.gateX, this.gateY, floorTileCode)`.
2. `TileGridLoader.setTileAt` writes the floor tile into `window.currentMapGrid` and immediately invokes `TileMapRenderer.markChunkDirty(gx, gy)`.
3. The affected $16 \times 16$ tile chunk is flagged `dirty = true`, causing `TileMapRenderer` to re-bake its `OffscreenCanvas` on the next frame with zero full-screen re-renders.

### 3.3. Progression Integration (`monster_system.js`)
When a monster pack is defeated:
```javascript
// MonsterSystem pack defeat hook:
if (window.bossGateController) {
  window.bossGateController.reportKill(1);
}
```
This increments `currentKills`, updates `window.zoneEncounterProgress[zoneId]`, and if `currentKills >= requiredKills`, executes `unlock()`.

---

## 4. Visual Rendering: 2.5D Isometric Seal Rune

The visual seal is rendered via `BossGateController.render(ctx, camera)`:
1. **Screen Projection**: Translates gate center $(gx + 0.5, gy + 0.5)$ via `worldToIso(wx, wy)`.
2. **Concentric Floor Aura**: An isometric compressed ellipse (`scale(1.0, 0.5)`) using a radial gradient:
   - Center ($r=0..4$): High-intensity cyan `rgba(6, 182, 212, 0.65)`.
   - Mid-ring ($r=18$): Fiery gold `rgba(245, 158, 11, 0.45)`.
   - Outer falloff ($r=36$): Transparent `rgba(0, 0, 0, 0)`.
3. **Rotating Gold Outer Rune Ring**: Radius $20\text{px}$, line width $1.5\text{px}$, stroke color `#f59e0b`, rotating at $\omega = 1.5\text{ rad/s}$.
4. **Counter-Rotating Cyan Diamond Sigil**: 4 cardinal runic vertices rotating at $-3.0\text{ rad/s}$, stroke color `#06b6d4`, line width $1.2\text{px}$.
5. **Core Energy Gem**: Floating central runic eye in `#e0f2fe`.

```
          .-----------------.
         /    Outer Gold     \
        /   Rune Ring (#f59e0b)\
       |    .-------------.     |
       |   /  Cyan Diamond \    |
       |  |   Sigil (#06b6d4)|  |
       |  |       [o]       |   |  <-- Core Gem (#e0f2fe)
       |   \               /    |
       |    '-------------'     |
        \   Pulsating Floor    /
         \  Aura (2:1 Iso)    /
          '-----------------'
```

---

## 5. Proximity Lore Popup Architecture

In `BossGateController.update(dt, playerWx, playerWy)`:
- Distance: `dist = Math.hypot(playerWx - (this.gateX + 0.5), playerWy - (this.gateY + 0.5))`.
- **Activation Boundary**: $dist \le 3.0$ tiles.
- **Hysteresis Deactivation**: $dist > 3.5$ tiles (prevents rapid toggle jitter when hovering near 3.0 tiles).
- **DOM Container**: `#boss-gate-lore-popup`, styled with Tailwind CSS, dark wuxia palette (`bg-stone-950/90 border-amber-500/60 text-stone-200 backdrop-blur-md`), positioned centrally above the action dock.
- **Content Formatting**:
  - `LOCKED`:
    - Title: `CỔNG NIÊM PHONG` (Amber-400)
    - Description: `"Cần tiêu diệt thêm ${rem} đàn quái dị biến để phá phong ấn!"`
  - `UNLOCKED`:
    - Title: `PHONG ẤN ĐÃ GIẢI` (Emerald-400)
    - Description: `"Lối vào Huyết Đàn đã mở. Tiến vào trảm diệt Lãnh Chúa!"`

---

## 6. Code Hygiene & Constraint Compliance

- **Exact Line Count**: **199 lines** (Soft Cap 350, Hard Cap 500, Target $\le 200$ verified).
- **Universal Export**:
  - Browser Global: `window.BossGateState`, `window.BossGateController`, `window.bossGateController`.
  - ES Module: `export const BossGateState`, `export class BossGateController`.
  - CommonJS: `module.exports = { BossGateState, BossGateController, defaultBossGateController }`.
- **Zero Allocations**: `render()` and `isPositionBlocked()` allocate no objects or arrays during frame execution.

---

## 7. Concrete Delivery Files

- Architecture Reference File: `.agents/teamwork/explorer_m3_2/proposed_boss_gate_controller.js` (199 lines, tested in Node.js)
- Handoff Report: `.agents/teamwork/explorer_m3_2/handoff.md`
