Capture & carry
The carry loop — grab, run, score, or get tagged and drop — built from items and interactions. Worked from Capture the Flag and Pirate’s Booty.
1. Declare the item and spawn it
Section titled “1. Declare the item and spawn it”itemTypes: - kind: red_flag label: "Red flag" icon: { type: glyph, value: "⚑", color: "#ef4444" }items: - { kind: red_flag, count: 1, spawnPointId: red_flag }2. Pick it up (walk-over)
Section titled “2. Pick it up (walk-over)”A worldItem + auto interaction is a walk-over grab. Restrict who can take it
with initiatorFilters:
interactions: - verb: grab_red_flag label: "Grab flag" target: worldItem trigger: auto rangeMeters: 5 itemKinds: [red_flag] initiatorFilters: [{ key: teamId, value: blue }] # only blue can take the red flag- id: pickup_red_flag when: { kind: interaction, verb: grab_red_flag } # same = grabber, other = the item do: - { kind: set_state, target: same, key: hasFlag, value: red } - { kind: destroy_item } # consume the world item - { kind: send_event, to: same, event: { type: toast, text: "Grabbed it — run home!" } }Track carriage in player state (hasFlag) so other rules can check it; the
world item itself is consumed and re-spawned later.
3. Score by delivering
Section titled “3. Score by delivering”- id: blue_score when: kind: and children: - { kind: entered_zone, who: any, zoneId: blue_base } - { kind: compare, op: eq, left: { ref: same.teamId }, right: blue } - { kind: state_equals, who: same, key: hasFlag, value: red } do: - { kind: set_state, target: same, key: hasFlag, value: null } - { kind: increment_state, target: { byTeam: blue }, key: score, by: 1 } - { kind: spawn_item, item: red_flag, atPoint: red_flag } # reset for next round4. Drop on tag
Section titled “4. Drop on tag”A proximity rule where same is the carrier and other is an enemy drops the
item where it fell so it’s contestable:
- id: blue_carrier_tagged when: kind: and children: - { kind: proximity, a: any, b: any, meters: 5 } - { kind: compare, op: eq, left: { ref: same.teamId }, right: blue } - { kind: state_equals, who: same, key: hasFlag, value: red } - { kind: compare, op: eq, left: { ref: other.teamId }, right: red } do: - { kind: set_state, target: same, key: hasFlag, value: null } - { kind: spawn_item, item: red_flag, at: same } # drop at the carrier's positionAll four snippets: apps/wage-engine/src/games/capture_the_flag/game.yaml.
Variations
Section titled “Variations”- Marker glow while carrying. Add a
theme.playerMarkersrule keyed on the carry state so carriers stand out:(Pirate’s Booty does this withtheme:playerMarkers:- { when: { key: carrying, value: true }, color: "#fbbf24" }carrying.) - One-at-a-time. Add
initiatorFilters: [{ key: state.carrying, value: false }]to the grab so a loaded player can’t grab a second. - Consumable currency. For coins kept in inventory rather than a carry flag,
remember the picked-up item’s id (
set_state … value: { ref: other.id }) so you candestroy_itemexactly that one on deposit (Pirate’s Booty’s coin loop).