On this page

NLTurtle API reference

Manual contents | Programming turtles | Project settings | Neighborhood reference | Supporting types | Alphabetical index

Source: nlturtle.js. Inheritance: NLTurtle extends NLRoot extends APIRoot. The module exports NLTurtle and re-exports Shape and NLRoot.

This page inventories declared instance members and the static goDiscrete helper. Examples assume lifecycle: "aligned". For complete models use Walkers, Grazers, or the obstacle example. Internal/legacy entries are identified, not presented as supported shortcuts. Unless stated otherwise, mutating methods return undefined.

1. Subclass and lifecycle

import {NLTurtle} from "@nwk/api/nlturtle.js";

class StraightTurtle extends NLTurtle {
  setup() {
    this.currentSpeed = this.main.getParam("SPD");
  }

  turtleStep() {
    this.nextSpeed = this.main.getParam("SPD");
    super.turtleStep();
  }
}

export default StraightTurtle;

Use an aligned agent Project with an SPD input, trajectory movement, continuous motion, explicit boundaries, and a Main that creates patches and turtles. This turtle reads current speed at setup/reset and each tick. With no heading updater it keeps its supplied heading.

Member Role / contract
constructor(id, main) Runtime construction. Preserve super(id, main). Allocates built-in Stores, synchronization, indexing listener, geometry/context fields. Requires Main's configured turtle vector. Built-in initial values are supplied afterward; do not read them or manually call init here.
init() Empty hook. Runs after initial/default built-ins are supplied, including for aligned births. One-time custom Store/listener/updater registration belongs here.
setup() Empty hook. Runs after initial populations exist, after world-reset recreation, or after a birth batch is inserted. Do population-dependent work here.
turtleStep() Base hook: if trajectory, schedule movement using pending speed/heading; then in aligned mode evaluate theta, color, size, shape updaters in that order. Keep the base call deliberately positioned.
turtleShift() Base hook clears newborn-hidden flag unless zombie. Preserve super.turtleShift() when overriding. Does not itself commit built-in Stores.
reset() Local reset of the configured stores list. Aligned mode does not call setup. Does not reset time, neighbors, pen, zombie/newborn flags, arbitrary fields, or every synchronized Store.

World Reset recreates turtles rather than calling reset on each old turtle. Custom local-reset policies and disposal of listeners on longer-lived owners are separate responsibilities.

2. State properties

For these built-ins, the plain property reads committed state and assignment initializes current/next and replaces its local reset baseline:

Read/write property Value
location Coordinate object with numeric x/y
realLocation Secondary location representation used by motion helpers; not a guaranteed unbounded odometer
color Numeric agent-palette value
size Drawing size in world units
shape Shape.Circle or Shape.Rectangle, not the Project string
speed Distance per base trajectory step, not pixels or automatically multiplied by Project dt
theta Radians, zero east, positive toward south; duplicate source getters have the same implementation
x_vel, y_vel Separate component Stores; not automatically kept consistent by plain speed/theta assignments

The corresponding pending properties are read/write: nextLocation, nextColor, nextSize, nextShape, nextSpeed, nextTheta. They propose for commitment without changing current values/baselines. There is no public nextRealLocation property.

The immediate-edit properties are setter only: currentLocation, currentColor, currentSize, currentShape, currentSpeed, currentTheta. They set current/next immediately but retain the baseline. Reading one does not read the committed state. Location-only assignments do not also update realLocation. Prefer initLocation for deliberate position initialization.

Broken legacy properties: nextX_val and nextY_val reference absent _x_val/_y_val Stores, not the allocated velocity Stores. Reading or assigning them throws unless a subclass separately defines those fields. They are not aliases for pending velocity; use setNextVelocity instead.

Context and geometry

Member Contract
id Population ID; newborn starts with null and receives an ID at insertion. Not persistent across world reset.
main, patches, turtles References to Main, patch matrix, and population vector.
rows, cols Inherited dimension accessors assigned from Main.
minX, maxX, minY, maxY Motion-helper bounds; hex doubles maxX and uses minY -1. Not generic physical extents.
isTrajectory, isDiscrete Flags captured at construction from movement/motion modes; not automatic live Project switches.
x, y Read-only location components; assignment is not a movement command.
col, row Read-only floored position; use myPatch for hex occupancy conversion.
radius Read-only size/2.
centerX, centerY For circles, location; for rectangles, location plus size/2 on each axis.
newbie Read-only newborn-hidden flag.
zombie Own dying flag, set by die. Do not equate it with hidden drawing.
turtleWrap Read-only comparison of agent edge mode to Wrap, independent of cellWrap.
pen_down Boolean field, initially false; controls trail writes by selected movement helpers.

