Files
deepgrain-foundry/docs/PROJECT_MAP.md
T

49 KiB
Raw Blame History

Project map

Where everything is and how the parts connect. The index at the end lists every source file in build order, with its top-level functions and variables. It is generated: run python3 tools/map.py after adding, moving or renaming files or top-level functions. Edit this top part by hand when the structure changes.

Layout

AGENTS.md, CLAUDE.md  instructions for coding agents (local only, not in git)
tasks/, .kandown/     the owner's to-do list: a kandown board (docs/kandown.md; local only, not in git)
build.py              joins src/ into dist/index.html (one self-contained page)
src/manifest.json     the build order: simulation files, then browser files
src/shell.html        page markup (HUD, menus, dialogs); CSS and JS are put in at the markers
src/styles/           base styles and the dev console panel
src/sim/              the simulation. No DOM. The headless tests load only these files.
src/render/           drawing: WebGPU pixel and smooth looks, rare CPU overrides and overlays
src/ui/               the browser shell: input, HUD, build menu, notebook, settings, saves,
                      audio, the frame loop
test/                 headless suites (t_*.js) and their harness; browser tests (play.py,
                      t_smooth.py, t_dev_console.py, t_caps.py, firefox_smoke.py); run_all.py
tools/                serve.py (build, serve, rebuild on change), server.py (isolated HTTP), shot.py (screenshots),
                      browser.py (shared launch/GPU choice), caps.py (capability report),
                      where.py, map.py, perf.py, playthrough.py, use_venv.py (switches browser
                      scripts to .venv), scenes/ (screenshot setups), experiments/
                      (measurements and reports)
