On this page

Project configuration reference

Manual contents | First model | Programming Main | Quick reference

Project describes the world and its interface. Main, Patch, and Turtle describe what happens in that world. A slider does not implement a rule, a palette does not create state, and a visit mode does not create populations.

This reference covers the patch/turtle settings used in the guide, assuming lifecycle: "aligned" and the JavaScript runtime. It is not a catalog of every deployment, analysis, or system-dynamics option.

1. Write a Project definition

In Studio's Project tab, keep the declaration const Project = { ... };. It is JavaScript, so comments and trailing commas are allowed, but the configuration must survive JSON serialization: use strings, finite numbers, booleans, arrays, objects, and null. Put functions and classes in the code tabs. Do not replace the declaration with an export default.

Here is a complete configuration compatible with the original Walkers Main, Patch, and Turtle. It differs from that tutorial by using an initial-population input, adding a toggle, and declaring a logger. The original Turtle still reads SPD explicitly each tick; MOVE and EVENTS do nothing until you add code using them.

const Project = {
  version: 0.2,
  name: "Walkers",
  title: "Configurable walkers",
  lifecycle: "aligned",
  frameWidth: 1170,
  frameHeight: 1000,
  connect: true,
  visitMode: "A",
  dt: 1,
  cell: {
    cellSize: 16,
    rowDim: 20,
    colDim: 30,
    topology: "cart",
    boundary: "Wrap",
    palette: ["#f0f4e8"]
  },
  agent: {
    count: "PPL",
    palette: ["#1f77b4"],
    defaults: {
      color: 0,
      size: 0.6,
      shape: "circle",
      speed: 0.5,
      theta: null
    },
    edge: "Wrap",
    movement: "Trajectory",
    motion: "Continuous",
    collisions: "None",
    agentGrid: true,
    start: "random"
  },
  inputs: [
    [
      {
        code: "PPL", type: "slider", legend: "Initial population",
        min: 0, max: 100, step: 1, value: 40, vtype: "Integer"
      },
      {
        code: "SPD", type: "slider", legend: "Speed",
        min: 0, max: 1, step: 0.1, value: 0.5, vtype: "Double"
      },
      {
        code: "TURN", type: "slider", legend: "Maximum turn (degrees)",
        min: 0, max: 90, step: 1, value: 15, vtype: "Integer"
      }
    ],
    [
      {
        code: "MOVE", type: "toggle", legend: "Movement",
        left: "Off", right: "On", value: 1
      }
    ]
  ],
  displays: [
    {
      code: "RIGHT", site: "display_01", type: "linechart",
      dom: [0, 100], ran: [0, 100], width: 460, height: 275,
      legend: ["Turtles in right half"], palette: ["#1f77b4"]
    },
    {
      code: "EVENTS", site: "display_11", type: "textdisplay",
      name: "Model events", rows: 8, cols: 48, max: 25
    }
  ]
};

Use the slots actually present in your app shell; a site name does not create a slot. Back up your current app before replacing sources.

2. Identity, frame, and connection

Field Meaning and advice
name Internal app name, also used in saved-preset keys. Keep the generated app/class/import naming consistent. Renaming can change which presets are found.
title Human-readable title; use spaces here if desired.
version Configuration compatibility metadata, not your model's version number or lifecycle selector. These examples use 0.2, the currently supported format; newer values produce a compatibility warning.
lifecycle Set exactly "aligned" at the top level. Omitting it retains legacy behavior.
frameWidth, frameHeight App frame dimensions in pixels, not grid dimensions. The current frame resizer enforces a minimum width of 800.
connect true connects automatically after startup; false leaves connection to the user. It is not an instruction to start Run.

Saved/shared presets may replace initial input values or starts at startup. If an old saved setting appears instead of a new Project value, inspect preset selection before changing the model rule. Project edits affect a newly launched app, not the already-running window.

3. Configure the patch world

Main must still call initializePatches(this.Patch) from initCells(). Patch-only models omit agent and initAgents(). An agent model with a zero initial count still includes both if it will create turtles later.