getRadius(), getCenterX(), and getCenterY() are method equivalents of radius/center accessors. inBounds() tests the square-style range 0 <= x < cols, 0 <= y < rows. Duplicate source definitions are equivalent; this is not a hex-aware footprint or collision test. clipped() instead tests y >= rows - 1 (as well as other outside bounds), so it is not the negation of inBounds. rowClip(y) and colClip(x) clamp to [0, rows - 1] / [0, cols - 1], without flooring or hex conversion.

3. Movement and commitment

Signature Effect
initLocation(x, y) / initLocation(coords) Initialize location and realLocation together, including baselines. May immediately update the index through the location listener. No boundary normalization.
moveTo(x, y) / moveTo(coords) Immediate location edit preserving baseline, plus immediate trail if pen_down. Does not update realLocation or normalize boundaries.
moveNext(x, y) / moveNext(coords) Propose location, plus pending trail if pen_down. No boundary normalization or realLocation update.
fdNext(dist) Schedule travel from current position using pending heading, mode-specific motion, and agent boundary policy through go; also propose secondary location using go(…, wrap=false).
move() Base trajectory operation, delegates to fdNext(pending speed). Arguments are ignored; not an arbitrary-coordinate move.
go(x, y, speed, theta, isDiscrete, wrap = true) Coordinate calculation → new coordinate object, no movement assignment. Continuous addition or goDiscrete, then wrap/clamp using stored bounds.
NLTurtle.goDiscrete(x, y, speed, theta) Static calculation → [x, y]. Rounds speed, selects nearest of eight Dir sectors, adds integer offsets, floors resulting coordinates. No boundary normalization. Diagonal grid step length is not Euclidean speed.

go's wrap uses (value + period) % period, not full modulo normalization for arbitrarily large negative offsets. Non-wrap clamps to min and max minus 0.000001; it does not itself implement reflection. Bounce/collision machinery is separate. These helpers do not validate arbitrary finite inputs. Do not use nonfinite headings in goDiscrete.

Movement occurs before the base step's thetaUpdater evaluation. Proposing nextTheta before the base call affects this move; doing it afterward affects the next move. Move proposals replace rather than accumulate: two fdNext calls start from the same committed location. Do not combine trajectory movement with another move unless intentionally replacing its proposal.

Legacy movement helpers

Member Classification
fd(dist) Defective immediate-movement implementation: passes a Store instead of numeric heading and calls move(coords), whose argument is ignored. Do not use; prefer fdNext or moveNext.
forward() Effective duplicate declaration returns theta; supplying a distance does not move. Earlier forward(speed) implementation is replaced by JavaScript's last declaration.
ahead() Returns current theta; not a sensed patch or a movement command.
getNextLocation() Low-level operation manually shifts location and realLocation and returns location. Premature commitment can change indexing/listener timing; not a pending-state getter. Read nextLocation instead.
initDynamics(other) Legacy Store-style copying calls .get() on public values/coordinates. Not compatible with ordinary current Turtle properties; do not use as cloning.

4. Heading and velocity

Signature Result / effect
left(deg), lt(deg) Return normalized current theta minus degrees converted to radians; do not assign or move.
right(deg), rt(deg) Return normalized current theta plus converted degrees; do not assign or move.
toRadians(deg) Return normalized radians, not an unrestricted linear conversion.
toDegrees(rad) Return rad * 180/pi; no normalization.
fixSpeed(speed), fixTheta(theta) Immediate initializing aliases, replacing corresponding baselines.
initVelocity(x_vel, y_vel) Initialize component Stores, speed as magnitude, theta as atan2; replaces those baselines.
setNextVelocity(x_vel, y_vel) Propose components, magnitude, and heading together.
setSpeedTheta(speed, theta) Propose speed/heading and corresponding components; despite its name, not an immediate setter.
dt() Returns 1, not Main's Project dt.
dx(), dy() Return dt() times cos/sin of heading; unit direction components, not speed-scaled displacement.

Typical turning:

this.nextTheta = this.right(90);

This is a method-body fragment, not a complete Turtle rule. Assigning speed or heading separately does not recalculate velocity components; use the joint helpers only when your model actually relies on those components. The base local-reset list excludes x_vel/y_vel even though they are synchronized. If individual reset needs them restored, define that policy explicitly.

