On this page
NLPatch API reference
Manual contents | Programming patches | Neighborhood reference | NLSimMain reference | Supporting types | Alphabetical index
Sources: nlpatch.js and
hexpatch.js.
Inheritance: NLPatch extends NLRoot extends APIRoot;
HexPatch extends NLPatch.
This page inventories NLPatch's declared instance members and static sequence
method, plus HexPatch's overrides/helpers. Inherited utilities are mapped at the
end. Examples assume Project.lifecycle: "aligned". Read
Programming patches for a complete Heat model and
Fire for a first cellular automaton.
Unless stated otherwise, mutating methods return undefined. Patch operations
do not automatically validate color ranges, activate patches, advance time,
or restore custom state.
1. Import and subclass
import {NLPatch} from "@nwk/api/nlpatch.js";
class AlternatingPatch extends NLPatch {
setup() {
this.main.visitAlways(this);
}
patchStep() {
super.patchStep();
this.nextColor = this.color === 0 ? 1 : 0;
}
}
export default AlternatingPatch;
Use an aligned Project with visitMode: "C", a two-entry cell palette, and a
Main that calls initializePatches(this.Patch) in initCells. Starting at color
zero, every selected patch alternates 0 → 1 → 0 across two ordinary ticks.
Reset restores its initial color. There is no custom Store to restore here.
The code does not install an updater; a later explicit nextColor assignment
would take precedence over a base-step updater evaluated earlier in that call.
For hex models import HexPatch from @nwk/api/hexpatch.js and extend it
instead, together with Project cell.topology: "hex".
2. Construction and lifecycle
| Member | Role / contract |
|---|---|
constructor(col, row, main) |
Runtime construction. Call super(col, row, main) in subclasses. Main must already have its patch matrix, coordinate factory, and synchronization plumbing. Numeric-coerces col/row, allocates built-in color at zero, and wires color commitment/reporting. Does not call init/setup. |
init() |
Hook, empty base. In aligned initialization, runs once after all patches are constructed and Project color starts applied, but before turtles are necessarily available. Register custom Stores/updaters/listeners here. |
setup() |
Hook, empty base. Runs after required populations exist; repeats after world reset. Activate static environmental rules and rebuild relationships here, not one-time listeners. |
patchStep() |
Hook. Aligned base evaluates the configured colorUpdater once per call, proposing color. It does nothing for an unset updater or in legacy mode. Preserve the base call if using a built-in updater. Does not commit or activate itself. |
patchShift() |
Hook, empty base. Optional extra phase only when Main enables doPatchShift in an applicable mode. Not needed for normal Store commitment. Do not rely on exactly one call if visitation paths overlap. |
reset() |
Local operation/hook. Reinitializes built-in color from its saved baseline. Does not restore custom Stores, invoke init/setup, reset time, or affect neighbors. Preserve super.reset() and explicitly restore your custom state. |
Patches survive aligned world reset. The runtime resets them and then runs coordinated setup; ordinary patch.reset() alone does not run setup. Custom Stores must be allocated once, synchronized once, and reinitialized deliberately. Built-in color is already synchronized and reported: do not re-register it or call its private Store's autoNext/shift. See Store ownership.
3. Coordinates and context
| Member | Value / restrictions |
|---|---|
col, row |
Own fields: fixed numeric grid address. Square grid starts at zero; hex uses valid doubled-column parity. Treat as read-only model context. |
location |
Own coordinate object created at (col, row), not a square display center. Read numeric x/y properties. Do not move patches by mutating it. |
centerX, centerY |
Read-only accessors returning col + 0.5 and row + 0.5. Literal square-center formulas; HexPatch does not override them. Do not assume these are hex centers. |
main |
Main reference supplied at construction (also the shared NLRoot owner link). Use for inputs, world queries, and scheduling. |
patches |
Reference to Main's NLMatrix, not an array of neighbors. Use toList()/forEach for a full scan. |
boundaryMode |
Patch-matrix boundary symbol; use the configured contract rather than modifying it independently of Main. |
agentGrid, agentSet |
Runtime spatial-index references; agentSet is this patch's indexed occupancy Set. Query through myTurtles rather than editing the Set manually. |
_color |
Internal built-in Store. Use the public color properties below, not direct writes to this field. |
There are no per-patch rows/cols assignments in this constructor. Although
NLRoot defines inherited dimension accessors, use this.main.rows/cols for
world dimensions rather than assuming patch.rows/cols are populated.
distanceTo(col, row)
Instance query → number: ordinary Euclidean distance from this patch's location to the supplied coordinate point. Arguments are column/x then row/y, not another patch object. Uses Coords.distanceTo.
No boundary wrapping or hex physical scaling is applied. In a width-9 Wrap world, patch (0, 0).distanceTo(8, 0) is 8, not 1. On a hex grid a doubled-column separation of 2 yields raw distance 2, even when the patches are adjacent. For boundary-aware spatial selection, use Main's radius helpers. This method does not validate finite arguments: malformed coordinates can produce NaN rather than the radius helpers' explicit errors.
4. Color state and updater
Color is numeric model state interpreted through Project's cell palette, not a CSS string, turtle palette value, or intrinsic ecological quantity.
| Member | Contract |
|---|---|
color (get) |
Current committed color. |
color = value |
Initialize current and next color immediately and replace the reset baseline. Schedules reporting through the built-in next assignment. |
currentColor = value |
Setter only: immediate current/next change without replacing the baseline. Not a synchronous proposal. Reading currentColor does not read color. |
nextColor (get/set) |
Read/replace pending color. Assignment arranges commitment and patch reporting; current color is unchanged until commit. |
initColor(value) |
Method alias for color = value, including baseline replacement. |
setNextColor(value) |
Method alias for nextColor = value. |
colorUpdater (get/set) |
Installed callback, initially undefined. Assign a zero-argument function returning the next color. Aligned super.patchStep() evaluates it. Set undefined to disable it; no return-value validation. |
randomColor() |
Query → fractional number from random() * main.cellPaletteLength, normally in [0, paletteLength). Does not assign color or choose an integer state. |
An arrow updater preserves the enclosing patch this. An ordinary function is invoked as a Store updater, not bound to the patch; do not rely on its this. Updater exceptions propagate. It is evaluated per base-step call, not inherently once per tick, and a subsequent explicit nextColor assignment overwrites its proposal. Main registration and patch activation remain separate jobs.
For example, these methods belong inside a patch subclass:
init() {
this.colorUpdater = () => this.color === 0 ? 1 : 0;
}
setup() {
this.main.visitAlways(this);
}
This gives the same alternating rule as section 1 using the inherited base step, rather than a second patchStep override. Do not install both versions as two competing rules. For a color derived from custom pending state, see Heat.
5. Color notifications
| Signature | Callback and registration |
|---|---|
setColorInitListener(f) |
Replace the single initialization callback with f(value). Called by color initialization/reinitialization, not currentColor or ordinary shift. This is separate from the change-listener list. |
addColorChangeListener(f) |
Append f(store, oldValue, newValue) to the Store listener list. No deduplication/removal API on NLPatch. Fires for initialize/reinitialize, immediate set, and shift, even when values compare equal. |
Both return undefined. Register once, not every setup/reset; duplicate functions in the change list are called repeatedly. An initialization from a falsy old color passes null as oldValue to change listeners because of Store's existing fallback, so do not assume an exact old zero. There is no guarantee of changed-value-only notification. Listener exceptions propagate and can interrupt the operation after state has already changed.
For init notifications, assigning undefined disables the optional callback. For long-lived custom listener policies, define ownership/disposal deliberately; ordinary reset neither clears listeners nor unregisters the updater. See listener cautions.
6. Neighborhoods
These are instance operations. They read patch identities, not turtles, colors, or pending state. No activation, stepping, or commitment occurs. They do not shuffle results; do not rely on a particular iteration order.
| Signature | Result and center policy |
|---|---|
neighbors() |
New Set; nearest ring, excluding this patch. Delegates to ring(1). |
ring(dist = 1) |
New Set; outer grid-distance shell, excluding this patch. |
block(dist = 1) |
New Set; filled region through dist, including this patch. |
blockX(dist = 1) |
New Set; same region excluding this patch. |
neighborVisit(visitor, dist = 1) |
Call visitor(patch) for each unique shell patch; undefined return. Note visitor comes first. |
ringVisit(dist, visitor) |
Same shell visitation, but distance first and required. |
blockVisit(dist, visitor, notMe = false) |
Filled-region visitation; notMe true excludes caller. Distance is required. |
visitNeighbor(col, row, visitor, seen) |
Internal low-level operation: boundary-aware lookup; if present and not in the supplied Set, add and call visitor(patch). Requires seen; not an ordinary one-neighbor lookup API. |
All ring/block distances must be nonnegative safe integers; invalid arguments throw RangeError. Visitor must be callable whenever any patch is visited. Callback this is not bound to the visited patch; use its argument. Returning false does not stop traversal. Callback exceptions propagate.
In square interiors ring(1) has 8, ring(2) 16, block(1) 9, blockX(1) 8. ring(0)/blockX(0) are empty and block(0) contains just this patch. Edge skips outside sites. Wrap maps across seams and deduplicates identities, including on tiny worlds; caller exclusion survives wrapping. Grid shell distance is not a Euclidean radius.
For four side neighbors use this.main.nhood4(this) (an array), not ring(1).
See exact neighborhood contracts.
7. Indexed occupancy
myTurtles(me) and occupied
myTurtles() returns an AgentList (array subclass) snapshot of the visible
indexed turtles on this patch. occupied is a read-only boolean equivalent to
myTurtles().length > 0. Newborn-hidden (newbie) and dying (zombie) turtles
are excluded by the underlying Set's toList().
These require this patch to have an agentSet reference. The standard Main
constructs its spatial grid even for a patch-only world, where the normal result
is an empty list. Custom construction without an index does not get a silent
empty-list fallback: myTurtles attempts agentSet.toList().
For meaningful resident queries configure agent.agentGrid: true and initialize
the population before querying; setup or a step is appropriate.
The optional me argument filters with me.sameLayer(other). It does not exclude me itself, represent a breed, or turn the query into a radius search. Layer comparison is specialized legacy motion behavior; filter explicitly for self exclusion or class membership.
Results reference the actual turtle objects but do not update their membership automatically. Queries read indexed committed positions, not nextLocation; insertion, visibility, and opportunity to step have distinct boundaries. Do not cache turtle lists across reset, since turtles are recreated. See local agent queries.
8. Serialization and diagnostics
| Signature | Contract |
|---|---|
toString() |
Instance query → string <<col, row, color>> using current color; no commitment or publication. |
NLPatch.sequence(patchSet) |
Static query → new array of [col, row, color] triples from patchSet.values(). Does not clear or mutate input; uses current color, not nextColor. |
sequence accepts arrays, Sets, and other collections with values() yielding patch-like objects. It does not deduplicate repeated entries, validate a schema, or include custom state. This is patch data, not full model persistence. The runtime uses it for changed-patch reporting. Call it on NLPatch, not this.
9. HexPatch overrides and extra helpers
HexPatch inherits color, lifecycle, occupancy, and the ring/block wrappers. Its overrides change the underlying traversal.
| Declared member | Contract |
|---|---|
constructor(col, row, main) |
Calls the patch base and stores colsx = main.cols * 2. Use with hex topology and valid addresses. |
ringVisit(dist, visitor) |
Validates distance, visits a hex shell with caller-excluding deduplication. Interior shells have 6 * dist patches for positive dist. |
blockVisit(dist, visitor, notMe = false) |
Validates distance, visits center unless excluded and hex shells through dist. Stops once all world identities are seen. |
visitRing(dist, visitor, seen) |
Internal shell walker using a caller-supplied seen Set; public wrappers own validation and deduplication policy. |
visit(i, j, visitor) |
Low-level single-address boundary-aware visit; calls visitor(patch) if a valid patch exists. No persistent deduplication or activation. Not a full-grid scan. |
Hex block(1) has 7 and blockX(1) has 6 in an ordinary interior. Zero-distance policies match NLPatch. Wrapped odd-height grids apply a seam skew to maintain parity and reciprocal neighbors. Keep valid doubled-column coordinates; a topology string alone does not replace an NLPatch subclass's square neighborhood implementation.
HexPatch does not override distanceTo or centerX/centerY. Use the appropriate spatial helpers rather than inferring physical distances/centers from their square/raw-coordinate formulas.
10. Inherited helpers and verification
NLRoot supplies newCoords/path, model-owner/reset support, and selection/ collection operations. APIRoot supplies static math/random utilities inherited by the class. See tools and utilities and NLRoot reference. Static inheritance does not make this.random() a valid call; use an appropriate class import. NLPatch reset only restores its built-in color, not every inherited/custom Store.
The guide tests inventory all declared NLPatch/HexPatch prototype members and NLPatch.sequence, execute this page's alternating examples, and check color baseline/listener/updater behavior, occupancy visibility, raw distance, and non-consuming serialization. Existing guide and neighborhood tests cover synchronous Fire/Heat rules, repeated reset, boundary deduplication, square/hex contracts, and invalid distances. These are headless runtime checks, not browser appearance certification or validation of every inherited legacy helper.