Skip to content

Tutorial: Areas in Downbeat

An area is a named, concrete place that agents can inhabit — a town square, a harbor, a government hall, a restaurant. For downbeat, the entrance area is where the zine plays.

This tutorial is a reference. For narrative context on how areas work in the zine, see TUTORIAL-zines.md.


The Minimal Area Document

apiVersion: net.plantange/v1
kind: simulation.area

meta:
  title: <Human name>
  name:
    common:
      en: <machine_name>
  uuid: <unique id>

That's the absolute minimum. The Rust parser requires apiVersion, kind, meta.title, and meta.uuid. Everything else is optional.

meta.name — Two Valid Forms

Area names can be written in two ways:

Plain string (simple, preferred for bare stubs):

meta:
  name: entrance

Locale map (use when you need translated names):

meta:
  name:
    common:
      en: entrance

Either form is accepted by the parser. Pick the locale map form when you know the name may need translation; use the plain string for quick stubs.


Optional Blocks

Areas grow richer by adding optional blocks. None are required, but each unlocks something at runtime.

space

Declares the physical shape and scale of the area:

space:
  shape: point # point | circle | rectangle
  scale: medium # small | medium | large | epic
  orientation: horizontal # optional

For downbeat entrance, use shape: point (abstract) and scale: medium.

environment

Continuous field baselines — climate, atmosphere, sensory:

environment:
  climate:
    temperature: 18.5
    humidity: 0.65
    airflow: 0.3
    pressure: 101.3
  sensory:
    light_level: 0.85
    visibility: 0.9
    noise_level: 0.4
    odor_profile:
      stone: 0.3
      air: 0.7

Values are floats; most are 0.0–1.0. Omit any sub-field you don't need.

affordances

Typed activity declarations — what agents can do here:

affordances:
  - type: area.activity.gather
    class: social
    inputs:
      - agent.humanoid
      - agent.ensemble
    outputs:
      - event.gathering
    salience: 0.85

type uses dot-namespaced identifiers. class groups it semantically. inputs/outputs are content class hints. salience (0.0–1.0) weights how attractive this activity is.

constraints

Hosting limits:

constraints:
  capacity: 500
  content_types:
    - agent
    - item
    - data

capacity caps total occupancy. content_types restricts what can be present.

corporation

Declares the governing institution of the area:

corporation:
  type: townhall
  standing: sovereign
  name: Lobby Authority
Field Values Notes
type townhall, bank These are executable — runner creates service
type guild_council, land_trust, port_authority, market_board, charter Spec-only for now — recorded but no handler
standing sovereign, public, private Legitimacy regime
name any string Display name for the institution

Omit corporation entirely for abstract spaces and lobbies that have no governing body.


A Minimal Entrance Example

# area/entrance.yml
apiVersion: net.plantange/v1
kind: simulation.area

meta:
  title: Entrance Hall
  description:
    common:
      en: "The grand entrance lobby where all players begin."
  name:
    common:
      en: entrance
  uuid: 019d8202-e322-76c6-1f0a2b3c4d5e6fa2

space:
  shape: point
  scale: medium

environment:
  climate:
    temperature: 18.5
    humidity: 0.65
    airflow: 0.3
    pressure: 101.3
  sensory:
    light_level: 0.85
    visibility: 0.9
    noise_level: 0.4
    odor_profile:
      stone: 0.3
      air: 0.7

affordances:
  - type: area.activity.gather
    class: social
    inputs:
      - agent.humanoid
    outputs:
      - event.gathering
    salience: 0.85

No corporation block — entrance is a gathering place, not a legal seat.


A Staging Example — Antechamber

If you want NPCs to pre-stage before entrance (optional):

# area/antechamber.yml
apiVersion: net.plantange/v1
kind: simulation.area

meta:
  title: Antechamber
  name:
    common:
      en: antechamber
  uuid: 019d8202-e322-76c6-1f0a2b3c4d5e6fa9

space:
  shape: point
  scale: small

No environment, no affordances. Antechamber is just a waypoint.


How Areas Connect to Regions

A region references its areas by UUID in features::

# region/lobby.yml
features:
  - spec: 019d8202-e322-76c6-1f0a2b3c4d5e6fa2 # entrance
  - spec: 019d8202-e322-76c6-1f0a2b3c4d5e6fa9 # antechamber

The UUID must match meta.uuid in the area doc exactly.


Area vs Region — When to Use Which

Use simulation.area when… Use simulation.region when…
It's a specific named place It's a geographic zone
Agents concretely inhabit and act there It defines terrain, climate, ecology
It may have a corporation / institution It contains multiple areas
It's a leaf in the world graph It's a parent in the world graph

For downbeat:

  • Area (entrance) = the specific hall where the zine plays (leaf)
  • Region (lobby) = the overall entrance zone (parent)

Common Mistakes

Mistake Symptom Fix
Missing meta.uuid Parser error Add a unique UUID under meta:
kind: simulation.region in area/ folder Area handler rejects it Change to kind: simulation.area
Using unknown corporation.type Warning logged, no service Use townhall or bank for executable; use roadmap names for spec-only
space.shape not in valid list Parser error Use point, circle, or rectangle only
meta.name locale map missing common.en Name resolves as empty Add common: en: <name> inside the map
Affordance salience out of range 0.0-1.0 Behavior undefined; may clamp Keep salience between 0.0 and 1.0