// Throughput for the info overlay (t49): how many grains each belt, filter and screw conveyor // block hands on, per second of game time. Counting runs only while the overlay is on, so // normal play pays one flag check per carried grain. Bars are not counted. let flowOn = false, flowCount = new Uint16Array(0), flowRate = new Float32Array(0); function setFlowCounting(on) { flowOn = on; if (flowCount.length !== NB) { flowCount = new Uint16Array(NB); flowRate = new Float32Array(NB); } else if (!on) { flowCount.fill(0); flowRate.fill(0); } } // A grain left carrier block b across one of its edges. function flowNote(b) { if (b >= 0 && b < flowCount.length && flowCount[b] < 65535) flowCount[b]++; } // Count a move from cell a to cell j if it crosses into another column of blocks or row of blocks. function flowCross(b, a, j) { if (((a % W) >> 2) !== ((j % W) >> 2) || ((a / W) >> 2) !== ((j / W) >> 2)) flowNote(b); } // The sloped belt block carrying a grain at cell a: the slope under it in the same block column. function flowSlopeUnder(a) { const bx = (a % W) >> 2; for (let by = ((a / W) | 0) >> 2, k = 0; k < 3 && by < BH; k++, by++) if (isSlopeBelt(blockP[by * BW + bx])) return by * BW + bx; return -1; } // Once a second, fold the count into a smoothed rate. function flowTick() { if (flowCount.length !== NB) setFlowCounting(flowOn); if (tick % 60) return; for (let b = 0; b < NB; b++) { if (flowCount[b] || flowRate[b]) { flowRate[b] = flowRate[b] * 0.5 + flowCount[b] * 0.5; if (flowRate[b] < 0.05) flowRate[b] = 0; } } flowCount.fill(0); }