90 lines
4.7 KiB
Markdown
90 lines
4.7 KiB
Markdown
# Authoritative game core
|
|
|
|
Milestones 006 and 007 provide the portable movement engine, gameplay object
|
|
systems, terminal results, and view projector. The ESP remains the only owner
|
|
of mutable game state. Reconnect behavior and browser controls remain out of
|
|
scope until their later milestones.
|
|
|
|
## Command processing
|
|
|
|
Move commands enter a fixed 16-entry FIFO. The server assigns a monotonically
|
|
increasing command sequence when an entry is accepted into the queue, then
|
|
processes entries one at a time. An accepted move crosses exactly one open
|
|
north, east, south, or west passage. Countdown commands, closed-wall moves,
|
|
out-of-order timestamps, and commands inside the configured per-player
|
|
cooldown leave authoritative game state and the state sequence unchanged.
|
|
|
|
Each player has an independent cooldown clock. Player positions never block
|
|
one another. When an accepted move ends on the other player's cell, that
|
|
command emits exactly one meeting event and advances the meeting sequence.
|
|
Observers cannot enqueue commands.
|
|
|
|
## Projection boundary
|
|
|
|
Player projections contain only cells whose Chebyshev distance from the
|
|
player is at most the server-owned active radius:
|
|
|
|
`max(abs(x - player_x), abs(y - player_y)) <= radius`
|
|
|
|
The projector selects the normal radius three or vision-effect radius six from
|
|
authoritative player state; clients cannot request a radius.
|
|
Map boundaries clip the square; walls do not occlude it. Each projection is
|
|
rebuilt from zero, so an opponent or object that leaves the current square is
|
|
omitted instead of surviving as stale state. Observer projections contain all
|
|
maze cells, static objects, and both current player positions.
|
|
|
|
The serialized view is split into bounded JSON records of at most 512 bytes,
|
|
matching the WebSocket gateway's message bound.
|
|
Every record uses the architecture's versioned envelope and carries the
|
|
authoritative state sequence, role, match phase, maze width and height,
|
|
meeting sequence, chunk index, and chunk count. Role status appears once in chunk zero instead of being
|
|
duplicated across the snapshot. Cell records contain only the cell index and
|
|
current passage flags. Object records contain kind, owner, variant, and cell
|
|
index. Player records omit the `opponent` member when that player is not
|
|
currently visible; observer records instead carry both positions in `players`.
|
|
|
|
## Gameplay resolution
|
|
|
|
Every accepted in-maze move resolves in this order:
|
|
|
|
1. Decrement an existing vision effect.
|
|
2. Consume and activate an artifact on the destination cell.
|
|
3. Pick up the lowest-owner-numbered ground key when the inventory is empty.
|
|
4. Detect a meeting and atomically return all carried keys to their owners.
|
|
5. Activate the moving player's own compass.
|
|
6. Open the moving player's own exit when they carry their own key.
|
|
|
|
The deterministic key priority matters only if voluntary drops place both keys
|
|
on one cell. Each key always has exactly one authoritative location: a ground
|
|
cell or one carrier. Inventory has one slot, dropping places the key on the
|
|
current cell, and carrying an opponent's key is allowed. A meeting clears both
|
|
inventory slots before assigning every carried key to its owner, so crossed
|
|
keys swap atomically without duplication or loss.
|
|
|
|
An unconsumed vision artifact is removed on entry and sets the player's effect
|
|
counter to ten. Only later successful moves decrement the counter; failed
|
|
moves and key drops do not. Entering another unconsumed artifact resets the
|
|
counter to ten rather than stacking effects.
|
|
|
|
Entering the player's associated compass produces one of eight direct compass
|
|
bearings toward that player's own exit. It provides neither a coordinate nor a
|
|
route. The hint remains through rejected commands and is cleared by the next
|
|
successful move unless that move activates the compass again.
|
|
|
|
## Exits and results
|
|
|
|
Entering an owner's exit while carrying the matching key opens it but does not
|
|
finish the match. The player must issue another movement command pointing out
|
|
of the map from that open exit. The first accepted outward move starts a
|
|
200-millisecond finish window. A different player exiting at the same timestamp
|
|
or up to and including 200 milliseconds later produces a draw. Once time is
|
|
strictly more than 200 milliseconds later, advancing the authoritative clock
|
|
finalizes the first player as winner. Opponent exits never open or permit an
|
|
outward move for the wrong player.
|
|
|
|
Player snapshots always contain their own inventory, remaining vision moves,
|
|
compass hint, and own-exit status. An opponent's carried key is included only
|
|
while that opponent is currently visible. Observer snapshots contain both
|
|
inventories and effect counters, both exit states and authoritative exit
|
|
timestamps, every remaining ground object, and the public match result.
|