Prompt utilisé pour régénérer cette page :
Page: Natural Selection - Darwinian Evolution Simulation
Description: "Observe Darwinian evolution in action: a single species adapts to environmental pressures through genetic variation and natural selection"
Category: artificial-life
Icon: dna
Tags: evolution, natural-selection, simulation, genetics
Status: new
Front matter (index.md):
title: "Natural Selection"
description: "Observe Darwinian evolution in action: a single species adapts to environmental pressures through genetic variation and natural selection"
icon: "dna"
tags: ["evolution", "natural-selection", "simulation", "genetics"]
status: ["new"]
HTML structure (index.md):
<section class="container visual size-800 ratio-1-1 canvas-contain">
<canvas id="natural-selection-canvas"></canvas>
</section>
Widget files:
- _stats.right.md (weight: 10): Two stat groups:
##### Population — div.natural-selection-stats with 4 stat-items:
Population (swatch.organism), Generation, Food (swatch.food), Diversity
Stat IDs: stat-population, stat-generation, stat-food, stat-diversity
##### Trait Averages — div.natural-selection-stats.traits with 4 stat-items:
Speed, Size, Vision, Metabolism
Stat IDs: stat-avg-speed, stat-avg-size, stat-avg-vision, stat-avg-metabolism
- _controls.right.md (weight: 20): Two sections:
##### Controls — div.natural-selection-controls > div.natural-selection-actions:
{{< button id="btn-start" label="Start" class="is-start" >}}
{{< button id="btn-pause" label="Pause" class="is-pause" >}}
{{< button id="btn-reset" label="Reset" >}}
##### Simulation — div.natural-selection-options:
Speed slider: opt-speed (0.5-3, step 0.5, value 1), display span#speed-value
- _options.right.md (weight: 30): Two sections:
##### Parameters — div.natural-selection-options with 5 sliders:
Initial Population: opt-population (5-80, step 5, value 30), display span#population-value
Food Abundance: opt-food (10-100, step 5, value 50) → CONFIG.foodAbundance = value/100, display span#food-value
Mutation Rate: opt-mutation-rate (5-80, step 5, value 20) → CONFIG.mutationRate = value/100, display span#mutation-rate-value
Mutation Strength: opt-mutation-strength (5-50, step 5, value 15) → CONFIG.mutationStrength = value/100, display span#mutation-strength-value
Reproduction Threshold: opt-reproduction (60-200, step 10, value 120), display span#reproduction-value
##### Effects — 3 checkboxes:
opt-traits (checked): Show Traits
opt-energy: Show Energy
opt-vision: Show Vision
- _graph.right.md (weight: 40): ##### Population Over Time — div.natural-selection-graph > <canvas id="population-graph">
- _traits-graph.right.md (weight: 50): ##### Trait Dominance Over Time — div.natural-selection-graph > <canvas id="traits-graph">
Legend: div.natural-selection-legend.inline with 4 legend-items:
Speed (swatch.speed), Size (swatch.size), Vision (swatch.vision), Metabolism (swatch.metabolism)
- _algorithm.after.md: Explains Darwinian natural selection: 4 pillars (variation/heredity/selection/time), 4 genetic traits with trade-offs, visual encoding via HSL color, asexual reproduction with mutation.
Architecture (single file default.js):
- IIFE, no imports (uses console.log)
- No external dependencies
SCSS file (default.scss):
- CSS custom properties: --natural-selection-color-organism (#3498db), --natural-selection-color-food (#27ae60), --natural-selection-color-speed (#e74c3c), --natural-selection-color-size (#3498db), --natural-selection-color-vision (#f39c12), --natural-selection-color-metabolism (#9b59b6)
- $breakpoint-mobile: 768px
- layout-main: flex column centered, #natural-selection-canvas 100% with border
- .natural-selection-controls: .natural-selection-actions flex row, .is-start/.is-pause toggled by .is-running
- .natural-selection-stats: flex column, .stat-item with .label+.swatch and .value; .traits variant with smaller font
- .natural-selection-graph: #population-graph and #traits-graph both 120px height (100px mobile), border, background
- .natural-selection-options: flex column, .option-item with label+range, .checkbox variant for horizontal layout
- .natural-selection-legend: flex column (or .inline row), .legend-item with colored .swatch circles per trait
- Responsive: smaller padding/gaps/fonts on mobile
CONFIG defaults:
initialPopulation: 30, foodAbundance: 0.50, maxFood: 120, foodEnergy: 25,
reproductionThreshold: 120, reproductionCost: 50,
mutationRate: 0.20, mutationStrength: 0.15, speed: 1.0,
showTraits: true, showEnergy: false, showVision: false
Food class:
- Stationary green circle at random position
- size: 3 + random()*2, energy: CONFIG.foodEnergy (25)
- Drawn using cachedColors.food
Organism class:
- Constructor: x, y, genes (null → 4 random 0-1), gen (0)
- Genome: 4 genes [speed, size, vision, metabolism], each 0-1
- Derived traits:
- speed = 1 + genes[0]*3 (range 1-4)
- size = 4 + genes[1]*8 (range 4-12 px)
- visionRange = 30 + genes[2]*120 (range 30-150 px)
- metabolismEfficiency = 0.5 + genes[3]*0.5 (range 0.5-1.0)
- Energy starts at reproductionThreshold * 0.8
- Movement vector: vx, vy initialized to random (-1 to 1)
- HSL color derived from genome:
- Hue = (genes[0] + genes[3])/2 * 360
- Saturation = 40 + genes[1]*50 (40-90%)
- Lightness = 35 + genes[2]*30 (35-65%)
- Methods:
- computeColor(): HSL string from genome for visual lineage tracking
- senseFood(): finds nearest food within visionRange
- moveTowards(targetX, targetY): steer toward target at this.speed
- wander(): random acceleration with speed limiting
- update(width, height): sense → move/wander → apply movement → wrap edges → apply energy cost
- tryEat(): eat food on contact (this.size + item.size), gain item.energy * metabolismEfficiency
- canReproduce(): energy > CONFIG.reproductionThreshold
- isDead(): energy <= 0
- reproduce(): subtract reproductionCost, create child with mutated genes, update generation counter
- drawEnergyBar(ctx): colored bar above entity (red→green based on energy/threshold)
- draw(ctx): draw circle (trait color or default), optional vision range circle, optional energy bar
Energy cost formula per frame:
baseCost(0.05) + genes[0]*0.08 + genes[1]*0.06 + genes[2]*0.04 + genes[3]*0.03
Reproduction:
- Asexual: when energy > threshold
- Child gets mutated genes: each gene has mutationRate chance of mutation
- Mutation: gene + (random()-0.5) * mutationStrength * 2, clamped to 0-1
- Child spawned at parent position ±10px
Genetic diversity calculation:
- Average standard deviation across 4 genes
- Normalized to 0-1 range (multiplied by 4)
Population history:
- HISTORY_LENGTH = 300 samples max
- Recorded every 5 frames
- populationHistory[] stores organism count
- traitHistory {speed, size, vision, metabolism} stores average gene values per sample
Simulation loop:
- Fixed timestep accumulator pattern (16.67ms base step)
- CONFIG.speed multiplier applied to delta time
- Food spawning: probability CONFIG.foodAbundance * 0.3 per step, max CONFIG.maxFood (120)
- Organism update → tryEat → reproduce → filter dead
- Extinction protection: respawn 5 random organisms if population hits 0
Rendering:
- HD canvas: 800px × devicePixelRatio, ctx.setTransform for scaling
- Main canvas: surface background, green food dots, colored organism circles
- Optional vision range circles (faint stroke, alpha 0.1)
- Optional energy bars above organisms (red→green gradient)
- Population graph: separate canvas sized to parent, line chart with axes (alpha 0.3)
- Trait dominance graph: separate canvas, 4 colored lines (speed=red, size=blue, vision=yellow, metabolism=purple), Y axis fixed 0-1
Controls:
- Start/Pause buttons toggle isRunning, toggle .is-running CSS class
- Reset: stop, clear organisms/food/history, regenerate initial populations, redraw
- Sliders update CONFIG values; display span updated via updateValueDisplay()
- Checkboxes toggle CONFIG.showTraits/showEnergy/showVision; redraw when paused
Color caching:
- cachedColors object with surface, food, organism, grid, traitSpeed, traitSize, traitVision, traitMetabolism
- cacheColors() reads from CSS custom properties
- Refreshed on prefers-color-scheme change
Canvas setup:
- Main canvas: fixed 800x800 pixels (square)
- Graph canvases: sized to parent bounding rect
- All use devicePixelRatio with setTransform for HD rendering
DOM element lookups:
- All use getElementById with optional chaining (?.)
- Graph canvases are optional (null-checked before drawing)
Auto-init on DOM ready (DOMContentLoaded or immediate if already loaded).
Page entièrement générée et maintenue par IA, sans intervention humaine.