import { grid, cols, rows } from './state.js'; import { config } from './config.js'; import { move, swap } from './actions.js'; import { createCell } from './physics.js'; export function updateLava(x, y, cell) { const dxs = [0, 0, -1, 1]; const dys = [-1, 1, 0, 0]; // Thermal interactions with neighbors for (let i = 0; i < 4; i++) { const nx = x + dxs[i]; const ny = y + dys[i]; if (nx >= 0 && nx < cols && ny >= 0 && ny < rows) { const neighbor = grid[nx][ny]; if (neighbor) { const nt = neighbor.type; if (nt === 'water') { // Boils water into steam, and lava cools into rock grid[nx][ny] = createCell('steam'); if (Math.random() < (config.lava?.coolingChance || 0.04)) { grid[x][y] = createCell('rock'); return; } } else if (nt === 'ice') { grid[nx][ny] = createCell('water'); } else if (nt === 'plant' || nt === 'grass' || nt === 'wood' || nt === 'oil') { grid[nx][ny] = createCell('fire'); } } } } // Occasional surface cooling into rock if (Math.random() < (config.lava?.coolingChance || 0.04) * 0.05) { grid[x][y] = createCell('rock'); return; } // Spontaneous smoke/spark above if (y > 0 && !grid[x][y - 1] && Math.random() < 0.003) { grid[x][y - 1] = createCell(Math.random() < 0.5 ? 'smoke' : 'fire'); } // 1. Straight fall const below = y + 1; if (below >= rows) return; const belowCell = grid[x][below]; if (!belowCell) { move(x, y, x, below); return; } // Lava is dense: sinks rapidly through water, oil, and acid if (belowCell.type === 'water') { const sinkRate = config.lava?.sinkChance !== undefined ? config.lava.sinkChance : 0.7; if (Math.random() < sinkRate) { // Plunge into the water and boil water into rising steam swap(x, y, x, below); if (Math.random() < 0.5) { grid[x][y] = createCell('steam'); } if (Math.random() < (config.lava?.coolingChance || 0.04)) { grid[x][below] = createCell('rock'); } return; } } else if (belowCell.type === 'oil' || belowCell.type === 'acid') { swap(x, y, x, below); return; } // 2. Diagonal fall const canDownLeft = x > 0 && (!grid[x - 1][below] || grid[x - 1][below].type === 'water'); const canDownRight = x < cols - 1 && (!grid[x + 1][below] || grid[x + 1][below].type === 'water'); if (canDownLeft && canDownRight) { const targetX = Math.random() < 0.5 ? x - 1 : x + 1; executeLavaStep(x, y, targetX, below); return; } else if (canDownLeft) { executeLavaStep(x, y, x - 1, below); return; } else if (canDownRight) { executeLavaStep(x, y, x + 1, below); return; } // 3. Horizontal dispersion const flowChance = config.lava?.flowChance !== undefined ? config.lava.flowChance : 0.4; if (Math.random() < flowChance) { const maxDisp = config.lava?.dispersion || 2; const dir = Math.random() < 0.5 ? 1 : -1; for (const d of [dir, -dir]) { let targetX = x; for (let step = 1; step <= maxDisp; step++) { const nx = x + d * step; if (nx < 0 || nx >= cols) break; const c = grid[nx][y]; if (!c) { targetX = nx; if (y + 1 < rows && !grid[nx][y + 1]) { targetX = nx; break; } } else if (c.type === 'water') { targetX = nx; break; } else { break; } } if (targetX !== x) { executeLavaStep(x, y, targetX, y); return; } } } } function executeLavaStep(x1, y1, x2, y2) { if (grid[x2][y2]) { if (grid[x2][y2].type === 'water') { grid[x2][y2] = createCell('steam'); } swap(x1, y1, x2, y2); } else { move(x1, y1, x2, y2); } }