5. Appearance, updaters, and visibility

Read/write thetaUpdater, colorUpdater, sizeUpdater, and shapeUpdater store zero-argument functions returning proposals. Assign once in init. Aligned super.turtleStep evaluates them after movement in that order. Set undefined to disable. Use arrows to retain Turtle this: ordinary callbacks are called as Store methods, not bound to the Turtle. Exceptions propagate.

setNextSize(val), setNextSpeed(val), setNextTheta(val), and setNextShape(val) are pending-property method aliases. setNextColor(val) is not always an alias: while hidden it only updates cacheColor, whereas nextColor assignment bypasses the hidden-color check.

Signature Contract
hide_turtle() If not already hidden, cache current color then initialize color to sentinel 65536. Replaces color baseline; returns undefined.
show_turtle() If color is sentinel, initialize it from cached color.
setVisible(visible) Truthy → show_turtle, falsy → hide_turtle.
initColor(color) Initialize color and cacheColor together. Unlike plain color assignment, updates hidden-color cache.

Hiding does not remove a turtle from population, indexing, stepping, sensing, or resource use. It is not death. Direct nextColor writes or colorUpdater can replace sentinel and reveal it. Local reset does not separately reset cacheColor; do not treat visibility/cache as a synchronized ecological state. See appearance guidance.

6. Location and environmental sensing

Signature Result / boundary policy
myPatch() Current patch using floored position, with agent-grid hex conversion when needed, then matrix lookup. Not the pending destination.
patch_ahead(speed, next) Patch sampled at location plus distance along current theta, or pending theta if next truthy. Parameter named speed is a sensing distance. Uses cell boundaries; returns null outside Edge.
patch_ahead_next(speed) Alias for patch_ahead(speed, true).
patchAtAngle(theta, r) Legacy rounded grid-offset sampler, wraps before checking bounds and contains unresolved cols/rows in Bounce branch. Not a general boundary-safe alternative.

patch_ahead is a destination-point sample, not a whole-path or turtle-radius collision check. Its preliminary wrap adjustment is single-period and square dimension based; do not infer general hex/path-normalization support. Use small checked square-world sensing steps as in the obstacle example. The final Main lookup can normalize farther square Wrap offsets, but does not repair the helper's hex geometry.

Directions and distances

Signature Result
distanceTo(agent) Raw direct coordinate distance to another compatible Turtle (reads its internal location Store). No wrapped shortest displacement or hex physical scaling.
patchDist(other) Raw Euclidean distance between location values.
realDist(other) Raw Euclidean distance between secondary realLocation values.
sameLayer(other) Boolean abs(patchDist - realDist) < 0.01; specialized legacy motion comparison, not a breed or patch equality test.
towards(leader) atan2 angle from secondary realLocation values.
towards0(leader) Direct angle from location values.
towards1(leader) Angle from this location to leader.centerX/centerY.
towardsxy(x, y) Direct atan2 angle to a point. Does not change heading.

These are not shortest wrapped direction/distance helpers. Main.turtlesInRadius accepts a coordinate point for a wrapped-distance query; filter out self explicitly when using it from a Turtle.

7. Local turtle queries

Require indexed committed occupancy and initialized populations. Results hide zombies/newbies and exclude this Turtle, independently of drawing visibility.

Signature Result
nhoodPatches(patches) / nhoodPatches(f, patches) New AgentSet of unique other turtles on supplied patches, optionally satisfying f(other). Collection must provide values() yielding patch-like col/row objects.
nhoodCoords(coords) / nhoodCoords(f, coords) Same query selected by coordinates with finite x/y or col/row; legacy callable coordinate access also works. Invalid coordinates throw TypeError.
nhoodCount(f = other => true, patches) Count matching others; default patches is myPatch().neighbors(). One-argument nonfunction overload treats argument as patches.

Duplicate patches/coordinates do not duplicate results or predicate calls. Include the current patch with block(1) if co-residents should be considered; blockX/ring excludes it. Optional predicates receive actual other Turtle objects, not distances or patches. Callback exceptions propagate.

Example method-body fragment:

const region = this.myPatch().block(1);
const others = this.nhoodPatches(region);
const count = this.nhoodCount(region);

See full local-query contracts.

8. Population and index operations

