Spelunking · prototype timeline ▶ latest, live◆ shape map

Every prototype: what we believed, what we built, how it played, what we decided. Newest first. Each ▶ plays the build exactly as it was tested.

✓ 13 held ✗ 6 broken ? 45 open · 17 constraints · 13 prototypes · 108 builds · 186 decisions

p13

Taming

buildingbudget 3 daysgrew out of p12 · Shape map (v9)

Can one taming engagement be as easy to start and as hard to master as Slay the Spire, as strategic and intriguing as Sonny, and as free as Noita's wand building, without luck and without killing?

▶ v10.42026-10-05 · the motivations act on each other, one extreme per animal, and scripted encounters turn by turn (Claude's recommendation, with its reasons on the page)▶ v10.32026-10-05 · curiosity by intelligence: smarter animals are more curious by default; the animals still come out too alike▶ v10.22026-10-05 · decay and volatility merged into inertia (calm ↔ jumpy); comfort's default by size▶ v10.12026-10-04 · the taming gauge model: what each animal dimension does to each motivation's gauge, every cell a draft

→ Not concluded. Next: pressure downward in the gauge model (actions with side effects, animal moves that lower its own needles) and the lines tuned; then a toy of the taming alone, played by hand.

Full entry

Question

Can one taming engagement be as easy to start and as hard to master as Slay the Spire, as strategic and intriguing as Sonny, and as free as Noita's wand building, without luck and without killing?

Pass: in a toy of the taming alone, played by hand, a first encounter makes sense within seconds, and later encounters are won by reading the animal and combining the kit in ways that weren't written as pairs.

Kill: the encounters read as solved puzzles with one answer each, or the interactions turn into noise that can't be read on screen.

Assumptions

  1. [?] Full information and no luck still leave enough depth: the variety comes from scouting, the kit and procedurally generated animals, not from a draw.
  2. [?] Moves with several effects, on a shared visible state (the team, the animal, the cavern), make combinations nobody wrote as pairs, and stay readable turn by turn.
  3. [?] One engagement makes one game: scouting as team setup plus an automatic run in the simulation doesn't feel like a second, lesser game.
  4. [?] Routes into a tame from different pillars keep bait from becoming a grind, even with a food chain of two or more tiers.
  5. [?] Watchable replays let the user check that the simulator and its bot test the right thing.

Limitations

  • [constraint ?] No luck in the engagement: every encounter must be solvable by construction.
  • [constraint ?] Turn-based only; real-time engagements are an idea for meta-progression, not built.
  • [cut] Scouting: the next component; the food chain and the colony are content and balancing on the b4 system (D177; D188 in p12).
  • [cut] Levelling, team size and slots: knobs or left out until the taming toy needs them.
  • [cut] The market part of stage 4 from p12: parked.

Built

The decisions so far (design, no build yet):

DecisionWhat it settles
D196The gauge's properties are share, default and inertia (decay and volatility merged); small animals start less comfortable, large ones more
D195Fight or flight depends on the animal's strength against the team's; strong pets hold out longer when attacked but scare animals away
D194All models are wrong, but some are useful; "when scared" is no longer an axis: an animal fights, flees or hides by its strongest stat
D193Animals live in a trait space: discrete behaviour axes (diet, when scared, social) and stats (size and strength, agility, intelligence, nerve); traits add up to behaviour and pet skills, how is open
D187The taming gauge: willingness 0–100% in three zones, made of motivations, each with its own zones, temperament and decay; actions act on each motivation; a motivation-driven animal, to test
D186Learning an animal, kept abstract: observation can fill the whole card, with gaps when time ran out; engagements add the numbers and fill the gaps; shown, not told; families share rules; late game, animals bend them
D185The animal's card: scouting fills it by observation, taming through engagement; failed attempts reveal what scouting can't; attempts cost consumables, some from earlier tiers, never punitively (supersedes D184)
D183Routes into a tame come from different pillars; taming without bait is as hard, in another pillar's shape
D182Taming is the only engagement; scouting is team setup plus an automatic run; failure is the animal getting away and bait consumed
D181Turn-based, no time pressure, all cards on the table, the player acts every turn
D180The engagement is the core gameplay; the bar is Slay the Spire, Sonny and Noita's wand building
D179Taming plays like a deck-builder's combat with simpler UX: cooldowns instead of a deck, no luck, telegraphs, moves with several effects
D178Every simulated run can be watched: one rules core, replays from seed and actions, reports that link to runs
D177One component at a time: taming, the food chain, scouting, the colony

The research (guides/game-design): what makes the references' engagements work, and where they fail.

Where it stands: the design is in build-principles → Pillars and Building it: one component at a time. Open: whether the motivation-driven animal is fun and simple enough, and how the animal's state is shown. The gauge model lays out what each animal dimension does to each motivation's gauge, to go through cell by cell. v10.4's encounters show the animals behaving differently, but jumpy animals are the easiest to tame: nothing pushes a needle down. Next: pressure downward (actions with side effects, animal moves that lower its own needles), then tune the lines (findings).

Feedback

No play sessions yet: this is design work.

Conclusion → next

Not concluded. Next: pressure downward in the gauge model (actions with side effects, animal moves that lower its own needles) and the lines tuned; then a toy of the taming alone, played by hand.

p12

Shape map (v9)

buildingbudget 3 daysgrew out of p11 · Rail Loop (b4)
Shape map (v9)

Which game goes around the toy, matched to an audience that will be thrilled by it?

▶ v9.92026-10-04 · Monster Sanctuary joins the reference games, for its pet levelling, team building and synergy▶ v9.82026-10-04 · a passive Simulation pillar between Discovery, Design and Story balances the active loops around the audience▶ v9.72026-10-04 · the three loops as pillars: Engagement (a card battle) and Pet management (a management game) at the core, Resources (idle farming) in support▶ v9.62026-10-03 · one arrow per action (action, condition, outcome); the pillars The Unseen, Prospecting and Cultivation; and the lifecycle page▶ v9.52026-10-03 · the taming game: The Unseen, Caverns and Colony, with pioneers, foragers and the flows between them▶ v9.42026-10-03 · three equal pillars placed around the audience, far enough apart to rest from one another▶ v9.32026-10-03 · the audience: this game's motivation mix, set by the user (Discovery 30, Strategy 30, Power 20, Story 10, Challenge 10)▶ v9.22026-10-02 · the references: small indie successes split into their loops on the same axes, each audience read from its Steam tags▶ v9.12026-10-02 · the pool: 29 candidate shapes and their variants, placed on Quantic Foundry's motivation map

→ Not concluded: reopened on 2026-10-04 for the game's shape. So far the phase went from "no clue what mechanics this game needs" to three pillars (The Unseen, Prospecting, Cultivation) placed around the audience's motivations, with every interaction an action, a condition and an outcome, and a lifecycle simple enough to code and natural enough to read. Complexity now comes from depth and lore, not from uninformed decisions. Decisions D173–D176, then D188 (an incremental idle game), D189 (climb differently, not faster), D190 (three loops, beastmasters) and D191 (a passive Simulation pillar). Next: more work on the shape, alongside p13.

Full entry

Question

Which game goes around the toy, matched to an audience that will be thrilled by it?

Pass: a few distinct pillars that sit around the audience's motivations, swing between thinking and doing, and follow the rules collected in build-principles.

Kill: the shapes scatter with no audience to hold them together, and the choice falls back on taste.

Assumptions

  1. [✓] Candidate shapes and reference games can be compared on one motivation map, so the shape is placed instead of picked by taste. Held: the pillars were placed on the map around the audience (v9.4). (post-hoc)
  2. [✓] Successful small indies space their core and supporting loops apart, a swing between pillars that lets the player rest from one in the other. Held as likely: six of nine reference games show it; Stacklands and SUMMERHOUSE don't (findings). (post-hoc)
  3. [✓] The factors the audience decides stay open until the audience is chosen. Held: the audience mix came first (v9.3), the pillars after it (v9.4). (post-hoc)
  4. [?] The three pillars weigh the same for this audience. Nothing has been played yet. (post-hoc)
  5. [?] The lifecycle's rules read as natural and need no text: five stages, three decisions, the rest on autopilot. (post-hoc)

Limitations

  • [constraint ?] Every position on the map is a judgement (the shapes', the reference games', the pillars'), not measured data. The user checked the games they had played.
  • [cut] The market part of stage 4 (competition and success rate per market) is not done; it is the next step.
  • [cut] Stage 5, loop times and complexity, is parked until the end, as the method says.
  • [cut] Nothing playable: the first prototype of the pillars comes after this.

Built

The method (user, 2026-10-02), in the working folder: broaden (29 shapes), deepen, consolidate (two anchors), assess (each shape's motivation mix on Quantic Foundry's map), then loop times. The map page is the assessment drawn: every shape on two axes, World ↔ Player and Cerebral ↔ Kinetic.

The milestones, each frozen with the folder as it was:

BuildWhat it added
v9.1The pool of 29 shapes, each with the reason for its place
v9.2Reference games split into their loops, with each audience read from its Steam tags; the finding that core and supporting loops swing between pillars
v9.3Loops draggable when opened from disk; a card for each motivation; this game's audience mix (user)
v9.4Three equal pillars around the audience; build-principles starts: accessible and never boring, through systems
v9.5The taming direction: an ecology theme with no technology, pets that go on excursions, pillars named, flows between them
v9.6Every interaction as one arrow with an action, a condition and an outcome; the lifecycle of terrain, flora and fauna, with who does each step
v9.7The three loops the player controls as pillars: Engagement between Strategy and Challenge, Pet management between Strategy and Power, Resources (smaller, support) beside the idle shapes; passive things are spectacle and lore, not drawn; Design read as building for aesthetics
v9.8A passive Simulation pillar (dashed) between Discovery, Design and Story: the ecosystem running while the player is away, as spectacle and lore; with it, the pillars balance around the audience
v9.9Monster Sanctuary as an eleventh reference game: its loops, and its audience from the store page, which lands next to this game's audience; guide 16 on its levelling, team building and synergy

Where it ended (build-principles): ground moves Unseen → Wild → Caverns → Cultivated. The pioneers open the Unseen and tame fauna up the food chain to the top predator. The foragers study and forage, and build a colony once the top predator is tamed. A colony harvests itself. Only those three decisions carry a name; the hands-on game around them is levelling and combining the pet teams.

The game shape (2026-10-04, build-principles → Game shape): an incremental idle game. A session is one or more runs, and a run is anything that pushes the needle; colonies, foragers and scouts keep working while the player is away. Long-term progression climbs differently, not faster (D188, D189).

The loops (2026-10-04): three loops the player controls (engagement and pet management at the core, resource management in support); passive things are spectacle and lore. Pioneers are replaced by scouts and beastmasters (D190).

Feedback

No play sessions: this is design work. The user's corrections, objections and choices are in the log, dated, with their words.

Conclusion → next

Not concluded: reopened on 2026-10-04 for the game's shape. So far the phase went from "no clue what mechanics this game needs" to three pillars (The Unseen, Prospecting, Cultivation) placed around the audience's motivations, with every interaction an action, a condition and an outcome, and a lifecycle simple enough to code and natural enough to read. Complexity now comes from depth and lore, not from uninformed decisions. Decisions D173–D176, then D188 (an incremental idle game), D189 (climb differently, not faster), D190 (three loops, beastmasters) and D191 (a passive Simulation pillar). Next: more work on the shape, alongside p13.

p11

Rail Loop (b4)

buildingbudget 3 daysgrew out of p10 · Rails (v8)

Does exploring as a spider bot, mining on the way, and building rails node by node make a loop you want to repeat into the next cavern?

▶ live b4latest, unfrozen▶ b4.772026-09-28 · p11: b4.77, slime films gassy rock and bugs tap it for gas (D163); refrozen 2026-10-04: moths hatch only while fewer than 2 are near the node (D192); reset and stuck buttons▶ b4.762026-09-28 · p11: b4.76, beasts eat 30-100 px from you where there's no moss (D162)▶ b4.752026-09-28 · p11: b4.75, no hives; built nodes with gas hatch a moth every 30 s (D161)▶ b4.742026-09-28 · p11: b4.74, hives twice as often (D160)▶ b4.732026-09-28 · p11: b4.73, predators haul their catch, hives hatch moths, 5x gas, bugs leave fruit (D156-D159)▶ b4.722026-09-28 · p11: b4.72, pink predators eat crowded bugs and leave ore (D155)▶ b4.712026-09-28 · p11: b4.71, tamed bugs that meet gas fly as moths, jumpers paler (D154)▶ b4.702026-09-28 · p11: b4.70, bugs are wall-bouncers, units to the ledger at once, one nibble tames (D153)▶ b4.692026-09-28 · p11: b4.69, tamed bugs lay moss only where there's gas, one gas a pixel (D152)▶ b4.682026-09-28 · p11: b4.68, tamed bugs stand still with fire within 6 px (D151)▶ b4.672026-09-28 · p11: b4.67, saturated gas stations pass half their surplus on through the cave (D150)▶ b4.662026-09-28 · p11: b4.66, beast pools evaporate into gas at the nodes (D149)▶ b4.652026-09-28 · p11: b4.65, worms glide between pixels (D148)▶ b4.642026-09-28 · p11: b4.64, loot is crystals (D146); tamed bugs shield a 3x3 from fire (D147)▶ b4.632026-09-28 · p11: b4.63, every 4 built nodes add a tamed bug; loot no longer tames (D145)▶ b4.622026-09-28 · p11: b4.62, the game saves itself and comes back on the next visit (D144)▶ b4.612026-09-28 · p11: b4.61, the mega beast in crawling dark pixels (D143)▶ b4.602026-09-28 · p11: b4.60, worms tunnel to fruit (D142)▶ b4.592026-09-28 · p11: b4.59, mega beasts eat bulbs; their drops fill cave pools (D141)▶ b4.582026-09-28 · p11: b4.58, tamed bugs eat 2x slower (D140)▶ b4.572026-09-28 · p11: b4.57, lizards linger: 3x slower licks, zip after every rest, 5x longer life (D139)▶ b4.562026-09-28 · p11: b4.56, loot upgrades lizards; the bug level grows you (D138)▶ b4.552026-09-28 · p11: b4.55, lizards dash off the wall for ash and back (D137)▶ b4.542026-09-28 · p11: b4.54, lizards eat ash and burrow into 5 loot (D136)▶ b4.532026-09-28 · p11: b4.53, bulbs light up within the light's radius (D135)▶ b4.522026-09-28 · p11: b4.52, bulbs: 50 ms hold-off, 1.5 s eject (D134)▶ b4.512026-09-28 · p11: b4.51, tamed bugs head for back wall not green yet (D133)▶ b4.502026-09-28 · p11: b4.50, built nodes on the ledger (D132)▶ b4.492026-09-28 · p11: b4.49, a just-tamed bug starts near you (D131)▶ b4.482026-09-28 · p11: b4.48, loot triple-pings now and then (D130)▶ b4.472026-09-28 · p11: b4.47, pinch zoom, zoom in CSS px, brighter on touch screens (D129)▶ b4.462026-09-28 · p11: b4.46, scans no longer scare wild bugs (D128)▶ b4.452026-09-28 · p11: b4.45, burst light worms give pink; ledger rows earned with theatrics (D127)▶ b4.442026-09-28 · p11: b4.44, the bot row counts you plus the flower bots (D126)▶ b4.432026-09-28 · p11: b4.43, the ledger: resources, a gap, then levels; fruit a pixel (D125)▶ b4.422026-09-28 · p11: b4.42, hearts half the bites, a "?" when the ledger has no ore (D124)▶ b4.412026-09-28 · p11: b4.41, lichen light, no scan circle, drag-and-release bulbs (D123)▶ b4.402026-09-28 · p11: b4.40, a wild bug that finds loot eats it and is tamed (D122)▶ b4.392026-09-28 · p11: b4.39, lizards over the fog; a round mask hides the map's repeat (D121)▶ b4.382026-09-28 · p11: b4.38, ride at 40 px/s; a tap gets you off mid-root (D120)▶ b4.372026-09-28 · p11: b4.37, a ragged fire from 3 embers; ash worms that lift the fog (D119)▶ b4.362026-09-28 · p11: b4.36, tamed bugs start their trips away from vines first (D118)▶ b4.352026-09-28 · p11: b4.35, smaller ash patches, r 2-3 (D117)▶ b4.342026-09-28 · p11: b4.34, tamed bugs start their trips where the fewest bugs are (D116)▶ b4.332026-09-28 · p11: b4.33, flower bots grow the network's rim; vines touching ash make fruit 10x (D115)▶ b4.322026-09-28 · p11: b4.32, the network under the fog, smaller bulbs (D114)▶ b4.312026-09-28 · p11: b4.31, lichen sparks 4x rarer (D113)▶ b4.302026-09-28 · p11: b4.30, fix the crash when a lizard's ore flight outlived the lizard▶ b4.292026-09-28 · p11: b4.29, half the flowers, dimmer (D112)▶ b4.282026-09-28 · p11: b4.28, white loot, lizards don't glow, 1 flower per 4 ash discs (D111)▶ b4.272026-09-28 · p11: b4.27, a dimmer network; only the bulb holding the bot beats (D110)▶ b4.262026-09-28 · p11: b4.26, a bulb ejects the bot after 3 s with nothing built (D109)▶ b4.252026-09-28 · p11: b4.25, brighter fire with sparks; ash flowers bloom into bots that extend the network (D108)▶ b4.242026-09-28 · p11: b4.24, ride a root by pointing along it near its node; still bulbs on built nodes (D107)▶ b4.232026-09-28 · p11: b4.23, lichen grows on a large area of the bugs' cover, not on loot (D106)▶ b4.222026-09-28 · p11: b4.22, roots and bulbs instead of the metro map, scan on touch, no lizards in small caves (D103-D105)▶ b4.212026-09-28 · p11: b4.21, lichen sparks a fire through the bugs' cover, leaving ash discs (D102)▶ b4.202026-09-28 · p11: b4.20, lizards spawn on reachable ore and route to it, so they retire (D101)▶ b4.192026-09-28 · p11: b4.19, the lichen's leaf in pixels (D100)▶ b4.182026-09-28 · p11: b4.18, soft and hard rock much darker (D099)▶ b4.172026-09-28 · p11: b4.17, no loot in the generated world, only lizards make it (D098)▶ b4.162026-09-28 · p11: b4.16, the cave's back wall dark grey-blue, apart from the unexplored black (D097)▶ b4.152026-09-28 · p11: b4.15, loot upgrades the bot, +20% radius and speed per upgrade, the bot on the ledger, purple lichen (D096)▶ b4.142026-09-28 · p11: b4.14, taming hearts, ore-eating lizards that burrow into loot, ore and loot as specks in the rock (D095)▶ b4.132026-09-28 · p11: b4.13, fruit buys the bugs' reach (16, 32, 64…), wild bugs drawn like tamed in blue, no taming particles (D094)▶ b4.122026-09-28 · p11: b4.12, worms turn fruit into ore deposits, fruit stops glowing, your pull favours the scarcest resource (D091–D093)▶ b4.112026-09-28 · p11: b4.11, bugs mine within 4 px (D090)▶ b4.102026-09-28 · p11: b4.10, the garden: bugs green the back wall, vines grow, glowing red fruit on the ledger (D089)▶ b4.92026-09-28 · p11: b4.9, after the first edge only built edges' ends show; unconnected pod nodes hide (D088 corrected)▶ b4.82026-09-28 · p11: b4.8, only network nodes show, the pod's glow until the first edge, quieter rings (D088)▶ b4.72026-09-27 · p11: b4.7, tamed bugs' trips 30 s, pulling with the player's stream and flight (D087)▶ b4.62026-09-27 · p11: b4.6, the scan fires only when something within its radius is unseen (D086)▶ b4.52026-09-27 · p11: b4.5, the bot mines while walking (D085)▶ b4.42026-09-27 · p11: b4.4, the bot glides at every angle (sub-pixel), explored unlit areas 50% darker (D084)▶ b4.32026-09-27 · p11: b4.3, the incremental turn: one ledger, abstract tamed bugs, tap-drag-tap build, 8 px line-of-sight light, nodes never in rock, any-angle walk, 1 s scan (D083)▶ b4.22026-09-27 · p11: b4.2 built per next-b4.2.md, the world at 1 px of v5 with b3.7's rock, pack and bugs (D082)▶ b4.12026-09-27 · p11: b4 Rail Loop, step 1: the whole loop without bugs (new bundle, not a copy of b3; D079)

→ The Question (does a scan-mine-build rail loop pull you into the next cavern?) was overtaken by the incremental turn (b4.3) and then by the ecosystem (b4.10 onwards: moss, vines, fire, ash, lizards, worms, beasts, gas, moths, predators, slime). What p11 found instead, in the user's words: "It is possible to build a very enjoyable and engaging cave ecosystem idle game, that both feels very involved, but at the same time, does not really need the player to run. It is possible to engineer it to make time spent rewarding - e.g. taming a lot of moths and pushing the game out of balance temporarily for a big fat resource reward, but the system can be designed to be resilient, and restore balance after the push."

Full entry · 3 feedback sessions

Question

Does exploring as a spider bot, mining on the way, and building rails node by node make a loop you want to repeat into the next cavern?

Pass: the player scans and mines to afford the next edge, not as a chore; building an edge and riding it to a new cavern feels like a reward; they go for the next one without being asked.

Kill: walking around to fill the pack feels like waiting for the build, or the rails feel like a menu rather than a place. Then the costs or the node spacing change before anything is added.

Assumptions

  1. [?] b3's probe, pull, pack, light and bugs work unchanged on the new terrain once it's in b3's tile world (Tile: open, soft, hard, ore, loot).
  2. [?] D078's lattice (3 cells apart, Gabriel, rock ×5, bend 15, overlap +100%, crossing 100) gives reachable, affordable edges from the pod on every seed.
  3. [?] The player can't trap themselves (user: "we will have to adjust to make sure"): from wherever you stand, some edge is affordable, or ore to afford one is within reach.

Limitations

  • [cut] The shield timer (D077), walls, gates and buildables (small, big, titan): later (user).
  • [cut] Rendering stays b3's Canvas2D; it moves to PixiJS later.

Built

b4 step 1, the whole loop without bugs (2026-09-27, b4.html, src/bundles/b4/). A new bundle, not a copy of b3 (D079). world.js makes the tile world: p7's quad caves, the pod's interior carved open (no dome walls), p10's rails (mode C, D078's defaults) in tiles, and b3's CA ore layer over the rock, with loot by chance. game.js is b4's own sim, reusing b3's probe rings, pull targeting, pack and light (src/sim/dig/); input.js, render.js and main.js are new; the dev panel is b3's. Checked in headless Chromium: walking and the scan, the hold preview, the drag selection with the red X and the green hammer, the ore stream and the build, boarding the car, a swipe ride to the far node. Claude's calls while building:

  • Ore: b3's ore layer seeds at 380‰ (knob world.ore), because b3's 280 leaves 20–60 ore tiles on this 60 × 40 map; 380 gives 75–206 across five seeds.
  • The pull: 1 s a unit (knob sim.pull.ticks), not b3's 5 s, or an edge is nearly a minute of standing still.
  • The scan fires on the rock tile pointed at; a diagonal into rock slides along the open side first.
  • A revealed node can be built from anywhere (user: "if the node is revealed, I'm standing close enough").
  • Rails cross rock without carving it; cars are the only way through.
  • In a car, drags are always swipes (the car stands on a node); pointing where no built edge fits, while stopped, gets you out and walking that way; Space is the keyboard's tap.
  • You only get out of a car onto an open tile: a node's tile can be rock (the router rounds nodes to tiles), and getting out there shut the bot in the rock with its car out of reach (the build check's finding).
  • Rails at the frame's bottom edge, where the router clamps a node, are dropped.
  • Edges are short (3–7 tiles on seed 1): D078's spacing of 3 cells.

Not yet: the bugs (step 8). Not pushed: a new bundle needs the build check and a freeze (R13, R16).

b4.2, the user's notes on b4.1 (2026-09-27, D080, D081, D082; plan: next-b4.2.md). Built in the plan's order, each step play-checked in headless Chromium (screenshots gallery/p11/b4.2_*):

  1. The world: a tile is one v5 pixel, all of v5's map (240 × ~528 px) under v6's sheet (solid, drawn with no fog, stars above), the sea at the bottom solid; network C routed over the whole depth (rails 120–320 ms, the whole map 0.4–0.7 s); b3.7's ore layer (≈10% of rock, as b3.7), loot 50‰ and hard/soft split (≈42% hard) at the map's size, wrapping. The pod's interior starts seen; nothing is always lit.
  2. Nodes: the network's show for good, the rest only within 12 px; edges build only from a network node within 12 px of the bot.
  3. Speeds: walk 12 px/s, ride 80 px/s (knobs sim.walkSpeed, sim.rideSpeed, in px/s now).
  4. The pack: b3.7's, ore and loot slots reserved, drawn at the top of the screen (the bot is 1 px), with the ore-against-price bar under it; a refused build blinks it red, as b3's did.
  5. Bugs: b3.7's as they are, with b3.7's numbers. A 1 s hold within 60 CSS px of the bot places one (E held 1 s on a keyboard), with b3's filling ring.

Claude's calls while building (D082):

  • Lit rock goes 4 px deep (knob sim.light.face): at 1 px, b3's one-tile face was a hairline.
  • The light grows +1 px per 4 ore or 2 loot (b3's per 16 / 8 tiles ×4); the scan runs a ring a tick (0.4 s to radius 24, about b4.1's 0.5 s). An edge's heading is read 12 px out (b4.1's 3 tiles).
  • Nodes are drawn as rings: at 1 px a tamed bug is a warm dot too.
  • The fog and the world textures change pixel by pixel (a whole repaint each step was too slow to play).
  • Zoom levels 2–24 device px a tile, default about 100 px across the short side.
  • b3's wild-bug glow through the fog is left out (2 px at this scale).