cell field Meaning
rowDim, colDim Positive integer row/column counts. Use numeric constants for the guide examples.
cellSize Display size in pixels. A square world is roughly colDim * cellSize by rowDim * cellSize pixels.
topology "cart" for square patches (the default), "hex" for hex patches.
boundary "Edge" or "Wrap"; choose explicitly rather than relying on the Wrap default.
palette Nonempty array of drawing colors. Ordinary integer patch colors select its entries, starting at zero.
start Initial patch-color overrides; use the flat triples shown below. Omit for no overrides.
colorScale Optional drawing scale, normally 1. Color values are divided by it before palette interpolation.

Initial patch colors

This is a property fragment inside cell, not a whole Project:

start: [10, 10, 1, 11, 10, 1]

It initializes patches (10, 10) and (11, 10) to color 1. Supply a palette with at least two entries and keep coordinates inside the world. The guide uses flat column/row/color triples for the initialization message path. Do not confuse these with turtle start records below. Initial color is applied before aligned Patch init; world reset restores the saved baseline unless model code intentionally replaces it.

These are color starts, not arbitrary custom-state starts. In Heat, the heat Store is initialized separately and setup derives its color.

What a boundary changes

With Edge boundaries, neighborhood queries skip outside positions. However, main.patch(col, row) clamps an outside lookup to an edge patch; it does not return null. With Wrap, lookups and neighborhoods cross opposite edges. See lookup contracts.

Hex requires a HexPatch-derived Patch class as well as topology: "hex". Hex addresses use doubled columns and valid parity, not ordinary square addresses. Do not convert a working square model merely by changing this string; review its neighborhoods, initial coordinates, and movement.

Palettes are drawing, not units

Cell and agent palettes are independent. Color 1 on a patch need not resemble color 1 on a turtle. Use hex strings such as "#1f77b4" when interpolating; fractional color values blend adjacent entries and palette indexing cycles. For discrete states, keep colors at intended integer indices. For continuous quantities, keep the precise value in a Store and derive drawing color. Neither cellSize nor colorScale changes the model's stored quantity.

4. Configure turtles

Main must call initializeTurtles(this.Turtle) in initAgents(). The presence of the Turtle tab alone does not create a population.

agent field Meaning
count Initial count: a nonnegative integer or an exact input code such as "PPL". Nonempty explicit starts override it.
palette Nonempty array of agent drawing colors.
defaults Initial color, size, shape, speed, and heading; include all five.
start "random", "randomPatch", or a nested array of full start records.
edge "Wrap", "Bounce", or "Stop" turtle boundary policy; independent of cell.boundary.
movement "Trajectory" for base speed/heading movement; "Next_Location" for model-proposed positions.
motion "Continuous" permits fractional positions; "Discrete" uses the runtime's discrete movement calculation.
collisions "None" for no turtle collision response; "Gas" for built-in gas-style handling. Neither implements an ecological interaction rule.
agentGrid Set true for patch occupancy and local turtle queries. Do not rely on false disabling indexing: the current runtime falls back to true.
wallBounce, wallColor Optional built-in wall handling, with a numeric patch color identifying walls. Keep these with a verified compatible model; they are not general path planning.
colorScale Optional drawing scale for the agent palette, normally 1.

Use "Continuous", "Trajectory", "None", and explicit boundaries as the simple starting point. Discrete movement, collision handling, and hex movement have additional semantics; changing a setting is not a substitute for testing your Turtle rule. The base super.turtleStep() is needed for trajectory movement. See Programming turtles.

Defaults and units

agent.defaults field Meaning
color Numeric agent-palette value; null requests random palette selection for generated turtles.
size Drawing size in world units; supply a positive number.
shape Use "circle" or "rectangle" in Project. Runtime code uses Shape values instead.
speed Movement distance per base trajectory step; use a positive number or a supported input-code binding.
theta Radians: zero east, positive toward south. Null gives generated turtles random headings; a number supplies a heading.

With cellSize 16, a movement of 0.5 world units is about eight pixels. Do not supply degrees for theta. TURN in Walkers is a degree-valued model input converted by its code, not a change to the heading convention.