Signature Contract
die() Set zombie immediately, queue this ID for shift removal through Main. Does not stop the rest of the current rule: return explicitly.
kill(id) Find Main's turtle by ID and call its die. Missing IDs are not silently ignored; dereferencing absent turtle fails.
unlink() Remove spatial-index membership through Main.unPoke. Not population removal by itself.
link() Legacy index helper calls Main.poke without its required new-coordinate argument; not a working manual relink operation. Use runtime-managed movement/insertion.

Birth operations live on Main. Constructor/defaults/init occur before customization; setup follows insertion. Membership, local-query visibility, and opportunity to step begin at different boundaries. Retain the base turtleShift for newborn visibility.

9. Notifications

Each initialization setter replaces a single callback f(value). Each change method appends f(store, oldValue, newValue), without deduplication or a Turtle removal method:

Initialization callback setter Change-listener method
setColorInitListener(f) addColorChangeListener(f)
setShapeInitListener(f) addShapeChangeListener(f)
setSizeInitListener(f) addSizeChangeListener(f)
setSpeedInitListener(f) addSpeedChangeListener(f)
setThetaInitListener(f) addThetaChangeListener(f)
setLocationInitListener(f) addLocationChangeListener(f)
setXVelInitListener(f) addXVelChangeListener(f)
setYVelInitListener(f) addYVelChangeListener(f)

Initialization callbacks run on initialize/reinitialize, not ordinary immediate set/shift. Assign undefined to disable one. Change listeners run for those operations too, even equal-value shifts. Initialization reports a falsy old value as null under Store's existing fallback. Register once, not every setup. Exceptions can interrupt an operation after the value is already changed. Location already has the runtime's indexing listener; these append, rather than replace it.

The similarly named setXValInitListener(f), addXValChangeListener(f), setYValInitListener(f), and addYValChangeListener(f) are broken legacy methods referencing absent _x_val/_y_val, not the velocity Stores. Do not use.

10. Serialization and internals

Member Result / classification
toJsonMini() New [id, x, y, color] array.
toJsonMedium() New [id, x, y, color, size, shapeNumber] array.
toJsonFull() New [id, x, y, color, size, shapeNumber, speed, theta] array.
startSequence Read-only accessor yielding the full-record shape above. Not full custom-state persistence.
toString() Diagnostic string with ID/color/size/Shape string/location. Requires initialized built-ins.
stores Base local-reset list of appearance, speed/heading, location/realLocation Stores; not every synchronized resource.
_location, _realLocation, _color, _size, _shape, _speed, _theta, _x_vel, _y_vel Internal Stores; ordinary model code uses public properties/joint operations.
_newbie, cacheColor Internal newborn flag and visibility cache.

Serialization reads committed state, does not commit/consume output, and does not include updater/listener/custom Store state.

Trails and legacy field sampling

Signature Classification / limitations
drawTo(ocoords, ncoords) Immediate sampled patch-color trail using inherited path. Existing implementation swallows patch-write errors; not a reliable general geometry renderer.
drawNext(ocoords, ncoords) Pending sampled trail; same swallowed-error/path caveats. Colors use turtle's committed numeric color interpreted in the cell palette.
sniffer(col, row, theta, len, comp, decay) Legacy weighted patch sampling along a ray; angles radians, length sampled by floor/integer increments. Returns 0 if willBounce. Wrapped row branch references unresolved rows; callback errors are swallowed as zero. Avoid as an introductory sensing API.
sniffCone(width, slices, len, comp, decay = x => 1) Legacy direction search, returns best sampled angle (or current heading if no positive improvement/willBounce). width radians. Needs finite positive width and multiple slices for meaningful stepping; no robust argument validation. Inherits sniffer defects.

willBounce can be supplied by collision machinery; it is not initialized here. Trails are not guaranteed continuous shortest seam paths. Do not repair these limitations by manually shifting private Stores. The checked obstacle and Grazers examples use explicit public queries instead.

11. Inherited utilities and verification

NLRoot supplies newCoords/path, collection operations and selection helpers; APIRoot supplies static random/math functions. See NLRoot reference and tools and utilities. Call static helpers on their class, not this.random(). Not every legacy inherited helper/collection shape is certified.

The guide tests inventory every NLTurtle prototype member plus static goDiscrete, execute this page's StraightTurtle and query/turn fragments, and check motion proposals, aliases, velocity/reset distinctions, visibility, serialization, and known defective entry points. Existing guide tests cover movement/updater ordering, indexed birth/death visibility, live inputs, wrapping, and repeated world reset. These are headless contract checks, not certification of every collision, hex movement, trail, or legacy sampler behavior.