Skip to content

Zones & bounds

Patterns for the spatial side of a game: keeping players in bounds, tracking occupancy, and gating zones by state.

The friendliest boundary: a toast when you leave, a toast when you return. No elimination. Both conditions are edge-triggered, so they fire once per crossing.

- id: out_of_bounds
when: { kind: left_zone, who: any, zoneId: play_area }
do:
- { kind: send_event, to: same, event: { type: toast, text: "Out of bounds." } }
- id: back_in
when: { kind: entered_zone, who: any, zoneId: play_area }
do:
- { kind: send_event, to: same, event: { type: toast, text: "Back in bounds." } }

Source: apps/wage-engine/src/games/tag/game.yaml.

To let other rules ask “is this player in the zone?”, flip a flag on entry/exit (this is the King of the Hill inHill pattern):

- id: enter_hill
when: { kind: entered_zone, who: any, zoneId: hill }
do: [{ kind: set_state, target: same, key: inHill, value: true }]
- id: leave_hill
when: { kind: left_zone, who: any, zoneId: hill }
do: [{ kind: set_state, target: same, key: inHill, value: false }]

Now state.inHill is queryable by a scoring tick rule. See Scoring.

For boundaries the engine should enforce (reject the position update), use zone flags in the map rather than rules:

  • navigable: false — an unconditional wall; players can’t enter.
  • blockedBy: { key, value } — keep matching players out (e.g. a base only your team may enter).
  • confinedBy: { key, value } — keep matching players in (e.g. a holding pen until released).
zones:
- id: red_base
blockedBy: { key: teamId, value: blue } # blue players can't step into red base
shapes: [ /* … */ ]

See Map & zones for the full field list.

Punch an exclusion cutout so random item spawns (spawn_item inZone / items spawnZoneId) avoid part of a zone — e.g. keep loot off the ships:

shapes:
- { id: island, kind: rectangle, from: { x: -35, y: -35 }, to: { x: 35, y: 35 } }
- { id: no-ship, kind: circle, center: { x: -35, y: 35 }, radius: 15, exclusion: true }

Source: apps/wage-engine/src/games/pirates_booty/game.yaml.