Items & interactions
Items are things with identity that live in the world or in an inventory. Interactions are how players act on each other and on items. Together they cover tags, captures, pickups, and uses.
itemTypes
Section titled “itemTypes”The authoritative registry of item kinds. Every kind referenced anywhere
(items, interactions.itemKinds, spawn_item.item) must be declared here,
or the ruleset fails to load.
interface ItemType { kind: string; label: string; icon: ItemIcon; useLabel?: string; // button text for a held-item "use" interaction}
interface ItemIcon { type: "glyph" | "mdi"; value: string; // a unicode char (glyph) or Material Design icon name (mdi) color?: string; // hex; the symbol is drawn white on a chip of this color}itemTypes: - kind: treasure_chest label: "Treasure chest" icon: { type: mdi, value: "treasure-chest", color: "#fbbf24" } - kind: coin label: "Coin" icon: { type: glyph, value: "🪙", color: "#1e3a5f" }Source: apps/wage-engine/src/games/pirates_booty/game.yaml.
glyph—valueis a literal unicode character/emoji ("⚑","🪙").mdi—valueis a Material Design icon name ("flag","treasure-chest"; a"mdi:"prefix is normalized away). If the name can’t resolve, clients draw the colored chip with no symbol — never an invisible item.colorshould never be white (the white symbol would vanish).
Placement specs: how many of each kind spawn at game start, and where.
interface ItemSpawnSpec { kind: string; count: number; spawnZoneId?: string; // random points inside this placed zone spawnPointId?: string; // exactly at this placed map point}Provide one of spawnZoneId (scatter) or spawnPointId (precise). Zone spawns
honor exclusions.
items: - { kind: treasure_chest, count: 12, spawnZoneId: treasure_island } - { kind: blue_flag, count: 1, spawnPointId: blue_flag }The runtime item itself:
interface Item { id: string; kind: string; position?: LatLng; // set while in the world holderId?: string; // set while held; pickup is a custody transfer keeping the id acquiredTs?: number; // orders inventory display}A player’s inventory is simply the items whose holderId is that player.
interactions
Section titled “interactions”A player-initiated, range-gated, optionally-confirmed action. GPS proximity can’t tell the engine a real-world tag/handoff happened — an interaction lets a player assert it against a nearby eligible target, and the server validates it.
interface InteractionSpec { verb: string; label: string; target?: "player" | "worldItem" | "heldItem"; // default "player" trigger?: "auto" | "manual"; // default "manual" itemKinds?: string[]; // for item targets rangeMeters: number; confirm?: "none" | "mutual"; // default "none" confirmTimeoutMs?: number; // default 15000 initiatorFilters?: { key: string; value: unknown }[]; targetFilters?: { key: string; value: unknown }[]; teamRelation?: "same" | "other"; icon?: string;}Fields
Section titled “Fields”verb— the key rules match on (tag,capture,grab_chest). The engine ascribes no meaning; only your rules do.label— button text on the initiator’s phone.target— what it acts on:player(default) — a nearby player.worldItem— an item lying in the world (a pickup/grab).heldItem— an item already in the initiator’s inventory (a use).
trigger—manual(tap a button; the default) orauto(the engine claims it the instant range + filters pass — a walk-over pickup).autois only valid withtarget: worldItem.itemKinds— for item targets, restrict which kinds the verb applies to.rangeMeters— max initiator↔target distance (haversine). ForworldItemit’s the pickup radius; ignored forheldItem.confirm—none(apply immediately) ormutual(target must confirm withinconfirmTimeoutMs, default 15000 ms).initiatorFilters/targetFilters— predicates that must all pass. Key isteamIdorstate.<name>; value is the required value.teamRelation— constrain initiator/target teams:sameorother. Omit for no constraint.icon— optional UI hint.
Player interaction (a tag)
Section titled “Player interaction (a tag)”interactions: - verb: tag label: "Tag" rangeMeters: 5 confirm: none initiatorFilters: [{ key: "state.it", value: true }] targetFilters: [{ key: "state.it", value: false }]Binds initiator = same, target = other. Source: tag/game.yaml.
Auto world-item pickup
Section titled “Auto world-item pickup”interactions: - verb: grab_chest label: "Grab chest" target: worldItem trigger: auto rangeMeters: 3 itemKinds: [treasure_chest] initiatorFilters: [{ key: state.carrying, value: false }]Binds initiator = same, item = other. Source: pirates_booty/game.yaml.
Reacting in a rule
Section titled “Reacting in a rule”Whatever the target, you react with an interaction condition on the verb:
- id: pickup_chest when: { kind: interaction, verb: grab_chest } do: - { kind: set_state, target: same, key: carrying, value: true } - { kind: destroy_item } # consumes the item bound as `other`See the interaction condition and
item actions for the full picture.