Zero-default trap: numeric defaults.speed: 0 currently falls back to 1. Use Walkers' explicit currentSpeed in setup and nextSpeed in step when zero and current-slider reset behavior matter. Numeric size: 0 similarly falls back to 1; it is not a reliable way to hide turtles.

Explicit turtle starts

Use full records, not abbreviated triples:

const singleStart = [
  [0, 14.5, 5.5, 0, 0.6, 0, 0.5, 0]
];

Set agent.start to that array in Project (or paste the array directly). Each record is:

[id, x, y, color, size, shapeNumber, speed, theta]

Shape number 0 is circle, 1 rectangle. Speed and heading here are numeric. IDs are normally sequential from zero; do not treat them as durable identities. This one record overrides count 40 and creates one turtle. The guide's runtime tests compare direction modulo a full rotation: an explicit heading zero may be represented internally as minus two pi.

"random" generates continuous positions; "randomPatch" generates patch coordinates, not automatically square centers at .5. Normal world reset reuses captured starts; it does not promise a fresh spatial sample or rewind all later random draws. For a fresh initialization, relaunch/reinitialize.

Bind a default to an input, or read the input yourself

The supported speed binding is a property inside agent.defaults:

speed: "SPD"

The code must match a declared input. The runtime reads it at initialization and installs a listener that assigns speed to the current turtle population when the parameter changes. Theta supports a corresponding heading binding. These assignments are immediate built-in state initialization, not pending per-tick decisions. They can replace local reset baselines.

They are not arbitrary expression evaluation, and not every Project field accepts input-code strings. In particular, do not assume palette, boundary, or shape can name a slider.

Do not combine a binding with a conflicting Turtle speed rule. Walkers instead reads SPD explicitly in setup and every step. That makes its policy clear, including Reset with today's SPD value. A default binding alone does not guarantee that policy: recreated turtles can receive captured start values until another parameter-change event occurs.

5. Choose execution and time settings

Field Use
visitMode Choose which individual rules run, in which order; see below.
dt Positive simulation-time increment, normally 1 for these discrete models.
maxTime Optional end time; omit for no configured limit.
simSpeed Initial run-speed control setting, normally 100; affects pacing, not agent distance.
minDelay Advanced pacing setting; normally leave it alone. Not a simulation-time unit.
visitMode Individual rules
"C" Selected patches
"A" Turtles
"C_A" Selected patches then turtles, with a common commitment afterward
"A_C" Turtles then selected patches, with a common commitment afterward
"C/A", "A/C" Advanced modes with an intermediate shift between groups
"No" No automatic individual steps

The ordinary tick is coordinate → individual rules → commit → clock advance → update. Patch selection is separate: register always-active patches in setup with this.main.visitAlways(this). Do not use visitAll = true as a once-per-tick shortcut. See patch activation.

Time and movement are distinct. Base turtle trajectory movement uses speed per step, not speed multiplied by Project dt. A custom per-tick food/heat rule also does not automatically rescale when dt changes. Changing dt from 1 to 0.5 changes the clock increment; it does not halve every action. Use dt 1 until your rules explicitly define another time interpretation. System-dynamics integration modes and their time-step controls are outside this reference; start from an appropriate system-dynamics model for those.

6. Declare inputs and implement their effects

A flat inputs: [control, control] makes one row. Nested arrays, as in the complete definition above, make multiple rows. Do not mix the two shapes. Use unique case-sensitive input codes.

Slider field Meaning
code Name Main uses in getParam(code)
type "slider"
legend User-facing label
min, max, step Control range and increment
value Startup value within the range
vtype "Integer" or "Double"
tooltip Optional explanation

A "toggle" uses left, right, and value (0 or 1) instead of a slider range. Main reads it with getBParam, which tests for value 1. These are Main methods, not Project properties:

get PPL() { return this.getParam("PPL"); }
get SPD() { return this.getParam("SPD"); }
get MOVE() { return this.getBParam("MOVE"); }

