// Inspiration from halogen.js // --- Halogens and water-containing liquids --- var halogens = [ "fluorine", "liquid_fluorine", "fluorine_ice", "chlorine", "liquid_chlorine", "chlorine_ice", "bromine_ice", "bromine", "bromine_gas", "iodine", "liquid_iodine", "iodine_gas", "astatine", "molten_astatine", "astatine_gas", "tennessine" ]; var water_containing = [ "water", "dirty_water", "salt_water", "sugar_water", "seltzer", "pool_water", "primordial_soup", "nut_milk" ]; // --- Alkali metal hydroxide densities (kg/m³) --- const hydroxideDensities = { li: 1460, na: 2130, k: 2120, rb: 2350, cs: 2200, fr: 2400 }; // --- Normal alkali reaction with halogens --- function normalAlkali(pixel, reactto = "pop") { for (let i = 0; i < adjacentCoords.length; i++) { const x = pixel.x + adjacentCoords[i][0]; const y = pixel.y + adjacentCoords[i][1]; const otherPixel = getPixel(x, y); if (!isEmpty(x, y, true) && halogens.includes(otherPixel.element)) { if (Math.random() <= 0.1) { changePixel(pixel, "salt"); changePixel(otherPixel, reactto); } } } } function waterReaction(pixel, options = {}) { const { tempIncrease = 100, reactionChance = 0.05, effectType = "pop" } = options; if (!pixel) return; for (let i = 0; i < adjacentCoords.length; i++) { const x = pixel.x + adjacentCoords[i][0]; const y = pixel.y + adjacentCoords[i][1]; const otherPixel = getPixel(x, y); if (!otherPixel) continue; if (!isEmpty(x, y, true) && water_containing.includes(otherPixel.element)) { if (Math.random() <= reactionChance) { const rand = Math.random(); if (rand <= 0.33 && pixel && (pixel.element !== "explosion" || pixel.element !== "pop")) { if (effectType === "explosion") { deletePixel(pixel.x, pixel.y) explodeAt(pixel.x, pixel.y, 10) } else { changePixel(pixel, effectType); } } else if (rand <= 0.66) { // form hydroxide const hydroxide = pixel.symbol + "oh"; if (!elements[hydroxide]) { addElement(hydroxide, { color: "#dfefff", category: "compounds", behavior: behaviors.POWDER, state: "solid", density: hydroxideDensities[pixel.symbol] || 1500, tempHigh: 500, reactions: { "acid": { elem1: "water", elem2: "salt" } } }); } changePixel(pixel, hydroxide); deletePixel(otherPixel.x, otherPixel.y); } else { // produce hydrogen gas createPixel("hydrogen", otherPixel.x, otherPixel.y); } pixel.temp += tempIncrease; } } } } // Solid lithium elements.lithium = { color: "#bfbfbf", state: "solid", behavior: behaviors.POWDER, category: "alkali", tempHigh: 180.5, density: 533, conduct: 0.42, reactions: { "chlorine": { elem1: "salt", elem2: "pop" }, "vinegar": { elem1: "sodium_acetate", elem2: [null, null, null, "hydrogen"], attr1: { "foam": 15 } }, "water": { elem1: ["pop", "pop", "pop", "hydrogen", "lioh"], chance: 0.01, temp2: 200 }, "salt_water": { elem1: ["pop", "pop", "pop", "hydrogen", "lioh"], chance: 0.01, temp2: 200 }, "sugar_water": { elem1: ["pop", "pop", "pop", "hydrogen", "lioh"], chance: 0.01, temp2: 200 }, "dirty_water": { elem1: ["pop", "pop", "pop", "hydrogen", "lioh"], chance: 0.01, temp2: 200 }, "seltzer": { elem1: ["pop", "pop", "pop", "hydrogen", "lioh"], chance: 0.01, temp2: 200 }, "pool_water": { elem1: ["pop", "pop", "pop", "hydrogen", "lioh"], chance: 0.01, temp2: 200 }, "primordial_soup": { elem1: ["pop", "pop", "pop", "hydrogen", "lioh"], chance: 0.01, temp2: 200 }, "nut_milk": { elem1: ["pop", "pop", "pop", "hydrogen", "lioh"], chance: 0.01, temp2: 200 }, "acid": { elem1: ["hydrogen", "salt", "salt", "pop"], elem2: ["hydrogen", "salt", "salt", "pop"], temp1: 100, temp2: 100 } }, properties: { symbol: "li" } }; // Molten lithium elements.molten_lithium = { tempLow: 180.5, tempHigh: 1334, stateLow: "lithium", density: 533, conduct: 0.42, category: "states", reactions: { "chlorine": { elem1: "salt", elem2: "pop" }, "vinegar": { elem1: "sodium_acetate", elem2: [null, null, null, "hydrogen"], attr1: { "foam": 15 } }, "water": { elem1: ["pop", "pop", "pop", "hydrogen", "lye"], chance: 0.01, temp2: 200 }, "salt_water": { elem1: ["pop", "pop", "pop", "hydrogen", "lye"], chance: 0.01, temp2: 200 }, "sugar_water": { elem1: ["pop", "pop", "pop", "hydrogen", "lye"], chance: 0.01, temp2: 200 }, "dirty_water": { elem1: ["pop", "pop", "pop", "hydrogen", "lye"], chance: 0.01, temp2: 200 }, "seltzer": { elem1: ["pop", "pop", "pop", "hydrogen", "lye"], chance: 0.01, temp2: 200 }, "pool_water": { elem1: ["pop", "pop", "pop", "hydrogen", "lye"], chance: 0.01, temp2: 200 }, "primordial_soup": { elem1: ["pop", "pop", "pop", "hydrogen", "lye"], chance: 0.01, temp2: 200 }, "nut_milk": { elem1: ["pop", "pop", "pop", "hydrogen", "lye"], chance: 0.01, temp2: 200 }, "acid": { elem1: ["hydrogen", "salt", "salt", "pop"], elem2: ["hydrogen", "salt", "salt", "pop"], temp1: 100, temp2: 100 } }, properties: { symbol: "li" } }; // Gas elements.lithium_gas = { color: "#bfbfbf", state: "gas", tempLow: 1334, stateLow: "molten_lithium" }; elements.lioh = { color: "#dfefff", category: "compounds", behavior: behaviors.POWDER, state: "solid", density: 1460, tempHigh: 500, reactions: { "acid": { elem1: "water", elem2: "salt" } } } // --- Alkali metals configuration --- const alkaliMetals = [ { name: "rubidium", symbol: "rb", density: 1534, conduct: 0.6, melt: 39.3, boil: 688, color: ["#ffffff", "#e1e1e1", "#c0c0c0", "#bbbbbb"] }, { name: "caesium", symbol: "cs", density: 1850, conduct: 0.59, melt: 28.44, boil: 671, color: ["#ffffff", "#e5e5e5", "#cfcfcf", "#bbbbbb"] } ]; // --- Generate elements dynamically --- alkaliMetals.forEach(metal => { // Solid elements[metal.name] = { color: metal.color, state: "solid", behavior: behaviors.POWDER, category: "alkali", tempHigh: metal.melt, stateHigh: `liquid_${metal.name}`, density: metal.density, conduct: metal.conduct, tick(pixel) { normalAlkali(pixel); waterReaction(pixel, { effectType: "explosion", reactionChance: 0.05 }); }, properties: { symbol: metal.symbol } }; // Liquid elements[`liquid_${metal.name}`] = { color: metal.color, state: "liquid", behavior: behaviors.LIQUID, tempLow: metal.melt, temp: metal.melt, tempHigh: metal.boil, stateLow: metal.name, stateHigh: `${metal.name}_gas`, density: metal.density, conduct: metal.conduct, category: "states", hidden: true, tick(pixel) { normalAlkali(pixel); waterReaction(pixel, { effectType: "explosion", reactionChance: 0.05 }); }, properties: { symbol: metal.symbol } }; // Gas elements[`${metal.name}_gas`] = { color: metal.color, state: "gas", tempLow: metal.boil, stateLow: `liquid_${metal.name}`, category: "states", hidden: true, behavior: behaviors.GAS, temp: metal.boil }; }); elements.sodium.category = "alkali" elements.potassium.category = "alkali" elements.francium = { color: ["#ddddff", "#ccccff", "#aaaaff"], category: "alkali", behavior: behaviors.POWDER, state: "solid", density: 1870, tempHigh: 27, stateHigh: "molten_francium", conduct: 0.2, tick(pixel) { normalAlkali(pixel); waterReaction(pixel, { effectType: "explosion", reactionChance: 0.2, tempIncrease: 300 }); if (Math.random() < 0.001) { changePixel(pixel, "lead"); } for (var i = 0; i < adjacentCoords.length; i++) { var x = pixel.x + adjacentCoords[i][0]; var y = pixel.y + adjacentCoords[i][1]; if (isEmpty(x, y) && Math.random() <= 0.02) { createPixel("radiation", x, y) getPixel(x, y).temp = pixel.temp } if (!isEmpty(x, y)) { let p = getPixel(x, y) if (p && p.element === "neutron" && Math.random() <= 0.5) { var rand = Math.random() if (rand <= 0.01) { changePixel(pixel, "lead") } } } } }, properties: { symbol: "fr" } } elements.molten_francium = { color: ["#ddddff", "#ccccff", "#aaaaff"], state: "liquid", behavior: behaviors.LIQUID, density: 1870, tempLow: 27, temp: 27, tempHigh: 600, stateLow: "francium", stateHigh: "francium_gas", category: "states", hidden: true, tick(pixel) { normalAlkali(pixel); waterReaction(pixel, { effectType: "explosion", reactionChance: 0.2, tempIncrease: 300 }); if (Math.random() < 0.001) { changePixel(pixel, "lead"); } for (var i = 0; i < adjacentCoords.length; i++) { var x = pixel.x + adjacentCoords[i][0]; var y = pixel.y + adjacentCoords[i][1]; if (isEmpty(x, y) && Math.random() <= 0.02) { createPixel("radiation", x, y) getPixel(x, y).temp = pixel.temp } if (!isEmpty(x, y)) { let p = getPixel(x, y) if (p && p.element === "neutron" && Math.random() <= 0.5) { var rand = Math.random() if (rand <= 0.01) { changePixel(pixel, "lead") } } } } }, properties: { symbol: "fr" } } elements.francium_gas = { color: "#ccccff", behavior: behaviors.GAS, state: "gas", tempLow: 600, temp: 600, stateLow: "molten_francium", category: "states", hidden: true }