// Processing machines: the Refiner, the Stone cutter and the Silo. // ---------- Refiner ---------- // Grinding a grain of rock, gravel, sand or dirt turns up the odd grain of ore: [chance, what], // tried in turn. If none turns up, half the time a grain of fine sand comes out, else nothing: // the rest is ground to dust and washed away, so a refiner halves a pile of waste rock. const REFINE = []; REFINE[RSTONE] = [[0.025, CUORE], [0.02, COAL], [0.015, FEORE], [0.006, SNORE]]; REFINE[RGRAN] = [[0.02, FEORE], [0.012, ZNORE], [0.01, CUORE], [0.002, AGORE]]; REFINE[RBAS] = [[0.03, FEORE], [0.01, ZNORE], [0.003, AUORE]]; REFINE[GRAVEL] = [[0.03, FEORE], [0.02, CUORE], [0.01, SNORE], [0.003, ZNORE]]; REFINE[SAND] = [[0.01, SNORE], [0.008, FEORE], [0.0015, AUORE]]; REFINE[LDIRT] = [[0.08, LCLAY], [0.01, COAL], [0.008, CUORE], [0.003, ACORN]]; const REFINE_SAND = 0.5, REFINE_RATE = 0.5; // grains ground per tick // a free cell under the refiner's chute, or -1 if the way out is blocked function refinerSlot(mm) { const y = mm.y + 12; if (y >= H) return -1; for (const dx of [5, 6, 4, 7]) { const j = y * W + mm.x + dx; if (mat[j] === EMPTY && !part[j] && !occ[j] && !mach[j]) return j; } return -1; } function refinerTick(mm) { mm.work = (mm.work || 0) + REFINE_RATE; if (mm.work < 1) return; let jobs = Math.floor(mm.work); mm.work -= jobs; const y = mm.y + 9; mm.blocked = false; for (let k = 0; k < 8 && jobs > 0; k++) { const x = mm.x + 2 + ((k + tick) & 7), i = y * W + x, m = mat[i]; if (m === EMPTY || PH[m] === PH_GAS || PH[m] === PH_SOLID || stamp[i] === tickStamp) continue; const out = refinerSlot(mm); if (out < 0) { mm.blocked = true; break; } jobs--; mm.busyT = tick; const T = temp[i]; if (PH[m] === PH_POWDER && REFINE[m]) { setCell(i, EMPTY, AMB[y], 0); let got = 0; for (const [chance, o] of REFINE[m]) if (rnd() < chance) { got = o; break; } if (got) { stats.refinedOre = (stats.refinedOre || 0) + 1; discover(got, x, y, m, 'refine'); } else if (rnd() < REFINE_SAND) got = SAND; if (got) setCell(out, got, T, 0); stats.refined = (stats.refined || 0) + 1; } else { // ore, coal, liquids: nothing to grind, so they go straight through setCell(out, m, T, 0); setCell(i, EMPTY, AMB[y], 0); } } } // ---------- Stone cutter ---------- const CUT_PER_BRICK = 8, CUT_RATE = 0.5; function cutterTick(mm) { mm.work = (mm.work || 0) + CUT_RATE; if (mm.work < 1) return; let jobs = Math.floor(mm.work); mm.work -= jobs; const y = mm.y + 4; mm.blocked = false; for (let k = 0; k < 4 && jobs > 0; k++) { const x = mm.x + 2 + ((k + tick) & 3), i = y * W + x, m = mat[i]; if (m === EMPTY || PH[m] === PH_GAS || PH[m] === PH_SOLID || stamp[i] === tickStamp) continue; if (m === RSTONE) { if ((mm.cut || 0) + 1 >= CUT_PER_BRICK) { // a brick is ready: it needs room under the machine if (!entFreeAt(mm.x + 2, mm.y + 8)) { mm.blocked = true; break; } mm.cut = 0; const e = spawnBar(BARSB, mm.x + 2, mm.y + 8, (rnd() - 0.5) * 0.1, 0.05); if (e) { e.T = temp[i]; discover(BARSB, x, y, RSTONE, 'cut'); stats.bricks = (stats.bricks || 0) + 1; } } else mm.cut = (mm.cut || 0) + 1; setCell(i, EMPTY, AMB[y], 0); } else { // anything else drops through, out of the bottom const j = (mm.y + 8) * W + mm.x + 3 + (k & 1); if (mm.y + 8 >= H || mat[j] !== EMPTY || part[j] || occ[j]) { mm.blocked = true; break; } setCell(j, m, temp[i], 0); setCell(i, EMPTY, AMB[y], 0); } jobs--; mm.busyT = tick; } } // ---------- Silo ---------- // One loose material, counted (not simulated grain by grain inside): grains in the roof hatch // go in, and with the gate open they come out of the bottom of the cone. const SILO_CAP = 4000, SILO_RATE = 1; function siloTick(mm) { for (let dy = 0; dy < 2; dy++) for (let dx = 3; dx <= 8; dx++) { const i = (mm.y + dy) * W + mm.x + dx, m = mat[i]; if (PH[m] !== PH_POWDER || stamp[i] === tickStamp || (mm.sn > 0 && m !== mm.sm) || (mm.sn || 0) >= SILO_CAP) continue; mm.sm = m; mm.sn = (mm.sn || 0) + 1; mm.fillT = tick; setCell(i, EMPTY, AMB[mm.y + dy], 0); } if (mm.open && mm.sn > 0) { let put = 0; for (let k = 0; k < 4 && put < SILO_RATE && mm.sn > 0; k++) { const x = mm.x + 4 + ((k + tick) & 3), j = (mm.y + 23) * W + x; if (mat[j] !== EMPTY || occ[j]) continue; setCell(j, mm.sm, AMB[mm.y + 23], 0); mm.sn--; put++; mm.pourT = tick; } if (!mm.sn) mm.sm = 0; } } // a silo with something in it is emptied before it can be taken down function siloFull(mm) { return mm && mm.type === 'silo' && mm.sn > 0; }