Seen in the check: the start cave is small and all lit, so no wild bug can appear in it (b3's rule: dark cells only); in a big cave a chaser came at once and one was tamed within 5 s. b3.7's seek of 20 steps is 20 px now: sim.bugs.seek is on the panel, with the other bug numbers, for tuning in play.

b4.3, the user's notes on b4.2 (2026-09-27, D083; plan: next-b4.3.md). The game turns incremental. Built in the plan's order; tests (src/bundles/b4/game.test.js, the new sight tests in light.test.js) and a headless Chromium check (screenshots gallery/p11/b4.3*):

  1. The light: a fixed 8 px, line of sight (sightCells in src/sim/dig/light.js, b3 keeps its flood), rock lit 1 px deep; its last 3 px fade out. The pull reaches 8 px too.
  2. Nodes never in rock: v8 mode C skips a vertex whose tile centre is rock (v8's page gets it too). Seeds 1–5: 0 nodes in rock (was 24–37), ~380 nodes on rails as before.
  3. The ledger, top right: ore, loot, bugs. Pulls count there; the build gesture is tap node, drag, release, tap the green-flashing edge; the price shows on it; red pulse and a red ore count when short.
  4. Wild bugs nibble the ledger; 16 fed is +1 bug (bugs.js's ledger switch; b3 unchanged). Tamed bugs: swarm.js, knobs sim.swarm.* on the panel (trip 2 min, 5 px/s, a unit a second within 2 px).
  5. The user, mid-build: walking at any angle (a drag's angle; keys stay 8-way), the scan's cooldown 1 s.

Gone: the pack, the bug bar, placing bugs (the 1 s hold, E), placed bugs mining, the X and hammer, the ore streaming into the node. Seen in the check: the start cave has loot but little ore within 8 px, so the first edge takes some walking. Then (D084, the user): walking glides at the drag's exact angle (a sub-pixel position; b4.3 still stepped in 8 ways on screen), and explored, unlit areas are 50% darker (17.5% bright). Then (D085, the user): the pull goes on while walking (not in a moving car). Then (D086, the user): the scan fires only when some pixel within its radius is still unseen. Then (D087, the user): tamed bugs' trips last 30 s, and they pull with your dust stream and flight. Then (D088, the user): only network nodes show; the pod's glow until the first edge, then only the ends of built edges show, as quiet rings (b4.9 fixed b4.8, which kept the pod's showing). Then (D089, the user): the garden (garden.js): bugs green the back wall, vines grow on green, 12 px of vine make a red fruit a minute; fruit glows, is harvested by you and bugs (8 a bug) and sits on the ledger's 4th row. Then (D090, the user): bugs mine within 4 px. Then (D091–D093, the user): worms (worms.js) spawn where fruit is dense, eat 8, burrow and curl up into 12 px of ore inside the rock; fruit no longer glows; your pull goes for the kind the ledger holds least of. Then (D094, the user): no taming particles; wild bugs drawn like tamed ones in blue; fruit buys the bugs' reach by itself (16, 32, 64…, +1 px each), the ledger shows the next target and a bug icon per upgrade. Then (D095, the user): hearts when a bug is tamed; lizards (lizards.js) where ore is plentiful, zipping round the surfaces mining ore, burrowing after 16 into one loot inside the rock; ore and loot drawn as specks in the rock. Not seen on screen in the check: the hearts (the start cave is all lit, so no wild bug came). Then (D096, the user): loot buys the bot's upgrades (16, 32, 64…), every upgrade +20% mining radius and speed, the bot on the ledger; purple lichen (lichen.js) with a curly leaf where loot is plentiful. Then (D097, the user): the cave's back wall is dark grey-blue, apart from the unexplored black. Then (D098, the user): no loot in the generated world; lizards are its only source. Then (D099, the user): soft and hard rock much darker, under the back wall's grey-blue. Then (D100, the user): the lichen's leaf is world pixels, not a smooth curve. Then (D101, the user): lizards spawn only with 24 reachable ore within 16 px, and route along the surface to ore they can reach (a 32-step flood); 163 of 176 retired in a 20-minute measurement (was 1 of 20). Then (D102, the user): a lichen next to the bugs' cover sparks once and its leaf withers; the fire spreads through all the connected cover like a cellular automaton, leaves bare wall, and burns permanent round ash discs (r 3–5, 8–12 px apart). Screenshots gallery/p11/b4.21_fire_*. Then (D103, the user): the network is wiggly orange roots along the caves' relaxed mesh, in pixels; a node is a beating orange pixel bulb, shown only while the ledger holds the price; 2 px close it holds the bot until an edge is built (drag aims, tap builds); no carts, the bot rides the root itself. D104: the scan fires the moment the bot touches rock. D105: no lizard spawns in a cave under 400 px. Screenshots gallery/p11/b4.22_*. Then (D106, the user): lichen grows where the bugs' cover is large (150 px within 12), not where loot is. Then (D107, the user): pointing along a built root within 2 px of its node rides it; built nodes show a still bulb, buildable ones beat. Screenshots gallery/p11/b4.23_*. Then (D108, the user): brighter, many-coloured fire with sparks; the ash grows white flowers (1 per 24 px) that bloom after 2 minutes into light-less bots; they clear their ash, go to the network, zip along it, build 3 edges from your ore (60 s apart at least) and pop. Screenshots gallery/p11/b4.25_*. Then (D109, the user): a bulb lets the bot go after 3 s with nothing built. Then (D110, the user): the roots and bulbs much dimmer; only the bulb holding the bot beats, bright. Then (D111, the user): loot white; lizards under the fog, duller; 1 flower per 4 ash discs. Then (D112, the user): 1 flower per 8 ash discs, drawn dimmer. Fix (the user's crash in b4.28, there since b4.14): a lizard's ore flight named the lizard by its index, which went stale when one burrowed; the licked event now carries where its head was. Then (D113, the user): lichen sparks 4× rarer, 1 in 24 checks. Then (D114, the user): roots and still bulbs under the fog, bulbs a 5 px plus. Screenshots gallery/p11/b4.32_*. Then (D115, the user): flower bots grow the network outwards only, heading for its rim; vines touching ash make fruit 10× as fast. Then (D116, the user): a tamed bug starts its trip at the network node with the fewest bugs round it. Then (D117, the user): ash discs r 2–3, leaving room for the vines. Then (D118, the user): a tamed bug starts where there's no vine first, then where the fewest bugs are. Then (D119, the user): the fire starts at 3 points and spreads by chance, ragged; ash sends out grey worms with side lights that snake 12 s towards the unexplored and lift the fog. Screenshots gallery/p11/b4.37_*. Then (D120, the user): riding at half the speed, 40 px/s; a tap gets you off at the next open pixel. Then (D121, the user): lizards over the fog like every animal; a round, soft-edged mask as wide as the map hides its repeat. Screenshots gallery/p11/b4.39_*. Then (D122, the user): a wild bug that finds loot eats it and is tamed. Then (D123, the user): lichen lights 24 px round it, faintly and for good; no white scan circle; in a bulb a drag picks a root (built: lit orange, affordable: green), letting go rides or builds it, 3 s puts you 5 px out. Screenshots gallery/p11/b4.41_*. Then (D124, the user): a bite sends up hearts half the time; with no ore on the ledger, a "?". Then (D125, the user): the ledger is ore, loot, fruit, a gap, then the bot's and the bugs' levels; fruit a pixel. Then (D126, the user): the bot row counts you plus the flower bots at work. Then (D127, the user): a light worm with nothing to light bursts into rainbow and a pink resource; ledger rows show only once earned, the first time with a shake and 8 streams of their colour. Screenshots gallery/p11/b4.45_*. Then (D128, the user): scans no longer scare wild bugs. Then (D129, the user): pinch zoom; zoom levels in CSS px (a phone zooms as far in as a desktop); touch screens 1.5× brighter (view.bright). Screenshots gallery/p11/b4.47_*. Then (D130, the user): seen loot triple-pings a white halo, a frame on and a frame off, once every 30 s. Then (D131, the user): a just-tamed bug starts its first trip near you. Then (D132, the user): the ledger counts built nodes below ore, with a small bulb icon. Then (D133, the user): tamed bugs head for back wall that isn't green yet, looking 8 px along each way. Then (D134, the user): a bulb ignores picks for its first 50 ms and lets you go after 1.5 s. Then (D135, the user): bulbs within the light's radius are drawn bright and bigger. Then (D136, the user): lizards spawn on ash, lick ash within 6 px bare, and burrow into 5 loot. Then (D137, the user): lizards dash off the wall for ash in the middle of a cave, then run straight back. Then (D138, the user): loot upgrades the lizards' reach; the bug level grows your light, mining radius and speed. Then (D139, the user): lizards lick 3× slower, zip on after every rest, and live ~40 s (5× longer). Then (D140, the user): tamed bugs pull 2× slower. Then (D141, the user): mega beasts join at 16, 32, 64… built nodes; every 5 min each tunnels in (a shadow, a tremor), eats a bulb near you and its roots, and 24 drops run down into lasting pools. Screenshots gallery/p11/b4.59_*. Then (D142, the user): worms tunnel through rock towards fruit. Then (D143, the user): the mega beast's shadow is pixel art and bigger: a 96 px body, head 12 px, darkened world pixels that crawl, with a dusty rim. Screenshots gallery/p11/b4.61_*. Then (D144, the user): the game saves itself (localStorage, per build, seed and map knobs) and comes back on the next visit; the dev panel's "new game" starts over. Screenshot gallery/p11/b4.62_after_reload.png. Then (D145, the user): every 4 built nodes add a tamed bug, on top of the nibbling; loot no longer tames. Then (D146, the user): loot is called crystals in b4's code and docs. Then (D147, the user): no cover within a tamed bug's 3×3 catches fire. Then (D148, the user): worms glide between pixels like the bot, not a pixel jump a step (view only). Then (D149, the user): the beasts' pools evaporate from the top, 8 particles a drop, each to its climate station (every node) in the same cave; the stations' gas counts are saved and drawn as pale clouds round the nodes. Screenshot gallery/p11/b4.66_gas_b.png. Then (D150, the user): a station holds 8; over that it passes half its surplus on, a hop towards the nearest station with room in its cave, so the gas fills the cave out from the pool and settles in seconds; a full cave evens out. Screenshot gallery/p11/b4.67_spread_b.png. Then (D151, the user): a tamed bug with fire within 6 px stops moving until it's out. Then (D152, the user): moss costs gas: a tamed bug greens a back-wall pixel only while that pixel's station holds gas, one gas a pixel (gas.perMoss). Then (D153, the user): bugs are wall-bouncers (bounce.js): they crawl along the rock and jump in random low-gravity arcs; tamed ones stay to mine, send each unit to the ledger at once, and fade after 30 s with none to come back at a node; wild ones wander the same way. One nibble tames a wild bug. Then (D154, the user): a tamed bug that meets gas turns into a moth, circling through open air (moss where it flies), still sending units at once and fading after 30 s; jumpers are drawn paler, moths amber. Then (D155, the user): pink predators hang from the ceiling where bugs crowd (one per 4 built nodes at most), eat the bugs that touch them (tamed ones for good) and leave 3 ore in the rock per bug, 5 times, then withdraw. Then (D156–D159, the user): predators haul the catch up into the rock and come down again slowly, only the pink tip glows; bugs no longer pick fruit and come back at nodes with gas first; liquid makes 5× the gas; hives grow by ore and hatch 3 moths each, and moths hover while they harvest. Then (D160, the user): hives look for a site twice as often (every 30 s). Then (D161, the user): no hives after all; every 30 s each built node with gas hatches a moth. Then (D162, the user): beasts eat a bulb 30–100 px from you with no or very little moss round it, not one by you. Then (D163, the user): slime films the rock surface where there's gas, free; tamed bugs tap it for gas, lichen replaces it, fire leaves it: a meal's gas now lasts while bugs visit. Then (D192, the user, 2026-10-04, refrozen as b4.77): a gas node hatches its one moth only while fewer than 2 moths are within 32 px of it (swarm.mothMax), against the runaway. Then (the user, 2026-10-04, b4.77 again): a small reset button bottom right: "reset", then a red "SURE??" that wipes the save and starts the sim over (back to "reset" after 3 s); the panel's "new game" does the same. Then (the user, 2026-10-04, b4.77 again): a "stuck" button next to it, asking the same way: the bot goes home into the pod node's bulb (Claude's call: the pod, the one place that's always open), then 180 s of cooldown (stuckTicks), counted down on the greyed-out button.

Feedback

  • b4.1 (user, 2026-09-27, feedback/2026-09-27_lorinc_b4.1.md): wants v5's terrain gen and scale, p10's network C, v6's ice sheet, and b3.7's bugs, ore, hard/soft rock and inventory; problems: travel nodes should show only within 3 tiles, building only extends the existing network, the spider is too fast (the rails have no purpose), not enough ore on the map. The plan for b4.2: next-b4.2.md (build next session).
  • b4.2 (user, 2026-09-27, feedback/2026-09-27_lorinc_b4.2.md): the light far too big and lighting 4 px into rock; wants line of sight; then the incremental turn: one ledger, abstract tamed bugs, a simpler build, a fixed light. The plan: next-b4.3.md; built as b4.3 (D083).
  • b4.77 (user, 2026-09-28, feedback/2026-09-28_lorinc_b4.77.md): the ecosystem idle game works and can be made resilient (push it out of balance for a reward, it restores itself); left running, b4.77 ran away (3,000+ moths). A young player: "Where do I go? Why is this following me? I'm lost! What just happened?" The user: the simulation felt flat, "like an open world game that looks the same everywhere you go".

Conclusion → next

The Question (does a scan-mine-build rail loop pull you into the next cavern?) was overtaken by the incremental turn (b4.3) and then by the ecosystem (b4.10 onwards: moss, vines, fire, ash, lizards, worms, beasts, gas, moths, predators, slime). What p11 found instead, in the user's words: "It is possible to build a very enjoyable and engaging cave ecosystem idle game, that both feels very involved, but at the same time, does not really need the player to run. It is possible to engineer it to make time spent rewarding - e.g. taming a lot of moths and pushing the game out of balance temporarily for a big fat resource reward, but the system can be designed to be resilient, and restore balance after the push."

And, the user: "This kind of game, this kind of complexity CAN be made fun with no menus, no instructions, and VERY simple swipe controls."

Found on the way:

  • Stability needs rules, not hope: b4.77 left running ran away (3,000+ moths): free hatching wherever gas is, slime keeping the gas forever, no carrying capacity. How an architecture keeps a big sim fast and bounded, and a scenario engine that searches knobs for goals: guides/engineering/ideal_sw_architecture.md.
  • It isn't a game yet. A young player: "Where do I go? Why is this following me? I'm lost! What just happened?" The user: the simulation felt flat, "like an open world game that looks the same everywhere you go".

Next (user): how to turn this into a game. Settled the same day (D164): an intelligent idle game, "an intelligent, complex, systematically beautiful cookie clicker": endless, biomes restored one by one open others, transition zones between restored pairs, levers beyond building and taming, unlocks that explain themselves, level-ups as understood points of no return; Callisto stays; a 6-year-old is the complexity floor. Full text in concepts/callisto_design.md.

Since then (2026-10-02): before more is built, the shape of the game around the simulation is being matched to an audience. The simulation is kept as the toy; 29 candidate shapes were collected and placed on Quantic Foundry's map of gaming motivations. Nothing is decided yet. See the map of the shapes and the shape exploration it belongs to.

Feedback · 2026-09-27_lorinc_b4.1

"There are MANY things we got to discuss."

I want:

  • the terrain gen and scale of v5
  • the node network type C of p10
  • the ice sheet above from v6
  • the bugs from b3.7
  • the ore density and distribution of b3.7
  • the hard rock / soft rock gen of b3.7
  • the inventory of b3.7

And problems in this release:

  • only show travel nodes within 3 tiles
  • only allow extending the existing network
  • spider moves too fast, no purpose of rail this way
  • there was not enough ore on the map to build the nodes

"Collect info, discuss, write the plan, but execute only in the next session."

Feedback · 2026-09-27_lorinc_b4.2

"Scaling problems in the build: torchlight is waaay too big, cut in half. Also, it reveals the inside of the rock at 4 depth, it should not. Is dynamic lighting (really only reveal what's possible to see from a given point) very expensive? It would add a lot of atmosphere. Tamed bugs should not get into the inventory, but act autonomously: pull ore from walls, send it to the nearest connected node, and ore should travel to the landing pod. Do not implement here and now, just consider gaps, problems, then plan it."

Answers to the plan's questions:

  1. Pull reach tied to the light: "y, I'm mining far too far".
  2. Where a tamed bug works: "b, and it keeps doing it".
  3. Bug to node: "b, and nodes sitting in rock is not okay. Are nodes created at WFC? If yes, make sure they are never inside wall. If not, or this is a complex fix, just make a r3 open space around each node."
  4. What the pod's ore is for: "yes... so, the backpack should dump everything into the nearest node, the same way bugs do it, and building costs are deducted from a central ore ledger."

Second answers (the incremental direction):

  • "Thank you for the node-in-rock proposal, I like it so much that I'd like to drop the fallback plan. The fallback plan is to try to make it work, even if it does not at first."
  • "Ledger: ALL kinds of collectible resources go to the central ledger and are listed in a column in the top-right corner: ore, loot, bugs. I want you to cheat with bugs, no pathfinding. They are a central ledger, they just spawn near a network node, fly around, collect resources. No pathfinding, just random walk. There will be a lot of them (this is an incremental / idle-ish game)."
  • "Building: no need to complicate. If there's not enough material, building fails with a red pulse; if building succeeds, ore particles stream from the ore ledger icons to the building site."
  • "Also, the node building system got overcomplicated. Tap on node, drag to select, release, selected edge flashes green, tap on it, builds."
  • "Bugs: tamed bugs become 'abstract'. They are on the central ledger now, can spawn anywhere near the network nodes, random walk for n minutes, then send the loot straight to the ledger symbols on the top right, not on the nodes!! This is not a deep simulation, but an incremental game with simulation aesthetics and aspects."
  • "Light: no need to grow radius. Again, this is an incremental game, it will grow by buying light upgrades."
  • "Loot: yes, keep it on ledger, it will be for tech unlocks."

The last two questions (2026-09-27, 17th session):

  • Your own mining: "Straight to the ledger, no bot > ledger particle stream".
  • How a bug gets onto the ledger: "Tame wild bugs, 16 ore".

After b4.9 (2026-09-28): "Tame bugs should have an effect on the cave back wall, turning it dark green. Where the wall is green, a green vine starts to grow on it. That vine makes a red fruit: 12 px of vine makes 1 red fruit every minute. This red fruit is a resource, to be collected by bot and bug, the same way as the rest of the resources."

Feedback · 2026-09-28_lorinc_b4.77

"It is possible to build a very enjoyable and engaging cave ecosystem idle game that both feels very involved and, at the same time, does not really need the player to run. It is possible to engineer it to make time spent rewarding (e.g. taming a lot of moths and pushing the game out of balance temporarily for a big fat resource reward), but the system can be designed to be resilient, and restore balance after the push."

And: "This kind of game, this kind of complexity CAN be made fun with no menus, no instructions, and VERY simple swipe controls."

Left running, b4.77 ran away: 3,000+ moths. Notes on an architecture that stays fast and bounded: guides/engineering/ideal_sw_architecture.md.

A young player (the user's daughter)

"Where do I go? Why is this following me? I'm lost! What just happened?"

The user: "these are valid player reactions, especially in a prototype with no tutorial or any kind of narrative or explanation. But this needs to become a game somehow, and the simulation itself felt… flat. Like an open world game that looks the same everywhere you go."

p10

Rails (v8)

buildingbudget 1 daysgrew out of p9 · Lattice (v7)

Do straight rails on a relaxed grid look good over the caves, and do they run mostly through open air rather than boring rock?

▶ live v8latest, unfrozen

→ open

Full entry

Question

Do straight rails on a relaxed grid look good over the caves, and do they run mostly through open air rather than boring rock?

Pass: the user finds one of the two ways (A or B) good-looking on most seeds, with a small share of rail length through rock.

Kill: both look like a net thrown over the caves, or most of the rail bores rock. Then the nodes and corridors move into the WFC (the caves grow around the rails).

Assumptions

  1. [?] The caves' own relaxed grid is too fine for rails (edges ~0.9 cells), so A takes chords between its vertices and B a coarse relaxed grid of its own.
  2. [?] Nodes in the most open places (A) bore less rock than a grid that ignores the caves (B).

Limitations

  • [cut] No buildables, no routing, no choosing: only the candidate rails and their nodes.
  • [cut] How the rail hangs (ceiling, pylons, free) isn't decided; rails are drawn as lines.
  • [cut] Only the ice layer.

Built

v8.html + src/bundles/v8/{rails,main}.js, reusing p8's pod and p9's terrain painter.

  • A · chords between cave-grid vertices: the caves' relaxed-grid vertices in open air, the farthest from rock first, kept spacing apart (8 cells), joined by a relative neighbourhood graph (a and b are joined unless some c is closer to both): straight rails at any angle, no crossings.
  • B · coarse relaxed grid: a triangle lattice of cols triangles across (5), wrapping with the map, then p7's own steps: paired into quads, subdivided, relaxed (20 rounds). Vertices are nodes, edges rails. The caves' own grid is ~0.9 cells an edge after relaxing, so it can't be used directly.
  • A rail is white through open air and red where it would bore rock; a toggle drops rails steeper than 45° (nothing vertical, D068).
  • Measured, seed 5512: A: 27 nodes, 38 rails, median 8.8 cells, 34% of rail length bores rock, 16 steeper than 45°. B: 78 nodes (34 in open air), 142 rails, median 5.5 cells, 49% bores rock, 83 steeper than 45°. Screenshots: gallery/p9/v8_A.png, v8_B.png.

Then (user, on A): "This is ideal density for the travel nodes, and I also like the cavern-central placements" (at 4 cells apart). "Can you connect nodes with similar density and placement … with these constraints? Rails use only the 8 angles, can be made of multiple segments, and digging has a 50% penalty."

  • C · A routed in 8 directions: A's nodes (snapped to tiles) and A's pairs, each routed on the tile grid by Dijkstra over (tile, heading): a step costs its length (√2 diagonal), ×1.5 in rock (knob); a 45° bend costs 3 tiles, a 90° bend 6 (knob); sharper bends aren't allowed; sky and sea can't be crossed. The 45° toggle forbids upright steps.
  • Measured, 4 cells apart: seed 69866: 90 nodes, 126 rails, 28% of rail length bores rock (A: 30%), 87 bends (0.7 a rail), routes 1.05× the straight line. Seed 5512: 89 nodes, 134 rails, 28% bores rock, 96 bends. Rails often share stretches where routes run together.
  • Fixed: B's relax knob was renamed rrelax; it shared its name with the caves' relax in the URL, so a shared link rebuilt the caves with B's 20 rounds instead of 150.

Then (user): "The map misrepresents the tunnelling needs" (screenshot of seed 69866 in C). Each tile was classed by its centre pixel alone, and each step coloured by the tile it entered: 100 of 553 steps showed the wrong colour for the rock actually under the line (52 bored rock drawn white, 48 open air drawn red). Now each step's rock is sampled along its line, pixel by pixel, and that one measure drives the route's cost, the colour and the numbers; every rail (A, B, C) is drawn that way. The totals barely moved (the errors roughly cancelled): seed 69866 C 28% bores rock, seed 5512 C 27%.

Then (user): "I like this node density" (3 cells apart; rock ×5, bend 15), "but I need more edge density, AND I'd like to add a 100% penalty for overlapping edges."

  • Edge density (links, 0 to 1): the lune β-skeleton, β = 2 − links: 0 is the relative neighbourhood graph as before, 1 the Gabriel graph; edges never cross. Tried first: a scaled RNG test, far too steep (220 → 372 → 928 rails at 1, 1.3, 1.6, 90% of track shared).
  • Overlap penalty (overlap, +100%): routes are laid shortest first; a step onto a tile an earlier rail uses costs 2× (nodes' tiles are free, rails meet there). A new number: the share of track shared.
  • Measured, seed 69866, 3 cells apart, rock ×5, bend 15: 150 nodes; links 0 → 220 rails, 0.5 → 283, 1 → 366. At links 1 the penalty takes shared track from 17% to 10%; 28% bores rock either way.
  • Seen (Claude): the straight edges never cross, but their 8-direction routes sometimes do.
  • New defaults: nodes 3 cells apart, links 1, overlap 1.

Then (user): "There's a difference between overlap and paths crossing. Crossing paths should have a MASSIVE penalty, so that one single cross overweights paths running on the same path for a while."

  • Overlap is now a step along an earlier rail's step (+100%). A crossing is a step into an earlier rail's tile off its line (which also covers a junction that isn't a node), or a diagonal step cutting an earlier diagonal between the same four tiles: a flat cross penalty, 100 tiles by default.
  • Measured (3 cells apart, links 1, rock ×5, bend 15): crossings at penalty 0 / 40 / 100: seed 69866 18 / 4 / 0, seed 5512 14 / 3 / 0; shared track ~9–10%, routes 1.05–1.06× the straight line.

Feedback

Conclusion → next

p9

Lattice (v7)

buildingbudget 1 daysgrew out of p8 · Storeys (v6)

Is the candidate lattice dense enough to offer real choices everywhere, while each build clears its neighbourhood enough that what's left stays readable?

▶ live v7latest, unfrozen

→ open

Full entry

Question

Is the candidate lattice dense enough to offer real choices everywhere, while each build clears its neighbourhood enough that what's left stays readable?

Pass: clicking through a few builds on a seed, the user can always find a link or a wall where they want one, and after each build the candidates left around it still make sense (no parallels, no X crossings, no airlock clusters).

Kill: the lattice is either a blur (too many candidates to read) or collapses to nothing after a few builds. Then the candidate set needs a coarser skeleton (fewer, pre-merged candidates) first.

Assumptions

  1. [?] p8's candidate links (cheapest per pair of floors, direction and 4-cell stretch) are the right density for choosing from.
  2. [?] p8's clash rule (D073: a crossing, or running parallel within a storey for over 30% of the middle) works as the collapse rule: a candidate dies when it clashes with the floors or a build.
  3. [?] Walls at waists (locally narrowest rock-to-rock crossings of open air, 4 directions) are the useful wall candidates.
  4. [?] Airlocks placed automatically where walls cross paths, kept apart by a minimum gap, don't need their own candidates.

Limitations

  • [cut] No character, no walking: builds are clicks on the map. Later.
  • [cut] Only the ice layer, as in p8.
  • [cut] Walls don't change the terrain or the floors: they're drawn over it, and they don't create new floor.
  • [cut] A desktop tool page, not a phone layout.

Built

Built in one session (D074). v7.html shows p8's ice layer (p7's settled caves, p8's pod and floors) with every candidate drawn thin over it; builds are thick. Click a candidate to build it, click a build to revert it; hovering shows in cyan what the click would collapse (or bring back). The URL carries the seed, every knob and the builds (b=), so a state can be shared. New in src/bundles/v7/: lattice.js (candidates and collapse), paint.js, main.js; p8's pod code is imported (carvePod is now exported from v6).

  • The user on the page (before building): no v6 toggle ("I can see what a good layout looks like"); "airlocks are just plank-behaviour blocks (can pass through, can stand on it), automatically placed where walls and paths intersect. Just like parallel paths, airlocks are also discouraged to be in close proximity"; the map size is right, but bigger pixels and more contrast: rock keeps its colours, open air is darker.
  • Picture: the map fits the window's width (zoom − / + buttons), cropped to the crust and the ice. Open air is near black (4, 4, 7, was 21, 21, 24) with no outlines; the drawn ice sheet is gone (only a strip of sky). The lattice is drawn as lines at screen resolution on a second canvas.
  • Candidate links are p8's, unchanged: cutoffs (short, end to end), sideways links from a floor's end, 45° ramps from every half cell of floor (carrying on sideways), the cheapest per pair of floors, direction and 4-cell stretch.
  • Candidate walls: straight rock-to-rock crossings of open air (level, upright, both 45°), up to 6 cells (knob), at waists (open a cell away on both sides, nothing narrower the same way within 2 cells), the shortest first, 3 cells apart (knob); none lying along a floor, none in the pod.
  • Airlocks (user): wherever a built wall crosses a path (a floor or a built link), one per crossing, a cell-sized block.
  • Collapse (all recomputed from the build list, so a revert is exact): a link dies if it crosses a built link or runs within a storey of a path going the same way for over 30% of its middle (knob) (p8's D073 rule, with the natural floors counting as paths from the start); a link or wall dies if it would place an airlock within 5 cells (knob) of another; a wall dies within a cell of a built wall.
  • Measured, seed 5512: 50 cutoffs, 68 sideways links, 391 ramps and 77 walls; the floors alone collapse 32 sideways links and 219 ramps, leaving 50 / 36 / 172 / 77. A build near the pod collapses 0 to 13 candidates. The lattice takes ~150 ms, a collapse ~10 ms.
  • Seen (Claude): where rock is thick, the ramps that carry on sideways stack up as bundles of near-parallel tunnels a pixel or two apart (the cheapest per 4-cell stretch keeps one per stretch, and neighbouring stretches give near-copies). Clicking one collapses the bundle, but before that it reads as a blur. Screenshots: gallery/p9/v7_seed5512*.png.

Feedback

Conclusion → next

p8

Storeys (v6)

buildingbudget 1 daysgrew out of p7 · Hex Caves (v5)

Does a storey pass over the settled quad caves give a lattice that mostly runs on natural cavern floor, reads as clean storeys, and needs few bridges and tunnels?

▶ live v6latest, unfrozen

→ open

Full entry · 1 feedback session

Question

Does a storey pass over the settled quad caves give a lattice that mostly runs on natural cavern floor, reads as clean storeys, and needs few bridges and tunnels?

Pass: on most seeds the storeys look like a building's floors laid into the caves (the user's eye); most of the storey length is natural floor; the pod always finds a place near the centre.

Kill: the storeys zigzag, pile up or bury themselves in rock whatever the knobs. Then the caves need a floor skeleton before the WFC (pinned storey floors), not a pass after it.

Assumptions

  1. [?] The ½-storey follow rule keeps storeys on natural floor most of the way, with 3-cell storeys.
  2. [?] One ramp per storey pair, near where the storey above started, is enough to reach the whole ice layer.
  3. [?] Every seed has natural floor for the pod (10 cells wide, level within a cell) near the centre, under the crust.
  4. [?] Merging storeys closer than ½ storey keeps the picture clean (no near-parallel lines).
  5. [?] The pass is cheap: well under 50 ms a map on top of the WFC.

Limitations

  • [cut] No character, walking, building, walls, airlocks or candidates: only the storeys. Later.
  • [cut] Only the ice layer. The pudding and brine come when the storeys hold up.
  • [cut] Catwalks for prospecting (the highest storey under a ceiling) aren't placed yet.
  • [constraint ?] Storeys follow floors column by column with a 45° smoothing pass, not cavern by cavern: is that the user's "the Y it had one cavern before"?
  • [cut] A desktop tool page, not a phone layout.

Built

Built in one session (D069). v6.html shows one seed's ice layer, zoomed to fit the window, under a drawn, rugged ice sheet (scenery for the 90 m, no caves in it), with the pod, the storeys, the ramps and the divergence points; toggles for storeys, points and the walkable floor; sliders for the storey knobs; stats under the map. The caves are p7's settled quad WFC with QKNOBS, imported from src/bundles/v5/ unchanged; the URL carries the cave knobs too, so p7's links (seed 24474) open here. New modules in src/bundles/v6/: terrain.js (the quad map as a raster, 4 px a cell), storeys.js (floors, pod, storeys, ramps, points), paint.js. node tools/storeys.js [seed] [n] writes 4 stages for 4 seeds to gallery/p8/ and checks n seeds: a pod on each, every storey 45° at most across the wrap, the same seed twice gives the same storeys. All pass.

  • Walkable floor: an open pixel with rock under it and 2 cells of headroom (knob). Floor runs join neighbouring columns at most 1 px apart (45°); runs under 2 cells (knob) aren't followed.
  • A storey, column by column from its start, both ways round the wrap: the same floor if it carries on; else the nearest floor within ½ storey (knob) of the current Y; else hold the Y. Then a 45° pass lifts the lower side of every jump into a slope. Each column is named by what's there: floor, bridge (air under it) or tunnel (rock, or a ceiling under 2 cells).
  • Ramps: 45° down, a storey ± ½ storey long, within 15 cells (knob) of the storey's start, where the foot lands on real floor (then: shortest, least rock, nearest). The foot starts the next storey. It stops when a foot falls below the ice layer.
  • Merging: a column closer than ½ storey to the storey above (or above it) is merged: not drawn, not counted.
  • Divergence points: ramp heads and feet, and floor ↔ bridge/tunnel changes (runs under a cell ignored).
  • Storey height 3 cells (user: "6 cells is too much expectation. 3 cells is enough").
  • The pod (user): a dome 8 + 2 cells wide and 4 + 1 high, cut into the ceiling; a flat slab under it, a 2-cell door in each side wall. Its spot: on natural floor, in the ice, with a cell of ice over the dome; the central sixth of the width first (the shallowest spot there), then a third, then half; its width on floor if possible, then 80%, 60%, then the best-supported spot anywhere. It may sink into the floor (user: "cavern floor is not expected to be THAT flat and level"): a column counts as supported if floor lies up to 2 cells above the base or a cell below it.
    • Changed while building: "shallowest first, then outward" put pods 16 cells off the centre, so the central window comes first (Claude's call). Over 100 seeds: a pod on every seed, all within 10 cells of the centre (median 4), 80 fully on floor; depth under the crust median 11.5 cells, worst 34.5.
  • Measured, 300 seeds, default knobs: 6.7 storeys a map; storey length 26% on floor, 36% bridge, 38% tunnel; the pass takes 11 ms median, 16 ms p90 in Node (the WFC ~270 ms in the browser, the raster ~25 ms).
  • Seen: with 3-cell storeys the ice's caves are taller than a storey, so storeys cross most caves in mid-air and hit the thin walls of the maze-like ice: floors more than 1.5 cells off a storey's Y go unused. Chained follows let a storey drift over the map (seed 1: storey 1 climbs about 2 storeys from the pod to the map's edges). Screenshots: gallery/p8/v6_page_seed1.png, stages gallery/p8/v6_seeds1-4_*.png.

Then (user, after seed 5512): "Extend the network to above the pod as well, not just below. In early game, the player wants to manually collect a lot of materials, not picking up, what's above our head does not make any sense." A second chain now grows up from the pod's storey the same way (ramps up, near where the last storey started), until a ramp's foot has no headroom under the crust; an upper storey dips under the crust at 45° where it would break through (D070).

  • Dead ends were a bug (user: "is this a bug, or there's logic behind it?"): a storey merging into the one it came from simply stopped, up to 1.5 cells short of it. Now it takes that storey's line where merged and climbs or drops into it at 45°; the join is a divergence point. The crust clip made fragments too, until it became a dip. tools/storeys.js checks for dead ends: none on 300 seeds.
  • Measured, 300 seeds: 11.2 storeys a map; 23% floor, 37% bridge, 40% tunnel; 16 ms median, 45 ms p90.

Then the rework: floors first, links second (D071). The user on seed 5512: "1. there's no way to path towards SW from the pod without unreasonable detour; 2. the div point immediately left from the pod should have a SE ramp, leading to the walkable cave floor right after the gap; 3. that massive accumulation of 7 + additional 9 connected div points … is a mess. That whole area could be 4-5 points in total; 4. there's a large cavern touching the pod from NW, no path goes there, those resources are gone." All four came from drawing map-wide lines first. Now (storeys.js, same file):

  • Nodes are cavern floors (walkable floor pieces). Candidate links: sideways from a piece's end to floor within ½ storey (up to 12 cells, knob), and 45° ramps up or down from any point (every half cell), landing on floor or carrying on sideways to the first floor within the span (up to 2 storeys, knob). Cost: length, with rock at 2× (knob).
  • Cutoffs first (user's tip, mid-build: "if you consider what tiny cutoffs ramps could connect cave walkable floor parts, and prioritized extending the walkable cavern floors this way, it would increase the ratio by a lot"): links up to 3 cells (knob) join one piece's end to near another's end, so a floor broken by a bump or a step is one floor. Drawn as floor (light green where carved).
  • Then a spanning tree of the cheapest links between floors of 3+ cells (with their cutoffs), from the pod. Then detours: while the walk from the pod to some floor is more than 1.5× the straight line (knob; damped by 5 cells so the pod's neighbours don't count as huge), the link into it that shortens it most is added; a floor no single link fixes is left.
  • Divergence points only at forks (3+ ways) and ends, merged within 2 cells.
  • No more full-width storeys: a storey is as long as the floors it chains (the user OK'd this).
  • Measured, 300 seeds: 98% of floors reached, 41.8 links (of them ~20 cutoffs) and 38 divergence points a map; detour from the pod median 1.59×, the worst floor per map median 2.82× (p90 4.39×): the detour pass often finds no single link that helps. 58 ms median, 86 ms p90. Seed 5512: all 19 floors, 20 cutoffs, 20 ramps, 4 sideways links, 51 points, worst detour 2.0×.
  • Fixed on the way: the pod's own floor couldn't start a link (ramps were blocked in the whole pod area, doors included), and its dome roof counted as floor.

Then the user's meaning of "floor" (D072): "For me, cave floor means 'naturally generated area that can be traversed in one run'… first, connect these, then try to build continuous paths from them." And: "I have no problem with passages that are only 1 cell high"; "often walkable floors are cut by a small drop that can be bridged with very little walkway or removal of a few blocks. In this case, removal is preferred"; "connecting natural walkable paths, so that one swipe covers long distances. Path follows the natural floor, wherever. The only exception is if they run very close to each other - then only one path is needed."

  • Headroom 1 cell. Cutoffs are chosen by their own cost, where a pixel of walkway costs 2 of removed rock, so a drop gets cut through its lip rather than bridged. A floor piece within ½ storey of a longer one for 70% of its length is left out.
  • Divergence points only at forks now (a floor's end is a stop, not a choice), with stubs under a cell not counted as a way.
  • Tried and reverted: turning down detour links that run alongside the network. Parallel links went down a little, but the worst detour rose (seed 5512: 2.2× → 4.8×) and the pass took twice as long.
  • Measured, 300 seeds: 100% of floors reached; 81.6 links a map (about half of them cutoffs) and 28 divergence points; detour median 1.63×, worst per map median 2.76× (p90 3.81×); 58 ms median.

Then (user): "Seed 5512 div point immediately left of the pod - why branch, then run in parallel? Wasteful and loses on simplicity. Branch only when needed to, not before. Seed 5513: pathways crossing each other in X-shape? What's the benefit of that? Pathways running in parallel 2 and 3 blocks from each other? Apart from these two kinds of problems - this is the best yet." (D073)

  • A built link is refused if it crosses a chosen link (it should join it instead), or if over 30% of its middle (its first and last ½ storey don't count) runs within a storey of floor or a chosen link going the same way (slopes within 0.5). That holds in the spanning tree and the detour pass; floors that only clashing links can reach get their cheapest link anyway.
  • The first try counted any floor within a storey, in any direction: clean, but in this maze there's floor every few cells, so nearly every detour ramp was refused (detour median 2.63×, worst 6.2×). Counting only paths running the same way brought part of it back.
  • Measured, 300 seeds: 100% of floors reached; 75 links and 21 divergence points a map (from 82 and 28); detour median 2.09× (from 1.63×), worst floor per map median 4.6×; 113 ms median. The price of simplicity is longer walks.

Feedback

  • 2026-09-27 · v6: "I find these paths fairly good. Sometimes a round tour means more resources collected... keep this for now."

Conclusion → next

Feedback · 2026-09-27_lorinc_v6

  • Build: live dev v6.html (2819b45 storey lines, then the rework up to 8fb9329)
  • Source: chat after looking at the page; the quotes are Lorinc's words with minimal spelling and grammar fixes.

Quotes

On the storey lines (seed 5512):

Extend the network to above the pod as well, not just below. In early game, the player wants to manually collect a lot of materials, not picking up, what's above our head does not make any sense.

  1. There's no way to path towards SW from the pod without unreasonable detour. 2. The div point

immediately left from the pod should have a SE ramp, leading to the walkable cave floor right after the gap. 3. That massive accumulation of 7 + additional 9 connected div points … is a mess. That whole area could be 4-5 points in total. 4. There's a large cavern touching the pod from NW, no path goes there, those resources are gone.

On what a floor is:

For me, cave floor means "naturally generated area that can be traversed in one run". For me, these are equally valuable surfaces than actual vertical floors. And I meant to say: first, connect these, then try to build continuous paths from them.

I have no problem with passages that are only 1 cell high - the char fits, so it's distance covered with one swipe. Often walkable floors are cut by a small drop that can be bridged with very little walkway or removal of a few blocks. In this case, removal is preferred.

On branching (seeds 5512, 5513):

Why branch, then run in parallel? Wasteful and loses on simplicity. Branch only when needed to, not before. … Pathways crossing each other in X-shape? What's the benefit of that? Pathways running in parallel 2 and 3 blocks from each other? Apart from these two kinds of problems - this is the best yet.

On the result:

I find these paths fairly good. Sometimes a round tour means more resources collected... keep this for now.

On the goal of the exercise:

So, we have been iterating on v6.html, it looks promising… but I'm not sure about the goal of this exercise. What we want to build is a dense network of potential pathways (and walls), that the user can choose from. What I see in these simulations is the network + what making good choices would build for the player.

What changed because of it

  • Decisions: D070 (storeys up from the pod; dead ends were a bug), D071 (floors first, links second, with cutoffs), D072 (floor = natural one-run stretch, 1-cell headroom, removal preferred), D073 (branch only when needed).
  • The next prototype, p9 (v7), draws the candidate lattice and its collapse instead (D074).
  • Kept as it is (user): walks about 2× the straight line are fine; a round tour can collect more.
p7

Hex Caves (v5)

buildingbudget 1 daysgrew out of p6 · Tamed Bugs (b3)

Can a hex WFC with code-generated tiles and Markov-weighted pairing produce layered, organic-looking, horizontally tiling caves, with no visible grid and few contradictions?

▶ live v5latest, unfrozen

→ The user: "Let's go with this one" (2026-09-27): the quad WFC on the relaxed Townscaper-style grid, with the defaults as they are now (seed 12227's setting, flat floors and flat ceilings 1.75). The hex WFC answered the Question with a partial fail (it works, fast and seamless, but the grid shows); the quad WFC passes the user's eye ("looks like real caves, not game design"; "great for gameplay"). The layer roles aren't judged yet, and the cave/tunnel skeleton wasn't needed for now: the user got rooms and thin walls from the knobs.

Full entry · 1 feedback session

Question

Can a hex WFC with code-generated tiles and Markov-weighted pairing produce layered, organic-looking, horizontally tiling caves, with no visible grid and few contradictions?

Pass: four random seeds side by side look like caves and corridors (the user's eye), not noise and not a hex grid; ice, pudding and brine read as layers with natural transitions; the left and right edges join seamlessly; restarts are rare; a map generates in well under a second.

Kill: whatever the knobs, the output reads as tiles or as noise, or contradictions dominate. Then drop WFC for terrain and go back to CA caves with a lattice fitted afterwards.

Assumptions

  1. [?] Tiles generated by code from a few shape families give enough variety, with no hand-drawn tiles.
  2. [?] Markov-weighted pairing makes structures continue (corridors run on, caves cluster), so the result reads as caves, not noise.
  3. [?] Snapping each tile's edge band to its sockets, with noise only inside, hides the hex grid and still joins every edge seamlessly.
  4. [?] Layers emerge from depth-dependent weights and materials in one pass, with natural transitions.
  5. [?] Contradictions are rare enough that restarting is fine (a few restarts per map at most).
  6. [?] A 16 × 32 map generates in under 100 ms in Node.

Limitations

  • [cut] The lattice: candidate tunnels, bridges and walls left uncollapsed. Next prototype.
  • [cut] No character, traversal, building, ecology, bubbles, relics or light. Later prototypes.
  • [cut] Reachability isn't enforced, only measured (cavity statistics per map). Enforcing it comes with the lattice.
  • [constraint ?] Graphics are deliberately crude ("a 6-year-old in MS Paint", user): flat colours, black outlines. Is that enough to judge the shapes?
  • [cut] A desktop tool page, not a phone layout.

Built

Built per spec.md in one session (D066). v5.html shows seeds s … s+3 side by side, with view toggles (painted, classes, hex grid, sockets), the knob sliders and stats under each map. The pure modules are in src/bundles/v5/ (hex.js, tiles.js, wfc.js, raster.js, plus paint.js, which paints pixels for both the page and the gallery script). node tools/hexcaves.js [seed] writes the 5 stages for 4 seeds to gallery/p7/ and checks that every pair of neighbours matches on all 3 sockets (across the wrap too) and that the same seed gives the same map twice. Both checks pass.

  • Tiles: 486 (1 solid, 1 open, 36 walls, 117 passages, 330 junctions, 1 pocket).
  • Measured, 100 seeds with the default knobs, in Node: restarts median 2, p90 8, max 21, no failures; time median 70 ms, p90 176 ms, max 393 ms. So assumption 6 (under 100 ms) holds for the median but not for the tail: the restarts cost it. The browser shows about the same (25–180 ms).
  • What changed from the spec's defaults while building (it fought the build):
    • At first open space flooded every map (60–90 % open). The single "open" tile beat the few walls that fit at a cave's edge. So now each class keeps its whole base weight among the tiles still in the domain: a cave's edge is a fair choice between "open" and the fitting walls.
    • New knob "rock grows" (solid next to solid, and next to corridors), symmetric to "caves grow". The layer openness knobs now weigh solid against open only, not walls and passages.
    • Noise is stronger than the spec's ~1 cell: about 2 cells, knots every 8 and 4 cells. The straight tile lines needed the bend.
    • A pocket stays a tile of its own, though its sockets (all solid) duplicate solid rock.
    • Layer wobble is a knob too (default ±2 rows). A bug fixed on the way: hashSeed barely mixes its last argument, so neighbouring noise knots came out almost equal and the layer borders were flat. wobble/noise now use hash11 (a murmur3 finish).
    • Defaults: open ice 0.3, pudding 0.35, brine 0.3; caves grow 2, rock grows 3; corridor on 4, turn 1.5, branch 0.7; walls straight 3.
  • Seen, not fixed: the ocean rows force every hex above them open at the bottom, so there's always an open band over the ocean. Isolated open or solid hexes still show as hexagons (the socket band snaps their edges straight). Thin passages (about 2 cells wide) come out as squiggles after the noise.
  • Screenshots: gallery/p7/v5_page_*.png; stages: gallery/p7/v5_seeds1-4_{1..5}_*.png.

Then the quad WFC (D067), after the user's verdict on the hex version. A Townscaper-style grid inside the hexes (quads.js, tools/quadgrid.js): 54 triangles per hex, random pairs within a hex, every face subdivided into quads, the whole mesh relaxed as one (58,530 quads). The WFC runs on those small quads (quadwfc.js): a tile is its 4 corners, open or rock; neighbours agree on shared corners; the entropy order is a heap; no contradictions. Painted by marching squares (paintQuads). The page has a quads | hex switch, quads by default. 130–180 ms a map; the grid takes ~1 s once. At one cell per quad clustering needs ~10× the hex weights (QKNOBS: open 0.45 / 0.5 / 0.45, caves grow 30, rock grows 30, walls straight 10), with a tipping point near 0.5 open where rock or open floods the map.

The map at 1/5 (user: "1/5 width and height should be enough for a whole playthrough"). The quad map is now 3 × 6 hexes (30 × 57 cells, about 2,050 quads), with the layers scaled to its depth and a fresh grid per seed (about 30 ms, plus 5–20 ms for the WFC). A quad stays about one cell. The sliders move by one step per mouse-wheel notch, ten with Shift (user). New knob thinnest wall (user: "a slider for how thin walls can get"): rock at a corner with already-open corners on opposite sides (over 120° apart) within that many grid edges (about a cell each) is weighted down 100×, so thin walls break through and the caves join; since every merge adds open space, higher values push towards the open flood.

Then (user): the map doubled each way, to 6 × 12 terrain hexes (60 × 129 cells, about 8,200 quads), plus a sky hex row on top and an ocean row below that relax with the rest. The hex outlines stay zigzags even relaxed, so a corner is sky or ocean by a smooth wavy line near the row border, painted by marching squares: the surface and the shore are natural curves, with a 1-quad rock crust under the sky. The URL carries every knob (k=name:value,…) so a setting can be shared. The quad defaults are now the user's best setting from the 3 × 6 map (seed 6398): open 0.12, caves grow 7.5, rock grows 1, walls straight 6, thinnest wall 0, wobble 0.5.

The user's room setting as defaults (goal: "enough big enough, but separable rooms"; seed 1643): open ice 0.3, pudding 0.365, brine 0.04; caves grow 5, rock grows 2.5, walls straight 1, thinnest wall 1, wobble 0.5. The user: thinnest wall and walls straight had the largest impact, so they got finer steps (walls straight 0.05, thinnest wall 0.1). Thinnest wall is now a straight distance in cells instead of grid steps, so it can take tenths; 1.0 comes closest to the old 1 step (seed 1643: 105 cavities and largest 51% against 112 and 59%).

A knob search (user: "ice layer stats similar to seed 18142 with these last settings, but less volatility", then: search the hidden parameters too). The code's constants became knobs (tile family weights, border-tile affinities, the thin-wall force and angle, relaxation passes), shown as · sliders. tools/knobsearch.js scores a setting on 12 seeds: the ice's open share (3×), rooms (caves of 20+ corners), their mean size, tiny caves and the largest cave's share against seed 18142's, plus their spread across seeds, plus half-weight drift of the pudding and brine; 800 random settings, 400 around the best 8, the finalists verified on 40 fresh seeds (about 7 minutes on 8 cores). Seed 18142 was unusual for the user's setting: on it the ice had 11 rooms of about 75 corners, the largest cave 21% of the open; over 40 seeds the setting averages 5.8 ± 2.4 rooms of 210 ± 128, largest 56 ± 22%. The winner (now the default) gives 12.1 ± 2.3 rooms of 67 ± 16, open 37 ± 4%, largest 22 ± 8%: the ice as on 18142, steady. It turned thinnest wall off and made walls heavy (3.3) and inner corners rare (0.05), so rooms are more faceted. The hidden knobs act on every layer: the pudding got less open (fixed by raising its open to 0.65: 49% against the user's 54%), and the brine's worm tunnels became blocky rooms.

The user's tuning, and flat caves. The user tuned on (seed 36048, then 43344: border next to open 2.1, next to rock 6.8, thinnest wall 0.9, walls straight 1): "variety, but also a lot of space to work with, small caves, bigger ones, almost no impractically massive ones, walls are thin enough for simple tunnels… great for gameplay", then "even better"; that is the default now. Asked for caves "more horizontal, less vertical", two knobs (1 = off, the default): flat caves (like next to like pulls harder sideways than up and down, by flat^cos 2θ of the link) and flat walls (a border tile's border weighs flatWalls^cos 2θ of its direction: floors and ceilings over side walls). Measured as the border's mean levelness (+1 all level, −1 all upright) on seed 43344: 0.06 off, 0.18 at 3/3, 0.23 at 5/5. The user then set flat walls 1.75 (seed 12227), now the default: "this brought back some volatility, but the caves are easier to traverse now, and floor is the most important part of a cave". Then (user: "just the ceiling knob") flat walls split: flat floors (URL name flatWalls, a border with cave above and rock below) and flat ceilings (flatCeil, rock above), both 1.75 by default, so the default maps are unchanged (checked: identical tiles). Over 6 seeds the ceiling knob moves the ceilings' levelness (0.034 at 1, 0.069 at 1.75, 0.091 at 3) and drags the floors with it (0.068, 0.114, 0.134): a ceiling is often the next cave's floor seen from below.

Feedback

  • 2026-09-26 · v5: hex version 6/10, the grid clearly visible (assumption 3 failed); the quad WFC "looks like real caves, not game design". Next: more middle-sized caves connected by tunnels, and a map about 1/5 the width and height.

Conclusion → next

The user: "Let's go with this one" (2026-09-27): the quad WFC on the relaxed Townscaper-style grid, with the defaults as they are now (seed 12227's setting, flat floors and flat ceilings 1.75). The hex WFC answered the Question with a partial fail (it works, fast and seamless, but the grid shows); the quad WFC passes the user's eye ("looks like real caves, not game design"; "great for gameplay"). The layer roles aren't judged yet, and the cave/tunnel skeleton wasn't needed for now: the user got rooms and thin walls from the knobs.

A second setting to keep (user): "I also like this layout a LOT, but it means more walling than opening - but this is still a great, interesting, challenging terrain. I will want a test run with this one too for the wall building, when we get there." Seed 24474: ?seed=24474&k=openIce:0.255,openPudding:0.65,openBrine:0.05,grow:15,rock:2.35,straight:0.9,thin:1,wobble:0.5,flat:2.9,flatWalls:3.5,flatCeil:2.35,wallW:7.44,nookW:1.47,innerW:1.61,saddleW:0.001,edgeAff:0.1,openEdge:2.5,rockEdge:6,thinForce:0.15,thinAngle:80,relax:140

Next (user): a new simulator zoomed in on the ice layer, and a talk about the player navigation / cave connection network (the lattice) before building it.

Feedback · 2026-09-26_lorinc_v5

  • Build: live dev v5.html (hex WFC 062db0b, then the quad WFC)
  • Source: chat after looking at the page; the quotes are Lorinc's words with minimal spelling and grammar fixes.

Quotes

On the hex WFC:

I have seen the caves we generated in v5... it's like 6/10. Not horrible, not awesome either.

No, the grid is clearly visible, no amount of wobble fixes that.

Then the user described Oskar Stålberg's Townscaper grid (triangles paired into quads, leftovers cut into 3, everything subdivided, the grid relaxed) and corrected Claude twice: keep the pointy-top hexes as the base with the distorted quad grid inside them, relax the connected big hexes too, and build the WFC in the small 4-corner cells, not on the bounding hexes.

On the quad WFC:

This looks super organic. Honestly, this looks like real caves, not game design. But we will have to work a bit on the Markov weights, because the result has massive solid areas, massive caverns, and around the caverns, some (awesome-organic) small tunnels. What we need is more middle-sized caves, connected by tunnels. Also, this map is massive: like 1/5 width and height should be enough for a whole playthrough.

What changed because of it

  • Assumption 3 failed (snapping hex edges to sockets plus noise doesn't hide the grid).
  • Decisions: D067 (the quad WFC on the relaxed Townscaper-style grid).
p6

Tamed Bugs (b3)

buildingbudget 3 daysgrew out of p5 · Darkness (b2)
Tamed Bugs (b3)

Does taming bugs that mine what you've revealed turn exploring into a loop you want to come back to?

▶ live b3latest, unfrozen▶ b3.72026-09-26 · p6 · b3 Tamed Bugs step 3: shared ore, reserved slots, 8 stone from home, taming progress, bugs back to the bar (D064)▶ b3.62026-09-26 · p6 · b3 Tamed Bugs step 3: placed bugs mine and hand their ore over as you pass, the dust stream (D063), the bug stream holds still▶ b3.52026-09-26 · p6 · b3 Tamed Bugs step 3a: standing still pulls ore and loot, the bar calms the chasers, bar bugs roam (D062), bar bugs fly 2 to 8 off with inertia▶ b3.42026-09-26 · p6 · b3 Tamed Bugs step 2c: wild bugs live in the fog, 1 per 32×32 block, flicker and dark (D061), the wild light fades out▶ b3.32026-09-26 · p6 · b3 Tamed Bugs step 2b: shared taming, the bug bar, the hold places a bug, bug lights (D060)▶ b3.22026-09-26 · p6 · b3 Tamed Bugs step 2: wild bugs drift to you, nibble ore with hearts, tamed at 16 turn warm (D059)▶ b3.12026-09-26 · p6 · b3 Tamed Bugs: the pivot recorded, the probe centred on the probed block, ↑ probes the ceiling, no teleport home (D054–D058)

→ Open.

Full entry · 1 feedback session

Question

Does taming bugs that mine what you've revealed turn exploring into a loop you want to come back to?

Pass: you probe to find ore for your bugs, not for yourself; you swing by your dens to collect; the walk home with a full pack through your own tunnels feels like a triumph.

Kill: the bugs feel like a chore (herding, waiting), or like a tax you can't escape; walking home feels like a punishment for the lost teleport.

Assumptions

  1. [?] Losing wild-bug nibbles from your pack reads as cute, not as punishment: the hearts and the taming at 16 make it an investment.
  2. [?] Tamed bugs mining only what you've revealed makes the probe a tool for your bugs, and gives exploring a purpose.
  3. [?] Collection by running past (no stopping, no menu) is enough of a hand-over.
  4. [?] Walking home without a teleport is a triumph, not a chore, once your own tunnels lead there.
  5. [?] The friendly areas make your territory readable at a glance, and pleasant to come back to.
  6. [?] Ore with no use yet doesn't kill the motivation to collect it, for now.

Limitations

  • [constraint ?] No use for ore or loot, on purpose (D054).
  • [constraint ?] No teleport home.
  • [cut] Save and offline piles at the base: step 5, after this.
  • [cut] Outposts (the 1 s hold) and PvP uses for ore and loot: later.
  • [cut] Noise, the other loadouts, and the "why go home" drill.

Built

Built in steps, one per session (user, 2026-09-25): 0 + 1 · 2 · 3 · 3b + 4.

  1. The b3 bundle, forked from b2.1; this entry; decisions D054–D057.
  2. The probe centred on the probed block; ↑ into rock probes the ceiling; no teleport home (D055, ruleset b3.1).
  3. Wild bugs (D056, D059).

2b. Shared taming, the bug bar, placing bugs with the hold (D060), after playing b3.2. 2c. Wild bugs live in the fog (D061), after playing b3.3.

  1. Pulling ore and loot while you stand still, the bar calms the chasers, bar bugs roam (D062); then placed bugs mine, with the dust stream (D063).

3a. The TODOs after playing b3.6: shared ore, reserved slots, 8 stone from home, taming progress in the bar, bugs going back to the bar (D064). 3b. The friendly area (D057).

  1. The build check, and b3.1 frozen.

The probe and the walk home (step 1, D055, D058): ruleset b3.1 = b2.1 with ↓ on a floor → probeBelow, ↑ into rock → probeAbove, and teleport: false.

  • The probe: its rings spread from the block under you (↓) or the block above you (↑), with b2.1's reach: light + 2 for a flick, up to light + 4 held. The ceiling isn't mined any more. Ring 1 holds the centre cell too.
  • No teleport: the command does nothing, and a deep fall just lands (stop fell), pack and all.
  • Home: stepping onto the home cell with anything in the pack counts it in and shows the dive log; the pack empties and the light goes back to base.
  • Tests: 3 probe tests and 5 walk-home tests on ASCII maps; b2.1 still probes around you and teleports after a deep fall.

Wild bugs (step 2, D059): ruleset b3.2 = b3.1 + bugs numbers. Wild moon bugs appear in the dark, drift to you through open cells, and nibble ore (never loot) from your pack, with an ore flying into them and a heart popping. The 16th ore tames one where it is, and it turns warm amber (wild ones are cool blue). A probe ring scares them off for 4 s. No wild bug comes within 12 tiles of a tamed one. Tamed bugs just stay at their den for now (step 3 puts them to work). The Claude's calls are listed in D059.

  • Tests: 8 bug tests on ASCII maps (drift, nibble and taming, never loot, the probe's scare, the wander and despawn, where they appear, den areas kept clear, none in b3.1), plus a determinism test with bugs.
  • Screenshots (local, gallery/p6/, not in the repo): a nibble with its heart, a taming, and a tamed bug at its den with wild ones blinking out in the dark.

Shared taming, the bug bar and the hold (step 2b, D060): ruleset b3.3. After playing b3.2, the user redesigned the tamed side: several wild bugs split the nibbles, so none of them got tamed.

  • All wild bugs' bites add up to one count; at 16, the last biter is tamed into the bug bar, b1.1's slot row along the bottom (4 slots).
  • Bar bugs circle you and light 2 around themselves, seen for good.
  • The 1 s hold is back: it places the bar's first bug 2 above your head (or at the nearest open cell), where it's the mining utility for step 3, lit, with no wild bugs within 12.
  • Wild bugs show everywhere and light 2 around them for the moment they blink on, without making anything seen.
  • Tests: 12 bug tests (the shared count, a full bar, the orbit's light, placing, above rock, an empty bar) plus determinism with a place; 178 in all.

Bugs live in the fog (step 2c, D061): ruleset b3.4. After b3.3, the user wanted wild bugs out in the dark, not spawning near you.

  • The world is cut into 32×32-tile blocks. The 64 nearest you each hold 1 wild bug, in a dark cave cell of the block, sealed caves included: they hint at hidden caves. Today's world has 36 blocks, so every block has one.
  • Wild bugs wander inside their block. At most 3, the nearest that can reach you within 20 steps of open cave, come for your ore as before. A block whose bug is tamed or gone gets a new one 5 s later.
  • Wild bugs flicker for 3–5 s, then go dark for 5–9 s, with no sync between them. Only bugs on screen are drawn, so zooming out shows more.
  • Tests: 7 new bug tests (one per block, the nearest blocks only, the refill, wanderers stay in their block, a sealed cave, at most 3 chasers, a lost chaser), and determinism covers the blocks; 184 in all. With 36 bugs the sim costs 0.03 ms a tick (0.01 without bugs).
  • Screenshots (local, gallery/p6/): zoomed out, the never-seen caves with the bugs flickering in them.
  • A wild bug's light fades out from the bug (user, 2026-09-26: "the strict integer hard-cut light of the bugs is weird"): a radial gradient, and its lit cells' edge softened over a tile. Wild bugs only; your light and tamed bugs' keep the fog's hard tile edge (D052).

Pulling, and the bar calms the chasers (step 3, first part, D062): ruleset b3.5. The user: "manually collecting ore to tame bugs goes against the 'let's build tidy and regular hallways' goal. You zip around, try to mine with precision with a system that was designed for loose intent."

  • Standing still, you pull the nearest seen ore or loot within your light out of the wall, 1 every 5 s, and the cell turns to rock (soft or hard, like the rock round it). Any move restarts the count; the probe counts as standing.
  • Each bug in the bar keeps one wild chaser away: 3 chasers with an empty bar, none with a full one. The bar has 3 slots now.
  • Bar bugs roam round you instead of circling. After playing, the user found them hysterical ("their speed and random walk and their need to stay close is annoying"), then jittery ("like it's being pulled back then flies, then pulled back"; a pause snapped the drawing back a cell, fixed). Now they fly 2 to 8 steps from you at wild-bug speed (faster only to catch up), never pause, keep their heading for at least 2 steps, and turn round only when nothing else works.
  • Tests: 7 pull tests (nearest first, the rock round it, seen only, the light's reach, a move restarts, what fits, none in b3.4), 3 bug tests (roaming with its distance and inertia, following and the jump, the chaser cap); determinism covers the pull; 195 in all.
  • Screenshots (local, gallery/p6/b3.5_*): an ore pulled out of the wall, flying to you, eaten by the one chaser left with 2 bugs in the bar.

Placed bugs mine, and the dust stream (step 3, second part, D063): ruleset b3.6, as planned in next-bugs.md's seventh pass.

  • A placed bug pulls the nearest seen ore (never loot) within 12 of its den, 4 a minute, and the cell turns to rock. It carries 8; full, it waits, its halo swelling.
  • Pass within 4 tiles of one with ore and it flies into your pack, 10 a second, without stopping you; with your pack full, it waits.
  • While a pull is under way, a thin trickle of dust in the material's colour flows from the cell that goes to the puller: to you half a second after you stop, to a placed bug whenever it's pulling.
  • Tests: 7 new pull tests (a bug's nearest seen ore, ore only, the rate and the rock; it carries 8 then waits; the hand-over within 4 and not at 5; a full pack waits; walking past a full bug; b3.5's bugs only hover; g.pulling points at the next cell), and determinism places a bug mid-dive that mines; 202 in all.
  • Screenshots (local, gallery/p6/b3.6_*): both streams at once, a full bug's swollen halo, a hand-over.

The TODOs after playing b3.6 (D064): ruleset b3.7, as planned in next-bugs.md's eighth pass.

  • The first to target an ore keeps it: you and a bug never pull the same cell.
  • The pack's first 4 slots are reserved for ore, loot, soft and hard stone; the last 2 are free, and a full reserved slot overflows into them.
  • You leave home with 8 soft stone, topped up each time you bank.
  • The taming count fills the bar's next free slot as a 4×4 grid, like a pack slot.
  • A placed bug whose area has run out comes to you, hands its ore over and goes back into the bar, but only when a bar slot is wholly empty (no taming started in it); otherwise it stays.
  • Tests: 7 new tests (the first target keeps its ore, both ways; reserved slots and overflow; 8 stone from home and the top-up; a new game's 8 with no empty dive logged; a bug coming back to the bar; none with taming started in the last free slot; a bug that never pulled stays, and one beyond the field waits at its den); determinism covers the reserve and the stone; 210 in all.
  • Screenshots (local, gallery/p6/b3.7_*): the 8 stone on your back, a bug coming back, the bar with a bug and the taming half done.

Claude's calls in step 1, not discussed:

  • Only the home cell counts the pack in, and only when there's something in it, so walking past home logs no empty dives.
  • Home is a plain orange pod, 2 tiles wide, since you walk back to it now.
  • A long press does nothing in b3 (no ring), and Numpad 5 is a tap only (stop).

Feedback

  • 2026-09-26 · b3.6: the bug's dust stream swayed (fixed in the refreeze). The user's TODOs, built in b3.7 (D064):
    • you and a bug can target the same ore;
    • reserve one pack slot for loot and one for ore;
    • leave base with 8 stone;
    • show the taming progress the way a 4×4 pack slot fills up;
    • when a placed bug's area runs out of ore, it seeks you out, hands its ore over, and goes back into the bar.

Conclusion → next

Open.

Feedback · 2026-09-26_lorinc_b3.6

  • Build: b3.6 (D063: placed bugs mine, the dust stream)
  • Source: chat after playing; the quotes are Lorinc's words with minimal spelling and grammar fixes.

Quotes

The bugs' particle stream is doing some back-and-forth movement, whereas the char stream is perfect.

Fixed in the b3.6 refreeze: a bug's stream ends at the middle of its bob (D063).

TODO: bug and char target the same ore.

TODO: one slot should be reserved for loot and another for ore.

TODO: char should leave base with 8 stone.

TODO: taming progress should show the same way the 4×4 backpack slot fills up.

TODO: when ores run out in the area, the bug should seek out the char, give the ore, and return to inventory.

Status

The user answered Claude's questions the same day ("1: ok · 2: 1-1 for ore, loot, soft stone, hard stone, the rest is ffa · 3: every time · 4: perfect · 5: inv full, bug stays where it was placed. seeks: yes"). The plan is next-bugs.md's eighth pass, built as b3.7 (D064). While it was being built the user added:

Tamed bug with no ore to mine left only seeks out char if 1+ bug slots are completely empty (not even taming started).

p5

Darkness (b2)

buildingbudget 3 daysgrew out of p4 · Rule Lab (v4)

Does darkness, with a light that grows with your loot and a probe that sees into the rock, turn digging into exploring?

▶ live b2latest, unfrozen▶ b2.12026-09-25 · p5 · b2 Darkness: zoom, light and the seen map, the fog, the seismic probe (D049–D053)

→ Open.

Full entry

Question

Does darkness, with a light that grows with your loot and a probe that sees into the rock, turn digging into exploring?

Pass: you probe to decide where to dig, and follow what it shows; a fuller pack feels brighter and pulls you deeper; the dim map of what you've seen gets you back without thinking.

Kill: probing becomes a reflex every few steps, or is never used; the dark only hides the caves you want to see, and feels like a chore.

Assumptions

  1. [?] Standing still while the probe's rings spread is enough of a cost while there are no bugs: you probe to choose, you don't spam it.
  2. [?] A light radius that grows with the ore and loot in the pack is felt, and pulls you on.
  3. [?] Light that spreads only through air (it shows surfaces, never inside rock) reads naturally, and the probe is the way into the rock.
  4. [?] The dim "seen" layer is enough to find your way; no map screen is needed yet.
  5. [?] Fixed zoom steps (the pack's pixel-exact tile sizes) feel fine with the wheel and with a pinch.

Limitations

  • [constraint ?] One loadout (the Engineer), and darkness and the probe alone: no bugs, no noise.
  • [cut] Moon bugs, noise, the Demolitionist and the Ghost, and the "why go home" drill: the rest of Bundle 2, after this.
  • [cut] Soft light edges and glow: hard tile edges for now (user: "this is a prototype, not the game itself").
  • [cut] A map screen or pause: the zoom levels are the map for now.

Built

Built in steps, one at a time (the user's call: sequential sub-sessions with small scopes, not parallel ones):

  1. The b2 bundle, forked from b1.7; this entry; decisions D049–D053.
  2. Zoom (D050).
  3. Light and the seen map in the sim (D051, D052).
  4. The darkness drawn (D052).
  5. The probe (D053).
  6. The build check, and b2.1 frozen.

Zoom (step 1, D050):

  • The tunable view.zoom is an index into the 11 sizes, or −1 for the default: about 24 tiles across the short side, so 30 px on a 1280×720 window.
  • Wheel: one level per notch, and a trackpad's small steps add up to one level per 100 px. A trackpad pinch (ctrl+wheel) works the same.
  • Pinch: one level per ×1.25 change in the distance between the two fingers.
  • A second finger drops the first finger's pending tap, swipe or teleport. A swipe already made still ends its hold when you lift.
  • The browser never zooms the page, and the zoom is remembered per browser.
  • Planks: their treads are drawn from a list kept up to date as you build and mine, instead of a scan of every visible tile each frame. The pixels are identical.

Claude's calls, not discussed:

  • A finger that swiped and got a second finger within 0.2 s stays a flick.
  • A new finger added to a pinch starts a fresh pinch.

Known: near the surface, the camera's existing clamp makes the view jump when you zoom.

Light and seen in the sim (step 2, D051, D052): ruleset b2.1 = b1.7 + light: { base 4, orePer 16, lootPer 8 }. A new keeper module, src/sim/dig/light.js, holds the radius, computed in whole numbers from the pack, and the lit cells.

  • How the light spreads: it floods 4-connected through open cells within dx² + dy² ≤ r², wrapping at the world's edge. It also lights the rock cells 8-bordering those, if they're in range.
  • Seen: the game keeps a seen map, which only grows, plus the current lit list and radius, and emits a seen event for newly seen cells. The reveal() helper is ready for the probe.
  • Cost: the lit cells are recomputed only when your cell, the radius or the world changes, about once a step, in 20–60 µs on a desktop.
  • Without light, as in every b1 ruleset, none of it runs, and every example gives the same result.
  • Tests: 17 light tests on ASCII maps, and the determinism test covers the seen map.

Claude's calls, not discussed:

  • The surface cells are fixed at the start, and always lit.
  • The light spreads on the tick a wall is mined, before you step in.
  • Distance across the wrap edge is the short way round.

Known: ?rules=lab (a Rule Lab ruleset) has no light, so it plays without darkness.

The darkness drawn (step 3, D052):

  • A fog overlay, 1 px per tile, the size of the world, drawn over the world and the plank treads and under the character, debris and cues.
  • Never seen is opaque black, seen is black at 65% alpha, lit is clear.
  • It's built from the seen map at the start, then updated only from seen events and when the lit list changes, by merging the old and new sorted lists.
  • The dev panel's readout shows light r N.
  • Cost: the CPU per frame barely changes, but the second full-screen blit adds about 1.5 ms of fill in headless Chromium. It's untested on the A41.

Claude's calls, not discussed:

  • The lit diff runs at the start of a frame, so several changes in one frame cost one update.
  • A per-cell "clear now" flag keeps the surface from being dimmed at the start.

Known: the dim level on dark tiles (hard rock, cave air) is barely distinguishable from black; worth a look on a real screen.

The probe (step 4, D053):

  • The rule: in ruleset b2.1, the ↓ row onFloor is now the meaning probe. It comes after the plank rows and after ledgeAhead → climbOver, so the ledge still wins. b1.7 still refuses there.
  • Numbers: numbers.probe = { flick 2, hold 4, ringTicks 5 }, in a new keeper module, src/sim/dig/probe.js. Ring r reveals the cells with (r−1)² < dx² + dy² ≤ r².
  • Timing: at radius 4, a flick runs 6 rings in 30 ticks and a hold 8 rings in 40 ticks (0.67 s).
  • While it runs: the character stands still, and the run ends with an always-on stop, probe, which shows no cue.
  • On screen: up to 4 thin rings fading around the character, and a low ping per ring.
  • Tests: 21 probe tests on ASCII maps.

Claude's calls, not discussed:

  • A new swipe during a probe counts as letting go of the probe's hold. The swipe then runs after the probe.
  • A teleport ends a probe at once. It's the only thing that does.
  • Ring 1 comes on the probe's first tick.

Feedback

None yet.

Conclusion → next

Open.

p4

Rule Lab (v4)

buildingbudget 3 daysgrew out of p3 · Dig Feel (b1)

Can the swipe table and stop rules live as a JSON ruleset, edited visually against small example situations, without losing any b1.2 behaviour?

▶ live v4latest, unfrozen▶ live b1latest, unfrozen▶ b1.72026-09-25 · Flick and hold: a flick follows the world, a hold goes straight and builds (D046, D047); hold check 0.2 s (D048); the crossing stop reaches the game▶ b1.62026-09-25 · Ruleset b1.6: planks, asking first, fewer stops (D039–D043); a yes covers only its kind of action (D044); the crossing stop (D045)▶ b1.52026-09-25 · b1: the backpack on the character's back, 6 slots of 16, building paid in rock (D038)▶ b1.42026-09-25 · b1: deep-fall red + teleport charge (D036); every version on the timeline (D037, R13)▶ b1.32026-09-25 · ruleset b1.3: cling above a chasm, any mining, gravity (D035); swipe cue disc, "?" on stops, bug reports

→ Open.

Full entry · 1 feedback session

Question

Can the swipe table and stop rules live as a JSON ruleset, edited visually against small example situations, without losing any b1.2 behaviour?

Pass: rules/b1.2.json reproduces b1.2 exactly (every existing dig test passes on the data-driven sim). A rule change like D024 is made in the editor, checked against its situations, exported and loaded into b1, with no code change.

Kill: the table needs so many special conditions that it's code in disguise. Then keep the rules in code, and only make the numbers and stop toggles data.

Assumptions

  1. [✓] Every b1.2 behaviour fits a first-match decision table: (swipe, situation) → action, over a small, fixed vocabulary of named conditions (next cell open, floor below, headroom, standing / clinging, drop ≤ N, …). Held: 11 conditions, 18 rows. The one catch, "mine first, then look", fits by keeping sequencing inside a meaning.
  2. [✓] The data-driven sim stays deterministic and passes every current dig test unchanged. Held: identical to resolve() on 48,000 random actions, and the determinism hash is unchanged.
  3. [?] Seeing a rule's situation (a small map, the swipe, the result) beside the rule makes changes faster and safer than editing code.
  4. [?] A ruleset JSON is small and readable enough to diff in git and paste into chat, like a terrain recipe. b1.2.json is 73 lines, one row or situation per line. Is it readable enough for you?
  5. [✓] The same situations (small ASCII maps + the expected result) can be both the editor's previews and the test suite. Held: rules/examples.json (they're called examples now: "situation" became the name for a condition set).
  6. [✓] The timeline's "Rules at close" table can be generated from the ruleset instead of written by hand. Held: the <!-- ruleset: … --> line.

Limitations

  • [constraint ?] No new mechanics: p4 only represents and edits the rules b1.2 already has. The Engineer is still the only character.
  • [constraint ?] The condition vocabulary is fixed in code. The editor combines conditions, it can't invent new ones. A new condition is a code change with a test.
  • [cut] Terrain editing: that stays in the v2 / v3 recipes.
  • [cut] Zipline, chasm crossing, the chasm-cling fix, Ghost and Demolitionist: these go to the next dig playtest, built on rulesets.
  • [cut] Phone layout for the editor: it's a desktop tool. The rulesets it makes are played on every device.

Built

Format (D028). A ruleset is one JSON file, rules/<name>.json, whose sections refer to each other only by id:

  • swipes: the gesture → intent numbers (commit distance, the horizontal and vertical angle bands).
  • situations: named, all-of combinations of conditions (! negates), such as stepUpAhead: standing, !fwdOpen, fwdAboveOpen, aboveOpen.
  • table: per intent (← → · ↓ · ↑ · ↗ ↖ · ↘ ↙), an ordered first-match list of { if: situation, do: meaning }, plus reason for a refusal or place for a build.
  • reasons: every refusal names its signal, none or flash (D027).
  • stops and numbers: the stop switches and the tunables.

The order is swipe > situation > meaning, because "ahead" means the swipe's side, so the situation can only be judged once the intent is known. rules/b1.2.json has 14 situations and 18 rows. A row that needs "do, then look" (like mine first, then look) keeps that inside a meaning, so the table never has to encode sequencing.

Vocabulary (code, src/sim/dig/ruleset.js): 11 conditions, 13 meanings and 2 signals, each with its own description. The editor combines these but can't invent new ones.

Interpreter: interpret() replaced resolve() in the game. resolve() stays as the reference. ruleset.test.js compares the two on 3,000 random small worlds × 8 swipes × 2 facings (48,000 actions), and they're identical. Every row is hit. The determinism hash is unchanged.

Examples (rules/examples.json): 22 ASCII maps, each with swipes and the expected stop (and optionally the position, the map after and the pack).

  • The 14 map tests from dig.test.js moved there. 8 new ones cover the rows that had no test: ↑, the diagonals while clinging, the overhang, letting go, getting stuck, the staircase down into rock and into air.
  • examples.test.js runs them all and fails if any row of the b1.2 table is used by no example.
  • dig.test.js keeps what a map can't show: build credit, tried cells, dives, determinism.

v4.html · Rule Lab:

  • The table editor: a situation and a meaning dropdown per row, a reason or place field, reorder and delete, and each row's plain-text reading underneath.
  • The situations as condition chips (click cycles ignore → needed → needed not), the refusal signals, the stop switches and the numbers.
  • The examples replay on every change: a preview of each map with the path, the mined cells and the refused cells in red, the actual stop against the expected one, and the rows each swipe used.
  • Click a row's number or its "N ex" count to highlight the examples it decides. Failing examples sort first. "accept result" records a new behaviour as the expected one.
  • A form for new examples draws a map, adds swipes and shows a live preview.
  • Buttons: copy / paste / download the ruleset, copy / paste the examples, copy as Markdown, reset to the files, and ▶ play in b1. Everything autosaves in the browser.

b1 loads a ruleset: rules/b1.2.json by default, or with b1.html?rules=lab the one the Rule Lab saved. Its numbers, stops and swipe angles become the panel defaults. The red flash follows each reason's signal, and the dive log names the ruleset.

The timeline renders rulesets: the line <!-- ruleset: builds/bN.M/rules/<name>.json --> in an entry becomes the ruleset's tables. npm run freeze now copies rules/ into the build, so a closed playtest's rules come from the frozen file.

Checked in a browser (headless Chromium): v4 loads with 22 of 22 passing. Switching the junction stop off fails exactly junction-shaft, and b1.html?rules=lab then plays with junction off. b1 on the default ruleset walks, mines a staircase and stops as before.

After the first report (feedback):

  • D030: a noOre / packFull refusal in the middle of a run gives way to the stop the run would have made anyway, so it stops quietly with no flash. Examples: stairs-end is new, and loot-pack and stair-into-chasm are updated.
  • D031, bug reports: the 🐞 button bottom-left in b1, or the B key, shows "Copied last events to clipboard". The text has:
    • the last 5 swipes: the raw gesture (angle and length, or the key), the intent, the ruleset row for each step, the stop with its signal and the refused cells;
    • the map where the last swipe started;
    • an EXAMPLE line, which the Rule Lab's "paste bug report" opens as a draft example;
    • a REPLAY line with every command and its tick. npm run replay -- report.txt rebuilds the session and checks it tells the same story.
  • Checked: tools/replay.test.js checks the replay. In headless Chromium, real mouse swipes → B → the clipboard → a ✓ replay → v4 opened the draft.

The swipe cue (D032): what a swipe attempts is now visible. A white disc, one step out in the swipe's direction, shows an arrow, stairs or a pickaxe, blinks red if refused and fades in 0.6 s. It replaces the red flash on the refused cells. The pack flash stays for now. A run that stops on its own shows the disc with just "?" in the run's direction, never red (D034; the exact trigger is in the bug report).

Ruleset b1.3 (D035), from a bug report (clinging at the foot of your own staircase, above a chasm, with no way back up). ↗ ↖ toward the wall you hold climb it; any mining is allowed; gravity makes you fall when nothing holds you, and home after a fall deeper than harmlessDrop. b1 and the Rule Lab load rules/b1.3.json; b1.2.json stays as the frozen reference. Four new examples.

Deep-fall feedback (D036, after b1.3): at the bottom of a fall deeper than harmlessDrop, the character turns red and the teleport charge ring fills over 0.7 s, then it teleports home.

The backpack (D038, ruleset b1.5): the pack strip at the bottom is gone. The character carries a backpack of 6 slots × 16 units (2 wide, 3 tall, each slot a 4×4 grid filling from the bottom), and every material mined goes in. Building costs 1 rock per tile (soft first); ore and loot never pay. With no room, rock is dropped and ore or loot refuse. rules/b1.5.json is the default, and migrate() brings older rulesets (the Rule Lab's saved one, b1.2 in the tests) up to it. Four examples changed; stair-into-chasm now builds on down with the rock it dug.

Planks and asking first (D039–D043, ruleset b1.6): every build places a plank, a tread along the top of an open cell, which you stand on or walk under. A build, or digging a step you could walk up, asks first: the run stops, the swipe disc blinks, and the same swipe again does it. Runs no longer stop for break-outs, harder rock, ore, loot or junctions. → at a gap bridges (after asking) and never steps off; ↓ drops. ↑ mines the rock above, climbs a plank ladder, or builds one. The tick-6659 crossing is the example plank-crossing. A yes covers only the kind of action it was asked about, while the run keeps doing it (D044, from a b1.6 report). A walking run stops in front of a plank that crosses its way, so you can pick → or ↗ (D045). Of the 27 old examples, 15 changed and one (no-up) went; 9 are new.

Flick and hold (D046, D047, ruleset b1.7): nothing asks first any more. A flick (a quick swipe, a key tap) follows the world: it walks, goes up and down steps and ramps, and tunnels. Where only building would go on, it stops with "?". A hold (still down 0.3 s after the swipe, or down 0.3 s before it) goes straight: it lays planks over gaps, including a 1-deep dip or ramp mouth, and digs a step in the way. It pauses 0.3 s after each step, and letting go stops it on a whole cell, cancelling a dig or build in progress. Until the input knows which it is, a run waits only where the two differ. The sim gets hold and release as commands, so replays stay exact. Keys work the same way, and the teleport ring waits 0.3 s, then fills in 0.7 s. v4 lost its "asks" column; its example swipes take →h2 for a hold of 2 steps. 17 examples changed, dig-yes-not-build (D044) went, and ramp-mouth is new.

Fixes after b1.7 (code check, 2026-09-25): the hold check is 0.2 s (D048). b1 copied only the sim values its defaults already listed from the ruleset, so the crossing stop (D045) was never on in the browser, only in the examples; now every ruleset value reaches the game.

Pass criterion, half met: rules/b1.2.json reproduces b1.2 exactly. A D024-style change made in the editor, checked against examples and played in b1 without code has been tried once, by the build check above. It's still open for you.

Feedback

None yet.

Conclusion → next

Open.

Feedback · 2026-09-25_lorinc_desktop

  • Build: live dev @ 0bdeae3 (b1 on the Rule Lab's ruleset, b1.html?rules=lab, still the b1.2 rules)
  • Device: desktop, Chrome, mouse
  • Source: the dive log and two screenshots; the quotes are Lorinc's words with minimal spelling and grammar fixes.

What was seen

  • A staircase dug with ↙ from the surface into the cave, then walking up and down it.
  • At the top, the run stopped with the red "I tried, can't do" flash on the surface cell beside the character. Later runs didn't stop there.

Quotes

At the end of this dive log, I was walking up and down on a slope. In the beginning, I was stopped by something at the top. And after 2–3 tries, that "something" did not stop me anymore. This IS a bug, let's find the reason.

Okay, we need a bug report system that removes the guesswork from any report.

Dive log

b1.1 rules b1.2 #1 59.0s ore 0 loot 0 depth 12 mined 11 built 0 | noOre:5 floor:1 wall:4 open:1 down:3 | preset d6525b

The reason

  • The red cell was the step ↗ would build at the top of the stairs, where they end in open air. A 45° swipe along the stairs reads as ↗. ↗ walks up an existing staircase, and at the top, going on would mean building. With no ore that's noOre, which accounts for the 5 in the log.
  • The later tries were flatter swipes (within 30° of horizontal), which read as →. → walks up the stairs and on along the surface. Nothing in the world changed between the tries: they were two different swipes.
  • The bug: with ore, the same run would have stopped quietly at the top (the open stop rule: a walk turning into building). Without ore, the refusal fired before the stop rules could, so the flash said "I tried" about something the run would never have done.

What changed because of it

  • D030: a noOre / packFull refusal in the middle of a run gives way to the stop the run would have made anyway. A quiet stop has no tried cells, so there's no flash. Asking again with a fresh swipe still refuses and flashes. The new example stairs-end covers it, and loot-pack and stair-into-chasm were updated.
  • D031: the 🐞 bug report (the button bottom-left, or the B key) copies the last events. Replay a report with npm run replay -- report.txt, or open it in the Rule Lab with "paste bug report".

Later: stuck above a chasm (bug report, tick 1222)

I want to change some situation > intent > effect rules concerning the situation when the char is climbing on a wall above a chasm.

Any mining is allowed. And every time the char finds itself in a situation where, after the mine-check-move concluded, it is standing in open space with nothing to hold on, it falls. And if it falls more than the allowed safe threshold, it teleports home.

  • Seen in the report: after ↓ climbed over the staircase's last step, every way back up refused: ↗ (noFooting), ↑ (up).
  • Changed: ruleset b1.3 (D035), with the examples cling-climb-back, cling-mine-hold, cling-fall-home and cling-mine-down.

Later: a staircase at a tunnel crossing (bug report, tick 7166)

In the next session, we will address the staircase problem. This is a prime example of when I need a staircase built instead of a solid wall.

  • Seen in the report (the replay matches exactly):
    1. ↙ mined a diagonal tunnel down from (370,7).
    2. From (363,14), ↘ mined a second diagonal down to (368,19), crossing the first in an X.
    3. ↖ walked back up to the crossing.
    4. ↗ then built its step at (364,14). That cell is the top of the ↘ tunnel, so the crossing now has a solid Built block in it, and the ↘ tunnel is plugged.
  • What's wanted: the stair block (D029). ↗ climbs onto it, and ↘ still walks through it.
  • The report's EXAMPLE line (report-6659, start pack soft 16 + soft 12) is the starting point for the stairs example (R8). The full report is in the user's temp/2026-09-25_stairs-report-tick7166.txt, which is local and not in the repo.
  • Changed: D039 (planks), with D040–D043 from the same design session: ruleset b1.6. The crossing is the example plank-crossing: ↗ asks, lays a plank at (364,14) and climbs the ↙ tunnel, and ↘ still runs down its own tunnel under the plank.

Later: digging turned into bridging (bug report, tick 3900, on b1.6)

A digging resulted in a bridge building. Is this a bug or an intentional rule that needs a fix?

  • Seen in the report (the replay matches exactly): → at the foot of a step asked, and the second → dug it. The run tunnelled level, walked out, stepped down, and at the gap laid 4 planks without asking.
  • The reason: D041's "once confirmed, the whole run is confirmed" (Claude's call, not discussed). The yes to dig also counted as a yes to build.
  • Changed: D044. A yes covers only its kind of action, and only while the run keeps doing it. The run now stops at the gap's edge (348,14) and asks. Example dig-yes-not-build.

Later: a run should stop at a plank crossing (screenshot, on b1.6 + D044)

The char should stop a run here, so user can pick a direction.

I think there's no naturally occurring "crossing" situation in the game, we added it with the plank.

  • Seen: walking along a tunnel toward a plank bridge at head height. The run walked on under it without a pause, so there was no chance to take ↗ up onto it.
  • Changed: D045, the crossing stop. Example plank-crossing-stop.

Later: no way to bridge over a down-ramp (screenshot, on b1.6)

Awesome progress, the game feels unrestricted now. There's only one problem, and I have no straight answer to it. There's no easy way to bridge over a down-ramp now.

My idea is: ALL building + dig-into-ramp should be swipe+hold, stop at every step for .3s, and should stop at release, and should not ask for confirmation. The reason is: all building is a high-value, precision action, and you do not do it too much, so it does not feel a chore, more like control. It solves a LOT of clumsy situations. Building ONE step up is now a chore, where you got to intent+confirm+cancel in quick succession. And you can not bridge over small gaps.

  • Seen: standing on the surface beside the mouth of a ↙ ramp. The first cell ahead is only 1 step down, so ← walks down the ramp; the bridge rule only covers drops of 2 or more.
  • Decided: D046 (flick follows the world, hold draws a straight line and builds), to be built in the next session.
  • Built: D046, with the details settled while building it (D047): ruleset b1.7. The ramp mouth is the example ramp-mouth.
p3

Dig Feel (b1)

concluded2 of 3 daysgrew out of p2 · Atomic terrain
Dig Feel (b1)

Does "move until something changes" feel good on every target setup, and do I want another dive?

▶ b1.22026-09-25 · closing build: seed-7727 terrain, zoomed out 3×, junction only at real side passages (D024), settings store only what you changed▶ b1.12026-09-25 · first playable, plus the first-play rules (mine then look, no digging down, step off by asking) and numpad 5

→ Closed on 2026-09-25 without a full verdict. Lorinc: "This is getting enjoyable, still a lot to improve". Every rule change so far was a change to the swipe table or the stop rules above, and each one needed code. Those rules are the game feel. So the next prototype makes them data, with a visual editor: p4 · Rule Lab.

Rules at close

The rules as they stood in b1.2, when this playtest closed. They live in code (src/sim/dig/rules.js + src/bundles/b1/tunables.js). p4 turns them into data.

What a swipe does (Engineer, 1 tile tall, never falls: it stands on a floor or clings to a wall):

SwipeSituationAction
← →next cell open, with a floorwalk
← →next cell open, floor 1 belowstep down 1, keep walking
← →next cell open, deeper gapa running walk stops (ledge); a fresh swipe drops you if the floor is ≤ harmlessDrop, else blocked
← →next cell rock, headroom above you and itstep up 1, keep walking
← →next cell rockmine it; step in only if it has a floor or a 1-step down (mine first, then look)
↓standing, a ledge on the facing sideclimb down over it
↓standing, anything elsenothing (no digging straight down)
↓clingingclimb down; follow an overhang up to 45°; past that, drop if the floor is ≤ harmlessDrop, else stuck (overhang)
↑anywherenothing (straight up is the Ghost's)
↗ ↖standingmine the headroom and the target, build a step under the target if it's air, walk up
↘ ↙standingmine the cell beside you; target rock: mine it, step only onto a floor; target air: build a floor under it (ore) and step
any diagonalclingingnothing (noFooting)
anypack full / out of ore for buildingnothing (packFull / noOre)

Stop rules (a run of steps goes on until one fires; a blocked action always stops):

RuleStops the run whenb1.2
wallwalking turns into mining (you reach rock)on
openthe action changes to anything but mining: typically you break out of rock into open space, or a walk turns into buildingon
lootthe next tile to mine is ore or looton
harderthe next tile is slower to mine than the laston
junctionwalking or tunnelling under a real side passage: a shaft with rock on both sides (D024)on
ledgethe next walk step would drop (always; only a fresh swipe steps off)always
floora climb reaches the groundalways

Numbers (ticks at 60 per second):

Tunableb1.2
walk / climb / fall per tile / build per tile7 / 10 / 3 / 14
mine soft / hard / ore / loot / built14 / 42 / 21 / 14 / 7
harmless drop4 tiles
pack slots4
tiles built per ore12
swipe commits after24 CSS px; horizontal ±30°, vertical ±25°, the rest diagonal
teleport charge700 ms
view48 tiles across the short side, lookahead 3
terrainseed-7727 recipe, 384×64 + a 7-row surface strip
Full entry · 1 feedback session

Question

Does "move until something changes" feel good on every target setup, and do I want another dive?

Every game must run in portrait, landscape and square, with touch and with mouse / keyboard. So b1 tests the feel across all of them, not on one favourite setup.

SetupInputRatios
Samsung Galaxy A41 (2020, the performance floor)touch9:16, 16:9
New HD phonetouch9:16, 16:9
Desktop, HD monitormouse + keyboard16:9, 1:1, 9:16 (resized window)

Pass:

  • You instinctively start another dive, on every row of the matrix.
  • "Push through the hard rock, or recall?" feels like a choice.
  • Swipes on the phone neither overshoot nor feel twitchy.
  • The old phone doesn't visibly hitch, and the frame-time readout in the dev panel agrees.
  • It's sharp on the HD screens (drawn at the device pixel ratio) and readable on the small one.
  • Portrait shows enough depth to plan a dive, and landscape doesn't feel like wasted space.

Kill: if it's still boring after tuning the stop rules, rethink movement before anything else. If it only feels good on one input or one ratio, that input or ratio gets redesigned before b2.

Time box: 3 days. Running over means cutting features, not extending the deadline.

Assumptions

  1. [?] "Move until something changes" (swipe, and the character walks, mines or builds until the environment changes) is fun enough that you start another dive without thinking.
  2. [✗] A mining step can move you into whatever it opens up. First play: tunnels walked the character into chasms. Now it mines first and then looks.
  3. [✗] Every direction should be diggable, including straight down. Removed after first play: the way down through rock is the diagonal staircase.
  4. [✗] Walking stops at every drop of 2+, and that's all you need at a ledge. First play: you couldn't step off a 2-deep drop even though it's harmless. Swiping into the gap again now drops you.
  5. [✗] Climbing down at a ledge is always a safe move. Going diagonally down into a chasm and then pressing down leaves you clinging over the void and stuck. Clinging is also drawn exactly like standing. The fix is open (see below).
  6. [?] One swipe recogniser (pointer events, commit at a distance) feels the same on touch and on mouse.
  7. [?] The keyboard feels as good as swiping, both with numpad intents and with held WASD.
  8. [?] Canvas2D with no dependencies runs without hitching on the Galaxy A41.
  9. [?] Stop rules as a tunable table (wall, drop, open space, new material, loot, hazard, junction) can make the movement feel right without new mechanics.

Limitations

  • [constraint ?] Coloured squares only: no art, and no effects beyond the juice. If it's fun as squares, art can only lift it.
  • [constraint ?] Casual, not survival: no fall damage, and a wrong move never ends a dive (D011).
  • [constraint ?] Everyone is an Engineer: one path, no loadouts to choose between (D014).
  • [constraint ?] No digging straight down: the way down through rock is the diagonal staircase. It was cut after first play, to see if the loop gets sharper without it (D019).
  • [constraint ?] Everything is lit: no darkness, so digging is judged on its own before b2 adds greed.
  • [cut] Zipline: moved to b1.2 (D014).
  • [cut] Torchlight: moved to b2, where darkness arrives (D014).
  • [cut] Moon bugs, Demolitionist and Ghost, the base, heat and raids: later bundles.

Built

World: the v3 terrain (the recipe archived in p2, live = cave), wrapping horizontally, with a surface strip on top and a home spot. The strip is 4 sky rows + 3 solid crust rows, and home is at x = 0.

Character: 1 tile tall in the sim, drawn about 1.3 tiles. Everyone is an Engineer: walk, mine, build, climb down. The zipline is cut from b1.1 and comes in b1.2. Torchlight comes with b2's darkness.

Swipes by context (8 directions; a new swipe replaces the current intent):

  • Open floor:
    • Left / right walks, following the floor over 1-tile steps up and down without stopping.
    • Diagonal mines or builds.
    • Down does nothing.
  • At a wall: a swipe into the wall mines until the environment changes. Diagonal mines or builds.
  • At a ledge (a drop of 2+):
    • A swipe into the gap drops you if the floor is within harmlessDrop.
    • Down climbs down: overhangs up to 45°, drop if the floor is ≤4 below.
  • Mine or build: rock is mined, air is built (1 ore per 12 tiles).

Taps and keys:

  • Tap the character to stop. Long-tap charges the teleport home.
  • WASD: two keys together make a diagonal.
  • Numpad 1–9: 5 = tap (stop); hold 5 = long-tap (teleport, with a charge ring).
  • Mouse click / hold = tap / long-tap.
  • Swipes use pointer events, so mouse and touch share one recogniser. A swipe commits at a distance threshold, not on release. A swipe made mid-tile applies at the next tile boundary.

Loop: a pack with 3–5 slots, teleport home, loot counted at home.

Juice: screen shake, square chunks flying, per-material dig resistance, all behind a master switch. The stop rules are judged with juice off first.

Any aspect ratio: portrait shows deeper, landscape wider. The layout follows the window live.

Dev panel: backtick, or tap the top-left corner. It shows every tunable, frame time, device pixel ratio, viewport and input type. The dive log is copyable, so testers can paste it back.

Rules decided at first play (2026-09-25):

  • Mine first, then look (D020). A mining step moves into the mined cell only if you can stand there: it has a floor, or a 1-tile step down to one. Tunnels never walk you into a chasm.
  • Step off by asking (D018). Walking still stops at every drop of 2+. Swiping into the gap again drops you to the floor if it's within harmlessDrop (default 4), and the walk then continues. A deeper gap stays a ledge.
  • No digging straight down (D019). A down swipe only climbs over a ledge on the facing side, or continues a climb.
  • Junction means a real side passage (D024). Walking out of a tunnel into an open cave no longer stops at the step down. A narrow shaft overhead still stops a walk, and breaking out of rock by mining still stops.

Tunables (current values in presets/):

TunableStart value
Walk speed1 tile / tick unit (placeholder)
Dig speed3× slower than walking
Build cost1 ore per 12 tiles
Ledge stop height2+ tiles
Harmless dropfloor ≤4 below
Climb overhang limit45°
Stop ruleswall, 2+ drop (walking); open space, new material, loot (mining / building); hazard, junction (always). Each can be toggled
Swipe angle zoneshorizontal ±30°, diagonals narrower
Pack slots3–5

Out (later bundles or never): darkness and glow, moon bugs, Demolitionist and Ghost, base, heat, raids, and art beyond coloured squares.

Feedback

  • 2026-09-25 · Lorinc · desktop, first play of b1.1: "the char should mine first, then check if the newly mined place is a viable location". Three rule changes, numpad 5, and the chasm-cling bug.
  • Phone (Galaxy A41) and the other ratios: not played yet. This is waiting on the public repo for the phone link.

Conclusion → next

Closed on 2026-09-25 without a full verdict. Lorinc: "This is getting enjoyable, still a lot to improve". Every rule change so far was a change to the swipe table or the stop rules above, and each one needed code. Those rules are the game feel. So the next prototype makes them data, with a visual editor: p4 · Rule Lab.

  • Not tested: the phone matrix (Galaxy A41, HD phone, portrait / landscape). The open assumptions (1, 6–9) and every constraint stay open. They carry over to the next dig playtest, which will run on p4's rule files.
  • Carried over, open: the chasm-cling bug (clinging is drawn like standing, and a climb into a chasm gets stuck); how to cross or descend chasms (the zipline was planned for b1.2).
  • Decisions: D014–D022, D024–D026.

Feedback · 2026-09-25_lorinc_desktop

  • Build: b1.1 (first playable, commit 2054adc), then fixes on the dev server, frozen as b1.1 (12146ee)
  • Device: desktop, Chromium, keyboard + mouse
  • Source: written on 2026-09-25 from the session notes; the quotes are Lorinc's words with minimal spelling and grammar fixes.

What was seen

  • The character mined into chasms and walked out over the void.
  • It stopped at a 2-deep drop and refused to step off, although harmlessDrop is 4.
  • Going diagonally down into a chasm, then down: the character climbs into the hole, clings to the rock it stood on, and stops (overhang). It looks like standing on air.

Quotes

TBD: We have not covered the use case where the char digs into a chasm. What's up with the 4 slots? Is that the inventory?

Feedback:

  • The char should mine first, then check if the newly mined place is a viable location, and only then move there if it IS. This would prevent digging into chasms.
  • Remove the ability to dig straight down.

The char does not step off an edge if there are 2 empty spaces below, although harmlessDrop=4.

Tap and long-tap should work with '5' on the numeric keyboard.

If I dig down diagonally into a chasm, the engine allows me to push the down button and stand over the chasm. I think the engine thinks I'm in the climbed down, got stuck situation, right?

Dive log

Not captured in this session.

What changed because of it

  • Mine first, then look. No digging straight down. Step off by asking. All three have ASCII-map tests (src/sim/dig/dig.test.js).
  • Numpad 5: tap = stop, hold = teleport, with a charge ring.
  • Open: the chasm-cling bug (see Conclusion → next in the entry).

Later the same day · live dev (seed-7727 terrain, zoomed out 3×)

I created two screenshots …, where the char stops at a 1-step-down location where it should not stop. I have seen this in other locations as well. My assumption is that the char reacts to what used to be in that spot, not what's there right now.

That's NOT what I said. Not what was there a moment earlier. What was there originally.

  • Found: the terrain logic was right: sim, renderer and rules share one world, and digging changes it in place. The stops came from the stop rules. junction read an open cave above the step-down cell as "a shaft overhead". open fires when mining breaks out of rock.
  • Changed: junction now needs rock on both sides of the shaft (D024). Mining break-out still stops, by choice ("walk on only when walking").
  • Not added: an on-screen stop reason (the user said no; the dive log already counts the reasons).

After closing · b1.2 (live)

Terrain traversal is clumsy for a few reasons:

  • There's no way to dig a 1-block-high ledge.
  • There's no way to build a ramp down to the right, then go left (there's no stairs-type block where the char can decide to walk up or go straight).
  • The backpack is very limiting, which is okay for a game balanced like Dome Keeper, but not for this game, where resources are used at a much larger scale. I want the current backpack to stack 32 materials per slot, and to collect all 4 kinds of materials currently in the game. Add these as TODOs to the current live build.

My 'gut feeling' is that for this game to become an impulse-fun engine, it must become a semi-idle 'terrain tamer', where you traverse the terrain, remove fog from resources, create pathways, and your idle robots, tamed animals, whatever your char has, gradually mine the resources available within reach of those pathways.

  • Recorded as TODOs in the live code: the 1-high ledge and stairs block in src/sim/dig/rules.js, to be designed as rules in p4. The pack (32 per slot, all 4 materials) in src/sim/dig/game.js and tunables.js.
  • Direction (not decided): a semi-idle "terrain tamer". You traverse, lift the fog off resources and cut pathways, and your robots or tamed animals gradually mine whatever is in reach of those pathways. This pulls the concept's b3 idea ("it mined while I was gone") forward and makes it the core loop. It would also change what the pack is for.

The tamer loop test is limited by the clumsiness of terrain traversal. Also, we need a visual signal for why something does NOT happen, because everything that felt like a bug was indeed a misinterpreted feature. So: when the char wants to place a block but there's no material, flash the placed block AND the backpack in transparent red, signalling "I tried, can't do".

  • Order kept: p4 · Rule Lab first. The terrain-tamer test waits until traversal is fixed.
  • Built in the live b1 (D027): a refused build (noOre) or loot pickup (packFull) reports the cells it tried, and those cells and the backpack flash red: two blinks, fading over 0.7 s.
p2

Atomic terrain

concluded1 of 1 daysgrew out of p1 · Cave generator
Atomic terrain

If one binary grid is designed step by step by hand, can it give good starter caves cheaply, with predictable output?

▶ v32026-09-24 · Terrain: the archived v2 recipe gives the caves, soft / hard rock, ore and loot▶ v22026-09-24 · CA Lab: one binary grid, a hand-built pipeline of gen and scale steps, every step visible

→ It worked: 5 steps on one binary grid give starter caves, cheaply and predictably. v2 stays frozen as the tool for finding terrain patterns. New terrain ideas become a new tool (v4, …). The v3 terrain feeds the first playtest: p3 · Dig Feel.

Full entry · 1 feedback session

Question

If one binary grid is designed step by step by hand, can it give good starter caves cheaply, with predictable output?

Assumptions

  1. [✓] One binary grid with a hand-built pipeline of gen (CA rule × repeat) and scale (integer X / Y) steps is predictable enough to design with.
  2. [✓] Scaling X and Y separately gives caves a horizontal or vertical character without separate layers.
  3. [✓] One recipe can be reused: with a different seed it splits soft from hard rock. Ore and loot go on top.
  4. [✓] The v3 terrain is good enough to test digging in (b1).

Limitations

  • [constraint ✓] One binary grid only (live / dead): no layers, no materials in v2. It made the output predictable enough to design by hand.
  • [constraint ✓] Every step is visible: the lab shows every intermediate grid, never just the result.
  • [cut] No character and no digging: v3 is judged by eye and by its stats (open / soft / hard / ore / loot, drop counts).

Built

v2 · CA Lab, the pattern-finding tool, frozen by request: "a fundamental tool for any terrain generation pattern finding".

  • One binary grid (live / dead). The pipeline is a list of steps: gen runs a keep / born / die rule N times, and scale enlarges by integer factors, separately on X and Y.
  • A thumbnail strip shows every step. You can see which rule changes what.
  • Scaling started as "2× or nothing". It became any integer at Lorinc's request.
  • The recipe Lorinc found is archived as media/starter-caves_seed6712.json:
seed 6712 · 128×64 · density 450 · wrap
gen  d012 b5678  ×2
scale 4×1
gen  d0124 b78   ×4
scale 2×2
gen  d012 b345   ×1

v3 · Terrain, the v2 recipe as a world:

  • The recipe shapes the caves, and the same recipe with another seed splits soft from hard rock.
  • Ore is its own CA layer (density 300, no scale steps, default rules), and loot is scattered at density 50. Both values come from the v1 generator.
  • Its output is src/sim/gen/terrain.js, which b1 digs in.

Feedback

Conclusion → next

It worked: 5 steps on one binary grid give starter caves, cheaply and predictably. v2 stays frozen as the tool for finding terrain patterns. New terrain ideas become a new tool (v4, …). The v3 terrain feeds the first playtest: p3 · Dig Feel.

  • Decisions: D004, D005.
  • Deferred: depth tiers (the world is homogeneous for now), and chasms, which the recipe produces and which b1 now has to handle.

Feedback · 2026-09-24_lorinc_desktop

  • Builds: v2, then v3, live on the dev server
  • Device: desktop browser
  • Source: reconstructed on 2026-09-25 from the session notes; the quotes are Lorinc's words with minimal spelling and grammar fixes.

Quotes

On v2:

Make scaling an integer, not just 2 or nothing.

(recipe JSON pasted) … these are fairly good starter caves with minimal computation.

Create an archive folder and add the current terrain generation JSON and PNG for future reference. Also, make sure this basic generator (lab.html) stays as-is, because it is a fundamental tool for any terrain generation pattern finding.

On v3:

This is perfect for testing bundle 1.

What changed because of it

  • Scale steps take any integer, separately for X and Y.
  • The recipe and its render were archived as archive/2026-09-24_starter-caves_seed6712.*, and are copied here as media/.
  • v2 was frozen. v3 was built as a new tool on top of it, following the rule "new ideas become a new version".
p1

Cave generator

concluded1 of 1 days
Cave generator

Can a port of Lorinc's old tileable cave generator (a cellular automaton in a Kaggle notebook) produce a world that's worth spelunking?

▶ v12026-09-24 · layered CA world, sliders for every parameter (TS + Vite + Pixi + Tweakpane, rebuilt 2026-09-25 from tag tools-v1-v3)

→ Too volatile to design by hand: with several interacting layers, small input changes swing the output into chaos. Step back to a single binary grid, designed step by step: p2 · Atomic terrain.

Full entry · 1 feedback session

Question

Can a port of Lorinc's old tileable cave generator (a cellular automaton in a Kaggle notebook) produce a world that's worth spelunking?

Assumptions

  1. [✓] The Python notebook's cellular automaton ports to the browser and runs live with sliders.
  2. [✗] Random CA caves are a good space to spelunk in.
  3. [✗] Stacking several CA layers (sideways galleries, vertical shafts, hard rock, ore, loot) with separate horizontal and vertical biases gives controllable shapes.
  4. [✓] Editing keep / born / die rules with an interactive control beats typing them as text.

Limitations

  • [cut] No character and no digging: the generator is judged by eye, from the map and the stats.
  • [cut] No depth tiers: after the first feedback the whole map became homogeneous (D002).

Built

  • A layered CA world: galleries (open space, stretched sideways) and shafts (open space, stretched vertically), a hard rock layer, ore and loot drops, and a sky strip and crust on top.
  • A slider for every layer parameter (seed, density, rule, steps, scale X / Y), a live map, stats and drop markers. The settings are saved in the browser.
  • The rule editor: a keep / born / die toggle per neighbour count. It replaced free-text rules and survives in v2 and v3.
  • During the session, the top / bottom differentiation was removed, which made the whole map homogeneous.
  • Stack: TypeScript + Vite + PixiJS + Tweakpane. That stack was retired on 2026-09-25. The generator lives on as src/sim/gen/world.js, which npm run gallery uses to dump every stage as PNGs.

Feedback

  • 2026-09-24 · Lorinc · desktop: "these caves are truly random, and that does not make a great spelunking experience", and then: "a volatile system … collapsing into chaos after a few steps".

Conclusion → next

Too volatile to design by hand: with several interacting layers, small input changes swing the output into chaos. Step back to a single binary grid, designed step by step: p2 · Atomic terrain.

  • Kept: the keep / born / die rule editor, and horizontal wrapping (the map tiles sideways).
  • Dropped: many-layer composition as the way to design terrain.
  • Decisions: D001, D002, D003.

Feedback · 2026-09-24_lorinc_desktop

  • Build: v1, live on the dev server
  • Device: desktop browser
  • Source: reconstructed on 2026-09-25 from the session notes; the quotes are Lorinc's words with minimal spelling and grammar fixes.

Quotes

So, these caves are truly random, and that does not make a great spelunking experience. Is there a way we could incorporate differentiating the vertical and horizontal axes during the generation, and use that to create shapes with different verticality and horizontality?

Remove the top/bottom differentiation for now, make the whole area homogeneous, and make the rules an interactive control instead of free text.

You know what a volatile system is? When the inputs change the output dramatically, collapsing into chaos after a few steps. Our system is like that now. I think we've got to step back to a very simple binary mode now: a barebones algorithm, and let me design the steps, layer by layer. The keep-born-die control you created is awesome, but give me a tool where I can just control one single grid.

What changed because of it

  • Horizontal and vertical bias per layer (galleries vs. shafts) was added, and then the top / bottom split was removed.
  • The rule text fields became the keep / born / die editor.
  • The next tool became v2, a single binary grid: p2.
Decision ledger · 186 active · 10 superseded
IDDateFromStatusDecision
D1962026-10-05p13activeThe taming gauge's properties are share, default and inertia (user; Claude's merge, confirmed). Decay and volatility merged: "decay and volatility are very similar: they describe the efficiency of the Beastmaster's actions, just slightly differently... these nuances do not fit well into the 'simple approximation of reality' concept." Inertia is how heavy a motivation's needle is: an action moves it by 1/inertia, and it drifts back to its default by 5/inertia points a turn; shown to the player as calm ↔ jumpy. Also (user): small animals start with lower comfort, large ones with higher. The model, every other cell a draft: concepts/taming/gauge-model.html (motivations hunger, comfort, curiosity; dimensions size, agility, intelligence, diet).
D1952026-10-04p13activeFight or flight depends on the team (user): "the animal's attack or flee reaction can depend on the team's strength. Stronger animals must retreat later if an animal attacks but also scare animals away." Against a stronger team the animal is more likely to flee, against a weaker one to attack; strong pets hold out longer when attacked, but scare animals away: team strength is a trade-off chosen before the taming. Open: team strength as the sum, the strongest pet, or the pets near the animal. Refines D194. Text: concepts/shape-exploration/build-principles.md → Pillars (trait space).
D1942026-10-04p13activeAll models are wrong, but some are useful (user): "We can not model reality, but we can create a model that is interesting, intuitive, creates immersion, yet not overly complicated. So... I do not care at a micro-level. If the feature is interesting enough, the complexity comes from the permutation of a few systems, that's intuitive... I'm good." Applied: "Stats could explain what the animal does when scared, and that's one less dimension, always good." "When scared" is no longer a behaviour axis: an animal fights (strength leads), flees (agility leads) or hides (neither; freezing is hiding in place), the generator giving one stat a clear lead. Refines D193. Text: concepts/shape-exploration/build-principles.md → All models are wrong, Pillars (trait space).
D1932026-10-04p13activeAnimals live in a trait space, not a list of families (user: "can we make this a space, instead of a list? like intelligence/agility/strength dimensions, social/solitary axis, diet, survival strategy"; on Claude's split: "yes, and make sure you record 1 and 2, this is a good categorization"). 1. Behaviour axes, discrete, each value a learnable rule: diet (plants, anything, meat), when scared (flee, hide, freeze, fight), social (solitary, pair, group). 2. Stats, numbers within the rules: size and strength, agility, intelligence, nerve (shy to curious). Values are a first set; families name common corners ("herd prey" is a social animal that flees). Direction: traits add up to behaviour, stats and, once tamed, pet skills; "how these translate into pet skills (and animal behavior) is still TBD, but the direction is great." Refines D186's families. Text: concepts/shape-exploration/build-principles.md → Pillars (trait space).
D1922026-10-04p11activeMoth hatching capped (user: "moths only spawn near nodes if there's less than 2 of them there, and only spawns 1"; "keep the release no"): every swarm.mothTicks a built node with gas hatches one moth only while fewer than swarm.mothMax 2 moths are within swarm.crowd 32 px of it. Against b4.77's runaway (3,000+ moths). b4.77 refrozen under the same number. Refines D161.
D1912026-10-04p12activeA passive Simulation pillar (user): the three active loops sit in a dense zone ("I like this a lot: all our active loops are in a dense zone"); "add a passive Simulation pillar somewhere between discovery-design-story, and it will balance the pillars around the audience, as expected." Team management is Strategy, not Design: "design is 'building for aesthetics', that's why it is in that corner." Discovery needs no loop of its own: "the world's idle functions and the animal cards cover that perfectly." Text: concepts/shape-exploration/build-principles.md → Gameplay loops; map.html (v9.8).
D1902026-10-04p12activeThree gameplay loops, and beastmasters (user). "I do not call passive things a loop. Without direct control, they are spectacle and lore." The loops: engagement, core, "feels like a card battle" (learning or taming, and testing teams against the simulation: "this actually falls under the engagement loop"); pet management, core, "feels like a management game" (teams, pet levelling, sending them on missions); resource management, support, "feels like idle farming" (checking what is low and pushing the idle collection toward it: better forager teams, splitting them to the right biomes, more colonies in the right biomes). Pioneers are replaced: scouts open the Unseen, and the taming team are beastmasters ("lock in beastmaster"; "tamer is such a lame name"). Open: whether pets level up by using their skills. Text: concepts/shape-exploration/build-principles.md → Gameplay loops; lifecycle.html, map.html.
D1892026-10-04p12activeLong-term progression: climb differently, not faster (user; Claude's wording, confirmed). On prestige (resetting for multipliers that make the next climb faster): "Does Slay the Spire allow you to climb faster? No. It allows you to climb differently, with harder / more complex mechanics that require more mastery." Progress opens new, harder, more complex challenges the player chooses when to face; quantity piles up on its own, complexity enters only when the player goes looking for it. Refines D188 (no prestige). Text: concepts/shape-exploration/build-principles.md → Game shape.
D1882026-10-04p12activeThe game shape: an incremental idle game (user): "it is an incremental idle game, where you come in, move the needle, reap the rewards: resources, lore, unlocks, and play the taming game." "Each session can be 1 or more runs, and a run can be anything that pushes the needle: levelling up pets, changing and testing teams, reviewing new info on scouted animals, deciding on what to tame with what strategy." While away, "colonies (auto-harvest), foragers (caverns foraging) and scouts (intel gathering) keep working". Candidate A (the short run that keeps only knowledge) is dropped; prestige is not decided. The food chain and the colony are content and balancing on the b4 system, not new components ("the colony: same as the food chain, just auto-harvests"), which refines D177's order. Text: concepts/shape-exploration/build-principles.md → Game shape.
D1872026-10-04p13activeThe taming gauge (user, with Claude's proposals the user OK'd): "this 0–100% IS the taming gauge. There are 3 zones in it: flee/attack, neutral, friendly." Intuitive "for even small kids, nothing you do not know already". "Motivations add up to the 100%, but each have their own zones and needle temperament, and decay. Pet action and consumable primary, secondary effects act on all these individually, and that makes a fun game to play." Each animal draws its own zones (snail picked up; a flea: "bottom of food chain does not necessarily mean easy capture"; bear); a filled need ignores more of the same; startled/territorial "is just scared, but for prey/predator". To test, not settled: the animal acts, its moves derived from its motivations ("we can check if this is fun/simple enough"). Idea, not decided: animal state shown through basic postures, "a MAJOR effort for the value it brings". Text: concepts/shape-exploration/build-principles.md → Pillars (the taming gauge).
D1862026-10-04p13activeHow a new animal is learned (user; Claude's proposal, amended): more abstraction, less realism: "allow observation to fill everything, even if it did not happen in front of the scout, and engagements just put numbers (thresholds, cooldowns) on the skills. It's okay, and even fun, to leave gaps on the card when there was not enough time to observe everything; then that gap will be filled during the first engagement." Kept from the proposal ("I liked everything else"): lines shown, not told, with numbers; blanks visible; a failure says why. Animals come in families that share rules (procedural, "this is not a scripted game"); late game, an animal can bend its family's rules. Rejected: the prey taming teaches the predator ("a predator–prey engagement is not the same as a taming one"). Text: concepts/shape-exploration/build-principles.md → Pillars (the animal's card).
D1852026-10-04p13activeThe animal's card and repeated attempts, without an all-tiers rule (user): D184 as written, except that attempts cost consumables some of which come from earlier tiers, not obligatorily from all of them. User: "Costs from all tiers: I've never said this, and I do not like these absolute rules. It makes the design rigid. Yes, costs come from some earlier tier, but not obligatory 'all' here." Text: concepts/shape-exploration/build-principles.md → Pillars (the animal's card).
D1842026-10-04p13superseded by D185The animal's card and repeated attempts (user): each animal has a card; scouting fills it by observation, a taming party brings back knowledge "not from observation, but engagement, completing the card of the animal". "Players will attempt taming a new animal several times; attempts should cost consumables (from all tiers), but not in a punitive way." "Failed attempts reveal information that simple scouting does not. That's a decision." Text: concepts/shape-exploration/build-principles.md → Pillars (the animal's card).
D1832026-10-04p13activeRoutes into a tame come from different pillars (user; Claude's per-pillar cut, confirmed: "a pretty good shape"). Taming wild bait "will be a major pain point in the game, especially if the food chain has 2+ tiers. We got to give several, very different alternatives." Skipping bait "should be equally hard, but different shape", and "different shape means different pillar". Cultivation: bait from same-tier colonies; recreating the prey's environment in a colony stays only if really simple for both the player and the build, or it is dropped. Prospecting: flora that acts on the animal, and knowledge. The taming itself: team skills; driving prey is "just one (pretty good) skill to have in a team"; making the animal accept something else may be several skills ("hunger", "smells like": first ideas, not decisions). The gauges are where the routes meet; the gauge set is not decided. Text: concepts/shape-exploration/build-principles.md → Pillars.
D1822026-10-04p13activeTaming is the only engagement (user; Claude's restatement, confirmed): scouting as a second engagement "makes it two games, not one"; "scouts need only the team setup active, and the scout itself plays out in the simulation, automatically." The kit is built before the taming: "player arrives into the engagement with knowledge, and failure is just failure, not death: the animal got away, some bait was consumed." Refines D179 (no longer "taming and the breach") and D177's order (3 = scouting as setup + automatic run). Text: concepts/shape-exploration/build-principles.md → Pillars; idea-taming-and-breach.md → The breach.
D1812026-10-04p13activeThe engagement is turn-based and truly strategic, never under time pressure (user): "all the cards are on the table, visible cooldowns (WoW style), turn-based, and environmental effects are also." The player acts every turn: Super Auto Pets also makes pets' effects on each other the primary strategy, but "the auto-battle nature attracted only a narrow niche, because it's like chess: you've got to anticipate the enemy and play the game ahead, in your head, from start to end. Too hard." An idea, not decided: real-time engagements unlocked in meta-progression. Refines D179. Text: concepts/shape-exploration/build-principles.md → Pillars.
D1802026-10-04p13activeThe engagement (taming and the breach) is the core gameplay, the most critical element of the game (user): "We got to build something that is as easy to start and as hard to master as Slay the Spire, and as strategic and intriguing as Sonny, and as free as Noita's wand building." It is designed as its own piece, not settled as one open question. Text: concepts/shape-exploration/build-principles.md → Pillars.
D1792026-10-04p13activeTaming and the breach play like a deck-builder's combat, with simpler UX (user): "there's no shuffle and deck, but cooldown, so players do not have to memorize when a card will be back in play, and there's no luck, just strategy, just like in Sonny. And enemies telegraph their moves, sometimes multiple moves ahead. And moves have multiple effects, and that gives the complexity of the engagement." Within D171: the opponent is the animal being tamed, not an enemy to kill. Text: concepts/shape-exploration/build-principles.md → Pillars (the encounter); pattern in idea-taming-and-breach.md.
D1782026-10-04p13activeEvery simulated run can be watched (user OK'd Claude's proposal; the user's concern: "I can not watch it to verify you are indeed testing the right thing"). The simulator and the view share one rules core; every run replays from its seed and the bot's actions; the report links each number to its runs; the bot shows its intent before acting; batches only after the bot has been watched playing sensibly. Text: concepts/shape-exploration/build-principles.md → The tool → Every run can be watched.
D1772026-10-04p13activeOne component at a time (user): no end-to-end simulation of the lifecycle first; "there's no practical chance that you will pull this off if we do not flesh out the components first." Each component gets its own question, real content and isolated runs with stubbed neighbours, and is wired to the others only once it holds. Order: taming, the food chain, the breach as scouting, the colony. Text: concepts/shape-exploration/build-principles.md → Building it: one component at a time.
D1762026-10-03p12activeThe lifecycle (user): terrain, flora and fauna go unseen → wild → studied → foraged (fauna: tamed) → cultivated. Pioneers open the Unseen and tame up the food chain (a creature only once its natural diet is foraged; a predator once enough prey is tamed, exponentially more for a deep chain); taming the top predator turns the area into Caverns; the foragers build a colony there, which harvests itself. Only those decisions are named; the rest runs on autopilot. "Complexity is now depth and lore, and not confusing uninformed decisions." Text: build-principles.md → How an area moves; concepts/shape-exploration/lifecycle.html.
D1752026-10-03p12activeA taming game (user): "you find procgen living things (from slime mold to Arrakis sand worm), raise them, and send them to excursions"; the theme is ecology, nothing the player uses is technology; grinding is the difficulty setting. Two pet teams: pioneers and foragers. Colonies are claimed in place in every biome, never carried home. Refines D171. Text: build-principles.md → Direction and Ground.
D1742026-10-03p12activeThree equal-weight pillars (user), placed on the shape map around the audience and far enough apart to rest from one another: P1 The Unseen (Strategy, Power, Challenge), P2 Prospecting (Discovery, Story, the most kinetic), P3 Cultivation (the simulation). "Not all pillars will be identical, but they should weigh the same." Text: concepts/shape-exploration/build-principles.md → Pillars.
D1732026-10-03p12activeThis game's audience (user): Discovery 30%, Strategy 30%, Power 20%, Story 10%, Challenge 10% of Quantic Foundry's motivations; a first version had Strategy at 20%. On the shape map as the green diamond. Text: concepts/shape-exploration/README.md.
D1722026-09-29—activeNature, not enemies (user): design storms (earthquakes, firestorms, heatwaves, toxic runaways); the punch is nature's occasional non-linear, elementally strong event; tipping points are the boss fights: pressure (gas accumulating) + climax (gas explodes at a fire), and a quest met before the climax (humidity to a threshold) is the beaten boss (the explosion kickstarts the water cycle instead). No problems: everything always works, pushing it opens new states, systems, areas, climates, toys. Every runaway triggers a negative feedback loop. Nature kills (death between creatures is fine). Symbiosis well represented (user's note to self: endosymbiosis). Text: concepts/callisto_design.md → Nature, not enemies.
D1712026-09-29—activeNo killing, no enemies (user): "In this game, problems are not solved by killing. And there are no enemies. This is a surprisingly restrictive limit, most people equate excitement with punching something scary in the face, and I can not do that." A hard constraint: concepts/callisto_design.md → Hard constraints.
D1702026-09-29—activeThe map switch (user): "a certain zoom level as a switch-over to a static/symbolic/frozen map. When zoomed out that much, the simulation stops (production does not) and the world is displayed in a simplified, highly readable way, like a subway map, showing biomes, zones, climates clearly." Refines D169. Text: concepts/callisto_design.md → The genesis freeze.
D1692026-09-29—activeLocal sim, remote numbers (user): "When offloaded into simple calculation, simulation could just freeze world state and calculate passive resource production. And when player comes into view, real simulation happens (liquid > evaporation > gas > slime), so player gets a guttural understanding of how the world works." Off-screen areas don't evolve; extends D164's offline rule to everywhere the player isn't; supersedes the architecture guide's §3 invariant (numbers mode tracks the individual mode on average). Text: concepts/callisto_design.md → The genesis freeze.
D1682026-09-29—activeWhere a freeze looks (user): "The world is fairly small atm, and zoom range is massive... anything meaningful happening could trigger a zoom out, zoom-in-on-action." A freeze can trigger wherever the new thing happens, not only near the player. Refines D165. Text: concepts/callisto_design.md → The genesis freeze.
D1672026-09-29—activeThe loop (user): "an open world incremental game, where the player keeps adding living systems to the ecosystem, and then gets quests to push certain elements into a tipping point (nodes+ → megabeast)". The player can carry anything, several kinds at once. Refines D165/D166. Text: concepts/callisto_design.md → The genesis freeze.
D1662026-09-29—activeSeveral quests at once (user): the ledger holds more than one recipe; the game starts with two on it, moth+ = ore+ and nodes+ = megabeast. Refines D165. Text: concepts/callisto_design.md → The genesis freeze.
D1652026-09-29—activeThe genesis freeze (user): when something new needs the player's attention, freeze, highlight it, play a sped-up in-situ story of its actual history, show the player picking it up and it arriving on the ledger; short early (short causal chains), players cozy with it by the time chains are long. No ghost fingers: the situation is the decision (at worst a hold-drag circular inventory). Worked example: a spore coats the player on entering its isolated cavern; the first freeze adds its recipe to the ledger as a quest marker (spore + heat + water + soil = sprout); where the conditions hold, a second freeze: it detaches and sprouts. Full text and Claude's draft notes: concepts/callisto_design.md → The genesis freeze.
D1642026-09-28p11activeThe game is an intelligent idle game (user: "an intelligent, complex, systematically beautiful cookie clicker"; idle retention; Vampire Survivors' grind-unlock in n dimensions; "NOT […] a puzzle game" like Terra Nil). Rules: unlock moments explain what you did and where the resource came from (b4's ledger theatrics weren't enough); the level-up is pushing through clearly understood points of no return (seeding slime; "all the regenerating ore in the world to just spam nodes"); more levers than b4's two (nodes, taming); don't densify the interaction graph. Structure: endless, resource-producing environments kept; restoring a biome opens others; two restored → a transition zone (e.g. ice / dust) whose fixing unlocks new states in both; offline = the sim as numbers, stable while away, visuals on arrival. Callisto stays; a 6-year-old is the complexity floor, not the audience. Full text: concepts/callisto_design.md → The game: an intelligent idle game.
D1632026-09-28p11activeSlime (user: "Slime grows on EVERY surface that is not occupied and has a node nearby - built or not - that has gas. It grows aggressively, does not consume gas. On the other hand - it releases gas, when a tamed bug is nearby. Lichen can grow over it, replacing it. Fire does not kill it. It looks like a particle-thin layer of green gooey"; asked: the rock surface, not the back wall, so no competition with moss; lichen replaces it where lichen grows; a release uses the slime pixel up; "The purpose of moss is making the climate change seeded by the monster worm a permanent one-way change"). slime.js (knobs slime.*, g.slime.on): lichen.js's surface (open, rock among 8 neighbours), free of lichen, its station holding gas; every growTicks 30 each slime pixel spreads to one fed free neighbour, and a fed station with none seeds one 1 in seed 4 steps; it takes no gas. Every releaseTicks 60 each tamed bug turns the nearest slime pixel within reach 4 into 1 gas at its station (the evaporated wisp). Lichen placing a patch clears slime under it (unslime); fire never touches it. Drawn in the texture as a yellow-green film (SLIME_RGB, 55%) over the pixel, under the fog. Measured, seed 1, 16 built nodes, one meal, 10 bugs, 15 min: slime steady ~190–200 px, bugs tap ~11 a second, the cave's gas never runs out (7 000 at 15 min: moss had no bare wall left), tamed bugs swing 12–42 between gas-node moths and predators; 0.12 ms a tick. So a meal's climate change sticks while bugs visit.
D1622026-09-28p11activeBeasts eat far from you, where there's no moss (user: "megafauna should target areas with no moss at all, 'near user' is not a good target, I got stuck at an enclosure several times. in fact, attack something 30-100 away from the player in an area with zero or very little moss"). beasts.js edible: a built bulb nearMin 30 – near 100 px from you (was within 50) with at most mossMax 8 px of cover (green, vine, fruit) within mossR 12 px; the beast takes one of those with the least cover, at random. Claude's calls: "very little" = 8 px; none fits: it waits, as before; you walking within 30 px during its 5 s approach makes it look again.
D1612026-09-28p11activeNo hives; gas nodes hatch moths (user: "delete the whole moth nest concept. I do not want moth nests. nodes, that have gas, should spawn their own moths every 30 seconds"). hives.js, its drawing and knobs are gone (supersedes D159's hives and D160; D159's moths hovering while they harvest stays). swarm.js: every swarm.mothTicks 1800 each built node whose station holds gas hatches a moth there (hatch: +1 bug on the ledger, event hatched). Claude's calls: built nodes only (the ledger's "nodes"); hatching takes no gas. Measured, seed 1, 16 built nodes, one meal's liquid (960 gas): 7 moths at 30 s, 3 at 60 s, then the moss has used the gas up (~90 s): 10 moths a meal.
D1602026-09-28p11superseded by D161Hives twice as often (user: "I want the moth nest spawn rate pushed up by 2x"): hives.everyTicks 1800 (30 s; was 3600), still 1 at a time.
D1592026-09-28p11superseded by D161Hives (user: "near a lot of ore, spawn hives. hives spawn 3 moths (tame bugs) before they shrink and despawn"; then "moths should stop, when they are harvesting something, now they just run past"). hives.js (knobs hives.*): every everyTicks 3600, under max 1, a random network node (the pod's from the start) looks within look 48 px for the wall pixel with the most ore within radius 12 (ore 20 or more), apart 32 from another; it hatches a moth every birthTicks 300 (swarm.js hatch: ledger bugs +1, a worker there that is a moth from the start), 3 in all, then shrinks for shrinkTicks 300 and goes. Drawn as a honey blob over the fog, swelling, beating at each hatch, shrinking. Moths with a unit in reach now hover till it's out. Claude's calls: the numbers; at 20 s and 2 hives an idle game hatched ~90 bugs in 10 min, now 27 (seeds 1–3, first hive at 1 min).
D1582026-09-28p11active5× the gas per liquid (user: "5x the liquid / gas ratio, liquid should create much more gas"). gas.per 40 (was 8); Claude's call: gas.burst 5 particles a surface pixel each evaporation (was 1), so pools dry as fast as before and the gas comes 5× as fast, not 5× as long. A beast meal: 960 particles.
D1572026-09-28p11activeBugs don't pick fruit (user: "bugs should not collect the fruit anymore, it will be way less common"); a returning tamed bug prefers a network node with gas (user: "bugs now should prefer spawning at a node with gas"): swarm.js spawnAt scores gas first, then no vine (D118), then the fewest bugs (D116).
D1562026-09-28p11activePredators haul their catch (user: "the predator itself should pull back into the rock too with the prey, then slowly re-descend. The pink part should not glow, but the tip yes, and THAT should be pink"; "the pink predator must pull back with its last prey, THEN despawn"). predators.js: a string has len up to full; it comes down a px every descendTicks 30 (new ones too, from the rock); a catch hauls it up a px every retractTicks 3 with the prey on the tip, and the ore appears when it's in the rock (event predatorOre); hauling, it catches nothing, one catch a haul; after the last meal it hauls that one up, then goes. Render: the string dull pink [120, 62, 92] under the fog, the tip glowing pink [255, 70, 175] over it with the prey drawn below it.
D1552026-09-28p11activePredators (user: "a pink predator, with a bright tip, that spawns at places with a lot of bugs, hangs from the ceiling like a string, and when a bug comes in contact with it, it pulls it back into the stone and creates 3 ores. Can repeat 5 times before despawning"; asked: both tamed and wild bugs, a tamed one gone for good; "at most 1 predator per 4 nodes at a time… this will be the main ore replenisher"). predators.js (knobs predators.*): every spawnTicks 600, while fewer than built nodes / perNodes 4, the bug with the most bugs within crowdR 24 px (crowd 6 or more), not near another predator, calls one: straight up at most up 32 px to the rock, anchored on the open pixel under it, hanging to the next rock or length 16 px. A bug on the string or beside it (flying too) is caught at once: tamed → off g.swarm and ledger bugs −1, wild → gone (its block refills later); the ore 3 soft/hard pixels nearest the anchor turn to ore (event caught, the view slides the bug up into the rock and repaints the ore). After meals 5 it withdraws (predatorGone). Drawn over the fog: pink pixels swaying a little lower down, a bright tip with a halo. Claude's calls: the numbers above; no randomness (the most crowded bug, then the first). Measured, seed 1, 16 built nodes, 20 tamed bugs, 5 min, no new bugs coming in: 16 predators (4 at once), 73 bugs eaten (18 tamed, 55 wild), 219 ore; the ledger's bugs 20 → 4.
D1542026-09-28p11activeMoths (user: "When a bug comes in contact of gas, it starts to behave like a moth - flies in circles with an element of random walk. Still sends everything to the ledger immediately, still lives for 30s. Let's change the jumper bug's color a bit less warm, so there's a visual difference too"). swarm.js: a tamed bug on a pixel whose station holds gas (checked in the air too) becomes a moth until it fades (b.moth, bounce.js becomeMoth/mothTick): it flies through open air at bounce.mothSpeed 12 px/s, its heading turning for a mothRadius 6 px circle, nudged ± mothJitter (60/6400 of a turn) each tick and turning the other way round 1 in mothFlip 120 ticks; rock ahead: it turns round. It never stops for a unit but pulls what's in reach as it passes (each to the ledger at once), greens what it flies over where there's gas, and fades after idleTicks with no unit, coming back a jumper. Render: moths amber (BUG), jumpers JUMPER [245, 222, 160]; the fade ghost keeps the colour. Claude's calls: a moth stays one once it met gas, even after the gas is used up (the user: "starts to behave"). Measured: a moth in a cave with gas flew ~430 px of loops across ~50 px in 30 s, laid 105 moss, mined nothing (it flies mid-cave) and faded.
D1532026-09-28p11activeWall-bouncers and cheap taming, for an exciting loop until 64 nodes (user: "drop the wild bug taming cost to 1 and change its natural movement. Let's make it a wall-bouncer. It moves on the wall, and if there's no ore nearby to mine, it shoots itself in a low-gravity arch through the cave. If no ore found for 30s, fades away and spawns again randomly around a node"; asked: wild ones "do the same, but do not linger around ores, just walk around and sometimes do the wall-jump"; "send ore as soon as mined"; "make it a random arch, no logic or memory"; no free liquid). bugs.tame 1. New bounce.js (knobs bounce.*): crawl along the wall (open pixels touching rock), a jump at jumpSpeed 40 px/s in a random direction, gravity 18 px/s², stick to the last open pixel before rock; flight in 1/1000 px, integers. Tamed (swarm.js): stays while a unit is in reach, jumps when none within swarm.near 8 px (after restTicks 60 on the wall), each unit to the ledger at once (a haul event per unit), idleTicks 1800 with no unit → event faded, back near a node (the D116/D118 rules); no trips, no fruit carry limit; D133's pull to bare wall is gone. Wild: bugs.js g.wander hook (b3 unchanged); a wanderer crawls every bugs.moveTicks and jumps 1 in wildJump 40 steps; chasers drift to you as before; a wanderer may leave its block. Claude's calls: a jump needs 8 px of open air ahead (with 3 px, most flights ended in 0.23 s against the next rock; now median 0.35 s, max 2 s); a bug spawned in the air falls to the wall; fading drawn as a 1.5 s widening ghost. Measured, seed 1, 6 bugs, 3 min: 110 units (56 before), 0 ticks in rock, 91% of the time on the wall.
D1522026-09-28p11activeMoss costs gas (user: "tamed bugs place moss on cave back wall only in the presence of gas, every placed moss uses one gas"). garden.js greenAround: a pixel greens only while its station (gas.js stationOf, the node whose share of the cave it's in) holds gas.perMoss (1) or more, and takes it; no gas there, the bug passes and the wall stays bare. Claude's calls: the gas is the pixel's own station's, not the bug's or a neighbour's; bugs still head for bare wall (D133) with or without gas; gas.perMoss 0 = free moss, as before. Consequence, flagged to the user: gas comes only from beasts' pools (the first beast at 16 built nodes), so before that no moss, no vines, no fruit and no lichen fire.
D1512026-09-28p11activeTamed bugs stop for fire (user: "tame bugs must stop moving if there's fire in their 6px vicinity"). swarm.js fireNear: a burning pixel within swarm.fireStop (6) px, round, and the bug skips its step; it walks on when the fire there is out. Claude's calls: it still pulls and its trip still ends on time (only moving stops); a still bug's 3×3 fire shield (D147) keeps its ground green through the fire.
D1502026-09-28p11activeGas spreads (user: "all I'm seeing is that the gas stays at the closest node(s) without any consideration to saturation […] use the fire-spread algo to spread the gas particles? once a node gets saturated, it sends half of the surplus further, and it quickly settles"). gas.cap 8; every gas.spreadTicks (30, 0.5 s) each station over the cap sends half its surplus (rounded up). Claude's calls: stations are neighbours where their shares of a cave touch (every open pixel belongs to the node nearest it through open pixels, one flood from all nodes, ~12 ms once per map), not along roots (only ~30% of roots avoid rock: ~200 groups, a third of the nodes alone; the caves give ~80 groups, the biggest 60–124, ~40 nodes alone); the surplus goes a hop towards the nearest station with room (plain "to emptier neighbours" left cones of 14…9 behind stations stuck at exactly 8); a full cave evens out to within 1; stations take turns in node order (all at once, they swapped back and forth for ever). Measured on seed 1: 192 particles fill 26 stations in 4.5 s; 1887 in a 111-station cave even out in 22 s; a spread step ≤ 0.4 ms. Wisps drift between stations as gas moves.
D1492026-09-28p11activeGas (user: "nodes will behave like climate stations. I want the mega-worm-made shimmery liquid to gradually evaporate, creating 8 particles per liquid"; "I want the vapor to be contained in these closed caverns"; "I do not need pressure, saturation, just gas presence"; "gas needs to be a visual particle effect, not something with persistence"; no cap per station, "we will do something with the gas levels"). Every node is a station, built or not, eaten or not: g.gas[node], a count, saved. g.liquid holds a drop's particles left (gas.per 8). Every gas.everyTicks (300, 5 s) each pool pixel with no wet pixel above gives one particle to its station and dries at 0 (the ledger's liquid −1). Claude's calls: the station is the nearest node through open pixels (a 4-way flood, memoised; b4's rock never opens, so gas stays in its cave); none within gas.reach 20000 px flooded → the nearest in a straight line; the pool shrinks from the top; drawn as a cloud of up to 48 pale specks round the station (wider with more), and a wisp drifting from the pool to it, under the fog like the liquid. No overflow between stations, so the cavern graph was never needed.
D1482026-09-28p11activeWorms glide (user: "can the red snake move in a less blocky way? it moves at a tile-resolution, please move it the same way the player moves"). View only (render.js drawWorms): each body pixel slides from where it was before the worm's last step to where it is, over the step's worms.moveTicks, drawn between ticks like the bot and the bugs; the sim still steps whole pixels, 8-way.
D1472026-09-28p11activeTamed bugs suppress fire (user: "give tame bugs a 3x3 fire suppression area"). garden.suppress 1: no cover within the 3×3 round a tamed bug at work catches fire, whether from the spread, a lichen's ember or an ash disc's flare-up. Claude's call: a pixel already burning there burns on (no putting out), so the effect is green squares that come through a fire where the bugs were.
D1462026-09-28p11activeLoot is crystals (user: "let's rename internally loot to crystals"). Claude's calls: all of b4 (code, ledger row and field crystals, crystalPx, view.crystalPing, world.crystals, comments, concepts/player-influences-but-system-has-its-own-trajectory.md); the user's quoted words keep "loot"; b1–b3, the shared sim (Tile.Loot) and their rulesets keep it (b4's world.js: CRYSTAL = Tile.Loot). The save format is version 2: b4.62–b4.63 saves start a fresh game. Old links with k=world.loot or view.lootPing lose those knobs.
D1452026-09-28p11activeTamed bugs from the network (user: "Detach the tamed bug count from direct user actions, every 4 automatically creates a new tamed bug, that acts exactly the current ones. Eating a loot does not tame a bug anymore"; asked, "4 built nodes"; then "let wild bugs get tamed by nibbling, I just wanted to make sure the player can not stop the progress by running away from bugs"). nodeTames in game.js: each nodesPerBug (4) built nodes reached is +1 bug on the ledger, a worker like the others (starts near you, b4.49); nibbling still tames (D060); b4.40's loot taming is gone (supersedes D122). Claude's call: a node a beast eats takes no bug back (nodeBugs follows the most reached). The lizard enclosure test now lays its own ash: since b4.54 it had passed only on ash from fires started by bugs tamed on loot other tests left in the shared map.
D1442026-09-28p11activeThe game saves itself and comes back on the next visit (user: "how could you save game state, store in cookie, and reload it, when the site is visited again? all this without a lag spike of massive files stored?"; then "wrong assumptions, check b4.61 and try again. there's no terrain manipulation"; then "let's try to build it"). Claude's calls: localStorage, not a cookie (4 KB, sent with every request); one save per build id, seed and map knobs; saved on pagehide, on the tab going hidden and every 30 s. save.js: the cave never changes shape, so a save is the state over the map as made: per-pixel layers run-length encoded, tiles that changed kind (ore/loot pulled, worm ore) as a diff, the rest as JSON; generic over the game state, so new systems save with no change there. Randomness comes from the tick, so restoring tick continues the same game (a test runs a saved and a loaded game 4000 ticks on: identical). Seed 1 after 20,000 ticks: 25 KB, save 9 ms, load 2.5 ms. A save that won't load is dropped for a fresh game; the dev panel's "new game" wipes it. Not kept: a beast's shadow mid-approach (its bite still comes).
D1432026-09-28p11activeThe mega beast's shadow in pixels (user: "make the bulb-eating giga-worm bigger and pixel-art, like everything else is on screen? I'm thinking of sampling the screen, and displaying the worm presence as shifting, darkened pixels"). Claude's calls: a 96 px body snaking behind its head (radius 12 px, tapering to 6), each world pixel under it darkened by how deep inside it is, hashed per pixel and re-rolled 12×/s so the ground crawls; a sparse dusty rim. No screen sampling: black pixels over the frame darken it the same way, cheaper. Over the fog, so on unlit ground mostly the rim shows.
D1422026-09-28p11activeWorms tunnel to fruit (user: "worms can tunnel towards fruits"). A foraging worm with a fruit within sense 24 px steps to the neighbour nearest it through rock as well as air (not the sheet, sea or space); the rock stays as it is, as on its way to a deposit site (D091). With no fruit in sense it wanders the open cave as before. So fruit in the next cave is reachable.
D1412026-09-28p11activeMega beasts (user: "at 16/32/... node count add 1-1 mega beast to the pool. These are like Dune sandworms, you do not see them, just the massive tremor and a shadow as they tunnel below the surface. They eat one bulb every 5 minutes. You do not see them, they just pull the bulb back into the backwall and 24 shimmery liquid particle drops from the bulb's location and flows down and settles in natural cave pools"; answers: doubling thresholds; the node and its roots go; "not the nearest but a random, on screen"; the pools permanent, "I will want to use these pools for some interactions", the ledger counts them, nothing collects them yet; on screen = within 50 px of you, else it waits; a 5 s build-up then a jolt; never the bulb holding you or an end of the root you ride). beasts.js: a beast joins at 16, 32, 64… built nodes and stays; each eats every everyTicks 5 min; 5 s before, it picks a random built bulb within near 50 px and its shadow (a long soft dark mass with a dusty rim, over the fog) slides in from 48 px away while the screen trembles, growing; the bite: a big shake, the bulb sinks, the node and every root touching it are unbuilt (they can be built again); 24 drops fall and flow down (the sim settles them one by one: down, down-sideways, else along the row within 32 px to a way down) and stay as shimmering liquid pixels; a ledger row counts them. Claude's call: pod nodes are never eaten and stay on the network, else a fully eaten network would leave nothing to build from.
D1402026-09-28p11activeTamed bugs eat 2× slower (user: "bugs outcompete every other animal, they should eat 2x slower"). A tamed bug pulls a unit (ore, loot, fruit) every swarm.pullTicks 120 ticks at most (2 s; was 60), still faster by the bug level's gain. Wild bugs' nibbles of the ledger are unchanged.
D1392026-09-28p11activeLizards linger (user: "lizards should eat 3x slower, and stay on screen and zip around the walls 5x longer. they are cute, but I barely see them"). A lick every mineTicks 90 (1.5 s; was 30); a life is its licks, so 5× longer with 3× slower eating needs eat 27 before it burrows (was 16; still 5 loot). And after every rest it zips on along the wall (4–12 px), even with ash still in reach (before, it stayed put and licked on, and an empty route sent it on a 1 px "dash"). Measured on seed 1 with ash round the start: 8 s from spawn to burrow before, 40 s now.
D1382026-09-28p11activeLoot for the lizards, the bug level for you (user: "loot should upgrade lizard mining distance, not the player's"; "player reach, mining speed and light should depend on the bug level instead"). Loot buys lizard levels by itself (16, 32, 64…; lizardUpgradeCost), each +20% lizard reach (6 px → 7 → 9…); a purchase flies loot from the ledger to every lizard. The bug level (fruit, D094) now also makes your light, your mining radius (the light's) and your mining speed 20% bigger a level (the light grew with nothing before; the radius and speed grew with loot, D096). The bot row's dots follow the bug level.
D1372026-09-28p11activeLizards dash for ash in the open (user: "lizards can leave the walls for a short dash to reach ash in the cavern centre, but goes back to the safety of the wall at the next movement"). When no wall pixel in its route range has ash within its reach, a lizard runs straight through the air towards the nearest ash within dash 16 px, stops within reach (6 px) and licks while it rests; its next move is straight back to the nearest wall pixel. No new state: a lizard whose head isn't on a wall pixel is out on a dash.
D1362026-09-28p11activeLizards live off ash (user: "change lizard mechanics. it should spawn in areas with ash, have a 6 mining radius, eat up ash tiles, and when burrows, creates 5 loot resources"). A lizard spawns where density 24 ash pixels lie within radius 16 px (was reachable ore, D101); it seeks and licks ash within reach 6 px (was ore within 3); a licked ash pixel becomes bare back wall again, which bugs can green; after eat 16 it burrows into a 5 px site (lootPx) that turns to loot (was 1 px). So loot now comes from fire: lichen sparks, cover burns to ash (D102), lizards come.
D1352026-09-28p11activeBulbs light up near you (user: "highlight a bulb when in the light radius"). A still bulb (a built node, or one that shows) within the light's radius of the bot (8 px, straight distance) is drawn in the held bulb's bright colours at r 2 instead of the dim 5 px plus; still under the fog, so one behind rock stays hidden.
D1342026-09-28p11activeA quicker bulb with a hold-off (user: "block the player for 50ms after entering the bulb from make a choice, and change the hold-release time to a total 1.5s (incl the no-decision time)"). For holdOffTicks 3 (50 ms) after a bulb takes you in, a drag or a release picks and confirms nothing; after that, a drag you're still holding picks (so the drag you walked in with picks at 50 ms, not at once as in D123). The bulb lets you go after ejectTicks 90 (1.5 s from entry, the 50 ms included; was 3 s).
D1332026-09-28p11activeTamed bugs go for bare back wall (user: "tame bugs should be attracted to cave backwall tiles that are not green yet"). Before each step a bug counts, along each of its 8 ways, the open pixels with no cover in the next swarm.look 8 px (up to rock) and takes the way with the most (its heading on a tie); with none in sight it random-walks as before (D083). Measured on seed 1's start cave, 6 bugs: 1690 px greened in a minute against 1150 walking at random (look 4 gave 1304: the last bare nooks were out of sight).
D1322026-09-28p11activeBuilt nodes on the ledger (user: "add the built nodes as a ledger entry, below the ore counter, symbol is a bulb scaled down to visually fit the ledger's other entries"). A row below ore counts the nodes with a built root; its icon is the held bulb's pixels (r 3: core, body, rim) scaled into the icons' square. Like every row, it shows once the first node is built (D127).
D1312026-09-28p11activeA tamed bug starts near you (user: "tamed bugs should start their life right where they were tamed, so that the player sees it and connects taming -> green stuff"; then: "when a bug gets tamed, spawn a tamed bug near the player, that's it"). A new worker's first trip starts on an open pixel within swarm.spawn 12 px of the bot; its later trips start at network nodes as before (D116, D118).
D1302026-09-28p11activeLoot pings (user: "loot ore should rarely 'triple-ping': 5ms halo, 10ms gaps"). A seen loot pixel on screen flashes a white halo over the fog three times, once every view.lootPing 30 s at a phase hashed per pixel (Claude's reading of "rarely"). Claude's call: a frame is 16.7 ms at 60 Hz, so 5 ms and 10 ms can't be drawn; the halo shows for one frame, then one frame's gap, three times (~83 ms).
D1292026-09-28p11activePhone zoom and brightness (user: "zoom does not work on phone, and the whole game is too dark to see - but only on the phone"). Found: b4 had no pinch (a second finger was ignored), and the zoom levels were device px, so a 3× phone started at ~4 CSS px a tile and could zoom in only to 8. Now: the levels are CSS px (2–24) times the device pixel ratio (desktop at 1× unchanged); the default is ~100 tiles across the short side but at least 6 CSS px a tile; a two-finger pinch zooms a level per 1.25× change of the fingers' distance (it ends the drive without confirming anything, even in a bulb). Claude's call for the dark: phone screens crush dark greys, so a knob view.bright (the canvas's CSS brightness, black stays black) starts at 1.5 on touch screens, 1 elsewhere, on the dev panel.
D1282026-09-28p11activeScans don't scare wild bugs (user: "seismic events should not scare wild bugs anymore, delete that code"). b4's scan no longer calls bugs.js scare and its scareTicks is gone; the shared bugs.js keeps scare for b3.
D1272026-09-28p11activePink from burst light worms; ledger rows earned with theatrics (user: "if light worms have no FOW to lift, they instead explode into bright rainbow particles and give a new pink pixel resource. also - until you have at least one, elements of ledger do not show up, but when a new element shows up in the ledger for the first time, it does with theatrics: screen shake, and particle 8 streams of .4s duration from random positions of the new ledger element color flow to the new ledger item, and this lasts for 2s, with .2s overlap in particle stream source spawns. the player still just gets 1 new element though, the first one"). An ash worm (D119) that finds nothing unseen within 64 px bursts: a rainbow puff, +1 pink (a new ledger row, after fruit), its pixel flying there. A ledger row is hidden until its count first reaches 1, then stays; the bot's row shows from the start (you are its 1). A first show: the screen shakes, fading over 2 s; 8 streams of the row's colour, one every 0.2 s, each 0.4 s of particles from a random spot on the screen to the new row (drawing only: the ledger gets just the 1). Shown rows stack; the gap shows only between a shown resource and a level.
D1262026-09-28p11activeThe bot row counts bots (user: "bot should have a number on the ledger too: 1, if you are alone, and more, if there are white flower bots active on the travel network"): 1 + the flower bots at work (D108).
D1252026-09-28p11activeThe ledger regrouped (user: "fruit icon should be a pixel, just like other resources"; "ledger should be: ore, loot, fruit, a gap, then player and butterfly level"). Rows top to bottom: ore, loot, fruit, a row's gap, the bot's level, the bugs' level; fruit's icon is a red square like ore's and loot's. The level rows show what they did (a dot per level; the bugs' row also the tamed count).
D1242026-09-28p11activeHearts and "?"s from bugs being tamed (user: "bug must release heart particles 50% of the time it gets taming ore, and "?" particles if the player has none"). A wild bug's bite (nibble) of the ledger's ore sends up 3 hearts half the time (drawing only, Math.random); a bug that would bite but finds no ore on the ledger sends up a white "?", at most once per nibbleTicks (event hungry, b4's ledger mode only; b3 unchanged). The 6 hearts when a bug is tamed stay.
D1232026-09-28p11activeLichen light, no scan circle, and the bulb as the one way onto the network (user: "Lichen should have a permanent, faint, but large radius light"; "remove the white circle visual effect from the seismic test event"; "the navigation system bulb-entry-exit is still not great UX, let's try this: upon entry, bulb accepts the player, the whole pulsates dimly, local bulb local edges light up, local buildable edges light up in green. drag chooses, release confirms. bulb ejects the player in 3s to an 5px away open space from the bulb center"). Lichen: every patch lights 24 px round it by line of sight, forever; the fog there is 55% at the patch, easing to the seen dim at the rim; drawing only (nothing becomes seen). The scan's white rings aren't drawn (the scan itself is unchanged). Bulbs: held, the whole network pulses dimly over the fog, the bulb's built roots light up orange, the unbuilt ones the ledger can pay for show green; a drag picks one within 67.5° (it flashes), letting go confirms it; after 3 s the bulb puts the bot on an open pixel 5 px (ejectR) from its centre. Claude's calls: a bulb takes you in only when it offers something (a built root, or an unbuilt one with the price on the ledger), else the pod's nodes trap you at the start; confirming a built root rides it (on through the next nodes the way you dragged), an unbuilt one is built and ridden; a ride that stops at a node stops in its bulb; pointing along a root to board it (D107) is gone; a drag you were already walking with picks as soon as you're taken in; the bot is put out the way it came in.
D1222026-09-28p11activeLoot tames wild bugs (user: "When wild bugs find a loot, they become tame"). A wild bug within lootTame 2 px of a loot pixel in the rock is tamed: +1 on the ledger, gone from the world, hearts, as the ore-fed taming (D060). Claude's call: it eats that loot (the pixel turns to rock), else one loot pixel would tame every bug its fog block refills with, every 5 s.
D1212026-09-28p11activeAnimals seen everywhere; a round mask (user: "all moving animals should be visible even in unexplored areas, but there should be a circular mask on the map with a gradient at the edge, that hides the repeating X axis"). Lizards are drawn over the fog again, in D111's dull greens (the worms, wild and tamed bugs, flower bots and ash worms already were; wild bugs keep their dark blinks, D061). The world gets a round mask round the screen's middle, as wide as the map (r = half its width), fading to the background over its outer fifth; it's off when the circle lies off the screen; flights and the ledger are drawn over it.
D1202026-09-28p11activeSlower rides you can leave anywhere (user: "travel network is too fast, can not get out where I want"): rideSpeed 40 px/s (was 80); a tap (Space) while riding gets you off at the next open pixel along the root, mid-root (it stopped you at the next node before).
D1192026-09-28p11activeA ragged fire and ash worms (user: "Fire spreads in a square shape, looks silly... can you trigger it at random 3 points around the lichen, probably it will break the shape? Also, ash areas should spawn 12s lifetime grey worms, that have a series of small lights on their sides and quickly burrow in a snake path towards unexplored areas and lift the fog permanently"). Fire: the ember lights 3 random cover pixels within 6 px of the lichen; and (Claude's call, since 3 squares still merge into a square) each step a burning pixel sets a side neighbour's cover burning 50% of the time, a corner one's 25% (over its 4 steps: 94%, 68%), so the front is ragged; about 1 px in 1000 of the connected cover is left. Worms (ashworms.js): 1 in 2 discs sends one from its centre once its fire is out; 8 px of grey with a twinkling warm dot on each side of every other segment, over the fog; 20 px/s through rock and air (not the sheet, sea or space; the rock unchanged), heading for the nearest unseen pixel within 64 px and swinging a step to each side in turn; everything within 3 px of its head becomes seen for good; gone after 12 s in a grey puff. Seen: a whole burned cave sends out about 8 and lifts a lot of fog.
D1182026-09-28p11activeTamed bugs go where there's no vine (user: "prefer to spawn the bugs in areas with no vine"): a trip's start node is one with no vine or fruit within about swarm.crowd 32 px (vines counted per 16 px block, the blocks the circle overlaps) if there is one; among those, the fewest bugs (D116), then random.
D1172026-09-28p11activeSmaller ash patches (user: "make smaller ash patches, no room left for the vine to grow"): a disc is r 2–3 (was 3–5, D102), about a third of the ash; the centres stay 8–12 px apart, so there's bare wall between them for the bugs to green and the vines to grow into, next to the ash (D115).
D1162026-09-28p11activeTamed bugs spread out (user: "tame bugs try to spawn in areas with the least amount of tame bugs"): a bug starting a trip picks, among the network's nodes, one with the fewest other bugs within swarm.crowd 32 px, ties at random (was a random node).
D1152026-09-28p11activeFlower bots grow the rim; ash feeds vines (user: "make the bots try to grow edges into new nodes in the network edge, not just increasing edge density in the centre. make vines that touch ash becoming hyper-productive, because with the ash invented, now there's not enough ore"). Bots build only edges to nodes not on the network yet; away from the rim they take the built root that starts the shortest way (in hops) to the nearest node with such an edge, and at the rim they wait for the ore and their 60 s. Asked, the user chose more fruit (not ore) at 10×: a vine pixel with ash among its 8 neighbours makes fruit 10× as fast (garden.hyper), and the next fruit lands on one with that weight.
D1142026-09-28p11activeThe network under the fog, smaller bulbs (user: "network is still WAAAY too dominant visually. Draw it behind fog, make bulbs smaller"). Built roots and still bulbs are drawn under the fog: dimmed where seen, gone where unexplored. A still bulb is a 5 px plus (was r 2), a buildable one with a lit heart. The bulb holding the bot (r 2–3, was 3–4) and the edges it offers stay over the fog, so building works in the dark.
D1132026-09-28p11activeLichen sparks 4× rarer (user: "lichen explosion should be 4x more rare"): 1 in 24 of its checks (every 5 s), about 2 minutes on average with cover near, was 1 in 6 (D102).
D1122026-09-28p11activeFewer, dimmer flowers (user: "Let's halve even that number of white flowers, and do not make it this bright"): 1 in 8 ash discs (flowers.per 8, was 4); petals (168, 166, 160), heart (170, 150, 84), was white and (255, 233, 138). Still drawn over the fog.
D1112026-09-28p11activeThree fixes (user: "loot ore should be white; lizards should not glow; there should be 1/4 white flower per ash, this is waaaay too much"). Loot is white (240, 240, 240) in b4: the specks in the wall, the flights, the ledger (was b3's teal). Lizards are drawn under the fog, seen only where lit, in duller greens (104, 168, 78) head and (58, 128, 60) body. Flowers: read as 1 in 4 ash discs (flowers.per 4) grows one flower (D108 had 1 per 24 px of ash).
D1102026-09-28p11activeA dimmer network (user: "reduce bulb and network brightness, it outshines the whole map. only pulsate a bulb, when the player is inside it"). Roots (120, 64, 24) and (96, 50, 20), was (214, 118, 36) and (176, 86, 26); still bulbs dim, r 2, (128, 70, 26) with a (94, 50, 18) rim; one you can build from keeps a dim core (168, 110, 52), one only on a built root has none. Only the bulb holding the bot beats (r 3–4) in D103's bright colours.
D1092026-09-28p11activeA bulb lets go after 3 s (user: "'engulf' is okay, but it is not possible to leave the bulb… direction buttons select the edge to build, and it starts to blink green. This is the current behavior and it is good. But the bulb should eject the player in 3 seconds after not building an edge"). Replaces D103's "do not release until a path is built": 3 s (ejectTicks 180) after it takes the bot with nothing built, the bulb lets go (event eject, the aim dropped); a direction still held walks the bot on; the same bulb doesn't take it again until it has left its 2 px reach.
D1082026-09-28p11activeBrighter fire; ash flowers that become network-building bots (user: "the fire and the ash-splash is awesome, I love it. Flames can be brighter, more colorful, add some particles. The ash should spawn white, large flowers, 1/24 area. After 2 minutes, the flower becomes a bot, similar to the player, but without light, and all the touching ash reverts to open air. The bot lives on the network, zips around, and when there's enough ore, but minimum 60s apart, randomly extends the network from its current position. After 3 extensions, it pops into non-existence in a white particle puff"). Asked, the user chose: 1 flower per 24 px of a disc's ash; a new bot zips straight to the nearest node on a built root (the pod's before any), through rock; it spends your ledger's ore. Built: a pixel burns 4 fire steps (0.4 s), drawn over the fog in 7 colours from white-yellow to magenta by age, flickering, with rising sparks; flowers (5 px, white petals, yellow heart, over the fog) placed once a disc's fire is out, 5 px apart; at 2 min: a lilac-white bot pixel with no halo, the 8-connected ash round the flower cleared, a white puff; on the network it rests 0.5–1.5 s a node, zips 60 px/s along a random built root, and at a node with an unbuilt edge, with the price on the ledger and 60 s since its last, builds a random one (1 in 2 stops); after 3 it pops in a white puff. Knobs garden.burnFor, flowers.*. Seen: a whole burned cave gives about 30 flowers, so about 30 bots bloom at once and spend ore fast.
D1072026-09-28p11activeTravel along the roots, bulbs on the built nodes (user: "the network looks cool, but I still need to travel... when I said no carts, I meant, no blocky vehicles travelling on the edges. Keep the bulbs visible, where nodes are built, just not pulsating"). b4.22 boarded only on the node's own pixel, and built nodes showed nothing unless buildable. Now: pointing along a built root (within 67.5°, as at a node while riding) within nodeReach 2 px of one of its nodes rides it, the bot glides along it; this comes before the engulf, so riding into a buildable node carries on. A node on a built root always shows a still bulb; a node that can be built from beats (D103).
D1062026-09-28p11activeLichen grows where the bugs' cover is large (user: "change lichen spawn criteria - it is triggered by large area of vine-cover"), no longer by loot (D096). Claude's numbers: 150 px of cover (green, vine, fruit) within 12 px of the tried spot (knobs lichen.density, radius); the rest as D096. Measured over 20 simulated minutes with 4 or 10 bugs at work (seeds 1–3, the bot still): the first lichen at 0.7–2.2 min, and it sparks (D102) within about 15 s, since it now always sits in cover; 2–5 lichens and fires each.
D1052026-09-28p11activeLizards don't spawn in small enclosures (user): the spawn pixel's cave must hold lizards.room 400 open px (8-way flood). On seeds 1–3 that rules out about 80% of the caves by count (median cave ~100 px), a small share of the open area.
D1042026-09-28p11activeThe scan fires on touch (user: "bot seismic pulse should activate immediately on wall touch, no need to wait"): at the rock pixel touched, the tick the bot touches it, also while sliding along the wall (before, only when fully stuck); scan.cooldown 0 (was 1 s). It still fires only if something within its radius is unseen (D086).
D1032026-09-28p11activeRoots and bulbs, not a metro map (user: "I do not like the node network look and UX. Drop the metro map look, use the eased grid to make it look like a wiggly orange root, keep the pixelated look consistent with everything. Also, do not show the node until the ledger has enough ore to build any edge in it. And then if the bot gets 2px close, engulf the bot, and do not release until a path is built. The node should be a pulsating orange bulb still pixelated"; then "no cart on the network, just the bulbs"). Asked, the user chose: routes walk the relaxed quad mesh's edges; engulfed, a drag aims and a tap builds; the price stays flat and isn't shown. Built: v8's mode A pairs routed by A* over the caves' mesh (roots.js: rock ×5, an earlier root's edges ×2, its vertices +40 px, other nodes closed); roots drawn 1 px, two oranges; a node shows only while the ledger holds the price and it has an unbuilt edge, as a pixel bulb of r 2–3 (3–4 holding the bot) beating; within nodeReach 2 px it holds the bot on its pixel (moves ignored) until a build, then lets go and doesn't take it again until the bot has left its reach; while held, its unbuilt edges show faint and the aimed one flashes green. No carts: stepping onto the end of a built root boards it and the bot glides along.
D1022026-09-28p11activeLichen sparks fire (user: "lichen should sometimes spark an ember that eats through the bug-induced vine cover, leaving round r=3-5 ash patches about 8-12 tiles apart. lichen leaf withers, will not spark again, purple surface stays"). Asked, the user: the fire spreads "how fire does… any vine touching vine catches flame, and it spreads through the entire green cover like a cell automaton. it leaves empty open air and the ash patches"; ash is permanent ("we will find a function for it, should enrich the environment"); only a lichen with cover near it sparks. Built: a lichen with cover (green, vine, fruit) within 2 px sparks at 1 in 6 of its checks (every 5 s); the fire spreads 8-way, 1 px every 0.1 s, and burned pixels go back to bare wall (bugs can green them again). Where a pixel catches with no ash centre within 8–12 px, it becomes one: a disc of r 3–5 whose bare wall turns to ash at once and whose cover burns to ash. Ash stays; bugs and vines skip it. The leaf withers brown; the purple patch stays. Knobs: garden.burnTicks, ash/ashMax, ashGap/ashGapMax, lichen.spark, touch.
D1012026-09-28p11activeLizards get to retire (user, after b4.19: "lizards are stuck, because they do not reach far enough"; asked for a higher spawn requirement). A lizard spawns only with 24 ore it can mine (within its 3 px reach of a cave surface) within 16 px, 1.5× its 16 (was 16 ore of any depth within 8). Measured, that alone didn't help (20 simulated minutes on seeds 1–3: 1 of 20 retired): they stalled 3–11 px from reachable ore, snagged on the cave's shape. So, Claude's call: at each zip a lizard floods the surface up to 32 steps and follows the route to the nearest spot with ore in reach, and stays put while ore is in reach. Then 163 of 176 retired (about 2–4 loot a minute near the bot).
D1002026-09-28p11activeThe lichen's leaf is pixels, like everything else (user: "lichen is not pixelated… it should be"; D096 drew it as a smooth curve): up to 4 world pixels in the air from the patch's first pixel, 2 out from the rock (the nearest of 8 ways), then curling to a side; it stops at rock.
D0992026-09-28p11activeSoft and hard rock are much darker (user, after b4.17): soft (40, 30, 24), hard (22, 23, 28), was b3's (92, 70, 54) and (52, 54, 66); darker than the cave's grey-blue back wall (D097). b4 only.
D0982026-09-28p11activeThe world generates with no loot; only lizards make it (user, after b4.16). The world.loot knob stays on the panel (default 0).
D0972026-09-28p11activeThe cave's back wall (open pixels) is dark grey-blue, (36, 44, 62), not b3's near-black (8, 8, 12), so an explored cave doesn't read as unexplored (user, after b4.15). b4 only; b3 keeps its palette.
D0962026-09-28p11activeAfter b4.14 (user): loot works for the bot as fruit does for the bugs: spent by itself at 16, 32, 64…; each upgrade (bot or bugs) makes the mining radius and speed 20% bigger; the bot shows on the ledger (a bot icon per upgrade, loot as count/target); plentiful loot spawns purple lichen covering 6–8 pixels of cave wall, growing a single curly short leaf. Claude's calls: the 20% compounds (×1.2 a level) and also replaces b4.13's +1 px for the bugs; the bot's mining radius starts at 8 px but the light stays 8 px; lichen is decoration only (it takes no loot and gives nothing); a patch starts like a lizard spawn (a random pixel within 64 px of the bot with 8 loot within 8 px), on the nearest surface pixel with no lichen within 10 px, grows at random along the surface; the leaf curls out of the wall from the patch's first pixel, drawn under the fog. Knobs sim.lichen.*, sim.botUpgradeCost, sim.upgradeGain.
D0952026-09-28p11activeAfter b4.13 (user): taming a bug releases heart particles; plentiful ore spawns bright green lizards that zip-stop-zip round the cave surfaces mining ore, and after 16 burrow and make one loot in the wall; ore and loot in the wall are specks in the soft or hard rock, not whole pixels. Claude's calls: every 5 s a random pixel within 64 px of the bot with 16 ore within 8 px spawns a lizard on the nearest surface pixel (open, next to solid), 6 at most; a zip is 4–12 px at 20 px/s toward the nearest ore within 16 px, a stop 0.7–2 s mining an ore within 3 px every 0.5 s; the loot goes to a rock pixel with no open one within 2 (the worms' site finder, 1 px); lizards drawn 3 px, over the fog. A speck is half a pixel across at a hashed spot in its pixel, drawn under the fog (only seen ones); the pixel itself is drawn as the rock round it. Six pink hearts rise from the tamed bug for 1.2 s. Knobs sim.lizards.*.
D0942026-09-28p11activeAfter b4.12 (user): no particles for the ore fed to wild bugs when taming; wild bugs look like tamed ones, only blue (drawn the same way, over the fog, so they no longer blink out in the dark); red fruit is spent by itself on the tamed bugs' reach, at 16, 32, 64… fruit, the next target shown on the ledger (fruit as count/target), and each upgrade adds another bug icon next to the first on the ledger's bug row. Claude's call: an upgrade adds 1 px of reach (4, 5, 6…; sim.swarm.upgradeReach, cost sim.swarm.upgradeCost).
D0932026-09-28p11activeYour pull goes for the resource the ledger holds least of (user): among ore, loot and fruit in reach, the kind with the lowest ledger count first, the nearest of it; if none of that kind is in reach, the next lowest (ties: ore, loot, fruit). Bugs keep taking the nearest.
D0922026-09-28p11activeFruit doesn't glow (user; replaces D089's glow): it's a red pixel in the world, seen when lit and dim when remembered, like ore. It's still harvested seen or not.
D0912026-09-28p11activeWorms (user, after b4.11): where red fruit is dense, dark red striped worms 12 px long appear; slower than bugs, they go from fruit to fruit; after eating 8 they burrow into the walls, never at the surface, curl up into an irregular 12 px shape wholly inside the wall, and become an ore deposit. Claude's calls (no pathfinding, like the bugs): every 5 s a random fruit with 6 fruit within 12 px spawns a worm there, 12 worms at most; 3 px/s; the head steps to the open neighbour nearest the nearest fruit within 24 px, else a random open one; the site is the nearest soft or hard rock pixel within 32 px with no open pixel within 2, grown at random into 12 pixels none bordering open (8-way); the worm goes straight there through the rock without carving it; it's drawn over the fog, so you see it burrow; the deposit is unseen until lit or scanned. Knobs sim.worms.*.
D0902026-09-28p11activeTamed bugs mine and pick fruit within 4 px, not 2 (user, after b4.10; sim.swarm.reach).
D0892026-09-28p11activeThe garden (user, after b4.9): tamed bugs turn the cave's back wall (open pixels) dark green where they pass; vines grow on green; 12 px of vine make 1 red fruit a minute; fruit is a resource on the ledger, collected by you and bugs like ore and loot. Fruit glows, and if it exists it can be harvested (user): your pull takes it within the light, seen or not; a bug takes it within reach whether you were ever near. A bug holds 8 fruit at most, returned to the ledger at its trip's end (user). Claude's calls, the user saying "keep it simple": a bug greens its pixel and the 4 next to it (green is for good); 1 in 40 pixels turning green starts a vine anywhere on green; a vine's tip grows 1 px every 5 s into green, 8-way, keeping its heading 2 times in 3, and stops with no green round it; fruit appears on a random vine pixel with none (the rate as an accumulator), stays until picked; the nearest unit wins, fruit or tile. All knobs sim.garden.*, sim.swarm.fruitCarry.
D0882026-09-28p11activeNode discovery (user, after b4.7; replaces D080's nodes near the bot showing): only the network's nodes ever show. The pod's glow until the first edge is built; from then on the network's are quieter (user: "easy to find, but should not overshine everything else"). Claude's calls: before the first edge, a pulsing ring with a soft halo (alpha 0.3); after, a thin ring at half opacity, no halo; the node held or selected still gets a small halo. Corrected after b4.8 (user: "the pod nodes are still visible after building the first network edge"): "the network" means the ends of built edges, so after the first edge a pod node with no built edge hides, and only a shown node can be built from (shipped as b4.9).
D0872026-09-27p11activeTamed bugs' trips last 30 s, not 2 min (user, after b4.6: "lifespan" = the trip; bugs stay on the ledger), and they collect ore and loot with your animation (user): the nearest unit within reach is a bug's target, the dust stream runs from it to the bug, and after pullTicks the unit comes out and flies to the bug on your arc, following it as it moves.
D0862026-09-27p11activeThe seismic scan triggers only if a hidden pixel is within its radius (user, after b4.5): pointing into rock with the scan ready fires it only when some rock or cave pixel within scan.radius of its centre is still unseen; the sheet, the sea and space don't count (the scan never shows them). Otherwise nothing happens and no cooldown starts.
D0852026-09-27p11activeThe bot mines while walking (user, after b4.4; D062's pull only ran standing still): the nearest seen ore or loot within the light is pulled whether the bot walks or stands, one unit every pull.ticks of something being in reach; not in a moving car (Claude's call). The pulled unit flies to where the bot is as it moves.
D0842026-09-27p11activeAfter b4.3 (user): the bot walks every angle for real, not 8 (b4.3's Bresenham steps kept the average angle but moved in 8-way steps on screen): it has a sub-pixel position that glides along the drag's exact angle at walkSpeed, its pixel is where that position is (open only), and into rock it slides on the move's x or y part alone; keys stay 8-way. Explored but unlit areas are 50% darker: 17.5% bright (fog alpha 0.825), was 35% (D052's dim).
D0832026-09-27p11activeb4.3 turns b4 incremental (user, after playing b4.2; plan timeline/p11-rail-loop/next-b4.3.md, the last sections win): one ledger in the top-right corner holds every collectible (ore, loot, bugs); no pack. Your mining goes straight to it (user: "no bot > ledger particle stream"). Building: tap a network node, drag to select an edge, release; the edge flashes green; tap it: the price comes off the ledger at once and ore streams from the ledger's icon to the site; short of ore, a red pulse (user). Wild bugs (b3.7's) nibble ore from the ledger and 16 fed tames one (D060, user), which leaves the world as +1 bug on the ledger. Tamed bugs are abstract (user: "no pathfinding, just random walk"): each works trips near random network nodes, random-walking through open air, pulling ore and loot within reach, and sends the haul to the ledger's icons at a trip's end. The light is a fixed 8 px (half of b4.2's; upgrades later), the pull's reach with it; line of sight, rock lit only 1 px deep (user). Nodes are never in rock: a grid vertex whose tile centre isn't open is no candidate (Claude's proposal; user: no fallback). Mid-build, the user: the bot walks any angle, not 8 ways, and the scan's cooldown is 1 s. Claude's calls: the pull's stream from the wall to the bot stays; a trip lasts 2 min, a bug pulls a unit a second at most within 2 px, seen or not; line of sight by Bresenham lines (either way clear) plus the rock 8-bordering the air in sight (a line alone misses flat walls at a grazing angle); the light's last 3 px fade out (drawing only); the selected edge shows its price.
D0822026-09-27p11activeb4.2 as built (Claude's calls, for the user's play): lit rock faces 4 px deep (b3's one-tile face at 1 px a tile); the light +1 px per 4 ore or 2 loot; nodes drawn as rings so they don't read as tamed bugs; the pack drawn at the top of the screen, not on the 1 px bot; the bug-placing hold is 1 s within 60 CSS px of the bot (E on a keyboard); the sheet and the space above it are never fogged, the sea is. b3.7's bug numbers kept as they are (D081), with seek and the others on the panel.
D0812026-09-27p11activeb4.2's world is all of v5's map (user), about 240 × 516 px from the sheet down to the ocean, not only the ice layer: the network C and the ore cover the whole depth. At the 1 px scale (D080) what matters is the intent, not D079's numbers (user): the rails are much faster than walking (about 7×; the numbers get tested as knobs), and the light and the node detection radius grow with the scale, "otherwise the player will not find them" (user).
D0802026-09-27p11activeb4.2's direction, after the user played b4.1 (plan: timeline/p11-rail-loop/next-b4.2.md): the bot is 1 px of v5's painted world (user: "I want to be a 1px character in a world drawn in v5. not a 1 tile character. 1px"), so a b4 tile is one v5 pixel, 4 to a fine cell; D075's 2-tile character doesn't apply to b4's spider bot. p10's network C stays. v6's ice sheet on top, solid (user). b3.7's bugs; placing one is a 1 s hold near the bot, when a bug is tamed (user). b3.7's ore layer and loot, and its hard/soft rock split for how it looks (user: "the visuals of that hard/soft rock was natural, I need that"); it wraps (user). No digging and no rock in the pack yet (user): the pack holds ore and loot, drawn as b3.7's. Unbuilt travel nodes show only within 3 tiles; nodes on the built network stay shown (Claude's proposal, user: yes). Edges are built only from the existing network (user). Walk 3 tiles/s and ride 20 tiles/s, to be tested (Claude's proposal, user: "sure, test it").
D0792026-09-27p11activeThe b4 Rail Loop, settled with the user before building (full loop in the p11 entry): b4 is not a copy of b3 (new generation: p7's quad caves + D078's lattice), reusing b3's probe, pull, pack, light and bugs. Empty pack at start; the pod is its interior open space only, no dome walls (they delete rock and ore); ore and loot from b3's CA ore layer over the quad rock. Drag / A W S D moves the bot through open tiles. Walking into rock scans at once, 3 s cooldown, radius 6; revealed ore in range is pulled by itself (the bugs' particles). A node glows within 3 tiles; a revealed node is close enough to build from. Build gesture on the node: hold = preview its edges (skippable); press and drag towards an edge = select, a red X and a green hammer appear (b3's cue style); release, tap the hammer = ore streams in, the edge and its travel pod get built, the far node is revealed. An edge costs 8–12 ore for now (tuned later). Walk onto the travel pod to get in; a swipe sets a rough direction and the pod runs node to node until it can't go on (stops at the last node), you tap (stops at the next node) or you swipe a new direction (turns at the next node). An edge needn't reach a new cavern, only room to mine the next edge's ore.
D0782026-09-27p10activeThe traverse node layer is v8 mode C (user: "this will be the traverse node layer"): nodes on the caves' relaxed-grid vertices in open air, the most open first, 3 cells apart; edges by the lune β-skeleton at links 1 (the Gabriel graph); each edge a monorail routed in the 8 directions on the tile grid, rock costing ×5 and bends 15 tiles per 45° (the user's settings, now the defaults), +100% for running along an earlier rail, a flat 100 tiles for crossing one.
D0772026-09-27p9activeTravel and interact (user): a vehicle travels the path with fast swipes; a spider-bot detaches, crawls everywhere (back wall, walls, ceilings) and builds (walls, gates, bridges); interacting is getting close, at worst a tap. Its shield drains from the environment and from moving; when empty, a visual warning and it returns to the chassis by itself (still casual). Free digging is out (phone-control UX). "Nothing vertical" (D068) applies to the vehicle path only. The back wall is visuals only.
D0762026-09-27p9activeWalls are 2 tiles thick, like the path (user: "for consistency"), and run in the 8 directions only (level, upright, 45°); where that is restrictive, a wall is built of 2 segments (user).
D0752026-09-27p9activeThe lattice restarts from a blank slate of tile definitions (user; concepts/callisto_lattice.md): space, solid, semi-solid (bridge, gate), void; the path (tiles the character moves through) is kept apart from the floor (the solid it walks on), and we map the path. The character is 2 tiles high, and so are dig tunnels and the path (user: "I accept the side effects, I want to lock in the 2 tile high char"); 1-tile passages are no longer path until dug (supersedes the 1-cell headroom of D072). A gate is an upright 2 × 1 semi-solid block in the path, solid directly above and below, open on both sides; it closes level and 45° paths alike. Walls are built solid straight lines, both ends on solid, at most 24 tiles (config).
D0742026-09-27p9activeThe lattice is shown as candidates, not as a chosen network (user: "a dense network of potential pathways (and walls), that the user can choose from"; p8 drew what good choices would build). Candidates: p8's links, plus walls at waists. A build collapses what clashes with it: p8's D073 rule for links (natural floors count from the start), no wall within a cell of a wall, no airlock within a gap of another. Airlocks are plank-behaviour blocks (pass through, stand on), placed automatically where walls cross paths, and discouraged in close proximity (user).
D0732026-09-27p8activeBuilt links branch only when needed (user: "branch only when needed to, not before"; no X crossings; no paths "running in parallel 2 and 3 blocks from each other"): a link that crosses a chosen link, or runs within a storey of floor or a link going the same way for over 30% of its middle, is refused, unless nothing else reaches a floor. Walks got longer: detour median 1.63× → 2.09×.
D0722026-09-27p8activeA floor is any natural stretch the character crosses in one run (user), with 1 cell of headroom (user: the character fits). Cutoffs prefer removing rock to building walkway (user: "removal is preferred"). A floor piece running within ½ storey of a longer one for most of its length is left out (user: "only one path is needed"). Divergence points only at forks.
D0712026-09-27p8activeThe lattice pass is floors first, links second (user's four notes on seed 5512; OK'd): cavern floors are the nodes; tiny cutoffs (up to 3 cells, end to end) first join floor pieces into longer floors (user's tip); then a spanning tree of the cheapest links (sideways within ½ storey, 45° ramps that may carry on sideways) from the pod; then links are added while the walk from the pod to a floor is over 1.5× the straight line; divergence points only at forks and ends. Storeys no longer span the map: they're as long as the floors they chain (amends D068). Supersedes the storey lines of D069 and D070.
D0702026-09-27p8activeThe storey network grows up from the pod as well as down (user: "in early game, the player wants to manually collect a lot of materials, not picking up, what's above our head does not make any sense"): a second chain of ramps up, stopping when a ramp's foot has no headroom under the crust; an upper storey dips under the crust at 45° where it would break through. A storey merging into the one it came from now joins it at 45° (the dead ends were a bug).
D0692026-09-27p8activeThe storey pass is built (p8, v6.html) over p7's settled caves, per D068. Storey height 3 cells (user). The pod is a dome 8 + 2 wide and 4 + 1 high that cuts into the ceiling and may sink up to 2 cells into a floor that rises under it (user: "cavern floor is not expected to be THAT flat and level"); placed on natural floor near the centre, in the ice under the crust, on every seed. Claude's calls while building: storeys follow floors column by column with a 45° smoothing pass; walkable floor needs 2 cells of headroom; floors under 2 cells aren't followed; one ramp per storey, a storey ± ½ long, within 15 cells of the storey's start, landing on floor; merged columns are dropped; the pod searches the central sixth first. Measured: 26% of storey length on floor, 36% bridge, 38% tunnel.
D0682026-09-27p7activeThe navigation lattice is storeys (user: "humans think in storeys"): mostly horizontal paths across several caverns, linked by single 45° ramps; nothing vertical ("vertical paths literally break the flow"), so no ladders or shafts. A storey follows cavern floors: if walkable floor in the next cavern is within ~½ storey of its Y in the cavern before, it takes that Y, otherwise it crosses as a bridge or tunnel ("we want to run on cavern floors whenever it's possible"). Divergence points are set by the target (where a link lands best), not the start. The network grows from a large pod underground (never the surface): storey 1 from the pod, each deeper storey from the foot of the ramp above. The pod sits right below the map's thin surface layer with a rugged ice sheet drawn on top (drawing only). Catwalks exist for prospecting ceilings from below. Vents have no pipes. No "go there" taps ("it kills the immersion"). Generation: storeys are a pass after the quad WFC (Claude; the WFC can't see "the Y one cavern before"), superseding "the lattice is WFC". Claude's defaults: storeys closer than ½ storey merge; storey 1 runs on the pod floor. Full text: concepts/callisto_design.md, Storeys.
D0672026-09-26p7activeThe caves come from a WFC on the small quads of a Townscaper-style grid, not on the hexes (user: the hex grid was "clearly visible, no amount of wobble fixes that"; then "build the WFC in the small 4-corner cells, not on the bounding hexes"). The pointy-top hexes stay as the base: each is cut into triangles (3 to a side), random neighbouring triangles in a hex pair into quads, every face is subdivided into quads, and the whole mesh is relaxed as one, so the big hexes bend too (user). A quad's tile is its 4 corners, open or rock, and neighbours agree on shared corners; weights by depth band and Markov affinities to collapsed neighbours; drawn by marching squares. The user: "looks like real caves, not game design". Claude's calls: the entropy order by a heap; saddles allowed but rare, so no contradictions; the quad knobs are their own set (QKNOBS); the hex-only corridor knobs have no quad equivalent yet. The hex WFC stays on the page as the other generator.
D0662026-09-26p7activeThe hex cave generator is built (p7, v5.html), per the p7 spec: WFC on pointy-top hexes, 16 × 32 wrapping horizontally, 3 sockets per side, 486 tiles generated by code from shape families, Markov-weighted pairing by class, depth bands as weights and materials (surface, ice, pudding, brine, ocean), a 160 × 291 fine grid with the socket band snapped and noise inside. Claude's changes while building, not discussed: each class keeps its whole base weight among the tiles still in the domain (otherwise open floods the map); a "rock grows" knob symmetric to "caves grow"; openness weighs solid against open only; noise about 2 cells, not 1; a pocket stays a tile though its sockets equal solid rock. Measured over 100 seeds: restarts median 2 (max 21, no failures), 70 ms median, 176 ms p90. The user judges the Question from the page.
D0652026-09-26—activeThe Callisto pivot (user's design session; nothing built yet; the design is in concepts/callisto_design.md, the world in callisto_lore.md, the element pool in callisto_elements.md). The setting is Callisto: a decaying human colony in the ice, isotope dust instead of ore veins, sleeping native life that blooms where dust is concentrated; the goal is Earth and Callisto ecosystems in natural balance, reclaiming the habitat "as part of nature". Bugs feed the hearth (placed bugs carry dust to their den themselves); the ecosystem self-balances through negative feedback loops, and the player designs the environment. For kids it's a pretty sandbox (pets, burning stuff down, like dan-ball's Powder Game); no numbers competition; swipes, taps and holds on phone, tablet and PC. Anything with a meaningful effect must be painfully obvious, and what can't be communicated very clearly is cut (input randomness yes, output randomness no); nothing people don't already know (clathrates become colourful gas bubbles in ice). 32 elements, a dense but not full graph, telling the ghost-town-to-alien-Eden story; collecting catalogue entries isn't the fun. The character stays with a bounded role: exploration, discovery, bridging systems; not terraforming or large-scale gathering. The hidden path lattice: divergence points and candidate paths generated from the terrain; choosing a path collapses the nearby options; runs don't stop between divergence points, and a command takes effect at the next one; buildable points show only on build intent (a hold, which finishes the run and shows the options toward the pointer, or arriving at a graph endpoint); ghost, then tap, and the character builds the whole structure; every structure can be reverted. Every placeable (hearth, airlock, air vent…) goes on a lattice point. The cavity is the simulation unit: air and skins are mixes of shares, plus heat, life and water per cavity; pixels only draw that state; tunnels are links with no state; no pressure, wind or field maps; an open link mixes x units per step, one airlock mixes a little only when the character walks through, two airlocks none; saves hold causes (seed, edits, cavity states), not pixels. Cavities split only at lattice waists and merge on revert (user: "okay"). Keep simple ("all models are wrong, but some are useful"). Next: a lattice generation prototype, then a lattice traversal, building and undo prototype. When built, this supersedes the swipe rule table (D028 onward), D046's flick/hold, D060's hold to place, D063's hand-over and D064's seeking bug.
D0642026-09-26p6activeThe TODOs after playing b3.6 (user's list; ruleset b3.7, the b3 default; next-bugs.md's eighth pass). The first to target an ore keeps it: you and placed bugs never pull the same cell; the others take their next nearest (user: "ok"). Reserved pack slots: 1 each for ore, loot, soft stone and hard stone, the other 2 free for anything (user: "1-1 for ore, loot, soft stone, hard stone, the rest is ffa"); a unit goes to its reserved slot first, a full one overflows into the free ones, and units are taken from the last slot, so the free ones empty first (packReserve). You leave home with 8 stone, every time (homeStone): banking tops the pack back up to 8, the 8 don't count as brought, and walking home with just them logs no dive. Taming progress fills the bar's next free slot as a 4×4 grid of ore, 1 cell per bite, like a pack slot (user: "perfect"). A placed bug whose area has run out (it has pulled, and no seen ore is left within its reach) comes to you through the caves, hands its ore over and goes back into the bar (user: "seeks: yes"); only when a bar slot is wholly empty, taming not even started in it (user, while it was being built: "tamed bug with no ore to mine left only seeks out char if 1+ bug slots are completely empty (not even taming started)"); otherwise it stays where it was placed. Its slot is held for it on the way, so no taming takes it. Claude's defaults, shown to the user with no objection: the 8 are soft stone; "run out" means no seen ore left within reach; a returning bug moves like a chaser down the field at the bar bugs' catch-up pace (6 ticks a cell), waits at its den while you're beyond the field (20 steps of open cave), jumps to you if the field loses it on the way, and joins the bar once it's empty and within the hand-over's 4 tiles (with your pack full it follows you until it can hand over).
D0632026-09-26p6activePlaced bugs mine, and the dust stream (session 3, second part; ruleset b3.6, the b3 default; planned in next-bugs.md's seventh pass, OK'd by the user: "a: ok", "2: R=4"). A placed bug pulls ore like you do (D062): the nearest seen ore within 12 of its den, through the wall, and the cell turns to the rock round it; ore only, loot stays yours to pull; 4 a minute (1 per 900 ticks). It carries 8; full, it stops pulling and waits, its halo swelling slowly. Hand-over (user: R = 4): you within 4 tiles (straight distance) of a placed bug with ore take it, one unit every 6 ticks, without stopping; with your pack full, it waits. The dust stream (user's addition): while a pull is under way, a thin trickle of specks in the material's colour flows along a slight arc from the cell that goes to the puller (you, from 0.5 s after you stop, so short stops don't flicker it; or a placed bug whenever it's pulling); none with nothing in reach, a full bug, or while you move. The sim keeps the target (g.pulling, bug.target), picked by the pull's own code, so the stream points at the cell that goes; the dust is drawing only, from time, on screen only. The existing flight shows each unit: wall → bug on a bug's pull (quiet, since it may be far off), bug → you on a hand-over (a soft tick). Claude's calls, not discussed: the numbers live in numbers.bugs.mine (ticks, reach, carry, hand, handTicks), so older rulesets' placed bugs only hover; a bug counts its 900 ticks only while it has a target, and a hand-over comes before its pull in a tick; the specks flow at 3 tiles/s, 3 per tile of stream. Refrozen after play (user: "the bugs particle stream is doing some back-and-forth movement, whereas the char stream is perfect"): a bug's stream ends at the middle of its bob, not at the bobbing dot, so the arc holds still. A way to take a placed bug back is still a TODO.
D0622026-09-26p6activePulling, and the bar calms the chasers (user's design, session 3; ruleset b3.5, the b3 default). Mining single ore cells by hand fights the "tidy, regular hallways" goal, since the controls follow loose intent. So standing still, you pull ore and loot out of the walls the way placed bugs will: 1 unit every 5 s, and the cell turns to rock, so no gap is left. Each tamed bug in the bar keeps one wild chaser away, so you can collect in peace: chasers = 3 − bugs in the bar, and the bar has 3 slots (user), so a full bar leaves you alone. Bar bugs roam round you like normal bugs instead of circling (user: circling is annoying). Claude's defaults, OK'd by the user: you pull seen ore or loot within your light radius (straight distance, through the wall, so buried ore a probe showed counts), the nearest first (ties to the lowest cell index); still means no step and no run, or a probe in progress; any move restarts the 5 s; with no room for it, a cell is skipped for the nearest one that fits; the cell becomes the most common rock among its 8 neighbours (soft on a tie or none); the ore flight (wall → you) in the material's colour is the only cue; manual mining is unchanged. Roaming, revised twice after play. First (user: the bugs were hysterical, their speed, random walk and need to stay close annoying; keep some distance, add inertia so they're not fizzing like gas molecules) Claude kept them 2 to 5 steps off with pauses, which jittered: a pause snapped the drawing back a cell (a bug, fixed). Then the user: fly 2 to 8 from the character, deprioritise 180° turns and 1-step runs. Now a bar bug keeps 2 to 8 field steps from you, a step every 12 ticks, twice as fast while catching up, and never pauses. It keeps its heading: a voluntary turn 1 step in 6, only after 2 steps straight. A turn it must make takes, by preference: a side turn with room for 2 steps, any side turn, straight back with room for 2, then straight back. Outside the field (a long fall, more than 20 steps) it jumps to your cell. It lights from its own cell. Wild bugs are unchanged. Over the cap, the farthest chasers stop chasing. The pull code (pull.js) is shared with step 3's placed bugs.
D0612026-09-26p6activeWild bugs live in the fog (user's design after playing b3.3; ruleset b3.4, the b3 default). The world is cut into fixed 32×32-tile blocks (x wraps like the world; today's 384×71 world is 12×3 blocks, the last row 7 tall). The 64 blocks nearest you (by their centres) each hold 1 wild bug, in a dark open cave cell of the block: not lit now, not within 12 of a placed bug, at least 4 steps from you. Blocks beyond the nearest 64 lose theirs. The bugs live in the sim, so they're deterministic. At most 3 come for your ore at once, as in b3.3. Only bugs on screen are drawn, so zoom decides how many you see. Wild bugs go between a flicker of 3–5 s and dark for 5–9 s, each length drawn anew per cycle, so they aren't constantly visible; their R 2 light follows the flicker. The shared taming count, the bar, the hold and placed bugs are unchanged (D060). This replaces b3.3's spawning near you (max, spawnTicks, despawn). Claude's defaults, shown to the user with no objection: a block whose bug is tamed or gone gets a new one 5 s later, at a random dark cell of the block; wanderers drift around the open cells of their own block and never leave it, so they can sit in caves sealed off by rock and hint at them; the chasers are the nearest wanderers that can reach you through open cave within 20 steps; a chaser still counts as its block's bug (no refill while it's out); the flicker fades in over 0.5 s, flickers irregularly at 60–100%, and fades out; dark means no dot and no light; a bug next to you glows steadily, a scared one flickers fast, tamed ones glow steadily; the blink timings come from a hash of the bug's id and its cycle number, in drawing only. Claude's calls, not discussed: a block with no dark cell tries again 5 s later; a chaser the field lost wanders again if it's back in its block, and is gone otherwise (its block refills 5 s later); only chasers nibble; the numbers are block, blocks, chasers, refillTicks and near.
D0602026-09-26p6activeThe tamed side, redesigned after playing b3.2 (user's design; ruleset b3.3, the b3 default). Several wild bugs split the nibbles, so none got to 16. Now every nibble by any wild bug counts toward one shared total; at 16, the bug that took the last bite is tamed, and the count restarts. A tamed bug goes into the bug bar: b1.1's row of slots along the bottom edge is back, 4 slots, filled from slot 1, drawn amber (the backpack stays on your back). With the bar full, nobody is tamed. A bar bug circles you and lights R = 2 like your light, seen for good; it doesn't mine. The 1 s hold is back (the charge ring at the finger): it places the bar's first bug at the open cell nearest to 2 above your head, and the bar shifts left; with an empty bar it does nothing. A placed bug is the mining utility, covering R = 12 (D056's den; it mines in step 3), keeps its R = 2 light, and no wild bug comes within 12 of it. Taking one back is a TODO. Wild bugs show everywhere, never-seen areas included, and light R = 2 like your light for the moment they blink on; that light never makes anything seen. This supersedes D059's per-bug count and taming on the spot, and D056's "tamed where it is" and wild bugs kept away from tamed bugs (now: from placed bugs). Claude's calls, not discussed: a bar bug circles in 12 cell steps two out, one step every 10 ticks, lighting from its cell when open, else from yours; placing looks up to 4 rings out; the hold's command is place (report code p); with the bar full, the count waits at 16; a placed bug plays a falling chime.
D0592026-09-26p6activeD056's wild bugs as built (ruleset b3.2, the b3 default), plus the user's addition: a tamed bug turns a warmer colour, so tamed and wild read apart at a glance (amber; wild ones are cool blue). Claude's calls, not discussed: a bug sits in an open cell (not the sky) and drifts one cell every 12 ticks (5 tiles/s, slower than your walk) down a flood through open cells, 20 steps deep, and stops next to you. Up to 3 wild bugs; one may appear every 5 s, in a cell you could reach, at least 4 steps away, not lit now, and never within 12 tiles of a tamed bug. Next to you (8 around), a wild bug nibbles 1 ore every 40 ticks, from the last ore slot: an ore flies from the pack into it and a heart pops. The 16th tames it on the spot, which is its den. A probe ring that passes a wild bug scares it for 4 s: it drifts away from you and doesn't nibble. A wild bug caught inside a new den area drifts out and doesn't nibble there. One the flood lost wanders, and it's gone past 28 tiles. Wild bugs blink like fireflies (1.4 s on, then dark), steady next to you and flickering while scared; tamed ones glow steadily. Tamed bugs stay at their den until step 3. The ore flight and the hearts stay on with the juice off, since they show where your ore went.
D0582026-09-26p6activeD055 as built (ruleset b3.1, the b3 default). ↓ on a floor is the meaning probeBelow and ↑ into rock is probeAbove: the probe's rings spread from the block under or above you, with the same reach, and the ceiling stays rock. Ring 1 now holds the centre cell too (your own cell before, already lit, so b2.1 plays the same). The number teleport: false turns the teleport off: the command does nothing, and a deep fall lands with the stop fell. Claude's calls, not discussed: stepping onto the home cell with anything in the pack counts it in and logs the dive (the dive log shows, the light goes back to base); walking past home with an empty pack logs nothing. Home is drawn as a plain orange pod, 2 tiles wide, on the home cell, since you now walk back to it. In b3 a long press does nothing (no ring), and Numpad 5 is a tap only (stop).
D0572026-09-25p6activeNot built yet. The friendly area (user's design): a tamed bug's area becomes friendly. It's a bit more lit, the walls get mossy, bulbs and red grass grow on the floor, and glowing lichen grows on the ceiling, drawn as basic as the character ("do not complicate it"). Claude's proposal, accepted: it covers the 12-tile radius, open cells and the rock faces bordering them; the lichen is its light, dim but lasting, between seen and lit; each cell's decoration comes from a hash of its position; it spreads out in a ring over a couple of seconds after taming; it marks where wild bugs never come. Claude's defaults: the whole radius, not only seen cells; tunnels dug later get decorated; overlapping areas merge.
D0562026-09-25p6activeNot built yet. Moon bugs (user's design). They're like fireflies: no physics, dim lights that blink in and out; they don't burrow, and they ignore planks. Wild bugs appear in the dark, never inside a tamed area, drift toward your glow and nibble ore from your pack, never loot, popping little hearts. The probe shoos them off for a few seconds. One that has eaten 16 ore is tamed. Tamed bugs work within 12 tiles of where they were tamed. They suck any seen ore in range (buried and hard rock included) through the wall at 4 a minute, carry 8, and the ore's cell becomes rock (the rock it was generated from, else its neighbours' most common). One simple particle effect shows every ore transfer: wall → bug, pack → wild bug, bug → you. You run past, and a bug's ore flies into your pack when you're close, without interrupting you; with a full pack, it keeps glowing. Offline: up to 32 ore per bug per 24 h, left in piles at the base, once saving exists (a later step, browser or portal storage).
D0552026-09-25p6activeNot built yet. The probe (user's design): it's centred on the probed block, not on you. ↓ probes around the block under you, and ↑ into rock probes the ceiling around the block above, with the same reach (replacing D043's mine-above). You build planks to reach a ceiling. The teleport home goes, and a deep fall just lands, with no damage (Claude's default for D035/D036, casual). When built, this changes D053 and supersedes D043's ↑-into-rock and D035/D036's teleport.
D0542026-09-25p5activeThe theme pivots after playing b2.1 (user's call). Swipes make tunnelling and exploring easy, but mining by hand is messy, so tamed moon bugs do the mining while you explore, prospect and build the tunnel network. Bugs are cute annoyances and are never killed. Nothing teleports you home: walking home with the loot, through your own tunnels, is the triumph. The 1 s hold is kept for outposts (TODO). Ore and loot have no use yet, on purpose ("a gaping hole there is perfect"); PvP uses come later (King of Thieves-style). This pulls Bundle 3's idle production into Bundle 2, away from the vault and raid path. p6 builds it as b3, forked from b2.1. The design is in p5-darkness/next-bugs.md.
D0532026-09-25p5activeThe seismic probe (user's design). ↓ while standing on anything but a plank reveals everything around you, rock interiors too, for good, in growing concentric rings. A flick probe reaches light + 2; a held probe keeps growing until light + 4, reached at 0.7 s (about 5 ticks per ring, Claude's), or until released, and it always reaches light + 2. A probe that started always ends; a tap doesn't cut it (user: don't complicate it). The character stands still while the rings spread: the probe's cost until noise and bugs exist (Claude's proposal, accepted). At a ledge edge, ↓ still climbs down over the ledge (the ledge wins, accepted).
D0522026-09-25p5activeSeen and lit (Claude's proposal, accepted): what the light or a probe revealed stays seen for good, drawn at about 35% brightness; what's lit now is full brightness; what was never seen is black. The lit edge is hard, whole tiles (user: fine for a prototype).
D0512026-09-25p5activeLight (user's design): a radius of 4 tiles, plus floor(ore / 16 + loot / 8) from what's in the pack (the sum is Claude's, accepted), so it resets when the pack is emptied at home. It shows surfaces only: it spreads through open cells within the radius and lights them and the rock faces bordering them (through air, Claude's proposal, accepted). The surface is always lit.
D0502026-09-25p5activeZoom (user's call): the view steps through fixed tile sizes, 10, 12, 14, 16, 17, 18, 20, 24, 30, 40 and 48 device px (the sizes where the backpack is drawn pixel-exact), with the mouse wheel and a two-finger pinch, centred on the character. Never the browser's or the OS's zoom. The default is more zoomed in than b1, since there's little to see at first (user): the size closest to 24 tiles across the screen's short side (the 24 is Claude's).
D0492026-09-25p5activep5 is b2 with one loadout (the Engineer) and the exploration mechanics only: darkness, light and the probe. No bugs, pets or idle play yet (user's call). p4 stays open and isn't called a success: the Rule Lab is a tool the tuning so far didn't need (user). b2 is a new bundle forked from b1.7; b1 stays as frozen.
D0482026-09-25p4activeThe hold check is 0.2 s, not 0.3 s (user's call, refines D046 and D047): at 0.3 s a held swipe walked 3 blocks before its first pause, since a walk step takes about 0.12 s; now it's 2. The same check covers hold+swipe, and the teleport ring now shows after 0.2 s of holding still and fills in 0.8 s (the teleport still fires at 1 s). The risk, accepted: a lazy flick whose finger stays down past 0.2 s becomes a hold.
D0472026-09-25p4activeFlick and hold as built (D046, ruleset b1.7). The teleport ring shows nothing for the first 0.3 s of holding still, then fills in 0.7 s, so a hold+swipe has 0.3 s with no confusing animation (user's call). Letting go of a hold cancels a dig or build in progress (nothing placed, no rock spent), while a move in progress finishes, so you always stop on a whole cell (user's correction of Claude's first reading, where the step always finished). Until the input says hold or release, a run takes the steps a flick and a hold agree on and waits where they differ, so the ramp mouth works; the cost is up to 0.3 s before a flick walks down a dip (Claude's proposal, accepted). A held run ignores the stop switches (wall, crossing and the rest), since every held step is already deliberate; the always-on stops still apply (Claude, accepted). It ships as b1.7, a new feature (Claude, accepted). Claude's calls, not discussed: a flick walks up a step you could walk up on any run, so a tunnelling run no longer stays level through one (D042's "a tunnelling run keeps level"); a flick that only a hold could continue stops with "?" (reason hold), never red; with keys, the keys down give the direction and letting go of one doesn't change it; a held run pauses holdPauseTicks (18) after each step. Examples take "hold": n (held for n steps, then let go).
D0462026-09-25p4activeNot built yet (next session). Flick and hold (user's design; the timing and input details proposed by Claude and accepted). A flick follows the world: it walks the terrain, tunnels into walls, and walks up and down steps and ramps. It never builds and never digs a step you could walk up; where it would have to, the run stops ("?"). A hold draws a straight line: it keeps the swipe's exact direction and height, lays a plank where the floor is missing (a 1-deep ramp mouth too) and digs a step in the way. It takes a step, pauses 0.3 s, and stops when released, always after a whole step. Nothing asks for confirmation any more. Building is a high-value precision action you don't do often, so holding feels like control, not a chore (user). A hold is a finger still down 0.3 s after the swipe registers. Walking and tunnelling start at once; a building or step-digging step waits for that moment, so the shortest hold is exactly one step. Hold+swipe is the same intent as swipe+hold. The teleport long press goes from 0.7 s to 1 s. Keyboard: tap = flick, held = hold, for every key (WASD no longer walks while held). The controls are unusual, on PC especially, so they need a tutorial (TODO). From a screenshot: there was no way to bridge over the mouth of a down-ramp. When built, this supersedes D041 and D044.
D0452026-09-25p4activeThe crossing stop (the user's call, from a screenshot; the exact rule proposed by Claude and accepted). The only place two ways meet is where a plank path crosses yours; there's no natural crossing in the caves (user). A walking run stops in front of the first cell under a plank, so → (walk on under it) and ↗ (climb onto it) are both one swipe away. Walking on under a row of planks doesn't stop again. It's the stop switch crossing, on in b1.6 (example plank-crossing-stop).
D0442026-09-25p4superseded by D046A yes covers only what it was asked for (the user's bug report, tick 3900; the fix proposed by Claude and accepted). It allows the kind of action it was asked about (dig or build), and only while the run keeps doing it; once the run does anything else, the next thing that asks, asks again. A 5-wide bridge still asks once. Before, a yes to dig a step also let the same run bridge a gap without asking (example dig-yes-not-build).
D0432026-09-25p4activeThe ceiling (user's design). ↑ into rock mines it and stays put. ↑ with a plank's tread just above your head (your cell holds one) climbs onto it (Claude read "a plank there" as this). ↑ into open air asks, then builds a plank ladder up. ↗ mines and stays only where the rock ahead-up has no floor under it (an overhang); with a wall under it, ↗ is a tunnel up as before (user's rule).
D0422026-09-25p4active→ and ↓ (b1.6). → never steps off a ledge: at a gap it asks to bridge, then lays a plank and walks on; ↓ is how you drop (user's call). A fresh → at the foot of a step you could walk up asks, then digs it; a run arriving there walks up it (Claude's proposal, user agreed: a fresh swipe is literal, a run follows the terrain). A tunnelling run keeps level through such steps (Claude). Clinging, → into open air still refuses (Claude). ↓ on a plank drops through it if the floor is within harmlessDrop, else asks and builds a plank ladder down, a rung per step, until the rest is a safe drop (user's call).
D0412026-09-25p4superseded by D046Asking first (user's design): a step that builds (a plank) or digs a step you could walk up doesn't happen straight away. The run stops, and the swipe disc blinks what it would do. The same swipe again does it; there's no timeout, so the player has time to learn it until it becomes a habit. Normal tunnelling into a wall 2 or more high never asks. Claude's calls, not discussed: any other command cancels the question; once confirmed, the whole run is confirmed (narrowed by D044); with no rock, a fresh swipe refuses at once (flash), while mid-run it asks first (D030). Holding a swipe will count as confirmation (precise mode, a TODO in input.js).
D0402026-09-25p4activeFewer stops (user's call): breaking out into open space, harder rock, ore and loot no longer stop a run; they felt unjustified in play. The junction stop (D024) goes too (Claude's proposal; the user didn't object). A run stops only before it starts changing the world in a new way (walking reaches rock: wall), to ask (D041), or on the always-on stops (ledge, floor, falls). Walking includes 1-tile steps up and down, so a bumpy floor never stops a run (Claude, after the user asked for a simple fix to stopping at every lump).
D0392026-09-25p4activeStairs are planks (refines D029; the user's stair, named "plank" by the user, the tread model proposed by Claude). A plank is a tread along the top of an open cell: you stand on it from the cell above, or walk through its cell under it. Nothing digs it, since moves pass through. Falls land on it, and it isn't a wall to cling to. Every build places a plank (user's call: all planks for now); solid Built stays for older rulesets. It fixes the tick-6659 crossing: ↗ lays a plank at the top of the ↘ tunnel, and the ↘ tunnel stays open under it (example plank-crossing). On a plank ramp, → follows the ramp you stand on; from the floor it walks under it (found in the examples, Claude). Ruleset b1.6 is the new default.
D0382026-09-25p4activeThe backpack (user's design): 6 slots of 16 units, drawn as a rectangle on the character's back, 2 slots wide by 3 tall. A slot is a 4×4 grid that fills row by row from the bottom, and slots fill in the same order. It mirrors with the facing, and one unit is 1/12 of a tile. All materials are collected, and a Built tile mines back to soft. A unit tops up the first slot of its material with room, else takes the first empty slot; slots keep their place. Building costs 1 rock per tile, soft before hard, never ore or loot (refusal noRock, which was noOre). With no room, rock is dropped and mining goes on, while ore and loot refuse (packFull). The bottom strip is gone. Ruleset b1.5 is the new default; migrate() upgrades older rulesets. Later: zoomed out, the pack scales up past the character's proportions to stay legible.
D0372026-09-25p4activeEvery playable version is on the timeline, at all times (user's call). Pushing a changed b1 freezes the next build (b1.N+1) onto the open entry's card with a tag. The pre-push check refuses an unfrozen b1 (R13), and npm run ship does the freeze and the push. A card can show several live-dev links (p4: the Rule Lab and b1).
D0362026-09-25p4activeA deep fall shows its way home (user's call): at the bottom, the character turns red and the teleport charge ring fills around it over 0.7 s, the long-press animation. Then it teleports home. The sim holds the character there for those ticks (42), so replays match.
D0352026-09-25p4activeClinging above a chasm, and gravity (ruleset b1.3, the new default). Any mining is allowed, even the wall you hold, with the standard mine, check, move. ↗ ↖ toward the wall you cling to works like standing (climb the step, or mine up into it); ↘ ↙ into rock mines like any ↘. Gravity: after each step, if nothing holds you (floor below, wall left or right), you fall straight down to the first floor. Deeper than harmlessDrop, you land, then teleport home (the pack is banked). This is a deliberate exception to D011: it follows a series of choices, not one wrong button.
D0342026-09-25p4activeThe stop cue is a plain "?" on the disc, in the run's direction, for every stop. A symbol plus a badge was too much to read in 0.6 s. The player wants to stay in the flow; the developer reads the exact trigger in the bug report.
D0332026-09-25p4superseded by D034Stops get the swipe cue too (user's call): when a run stops on its own, the disc appears in the run's direction showing what the next step would do (arrow, stairs or pickaxe), with a "?" badge. It's white, never red, because it isn't a refusal.
D0322026-09-25p4activeThe swipe cue (user's design): a small opaque white disc appears one step from the character in the swipe's direction (beside, above, below or diagonal) and shows the attempted action as a negative symbol: an arrow for a walk or climb, stairs for a build, a pickaxe for a dig. It fades out in 0.6 s. It's red when the attempt is refused. The red flash moves from the refused cells to the disc, and the backpack flash stays for now. It shows on a swipe's first outcome, and mid-run only for flash refusals.
D0312026-09-25p4activeBug reports remove the guesswork (user's call). The 🐞 button (bottom-left, key B) copies the last 5 swipes: the raw gesture, the intent, the ruleset row for each step, the stop and what it tried, the map where the last swipe started, a Rule Lab example, and a REPLAY line with every command and its tick. npm run replay reproduces the dive exactly and checks it. The raw gesture, replay and example parts were proposed by Claude and accepted.
D0302026-09-25p4activeA refusal for lack of ore or pack room (noOre, packFull) in the middle of a run gives way to the stop the run would have made anyway: it stops quietly, with no flash. It refuses (and flashes) only when the action would really have happened: on a fresh swipe, or when no stop rule catches it. Found from the first b1 report on the Rule Lab rules: ↗ up a staircase flashed red at the top.
D0292026-09-25p4superseded by D039Stairs (user's design): a normal block that the intent decides, walked through or climbed on, and some build or mine actions place one. It needs a per-intent tiles section in the ruleset and a new tile, so it comes after p4. p4 ships without stairs.
D0282026-09-25p4activeA dig ruleset is one JSON file with separate sections that refer to each other only by id: swipes (gesture → intent), situations (named all-of condition sets), the table (per intent, first match: situation → meaning), refusal signals, stops, numbers. The order is swipe > situation > meaning, because "ahead" is the swipe's side (proposed by Claude; the user asked for the separation and in-place validation, and didn't mind the order). Meanings are fixed code bundles that the table picks, so sequencing like "mine first, then look" never becomes data.
D0272026-09-25p3activeRefusals are visible: when an action can't happen, the game shows it, because everything that felt like a bug so far was a rule working as designed. First signal: no ore to build, or no pack room for loot → the tried cells and the backpack flash transparent red ("I tried, can't do").
D0262026-09-25p3activeThe next demo is p4 · Rule Lab (tool v4): movement and stop rules become a JSON ruleset with a visual editor, saved, exported and loaded like terrain recipes. b2 waits.
D0252026-09-25p3activep3 (b1 · Dig Feel) closes at b1.2 without the phone matrix. Its open assumptions and constraints carry over to the next dig playtest. A closed playtest records its rule table ("Rules at close").
D0242026-09-25p3activeThe junction stop fires only for a real side passage: a shaft with rock on both sides overhead. Walking out of a tunnel into an open cave takes the 1-tile step down and walks on. Mining that breaks into open space still stops (the open rule).
D0232026-09-25—activeBuild in public: the repo is public, and a push to main publishes. Every prototype is a timeline entry with frozen, playable builds.
D0222026-09-25p3activeJuice sits behind a master switch. Stop rules are judged with it off first.
D0212026-09-25p3activeNumpad 5 mirrors the taps: tap = stop, hold = teleport home.
D0202026-09-25p3activeMine first, then look: a mining step moves into the mined cell only if you can stand there.
D0192026-09-25p3activeNo digging straight down: the way down through rock is the diagonal staircase.
D0182026-09-25p3activeStep off by asking: swiping into a gap again drops you, if the floor is within harmlessDrop (4).
D0172026-09-25p3activeSwipes use pointer events and commit at a distance threshold. A swipe made mid-tile applies at the next tile boundary.
D0162026-09-25p3activeSurface strip of 4 sky rows + 3 crust rows, home at x = 0.
D0152026-09-25p3activeThe keyboard gets both models, numpad intents and held WASD, to A/B test.
D0142026-09-25p3activeEveryone is an Engineer in b1. The zipline is cut to b1.2, torchlight to b2.
D0132026-09-25—activeStack: plain JS ES modules with JSDoc types checked by tsc, no build step, Canvas2D, zero runtime dependencies. Every dependency needs a written justification.
D0122026-09-24—activeEvery game runs in portrait, landscape and square, with touch and with mouse / keyboard. b1 tests the whole matrix.
D0112026-09-24—activeCasual, not survival: no fall damage. A wrong move never ends a dive; if you're stuck, you teleport home.
D0102026-09-24—superseded by D018At a ledge, a swipe into the gap is an Engineer zipline.
D0092026-09-24—superseded by D010At a ledge, a swipe into the gap builds a bridge.
D0082026-09-24—superseded by D019Swiping down on open floor digs straight down.
D0072026-09-24—activeControls signal intent, not movement: swipe (or press a key) and the character moves until something changes. What a swipe does depends on the context.
D0062026-09-24—activeThe character is 1 tile tall and climbs 1-tile steps without stopping.
D0052026-09-24p2activeThe starter terrain is the archived seed-6712 recipe as v3 (caves, a reseeded soft / hard split, ore CA at 300 ‰, loot at 50 ‰). b1 digs in it.
D0042026-09-24p2activev2 CA Lab is frozen as the pattern-finding tool. New terrain ideas become a new tool version.
D0032026-09-24p1activeCA rules are edited with the keep / born / die toggle editor, never as text.
D0022026-09-24p1activeThe map is homogeneous for now: no top / bottom differentiation. Depth tiers come later.
D0012026-09-24p1activeTerrain is designed on one binary grid, step by step. Stacking many CA layers is dropped as the design method.