diff --git a/IMPLEMENTATION-PLAN.md b/IMPLEMENTATION-PLAN.md index 3109f26..f7993ca 100644 --- a/IMPLEMENTATION-PLAN.md +++ b/IMPLEMENTATION-PLAN.md @@ -238,7 +238,7 @@ | Фаза | Содержание | |-------|-----------| -| Phase 9 | +2 биома (Кинетические Горы, Вердантовые Леса), +20 элементов, +100 реакций | +| Phase 9 ✅ | +2 биома (Кинетические Горы, Вердантовые Леса), +20 элементов, +100 реакций | | Phase 10 | +3 школы (Механик, Натуралист, Навигатор), принципы физики и биологии | | Phase 11 | Великий цикл (7 ранов): следы между ранами, Великое Обновление | | Phase 12 | +3 Архонта (Спора Прайма, Энтропа, Когнитон) | diff --git a/PROGRESS.md b/PROGRESS.md index bf83b2a..ada6e1c 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -1,7 +1,7 @@ # Synthesis — Development Progress > **Last updated:** 2026-02-12 -> **Current phase:** Phase 8 ✅ → Vertical Slice Complete +> **Current phase:** Phase 9 ✅ → Biome Expansion Complete --- @@ -111,15 +111,29 @@ - [x] Scene flow extended: GameScene → BossArenaScene → DeathScene (on death or victory) - [x] Unit tests — 70 passing (`tests/boss.test.ts`) (455 total) +### Phase 9: Biome Expansion ✅ +- [x] 9.1 New elements — 20 additional real elements (Li, B, F, Ne, Ar, Ti, Cr, Mn, Co, Ni, As, Br, Ag, I, Ba, W, Pt, Pb, Bi, U) → 40 total +- [x] 9.2 New compounds — 39 new compounds (acids, salts, oxides, organics) → 64 total +- [x] 9.3 New reactions — 85 new reactions (synthesis, combustion, acid-base, redox, decomposition, replacement) → 119 total +- [x] 9.4 Kinetic Mountains biome — physics/mechanics themed: chasms, gear floors, magnetic fields, steam vents, ore deposits +- [x] 9.5 Verdant Forests biome — biology/ecology themed: bogs, toxic blooms, ancient trees, mycelium carpet, herb patches +- [x] 9.6 Biome selection — CradleScene biome picker UI, biomeId passed to GameScene, generic world generator +- [x] 9.7 New creatures — 6 species: Pendulums/Mechanoids/Resonators (mountains), Symbiotes/Mimics/Spore-bearers (forests) +- [x] 9.8 World generator genericized — tile lookup by property (interactive/resource) instead of hardcoded names +- [x] Chemistry types extended — `actinide` element category for Uranium +- [x] Species types extended — `biome` field, `SpeciesId` enum expanded (0–8) +- [x] GameScene filters creatures by selected biome +- [x] Unit tests — 32 new tests (487 total) + --- ## In Progress -_None — Vertical Slice (Phase 0–8) complete_ +_None — Phase 9 complete_ --- -## Up Next: Post-MVP (Phase 9+) +## Up Next: Phase 10+ _(See IMPLEMENTATION-PLAN.md for Beyond Vertical Slice)_ @@ -144,3 +158,4 @@ None | 7 | 2026-02-12 | Phase 6 | Run Cycle: full roguelike loop (Cradle→Game→Death→Fractal→Cradle), school selection (Alchemist), meta-progression (Codex/spores/IndexedDB), run phases with auto-advance, escalation effects (creature aggression/env damage), Chemical Plague crisis with neutralization, death animation (real body composition), WebGL fractal shader, 56 new tests (349 total) | | 8 | 2026-02-12 | Phase 7 | Mycelium: persistent knowledge graph (nodes/edges/strength), fungal node ECS entities with glow animation, knowledge deposit (auto on death + manual at nodes), memory flash extraction (weighted by strength, Russian templates), mycosis visual effect (tint overlay + reveal threshold), spore shop in Cradle (5 bonuses: health/elements/knowledge), MetaState+IndexedDB persistence updated, GameScene+CradleScene integration, 36 new tests (385 total) | | 9 | 2026-02-12 | Phase 8 | Ouroboros boss fight: 4-phase cyclical AI (Coil/Spray/Lash/Digest) with escalating difficulty, 3 chemistry-based victory paths (NaOH neutralization, direct damage, Hg catalyst poison), circular arena generator, BossArenaScene with attacks+collision+UI, Archont's Memory lore reward, CodexEntry extended, GameScene Resolution→arena trigger, 70 new tests (455 total) | +| 10 | 2026-02-12 | Phase 9 | Biome expansion: +20 elements (40 total), +39 compounds (64 total), +85 reactions (119 total), 2 new biomes (Kinetic Mountains + Verdant Forests), biome selection in CradleScene, 6 new creature species (3 per new biome), generic world generator, 32 new tests (487 total) | diff --git a/src/chemistry/types.ts b/src/chemistry/types.ts index 3c098af..53d3c29 100644 --- a/src/chemistry/types.ts +++ b/src/chemistry/types.ts @@ -8,7 +8,8 @@ export type ElementCategory = | 'metalloid' | 'nonmetal' | 'halogen' - | 'noble-gas'; + | 'noble-gas' + | 'actinide'; export type MatterState = 'solid' | 'liquid' | 'gas'; diff --git a/src/creatures/types.ts b/src/creatures/types.ts index 46f6daf..dada2a3 100644 --- a/src/creatures/types.ts +++ b/src/creatures/types.ts @@ -1,10 +1,9 @@ /** * Creature Types — data definitions for the creature/ecology system * - * Three species in Catalytic Wastes: - * - Crystallids: slow, sturdy, eat minerals, excrete silicon - * - Acidophiles: medium speed, eat minerals, excrete acid - * - Reagents: fast, paired, predatory, explosive + * Catalytic Wastes: Crystallids, Acidophiles, Reagents + * Kinetic Mountains: Pendulums, Mechanoids, Resonators + * Verdant Forests: Symbiotes, Mimics, Spore-bearers */ /** Species identifier (stored as numeric ID in ECS components) */ @@ -12,6 +11,12 @@ export enum SpeciesId { Crystallid = 0, Acidophile = 1, Reagent = 2, + Pendulum = 3, + Mechanoid = 4, + Resonator = 5, + Symbiote = 6, + Mimic = 7, + SporeBearer = 8, } /** AI behavior state (FSM) */ @@ -40,6 +45,7 @@ export interface SpeciesData { name: string; nameRu: string; speciesId: SpeciesId; + biome: string; // biome id this species belongs to description: string; descriptionRu: string; diff --git a/src/data/biomes.json b/src/data/biomes.json index 80db81c..6f430a3 100644 --- a/src/data/biomes.json +++ b/src/data/biomes.json @@ -34,5 +34,77 @@ "geyserOnTile": 4, "mineralOnTiles": [0, 1, 2] } + }, + { + "id": "kinetic-mountains", + "name": "Kinetic Mountains", + "nameRu": "Кинетические Горы", + "description": "Towering cliffs embedded with ancient gears and pendulums. Anomalous gravity zones, avalanche-prone slopes, and whirring mechanical ruins.", + "descriptionRu": "Высокие скалы с вросшими древними шестернями и маятниками. Зоны аномальной гравитации, лавиноопасные склоны и гудящие механические руины.", + "tileSize": 32, + "mapWidth": 80, + "mapHeight": 80, + "tiles": [ + { "id": 0, "name": "bare-rock", "nameRu": "Голый камень", "color": "#5a5a5a", "walkable": true, "damage": 0, "interactive": false, "resource": false }, + { "id": 1, "name": "gravel-slope", "nameRu": "Гравийный склон", "color": "#7a7a6e", "walkable": true, "damage": 0, "interactive": false, "resource": false }, + { "id": 2, "name": "iron-ridge", "nameRu": "Железный хребет", "color": "#4a3a2a", "walkable": true, "damage": 0, "interactive": false, "resource": false }, + { "id": 3, "name": "chasm", "nameRu": "Пропасть", "color": "#0a0a1a", "walkable": false, "damage": 15, "interactive": false, "resource": false }, + { "id": 4, "name": "gear-floor", "nameRu": "Шестерёночный пол", "color": "#8b7355", "walkable": true, "damage": 0, "interactive": false, "resource": false }, + { "id": 5, "name": "magnetic-field", "nameRu": "Магнитное поле", "color": "#3344aa", "walkable": true, "damage": 2, "interactive": false, "resource": false }, + { "id": 6, "name": "steam-vent", "nameRu": "Паровой клапан", "color": "#cccccc", "walkable": false, "damage": 0, "interactive": true, "resource": false }, + { "id": 7, "name": "ore-deposit", "nameRu": "Рудное месторождение", "color": "#b87333", "walkable": true, "damage": 0, "interactive": false, "resource": true } + ], + "generation": { + "elevationScale": 0.05, + "detailScale": 0.18, + "elevationRules": [ + { "below": 0.15, "tileId": 3 }, + { "below": 0.25, "tileId": 5 }, + { "below": 0.50, "tileId": 0 }, + { "below": 0.68, "tileId": 1 }, + { "below": 0.82, "tileId": 2 }, + { "below": 1.00, "tileId": 4 } + ], + "geyserThreshold": 0.92, + "mineralThreshold": 0.88, + "geyserOnTile": 5, + "mineralOnTiles": [0, 1, 2] + } + }, + { + "id": "verdant-forests", + "name": "Verdant Forests", + "nameRu": "Вердантовые Леса", + "description": "A multi-layered living forest teeming with biodiversity. Underground mycorrhizal networks, towering canopies, and bioluminescent clearings.", + "descriptionRu": "Многоярусный живой лес, кишащий биоразнообразием. Подземные микоризные сети, высочайшие кроны и биолюминесцентные поляны.", + "tileSize": 32, + "mapWidth": 80, + "mapHeight": 80, + "tiles": [ + { "id": 0, "name": "forest-floor", "nameRu": "Лесная подстилка", "color": "#1a3a0e", "walkable": true, "damage": 0, "interactive": false, "resource": false }, + { "id": 1, "name": "dense-undergrowth", "nameRu": "Густой подлесок", "color": "#0d2b06", "walkable": true, "damage": 0, "interactive": false, "resource": false }, + { "id": 2, "name": "mycelium-carpet", "nameRu": "Мицелиевый ковёр", "color": "#4a2a5a", "walkable": true, "damage": 0, "interactive": false, "resource": false }, + { "id": 3, "name": "bog", "nameRu": "Трясина", "color": "#2a4a1a", "walkable": true, "damage": 4, "interactive": false, "resource": false }, + { "id": 4, "name": "toxic-bloom", "nameRu": "Ядовитый цвет", "color": "#9a3a6a", "walkable": false, "damage": 8, "interactive": false, "resource": false }, + { "id": 5, "name": "ancient-tree", "nameRu": "Древо-Великан", "color": "#1a2a0a", "walkable": false, "damage": 0, "interactive": false, "resource": false }, + { "id": 6, "name": "hollow-stump", "nameRu": "Полый пень", "color": "#5a4a2a", "walkable": true, "damage": 0, "interactive": true, "resource": false }, + { "id": 7, "name": "herb-patch", "nameRu": "Лекарственная поляна", "color": "#2a6a1a", "walkable": true, "damage": 0, "interactive": false, "resource": true } + ], + "generation": { + "elevationScale": 0.07, + "detailScale": 0.12, + "elevationRules": [ + { "below": 0.18, "tileId": 3 }, + { "below": 0.28, "tileId": 4 }, + { "below": 0.55, "tileId": 0 }, + { "below": 0.72, "tileId": 1 }, + { "below": 0.86, "tileId": 2 }, + { "below": 1.00, "tileId": 5 } + ], + "geyserThreshold": 0.91, + "mineralThreshold": 0.87, + "geyserOnTile": 2, + "mineralOnTiles": [0, 1, 2] + } } ] diff --git a/src/data/compounds.json b/src/data/compounds.json index fa4c0f5..a1936d6 100644 --- a/src/data/compounds.json +++ b/src/data/compounds.json @@ -198,5 +198,319 @@ "description": "Explosive mixture of saltpeter, sulfur, and charcoal. The discovery that changed civilizations.", "descriptionRu": "Взрывчатая смесь селитры, серы и угля. Открытие, изменившее цивилизации.", "gameEffects": ["explosive", "propellant", "signal_flare"] + }, + + { + "id": "NH3", "formula": "NH₃", "name": "Ammonia", "nameRu": "Аммиак", + "mass": 17.031, "state": "gas", "color": "#aaccff", + "properties": { "flammable": false, "toxic": true, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "Pungent gas. Key to fertilizer production (Haber process). Essential biological nitrogen carrier.", + "descriptionRu": "Едкий газ. Основа производства удобрений (процесс Габера). Важнейший биологический переносчик азота.", + "gameEffects": ["fertilizer", "cleaning", "refrigerant"] + }, + { + "id": "HF", "formula": "HF", "name": "Hydrofluoric Acid", "nameRu": "Плавиковая кислота", + "mass": 20.006, "state": "liquid", "color": "#ccff66", + "properties": { "flammable": false, "toxic": true, "explosive": false, "acidic": true, "basic": false, "oxidizer": false, "corrosive": true }, + "description": "Etches glass! One of the most dangerous acids — penetrates skin and attacks bones.", + "descriptionRu": "Растворяет стекло! Одна из опаснейших кислот — проникает через кожу и разрушает кости.", + "gameEffects": ["glass_etching", "damage", "dissolve_stone"] + }, + { + "id": "HBr", "formula": "HBr", "name": "Hydrobromic Acid", "nameRu": "Бромоводородная кислота", + "mass": 80.912, "state": "liquid", "color": "#cc6633", + "properties": { "flammable": false, "toxic": true, "explosive": false, "acidic": true, "basic": false, "oxidizer": false, "corrosive": true }, + "description": "Strong acid formed from hydrogen and bromine. Stronger than HCl.", + "descriptionRu": "Сильная кислота из водорода и брома. Сильнее соляной кислоты.", + "gameEffects": ["dissolve_metal", "damage"] + }, + { + "id": "HI", "formula": "HI", "name": "Hydroiodic Acid", "nameRu": "Йодоводородная кислота", + "mass": 127.912, "state": "liquid", "color": "#993399", + "properties": { "flammable": false, "toxic": true, "explosive": false, "acidic": true, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "Strongest of the hydrohalic acids. Powerful reducing agent.", + "descriptionRu": "Самая сильная из галогеноводородных кислот. Мощный восстановитель.", + "gameEffects": ["reducing_agent", "dissolve_metal"] + }, + { + "id": "LiOH", "formula": "LiOH", "name": "Lithium Hydroxide", "nameRu": "Гидроксид лития", + "mass": 23.948, "state": "solid", "color": "#e8e8ff", + "properties": { "flammable": false, "toxic": false, "explosive": false, "acidic": false, "basic": true, "oxidizer": false, "corrosive": true }, + "description": "Lightest alkali hydroxide. Used in spacecraft CO₂ scrubbers and lithium batteries.", + "descriptionRu": "Легчайший гидроксид щелочного металла. Используется для очистки воздуха на космических кораблях и в литиевых батареях.", + "gameEffects": ["co2_scrubber", "battery_material"] + }, + { + "id": "LiCl", "formula": "LiCl", "name": "Lithium Chloride", "nameRu": "Хлорид лития", + "mass": 42.394, "state": "solid", "color": "#e0e0e0", + "properties": { "flammable": false, "toxic": false, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "Extremely hygroscopic salt. Absorbs moisture from air. Used as desiccant.", + "descriptionRu": "Крайне гигроскопичная соль. Поглощает влагу из воздуха. Используется как осушитель.", + "gameEffects": ["desiccant", "dehumidifier"] + }, + { + "id": "TiO2", "formula": "TiO₂", "name": "Titanium Dioxide", "nameRu": "Диоксид титана", + "mass": 79.866, "state": "solid", "color": "#ffffff", + "properties": { "flammable": false, "toxic": false, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "Brilliant white pigment. UV blocker. Photocatalyst that breaks down pollutants in sunlight.", + "descriptionRu": "Ярко-белый пигмент. УФ-блокатор. Фотокатализатор, расщепляющий загрязнители на свету.", + "gameEffects": ["pigment", "sun_protection", "photocatalyst"] + }, + { + "id": "Cr2O3", "formula": "Cr₂O₃", "name": "Chromium(III) Oxide", "nameRu": "Оксид хрома(III)", + "mass": 151.99, "state": "solid", "color": "#336633", + "properties": { "flammable": false, "toxic": false, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "Deep green pigment. Extremely hard and heat-resistant. Used in armor and abrasives.", + "descriptionRu": "Насыщенный зелёный пигмент. Крайне твёрд и термостоек. Используется в броне и абразивах.", + "gameEffects": ["pigment", "armor_material", "abrasive"] + }, + { + "id": "MnO2", "formula": "MnO₂", "name": "Manganese Dioxide", "nameRu": "Диоксид марганца", + "mass": 86.937, "state": "solid", "color": "#333333", + "properties": { "flammable": false, "toxic": false, "explosive": false, "acidic": false, "basic": false, "oxidizer": true, "corrosive": false }, + "description": "Natural catalyst and oxidizer. Key component of dry cell batteries. Accelerates many reactions.", + "descriptionRu": "Природный катализатор и окислитель. Ключевой компонент батареек. Ускоряет многие реакции.", + "gameEffects": ["catalyst", "battery_material", "oxidizer"] + }, + { + "id": "CoO", "formula": "CoO", "name": "Cobalt(II) Oxide", "nameRu": "Оксид кобальта(II)", + "mass": 74.932, "state": "solid", "color": "#336699", + "properties": { "flammable": false, "toxic": true, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "Deep blue compound. Used in pottery glazes since ancient Egypt. Magnetic.", + "descriptionRu": "Тёмно-синее соединение. Используется в керамических глазурях со времён Древнего Египта. Магнитно.", + "gameEffects": ["pigment", "magnetic"] + }, + { + "id": "NiCl2", "formula": "NiCl₂", "name": "Nickel(II) Chloride", "nameRu": "Хлорид никеля(II)", + "mass": 129.60, "state": "solid", "color": "#00cc66", + "properties": { "flammable": false, "toxic": true, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "Bright green salt. Key reagent in electroplating. Catalyst for organic reactions.", + "descriptionRu": "Ярко-зелёная соль. Ключевой реагент для гальванопокрытий. Катализатор органических реакций.", + "gameEffects": ["electroplating", "catalyst"] + }, + { + "id": "As2O3", "formula": "As₂O₃", "name": "Arsenic Trioxide", "nameRu": "Оксид мышьяка(III)", + "mass": 197.841, "state": "solid", "color": "#f0f0f0", + "properties": { "flammable": false, "toxic": true, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "The 'King of Poisons'. Odorless, tasteless, lethal. Used as a rat poison for centuries.", + "descriptionRu": "«Король ядов». Без запаха, вкуса, смертелен. Веками использовался как крысиный яд.", + "gameEffects": ["deadly_poison", "rat_poison", "glass_clarifier"] + }, + { + "id": "AgCl", "formula": "AgCl", "name": "Silver Chloride", "nameRu": "Хлорид серебра", + "mass": 143.321, "state": "solid", "color": "#e0e0e0", + "properties": { "flammable": false, "toxic": false, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "White solid that darkens in light (basis of photography). Antimicrobial wound dressing.", + "descriptionRu": "Белое вещество, темнеющее на свету (основа фотографии). Антимикробная раневая повязка.", + "gameEffects": ["photography", "antimicrobial", "light_sensor"] + }, + { + "id": "BaO", "formula": "BaO", "name": "Barium Oxide", "nameRu": "Оксид бария", + "mass": 153.326, "state": "solid", "color": "#f5f5cc", + "properties": { "flammable": false, "toxic": false, "explosive": false, "acidic": false, "basic": true, "oxidizer": false, "corrosive": true }, + "description": "Powerful desiccant and getter. Reacts violently with water. Produces green flame.", + "descriptionRu": "Мощный осушитель и геттер. Бурно реагирует с водой. Даёт зелёное пламя.", + "gameEffects": ["desiccant", "green_flame"] + }, + { + "id": "WO3", "formula": "WO₃", "name": "Tungsten Trioxide", "nameRu": "Оксид вольфрама(VI)", + "mass": 231.84, "state": "solid", "color": "#cccc00", + "properties": { "flammable": false, "toxic": false, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "Yellow powder. Electrochromic — changes color with voltage. Smart glass technology.", + "descriptionRu": "Жёлтый порошок. Электрохромный — меняет цвет при напряжении. Технология умного стекла.", + "gameEffects": ["smart_glass", "electrochromic", "pigment"] + }, + { + "id": "PbO", "formula": "PbO", "name": "Lead(II) Oxide", "nameRu": "Оксид свинца(II)", + "mass": 223.2, "state": "solid", "color": "#cc9933", + "properties": { "flammable": false, "toxic": true, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "Yellow-orange powder (litharge). Used in lead-acid batteries and ancient pottery glazes.", + "descriptionRu": "Жёлто-оранжевый порошок (глёт). Используется в свинцовых аккумуляторах и древних керамических глазурях.", + "gameEffects": ["battery_material", "pigment", "radiation_shield"] + }, + { + "id": "PbS", "formula": "PbS", "name": "Lead(II) Sulfide", "nameRu": "Сульфид свинца (галенит)", + "mass": 239.27, "state": "solid", "color": "#333344", + "properties": { "flammable": false, "toxic": true, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "Galena — the principal ore of lead. First semiconductor discovered. Used in early radio crystal detectors.", + "descriptionRu": "Галенит — основная руда свинца. Первый обнаруженный полупроводник. Применялся в ранних радиоприёмниках.", + "gameEffects": ["semiconductor", "radio_detector", "lead_source"] + }, + { + "id": "Bi2O3", "formula": "Bi₂O₃", "name": "Bismuth Trioxide", "nameRu": "Оксид висмута(III)", + "mass": 465.959, "state": "solid", "color": "#ffffcc", + "properties": { "flammable": false, "toxic": false, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "Yellow powder with medicinal properties. Active ingredient in stomach remedies. Low toxicity.", + "descriptionRu": "Жёлтый порошок с лечебными свойствами. Действующее вещество желудочных средств. Малотоксичен.", + "gameEffects": ["medicine", "stomach_remedy", "pigment"] + }, + { + "id": "UO2", "formula": "UO₂", "name": "Uranium Dioxide", "nameRu": "Диоксид урана", + "mass": 270.028, "state": "solid", "color": "#333300", + "properties": { "flammable": false, "toxic": true, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "Nuclear fuel. Incredibly dense. A single pellet contains energy equivalent to a tonne of coal.", + "descriptionRu": "Ядерное топливо. Невероятно плотный. Один стержень содержит энергию, эквивалентную тонне угля.", + "gameEffects": ["nuclear_fuel", "energy_source", "radiation"] + }, + { + "id": "CH3COOH", "formula": "CH₃COOH", "name": "Acetic Acid", "nameRu": "Уксусная кислота", + "mass": 60.052, "state": "liquid", "color": "#eeeedd", + "properties": { "flammable": true, "toxic": false, "explosive": false, "acidic": true, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "Vinegar. Natural product of fermentation. Solvent, preservative, and creature bait.", + "descriptionRu": "Уксус. Природный продукт брожения. Растворитель, консервант и приманка для существ.", + "gameEffects": ["solvent", "preservative", "creature_bait", "descaler"] + }, + { + "id": "C6H12O6", "formula": "C₆H₁₂O₆", "name": "Glucose", "nameRu": "Глюкоза", + "mass": 180.156, "state": "solid", "color": "#ffffee", + "properties": { "flammable": false, "toxic": false, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "Simple sugar. Universal biological fuel. Feed to microorganisms or use as fast energy source.", + "descriptionRu": "Простой сахар. Универсальное биологическое топливо. Корм для микроорганизмов или быстрый источник энергии.", + "gameEffects": ["energy_food", "microorganism_feed", "fermentation_base"] + }, + + { + "id": "H2S", "formula": "H₂S", "name": "Hydrogen Sulfide", "nameRu": "Сероводород", + "mass": 34.08, "state": "gas", "color": "#cccc66", + "properties": { "flammable": true, "toxic": true, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "Rotten egg smell. Toxic in high concentrations. Natural hot spring emission.", + "descriptionRu": "Запах тухлых яиц. Токсичен в высоких концентрациях. Газ горячих источников.", + "gameEffects": ["poison_gas", "indicator", "hot_spring"] + }, + { + "id": "H2SO4", "formula": "H₂SO₄", "name": "Sulfuric Acid", "nameRu": "Серная кислота", + "mass": 98.079, "state": "liquid", "color": "#ffee00", + "properties": { "flammable": false, "toxic": true, "explosive": false, "acidic": true, "basic": false, "oxidizer": true, "corrosive": true }, + "description": "King of chemicals. Most produced chemical worldwide. Violently exothermic with water.", + "descriptionRu": "Царь химикатов. Самое производимое химическое вещество в мире. Бурно реагирует с водой.", + "gameEffects": ["dissolve_metal", "dissolve_organic", "battery_acid", "damage"] + }, + { + "id": "HNO3", "formula": "HNO₃", "name": "Nitric Acid", "nameRu": "Азотная кислота", + "mass": 63.012, "state": "liquid", "color": "#ff6600", + "properties": { "flammable": false, "toxic": true, "explosive": false, "acidic": true, "basic": false, "oxidizer": true, "corrosive": true }, + "description": "Fuming corrosive acid. Dissolves most metals. Component of aqua regia (with HCl) to dissolve gold.", + "descriptionRu": "Дымящая кислота. Растворяет большинство металлов. Компонент царской водки (с HCl) для растворения золота.", + "gameEffects": ["dissolve_metal", "oxidizer", "damage", "aqua_regia_component"] + }, + { + "id": "CuO", "formula": "CuO", "name": "Copper(II) Oxide", "nameRu": "Оксид меди(II)", + "mass": 79.545, "state": "solid", "color": "#1a1a1a", + "properties": { "flammable": false, "toxic": false, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "Black powder. Reducible by carbon or hydrogen — ancient copper smelting.", + "descriptionRu": "Чёрный порошок. Восстанавливается углеродом или водородом — древняя медеплавка.", + "gameEffects": ["pigment", "smelting_ore", "catalyst"] + }, + { + "id": "NaF", "formula": "NaF", "name": "Sodium Fluoride", "nameRu": "Фторид натрия", + "mass": 41.988, "state": "solid", "color": "#f0f0f0", + "properties": { "flammable": false, "toxic": true, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "Active ingredient in toothpaste. Strengthens tooth enamel. Toxic in large doses.", + "descriptionRu": "Активный компонент зубной пасты. Укрепляет зубную эмаль. Токсичен в больших дозах.", + "gameEffects": ["dental_protection", "water_treatment"] + }, + { + "id": "NaBr", "formula": "NaBr", "name": "Sodium Bromide", "nameRu": "Бромид натрия", + "mass": 102.894, "state": "solid", "color": "#e8e8e8", + "properties": { "flammable": false, "toxic": false, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "White crystalline salt. Historical sedative and anticonvulsant. Photography reagent.", + "descriptionRu": "Белая кристаллическая соль. Исторический седативный и противосудорожный препарат.", + "gameEffects": ["sedative", "photography"] + }, + { + "id": "KF", "formula": "KF", "name": "Potassium Fluoride", "nameRu": "Фторид калия", + "mass": 58.097, "state": "solid", "color": "#e0e0e0", + "properties": { "flammable": false, "toxic": true, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": true }, + "description": "Strong fluorinating agent. Used in organic synthesis. Corrosive.", + "descriptionRu": "Сильный фторирующий агент. Используется в органическом синтезе. Едкий.", + "gameEffects": ["fluorinating_agent"] + }, + { + "id": "KBr", "formula": "KBr", "name": "Potassium Bromide", "nameRu": "Бромид калия", + "mass": 119.002, "state": "solid", "color": "#e0e0e0", + "properties": { "flammable": false, "toxic": false, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "Photography essential. Historical anticonvulsant medicine. Transparent to infrared.", + "descriptionRu": "Необходим для фотографии. Исторический противосудорожный препарат. Прозрачен для инфракрасного.", + "gameEffects": ["photography", "medicine", "optics"] + }, + { + "id": "AgBr", "formula": "AgBr", "name": "Silver Bromide", "nameRu": "Бромид серебра", + "mass": 187.772, "state": "solid", "color": "#e8e8cc", + "properties": { "flammable": false, "toxic": false, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "Pale yellow, darkens in light. The basis of photographic film. More light-sensitive than AgCl.", + "descriptionRu": "Бледно-жёлтый, темнеет на свету. Основа фотоплёнки. Светочувствительнее AgCl.", + "gameEffects": ["photography", "light_sensor"] + }, + { + "id": "NH4Cl", "formula": "NH₄Cl", "name": "Ammonium Chloride", "nameRu": "Хлорид аммония", + "mass": 53.491, "state": "solid", "color": "#f5f5f5", + "properties": { "flammable": false, "toxic": false, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "Sal ammoniac. White smoke when heated. Used in batteries, flux, and cough medicine.", + "descriptionRu": "Нашатырь. Белый дым при нагревании. Используется в батарейках, флюсе и от кашля.", + "gameEffects": ["flux", "battery_material", "smoke_screen"] + }, + { + "id": "MgCl2", "formula": "MgCl₂", "name": "Magnesium Chloride", "nameRu": "Хлорид магния", + "mass": 95.211, "state": "solid", "color": "#e0e0e0", + "properties": { "flammable": false, "toxic": false, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "De-icing salt. Dust suppressant. Source of magnesium metal via electrolysis.", + "descriptionRu": "Противогололёдная соль. Подавитель пыли. Источник металлического магния через электролиз.", + "gameEffects": ["de_icing", "dust_control", "magnesium_source"] + }, + { + "id": "CaCl2", "formula": "CaCl₂", "name": "Calcium Chloride", "nameRu": "Хлорид кальция", + "mass": 110.984, "state": "solid", "color": "#f0f0f0", + "properties": { "flammable": false, "toxic": false, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "Powerful desiccant and de-icer. Exothermic when dissolved — can melt ice below -50°C.", + "descriptionRu": "Мощный осушитель и антигололёдный реагент. Экзотермичен при растворении — плавит лёд ниже -50°C.", + "gameEffects": ["desiccant", "de_icing", "heat_source"] + }, + { + "id": "BaCl2", "formula": "BaCl₂", "name": "Barium Chloride", "nameRu": "Хлорид бария", + "mass": 208.233, "state": "solid", "color": "#f0f0f0", + "properties": { "flammable": false, "toxic": true, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "Toxic barium salt. Burns with characteristic green flame. Chemical analysis reagent.", + "descriptionRu": "Токсичная соль бария. Горит характерным зелёным пламенем. Реагент для химического анализа.", + "gameEffects": ["green_flame", "analysis_reagent"] + }, + { + "id": "FeCl3", "formula": "FeCl₃", "name": "Iron(III) Chloride", "nameRu": "Хлорид железа(III)", + "mass": 162.204, "state": "solid", "color": "#663300", + "properties": { "flammable": false, "toxic": false, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": true }, + "description": "Dark brown, corrosive. Etches copper (circuit boards). Water purification agent.", + "descriptionRu": "Тёмно-коричневый, едкий. Травит медь (печатные платы). Реагент для очистки воды.", + "gameEffects": ["copper_etching", "water_purification", "coagulant"] + }, + { + "id": "CuCl2", "formula": "CuCl₂", "name": "Copper(II) Chloride", "nameRu": "Хлорид меди(II)", + "mass": 134.452, "state": "solid", "color": "#006633", + "properties": { "flammable": false, "toxic": true, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "Bright green crystals. Turns blue in water. Catalyst. Gives green-blue flame.", + "descriptionRu": "Ярко-зелёные кристаллы. Синеет в воде. Катализатор. Даёт зелёно-голубое пламя.", + "gameEffects": ["catalyst", "pigment", "blue_green_flame"] + }, + { + "id": "FeCl2", "formula": "FeCl₂", "name": "Iron(II) Chloride", "nameRu": "Хлорид железа(II)", + "mass": 126.751, "state": "solid", "color": "#669966", + "properties": { "flammable": false, "toxic": false, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": false }, + "description": "Greenish solid. Product of iron dissolved in HCl. Reducing agent.", + "descriptionRu": "Зеленоватое твёрдое вещество. Продукт растворения железа в HCl. Восстановитель.", + "gameEffects": ["reducing_agent", "water_treatment"] + }, + { + "id": "ZnCl2", "formula": "ZnCl₂", "name": "Zinc Chloride", "nameRu": "Хлорид цинка", + "mass": 136.286, "state": "solid", "color": "#e0e0e0", + "properties": { "flammable": false, "toxic": false, "explosive": false, "acidic": false, "basic": false, "oxidizer": false, "corrosive": true }, + "description": "Powerful flux for soldering. Dehydrating agent. Used in fireproofing fabric.", + "descriptionRu": "Мощный флюс для пайки. Обезвоживающий агент. Огнезащита тканей.", + "gameEffects": ["flux", "desiccant", "fireproofing"] + }, + { + "id": "Na2O", "formula": "Na₂O", "name": "Sodium Oxide", "nameRu": "Оксид натрия", + "mass": 61.979, "state": "solid", "color": "#f5f5f5", + "properties": { "flammable": false, "toxic": false, "explosive": false, "acidic": false, "basic": true, "oxidizer": false, "corrosive": true }, + "description": "White powder. Reacts violently with water to form NaOH. Key component in glass making.", + "descriptionRu": "Белый порошок. Бурно реагирует с водой, образуя NaOH. Ключевой компонент стекловарения.", + "gameEffects": ["glass_making", "caustic"] } ] diff --git a/src/data/creatures.json b/src/data/creatures.json index 8b259ce..0c632ec 100644 --- a/src/data/creatures.json +++ b/src/data/creatures.json @@ -4,6 +4,7 @@ "name": "Crystallid", "nameRu": "Кристаллид", "speciesId": 0, + "biome": "catalytic-wastes", "description": "Slow, armored creature that feeds on mineral deposits. Its silicon-rich body refracts light into prismatic patterns. When killed, it shatters into valuable crystalline fragments.", "descriptionRu": "Медленное бронированное существо, питающееся минеральными отложениями. Его кремниевое тело преломляет свет в призматические узоры. При гибели рассыпается на ценные кристаллические осколки.", "color": "#88ccff", @@ -40,6 +41,7 @@ "name": "Acidophile", "nameRu": "Ацидофил", "speciesId": 1, + "biome": "catalytic-wastes", "description": "Mid-sized creature that thrives in acidic environments. Consumes mineral deposits and excretes hydrochloric acid, gradually reshaping the landscape. Territorial but not predatory.", "descriptionRu": "Среднеразмерное существо, процветающее в кислотной среде. Поглощает минералы и выделяет соляную кислоту, постепенно изменяя ландшафт. Территориальное, но не хищное.", "color": "#44ff44", @@ -76,6 +78,7 @@ "name": "Reagent", "nameRu": "Реагент", "speciesId": 2, + "biome": "catalytic-wastes", "description": "Fast, aggressive predator that hunts in pairs. Contains unstable chemical compounds — when two Reagents collide, they trigger an exothermic reaction. Feeds on other creatures.", "descriptionRu": "Быстрый агрессивный хищник, охотящийся парами. Содержит нестабильные химические соединения — при столкновении двух Реагентов происходит экзотермическая реакция. Питается другими существами.", "color": "#ff4444", @@ -106,5 +109,227 @@ "maxPopulation": 8, "spawnWeight": 0.25, "preferredTiles": ["scorched-earth", "ground"] + }, + { + "id": "pendulum", + "name": "Pendulum", + "nameRu": "Маятник", + "speciesId": 3, + "biome": "kinetic-mountains", + "description": "Flying creature with strictly periodic motion. Swings back and forth on invisible pivot points. Can be used as a clock or platform. Docile unless struck mid-swing.", + "descriptionRu": "Летающее существо со строго периодичным движением. Качается взад-вперёд на невидимых опорных точках. Можно использовать как часы или платформу. Мирное, если не ударить в полёте.", + "color": "#77aadd", + "radius": 9, + "radiusYouth": 5, + "health": 90, + "speed": 60, + "damage": 10, + "armor": 0.15, + "diet": "mineral", + "dietTiles": ["ore-deposit", "gear-floor"], + "excretionElement": 26, + "energyMax": 90, + "energyPerFeed": 22, + "energyDrainPerSecond": 1.8, + "hungerThreshold": 0.45, + "aggressionRadius": 0, + "fleeRadius": 100, + "wanderRadius": 220, + "attackRange": 22, + "attackCooldown": 1800, + "eggDuration": 7000, + "youthDuration": 14000, + "matureDuration": 55000, + "agingDuration": 18000, + "reproductionEnergy": 55, + "offspringCount": 2, + "maxPopulation": 10, + "spawnWeight": 0.4, + "preferredTiles": ["bare-rock", "gear-floor"] + }, + { + "id": "mechanoid", + "name": "Mechanoid", + "nameRu": "Механоид", + "speciesId": 4, + "biome": "kinetic-mountains", + "description": "Half-living automaton. Can be repaired, reprogrammed, or scavenged for metal parts. Patrols ancient machinery and attacks intruders near gear mechanisms.", + "descriptionRu": "Полуживой автомат. Можно починить, перепрограммировать или разобрать на металлические детали. Патрулирует древние механизмы и атакует чужаков у шестерёнок.", + "color": "#aaaacc", + "radius": 11, + "radiusYouth": 7, + "health": 150, + "speed": 35, + "damage": 18, + "armor": 0.4, + "diet": "mineral", + "dietTiles": ["ore-deposit"], + "excretionElement": 29, + "energyMax": 120, + "energyPerFeed": 30, + "energyDrainPerSecond": 1.0, + "hungerThreshold": 0.3, + "aggressionRadius": 120, + "fleeRadius": 0, + "wanderRadius": 150, + "attackRange": 26, + "attackCooldown": 2200, + "eggDuration": 10000, + "youthDuration": 18000, + "matureDuration": 80000, + "agingDuration": 25000, + "reproductionEnergy": 70, + "offspringCount": 1, + "maxPopulation": 8, + "spawnWeight": 0.3, + "preferredTiles": ["gear-floor", "iron-ridge"] + }, + { + "id": "resonator", + "name": "Resonator", + "nameRu": "Резонатор", + "speciesId": 5, + "biome": "kinetic-mountains", + "description": "Vibrates at fixed frequencies. Dangerous if its frequency matches your gear — resonance shatters equipment. Can be used to break barriers or stun other creatures.", + "descriptionRu": "Вибрирует на фиксированных частотах. Опасен, если его частота совпадает с вашим снаряжением — резонанс разрушает оборудование. Может ломать барьеры или оглушать существ.", + "color": "#ff88ff", + "radius": 7, + "radiusYouth": 4, + "health": 50, + "speed": 70, + "damage": 25, + "armor": 0.0, + "diet": "creature", + "dietTiles": [], + "excretionElement": 0, + "energyMax": 55, + "energyPerFeed": 25, + "energyDrainPerSecond": 2.8, + "hungerThreshold": 0.55, + "aggressionRadius": 130, + "fleeRadius": 70, + "wanderRadius": 280, + "attackRange": 20, + "attackCooldown": 1200, + "eggDuration": 5000, + "youthDuration": 10000, + "matureDuration": 40000, + "agingDuration": 13000, + "reproductionEnergy": 35, + "offspringCount": 1, + "maxPopulation": 6, + "spawnWeight": 0.3, + "preferredTiles": ["magnetic-field", "bare-rock"] + }, + { + "id": "symbiote", + "name": "Symbiote", + "nameRu": "Симбионт", + "speciesId": 6, + "biome": "verdant-forests", + "description": "Always appears in bonded pairs. Separating them weakens both — one may die without the other. Feeds on forest floor decomposition. Peaceful but resilient in pairs.", + "descriptionRu": "Всегда появляется связанными парами. Разделение ослабляет обоих — один может погибнуть без другого. Питается лесной подстилкой. Мирные, но в паре стойкие.", + "color": "#44ddaa", + "radius": 8, + "radiusYouth": 5, + "health": 70, + "speed": 45, + "damage": 6, + "armor": 0.2, + "diet": "mineral", + "dietTiles": ["herb-patch", "mycelium-carpet"], + "excretionElement": 7, + "energyMax": 85, + "energyPerFeed": 20, + "energyDrainPerSecond": 1.6, + "hungerThreshold": 0.4, + "aggressionRadius": 0, + "fleeRadius": 90, + "wanderRadius": 180, + "attackRange": 18, + "attackCooldown": 2000, + "eggDuration": 7000, + "youthDuration": 13000, + "matureDuration": 50000, + "agingDuration": 17000, + "reproductionEnergy": 45, + "offspringCount": 2, + "maxPopulation": 14, + "spawnWeight": 0.4, + "preferredTiles": ["forest-floor", "dense-undergrowth"] + }, + { + "id": "mimic", + "name": "Mimic", + "nameRu": "Мимикр", + "speciesId": 7, + "biome": "verdant-forests", + "description": "Master of disguise. Can appear as a plant, resource, or even a fungal node. Only reveals itself when approached too closely. Ambush predator with potent venom.", + "descriptionRu": "Мастер маскировки. Может выглядеть как растение, ресурс или грибной узел. Раскрывает себя только при близком приближении. Засадный хищник с мощным ядом.", + "color": "#33cc33", + "radius": 8, + "radiusYouth": 5, + "health": 65, + "speed": 55, + "damage": 22, + "armor": 0.05, + "diet": "creature", + "dietTiles": [], + "excretionElement": 0, + "energyMax": 65, + "energyPerFeed": 28, + "energyDrainPerSecond": 2.2, + "hungerThreshold": 0.5, + "aggressionRadius": 60, + "fleeRadius": 80, + "wanderRadius": 200, + "attackRange": 16, + "attackCooldown": 1400, + "eggDuration": 6000, + "youthDuration": 11000, + "matureDuration": 42000, + "agingDuration": 14000, + "reproductionEnergy": 42, + "offspringCount": 1, + "maxPopulation": 7, + "spawnWeight": 0.25, + "preferredTiles": ["forest-floor", "mycelium-carpet"] + }, + { + "id": "spore-bearer", + "name": "Spore-bearer", + "nameRu": "Споровик", + "speciesId": 8, + "biome": "verdant-forests", + "description": "Fungal creature, avatar of the Mycelium. Peaceful and slow. If harmed, the entire forest turns hostile. Deposits knowledge into fungal nodes when passing near them.", + "descriptionRu": "Грибное существо, аватар Мицелия. Мирное и медленное. Если обидеть — весь лес становится враждебным. Откладывает знания в грибные узлы, проходя мимо них.", + "color": "#9966cc", + "radius": 12, + "radiusYouth": 7, + "health": 200, + "speed": 20, + "damage": 5, + "armor": 0.25, + "diet": "mineral", + "dietTiles": ["mycelium-carpet", "herb-patch"], + "excretionElement": 15, + "energyMax": 150, + "energyPerFeed": 35, + "energyDrainPerSecond": 0.8, + "hungerThreshold": 0.3, + "aggressionRadius": 0, + "fleeRadius": 60, + "wanderRadius": 160, + "attackRange": 24, + "attackCooldown": 3000, + "eggDuration": 12000, + "youthDuration": 20000, + "matureDuration": 90000, + "agingDuration": 30000, + "reproductionEnergy": 80, + "offspringCount": 1, + "maxPopulation": 5, + "spawnWeight": 0.35, + "preferredTiles": ["mycelium-carpet", "forest-floor"] } ] diff --git a/src/data/elements.json b/src/data/elements.json index b11ddd0..0c87d1b 100644 --- a/src/data/elements.json +++ b/src/data/elements.json @@ -25,6 +25,32 @@ "description": "Noble gas. Completely inert — refuses to react with anything. Lighter than air.", "descriptionRu": "Благородный газ. Абсолютно инертен — не реагирует ни с чем. Легче воздуха." }, + { + "symbol": "Li", + "name": "Lithium", + "nameRu": "Литий", + "atomicNumber": 3, + "atomicMass": 6.941, + "electronegativity": 0.98, + "category": "alkali-metal", + "state": "solid", + "color": "#cc80ff", + "description": "Lightest metal. Soft enough to cut with a knife. Key component of modern batteries. Burns crimson red.", + "descriptionRu": "Легчайший металл. Настолько мягкий, что режется ножом. Ключевой компонент современных аккумуляторов. Горит малиновым пламенем." + }, + { + "symbol": "B", + "name": "Boron", + "nameRu": "Бор", + "atomicNumber": 5, + "atomicMass": 10.811, + "electronegativity": 2.04, + "category": "metalloid", + "state": "solid", + "color": "#ffb5b5", + "description": "Hard metalloid. Essential for borosilicate glass (heat-resistant). Boron compounds are used as neutron absorbers.", + "descriptionRu": "Твёрдый металлоид. Основа боросиликатного стекла (термостойкого). Соединения бора поглощают нейтроны." + }, { "symbol": "C", "name": "Carbon", @@ -64,6 +90,32 @@ "description": "Essential for combustion and respiration. Highly reactive oxidizer. 21% of air.", "descriptionRu": "Необходим для горения и дыхания. Сильный окислитель. 21% воздуха." }, + { + "symbol": "F", + "name": "Fluorine", + "nameRu": "Фтор", + "atomicNumber": 9, + "atomicMass": 18.998, + "electronegativity": 3.98, + "category": "halogen", + "state": "gas", + "color": "#90e050", + "description": "Most reactive element in existence. Attacks almost everything, even glass. Handle with extreme caution.", + "descriptionRu": "Самый реактивный элемент в природе. Атакует почти всё, даже стекло. Обращаться с предельной осторожностью." + }, + { + "symbol": "Ne", + "name": "Neon", + "nameRu": "Неон", + "atomicNumber": 10, + "atomicMass": 20.180, + "electronegativity": 0, + "category": "noble-gas", + "state": "gas", + "color": "#b3e3f5", + "description": "Noble gas. Produces iconic red-orange glow in discharge tubes. Completely inert.", + "descriptionRu": "Благородный газ. Даёт культовое красно-оранжевое свечение в газоразрядных трубках. Полностью инертен." + }, { "symbol": "Na", "name": "Sodium", @@ -155,6 +207,19 @@ "description": "Toxic yellow-green gas. Powerful disinfectant. Combines readily with metals to form salts.", "descriptionRu": "Ядовитый жёлто-зелёный газ. Мощный дезинфектант. Легко соединяется с металлами, образуя соли." }, + { + "symbol": "Ar", + "name": "Argon", + "nameRu": "Аргон", + "atomicNumber": 18, + "atomicMass": 39.948, + "electronegativity": 0, + "category": "noble-gas", + "state": "gas", + "color": "#80d1e3", + "description": "Third most abundant gas in atmosphere (0.93%). Used as shielding gas in welding. Completely inert.", + "descriptionRu": "Третий по распространённости газ в атмосфере (0,93%). Защитный газ при сварке. Полностью инертен." + }, { "symbol": "K", "name": "Potassium", @@ -181,6 +246,45 @@ "description": "Essential for bones and shells. Reacts with water, but less violently than sodium. Component of limestone and cement.", "descriptionRu": "Необходим для костей и раковин. Реагирует с водой, но менее бурно, чем натрий. Компонент известняка и цемента." }, + { + "symbol": "Ti", + "name": "Titanium", + "nameRu": "Титан", + "atomicNumber": 22, + "atomicMass": 47.867, + "electronegativity": 1.54, + "category": "transition-metal", + "state": "solid", + "color": "#bfc2c7", + "description": "Strong as steel but 45% lighter. Corrosion-resistant. Used in aerospace, implants, and armor.", + "descriptionRu": "Прочен как сталь, но на 45% легче. Коррозионностойкий. Применяется в авиации, имплантах и броне." + }, + { + "symbol": "Cr", + "name": "Chromium", + "nameRu": "Хром", + "atomicNumber": 24, + "atomicMass": 51.996, + "electronegativity": 1.66, + "category": "transition-metal", + "state": "solid", + "color": "#8a99c7", + "description": "Hardest pure metal. Chrome plating resists corrosion. Stainless steel contains 10-20% chromium.", + "descriptionRu": "Самый твёрдый чистый металл. Хромирование защищает от коррозии. Нержавеющая сталь содержит 10-20% хрома." + }, + { + "symbol": "Mn", + "name": "Manganese", + "nameRu": "Марганец", + "atomicNumber": 25, + "atomicMass": 54.938, + "electronegativity": 1.55, + "category": "transition-metal", + "state": "solid", + "color": "#9c7ac7", + "description": "Essential for steel production. MnO₂ is a natural catalyst and battery material. Biological enzyme cofactor.", + "descriptionRu": "Необходим для производства стали. MnO₂ — природный катализатор и материал батарей. Кофактор биологических ферментов." + }, { "symbol": "Fe", "name": "Iron", @@ -194,6 +298,32 @@ "description": "Strong, abundant metal. Rusts in moist air. Core of Earth is mostly iron. Magnetic.", "descriptionRu": "Прочный, распространённый металл. Ржавеет на влажном воздухе. Ядро Земли в основном из железа. Магнитен." }, + { + "symbol": "Co", + "name": "Cobalt", + "nameRu": "Кобальт", + "atomicNumber": 27, + "atomicMass": 58.933, + "electronegativity": 1.88, + "category": "transition-metal", + "state": "solid", + "color": "#f090a0", + "description": "Source of brilliant blue pigment since antiquity. Magnetic. Essential in vitamin B12.", + "descriptionRu": "Источник насыщенного синего пигмента с древности. Магнитен. Входит в состав витамина B12." + }, + { + "symbol": "Ni", + "name": "Nickel", + "nameRu": "Никель", + "atomicNumber": 28, + "atomicMass": 58.693, + "electronegativity": 1.91, + "category": "transition-metal", + "state": "solid", + "color": "#50d050", + "description": "Corrosion-resistant metal. Key alloy component. Excellent catalyst for hydrogenation reactions.", + "descriptionRu": "Коррозионностойкий металл. Важный компонент сплавов. Превосходный катализатор гидрирования." + }, { "symbol": "Cu", "name": "Copper", @@ -220,6 +350,45 @@ "description": "Protects iron from rusting (galvanization). Zinc sulfide glows under UV light. Essential trace nutrient.", "descriptionRu": "Защищает железо от ржавчины (гальванизация). Сульфид цинка светится в УФ-свете. Необходимый микроэлемент." }, + { + "symbol": "As", + "name": "Arsenic", + "nameRu": "Мышьяк", + "atomicNumber": 33, + "atomicMass": 74.922, + "electronegativity": 2.18, + "category": "metalloid", + "state": "solid", + "color": "#bd80e3", + "description": "Infamous poison. 'Inheritance powder' of the Borgias. Also a semiconductor used in LEDs and lasers.", + "descriptionRu": "Печально известный яд. «Порошок наследников» Борджиа. Также полупроводник для светодиодов и лазеров." + }, + { + "symbol": "Br", + "name": "Bromine", + "nameRu": "Бром", + "atomicNumber": 35, + "atomicMass": 79.904, + "electronegativity": 2.96, + "category": "halogen", + "state": "liquid", + "color": "#a62929", + "description": "Only non-metallic element that is liquid at room temperature. Dark red, fuming, and corrosive.", + "descriptionRu": "Единственный неметалл, жидкий при комнатной температуре. Тёмно-красный, дымящий, едкий." + }, + { + "symbol": "Ag", + "name": "Silver", + "nameRu": "Серебро", + "atomicNumber": 47, + "atomicMass": 107.868, + "electronegativity": 1.93, + "category": "transition-metal", + "state": "solid", + "color": "#c0c0c0", + "description": "Best electrical and thermal conductor of all metals. Natural antimicrobial. Tarnishes in sulfur-containing air.", + "descriptionRu": "Лучший проводник электричества и тепла среди металлов. Природный антисептик. Темнеет в воздухе с серой." + }, { "symbol": "Sn", "name": "Tin", @@ -233,6 +402,58 @@ "description": "Soft, malleable metal. Resists corrosion. Used for solder and tin plating. Alloy with copper makes bronze.", "descriptionRu": "Мягкий, ковкий металл. Устойчив к коррозии. Используется для пайки и лужения. Сплав с медью — бронза." }, + { + "symbol": "I", + "name": "Iodine", + "nameRu": "Йод", + "atomicNumber": 53, + "atomicMass": 126.904, + "electronegativity": 2.66, + "category": "halogen", + "state": "solid", + "color": "#940094", + "description": "Purple-black crystals that sublimate into violet vapor. Essential for thyroid function. Powerful disinfectant.", + "descriptionRu": "Пурпурно-чёрные кристаллы, сублимирующие в фиолетовый пар. Необходим для щитовидной железы. Мощный антисептик." + }, + { + "symbol": "Ba", + "name": "Barium", + "nameRu": "Барий", + "atomicNumber": 56, + "atomicMass": 137.327, + "electronegativity": 0.89, + "category": "alkaline-earth", + "state": "solid", + "color": "#00c900", + "description": "Alkaline earth metal. Burns with bright green flame (fireworks!). BaSO₄ used in X-ray contrast imaging.", + "descriptionRu": "Щёлочноземельный металл. Горит ярко-зелёным пламенем (фейерверки!). BaSO₄ используется при рентгеновской диагностике." + }, + { + "symbol": "W", + "name": "Tungsten", + "nameRu": "Вольфрам", + "atomicNumber": 74, + "atomicMass": 183.84, + "electronegativity": 2.36, + "category": "transition-metal", + "state": "solid", + "color": "#2194d6", + "description": "Highest melting point of any element (3422°C). Extremely hard and dense. Light bulb filaments.", + "descriptionRu": "Самая высокая температура плавления среди элементов (3422°C). Крайне твёрд и плотен. Нити накаливания ламп." + }, + { + "symbol": "Pt", + "name": "Platinum", + "nameRu": "Платина", + "atomicNumber": 78, + "atomicMass": 195.084, + "electronegativity": 2.28, + "category": "transition-metal", + "state": "solid", + "color": "#d0d0e0", + "description": "Noble metal and supreme catalyst. Resists corrosion. Catalytic converters, lab equipment, jewelry.", + "descriptionRu": "Благородный металл и превосходный катализатор. Не поддаётся коррозии. Каталитические нейтрализаторы, лаборатории, ювелирные изделия." + }, { "symbol": "Au", "name": "Gold", @@ -258,5 +479,44 @@ "color": "#b8b8d0", "description": "Only metal that is liquid at room temperature. Extremely toxic — damages brain and kidneys. Handle with extreme care.", "descriptionRu": "Единственный металл, жидкий при комнатной температуре. Крайне токсичен — поражает мозг и почки. Обращаться с предельной осторожностью." + }, + { + "symbol": "Pb", + "name": "Lead", + "nameRu": "Свинец", + "atomicNumber": 82, + "atomicMass": 207.2, + "electronegativity": 2.33, + "category": "post-transition-metal", + "state": "solid", + "color": "#575961", + "description": "Dense, soft, toxic metal. Shields against radiation. Used in batteries. Cumulative neurotoxin.", + "descriptionRu": "Плотный, мягкий, токсичный металл. Экранирует от радиации. Используется в аккумуляторах. Кумулятивный нейротоксин." + }, + { + "symbol": "Bi", + "name": "Bismuth", + "nameRu": "Висмут", + "atomicNumber": 83, + "atomicMass": 208.980, + "electronegativity": 2.02, + "category": "post-transition-metal", + "state": "solid", + "color": "#9e4fb5", + "description": "Least toxic heavy metal. Forms beautiful iridescent crystals. Used in Pepto-Bismol and cosmetics.", + "descriptionRu": "Наименее токсичный тяжёлый металл. Образует красивые радужные кристаллы. Применяется в медицине и косметике." + }, + { + "symbol": "U", + "name": "Uranium", + "nameRu": "Уран", + "atomicNumber": 92, + "atomicMass": 238.029, + "electronegativity": 1.38, + "category": "actinide", + "state": "solid", + "color": "#008fff", + "description": "Radioactive element. Enormous energy density — 1 kg equals 3000 tonnes of coal. Powers nuclear reactors.", + "descriptionRu": "Радиоактивный элемент. Колоссальная плотность энергии — 1 кг равен 3000 тоннам угля. Питает ядерные реакторы." } ] diff --git a/src/data/reactions.json b/src/data/reactions.json index 79eaa0b..8af1caa 100644 --- a/src/data/reactions.json +++ b/src/data/reactions.json @@ -322,5 +322,822 @@ "description": "Lime burning: heating limestone drives off CO₂, leaving quicklime. Ancient building technology.", "descriptionRu": "Обжиг извести: нагрев известняка выгоняет CO₂, оставляя негашёную известь. Древняя строительная технология.", "difficulty": 3 + }, + + { + "id": "synth_hf", "type": "synthesis", + "reactants": [{ "id": "H", "count": 1 }, { "id": "F", "count": 1 }], + "products": [{ "id": "HF", "count": 1 }], + "energyChange": -3, + "description": "Hydrogen + fluorine combine to form hydrofluoric acid — dissolves glass!", + "descriptionRu": "Водород + фтор образуют плавиковую кислоту — растворяет стекло!", + "difficulty": 1 + }, + { + "id": "synth_hbr", "type": "synthesis", + "reactants": [{ "id": "H", "count": 1 }, { "id": "Br", "count": 1 }], + "products": [{ "id": "HBr", "count": 1 }], + "energyChange": -4, + "description": "Hydrogen + bromine → hydrobromic acid, a strong acid", + "descriptionRu": "Водород + бром → бромоводородная кислота, сильная кислота", + "difficulty": 1 + }, + { + "id": "synth_hi", "type": "synthesis", + "reactants": [{ "id": "H", "count": 1 }, { "id": "I", "count": 1 }], + "products": [{ "id": "HI", "count": 1 }], + "energyChange": -3, + "description": "Hydrogen + iodine → hydroiodic acid. Strongest hydrohalic acid", + "descriptionRu": "Водород + йод → йодоводородная кислота. Самая сильная галогенводородная кислота", + "difficulty": 1 + }, + { + "id": "synth_licl", "type": "synthesis", + "reactants": [{ "id": "Li", "count": 1 }, { "id": "Cl", "count": 1 }], + "products": [{ "id": "LiCl", "count": 1 }], + "energyChange": -38, + "description": "Lithium + chlorine → lithium chloride. Hygroscopic desiccant", + "descriptionRu": "Литий + хлор → хлорид лития. Гигроскопичный осушитель", + "difficulty": 1 + }, + { + "id": "synth_lioh", "type": "synthesis", + "reactants": [{ "id": "Li", "count": 1 }, { "id": "O", "count": 1 }, { "id": "H", "count": 1 }], + "products": [{ "id": "LiOH", "count": 1 }], + "energyChange": -45, + "description": "Lithium hydroxide synthesis. Used in spacecraft CO₂ scrubbers", + "descriptionRu": "Синтез гидроксида лития. Используется для очистки воздуха на космических кораблях", + "difficulty": 2 + }, + { + "id": "synth_agcl", "type": "synthesis", + "reactants": [{ "id": "Ag", "count": 1 }, { "id": "Cl", "count": 1 }], + "products": [{ "id": "AgCl", "count": 1 }], + "energyChange": -13, + "description": "Silver + chlorine → silver chloride. Darkens in light — basis of photography", + "descriptionRu": "Серебро + хлор → хлорид серебра. Темнеет на свету — основа фотографии", + "difficulty": 2 + }, + { + "id": "synth_agbr", "type": "synthesis", + "reactants": [{ "id": "Ag", "count": 1 }, { "id": "Br", "count": 1 }], + "products": [{ "id": "AgBr", "count": 1 }], + "energyChange": -10, + "description": "Silver + bromine → silver bromide. More light-sensitive than AgCl", + "descriptionRu": "Серебро + бром → бромид серебра. Светочувствительнее AgCl", + "difficulty": 2 + }, + { + "id": "synth_pbs", "type": "synthesis", + "reactants": [{ "id": "Pb", "count": 1 }, { "id": "S", "count": 1 }], + "products": [{ "id": "PbS", "count": 1 }], + "conditions": { "minTemp": 500 }, + "energyChange": -10, + "description": "Lead + sulfur → galena (lead sulfide). First semiconductor", + "descriptionRu": "Свинец + сера → галенит (сульфид свинца). Первый полупроводник", + "difficulty": 2 + }, + { + "id": "synth_nicl2", "type": "synthesis", + "reactants": [{ "id": "Ni", "count": 1 }, { "id": "Cl", "count": 2 }], + "products": [{ "id": "NiCl2", "count": 1 }], + "energyChange": -31, + "description": "Nickel + chlorine → green nickel chloride. Electroplating reagent", + "descriptionRu": "Никель + хлор → зелёный хлорид никеля. Реагент для гальваники", + "difficulty": 2 + }, + { + "id": "synth_naf", "type": "synthesis", + "reactants": [{ "id": "Na", "count": 1 }, { "id": "F", "count": 1 }], + "products": [{ "id": "NaF", "count": 1 }], + "energyChange": -57, + "description": "Sodium + fluorine → sodium fluoride. Active ingredient in toothpaste", + "descriptionRu": "Натрий + фтор → фторид натрия. Активный компонент зубной пасты", + "difficulty": 1 + }, + { + "id": "synth_nabr", "type": "synthesis", + "reactants": [{ "id": "Na", "count": 1 }, { "id": "Br", "count": 1 }], + "products": [{ "id": "NaBr", "count": 1 }], + "energyChange": -36, + "description": "Sodium + bromine → sodium bromide. Historical sedative", + "descriptionRu": "Натрий + бром → бромид натрия. Историческое седативное средство", + "difficulty": 1 + }, + { + "id": "synth_kf", "type": "synthesis", + "reactants": [{ "id": "K", "count": 1 }, { "id": "F", "count": 1 }], + "products": [{ "id": "KF", "count": 1 }], + "energyChange": -56, + "description": "Potassium + fluorine → potassium fluoride", + "descriptionRu": "Калий + фтор → фторид калия", + "difficulty": 1 + }, + { + "id": "synth_kbr", "type": "synthesis", + "reactants": [{ "id": "K", "count": 1 }, { "id": "Br", "count": 1 }], + "products": [{ "id": "KBr", "count": 1 }], + "energyChange": -39, + "description": "Potassium + bromine → potassium bromide. Photography essential", + "descriptionRu": "Калий + бром → бромид калия. Незаменим в фотографии", + "difficulty": 1 + }, + { + "id": "synth_mgcl2", "type": "synthesis", + "reactants": [{ "id": "Mg", "count": 1 }, { "id": "Cl", "count": 2 }], + "products": [{ "id": "MgCl2", "count": 1 }], + "energyChange": -64, + "description": "Magnesium + chlorine → magnesium chloride. De-icing salt", + "descriptionRu": "Магний + хлор → хлорид магния. Противогололёдная соль", + "difficulty": 1 + }, + { + "id": "synth_cacl2", "type": "synthesis", + "reactants": [{ "id": "Ca", "count": 1 }, { "id": "Cl", "count": 2 }], + "products": [{ "id": "CaCl2", "count": 1 }], + "energyChange": -80, + "description": "Calcium + chlorine → calcium chloride. Powerful desiccant", + "descriptionRu": "Кальций + хлор → хлорид кальция. Мощный осушитель", + "difficulty": 1 + }, + { + "id": "synth_bacl2", "type": "synthesis", + "reactants": [{ "id": "Ba", "count": 1 }, { "id": "Cl", "count": 2 }], + "products": [{ "id": "BaCl2", "count": 1 }], + "energyChange": -86, + "description": "Barium + chlorine → barium chloride. Green flame reagent", + "descriptionRu": "Барий + хлор → хлорид бария. Реагент зелёного пламени", + "difficulty": 1 + }, + { + "id": "synth_fecl3", "type": "synthesis", + "reactants": [{ "id": "Fe", "count": 1 }, { "id": "Cl", "count": 3 }], + "products": [{ "id": "FeCl3", "count": 1 }], + "conditions": { "minTemp": 500 }, + "energyChange": -40, + "description": "Iron + excess chlorine → iron(III) chloride. Etches copper circuit boards", + "descriptionRu": "Железо + избыток хлора → хлорид железа(III). Травит медные платы", + "difficulty": 2 + }, + { + "id": "synth_fecl2", "type": "synthesis", + "reactants": [{ "id": "Fe", "count": 1 }, { "id": "Cl", "count": 2 }], + "products": [{ "id": "FeCl2", "count": 1 }], + "energyChange": -34, + "description": "Iron + chlorine → iron(II) chloride. Reducing agent", + "descriptionRu": "Железо + хлор → хлорид железа(II). Восстановитель", + "difficulty": 2 + }, + { + "id": "synth_cucl2", "type": "synthesis", + "reactants": [{ "id": "Cu", "count": 1 }, { "id": "Cl", "count": 2 }], + "products": [{ "id": "CuCl2", "count": 1 }], + "conditions": { "minTemp": 500 }, + "energyChange": -22, + "description": "Copper + chlorine at heat → green copper(II) chloride crystals", + "descriptionRu": "Медь + хлор при нагреве → зелёные кристаллы хлорида меди(II)", + "difficulty": 2 + }, + { + "id": "synth_zncl2", "type": "synthesis", + "reactants": [{ "id": "Zn", "count": 1 }, { "id": "Cl", "count": 2 }], + "products": [{ "id": "ZnCl2", "count": 1 }], + "energyChange": -42, + "description": "Zinc + chlorine → zinc chloride. Soldering flux", + "descriptionRu": "Цинк + хлор → хлорид цинка. Паяльный флюс", + "difficulty": 1 + }, + { + "id": "synth_na2o", "type": "synthesis", + "reactants": [{ "id": "Na", "count": 2 }, { "id": "O", "count": 1 }], + "products": [{ "id": "Na2O", "count": 1 }], + "conditions": { "minTemp": 500 }, + "energyChange": -42, + "description": "Sodium burns in limited oxygen → sodium oxide. Key to glass making", + "descriptionRu": "Натрий горит в ограниченном кислороде → оксид натрия. Ключ к стекловарению", + "difficulty": 2 + }, + { + "id": "synth_nh3", "type": "synthesis", + "reactants": [{ "id": "N", "count": 1 }, { "id": "H", "count": 3 }], + "products": [{ "id": "NH3", "count": 1 }], + "conditions": { "minTemp": 500, "catalyst": "Fe" }, + "energyChange": -5, + "description": "Haber process: nitrogen + hydrogen with iron catalyst → ammonia. Nobel Prize reaction", + "descriptionRu": "Процесс Габера: азот + водород с железным катализатором → аммиак. Нобелевская реакция", + "difficulty": 3 + }, + { + "id": "synth_h2s", "type": "synthesis", + "reactants": [{ "id": "H", "count": 2 }, { "id": "S", "count": 1 }], + "products": [{ "id": "H2S", "count": 1 }], + "conditions": { "minTemp": 500 }, + "energyChange": -2, + "description": "Hydrogen + sulfur → hydrogen sulfide. Rotten egg gas", + "descriptionRu": "Водород + сера → сероводород. Газ с запахом тухлых яиц", + "difficulty": 2 + }, + { + "id": "synth_h2so4", "type": "synthesis", + "reactants": [{ "id": "S", "count": 1 }, { "id": "O", "count": 3 }, { "id": "H", "count": 2 }], + "products": [{ "id": "H2SO4", "count": 1 }], + "conditions": { "catalyst": "Pt" }, + "energyChange": -14, + "description": "Contact process: sulfur, oxygen, hydrogen with platinum catalyst → sulfuric acid", + "descriptionRu": "Контактный процесс: сера, кислород, водород с платиновым катализатором → серная кислота", + "difficulty": 4 + }, + { + "id": "synth_hno3", "type": "synthesis", + "reactants": [{ "id": "N", "count": 1 }, { "id": "O", "count": 3 }, { "id": "H", "count": 1 }], + "products": [{ "id": "HNO3", "count": 1 }], + "conditions": { "catalyst": "Pt" }, + "energyChange": -5, + "description": "Ostwald process: nitrogen, oxygen, hydrogen with platinum catalyst → nitric acid", + "descriptionRu": "Процесс Оствальда: азот, кислород, водород с платиновым катализатором → азотная кислота", + "difficulty": 4 + }, + { + "id": "synth_nh4cl", "type": "synthesis", + "reactants": [{ "id": "NH3", "count": 1 }, { "id": "HCl", "count": 1 }], + "products": [{ "id": "NH4Cl", "count": 1 }], + "energyChange": -18, + "description": "Ammonia + HCl → white smoke of ammonium chloride! Classic demonstration", + "descriptionRu": "Аммиак + HCl → белый дым хлорида аммония! Классическая демонстрация", + "difficulty": 2 + }, + { + "id": "synth_ch3cooh", "type": "synthesis", + "reactants": [{ "id": "C", "count": 2 }, { "id": "H", "count": 4 }, { "id": "O", "count": 2 }], + "products": [{ "id": "CH3COOH", "count": 1 }], + "conditions": { "catalyst": "Cu" }, + "energyChange": -5, + "description": "Acetic acid synthesis with copper catalyst. The chemistry of vinegar", + "descriptionRu": "Синтез уксусной кислоты с медным катализатором. Химия уксуса", + "difficulty": 4 + }, + { + "id": "synth_c6h12o6", "type": "synthesis", + "reactants": [{ "id": "C", "count": 6 }, { "id": "H", "count": 12 }, { "id": "O", "count": 6 }], + "products": [{ "id": "C6H12O6", "count": 1 }], + "conditions": { "requiresEnergy": true }, + "energyChange": 28, + "description": "Artificial photosynthesis: assembling glucose from its elements. Requires enormous energy", + "descriptionRu": "Искусственный фотосинтез: сборка глюкозы из элементов. Требует огромной энергии", + "difficulty": 5 + }, + + { + "id": "comb_tio2", "type": "combustion", + "reactants": [{ "id": "Ti", "count": 1 }, { "id": "O", "count": 2 }], + "products": [{ "id": "TiO2", "count": 1 }], + "conditions": { "minTemp": 1000 }, + "energyChange": -94, + "description": "Titanium burns brilliantly in pure oxygen. Produces white titanium dioxide", + "descriptionRu": "Титан ярко горит в чистом кислороде. Образует белый диоксид титана", + "difficulty": 4 + }, + { + "id": "comb_cr2o3", "type": "combustion", + "reactants": [{ "id": "Cr", "count": 2 }, { "id": "O", "count": 3 }], + "products": [{ "id": "Cr2O3", "count": 1 }], + "conditions": { "minTemp": 1000 }, + "energyChange": -113, + "description": "Chromium oxidation at extreme heat → green chromium oxide. Hard as corundum", + "descriptionRu": "Окисление хрома при экстремальном нагреве → зелёный оксид хрома. Твёрд как корунд", + "difficulty": 4 + }, + { + "id": "comb_mno2", "type": "combustion", + "reactants": [{ "id": "Mn", "count": 1 }, { "id": "O", "count": 2 }], + "products": [{ "id": "MnO2", "count": 1 }], + "conditions": { "minTemp": 500 }, + "energyChange": -52, + "description": "Manganese + oxygen → manganese dioxide. Nature's battery material and catalyst", + "descriptionRu": "Марганец + кислород → диоксид марганца. Природный материал батарей и катализатор", + "difficulty": 3 + }, + { + "id": "comb_coo", "type": "combustion", + "reactants": [{ "id": "Co", "count": 1 }, { "id": "O", "count": 1 }], + "products": [{ "id": "CoO", "count": 1 }], + "conditions": { "minTemp": 500 }, + "energyChange": -24, + "description": "Cobalt burns to form cobalt oxide — brilliant blue ceramic pigment", + "descriptionRu": "Кобальт горит, образуя оксид кобальта — великолепный синий керамический пигмент", + "difficulty": 2 + }, + { + "id": "comb_cuo", "type": "combustion", + "reactants": [{ "id": "Cu", "count": 1 }, { "id": "O", "count": 1 }], + "products": [{ "id": "CuO", "count": 1 }], + "conditions": { "minTemp": 500 }, + "energyChange": -16, + "description": "Copper oxidation → black copper(II) oxide. Basis of ancient smelting", + "descriptionRu": "Окисление меди → чёрный оксид меди(II). Основа древней металлургии", + "difficulty": 2 + }, + { + "id": "comb_bao", "type": "combustion", + "reactants": [{ "id": "Ba", "count": 1 }, { "id": "O", "count": 1 }], + "products": [{ "id": "BaO", "count": 1 }], + "conditions": { "minTemp": 500 }, + "energyChange": -56, + "description": "Barium burns with brilliant GREEN flame → barium oxide", + "descriptionRu": "Барий горит ярко-ЗЕЛЁНЫМ пламенем → оксид бария", + "difficulty": 2 + }, + { + "id": "comb_wo3", "type": "combustion", + "reactants": [{ "id": "W", "count": 1 }, { "id": "O", "count": 3 }], + "products": [{ "id": "WO3", "count": 1 }], + "conditions": { "minTemp": 1000 }, + "energyChange": -84, + "description": "Tungsten slowly oxidizes only at extreme temperatures. Highest melting point element", + "descriptionRu": "Вольфрам окисляется лишь при экстремальных температурах. Элемент с наивысшей температурой плавления", + "difficulty": 5 + }, + { + "id": "comb_pbo", "type": "combustion", + "reactants": [{ "id": "Pb", "count": 1 }, { "id": "O", "count": 1 }], + "products": [{ "id": "PbO", "count": 1 }], + "conditions": { "minTemp": 500 }, + "energyChange": -22, + "description": "Lead oxidation → litharge (yellow lead oxide). Battery material", + "descriptionRu": "Окисление свинца → глёт (жёлтый оксид свинца). Материал аккумуляторов", + "difficulty": 2 + }, + { + "id": "comb_bi2o3", "type": "combustion", + "reactants": [{ "id": "Bi", "count": 2 }, { "id": "O", "count": 3 }], + "products": [{ "id": "Bi2O3", "count": 1 }], + "conditions": { "minTemp": 500 }, + "energyChange": -58, + "description": "Bismuth burns → bismuth trioxide. Medicinal compound", + "descriptionRu": "Висмут горит → оксид висмута(III). Лекарственное соединение", + "difficulty": 3 + }, + { + "id": "comb_uo2", "type": "combustion", + "reactants": [{ "id": "U", "count": 1 }, { "id": "O", "count": 2 }], + "products": [{ "id": "UO2", "count": 1 }], + "conditions": { "minTemp": 1000 }, + "energyChange": -109, + "description": "Uranium oxidation → uranium dioxide. Nuclear fuel pellets", + "descriptionRu": "Окисление урана → диоксид урана. Таблетки ядерного топлива", + "difficulty": 5 + }, + { + "id": "comb_as2o3", "type": "combustion", + "reactants": [{ "id": "As", "count": 2 }, { "id": "O", "count": 3 }], + "products": [{ "id": "As2O3", "count": 1 }], + "conditions": { "minTemp": 500 }, + "energyChange": -66, + "description": "Arsenic combustion → arsenic trioxide. The 'King of Poisons'", + "descriptionRu": "Горение мышьяка → оксид мышьяка(III). «Король ядов»", + "difficulty": 3 + }, + { + "id": "comb_ch4", "type": "combustion", + "reactants": [{ "id": "CH4", "count": 1 }, { "id": "O", "count": 4 }], + "products": [{ "id": "CO2", "count": 1 }, { "id": "H2O", "count": 2 }], + "conditions": { "minTemp": 500 }, + "energyChange": -89, + "description": "Methane combustion: natural gas burning. Clean energy source", + "descriptionRu": "Горение метана: сжигание природного газа. Чистый источник энергии", + "difficulty": 2 + }, + { + "id": "comb_c2h5oh", "type": "combustion", + "reactants": [{ "id": "C2H5OH", "count": 1 }, { "id": "O", "count": 6 }], + "products": [{ "id": "CO2", "count": 2 }, { "id": "H2O", "count": 3 }], + "conditions": { "minTemp": 500 }, + "energyChange": -137, + "description": "Ethanol burns with blue flame. Clean-burning biofuel", + "descriptionRu": "Этанол горит синим пламенем. Чистое биотопливо", + "difficulty": 3 + }, + { + "id": "comb_h2s", "type": "combustion", + "reactants": [{ "id": "H2S", "count": 1 }, { "id": "O", "count": 3 }], + "products": [{ "id": "SO2", "count": 1 }, { "id": "H2O", "count": 1 }], + "conditions": { "minTemp": 500 }, + "energyChange": -52, + "description": "Hydrogen sulfide burns → sulfur dioxide + water. Converting one toxic gas to another", + "descriptionRu": "Сероводород горит → сернистый газ + вода. Превращение одного токсичного газа в другой", + "difficulty": 2 + }, + { + "id": "comb_co_full", "type": "combustion", + "reactants": [{ "id": "CO", "count": 1 }, { "id": "O", "count": 1 }], + "products": [{ "id": "CO2", "count": 1 }], + "conditions": { "minTemp": 500 }, + "energyChange": -28, + "description": "Carbon monoxide burns to carbon dioxide. Converting deadly poison to harmless gas", + "descriptionRu": "Угарный газ горит до углекислого. Превращение смертельного яда в безвредный газ", + "difficulty": 1 + }, + { + "id": "comb_glucose", "type": "combustion", + "reactants": [{ "id": "C6H12O6", "count": 1 }, { "id": "O", "count": 12 }], + "products": [{ "id": "CO2", "count": 6 }, { "id": "H2O", "count": 6 }], + "conditions": { "minTemp": 500 }, + "energyChange": -280, + "description": "Glucose combustion — same as cellular respiration. Maximum energy release from sugar", + "descriptionRu": "Горение глюкозы — то же, что клеточное дыхание. Максимальное выделение энергии из сахара", + "difficulty": 3 + }, + + { + "id": "repl_li_h2o", "type": "single-replacement", + "reactants": [{ "id": "Li", "count": 1 }, { "id": "H2O", "count": 1 }], + "products": [{ "id": "LiOH", "count": 1 }, { "id": "H", "count": 1 }], + "energyChange": -50, + "description": "Lithium fizzes gently in water → lithium hydroxide + hydrogen. Less violent than sodium", + "descriptionRu": "Литий тихо шипит в воде → гидроксид лития + водород. Менее бурно, чем натрий", + "difficulty": 1 + }, + { + "id": "repl_mg_hcl", "type": "single-replacement", + "reactants": [{ "id": "Mg", "count": 1 }, { "id": "HCl", "count": 2 }], + "products": [{ "id": "MgCl2", "count": 1 }, { "id": "H", "count": 2 }], + "energyChange": -46, + "description": "Magnesium dissolves in acid with vigorous hydrogen bubbling", + "descriptionRu": "Магний растворяется в кислоте с бурным выделением пузырьков водорода", + "difficulty": 2 + }, + { + "id": "repl_zn_hcl", "type": "single-replacement", + "reactants": [{ "id": "Zn", "count": 1 }, { "id": "HCl", "count": 2 }], + "products": [{ "id": "ZnCl2", "count": 1 }, { "id": "H", "count": 2 }], + "energyChange": -15, + "description": "Zinc dissolves in hydrochloric acid → zinc chloride + hydrogen gas", + "descriptionRu": "Цинк растворяется в соляной кислоте → хлорид цинка + водород", + "difficulty": 2 + }, + { + "id": "repl_fe_hcl", "type": "single-replacement", + "reactants": [{ "id": "Fe", "count": 1 }, { "id": "HCl", "count": 2 }], + "products": [{ "id": "FeCl2", "count": 1 }, { "id": "H", "count": 2 }], + "energyChange": -9, + "description": "Iron dissolves in acid → pale green iron(II) chloride + hydrogen", + "descriptionRu": "Железо растворяется в кислоте → бледно-зелёный хлорид железа(II) + водород", + "difficulty": 2 + }, + { + "id": "repl_ni_hcl", "type": "single-replacement", + "reactants": [{ "id": "Ni", "count": 1 }, { "id": "HCl", "count": 2 }], + "products": [{ "id": "NiCl2", "count": 1 }, { "id": "H", "count": 2 }], + "energyChange": -8, + "description": "Nickel dissolves slowly in HCl → green nickel chloride solution", + "descriptionRu": "Никель медленно растворяется в HCl → зелёный раствор хлорида никеля", + "difficulty": 2 + }, + { + "id": "repl_fe_cucl2", "type": "single-replacement", + "reactants": [{ "id": "Fe", "count": 1 }, { "id": "CuCl2", "count": 1 }], + "products": [{ "id": "FeCl2", "count": 1 }, { "id": "Cu", "count": 1 }], + "energyChange": -15, + "description": "Iron displaces copper from solution. Activity series: Fe > Cu", + "descriptionRu": "Железо вытесняет медь из раствора. Ряд активности: Fe > Cu", + "difficulty": 2 + }, + { + "id": "repl_zn_cucl2", "type": "single-replacement", + "reactants": [{ "id": "Zn", "count": 1 }, { "id": "CuCl2", "count": 1 }], + "products": [{ "id": "ZnCl2", "count": 1 }, { "id": "Cu", "count": 1 }], + "energyChange": -22, + "description": "Zinc displaces copper — red copper deposits on zinc surface", + "descriptionRu": "Цинк вытесняет медь — красная медь осаждается на поверхности цинка", + "difficulty": 2 + }, + { + "id": "repl_zn_fecl2", "type": "single-replacement", + "reactants": [{ "id": "Zn", "count": 1 }, { "id": "FeCl2", "count": 1 }], + "products": [{ "id": "ZnCl2", "count": 1 }, { "id": "Fe", "count": 1 }], + "energyChange": -7, + "description": "Zinc displaces iron from solution. Zinc is more reactive", + "descriptionRu": "Цинк вытесняет железо из раствора. Цинк активнее", + "difficulty": 2 + }, + { + "id": "repl_mg_cucl2", "type": "single-replacement", + "reactants": [{ "id": "Mg", "count": 1 }, { "id": "CuCl2", "count": 1 }], + "products": [{ "id": "MgCl2", "count": 1 }, { "id": "Cu", "count": 1 }], + "energyChange": -60, + "description": "Magnesium violently displaces copper. Extreme activity difference", + "descriptionRu": "Магний бурно вытесняет медь. Огромная разница активности", + "difficulty": 1 + }, + + { + "id": "ab_lioh_hcl", "type": "acid-base", + "reactants": [{ "id": "LiOH", "count": 1 }, { "id": "HCl", "count": 1 }], + "products": [{ "id": "LiCl", "count": 1 }, { "id": "H2O", "count": 1 }], + "energyChange": -55, + "description": "Neutralization: lithium hydroxide + hydrochloric acid → lithium chloride + water", + "descriptionRu": "Нейтрализация: гидроксид лития + соляная кислота → хлорид лития + вода", + "difficulty": 2 + }, + { + "id": "ab_naoh_hf", "type": "acid-base", + "reactants": [{ "id": "NaOH", "count": 1 }, { "id": "HF", "count": 1 }], + "products": [{ "id": "NaF", "count": 1 }, { "id": "H2O", "count": 1 }], + "energyChange": -68, + "description": "Neutralizing deadly HF with lye → safe sodium fluoride + water", + "descriptionRu": "Нейтрализация опасного HF щёлочью → безопасный фторид натрия + вода", + "difficulty": 2 + }, + { + "id": "ab_naoh_hbr", "type": "acid-base", + "reactants": [{ "id": "NaOH", "count": 1 }, { "id": "HBr", "count": 1 }], + "products": [{ "id": "NaBr", "count": 1 }, { "id": "H2O", "count": 1 }], + "energyChange": -56, + "description": "Neutralization: NaOH + HBr → sodium bromide + water", + "descriptionRu": "Нейтрализация: NaOH + HBr → бромид натрия + вода", + "difficulty": 2 + }, + { + "id": "ab_koh_hf", "type": "acid-base", + "reactants": [{ "id": "KOH", "count": 1 }, { "id": "HF", "count": 1 }], + "products": [{ "id": "KF", "count": 1 }, { "id": "H2O", "count": 1 }], + "energyChange": -68, + "description": "Potassium hydroxide neutralizes hydrofluoric acid", + "descriptionRu": "Гидроксид калия нейтрализует плавиковую кислоту", + "difficulty": 2 + }, + { + "id": "ab_koh_hbr", "type": "acid-base", + "reactants": [{ "id": "KOH", "count": 1 }, { "id": "HBr", "count": 1 }], + "products": [{ "id": "KBr", "count": 1 }, { "id": "H2O", "count": 1 }], + "energyChange": -56, + "description": "KOH + HBr → potassium bromide + water", + "descriptionRu": "KOH + HBr → бромид калия + вода", + "difficulty": 2 + }, + { + "id": "ab_caco3_hcl", "type": "acid-base", + "reactants": [{ "id": "CaCO3", "count": 1 }, { "id": "HCl", "count": 2 }], + "products": [{ "id": "CaCl2", "count": 1 }, { "id": "H2O", "count": 1 }, { "id": "CO2", "count": 1 }], + "energyChange": -12, + "description": "Limestone + acid → fizzing! Calcium chloride + water + CO₂. The cave dissolving reaction", + "descriptionRu": "Известняк + кислота → шипение! Хлорид кальция + вода + CO₂. Реакция растворения пещер", + "difficulty": 2 + }, + { + "id": "ab_cuo_hcl", "type": "acid-base", + "reactants": [{ "id": "CuO", "count": 1 }, { "id": "HCl", "count": 2 }], + "products": [{ "id": "CuCl2", "count": 1 }, { "id": "H2O", "count": 1 }], + "energyChange": -13, + "description": "Copper oxide + acid → blue-green copper chloride solution + water", + "descriptionRu": "Оксид меди + кислота → сине-зелёный раствор хлорида меди + вода", + "difficulty": 2 + }, + { + "id": "ab_zno_hcl", "type": "acid-base", + "reactants": [{ "id": "ZnO", "count": 1 }, { "id": "HCl", "count": 2 }], + "products": [{ "id": "ZnCl2", "count": 1 }, { "id": "H2O", "count": 1 }], + "energyChange": -14, + "description": "Zinc oxide + acid → zinc chloride + water. Classic oxide-acid reaction", + "descriptionRu": "Оксид цинка + кислота → хлорид цинка + вода. Классическая реакция оксида с кислотой", + "difficulty": 2 + }, + { + "id": "ab_mgo_hcl", "type": "acid-base", + "reactants": [{ "id": "MgO", "count": 1 }, { "id": "HCl", "count": 2 }], + "products": [{ "id": "MgCl2", "count": 1 }, { "id": "H2O", "count": 1 }], + "energyChange": -15, + "description": "Antacid reaction: magnesium oxide neutralizes stomach acid", + "descriptionRu": "Антацидная реакция: оксид магния нейтрализует желудочную кислоту", + "difficulty": 2 + }, + { + "id": "ab_bao_hcl", "type": "acid-base", + "reactants": [{ "id": "BaO", "count": 1 }, { "id": "HCl", "count": 2 }], + "products": [{ "id": "BaCl2", "count": 1 }, { "id": "H2O", "count": 1 }], + "energyChange": -17, + "description": "Barium oxide + acid → toxic barium chloride. Handle carefully", + "descriptionRu": "Оксид бария + кислота → токсичный хлорид бария. Осторожно", + "difficulty": 2 + }, + { + "id": "ab_caoh2_hcl", "type": "acid-base", + "reactants": [{ "id": "CaOH2", "count": 1 }, { "id": "HCl", "count": 2 }], + "products": [{ "id": "CaCl2", "count": 1 }, { "id": "H2O", "count": 2 }], + "energyChange": -58, + "description": "Slaked lime + acid → calcium chloride + water. Water treatment", + "descriptionRu": "Гашёная известь + кислота → хлорид кальция + вода. Очистка воды", + "difficulty": 2 + }, + { + "id": "ab_na2o_hcl", "type": "acid-base", + "reactants": [{ "id": "Na2O", "count": 1 }, { "id": "HCl", "count": 2 }], + "products": [{ "id": "NaCl", "count": 2 }, { "id": "H2O", "count": 1 }], + "energyChange": -60, + "description": "Sodium oxide + acid → table salt + water", + "descriptionRu": "Оксид натрия + кислота → поваренная соль + вода", + "difficulty": 2 + }, + { + "id": "repl_na2o_h2o", "type": "single-replacement", + "reactants": [{ "id": "Na2O", "count": 1 }, { "id": "H2O", "count": 1 }], + "products": [{ "id": "NaOH", "count": 2 }], + "energyChange": -70, + "description": "Sodium oxide dissolves in water → caustic soda (NaOH). Exothermic!", + "descriptionRu": "Оксид натрия растворяется в воде → каустическая сода (NaOH). Экзотермическая!", + "difficulty": 1 + }, + + { + "id": "decomp_nh3", "type": "decomposition", + "reactants": [{ "id": "NH3", "count": 1 }], + "products": [{ "id": "N", "count": 1 }, { "id": "H", "count": 3 }], + "conditions": { "minTemp": 1000 }, + "energyChange": 5, + "description": "Ammonia decomposes at extreme heat → nitrogen + hydrogen. Reversed Haber process", + "descriptionRu": "Аммиак разлагается при экстремальном нагреве → азот + водород. Обратный процесс Габера", + "difficulty": 3 + }, + { + "id": "decomp_h2s", "type": "decomposition", + "reactants": [{ "id": "H2S", "count": 1 }], + "products": [{ "id": "H", "count": 2 }, { "id": "S", "count": 1 }], + "conditions": { "minTemp": 1000 }, + "energyChange": 2, + "description": "Thermal decomposition of hydrogen sulfide → hydrogen + sulfur", + "descriptionRu": "Термическое разложение сероводорода → водород + сера", + "difficulty": 3 + }, + { + "id": "decomp_hno3", "type": "decomposition", + "reactants": [{ "id": "HNO3", "count": 1 }], + "products": [{ "id": "N", "count": 1 }, { "id": "O", "count": 3 }, { "id": "H", "count": 1 }], + "conditions": { "minTemp": 500 }, + "energyChange": 5, + "description": "Nitric acid decomposes under heat → brown toxic fumes", + "descriptionRu": "Азотная кислота разлагается при нагреве → бурые токсичные пары", + "difficulty": 3 + }, + { + "id": "decomp_h2so4", "type": "decomposition", + "reactants": [{ "id": "H2SO4", "count": 1 }], + "products": [{ "id": "S", "count": 1 }, { "id": "O", "count": 3 }, { "id": "H", "count": 2 }], + "conditions": { "minTemp": 1000 }, + "energyChange": 10, + "description": "Sulfuric acid decomposition at extreme heat. Very endothermic", + "descriptionRu": "Разложение серной кислоты при экстремальном нагреве. Сильно эндотермическое", + "difficulty": 4 + }, + + { + "id": "decomp_nacl_electro", "type": "decomposition", + "reactants": [{ "id": "NaCl", "count": 1 }], + "products": [{ "id": "Na", "count": 1 }, { "id": "Cl", "count": 1 }], + "conditions": { "requiresEnergy": true }, + "energyChange": 41, + "description": "Electrolysis of molten salt → pure sodium + chlorine gas. Industrial sodium production", + "descriptionRu": "Электролиз расплава соли → чистый натрий + хлор. Промышленное получение натрия", + "difficulty": 3 + }, + { + "id": "decomp_mgcl2", "type": "decomposition", + "reactants": [{ "id": "MgCl2", "count": 1 }], + "products": [{ "id": "Mg", "count": 1 }, { "id": "Cl", "count": 2 }], + "conditions": { "requiresEnergy": true }, + "energyChange": 64, + "description": "Electrolysis of molten MgCl₂ → magnesium metal + chlorine. Dow process", + "descriptionRu": "Электролиз расплава MgCl₂ → металлический магний + хлор. Процесс Дау", + "difficulty": 3 + }, + { + "id": "decomp_cacl2", "type": "decomposition", + "reactants": [{ "id": "CaCl2", "count": 1 }], + "products": [{ "id": "Ca", "count": 1 }, { "id": "Cl", "count": 2 }], + "conditions": { "requiresEnergy": true }, + "energyChange": 80, + "description": "Electrolysis of molten CaCl₂ → pure calcium metal", + "descriptionRu": "Электролиз расплава CaCl₂ → чистый металлический кальций", + "difficulty": 3 + }, + { + "id": "decomp_al2o3", "type": "decomposition", + "reactants": [{ "id": "Al2O3", "count": 1 }], + "products": [{ "id": "Al", "count": 2 }, { "id": "O", "count": 3 }], + "conditions": { "requiresEnergy": true }, + "energyChange": 84, + "description": "Hall-Héroult process: alumina electrolysis → aluminum. Most energy-intensive industrial process", + "descriptionRu": "Процесс Холла-Эру: электролиз глинозёма → алюминий. Самый энергоёмкий промышленный процесс", + "difficulty": 4 + }, + { + "id": "decomp_fecl3", "type": "decomposition", + "reactants": [{ "id": "FeCl3", "count": 1 }], + "products": [{ "id": "Fe", "count": 1 }, { "id": "Cl", "count": 3 }], + "conditions": { "minTemp": 1000 }, + "energyChange": 40, + "description": "Iron(III) chloride thermal decomposition → iron + chlorine gas", + "descriptionRu": "Термическое разложение хлорида железа(III) → железо + хлор", + "difficulty": 3 + }, + + { + "id": "redox_cr2o3_al", "type": "redox", + "reactants": [{ "id": "Cr2O3", "count": 1 }, { "id": "Al", "count": 2 }], + "products": [{ "id": "Cr", "count": 2 }, { "id": "Al2O3", "count": 1 }], + "conditions": { "minTemp": 1000 }, + "energyChange": -54, + "description": "Chromium thermite: aluminium reduces chromium oxide. Used to produce pure chromium", + "descriptionRu": "Хромовый термит: алюминий восстанавливает оксид хрома. Производство чистого хрома", + "difficulty": 5 + }, + { + "id": "redox_wo3_al", "type": "redox", + "reactants": [{ "id": "WO3", "count": 1 }, { "id": "Al", "count": 2 }], + "products": [{ "id": "W", "count": 1 }, { "id": "Al2O3", "count": 1 }], + "conditions": { "minTemp": 1000 }, + "energyChange": -70, + "description": "Tungsten extraction: aluminum reduces tungsten oxide to pure metal", + "descriptionRu": "Извлечение вольфрама: алюминий восстанавливает оксид вольфрама до чистого металла", + "difficulty": 5 + }, + { + "id": "redox_cuo_c", "type": "redox", + "reactants": [{ "id": "CuO", "count": 1 }, { "id": "C", "count": 1 }], + "products": [{ "id": "Cu", "count": 1 }, { "id": "CO", "count": 1 }], + "conditions": { "minTemp": 1000 }, + "energyChange": -13, + "description": "Ancient copper smelting: carbon reduces copper ore to pure copper", + "descriptionRu": "Древняя медеплавка: углерод восстанавливает медную руду до чистой меди", + "difficulty": 3 + }, + { + "id": "redox_pbo_c", "type": "redox", + "reactants": [{ "id": "PbO", "count": 1 }, { "id": "C", "count": 1 }], + "products": [{ "id": "Pb", "count": 1 }, { "id": "CO", "count": 1 }], + "conditions": { "minTemp": 1000 }, + "energyChange": -11, + "description": "Lead smelting: carbon reduces lead oxide to metallic lead", + "descriptionRu": "Свинцовая плавка: углерод восстанавливает оксид свинца до металлического свинца", + "difficulty": 3 + }, + { + "id": "redox_fe2o3_c", "type": "redox", + "reactants": [{ "id": "Fe2O3", "count": 1 }, { "id": "C", "count": 3 }], + "products": [{ "id": "Fe", "count": 2 }, { "id": "CO", "count": 3 }], + "conditions": { "minTemp": 1000 }, + "energyChange": -49, + "description": "Iron smelting: carbon reduces iron ore. Foundation of civilization", + "descriptionRu": "Выплавка железа: углерод восстанавливает железную руду. Основа цивилизации", + "difficulty": 4 + }, + { + "id": "redox_coo_c", "type": "redox", + "reactants": [{ "id": "CoO", "count": 1 }, { "id": "C", "count": 1 }], + "products": [{ "id": "Co", "count": 1 }, { "id": "CO", "count": 1 }], + "conditions": { "minTemp": 1000 }, + "energyChange": -10, + "description": "Carbon reduces cobalt oxide → pure cobalt. Blue pigment source", + "descriptionRu": "Углерод восстанавливает оксид кобальта → чистый кобальт. Источник синего пигмента", + "difficulty": 3 + }, + { + "id": "redox_fe2o3_co", "type": "redox", + "reactants": [{ "id": "Fe2O3", "count": 1 }, { "id": "CO", "count": 3 }], + "products": [{ "id": "Fe", "count": 2 }, { "id": "CO2", "count": 3 }], + "conditions": { "minTemp": 1000 }, + "energyChange": -25, + "description": "Blast furnace: CO reduces iron ore to iron + CO₂. Industrial steelmaking", + "descriptionRu": "Доменная печь: CO восстанавливает железную руду до железа + CO₂. Промышленная металлургия", + "difficulty": 4 + }, + { + "id": "redox_cuo_h", "type": "redox", + "reactants": [{ "id": "CuO", "count": 1 }, { "id": "H", "count": 2 }], + "products": [{ "id": "Cu", "count": 1 }, { "id": "H2O", "count": 1 }], + "conditions": { "minTemp": 500 }, + "energyChange": -13, + "description": "Hydrogen reduces copper oxide → shiny red copper appears + water", + "descriptionRu": "Водород восстанавливает оксид меди → появляется блестящая красная медь + вода", + "difficulty": 3 + }, + + { + "id": "ferment_glucose", "type": "decomposition", + "reactants": [{ "id": "C6H12O6", "count": 1 }], + "products": [{ "id": "C2H5OH", "count": 2 }, { "id": "CO2", "count": 2 }], + "energyChange": -7, + "description": "Fermentation: yeast converts glucose → ethanol + CO₂. Birth of brewing and baking", + "descriptionRu": "Брожение: дрожжи превращают глюкозу → этанол + CO₂. Рождение пивоварения и хлебопечения", + "difficulty": 3 + }, + { + "id": "decomp_ch3cooh", "type": "decomposition", + "reactants": [{ "id": "CH3COOH", "count": 1 }], + "products": [{ "id": "C", "count": 2 }, { "id": "H", "count": 4 }, { "id": "O", "count": 2 }], + "conditions": { "minTemp": 1000 }, + "energyChange": 5, + "description": "Thermal decomposition of acetic acid at extreme heat", + "descriptionRu": "Термическое разложение уксусной кислоты при экстремальном нагреве", + "difficulty": 3 } ] diff --git a/src/scenes/CradleScene.ts b/src/scenes/CradleScene.ts index 6fe0166..45d0701 100644 --- a/src/scenes/CradleScene.ts +++ b/src/scenes/CradleScene.ts @@ -8,7 +8,9 @@ import Phaser from 'phaser'; import schoolsData from '../data/schools.json'; +import biomeDataArray from '../data/biomes.json'; import type { SchoolData, MetaState } from '../run/types'; +import type { BiomeData } from '../world/types'; import { isSchoolUnlocked } from '../run/meta'; import { GAME_WIDTH, GAME_HEIGHT } from '../config'; import { getAvailableBonuses, purchaseBonus, canAffordBonus, resetShopSession } from '../mycelium/shop'; @@ -16,11 +18,14 @@ import { getGraphStats } from '../mycelium/graph'; import type { BonusEffect } from '../mycelium/types'; const schools = schoolsData as SchoolData[]; +const biomes = biomeDataArray as BiomeData[]; export class CradleScene extends Phaser.Scene { private meta!: MetaState; private selectedIndex = 0; + private selectedBiomeIndex = 0; private schoolCards: Phaser.GameObjects.Container[] = []; + private biomeCards: { bg: Phaser.GameObjects.Rectangle; label: Phaser.GameObjects.Text }[] = []; private particles: { x: number; y: number; vx: number; vy: number; alpha: number; radius: number }[] = []; private particleGraphics!: Phaser.GameObjects.Graphics; private introTimer = 0; @@ -36,7 +41,9 @@ export class CradleScene extends Phaser.Scene { init(data: { meta: MetaState }): void { this.meta = data.meta; this.selectedIndex = 0; + this.selectedBiomeIndex = 0; this.schoolCards = []; + this.biomeCards = []; this.introTimer = 0; this.introComplete = false; this.purchasedEffects = []; @@ -124,7 +131,7 @@ export class CradleScene extends Phaser.Scene { const cx = GAME_WIDTH / 2; // Title - const title = this.add.text(cx, 60, 'СПОРОВАЯ КОЛЫБЕЛЬ', { + const title = this.add.text(cx, 30, 'СПОРОВАЯ КОЛЫБЕЛЬ', { fontSize: '28px', color: '#00ff88', fontFamily: 'monospace', @@ -134,7 +141,7 @@ export class CradleScene extends Phaser.Scene { title.setAlpha(0); title.setDepth(10); - const subtitle = this.add.text(cx, 100, 'Выбери свой путь', { + const subtitle = this.add.text(cx, 65, 'Выбери биом и школу', { fontSize: '14px', color: '#557755', fontFamily: 'monospace', @@ -145,10 +152,13 @@ export class CradleScene extends Phaser.Scene { this.tweens.add({ targets: [title, subtitle], alpha: 1, duration: 800 }); + // Biome selection row + this.createBiomeSelector(cx, 105); + // School cards const cardWidth = 320; - const cardHeight = 260; - const startY = 160; + const cardHeight = 220; + const startY = 150; const unlockedSchools = schools.filter(s => isSchoolUnlocked(this.meta, s.id)); for (let i = 0; i < unlockedSchools.length; i++) { @@ -361,16 +371,98 @@ export class CradleScene extends Phaser.Scene { } } + /** Create the biome selection row */ + private createBiomeSelector(cx: number, y: number): void { + const btnWidth = 200; + const btnHeight = 36; + const spacing = 12; + const totalWidth = biomes.length * (btnWidth + spacing) - spacing; + const startX = cx - totalWidth / 2 + btnWidth / 2; + + const biomeColors: Record = { + 'catalytic-wastes': 0x886622, + 'kinetic-mountains': 0x5577aa, + 'verdant-forests': 0x228833, + }; + + for (let i = 0; i < biomes.length; i++) { + const biome = biomes[i]; + const bx = startX + i * (btnWidth + spacing); + const isSelected = i === this.selectedBiomeIndex; + const color = biomeColors[biome.id] ?? 0x444444; + + const bg = this.add.rectangle(bx, y, btnWidth, btnHeight, + isSelected ? color : 0x0a1a0f, 0.9); + bg.setStrokeStyle(isSelected ? 3 : 1, color); + bg.setDepth(10); + + const label = this.add.text(bx, y, biome.nameRu, { + fontSize: '13px', + color: isSelected ? '#ffffff' : '#888888', + fontFamily: 'monospace', + fontStyle: isSelected ? 'bold' : 'normal', + }); + label.setOrigin(0.5); + label.setDepth(10); + + bg.setInteractive({ useHandCursor: true }); + bg.on('pointerdown', () => { + this.selectedBiomeIndex = i; + this.refreshBiomeButtons(); + }); + bg.on('pointerover', () => { + if (i !== this.selectedBiomeIndex) { + bg.setStrokeStyle(2, 0x00ff88); + } + }); + bg.on('pointerout', () => { + const sel = i === this.selectedBiomeIndex; + bg.setStrokeStyle(sel ? 3 : 1, color); + }); + + // Fade in + bg.setAlpha(0); + label.setAlpha(0); + this.tweens.add({ targets: [bg, label], alpha: 1, duration: 600, delay: 100 + i * 100 }); + + this.biomeCards.push({ bg, label }); + } + } + + /** Refresh biome button visual states */ + private refreshBiomeButtons(): void { + const biomeColors: Record = { + 'catalytic-wastes': 0x886622, + 'kinetic-mountains': 0x5577aa, + 'verdant-forests': 0x228833, + }; + + for (let i = 0; i < this.biomeCards.length; i++) { + const card = this.biomeCards[i]; + const biome = biomes[i]; + const isSelected = i === this.selectedBiomeIndex; + const color = biomeColors[biome.id] ?? 0x444444; + + card.bg.setFillStyle(isSelected ? color : 0x0a1a0f, 0.9); + card.bg.setStrokeStyle(isSelected ? 3 : 1, color); + card.label.setColor(isSelected ? '#ffffff' : '#888888'); + card.label.setFontStyle(isSelected ? 'bold' : 'normal'); + } + } + private startRun(school: SchoolData): void { // Flash effect this.cameras.main.flash(300, 0, 255, 136); + const selectedBiome = biomes[this.selectedBiomeIndex]; + this.time.delayedCall(400, () => { this.scene.start('GameScene', { meta: this.meta, schoolId: school.id, runId: this.meta.totalRuns + 1, purchasedEffects: this.purchasedEffects, + biomeId: selectedBiome.id, }); }); } diff --git a/src/scenes/GameScene.ts b/src/scenes/GameScene.ts index 952edf9..4f65de2 100644 --- a/src/scenes/GameScene.ts +++ b/src/scenes/GameScene.ts @@ -132,7 +132,10 @@ export class GameScene extends Phaser.Scene { // Purchased bonuses from Cradle shop private purchasedEffects: import('../mycelium/types').BonusEffect[] = []; - init(data: { meta: MetaState; schoolId: string; runId: number; purchasedEffects?: import('../mycelium/types').BonusEffect[] }): void { + // Biome selection + private biomeId = 'catalytic-wastes'; + + init(data: { meta: MetaState; schoolId: string; runId: number; purchasedEffects?: import('../mycelium/types').BonusEffect[]; biomeId?: string }): void { this.meta = data.meta; this.runState = createRunState(data.runId, data.schoolId); this.crisisState = null; @@ -141,6 +144,7 @@ export class GameScene extends Phaser.Scene { this.hasDepositedThisRun = false; this.memoryFlashTimer = 0; this.purchasedEffects = data.purchasedEffects ?? []; + this.biomeId = data.biomeId ?? 'catalytic-wastes'; } create(): void { @@ -149,8 +153,8 @@ export class GameScene extends Phaser.Scene { this.bridge = new PhaserBridge(this); this.projectileData = new Map(); - // 2. Generate world - const biome = biomeDataArray[0] as BiomeData; + // 2. Generate world — use selected biome + const biome = (biomeDataArray as BiomeData[]).find(b => b.id === this.biomeId) ?? biomeDataArray[0] as BiomeData; this.worldSeed = Date.now() % 1000000; const worldData = generateWorld(biome, this.worldSeed); @@ -172,17 +176,18 @@ export class GameScene extends Phaser.Scene { this.gameWorld.world, worldData.grid, biome, this.worldSeed, ); - // 6. Initialize creature systems + // 6. Initialize creature systems — filter by biome const allSpecies = speciesDataArray as SpeciesData[]; - this.speciesRegistry = new SpeciesRegistry(allSpecies); + const biomeSpecies = allSpecies.filter(s => s.biome === biome.id); + this.speciesRegistry = new SpeciesRegistry(biomeSpecies); this.speciesLookup = new Map(); - for (const s of allSpecies) { + for (const s of biomeSpecies) { this.speciesLookup.set(s.speciesId, s); } // 7. Spawn creatures across the map this.creatureData = spawnInitialCreatures( - this.gameWorld.world, worldData.grid, biome, this.worldSeed, allSpecies, + this.gameWorld.world, worldData.grid, biome, this.worldSeed, biomeSpecies, ); // 8. Create player at spawn position + inventory with starting kit diff --git a/src/world/generator.ts b/src/world/generator.ts index b337cb6..c30499e 100644 --- a/src/world/generator.ts +++ b/src/world/generator.ts @@ -47,21 +47,27 @@ function determineTile(elevation: number, detail: number, biome: BiomeData): num } } - // Geyser overlay: on acid-shallow + very high detail noise + // Interactive overlay (geysers / steam vents / hollow stumps) on specific base tile + high detail noise if (baseTileId === gen.geyserOnTile && detail > gen.geyserThreshold) { - return findTileIdByName(biome, 'geyser'); + return findInteractiveTileId(biome); } - // Mineral overlay: on walkable ground + high detail noise + // Resource overlay (mineral veins / ore deposits / herb patches) on walkable ground + high detail noise if (gen.mineralOnTiles.includes(baseTileId) && detail > gen.mineralThreshold) { - return findTileIdByName(biome, 'mineral-vein'); + return findResourceTileId(biome); } return baseTileId; } -/** Find tile ID by name, falling back to 0 if not found */ -function findTileIdByName(biome: BiomeData, name: string): number { - const tile = biome.tiles.find(t => t.name === name); +/** Find the interactive tile (geyser/steam-vent/hollow-stump), falling back to 0 */ +function findInteractiveTileId(biome: BiomeData): number { + const tile = biome.tiles.find(t => t.interactive); + return tile ? tile.id : 0; +} + +/** Find the resource tile (mineral-vein/ore-deposit/herb-patch), falling back to 0 */ +function findResourceTileId(biome: BiomeData): number { + const tile = biome.tiles.find(t => t.resource); return tile ? tile.id : 0; } diff --git a/src/world/resources.ts b/src/world/resources.ts index e46c7d0..2efba83 100644 --- a/src/world/resources.ts +++ b/src/world/resources.ts @@ -39,9 +39,9 @@ export function spawnResources( ): Map { const resourceData = new Map(); - // Find tile IDs for resource types - const mineralTile = biome.tiles.find(t => t.name === 'mineral-vein'); - const geyserTile = biome.tiles.find(t => t.name === 'geyser'); + // Find tile IDs for resource types (generic: resource + interactive tiles) + const mineralTile = biome.tiles.find(t => t.resource); + const geyserTile = biome.tiles.find(t => t.interactive); const configs: ResourceTileConfig[] = []; diff --git a/tests/chemistry.test.ts b/tests/chemistry.test.ts index e9f6066..7e11530 100644 --- a/tests/chemistry.test.ts +++ b/tests/chemistry.test.ts @@ -8,8 +8,8 @@ import { ReactionEngine } from '../src/chemistry/engine'; // ============================================================================= describe('ElementRegistry', () => { - it('should load all 20 elements', () => { - expect(ElementRegistry.count()).toBe(20); + it('should load all 40 elements', () => { + expect(ElementRegistry.count()).toBe(40); }); it('should look up elements by symbol', () => { @@ -59,6 +59,39 @@ describe('ElementRegistry', () => { expect(ElementRegistry.isElement('NaCl')).toBe(false); expect(ElementRegistry.isElement('H2O')).toBe(false); }); + + it('should have all 20 new Phase 9 elements', () => { + const newSymbols = ['Li', 'B', 'F', 'Ne', 'Ar', 'Ti', 'Cr', 'Mn', 'Co', 'Ni', 'As', 'Br', 'Ag', 'I', 'Ba', 'W', 'Pt', 'Pb', 'Bi', 'U']; + for (const sym of newSymbols) { + expect(ElementRegistry.has(sym), `Element ${sym} not found`).toBe(true); + } + }); + + it('should have correct data for new elements (real periodic table)', () => { + const li = ElementRegistry.getBySymbol('Li')!; + expect(li.atomicNumber).toBe(3); + expect(li.category).toBe('alkali-metal'); + + const f = ElementRegistry.getBySymbol('F')!; + expect(f.atomicNumber).toBe(9); + expect(f.category).toBe('halogen'); + expect(f.state).toBe('gas'); + expect(f.electronegativity).toBeCloseTo(3.98, 1); // Most electronegative + + const br = ElementRegistry.getBySymbol('Br')!; + expect(br.state).toBe('liquid'); // Only liquid non-metal at room temp + + const w = ElementRegistry.getBySymbol('W')!; + expect(w.atomicNumber).toBe(74); + expect(w.name).toBe('Tungsten'); + + const u = ElementRegistry.getBySymbol('U')!; + expect(u.atomicNumber).toBe(92); + expect(u.category).toBe('actinide'); + + const pt = ElementRegistry.getBySymbol('Pt')!; + expect(pt.category).toBe('transition-metal'); + }); }); // ============================================================================= @@ -106,6 +139,32 @@ describe('CompoundRegistry', () => { expect(CompoundRegistry.isCompound('H2O')).toBe(true); expect(CompoundRegistry.isCompound('Na')).toBe(false); }); + + it('should load all 64 compounds', () => { + expect(CompoundRegistry.count()).toBe(64); + }); + + it('should have new Phase 9 compounds', () => { + const newIds = ['NH3', 'HF', 'HBr', 'TiO2', 'MnO2', 'As2O3', 'H2SO4', 'HNO3', 'CuO', 'FeCl3', 'CaCl2', 'NH4Cl', 'C6H12O6', 'CH3COOH']; + for (const id of newIds) { + expect(CompoundRegistry.has(id), `Compound ${id} not found`).toBe(true); + } + }); + + it('should correctly flag new dangerous compounds', () => { + const hf = CompoundRegistry.getById('HF')!; + expect(hf.properties.acidic).toBe(true); + expect(hf.properties.corrosive).toBe(true); + expect(hf.properties.toxic).toBe(true); + + const h2so4 = CompoundRegistry.getById('H2SO4')!; + expect(h2so4.properties.acidic).toBe(true); + expect(h2so4.properties.oxidizer).toBe(true); + + const as2o3 = CompoundRegistry.getById('As2O3')!; + expect(as2o3.properties.toxic).toBe(true); + expect(as2o3.name).toContain('Arsenic'); + }); }); // ============================================================================= @@ -204,6 +263,104 @@ describe('ReactionEngine — success', () => { expect(result.reaction!.energyChange).toBeGreaterThan(0); // Endothermic }); + it('should produce HF from H + F', () => { + const result = ReactionEngine.react([ + { id: 'H', count: 1 }, + { id: 'F', count: 1 }, + ]); + expect(result.success).toBe(true); + expect(result.products).toEqual([{ id: 'HF', count: 1 }]); + }); + + it('should produce NH3 via Haber process (N + 3H with Fe catalyst + heat)', () => { + const result = ReactionEngine.react( + [ + { id: 'N', count: 1 }, + { id: 'H', count: 3 }, + ], + { minTemp: 500, catalyst: 'Fe' }, + ); + expect(result.success).toBe(true); + expect(result.products).toEqual([{ id: 'NH3', count: 1 }]); + }); + + it('should produce TiO2 from Ti + 2O with extreme heat', () => { + const result = ReactionEngine.react( + [ + { id: 'Ti', count: 1 }, + { id: 'O', count: 2 }, + ], + { minTemp: 1000 }, + ); + expect(result.success).toBe(true); + expect(result.products).toEqual([{ id: 'TiO2', count: 1 }]); + }); + + it('should produce tungsten via WO3 + Al redox', () => { + const result = ReactionEngine.react( + [ + { id: 'WO3', count: 1 }, + { id: 'Al', count: 2 }, + ], + { minTemp: 1000 }, + ); + expect(result.success).toBe(true); + expect(result.products).toContainEqual({ id: 'W', count: 1 }); + expect(result.products).toContainEqual({ id: 'Al2O3', count: 1 }); + }); + + it('should neutralize HF with NaOH (acid-base)', () => { + const result = ReactionEngine.react([ + { id: 'NaOH', count: 1 }, + { id: 'HF', count: 1 }, + ]); + expect(result.success).toBe(true); + expect(result.products).toContainEqual({ id: 'NaF', count: 1 }); + expect(result.products).toContainEqual({ id: 'H2O', count: 1 }); + }); + + it('should dissolve Zn in HCl (single-replacement)', () => { + const result = ReactionEngine.react([ + { id: 'Zn', count: 1 }, + { id: 'HCl', count: 2 }, + ]); + expect(result.success).toBe(true); + expect(result.products).toContainEqual({ id: 'ZnCl2', count: 1 }); + expect(result.products).toContainEqual({ id: 'H', count: 2 }); + }); + + it('should displace Cu with Fe from CuCl2', () => { + const result = ReactionEngine.react([ + { id: 'Fe', count: 1 }, + { id: 'CuCl2', count: 1 }, + ]); + expect(result.success).toBe(true); + expect(result.products).toContainEqual({ id: 'Cu', count: 1 }); + expect(result.products).toContainEqual({ id: 'FeCl2', count: 1 }); + }); + + it('should ferment glucose into ethanol + CO2', () => { + const result = ReactionEngine.react([ + { id: 'C6H12O6', count: 1 }, + ]); + expect(result.success).toBe(true); + expect(result.products).toContainEqual({ id: 'C2H5OH', count: 2 }); + expect(result.products).toContainEqual({ id: 'CO2', count: 2 }); + }); + + it('should produce H2SO4 via Contact process (Pt catalyst)', () => { + const result = ReactionEngine.react( + [ + { id: 'S', count: 1 }, + { id: 'O', count: 3 }, + { id: 'H', count: 2 }, + ], + { catalyst: 'Pt' }, + ); + expect(result.success).toBe(true); + expect(result.products).toEqual([{ id: 'H2SO4', count: 1 }]); + }); + it('reactant order should not matter (key is sorted)', () => { const r1 = ReactionEngine.react([ { id: 'Cl', count: 1 }, @@ -234,6 +391,16 @@ describe('ReactionEngine — failures', () => { expect(result.failureReasonRu).toContain('благородный газ'); }); + it('should reject reactions with new noble gases (Ne, Ar)', () => { + const ne = ReactionEngine.react([{ id: 'Ne', count: 1 }, { id: 'F', count: 1 }]); + expect(ne.success).toBe(false); + expect(ne.failureReason).toContain('noble gas'); + + const ar = ReactionEngine.react([{ id: 'Ar', count: 1 }, { id: 'Cl', count: 1 }]); + expect(ar.success).toBe(false); + expect(ar.failureReason).toContain('noble gas'); + }); + it('should reject gold reactions with explanation', () => { const result = ReactionEngine.react([ { id: 'Au', count: 1 }, @@ -309,8 +476,8 @@ describe('ReactionEngine — failures', () => { // ============================================================================= describe('ReactionEngine — metadata', () => { - it('should have 30+ registered reactions', () => { - expect(ReactionEngine.count()).toBeGreaterThanOrEqual(30); + it('should have 100+ registered reactions', () => { + expect(ReactionEngine.count()).toBeGreaterThanOrEqual(100); }); it('should look up reactions by id', () => { diff --git a/tests/creatures.test.ts b/tests/creatures.test.ts index 5050b82..e8711ad 100644 --- a/tests/creatures.test.ts +++ b/tests/creatures.test.ts @@ -71,8 +71,8 @@ function createPlayerEntity(world: World, x: number, y: number): number { // ─── Species Data ──────────────────────────────────────────────── describe('Species Data', () => { - it('loads 3 species from JSON', () => { - expect(allSpecies).toHaveLength(3); + it('loads 9 species from JSON (3 per biome)', () => { + expect(allSpecies).toHaveLength(9); }); it('has Crystallid with correct properties', () => { @@ -128,7 +128,7 @@ describe('Species Registry', () => { }); it('has correct count', () => { - expect(registry.count).toBe(3); + expect(registry.count).toBe(9); }); it('looks up by string ID', () => { @@ -148,7 +148,27 @@ describe('Species Registry', () => { it('returns all species', () => { const all = registry.getAll(); - expect(all).toHaveLength(3); + expect(all).toHaveLength(9); + }); + + it('can look up new Phase 9 species', () => { + expect(registry.get('pendulum')?.biome).toBe('kinetic-mountains'); + expect(registry.get('mechanoid')?.biome).toBe('kinetic-mountains'); + expect(registry.get('resonator')?.biome).toBe('kinetic-mountains'); + expect(registry.get('symbiote')?.biome).toBe('verdant-forests'); + expect(registry.get('mimic')?.biome).toBe('verdant-forests'); + expect(registry.get('spore-bearer')?.biome).toBe('verdant-forests'); + }); + + it('each biome has exactly 3 species', () => { + const all = registry.getAll(); + const byBiome = new Map(); + for (const s of all) { + byBiome.set(s.biome, (byBiome.get(s.biome) ?? 0) + 1); + } + expect(byBiome.get('catalytic-wastes')).toBe(3); + expect(byBiome.get('kinetic-mountains')).toBe(3); + expect(byBiome.get('verdant-forests')).toBe(3); }); }); diff --git a/tests/world.test.ts b/tests/world.test.ts index 483f62b..a1da239 100644 --- a/tests/world.test.ts +++ b/tests/world.test.ts @@ -4,8 +4,9 @@ import { createSeededNoise, sampleNoise } from '../src/world/noise'; import { generateWorld } from '../src/world/generator'; import type { BiomeData } from '../src/world/types'; +const allBiomes = biomeDataArray as BiomeData[]; // Load the first biome — structural compatibility with BiomeData -const biome = biomeDataArray[0] as BiomeData; +const biome = allBiomes[0]; // ─── Noise ────────────────────────────────────────────────────── @@ -181,3 +182,139 @@ describe('World Generation', () => { } }); }); + +// ─── Multi-Biome Support (Phase 9) ────────────────────────────── + +describe('Multi-Biome Data', () => { + it('has 3 biomes loaded', () => { + expect(allBiomes).toHaveLength(3); + }); + + it('each biome has a unique id', () => { + const ids = allBiomes.map(b => b.id); + expect(new Set(ids).size).toBe(3); + expect(ids).toContain('catalytic-wastes'); + expect(ids).toContain('kinetic-mountains'); + expect(ids).toContain('verdant-forests'); + }); + + it('each biome has 8 tile types with sequential IDs', () => { + for (const b of allBiomes) { + expect(b.tiles).toHaveLength(8); + b.tiles.forEach((tile, index) => { + expect(tile.id, `${b.id}: tile ${index}`).toBe(index); + }); + } + }); + + it('each biome has an interactive tile and a resource tile', () => { + for (const b of allBiomes) { + const interactive = b.tiles.find(t => t.interactive); + const resource = b.tiles.find(t => t.resource); + expect(interactive, `${b.id}: no interactive tile`).toBeDefined(); + expect(resource, `${b.id}: no resource tile`).toBeDefined(); + } + }); + + it('each biome has valid elevation rules covering [0, 1]', () => { + for (const b of allBiomes) { + const rules = b.generation.elevationRules; + expect(rules.length).toBeGreaterThan(0); + expect(rules[rules.length - 1].below).toBe(1); + const validIds = new Set(b.tiles.map(t => t.id)); + for (const rule of rules) { + expect(validIds.has(rule.tileId), `${b.id}: invalid tileId ${rule.tileId}`).toBe(true); + } + } + }); +}); + +describe('Kinetic Mountains Generation', () => { + const mtns = allBiomes.find(b => b.id === 'kinetic-mountains')!; + + it('generates correct-size grid', () => { + const world = generateWorld(mtns, 42); + expect(world.grid).toHaveLength(mtns.mapHeight); + expect(world.grid[0]).toHaveLength(mtns.mapWidth); + }); + + it('all tile IDs are valid', () => { + const world = generateWorld(mtns, 42); + const validIds = new Set(mtns.tiles.map(t => t.id)); + for (const row of world.grid) { + for (const tileId of row) { + expect(validIds.has(tileId)).toBe(true); + } + } + }); + + it('has diverse tiles with no single type > 60%', () => { + const world = generateWorld(mtns, 42); + const counts = new Map(); + for (const row of world.grid) { + for (const t of row) counts.set(t, (counts.get(t) ?? 0) + 1); + } + const total = mtns.mapWidth * mtns.mapHeight; + expect(counts.size).toBeGreaterThanOrEqual(4); + for (const count of counts.values()) { + expect(count / total).toBeLessThan(0.6); + } + }); + + it('generates chasms (low elevation)', () => { + const world = generateWorld(mtns, 42); + const chasmId = mtns.tiles.find(t => t.name === 'chasm')?.id; + expect(world.grid.some(row => row.includes(chasmId!))).toBe(true); + }); + + it('generates ore deposits (resources)', () => { + const world = generateWorld(mtns, 42); + const oreId = mtns.tiles.find(t => t.resource)?.id; + expect(world.grid.some(row => row.includes(oreId!))).toBe(true); + }); +}); + +describe('Verdant Forests Generation', () => { + const forest = allBiomes.find(b => b.id === 'verdant-forests')!; + + it('generates correct-size grid', () => { + const world = generateWorld(forest, 42); + expect(world.grid).toHaveLength(forest.mapHeight); + expect(world.grid[0]).toHaveLength(forest.mapWidth); + }); + + it('all tile IDs are valid', () => { + const world = generateWorld(forest, 42); + const validIds = new Set(forest.tiles.map(t => t.id)); + for (const row of world.grid) { + for (const tileId of row) { + expect(validIds.has(tileId)).toBe(true); + } + } + }); + + it('has diverse tiles with no single type > 60%', () => { + const world = generateWorld(forest, 42); + const counts = new Map(); + for (const row of world.grid) { + for (const t of row) counts.set(t, (counts.get(t) ?? 0) + 1); + } + const total = forest.mapWidth * forest.mapHeight; + expect(counts.size).toBeGreaterThanOrEqual(4); + for (const count of counts.values()) { + expect(count / total).toBeLessThan(0.6); + } + }); + + it('generates bogs (low elevation)', () => { + const world = generateWorld(forest, 42); + const bogId = forest.tiles.find(t => t.name === 'bog')?.id; + expect(world.grid.some(row => row.includes(bogId!))).toBe(true); + }); + + it('generates herb patches (resources)', () => { + const world = generateWorld(forest, 42); + const herbId = forest.tiles.find(t => t.resource)?.id; + expect(world.grid.some(row => row.includes(herbId!))).toBe(true); + }); +});