32 KiB
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
tasks/, .kandown/ the owner's to-do list: a kandown board (docs/kandown.md)
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/style.css all styles
src/sim/ the simulation. No DOM. The headless tests load only these files.
src/render/ drawing: the pixel look (CPU) and the smooth look (WebGL2), 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); run_all.py
tools/ serve.py (build, serve, rebuild on change), shot.py (screenshots),
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)
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/letmust 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 ofsrc/sim/base.jscovers everything.
- The frame loop (
frameinsrc/ui/loop.js):- read input;
- run up to
SET.maxStepssimulation ticks, at 60 ticks a second of game time (none while paused); - draw the world (
drawWorld) and the overlays; - update the HUD.
- One tick (
simTickinsrc/sim/tick.js), in this order:- update the sky roof line (every 20 ticks);
- weather, machines (including belts and tubes), 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 × Hgrains; celli = y * W + x. Worlds are 2048×1024, 3072×1280 or 4096×1536. - Per-cell typed arrays:
mat: material id;temp: °C;flags:F_NATnatural rock,F_CAST,F_BURNburning;stamp: moved this tick;part: which built part a cell belongs to (P_*: tube directions, grate, open gate, filter, pipe...);mach: machine id;digp: drill damage;occ: covered by a bar;bgm: the background layer (trees);- also
life,netIdandnoiseB.
- Blocks: the 4×4-grain build grid (
BS = 4).blockPholds the piece code (BP_*) andblockVthe variant (direction, wall material, flags) of each block, overBW × BH. - Chunks of 32×32 grains.
awakemarks chunks where things move andhotwhere heat flows; only those are simulated.setCellwakes what it touches; after writing arrays directly, callwakeXY/wakeHeatXY. - Other state:
fog: exploration at one cell per 2×2 grains; see fog;machines: index = machine id; removed ones arenull. 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 tube 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 = 0toBARSB = 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_SOLIDholds,PH_POWDERfalls and piles,PH_LIQUID,PH_GAS, andPH_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 codeBP_*); - kind
machine(bw × bhblocks); - kind
mold.hiddenpieces are not in the menu. The menu's tabs and order areBUILD_CATSinsrc/ui/build-menu.js.
- kind
- 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
(
ghostTickinundo.js). - Undo:
undoRecord(label, fn)wraps one player action; the place and remove functions record their own steps withundoNote(op). - Blueprints (
blueprints.js):copyRegion,cutRegion,flipBlueprint,pasteGhost.
Drawing
- The pixel look:
drawWorld(src/render/world.js) fills one pixel per grain;computeLight(light.js) adds coloured light;- overlays (machines, molds, the bot, rain, arrows) are drawn on the 2D canvas afterwards
(
machines.js,overlays.js).
- The smooth look (
src/render/smooth.js) takes the buffersdrawWorldfills (colour and a class per cell, the colour behind, trees, fields, light, glow) and shades them with WebGL2.- The cell classes are set in
world.jsand read in the shader: 4 is a crisp built piece, 6 a wall tile, 7/8 a belt, 9–12 a screw tube, 13/14 a filter. - On software GL it falls back to pixels, unless
window.__allowSoftwareGLis set (the test tools set it).
- The cell classes are set in
The browser shell
GAME(src/ui/state.js) holds the UI state: tool, selected piece, build tab, drag, clipboard, paste mode, overlays.SETholds the settings, kept inlocalStorage.- 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.
- worlds are kept in IndexedDB (
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) |
| 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 tubes | src/sim/conveyors.js, 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/smooth.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 (167 lines)
Material ids, the material table (def), per-material property arrays, cell flags and part ids, and drill/tank tiers.
- functions: def, metalFamily
- variables: EMPTY, GRASS, DIRT, LDIRT, SAND, GRAVEL, CLAY, STONE, GRANITE, BASALT, NMAT, MD, FIRETO, PH, DENS, KC, ICAP, CASTMETAL, METAL_TIER, SOLIDMETAL, F_NAT, F_CAST, F_BURN, P_NONE, P_TU, P_TD, P_TL, P_TR, P_GRATE, P_GOPEN, P_WHEEL, P_INTAKE, P_FILTER, P_PIPE, TDX, TDY, BIT_TIERS, TANK_TIERS, REACH
src/sim/pieces.js (141 lines)
Everything the player can build (PIECES): blocks, machines and molds, with costs and descriptions; filter settings; wall materials and their cost.
- functions: isPipeCode, filterable, cleanFilterCfg, filterRec, filterPassAt, filterInfo, sameFilter, wallCost
- variables: BS, BP_WALL, BP_BELT, BP_TUBE, BP_SHAFT, BP_GRATE, BP_GATE, BP_FILTER, BP_PIPE, BP_PUMP, BP_OUTLET, BP_GRIND, BP_SAW, BP_PRESS, filterCfg, WALL_OF, WALL_LIST, BAR_OF, GRAINS_PER_BAR, POWER_FREE, CASH, PIECES, PIECE_BY_ID, PIECE_BY_CODE, BELT_POWER, TUBE_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 (97 lines)
World state: the per-cell typed arrays, alloc(), ambient temperature by depth, waking.
- functions: emit, bagCap, discover, alloc, depthU, depthY, computeAmbient, fillNoise, 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, awake, hot, hotLvl, tick, tickStamp, machines, molds, nets, pcells, powerDirty, beltL, beltR, tubeLists, 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 (176 lines)
Cell helpers (setCell, move, enter) and the falling-sand movement of powders, liquids and gases (simMove).
- functions: setCell, swapCells, move, enter, powder, passable, liquid, gas, simMove
- variables: SORTP
src/sim/heat.js (246 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, ALLOY
src/sim/machines.js (148 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/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 (163 lines)
Per-tick machine work: steam engines, fans, belts, filters, screw tubes (machinesTick).
- functions: engineIntake, fanBlow, machinesTick
src/sim/conveyors.js (128 lines)
How belts, filters and screw tubes 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: carryColumn, beltDrain, launchGrain, rebuildFilters, filterCarry, setFilter, filterRun, roomFor, tubeSpread, tubeIntake
- variables: CARRY_DEPTH, filterR, filterL, filtersDirty
src/sim/blocks.js (136 lines)
Building blocks: placing, integrity, removing, lines and rectangles of blocks.
- functions: blockOf, blockCellList, pieceCost, canPlaceBlock, placeBlock, blockIntegrity, removeBlock, blockLine, blockRect, blockInReach, blockIs, placeBlocks
src/sim/molds.js (319 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 (203 lines)
Bars and other loose objects (ents), and the bag: adding, taking, costs and refunds.
- functions: entSolidCell, entFreeAt, entMark, spawnBar, removeEnt, entTubeAt, entTubeFree, entTubeMove, entTubeEnter, entTubeTick, entTick, entsInCircle, bagAdd, bagTake, giveOrDrop, refundAt, canAfford, payCost, fmtMoney, costText, needText
- variables: BAR_W, BAR_H, entCurM, droppedLast
src/sim/tools.js (52 lines)
Tool helpers: reach, brushes, and plain digging.
- functions: inReach, forBrush, drillReach, inDrillReach, toolDig
src/sim/drill.js (161 lines)
The resonance drill: tuned pulses that shatter one material.
- functions: drillOrigin, pulseRay, builtCell, toolPulse, crumbleAround, crumbly, shatterCell, pulseTick
- variables: PULSE_W, PULSE_EVERY, PULSE_SPEED, PULSE_K, drillPulses, lastPulseTick, drillWidth, THIN_BONUS, CRUMBLE_MAX, THIN_BONUS_OFF
src/sim/nature.js (168 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 (166 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 (87 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 (87 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 (43 lines)
Milestone checks (the ledger) and the sky roof line used for cooling.
- functions: checkLedger, updateRoof
src/sim/weather.js (85 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/tick.js (26 lines)
simTick: one simulation step, in order.
- functions: simTick
src/sim/worldgen.js (322 lines)
World generation: noise, layers, ores, caves, water, trees, and clearing tiny hard specks.
- functions: makeNoise, fbm, clearHardSpecks, generateWorld
- variables: SPECK_MIN
src/sim/save.js (126 lines)
Saving and loading a world (serializeWorld / deserializeWorld) and old-save migration.
- functions: serializeWorld, deserializeWorld
- variables: SAVE_VERSION, TOFF
src/render/setup.js (196 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
- 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/light.js (79 lines)
Propagated coloured light from glowing and burning cells.
- functions: computeLight
src/render/world.js (308 lines)
Scale colour without changing the smooth-look class.
- functions: fogColor, drawWorld
- variables: TUBE_CLASS
src/render/machines.js (212 lines)
Machine overlays: fans, engines, silo and the rest, drawn on top of the world.
- functions: cellRect, drawHazardRims, drawMachines, drawProcBlocks, drawSilo, drawSiloPixel
src/render/overlays.js (229 lines)
Other overlays: floating text, rain and snow, flow arrows, filter tags, molds, the bot, particles.
- functions: spawnFloater, drawRain, drawFlowArrows, drawRunOutline, drawFilterTags, drawFloaters, moldLabel, drawMolds, drawBot, spawnDebris, spawnSpark, spawnSuck, drawParticles
src/render/smooth.js (430 lines)
Smooth look: a WebGL2 pass that turns the per-grain buffers drawWorld fills (colour + class, colour behind, trees, occupancy fields, light, glow) into rounded, outlined, softly lit shapes at screen resolution. The 2D canvas then draws this image as its world layer, and every overlay (machines, bot, previews, labels) goes on top as before.
- functions: smCompile, smoothAvailable, smUpload, smoothDraw, smoothPace
- variables: SM, SM_VS, SM_FS, smBytes
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 (75 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/title.js (46 lines)
The title screen art.
- functions: buildTitleCells, drawTitle
- variables: FONT5, TITLE
src/ui/saves.js (212 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
src/ui/claims.js (115 lines)
Shared player state; the world save remains a complete standalone fallback.
- functions: careerState, validCareer, applyCareerState, loadCareer, openNewClaim, travel, renderClaimsTab
- variables: career, claimBusy
src/ui/session.js (133 lines)
Starting, loading and quitting a game; modal dialogs; the pause menu.
- functions: showLoading, enterGame, setupNewWorld, startNewWorld, startFromSave, 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 (204 lines)
The notebook (N): milestones, market, wallet, blueprints, controls.
- functions: openNotebook, renderNotebook, fmtClock, orderName, orderLeft, renderMarketTab, fmtPrice, itemsText, renderWallet, renderBlueprintTab, copyCode, controlsHtml
- variables: nbTab, MARKET_GROUPS
src/ui/hud.js (34 lines)
The tool hotbar and what is selected.
- functions: renderHotbar, toolId, steering, modShift, grainAt, selectTool, bagMaterials, blowList, blowAllList, blowingAll, piece
src/ui/build-menu.js (103 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 (242 lines)
The selected tool and piece: R / Q / E, drill width, filter picker, the selection card, the bag panel.
- functions: pieceUsesWall, setDrillWidth, tuneUnderCursor, cycleItem, cycleWall, rotate, toggleBlow, pickFilterUnderCursor, toggleFilterMat, setBrush, pieceV, pieceExtra, filterChoices, matList, filterParts, filterSentence, applyFilterRun, openFilterPicker, openWallPicker, filterBlockAt, chipCost, pieceCostNow, renderSelCard, renderBag
- variables: lastBagKey
src/ui/info.js (174 lines)
Discovery cards, hover info (I) and the cursor label.
- functions: showCard, howText, discoveryCard, reactionsOf, hoverInfo, renderInfo, drawCursorLabel
src/ui/input.js (89 lines)
Keyboard and mouse listeners.
- functions: isTyping
- variables: canvas
src/ui/actions.js (239 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, toolTick
- variables: ovShown
src/ui/gamepad.js (60 lines)
Gamepad input.
- functions: padPressed, pollPad
- variables: PAD
src/ui/previews.js (371 lines)
Previews drawn under the cursor: build ghosts, drill aim and pulses, selections, paste.
- functions: blockRectPx, drawGrid, previewColor, crackSeg, drawCracks, pulseRGB, fanPoints, drawDrillPulses, drawDrillAim, drawAirStreaks, drawPreviews, drawTag, drawSelection, drawPastePreview
- variables: CRACK_N, CRACK_LV, SEL_COL
src/ui/events.js (42 lines)
Events from the simulation (emit) turned into sounds, toasts and cards.
- functions: drainEvents
src/ui/loop.js (126 lines)
The frame loop and boot.
- functions: scanVisible, frame, boot
- variables: lastT, acc, lastRender, frameMs, simMs, fpsSm, ambientT
Tests and tools
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/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/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_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_conveyors.js: Screw tubes that never carry liquid (it flows through), tube and belt throughput, filters.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_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_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_pipes.js: Pipes, pumps and outlets move liquids; the Grinder grinds waste rock for trace ore.test/t_smooth.py: The smooth look: the WebGL pass compiles, draws, falls back cleanly, 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_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/map.py: Regenerate the file and symbol index at the end of docs/PROJECT_MAP.md.tools/perf.py: Times the renderer and the simulation in a headless browser: light, drawWorld (with and without light and glow), the pixel upload and blit, and one simulation tick, in ms. Rebuild first.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/shot.py: Screenshot the game in a headless browser, after setting up a scene with JavaScript.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 tubes: 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/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 7tools/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/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/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