# Game
The spine of **GANESHA: GUARDIAN OF THE PORTAL**. One shared module every
slice requires: the tuning numbers, the eight Rakshasas and their arenas,
the eleven quests, the story machine's acts, the mount points, and the event
bus. It draws nothing, moves nothing and sounds nothing — it is the contract
that lets a slice be written without knowing who else is in the world.
`require` returns one shared instance per world, so `G.state` read in the
hero slice is the same table the interface slice reads, and `G.on` / `G.emit`
is how one slice learns what another did.
## Exports
- `G.TITLE`, `G.SUBTITLE` — the title card's own words.
- `G.ART_STYLE` — the one art-direction sentence every visual decision answers to.
- `G.PALETTE` (hex, for the interface) and `G.RGB` (0-1 triples, for lights/materials).
- `G.ACT` / `G.ACT_ORDER` — the story machine's phases.
- `G.QUESTS` — the eleven quests, in order: `{ title, objective }`.
- `G.PLAYER` — the guardian's 2000 HP, speeds, stamina, jump.
- `G.ATTACKS` / `G.ATTACK_ORDER` / `G.ABILITY_BAR` — the four attacks with damage,
timing, reach, arc and cooldown.
- `G.FOES` — the eight Rakshasas: health, speed, damage, reach, behaviour, tells.
- `G.ARENAS` — the eight battlefields: ground colour, sky, sun, fog, props.
- `G.BEATS` — timings for the beats between fights.
- `G.state` — the shared run state (act, quest, arena, health, foe, banner…).
- `G.EV` — event names; `G.on(name, fn)` and `G.emit(name, payload)`.
- `G.setAct` / `G.setQuest` / `G.setArena` — the only writers of those fields.
- `G.banner` / `G.toast` / `G.kick` / `G.freeze` — the presentation verbs.
- `G.MOUNTS` / `G.SLICES` — where each slice is booted.
- `G.clamp` / `G.lerp` / `G.damp` / `G.angleDelta` / `G.horizDist` / `G.yawTo`.
- `G.arena()` / `G.foeAt(i)` / `G.questForArena(i)` / `G.restart()`.
## Usage
```luau
local G = require("game.Game")
G.on(G.EV.FOE_DIED, function(foe)
G.setQuest(G.questForArena(G.state.arena))
end)
if G.state.act == G.ACT.FIGHT then
local arena = G.arena()
local tuning = G.foeAt(G.state.arena)
end
```
## Notes
- **State has one writer per field.** The hero slice owns `health`, `stamina`
and `cooldowns`; the foes slice owns `foe` and `bossBar`; the world slice owns
`act` transitions from its own beats. Announce changes with `G.emit` so the
interface and the sound slice hear them.
- **The bus is per world, not per frame.** Subscribe in `start()` and keep the
unsubscribe function the subscribe returns; drop it in `onDestroy()` or a
reload will leave two listeners running.
- **Arenas are 1-indexed and match `G.FOES` by `arena.foe`.**
# Director
The referee of **GANESHA: GUARDIAN OF THE PORTAL**. One instance, on the scene's
`Director` entity. It boots every slice onto its mount, owns the story machine's
act transitions, keeps the shared timers (banner, toast, camera shake, hit-stop)
and hands the interface slice the verbs it needs. It draws nothing, moves
nothing and sounds nothing — the slices do all of that, and this decides when.
## Public fields
None. The Director's state is the run state itself, held in `game.Game.state`.
## Methods
- `:beginRun()` — leave the title screen, open at the festival (quest 1, arena 1).
- `:retryArena()` — restore the guardian and re-enter the arena they fell in.
- `:startFight()` — begin the current arena's fight with no intro beat.
- `:toTitle()` — return to the title screen.
- `:liveSlices()` — the slice ids whose component type is registered and running.
## Lifecycle
- `start()` — boots the slices named in `G.SLICES`, subscribes to the bus, and
parks the run on `G.ACT.TITLE`.
- `update(dt)` — counts down the banner, toast and shake timers in real time
(dividing out `engine.timeScale`), and drives hit-stop by holding
`engine.timeScale` low for the freeze's duration.
- `onDestroy()` — drops every bus subscription and restores `engine.timeScale`.
## Notes
- **A slice that is not written yet is skipped, not an error.** Each entry in
`G.SLICES` is checked with `asset.exists(name, "component")`; an unregistered
one is passed over and lands the moment its component file exists. That is what
lets the slices be built one at a time against a scene none of them writes.
- **The mount names are the interface.** `G.MOUNTS` names the five entities the
scene lays out; a slice reaches its mount with `entity.find(G.MOUNTS.Hero)`
rather than guessing a path.
- **Acts advance from events, never from polling.** The Director reacts to
`FOE_DIED` and `PLAYER_DIED`; the world slice reports a portal reached by
emitting its own event and letting this decide.