Patch/Turtle accesses these as this.main.SPD, for example. To make the MOVE toggle affect Walkers, replace its Turtle step's speed proposal with this.nextSpeed = this.main.MOVE ? this.main.SPD : 0; after adding the MOVE getter to Main. Heading updates and time still advance when movement is off.

Decide the read policy: each tick for a live rule, setup/reset for a new starting quantity, or initialization for population/geometry. Changing an input alone does not hatch turtles, reset Stores, or make a model valid outside its intended parameter range. UI slider bounds are not validation of arbitrary programmatic parameter messages.

7. Declare outputs with matching value shapes

displays defines destinations; Main must publish to the exact code. Publish initial values in setup, then committed values in update.

Display field Meaning
code Unique output identifier used by show, showList, or logging
site Existing slot ID in the app layout, not a title or a new element
type Display kind, e.g. "linechart" or "textdisplay"
dom, ran Line-chart time and value ranges
width, height Chart dimensions in pixels
legend Line-series names, in output order
palette Series drawing colors, in that same order

For the complete definition, Main can use:

this.show("RIGHT", this.turtles.size);
this.log("EVENTS", `Time ${this.currentTime}: ${this.turtles.size} turtles`);

This is an output-call illustration: it would chart total population instead of the original Main's right-half count. Keep the label and computation consistent in your model.

For a two-series chart configured with legend: ["Left", "Right"], publish this.show("HALVES", left, right) or this.showList("HALVES", [left, right]). Do not use show("HALVES", [left, right]): it produces one array-valued argument rather than two series. Declaring a display does not automatically create the matching output call.

A text logger uses type: "textdisplay", name, rows, cols, and optional max (retained message batches). Use log to append messages and clearLogger to request clearing; it is not a numeric line chart. See Main output.

XY/XYZ charts, bar charts, tables, and histograms have different ranges and payload shapes. Do not convert a line chart just by changing its type. The histogram type name in the current display factory is "histo", not "histogram". Copy a working matching example for these advanced displays. Small numeric readouts use the top-level property spys (that spelling), with entries such as {code: "TOTAL", legend: "Total population", value: 0}; Main can publish show("TOTAL", count).

8. Live change, Reset, or relaunch?

This table describes ordinary aligned world Reset, without a model-specific override, automatic rerun, or Project hardReset: true. That advanced flag makes the Reset control reinitialize instead, changing object-lifetime behavior.

Change Ordinary effect Apply deliberately
Move a slider read every step Next rule reads the new value Step; no Reset needed
Move a bound speed/theta slider Listener assigns the current turtles' state No Reset needed; consider conflicts with model rules
Change a setup/reset-only input Existing state is not automatically rebuilt Reset if the owner rereads it there
Change PPL used by agent.count Parameter changes; population does not resize Full reinitialization with current inputs, not ordinary Reset
Edit grid dimensions, boundaries, topology, palettes, defaults, or start arrays in Project Running app keeps its loaded configuration Save All and launch the updated app
Edit inputs, displays, slots, frame size, lifecycle, visitMode, or dt in source Running app does not load source edits on Reset Save All and relaunch
Press ordinary Reset Time and owner state reset; patches survive, turtles are recreated from saved starts/count Check both output and appearance at time zero

Ordinary Reset retains current input values, but does not reevaluate every Project binding. In particular, agent.count: "PPL" is resolved at agent initialization and the count is retained for ordinary world reset. For experiments with another population, use a full reinitialization path that sends current parameters, or edit the startup value and relaunch. Do not add manual init calls to Main/Patch constructors to force this.

Use troubleshooting when startup differs from Reset. The guide tests execute this reference's configuration and examples, including explicit starts, parameter timing, population reinitialization, zero-speed behavior, output shapes, and dt versus movement. They do not certify every advanced display or browser layout.

9. Where the settings are consumed

For a precise implementation check:

Older projects contain deployment paths, preset/upload settings, RAM panels, or equation definitions. Those need their matching shell/model code; they are not required additions to a simple patch/turtle Project. See Studio Project help for broader configuration context.