// The notebook (N): milestones, market, wallet, blueprints, controls. // ---------- Notebook ---------- let nbTab = 'Ledger'; function openNotebook(tab) { if (tab) nbTab = tab; renderNotebook(); openModal('m-notebook'); } function renderNotebook() { const tabs = $('nb-tabs'); tabs.innerHTML = ''; for (const name of ['Ledger', 'Market', 'Materials', 'Pieces', 'Blueprints', 'Controls']) { const b = el('button', { role: 'tab', class: name === nbTab ? 'on' : '', 'aria-selected': name === nbTab }, name); b.onclick = () => { playSfx('ui'); nbTab = name; renderNotebook(); }; tabs.appendChild(b); } const body = $('nb-body'); if (nbTab === 'Ledger') { const done = MILESTONES.filter(m => ledger[m.id]).length; let h = `
${done} of ${MILESTONES.length} reached. There is no set order. Tips stay hidden until you ask for one. Upgrades come from what you make: your bit is as hard as the metal you cast it from.
Tools: ${esc(BIT_TIERS[player.bitTier].name)} (digs hardness ${BIT_TIERS[player.bitTier].hard} and below) · ${esc(TANK_TIERS[player.tankTier].name)} (${bagCap().toLocaleString('en-US')} grains)${player.lens ? ' · Thermal lens' : ''}${player.flask ? ' · Flask' : ''}
`; body.innerHTML = h; body.querySelectorAll('[data-tip]').forEach(b => b.onclick = () => { playSfx('ui'); GAME.tipsOpen.add(b.dataset.tip); renderNotebook(); }); } else if (nbTab === 'Market') { renderMarketTab(body); } else if (nbTab === 'Materials') { let rows = '', unknown = 0; const list = [DIRT, LDIRT, STONE, RSTONE, CLAY, LCLAY, WOOD, LWOOD, ACORN, CHARCOAL, SNOW, ICE, COALV, COAL, CUV, CUORE, FEV, FEORE, SAND, GRAVEL, GRANITE, RGRAN, BASALT, RBAS, BRICK, RBRICK, GLASS, CULLET, COPPER, SCRCU, BARCU, IRON, SCRFE, BARFE, STEEL, SCRST, BARST, ASH, SLAG, MSLAG, WATER, STEAM, MAGMA, MCU, MFE, MST, MGL, FIRE, SMOKE, SNV, SNORE, TIN, MSN, SCRSN, BARSN, ZNV, ZNORE, ZINC, MZN, SCRZN, BARZN, AGV, AGORE, SILVER, MAG, SCRAG, BARAG, AUV, AUORE, GOLD, MAU, SCRAU, BARAU, BRONZE, MBZ, SCRBZ, BARBZ, BRASS, MBS, SCRBS, BARBS]; for (const m of list) { if (!seen[m]) { unknown++; continue; } const d = MD[m]; const ph = ['', 'Solid', 'Loose', 'Liquid', 'Gas', 'Object'][d.ph]; const change = reactionsOf(m, true).map((t, k) => k ? t : t[0].toUpperCase() + t.slice(1)).join(' · '); rows += `What you have found so far. Hardness is what your drill bit has to match. Solid rock breaks into loose rubble that you vacuum up and build with.${unknown ? ` ${unknown} more to discover.` : ''}
| Material | State | Hard | What it does | Notes |
|---|
Everything you build snaps to a grid of 4×4-grain blocks. Pieces only move, hold, blow or sense material; every change to the material itself comes from heat. Select pieces with the Build tool (3). Hover a tile for its cost, full description and placement help. Your bot flies straight through anything you build.
The land is yours. Keep building: the ledger has bigger goals.
`; h += `Anything that drops through the trade dock's grate is sold on the spot, once it is cool enough to handle. Junk like dirt, rubble, ash and slag goes for nothing. Build walls around the dock to funnel more in.
`; h += `Orders · ${esc(STANDING[standing()])}
`; if (orders.length) { h += 'No open orders. Buyers post new ones every minute or two, for goods you have found.
`; h += `Goods dropped into the dock fill a matching order first. A missed deadline costs nothing: what you delivered is paid at market price. ${ordersDone} filled so far; bigger buyers come with more.
`; h += `Prices
Per grain, or per bar. Selling a lot of one thing lowers its price for a while; it recovers over about half an hour.
`; let rows = '', unknown = 0; for (const [g, list] of MARKET_GROUPS) { const known = list.filter(m => seen[m]); unknown += list.length - known.length; if (!known.length) continue; rows += `| Goods | Base | Now |
|---|
Find something worth selling first.
'; if (unknown) h += `${unknown} more goods to discover.
`; h += `Sales, minute by minute
`; const recent = saleAcc.total > 0 ? [{ total: saleAcc.total, items: saleAcc.items, now: true }].concat(shipLog) : shipLog; h += recent.length ? `Nothing sold yet.
'; body.innerHTML = h; body.querySelectorAll('[data-pay]').forEach(b => b.onclick = () => { const v = b.dataset.pay === 'all' ? money : +b.dataset.pay; const paid = payClaim(v); if (paid > 0) { playSfx('sale'); toast(`Paid ${fmtMoney(paid)} toward the claim.`); } renderNotebook(); hudDirty = true; }); } function fmtPrice(v) { return v >= 10 ? '$' + Math.round(v) : '$' + v.toFixed(2); } function itemsText(items) { const e = Object.entries(items).map(([m, n]) => [+m, n]).sort((a, b) => b[1] * PRICE[b[0]] - a[1] * PRICE[a[0]]); const parts = e.slice(0, 3).map(([m, n]) => PH[m] === PH_ITEM ? `${n} ${MD[m].name.toLowerCase()}${n === 1 ? '' : 's'}` : `${n} ${MD[m].name.toLowerCase()}`); if (e.length > 3) parts.push(`${e.length - 3} more`); return parts.join(', '); } function renderWallet() { $('w-money').textContent = fmtMoney(money); const c = $('w-claim'); c.className = 'line' + (debt <= 0 ? ' paid' : ''); c.innerHTML = debt > 0 ? `Claim owed${fmtMoney(debt)}` : `Claimpaid off ✓`; const h = orders.length ? orders.map(o => { const left = orderLeft(o); return `${o.got}/${esc(orderName(o))}${fmtClock(left)}`; }).join('') : 'No orders yet'; const box = $('w-orders'); if (box.innerHTML !== h) box.innerHTML = h; } function renderBlueprintTab(body) { const lib = libLoad(); let h = `Select the Blueprint tool (5), drag over something you built to copy it, then click to place a ghost. Your bot builds ghosts from the materials in your bag when it is within reach. Right-click clears ghosts.
`; h += `Starter designs
Optional. Tested builds to learn from or copy; place one as a ghost and your bot builds it from your bag. Clear the space first: ghosts wait for open air.
Your blueprints
'; h += `Library
`; if (!lib.length) h += `No saved blueprints yet.
`; else { h += 'Select the text and copy it.
`, [{ label: 'Done', cls: 'primary' }]); setTimeout(() => { const t = $('bp-out'); if (t) { t.focus(); t.select(); } }, 30); }; try { navigator.clipboard.writeText(code).then(done, fallback); } catch (e) { fallback(); } } function controlsHtml() { const kb = [ ['Fly', 'W A S D'], ['Boost while flying', 'Shift'], ['Tool modifier (while not flying)', 'Shift'], ['Use tool', 'Left mouse'], ['Second action', 'Right mouse'], ['Tools', '1 – 4'], ['Cycle what you blow · piece', 'Q / E'], ['Switch build tab', 'Shift + Q / E'], ['Variant: material · direction · flip', 'R'], ['Tick/untick what is under the cursor (Vacuum)', 'R or T'], ['Nozzle or brush size', '[ ] or Shift + wheel'], ['Replace what is built (Build)', 'Hold G'], ['Copy a box of what you built', 'Hold C, drag'], ['Cut a box (refunded, paste it back)', 'Hold X, drag'], ['Paste again', 'V'], ['Undo building', 'Ctrl + Z'], ['Blueprint library', 'B'], ['Zoom', 'Mouse wheel'], ['Interact (gates, molds, fans, filters)', 'F'], ['Thermal lens', 'H'], ['Info overlay: filters, belt and tube directions', 'I'], ['Bot lamp', 'L'], ['Pick the piece under the cursor (with its direction and settings)', 'Middle mouse'], ['Notebook', 'N'], ['Clear all blueprint ghosts', 'Delete'], ['Save', 'Ctrl + S'], ['Pause · menu', 'Esc'], ['Mute', 'M'], ]; const pad = [ ['Fly', 'Left stick'], ['Boost', 'Left stick pushed all the way'], ['Aim', 'Right stick'], ['Use tool · suck', 'RT'], ['Second action · blow', 'LT'], ['Tools', 'LB / RB'], ['Cycle what you blow · piece', 'D-pad ← →'], ['Brush size', 'D-pad ↑ ↓'], ['Interact', 'A'], ['Variant · tick material', 'X'], ['Thermal lens', 'Y'], ['Cancel', 'B'], ['Zoom', 'R3'], ['Lamp', 'L3'], ['Notebook', 'View / Back'], ['Menu', 'Menu / Start'], ]; const tools = [ ['1 Resonance drill', 'Hold left click to send pulses from the bot toward the cursor: rock they shake hard enough shatters and falls as rubble, ore, coal or scrap, and trees come apart into wood chunks and acorns. Q and E set the pulse width: narrow bores a tunnel fast, wide clears a big cone slowly, medium is in between. R over a material tunes the drill to it, so only that shatters (great for pulling a vein out of the rock); R again untunes. Built blocks are never harmed. Better bits dig harder rock, faster and further.'], ['2 Vacuum', 'Left click sucks up what you start on; if anything is ticked in your bag (R over it, or its tick box), it takes only the ticked materials instead. Hold Shift while not flying to take everything. Right click blows the chosen material out of the bot toward the cursor; Q and E choose it, and it stays chosen. Q and E (or clicking in your bag) can also pick Ticked mix, an even mix of everything ticked, which is how you charge a furnace. The swatches next to the cursor always show what right click will blow. R ticks or unticks what is under the cursor.'], ['3 Build', 'Places pieces on a grid of 4×4 blocks: wall blocks, belts, tubes, filters, grates, gates, pipes, pumps and outlets, machines (fans, the Refiner) and molds. Drag for a line, hold Shift while dragging for a filled rectangle. Right click takes a piece back. Your bot flies through anything you build.'], ['4 Igniter', 'Heats a small spot to 640°C, and its flame reaches a few grains into a pile. Enough to light coal and wood that touch air.'], ['Copy, cut and paste', 'Hold C (copy) or X (cut) and drag a box over what you built; let go and it is picked up, ready to paste. Cut takes it down and refunds it to your bag. Click to place ghosts: your bot builds them from your bag when it is close. R flips, V pastes again, right click or Esc stops. Ctrl+Z undoes building. The notebook (B) keeps saved blueprints and a few starter designs.'], ]; const tbl = rows => 'Tools
Keyboard and mouse
${tbl(kb)}Gamepad
${tbl(pad)}First steps
1. Drill down a little. Stone falls as rubble; coal (dark seams), copper ore (green speckles) and clay (reddish) come loose too.
2. With the Vacuum, click on coal to suck up only coal, then the copper ore, rubble and clay you want.
3. Build (3) a chamber of stone wall blocks with a one-block vent in the roof, a floor of clay Grates, and an Ingot mold right under the grates. The notebook's Blueprints tab has this as a starter design.
4. Tick coal and copper ore in your bag and pick Ticked mix (Q/E, or click it at the bottom of the bag). Fly inside (the bot passes through what you build) and right click to blow an even mix onto the grates: about 50 of each. (Ore first and coal on top works too; coal buried under ore will not light.) Light a coal grain on top with the Igniter.
5. When the ingot sets, bars drop out of the bottom of the mold onto whatever is under it. Leave one open block under it: a belt below that carries them off, or vacuum them up. Leftover metal stays for the next firing. F on the mold is optional: it cleans the trough, chips off slag and rakes the furnace grate. Scrap goes to your bag: throw it in with the next charge.
6. Blow the bars into the trade dock: they sell the moment they drop through its grate, and bars pay far more than ore. Watch the Market page for orders that pay double. Money buys belts, screw tubes and fans; pay down the claim there too.
7. From there: deeper ores (tin, zinc, silver, gold), alloys, fans for hotter fires, iron and steel.