On this page
- 1. Write a Project definition
- 2. Identity, frame, and connection
- 3. Configure the patch world
- 4. Configure turtles
- 5. Choose execution and time settings
- 6. Declare inputs and implement their effects
- 7. Declare outputs with matching value shapes
- 8. Live change, Reset, or relaunch?
- 9. Where the settings are consumed
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:
- Browser configuration and defaults.
- Input/output registration.
- Initialization message construction.
- Runtime initialization and Main population creation.
- Turtle defaults/bindings.
- Display construction.
- Ordinary Reset control versus full reinitialization.
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.