# DeepFieldGame
The session. One instance, on the entity `df_game`, put there by
`game/df_boot.module`. It is the only thing in Deep Field that decides.
It owns: the phase machine, the control scheme, the depth ceiling, the
attention pressure, when something rises out of the black, what a committed
identification did, and when the water below opens up.
It does not draw, move the lure, or animate an animal. That is `DfLure`,
`DfCreature` and the species modules.
## Phases
`Core.state.phase`, mirrored on the `phase` field, and announced on the
`"phase"` event.
| Phase | What is happening | How it leaves |
|---|---|---|
| `title` | Before the dive. | `advance`, `:beginDive()`, or `autoBegin` after `autoBeginAfter` seconds |
| `opening` | The staging slice's opening. | its `cutscene` end, `advance`, or `openingTimeout` — and immediately if nothing sets `Core.state.cinematic` within 1.5 s |
| `dive` | The loop. Line, lamp, sightings, attention. | attention reaching 1.0, or the specimen being named |
| `resolution` | The staging slice's ending. | its `cutscene` end, `advance`, or `openingTimeout` |
| `end` | The lamp is out. | `advance` returns to `title` with a fresh `Core.state` |
## What other slices call
```luau
local g = entity.find("df_game").component.get("DeepFieldGame")
g:beginDive() -- a title screen's Begin button
g:setPhase("dive") -- move the machine by hand
g:endDive("quit") -- put the lamp out
g:submitIdentification("moonjelly") -- what the journal commits; returns the result table
g:raise("moonjelly") -- call one up on purpose; "" if the water is busy
g:onCutscene("opening", "end") -- forwarded from the `cutscene` event by df_boot
```
`submitIdentification` is also reachable as the `"identify:submit"` event
(`{ guessId = ... }`), which is what the journal actually emits;
`game/df_boot.module` forwards it. Either way the answer arrives back on
`"identify:result"` with the whole outcome:
```luau
{ correct, reason, actualId, guessId, confidence, band, newly, apex,
attentionDelta, leaveReason, burn, note }
```
`reason` is `"correct"`, `"wrong"`, `"gone"` (it had already turned),
`"no-sighting"`, `"no-guess"` or `"already-called"`. `band` is
`"certain"` / `"probable"` / `"glimpsed"`, graded off `Core.readability`.
`note` is a line of naturalist's prose the journal can print as-is.
## A slice that owns the title screen
The game starts itself so a missing shell cannot strand it. A slice that
puts up a real title turns that off from its own `start()`:
```luau
local g = entity.find("df_game").component.get("DeepFieldGame")
if g then g.autoBegin = false end
```
## Readouts for the HUD
`phase`, `nextSightingIn`, `depthCeiling`, `sightingSpecies`,
`sightingConfidence`, `lastResult`, `lastNote`, `diveSeconds`. Everything
else the HUD needs is on `Core.state`.
`depthCeiling` is the progression gate — the line stops there, and it moves
deeper as strata unlock. It is a readout, not a setting.
## Two events beyond `df_core`'s list
`df_core` is frozen, so the input map's two remaining edges carry their own
names. Listen for them if you want the keyboard as well as your own button:
- `"input:journal"` — `{ open }`, the journal key
- `"input:pause"` — `{}`, the pause key
Slice owner: core-loop.