docs/                 this map, DESIGN.md, TESTING.md, systems/ (notes per system),
                      history/ (the owner's requests), agent-log.md
dist/, shots/         build output and screenshots (not committed)

The dev console pairs src/sim/devconsole.js (headless command dispatch, mark, log and runtime controls) with src/ui/devconsole.js (confirmation and bottom panel). Save metadata keeps dev and the last 200 devLog entries; free building, speed and dev pause reset on load. The frame loop applies speed and queued steps while keeping the per-frame tick limit.

How it runs

  • One script. All files share one global scope; there is no import/export.
    • A function may call functions in any file.
    • Top-level const/let must be declared before top-level code that uses it at load time. That is why the manifest order matters: sim, then render, then ui.
    • 'use strict' at the top of src/sim/base.js covers everything.
  • The frame loop (frame in src/ui/loop.js):
    1. read input;
    2. run up to SET.maxSteps simulation ticks, at 60 ticks a second of game time (none while paused);
    3. draw the world (drawWorld) and the overlays;
    4. update the HUD.
  • One tick (simTick in src/sim/tick.js), in this order:
    • update the sky roof line (every 20 ticks);
    • weather, machines (including belts and screw conveyors), pipes, drill pulses;
    • bars (entTick) and grains in flight (flyTick);
    • falling sand (simMove), then heat (heatPass);
    • every so often: molds, milestones, plants, cold, tree support;
    • the dock, the market and orders, saplings;
    • the bot building ghosts.
  • Events. The simulation reports what happened with emit({ t: ... }). drainEvents (src/ui/events.js) turns each event into sounds, toasts and cards.

The world (src/sim/world.js)

  • The grid is W × H grains; cell i = y * W + x. Worlds are 2048×1024, 3072×1280 or 4096×1536.
  • Per-cell typed arrays:
    • mat: material id;
    • temp: °C;
    • flags: F_NAT natural rock, F_CAST, F_BURN burning;
    • stamp: moved this tick;
    • part: which built part a cell belongs to (P_*: screw conveyor directions, grate, open gate, filter, pipe...);
    • mach: machine id;
    • digp: drill damage;
    • occ: covered by a bar;
    • bgm: the background layer (trees);
    • also life, netId and noiseB.
  • Blocks: the 4×4-grain build grid (BS = 4). blockP holds the piece code (BP_*) and blockV the variant (direction, wall material, flags) of each block, over BW × BH.
  • Chunks of 32×32 grains. awake marks chunks where things move and hot where heat flows; only those are simulated. setCell wakes what it touches; after writing arrays directly, call wakeXY / wakeHeatXY.
  • Other state:
    • fog: exploration at one cell per 2×2 grains; see fog;
    • machines: index = machine id; removed ones are null. Each is { type, x, y, w, h, dir, on, ... }. Its footprint is hull cells (solid) and void cells (open inside).
    • molds;
    • ents (bars, 4×2 grains, with their own physics);
    • flyers (grains in the air: blown, off belt ends, out of screw conveyor mouths, rain);
    • pipeNets;
    • ghostBlocks, ghostMachines, ghostMolds.
  • Player: bot (position), bag (count per material), player (bit and tank tier, lens, flask), ledger (milestones reached), stats, money, debt, orders.

Materials (src/sim/materials.js)

  • Ids are constants (EMPTY = 0 to BARSB = 94, NMAT = 95). They are stored in saves: never renumber them, only add new ones at the end.
  • def(id, {...}) sets each material's properties:
    • ph (phase), col, dens;
    • k (heat conduction), cap;
    • hard (which bit can break it), yld (what it breaks into);
    • melt / meltTo, freeze / freezeTo, boil / boilTo;
    • ign, flame, fuel, burnTo;
    • bag (can be carried), desc (the text players read). These are copied into per-material typed arrays (PH, DENS, KC...).
  • Phases: PH_SOLID holds, PH_POWDER falls and piles, PH_LIQUID, PH_GAS, and PH_ITEM (bars, which are ents, not cells).
  • Naming:
    • ...V: ore vein (solid);
    • ...ORE: loose ore;
    • M...: molten;
    • SCR...: scrap;
    • BAR...: bar;
    • R...: rubble (RSTONE);
    • L...: loose (LDIRT, LCLAY, LWOOD).

Building

  • PIECES (src/sim/pieces.js) lists everything buildable:
    • kind block (a code BP_*);
    • kind machine (bw × bh blocks);
    • kind mold. hidden pieces are not in the menu. The menu's tabs and order are BUILD_CATS in src/ui/build-menu.js.
  • Transport geometry: joins.js owns travel-directed ends and mutual joins for belts, filters and screws. pieceEnds(code, v) returns precomputed geometric left/right ends (vertical screws: up/down), with travel and inlet/outlet roles. endJoin(bx, by, endIndex, planned = null) returns neighbourBlock * 2 + neighbourEnd, or -1; pieceJoins returns bits 0/1. Plans override world blocks, including the queried block. Outlets target the next block along travel, with the belt surface exceptions. Inlet ties prefer same-shape travel, then top-to-bottom, left-to-right; a join must be reciprocal. Both looks, ghosts, previews, diagonal screw grain/bar transfers and straight screw entry into diagonals share this rule. Flat-belt bar entry uses entBeltScrewEnter and the swept-path collision check. Straight screw side-feeding into lifts remains independent. Edge elbows bend inside the diagonal; diagonal outlets bend inside the receiving straight block.
  • Placing and removing:
    • placeBlock / removeBlock (blocks.js);
    • placeMachineAt / addMachine / removeMachine (actions.js, machines.js);
    • addMold / removeMold (molds.js);
    • removePieceAt (actions.js) takes back whatever is at a cell;
    • interactAt (actions.js) is the F key.
  • Ghosts are what a paste or an out-of-reach drag leaves. The bot builds them from the bag (ghostTick in undo.js).
  • Undo: undoRecord(label, fn) wraps one player action; the place and remove functions record their own steps with undoNote(op).
  • Blueprints (blueprints.js): copyRegion, cutRegion, flipBlueprint, pasteGhost.

Drawing

Both looks require WebGPU. cell.js colours rare built geometry and objects.js adds bars, flyers and blueprint ghosts. The GPU canvas sits behind the transparent overlay canvas.

  • gpu/device.js compiles every pipeline asynchronously at startup, submits both looks during world loading, and handles one device recreation followed by an autosaved Reload notice.
  • gpu/textures.js owns world/view textures and bindings; gpu/uploads.js merges dirty 32x32 chunks into horizontal strips, retaining clean chunks across camera moves. Simulation writes mark renderDirty in sim/world.js; hot chunks include the conduction halo.
  • gpu/colour.js colours plain grains. Smooth uses a second pass for its four outputs so no pipeline exceeds four storage textures. gpu/cracks.js supplies drill contour shading.
  • gpu/light.js computes sky, heat emission, lamp and light propagation. No CPU light sweep.
  • gpu/shaders.js provides pixel upscaling and bloom. gpu/smooth*.js shapes smooth grains, field AO and glow; gpu/surface.js caches the parallax horizon.
  • Smooth classes are set in cell.js: 4 crisp built piece, 6 wall tile, 7/8 belt, 9–12 screw, 13/14 filter, 19–22 diagonal screw, 23–30 slope belt/filter, 31/32 slope sidewall and cleats. diagonal-screws.js and slope-belts.js share the simulation join geometry with pixel colours, smooth tags, ghosts and previews.

The browser shell

  • GAME (src/ui/state.js) holds the UI state: tool, selected piece, build tab, drag, clipboard, paste mode, overlays. SET holds the settings, kept in localStorage.
  • Saves:
    • worlds are kept in IndexedDB (src/ui/saves.js);
    • world files can be exported and imported;
    • serializeWorld / deserializeWorld (src/sim/save.js) do the conversion and migrate older saves.

Where to find...

What Where
Material properties and descriptions src/sim/materials.js (def)
Prices, orders, the dock src/sim/economy.js
Piece costs and descriptions src/sim/pieces.js (PIECES)
Build menu tabs, tiles, status and hover popup src/ui/build-menu.js
Key bindings src/ui/input.js (keydown); what they do: src/ui/actions.js
Mouse building and dragging src/ui/actions.js (primaryPress, primaryRelease, secondaryPress, toolTick)
Cursor previews (ghosts, drill aim, selection box) src/ui/previews.js
Controls help text src/ui/notebook.js (controlsHtml)
Cached vein membership, ore identification and label timing src/ui/cursor.js
Hover info and discovery cards src/ui/info.js
Milestones src/sim/progress.js (MILESTONES), checked in src/sim/ledger.js
Starter furnace designs src/sim/progress.js (STARTER_DESIGNS, smelterBlueprint)
Falling sand, liquids, gases src/sim/cells.js
Heat, melting, fire, reactions, alloys, steel src/sim/heat.js
Belts, filters, screw conveyors src/sim/conveyors.js, src/sim/slope-conveyors.js (uphill cleat barriers and screen nudges), src/sim/machine-tick.js
Fans src/sim/machine-tick.js (fanBlow)
Refiner, Stone cutter, Silo src/sim/processors.js
Pipes, pumps, outlets src/sim/pipes.js
Molds and casting src/sim/molds.js
The drill src/sim/drill.js; reach in src/sim/tools.js
Vacuum and blowing src/sim/vacuum.js
Trees and saplings src/sim/nature.js
Weather src/sim/weather.js
World generation src/sim/worldgen.js
Save format and migrations src/sim/save.js
Machine drawing (silo, refiner...) src/render/machines.js
Smooth-look shader src/render/gpu/smooth-shader.js
Settings screen src/ui/settings.js (settings and defaults: SET in src/ui/state.js)
Sound and music src/ui/audio.js

Index of source files (build order)

src/sim/base.js (24 lines)

Deepgrain Foundry: simulation core (src/sim/). No DOM anywhere in src/sim/: plain data and functions, so the headless tests can run it and the layout can be ported to Rust later. This file: the random number generators and the phase ids every material has.

  • functions: rnd, mulberry32, hash2
  • variables: RS, PH_EMPTY, PH_SOLID, PH_POWDER, PH_LIQUID, PH_GAS, PH_ITEM

src/sim/materials.js (119 lines)

Material definitions: ids, properties and metal families. ids, and drill/tank tiers.

  • functions: def, metalFamily
  • variables: EMPTY, GRASS, DIRT, LDIRT, SAND, GRAVEL, CLAY, STONE, GRANITE, BASALT, NMAT, MD, FIRETO

src/sim/material-tables.js (54 lines)

Material tables: typed properties, casting groups, flags, parts and tool tiers. Typed property tables

  • variables: PH, DENS, KC, ICAP, CASTMETAL, METAL_TIER, SOLIDMETAL, F_NAT, F_CAST, F_BURN, P_NONE, P_SCREW_U, P_SCREW_D, P_SCREW_L, P_SCREW_R, P_GRATE, P_GOPEN, P_WHEEL, P_INTAKE, P_FILTER, P_PIPE, P_SCREW_UR, P_SCREW_DR, P_SCREW_DL, P_SCREW_UL, SCREW_PARTS, SCREW_DIRS, IS_SCREW, SCREW_DX, SCREW_DY, BIT_TIERS, TANK_TIERS, REACH

src/sim/pieces.js (179 lines)

Everything the player can build (PIECES): blocks, machines and molds, with costs and descriptions; filter settings; wall materials and their cost.

  • functions: isSlopeBelt, isFilter, isBelt, beltGrade, slopeShape, beltFaceY, filterVariant, beltDirection, isSlope, isWall, slopeCell, slopeCode, isPipeCode, lineOnly, filterable, cleanFilterCfg, filterRec, filterPassAt, filterInfo, sameFilter, wallCost
  • variables: BS, BP_WALL, BP_BELT, BP_SCREW, BP_SHAFT, BP_GRATE, BP_GATE, BP_FILTER, BP_PIPE, BP_PUMP, BP_OUTLET, BP_GRIND, BP_SAW, BP_PRESS, BP_RACK, BP_SLOPE_BL, BP_SLOPE_BR, BP_SLOPE_TL, BP_SLOPE_TR, BP_BELT_UP, BP_BELT_DOWN, BP_FILTER_UP, BP_FILTER_DOWN, filterCfg, WALL_OF, WALL_LIST, BAR_OF, GRAINS_PER_BAR, POWER_FREE, CASH, PIECES, PIECE_BY_ID, PIECE_BY_CODE, BELT_POWER, SCREW_POWER, FAN_POWER, WHEEL_K, ENGINE_K, MOLDS

src/sim/economy.js (152 lines)

Money, prices, market saturation, the trade dock, buyer and builder orders.

  • functions: saleAs, priceFactor, priceNow, sellUnit, marketTick, resetEconomy, payClaim, dock, inDock, dockTick, sellToDock, standing, makeBuildersOrder, makeOrder, ordersTick, completeOrder, placeDock
  • variables: money, debt, earned, CLAIM_DEBT, PRICE, SAT_K, SAT_FLOOR, SAT_HALF, mkRecent, shipLog, saleAcc, floatAcc, orders, ordersDone, nextOrderT, orderSeq, ORDER_SLOTS, STANDING, BUILD_GOODS

src/sim/progress.js (48 lines)

Starter furnace designs and the milestone list shown in the notebook.

  • functions: smelterBlueprint
  • variables: STARTER_DESIGNS, MILESTONES

src/sim/world.js (123 lines)

World state: the per-cell typed arrays, alloc(), ambient temperature by depth, waking.

  • functions: emit, bagCap, discover, sharedArray, alloc, depthU, depthY, meanSurface, computeAmbient, fillNoise, renderDirtyXY, renderDirtyChunk, renderDirtyIdx, wakeXY, wakeHeatXY, wakeIdx, wakeHeatIdx
  • variables: W, H, N, CW, CH, NCH, mat, temp, life, flags, stamp, part, mach, digp, noiseB, airS, netId, isPow, occ, surfY, dirtY, graniteY, basaltY, magmaY, roofY, AMB, worldSeed, surfBase, underD, shallowD, lapse, BW, BH, NB, blockP, blockV, ents, bgm, flyers, ghostBlocks, ghostMolds, renderDirty, awake, hot, hotLvl, powderArea, roofDirty, loadWakeOrder, loadWakePending, loadWakeIndex, tick, tickStamp, machines, molds, nets, pcells, powerDirty, beltL, beltR, screwLists, brokenMachines, ghostMachines, ghostBlocked, EV, bot, bag, bagTotal, player, seen, ledger, stats

src/sim/fog.js (52 lines)

Exploration only: never changes grains or the random stream.

  • functions: fogAlloc, fogMark, fogSeen, fogInit, fogLook, fogRevealAround, fogRevealAll
  • variables: FOG, FOG_SENSE, FOG_SENSE_FADE, fog, FW, FH

src/sim/cells.js (223 lines)

Cell helpers (setCell, move, enter) and the falling-sand movement of powders, liquids and gases (simMove).

  • functions: setCell, swapCells, swapCellData, move, enter, enterFree, powder, passable, liquid, liquidSearch, gas, wakeBotPowder, simMove, moveChunk
  • variables: SORTP, SORTP_FUEL, LSTEP, LFILM, CORNER_SEAL

src/sim/heat.js (266 lines)

Heat: conduction, melting and freezing, reactions, fire and air, steel.

  • functions: curAir, airflowAt, alloyMix, airy, hasO2, condPair, heatPass, heatChunk, neighborDir, react, char, quench, burningNear, burn, steelCheck
  • variables: POROUS, SOIL, HOTLIQ, REACT_MIN, ALLOY

src/sim/machines.js (157 lines)

Machines: the power network, footprints, placing and removing machines.

  • functions: markPow, partLost, rebuildPower, netSat, evictCells, cellBuildable, machineFootprint, canPlaceMachine, addMachine, removeMachine
  • variables: nextPowerBuild

src/sim/processors.js (113 lines)

Processing: Grinder and Saw blocks, and the Silo.

  • functions: isProcCode, rebuildProcessors, procBottom, procSlot, procFeed, procBlocksTick, siloTick, siloFull
  • variables: REFINE, REFINE_SAND, CUT_PER_BRICK, SAW_CUTS, procState, procBlocks, procDirty, SILO_CAP, SILO_RATE

src/sim/racks.js (56 lines)

Each rack block owns its bars; only the bottom of a column releases them.

  • functions: newRack, rackTop, rackBottom, rackPush, rackShift, rackIntake, rackRefill, rackTick
  • variables: RACK_CAP, rackState

src/sim/pipes.js (114 lines)

Pipes, pumps and outlets: each joined line holds one liquid as a count, not as grains.

  • functions: sideOf, pipeClosedSide, pipeJoins, rebuildPipes, pipeNetOf, pipeTakeShare, faceCell, pumpDraw, outletPour, pipesTick
  • variables: PIPE_CAP, PUMP_RATE, OUTLET_RATE, PUMP_MAX_T, SIDE_V, PUMP_V, OUTLET_V, pipeNets, pipeNetAt, pipesDirty

src/sim/machine-tick.js (157 lines)

Per-tick machine work: steam engines, fans, belts, filters, screw conveyors (machinesTick).

  • functions: engineIntake, fanBlow, machinesTick

src/sim/joins.js (125 lines)

Travel-directed transport ends. Precomputed probes; world/plan queries allocate nothing. End indices stay geometric: left/right, or up/down for vertical screws.

  • functions: pieceEnds, joinCandidate, endJoin, pieceJoins, endAt, joinIsDrop, joinSnap, nearMiss
  • variables: JOIN_ENDS, NO_PIECE

src/sim/conveyors.js (213 lines)

How belts, filters and screw conveyors move what is on or in them. What rests on a belt or filter rides along: the whole stack standing on the carrying surface steps one cell toward d together (belts run front of the line first, so the way ahead is clear). If a powder grain is blocked, the load above it stands still and the belt slips underneath. A filter's own material drops through it instead, unless it is already full.

  • functions: conveyorStep, carryColumn, beltDrain, launchGrain, rebuildFilters, filterCarry, carryBeltsAndFilters, setFilter, filterRun, roomFor, screwSpread, screwIntake, screwAccepts, straightScrewNext, diagonalScrewNext
  • variables: CARRY_DEPTH, filterR, filterL, filtersDirty

src/sim/flow.js (26 lines)

Throughput for the info overlay (t49): how many grains each belt, filter and screw conveyor block hands on, per second of game time. Counting runs only while the overlay is on, so normal play pays one flag check per carried grain. Bars are not counted.

  • functions: setFlowCounting, flowNote, flowCross, flowSlopeUnder, flowTick
  • variables: flowOn, flowCount, flowRate

src/sim/slope-conveyors.js (231 lines)

Cleats are rubber ribs standing up from a sloped belt's face, one every CLEAT_SPACING face cells. Loose grains treat them as solid (cleatMask). Nothing grips the bare face: grains slide down it until a cleat stops them. Each belt step moves every cleat one face cell along the belt, and the rib pushes whatever is in its way ahead of it, so the pocket in front rides along while anything heaped above the rib is left to roll back. If a rib can't push its way, its whole run stalls. Only uphill runs have cleats: downhill, the belt carries its load like a flat one.

  • functions: ribMove, cleatFoot, ribCells, slopeUphill, slopeFaceAt, pushRow, scoop, pocketRoom, advanceCleat, slopeRunKey, slopeCleatsTick, rebuildCleatMask, expelFromRib, screenNudge, wakeCleatLoad
  • variables: CLEAT_SPACING, CLEAT_HEIGHT, CLEAT_REACH, SCREEN_NUDGE_TICKS, cleatChunks, cleatMask, cleatCells, slopePhase, ribLog

src/sim/blocks.js (237 lines)

Building blocks: placing, integrity, removing, lines and rectangles of blocks.

  • functions: blockOf, blockCellList, pieceCost, setSlopeSeal, slopeSeal, slopeSealOwner, blockOwnsCell, clearStraySeals, wallCells, canPlaceBlock, placeBlock, blockIntegrity, removeWallCell, removeBlock, diagonalDrag, blockLine, blockRect, blockInReach, blockIs, placeBlocks

src/sim/molds.js (317 lines)

Molds: cavities for castings; ingot troughs empty themselves below. Removal returns set metal.

  • functions: moldCellsAt, canPlaceMold, newMoldRecord, addMold, castMix, cavityState, troughState, clearCavity, moldPlugCells, rakeAbove, furnaceJunkHint, unplugMold, ejectIngot, checkMolds, moldAt, tally, collectMold, removeMold
  • variables: DROSS, grains, barWord

src/sim/items.js (318 lines)

Bars and other loose objects (ents), and the bag: adding, taking, costs and refunds.

  • functions: entSolidCell, entSupportCount, entFreeAt, entMark, spawnBar, removeEnt, entScrewAt, entScrewFree, entScrewMove, entScrewLane, entScrewEdge, entScrewEnter, entScrewTick, entDiagonalScrewTick, entBeltScrewEnter, entSlopeBeltTick, entTick, entsInCircle, bagAdd, bagTake, giveOrDrop, refundAt, canAfford, payCost, fmtMoney, costText, needText
  • variables: BAR_W, BAR_H, entCurM, droppedLast

src/sim/tools.js (65 lines)

Tool helpers: reach, brushes, and plain digging.

  • functions: setBuildRange, inBuildRange, inReach, forBrush, drillReach, inDrillReach, toolDig
  • variables: BUILD_MAX, buildBox

src/sim/drill.js (177 lines)

The resonance drill: tuned pulses that shatter one material.

  • functions: drillOrigin, pulseRay, builtCell, toolPulse, crumbleAround, crumbly, shatterCell, pulseTick, pingRadius, resonancePing
  • variables: PULSE_W, PULSE_EVERY, PULSE_SPEED, PULSE_K, drillPulses, lastPulseTick, drillWidth, THIN_BONUS, CRUMBLE_MAX, THIN_BONUS_OFF, PING_VEINS

src/sim/nature.js (170 lines)

Trees (background layer), acorns, saplings, and waking freezing water.

  • functions: cutTree, treeHeld, findTreeBases, treeSupportTick, woodRoom, treeFall, coldTick, plantTick, setTreeCell, saplingTick, igniteTree
  • variables: treeBases, saplings, treeDraw

src/sim/vacuum.js (199 lines)

The vacuum, blowing grains out, grains in flight (flyers), and the flame tool. Material the vacuum would start on at the cursor: a bar, else the nearest loose grain.

  • functions: vacuumTargetAt, toolVacuum, nozzle, toolBlow, flyOpen, depositNear, bagTemp, landFlyer, flyTick, toolIgnite
  • variables: blowRR, FLY_G, FLY_Q

src/sim/actions.js (92 lines)

Player actions on built things: take back, place a machine or mold, gates, F to interact. Take back whatever piece is at (x,y): machine, mold or block. Returns a message.

  • functions: removePieceAt, removePieceAt0, placeMachineAt, placeMoldAt, toggleGateAt, interactAt

src/sim/blueprints.js (105 lines)

Blueprints: copy, cut, flip, cost and paste (as ghosts) a region of built pieces.

  • functions: copyRegion, flipBlueprint, bpCost, pasteGhost, cutRegion, footprintBlocker, clearFootprint

src/sim/undo.js (93 lines)

Undo (Ctrl+Z) for building, and the bot building ghosts.

  • functions: undoNote, undoPush, undoRecord, undoLast, clearAllGhosts, ghostTick, ghostTick0
  • variables: UNDO_MAX, undoStack, undoRec, ghostMissing, ghostIter

src/sim/bot.js (55 lines)

The bot: movement and collision with the world.

  • functions: botBlocked, botOverlapSolid, botSlide, botStep
  • variables: SLIDE_MAX, SLIDE_STEP

src/sim/ledger.js (54 lines)

Milestone checks (the ledger) and the sky roof line used for cooling.

  • functions: checkLedger, updateRoof, updateDirtyRoof, scanRoof

src/sim/weather.js (87 lines)

Weather: clouds from steam, rain and snow, and the world water count.

  • functions: wrnd, resetWeather, rainGap, worldWater, absorbSteam, spawnRain, rainAt, weatherTick
  • variables: WBAND, WS, weather

src/sim/workers.js (153 lines)

The same chunk schedule runs inline or in workers. Workers only own a pass at a time.

  • functions: threadWorld, threadBind, threadContext, resetChunkWork, inlineChunkWork, chunkEvent, chunkWake, chunkHeat, chunkSeed, runChunks, mergeChunkWork, chunkPasses, threadParams, threadSetParams, threadSlot, threadExecute, threadPass, threadWait, threadFailure, threadMessage
  • variables: simPool, chunkWork, inlineWork

src/sim/tick.js (29 lines)

simTick: one simulation step, in order.

  • functions: simTick

src/sim/worldgen-helpers.js (61 lines)

World generation helpers: noise and removal of tiny hard rock specks.

  • functions: makeNoise, fbm, clearHardSpecks
  • variables: SPECK_MIN

src/sim/worldgen.js (286 lines)

World generation: staged terrain, ore, caves and placement, with synchronous and async entry points.

  • functions: generateWorld, generateWorldAsync

src/sim/devconsole.js (114 lines)

Dev commands are pure simulation operations; the browser owns the panel and confirmation.

  • functions: resetDevConsole, enableDevConsole, devMaterial, devCommand
  • variables: devWorld, devLog, devFree, devSpeed, devPaused, devSteps, DEV_HELP, DEV_MATERIALS

src/sim/save.js (185 lines)

Saving and loading a world (serializeWorld / deserializeWorld) and old-save migration.

  • functions: serializeWorld, deserializeWorld, startLoadWake, wakeLoadArea, wakeLoadNearBot, loadWakeTick
  • variables: SAVE_VERSION, TOFF

src/render/setup.js (190 lines)

Drawing (src/render/): browser only. This file: the renderer state R, colour tables (glow, thermal palettes, pipes, trees, sky), canvas setup and the camera.

  • functions: glowIndex, thermIdx, pipeCellColor, pipeBodyCell, thinPipeColor, beltLike, buildSky, initRender, resizeRender, viewCells, updateCamera, snapCamera, screenToWorld, worldToScreenPx, renderMonoFont
  • variables: R, GLOW_W, GLOW_R, GLOW_G, GLOW_B, THERM, PC, TREE_R, TREE_G, TREE_B, BG, SKY_R, SKY_G, SKY_B

src/render/slope-belts.js (167 lines)

Drawing only: the face stays on its simulation cells; the band hangs below it.

  • functions: slopeBeltConnections, flatBeltCaps, prepareSlopeBelts, slopeBeltSegment, slopeBeltCorner, slopeBeltShape, slopeBeltAt, slopeBeltColor, screenLoaded, slopeWallShape, slopeWallAt, slopeDetailAt, slopePreviewCleat
  • variables: slopeBeltJoins, slopeBeltHalo, beltCaps, slopeAcross, slopeAlong, slopeDistance, slopeWallOwner

src/render/diagonal-screws.js (79 lines)

Screw casing geometry shared by both looks, ghosts and placement previews. smooth-look class of a screw conveyor cell by direction: 9 up, 10 right, 11 down, 12 left

  • functions: diagonalScrewJoins, straightScrewJoins, diagonalScrewShape, diagonalScrewBlock
  • variables: SCREW_CLASS, diagonalJoins, diagonalAcross, diagonalAlong, diagonalCap

src/render/cell.js (276 lines)

Rare-cell shading also treats built pieces as transparent surroundings.

  • functions: builtForShade, cellPixel

src/render/objects.js (80 lines)

Loose bars, flying grains and queued blueprint blocks in the grain buffer.

  • functions: worldObjects

src/render/gpu/cracks.js (79 lines)

The drill's three seeded Perlin contour fields, uploaded once with the material tables.

  • functions: gpuCrackTables
  • variables: GPU_CRACKS, GPU_CRACK_COLOUR, GPU_CRACK_DRAW

src/render/gpu/colour.js (101 lines)

The plain-cell rules mirror cellPixel; built geometry stays in the CPU override.

  • functions: gpuColourShader
  • variables: GPU_COLOUR, GPU_COLOUR_SMOOTH

src/render/gpu/shaders.js (42 lines)

Half-resolution separable Gaussian bloom, then nearest colour + linear light.

  • variables: GPU_BLUR, GPU_DRAW

src/render/gpu/light.js (143 lines)

GPU sources retain the CPU roof and transmission rules; directional relaxation follows only left/up, then right/down, so it cannot introduce extra light paths.

  • functions: gpuLightGrid, gpuLightBindings, gpuLight
  • variables: GPU_LIGHT, GPU_LIGHT_SPREAD, GPU_LIGHT_PACK

src/render/gpu/smooth-slope.js (107 lines)

Smooth slope geometry and cleats, ported from slope-belt-shader.js.

  • variables: GPU_SMOOTH_SLOPE_HELPERS, GPU_SMOOTH_SLOPE_DRAW

src/render/gpu/smooth-shader.js (368 lines)

Literal port of the legacy smooth shader; dpdy is reversed for WebGPU's top-left origin.

  • variables: GPU_SMOOTH

src/render/gpu/surface.js (5 lines)

  • functions: smoothSurface
  • variables: SM

src/render/gpu/smooth.js (48 lines)

Field mip levels preserve the legacy trilinear AO sample at level 2.2.

  • functions: gpuSmoothInit, gpuSmoothTextures, gpuSmoothBindings, gpuSmoothUpload, gpuSmoothMips
  • variables: GPU_FIELD_MIP

src/render/gpu/device.js (90 lines)

All pipelines compile during startup; rendering never falls back.

  • functions: gpuLimitsOK, gpuInit, gpuFail, gpuRecover, gpuWarmWorld, worldPixelContext
  • variables: GPU_LIMITS, GPU

src/render/gpu/textures.js (98 lines)

Whole-world textures retain clean chunks across camera moves.

  • functions: gpuTexture, gpuWrite, gpuBuffer, gpuWorldTextures, gpuViewTextures, gpuBindings, gpuUpload

src/render/gpu/uploads.js (48 lines)

Upload full chunks so scrolling within a resident chunk needs no extra copy.

  • functions: gpuUploadChunks, gpuUploadStrip, gpuCheckUploads

src/render/gpu/draw.js (92 lines)

Only exceptional blocks and their geometric neighbours run the CPU colour rules.

  • functions: gpuOverrideHas, gpuOverrides, gpuDraw, gpuPresent
  • variables: GPU_PATTERN

src/render/world.js (46 lines)

Scale colour without changing the smooth-look class.

  • functions: fogColor, drawWorld

src/render/machines.js (256 lines)

Machine overlays: fans, engines, silo and the rest, drawn on top of the world.

  • functions: cellRect, drawHazardRims, drawMachines, drawProcBlocks, drawSilo, drawSiloPixel, drawSiloWindow, drawRackBlocks

src/render/overlays.js (370 lines)

Other overlays: floating text, rain and snow, flow arrows, filter tags, molds, the bot, particles.

  • functions: spawnFloater, drawRain, drawFlowArrows, drawJoinMark, drawJoinMarks, flowLoaded, drawFlowRates, pingImage, drawPing, drawHoveredVein, drawPingRecharge, drawRunOutline, drawFilterTags, drawFloaters, moldLabel, drawMolds, drawBot, spawnDebris, spawnSpark, spawnSuck, drawParticles
  • variables: PING_SPEED, PING_HOLD, PING_FADE, PING_BANDS, PING_GLINTS, GLINT_MS

src/ui/audio.js (230 lines)

Audio: chiptune effects and generative music that changes with depth. Everything is synthesized with WebAudio, no samples.

  • functions: auInit, auVolumes, rateOk, tone, noiseBurst, sfxPlace, playSfx, auAmbient, mtof, zoneForDepth, scaleNote, musicScheduler
  • variables: AU, SFX, SFX_NEAR, SFX_FAR, ZONES

src/ui/state.js (76 lines)

Game shell (src/ui/): browser only. This file: settings, the GAME state object, DOM helpers, toasts and tool status.

  • functions: loadSettings, saveSettings, el, esc, rgbOf, fmtT, toast, setStatus
  • variables: SET_DEFAULT, SET, TOOLS, ICONS, BAG_ORDER, GAME, keys, hudDirty, $

src/ui/threads.js (39 lines)

Browser transport only; the simulation owns the schedule and shared state.

  • functions: startThreads
  • variables: threadStarting

src/ui/title.js (77 lines)

Startup capabilities and title art.

  • functions: checkCapabilities, renderCapabilityNotice, canStartGame, buildTitleCells, drawTitle
  • variables: REQUIRE_WEBGPU, REQUIRE_THREADS, CAPS, CAPS_CHECK, FONT5, TITLE

src/ui/saves.js (224 lines)

Saves in IndexedDB, world files (export / import) and the blueprint library.

  • functions: newWorldId, worldWrite, listWorlds, putWorldEntry, worldNewest, deleteWorld, cleanWorldName, renameWorld, migrateWorlds, saveWorld, newestSave, b64FromBytes, bytesFromB64, gz, packBuffers, unpackBuffers, exportWorld, importWorldFile, libLoad, libSave, bpEncode, bpValid, bpDecode
  • variables: DB, worldIdTime, worldIdCounter, worldWrites, savingCount

src/ui/claims.js (146 lines)

Shared player state; the world save remains a complete standalone fallback.

  • functions: careerState, validCareer, applyCareerState, loadCareer, claimName, openNewClaim, travel, renderClaimsTab
  • variables: career, claimBusy

src/ui/session.js (162 lines)

Starting, loading and quitting a game; modal dialogs; the pause menu.

  • functions: showLoading, enterGame, setupNewWorld, startNewWorld, startFromSave, loadSavedWorld, quitToTitle, refreshContinue, anyModal, openModal, closeModal, closeAllModals, topModal, dialog, openPause, renderWorlds

src/ui/settings.js (124 lines)

The settings screen.

  • functions: openSettings, renderSettings, applySettings, toggleFullscreen, confirmWipe
  • variables: SET_TABS, setTab

src/ui/notebook.js (91 lines)

Notebook: tab navigation, ledger, materials, pieces and controls.

  • functions: openNotebook, renderNotebook, controlsHtml
  • variables: nbTab

src/ui/notebook-market.js (68 lines)

Notebook market: prices, orders, claim payments and wallet.

  • functions: fmtClock, orderName, orderLeft, renderMarketTab, fmtPrice, itemsText, renderWallet
  • variables: MARKET_GROUPS

src/ui/notebook-blueprints.js (47 lines)

Notebook blueprints: starter designs, saved library and code sharing.

  • functions: renderBlueprintTab, copyCode

src/ui/hud.js (40 lines)

The tool hotbar and what is selected.

  • functions: renderHotbar, toolId, steering, modShift, grainAt, selectTool, bagMaterials, blowList, blowAllList, blowingAll, piece
  • variables: IN_BAG_ORDER

src/ui/build-menu.js (111 lines)

The build menu along the bottom: categories, piece tiles and their icons.

  • functions: pieceIcon, catOf, selectBuildCat, cycleBuildCat, buildVariantChips, renderBuildBar, setupBuildBar
  • variables: BUILD_CATS, BUILD_ORDER, PIECE_ICONS, lastBuildKey, lastBuildMenu

src/ui/selection.js (133 lines)

Tool selection: cycling, drill tuning, piece variants and costs.

  • functions: pieceSize, pieceUsesWall, setDrillWidth, tuneUnderCursor, cycleItem, cycleWall, rotate, toggleBlow, pickFilterUnderCursor, toggleFilterMat, setBrush, pieceV, dragPlan, pieceExtra, filterBlockAt, chipCost, pieceCostNow, pieceCode, turnSlope

src/ui/selection-pickers.js (61 lines)

Selection pickers: filter rules, filter settings and wall materials. What a filter can hold: loose things and bars you have found, plus anything it already holds

  • functions: filterChoices, matList, filterParts, filterSentence, applyFilterRun, openFilterPicker, openWallPicker

src/ui/selection-panels.js (90 lines)

Selection panels: current tool card and bag materials.

  • functions: renderSelCard, renderBag
  • variables: lastBagKey

src/ui/cursor.js (47 lines)

Hover work is shared by the cursor label and the vein outline.

  • functions: oreLike, bitNeeded, pingVisible, cursorVein, hoveredVein, cursorLabelAlpha
  • variables: CURSOR_ORES, cursorVeinCache, cursorLabelKey, cursorLabelSince

src/ui/info.js (208 lines)

Discovery cards, hover info (I) and the cursor label.

  • functions: showCard, howText, discoveryCard, reactionsOf, hoverInfo, renderInfo, drawCursorLabel, pipeContentsText

src/ui/devconsole.js (42 lines)

Bottom panel; command dispatch and state live in sim/devconsole.js.

  • functions: closeDevConsole, showDevConsole, toggleDevConsole, devPrint, runDevCommand

src/ui/input.js (92 lines)

Keyboard and mouse listeners.

  • functions: isTyping
  • variables: canvas

src/ui/actions.js (256 lines)

What input does: overlays, F, pick, copy / cut / paste, undo, building and tool use each frame. Which overlays are on, shown as a coloured frame round the screen and a named badge

  • functions: updateOverlayUI, toggleLens, doInteract, pickUnderCursor, aimBlock, stampOrigin, selModeHeld, startPaste, stopSelectAndPaste, plural, piecesIn, doUndo, endRmbRecord, dragDirFor, blockLabel, primaryPress, primaryRelease, secondaryPress, pingWait, firePing, toolTick
  • variables: ovShown, PING_RECHARGE

src/ui/gamepad.js (60 lines)

Gamepad input.

  • functions: padPressed, pollPad
  • variables: PAD

src/ui/previews.js (241 lines)

Cursor previews: shared grid helpers, air streaks and tool preview dispatch.

  • functions: blockRectPx, drawGrid, previewColor, drawAirStreaks, drawReachCircle, drawPreviews, previewBlock

src/ui/preview-drill.js (67 lines)

Drill pulse wavefronts and aiming fan. The pulses in flight: a wavefront running out from the face of the bot, fading as it goes

  • functions: pulseRGB, fanPoints, drawDrillPulses, drawDrillAim

src/ui/preview-selection.js (81 lines)

Selection previews: labelled tags, copy and cut boxes, and paste ghosts. a small labelled tag drawn on the world (screen pixels)

  • functions: drawTag, drawSelection, drawPastePreview
  • variables: SEL_COL

src/ui/events.js (42 lines)

Events from the simulation (emit) turned into sounds, toasts and cards.

  • functions: drainEvents

src/ui/map.js (93 lines)

Shared world colours, minimap and full map.

  • functions: resetMap, mapArea, updateMap, drawMap, mapFit, drawFullMap, openMap, zoomMap, zoomMinimap
  • variables: MAP_S, MAP

src/ui/perf.js (15 lines)

Browser-only clocks; simulation code stays usable without a browser or a clock.

  • variables: PERF_MARKS, PERF_FRAME, perfMarks, perfTimes, perfLast

src/ui/loop.js (149 lines)

The frame loop and boot.

  • functions: scanVisible, frame, boot
  • variables: lastT, acc, lastRender, frameMs, simMs, fpsSm, ambientT

Tests and tools

  • test/firefox_smoke.py: An isolated Firefox title screen and three seconds of a new pixel world.
  • test/furnace_play.js: Fires a starter furnace design repeatedly the way a player would, without cleaning it out between firings, to see whether it clogs. Usage: node test/furnace_play.js [design] [ore] [coal] [firings] [roll] [mode] mode: 'mix' (even ore/coal mix blown in), 'layers' (ore first, coal on top), 'vent' (blown in from above through the vent)
  • test/gpu-readback.js: Read the four actual smooth textures without adding COPY_SRC usage to game resources.
  • test/harness.js: Loads the simulation (the src/sim/ files listed in src/manifest.json, joined in order into one script, the same way build.py joins them) so scenarios can drive it headlessly in Node. Errors point at the real file and line (sim/pipes.js:42), not at the joined script.
  • test/light-cases.js: Lighting behaviour checks executed by the GPU browser harness.
  • test/light-readback.js: Read float source channels, including transmittance, from the WGSL light pass.
  • test/play.py: Play-test in a real browser: mouse, keyboard and a mocked gamepad drive the game; save and continue. Screenshots go to shots/play/ (or the folder given as the first argument). Pixel look unless the second argument is 'smooth'.
  • test/run_all.py: Run the test suites and report.
  • test/t_bar_stacking.js: Resting bars snap into pairs of grains and tip off narrow supports.
  • test/t_basics.js: Basics: drilling to rubble, the vacuum and blowing, walls, the ingot mold and bars, belts, blueprints, save/load.
  • test/t_build.js: Building: undo (Ctrl+Z), cut, replace a machine with Ctrl, pasting ghosts, and the fan heat warning.
  • test/t_caps.py: Capability detection, title notices and the required-WebGPU startup gate.
  • test/t_conveyors.js: Screw conveyors that never carry liquid (it flows through), screw and belt throughput, filters.
  • test/t_corner_seal.js: Corner-touching square walls seal loose grains without changing free piles or worldgen.
  • test/t_cursor.js: Ore identification, cached connected veins, ping timing, settings and label lifetime.
  • test/t_dev_console.js: Dev command validation, discovery, build costs, runtime controls and save metadata.
  • test/t_dev_console.py: Dev console confirmation, keyboard isolation, HUD, time controls and saved badge.
  • test/t_diag_screws.js: Diagonal screws: sealed four-lane corner transfers, bars, joins and persistence.
  • test/t_drill.js: The resonance drill: pulses from the bot shake rock until it shatters. Widths trade area for speed, tuning shatters only one material and drains it out of the wall, built blocks are left alone, and the drill says why when nothing breaks.
  • test/t_econ.js: Economy: the dock (instant sale), orders, prices, the market dip, money for machines, alloys.
  • test/t_flow.js: Throughput overlay (t49): grains per second per transport block, counted only while the overlay is on, never changing what the simulation does.
  • test/t_fog.js: Fog: surface, sight, range, saves and simulation independence.
  • test/t_furnace_repeat.js: The starter furnaces keep working when fired again and again without cleaning, however the charge goes in: mixed, ore first with coal on top, or blown in through the vent. Each case plays furnace_play.js, which builds the design and fires it like a player.
  • test/t_gpu.py: Dirty uploads, default limits, warm pipelines, world replacement and device recovery.
  • test/t_gpu_golden.py: Frozen legacy references, captured before retirement; compare the WebGPU world only.
  • test/t_gpu_light.py: The former CPU light behavioural checks, now read from the actual GPU light grid.
  • test/t_joins.js: The oracle states the geometric rule independently of the precomputed neighbour tables.
  • test/t_load.js: Reload wakes nearby areas first, without losing distant water, fire or saved state.
  • test/t_molds.js: Molds and furnaces stay usable: ingots drop below and keep their stubs, plugs over molds are cleared, spoiled castings can be knocked out, grains never drop through a grate by teleporting, and slag lets the fire breathe.
  • test/t_nozzle.js: Blowing aims within the nozzle's reach, with room for the brush and settling.
  • test/t_perf.js: Profiling fixtures start in the same state after previous scenes and warm-up ticks.
  • test/t_physics.js: Sand and other powders, molten metal and gases: heaps, sorting, sinking, setting, rising and fading. Water has its own suite (t_water.js). Tall worlds keep geothermal heat out of the way.
  • test/t_pipes.js: Pipes, pumps and outlets move liquids; the Grinder grinds waste rock for trace ore.
  • test/t_racks.js: Rack intake, FIFO storage, gate, removal and saved-state validation.
  • test/t_render_dirty.js: Render invalidation must not depend on whether a grain moved or the chunk stayed awake.
  • test/t_silo_contents.js: Stored snow keeps its identity and remains in the world's water budget.
  • test/t_sim_optimizations.js: Optimized paths must match the full roof scan and the original heat loop exactly.
  • test/t_slope_belt_art.js: Drawing geometry against real parts, without changing transport.
  • test/t_slope_belts.js: Sloped belts: transport, joins, sorting, persistence and the actual drag controls.
  • test/t_slopes.js: Sloped walls: flow, sealed joints, building, refunds and persistence.
  • test/t_smooth.py: The smooth look: the WebGPU pass compiles and draws, and the thermal lens still works.
  • test/t_stone.js: Uses for waste rock and sand: glass bricks from a fan furnace, the Saw, the silo and builders' orders.
  • test/t_threads.js: Shared allocation, checkerboard independence, and real worker-count determinism.
  • test/t_water.js: Water conservation, settling, ledge pouring, boundaries, pipes and phase changes. Tall worlds keep geothermal heat out of the ponds.
  • test/t_weather.js: Weather: no more springs; steam rises into clouds and rains back; showers; snow when it is freezing.
  • test/t_world.js: Trees from acorns, charcoal, brick, density, water/lava/snow/ice, full-bag refunds, drill reach, ballistic blowing, snowy mountains.
  • tools/browser.py: Shared isolated HTTP sessions; callers attach hooks before navigating to url.
  • tools/caps.py: Print isolation, WebGPU adapter info and GL renderer for installed browsers.
  • tools/map.py: Regenerate the file and symbol index at the end of docs/PROJECT_MAP.md.
  • tools/perf-measure.js: Temporary wrappers live only in the profiling page, never in the simulation bundle.
  • tools/perf-scenes.js: Seeded worlds, no storage round-trip (saves quantize heat and land flying grains).
  • tools/perf.py: Profile a seeded world on the real GPU, with isolated HTTP serving. Times are milliseconds.
  • tools/playthrough.py: Headless browser run: load the page, start a world, play a little, take screenshots.
  • tools/serve.py: Build, serve and rebuild when sources change: python3 tools/serve.py [--port 8000].
  • tools/server.py: Serve dist/ with isolation headers; isolated_server() owns a free-port background server.
  • tools/shot.py: Screenshot the game in a headless browser, after setting up a scene with JavaScript.
  • tools/test_perf.py: Profiler checks: headers, summaries/comparison, and unchanged pixels/simulation with clocks on.
  • tools/use_venv.py: Let browser scripts run with plain python3 by switching to the repo's .venv.
  • tools/where.py: Turn a line number in dist/index.html into the source file and line it came from.
  • tools/experiments/cast_sunk_mold.js: Block-sized bit mold sunk into the ground with a stone furnace built over its funnel.
  • tools/experiments/factory_cost.js: What does a running factory cost when the player is somewhere else? Builds K self-running modules in a generated world, far from the bot, and measures simulation time per tick. Each module: a coal + copper-ore furnace burning in a stone-block box, a spring feeding a water wheel, a shaft carrying its power to a 10-block belt that hauls sand off a hopper.
  • tools/experiments/flow.js: Throughput of belts and screw conveyors: grains delivered per second. Whatever lands past the outlet is taken away, so the output pile never backs up into the line.
  • tools/experiments/furnace.js: Furnace scenarios on a flat test world: builds a chamber, charges it with ore and coal, lights it and prints temperatures, burning cells and what has melted or set at intervals.
  • tools/experiments/section.js: ASCII cross-section of a stone furnace firing, with a temperature digit per cell (0-9), printed at intervals. Usage: node tools/experiments/section.js [WALL_MATERIAL] (default STONE).
  • tools/experiments/slope-cost.js: Many loaded slopes, with a fresh deterministic world for each timing sample.
  • tools/experiments/slope-flow.js: Reproducible generous-feed throughput and settled pile angles for t42.
  • tools/experiments/smelter.js: Smelter design experiments, built with the same block pieces a player uses. Layout (block rows, 4x4 grains each), on flat ground at row 25: roof with a vent ........ row g-CH-1 chamber, CH blocks tall .. charge of coal + copper ore inside grate floor ............. row g = 23 (liquids pass, powders do not) ingot mold .............. row 24, sitting on the ground side walls run from the roof down past the mold. Usage: node t_smelter.js [key=value ...]
  • tools/experiments/starter.js: Plays a starter design the way a player would: paste the blueprint, let the bot build it from the bag, blow an even ore/coal mix inside, light it, wait, knock out the castings. Usage: node tools/experiments/starter.js [design id] [ore] [coal]
  • tools/experiments/worldgen.js: World generation report: time to generate, how many cells of each material, where the bot starts, and what idle ticks and ticks after digging cost.
  • tools/scenes/bar-lift.js: A mold drops copper bars onto a belt, through a screw lift and onto the upper belt.
  • tools/scenes/belt-heap.js: A belt feeding an upward screw: sand underneath a deep heap of copper ore. Run clear-sky.js first, e.g. python3 tools/shot.py /tmp/belt-heap.png --setup tools/scenes/clear-sky.js --js "$(cat tools/scenes/belt-heap.js)" --ticks 240 --zoom 7
  • tools/scenes/clear-sky.js: A clear work area left of the bot's starting point (the trade dock is to its right): open sky 160 grains wide and 40 tall, over a flat stone floor. Money and a bag of building stuff to build with. Sets FLOOR (the first row of the floor), BX, BY (the leftmost block of the area that stands on the floor) and CAM (the middle of the area).
  • tools/scenes/joins.js: Travel join grid: UR/DR/DL/UL, both ends, and all three neighbouring placements. Screw H and V, then belt H; each tries the side, above/below, and E. Self-contained, paused and empty. Use --zoom 4 --viewport 2100x1500 --no-light.
  • tools/scenes/mold-labels.js: Run after clear-sky.js: filling, blocked, set, and hot machinery in one view.
  • tools/scenes/silo.js: Run after clear-sky.js; leave paused so the open gate keeps its demonstration charge.
  • tools/scenes/slope-conveyors.js: Loaded sidewall conveyor and screen. Use --js 'slopeScene(false)' (belt) or 'slopeScene(true)' (screen).
  • tools/scenes/stone-uses.js: The stone and sand machines: a half-full silo with its gate open over a belt, a stone cutter fed with rubble, and cut stone and glass brick walls. Run clear-sky.js first, e.g. python3 tools/shot.py /tmp/stone.png --setup tools/scenes/clear-sky.js --js "$(cat tools/scenes/stone-uses.js)" --ticks 240 --zoom 7
  • tools/scenes/t-screen-joint.js: Downhill screen whose outlet belt sits level with its last block (the jam the owner saw).
  • tools/scenes/t33-ground.js: Paused dug pocket: copper ore, rubble and dirt against stone, granite and dirt. Use --js "..." to set daylight or R.lens after this setup; CAM frames the pocket.
  • tools/scenes/t35-diagonal.js: Run after clear-sky.js: a belt takes sand from a pile, up a diagonal screw to an upper belt.
  • tools/scenes/t35-joins.js: Run after clear-sky.js. Paused, empty pipes make casing, flights and mouths easy to inspect.
  • tools/scenes/t36-funnel.js: A twelve-block funnel, one block open at the bottom, draining 400 grains of sand.
  • tools/scenes/t40-sloped-belt.js: Self-contained: a flat feed climbs, crosses the top, and runs downhill; a filter sorts below.
  • tools/scenes/t88-light.js: Frozen light comparisons, also used by the WebGPU browser regression suite.
  • tools/scenes/t88-renderer.js: Paused comparison scene: ordinary grains, fog, heat, trees and exceptional geometry.