Files
synthesis/src/creatures/types.ts
Денис Шкабатур 6ba0746bb9 phase 9: biome expansion — 3 biomes, 40 elements, 119 reactions, 9 species
Expand beyond vertical slice with two new biomes and massive chemistry expansion:

Chemistry: +20 real elements (Li→U), +39 compounds (acids/salts/oxides/organics),
+85 reactions (Haber process, thermite variants, smelting, fermentation, etc.)

Biomes: Kinetic Mountains (physics/mechanics themed) and Verdant Forests
(biology/ecology themed), each with 8 tile types and unique generation rules.

Creatures: 6 new species — Pendulums/Mechanoids/Resonators (mountains),
Symbiotes/Mimics/Spore-bearers (forests). Species filtered by biome.

Infrastructure: CradleScene biome selector UI, generic world generator
(tile lookup by property instead of hardcoded names), actinide element category.

487 tests passing (32 new).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 17:27:15 +03:00

133 lines
3.5 KiB
TypeScript

/**
* Creature Types — data definitions for the creature/ecology system
*
* 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) */
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) */
export enum AIState {
Idle = 0,
Wander = 1,
Feed = 2,
Flee = 3,
Attack = 4,
}
/** Life cycle stage */
export enum LifeStage {
Egg = 0,
Youth = 1,
Mature = 2,
Aging = 3,
}
/** Diet type — what a creature can feed on */
export type DietType = 'mineral' | 'acid' | 'creature';
/** Species definition loaded from creatures.json */
export interface SpeciesData {
id: string;
name: string;
nameRu: string;
speciesId: SpeciesId;
biome: string; // biome id this species belongs to
description: string;
descriptionRu: string;
/** Visual */
color: string; // hex color string
radius: number; // base radius in pixels
radiusYouth: number; // smaller when young
/** Stats */
health: number;
speed: number; // pixels per second
damage: number; // damage per attack
armor: number; // damage reduction (0-1)
/** Metabolism */
diet: DietType;
dietTiles: string[]; // tile names this species feeds on
excretionElement: number; // atomic number of excreted element (0 = none)
energyMax: number; // max energy capacity
energyPerFeed: number; // energy gained per feeding
energyDrainPerSecond: number; // passive energy loss rate
hungerThreshold: number; // below this → seek food (0-1 fraction of max)
/** Behavior */
aggressionRadius: number; // distance to detect threats
fleeRadius: number; // distance to start fleeing
wanderRadius: number; // max wander distance from home
attackRange: number; // melee attack range
attackCooldown: number; // ms between attacks
/** Life cycle durations (ms) */
eggDuration: number;
youthDuration: number;
matureDuration: number;
agingDuration: number;
/** Reproduction */
reproductionEnergy: number; // energy cost to reproduce
offspringCount: number; // eggs per reproduction event
/** Population */
maxPopulation: number; // per-species cap
spawnWeight: number; // relative spawn density (0-1)
preferredTiles: string[]; // tiles where this species spawns
}
/** Runtime creature state (non-ECS, for string data lookup) */
export interface CreatureInfo {
speciesId: SpeciesId;
speciesDataId: string; // key into species registry
}
/** Creature species registry */
export class SpeciesRegistry {
private byId = new Map<string, SpeciesData>();
private byNumericId = new Map<SpeciesId, SpeciesData>();
constructor(data: SpeciesData[]) {
for (const species of data) {
this.byId.set(species.id, species);
this.byNumericId.set(species.speciesId, species);
}
}
/** Get species by string ID */
get(id: string): SpeciesData | undefined {
return this.byId.get(id);
}
/** Get species by numeric ID (from ECS component) */
getByNumericId(id: SpeciesId): SpeciesData | undefined {
return this.byNumericId.get(id);
}
/** Get all species */
getAll(): SpeciesData[] {
return [...this.byId.values()];
}
/** Get species count */
get count(): number {
return this.byId.size;
}
}