2025-03-15 06:49:30 +00:00
|
|
|
|
<!DOCTYPE html>
|
|
|
|
|
|
<html lang="en">
|
|
|
|
|
|
<head>
|
|
|
|
|
|
<meta charset="UTF-8" />
|
2025-03-15 20:30:48 +00:00
|
|
|
|
<title>Gummy Arena Simulator</title>
|
2025-03-15 17:43:55 +00:00
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
2025-03-15 06:49:30 +00:00
|
|
|
|
<link rel="stylesheet" href="styles.css">
|
|
|
|
|
|
</head>
|
|
|
|
|
|
<body>
|
2025-03-15 18:33:29 +00:00
|
|
|
|
|
|
|
|
|
|
<!-- Wrap canvas in a scalable container -->
|
|
|
|
|
|
<div id="simCanvasWrapper">
|
|
|
|
|
|
<canvas id="simCanvas"></canvas>
|
|
|
|
|
|
</div>
|
2025-03-15 06:49:30 +00:00
|
|
|
|
|
|
|
|
|
|
<!-- Loading Overlay -->
|
|
|
|
|
|
<div id="loadingOverlay">
|
|
|
|
|
|
<div class="sinewave">Fast Forwarding...</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Help Modal (Hidden By Default) -->
|
|
|
|
|
|
<div id="helpModal" class="help-modal">
|
|
|
|
|
|
<div class="help-content">
|
|
|
|
|
|
<button id="helpClose" class="help-close">×</button>
|
|
|
|
|
|
<h2>How This Simulation Works</h2>
|
|
|
|
|
|
<p>
|
|
|
|
|
|
Welcome to the Neon Synthwave Snake Evolution Simulator! Your main goal is to help create
|
|
|
|
|
|
(and sometimes directly control) the environment so the snakes can grow as long as possible.
|
|
|
|
|
|
</p>
|
|
|
|
|
|
<p>
|
|
|
|
|
|
Each snake tries to eat food (and occasionally each other) to gain points, grow in length, and
|
|
|
|
|
|
eventually become the biggest snake. Behind the scenes, genetic algorithms evolve the snakes’
|
|
|
|
|
|
“brains” to adapt their behavior over time.
|
|
|
|
|
|
</p>
|
|
|
|
|
|
<p>
|
|
|
|
|
|
There’s also a hidden twist: the size of your browser window subtly influences the snakes’
|
|
|
|
|
|
learning process. Try making the canvas larger or smaller to see how it affects the outcome!
|
|
|
|
|
|
</p>
|
|
|
|
|
|
<p style="font-weight: bold;">
|
|
|
|
|
|
Objective: Achieve the highest possible snake length!
|
|
|
|
|
|
</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Control Panel (Bottom) -->
|
|
|
|
|
|
<div id="controlPanel" class="control-panel">
|
|
|
|
|
|
<div class="header">
|
|
|
|
|
|
Simulation Controls
|
2025-03-15 18:33:29 +00:00
|
|
|
|
<!-- Move the help button here -->
|
|
|
|
|
|
<button id="helpButton" class="help-button">?</button>
|
2025-03-15 06:49:30 +00:00
|
|
|
|
<button class="minimize">–</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="content">
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Top-level Tabs -->
|
|
|
|
|
|
<div class="tab-buttons top-level-tabs">
|
|
|
|
|
|
<button class="tabBtn active" data-tab="rewardTab">Reward</button>
|
|
|
|
|
|
<button class="tabBtn" data-tab="foodTab">Food</button>
|
|
|
|
|
|
<button class="tabBtn" data-tab="snakesTab">Snakes</button>
|
2025-03-15 18:33:29 +00:00
|
|
|
|
<!-- Combine Evolution + Environment => 'World' main tab -->
|
|
|
|
|
|
<button class="tabBtn" data-tab="worldTab">World</button>
|
2025-03-15 06:49:30 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- REWARD TAB (with 2 sub-tabs) -->
|
|
|
|
|
|
<div id="rewardTab" class="tab-content active">
|
|
|
|
|
|
<div class="tab-buttons reward-subtabs">
|
|
|
|
|
|
<button class="tabBtn active" data-subtab="rewardPointsSubTab">Points & Kills</button>
|
|
|
|
|
|
<button class="tabBtn" data-subtab="rewardGrowthSubTab">Survival & Growth</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Sub-tab 1: Points & Kills -->
|
|
|
|
|
|
<div id="rewardPointsSubTab" class="reward-sub-content active">
|
|
|
|
|
|
<div class="tab-description">
|
|
|
|
|
|
Adjust food points, dropped food, and kill bonus rewards here.
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="control-group">
|
|
|
|
|
|
<label for="foodPointsSlider">Food Points:</label>
|
|
|
|
|
|
<input type="range" id="foodPointsSlider" min="0" max="10" value="3" step="0.5">
|
|
|
|
|
|
<span id="foodPointsVal">3</span>
|
|
|
|
|
|
<div class="setting-description">
|
|
|
|
|
|
Higher values give snakes more points for eating standard food.
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="control-group">
|
|
|
|
|
|
<label for="droppedFoodPointsSlider">Dropped Food:</label>
|
|
|
|
|
|
<input type="range" id="droppedFoodPointsSlider" min="0" max="10" value="10" step="0.5">
|
|
|
|
|
|
<span id="droppedFoodPointsVal">10</span>
|
|
|
|
|
|
<div class="setting-description">
|
|
|
|
|
|
When a snake dies, it leaves behind 'dropped food' worth these extra points.
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="control-group">
|
|
|
|
|
|
<label for="killBonusSlider">Kill Bonus:</label>
|
|
|
|
|
|
<input type="range" id="killBonusSlider" min="0" max="10" value="0" step="1">
|
|
|
|
|
|
<span id="killBonusVal">0</span>
|
|
|
|
|
|
<div class="setting-description">
|
|
|
|
|
|
If a snake collides with your body, you gain these extra points.
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Sub-tab 2: Survival & Growth -->
|
|
|
|
|
|
<div id="rewardGrowthSubTab" class="reward-sub-content">
|
|
|
|
|
|
<div class="tab-description">
|
|
|
|
|
|
Adjust survival bonus per frame and extra points for bigger snakes.
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="control-group">
|
|
|
|
|
|
<label for="survivalBonusSlider">Survival Bonus:</label>
|
|
|
|
|
|
<input type="range" id="survivalBonusSlider" min="0" max="10" value="2" step="0.5">
|
|
|
|
|
|
<span id="survivalBonusVal">2</span>
|
|
|
|
|
|
<div class="setting-description">
|
|
|
|
|
|
Each frame, snakes get a tiny fraction of this as extra points (×0.001).
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="control-group">
|
|
|
|
|
|
<label for="lengthBonusSlider">Length Bonus:</label>
|
|
|
|
|
|
<input type="range" id="lengthBonusSlider" min="0" max="10" value="1" step="0.5">
|
|
|
|
|
|
<span id="lengthBonusVal">1</span>
|
|
|
|
|
|
<div class="setting-description">
|
|
|
|
|
|
Extra points for each unit of snake length. Encourages bigger snakes!
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- FOOD TAB -->
|
|
|
|
|
|
<div id="foodTab" class="tab-content">
|
|
|
|
|
|
<div class="tab-description">
|
|
|
|
|
|
Control how food is generated and how big your snakes can get from it.
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="control-group">
|
|
|
|
|
|
<label for="maxFoodSlider">Max Food:</label>
|
|
|
|
|
|
<input type="range" id="maxFoodSlider" min="50" max="200" value="120" step="1">
|
|
|
|
|
|
<span id="maxFoodVal">120</span>
|
|
|
|
|
|
<div class="setting-description">
|
|
|
|
|
|
The map won't exceed this many food items at once.
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="control-group">
|
|
|
|
|
|
<label for="spawnChanceSlider">Food Spawn Chance:</label>
|
|
|
|
|
|
<input type="range" id="spawnChanceSlider" min="1" max="10" value="3" step="0.5">
|
|
|
|
|
|
<span id="spawnChanceVal">3</span>
|
|
|
|
|
|
<div class="setting-description">
|
|
|
|
|
|
Each frame, if below the max, there's a spawn chance out of 100.
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="control-group">
|
|
|
|
|
|
<label for="bodyLengthIncSlider">Length Increment:</label>
|
|
|
|
|
|
<input type="range" id="bodyLengthIncSlider" min="5" max="20" value="10" step="1">
|
|
|
|
|
|
<span id="bodyLengthIncVal">10</span>
|
|
|
|
|
|
<div class="setting-description">
|
|
|
|
|
|
Each time a snake eats, it grows by this many segments.
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="control-group">
|
|
|
|
|
|
<label for="thicknessIncSlider">Thickness Increment:</label>
|
|
|
|
|
|
<input type="range" id="thicknessIncSlider" min="0.01" max="0.1" value="0.05" step="0.01">
|
|
|
|
|
|
<span id="thicknessIncVal">0.05</span>
|
|
|
|
|
|
<div class="setting-description">
|
|
|
|
|
|
Controls how 'fat' the snake gets with each meal.
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2025-03-15 18:33:29 +00:00
|
|
|
|
<!-- SNAKES TAB (now subdivided) -->
|
2025-03-15 06:49:30 +00:00
|
|
|
|
<div id="snakesTab" class="tab-content">
|
2025-03-15 18:33:29 +00:00
|
|
|
|
<div class="tab-buttons snakes-subtabs">
|
|
|
|
|
|
<button class="tabBtn active" data-subtab="snakesGeneralSubTab">General</button>
|
|
|
|
|
|
<button class="tabBtn" data-subtab="snakesBoostSubTab">Boost & Turn</button>
|
2025-03-15 06:49:30 +00:00
|
|
|
|
</div>
|
2025-03-15 18:33:29 +00:00
|
|
|
|
|
|
|
|
|
|
<!-- Sub-tab 1: General -->
|
|
|
|
|
|
<div id="snakesGeneralSubTab" class="snakes-sub-content active">
|
|
|
|
|
|
<div class="tab-description">
|
|
|
|
|
|
Control the basic snake population, speed, and brain size.
|
2025-03-15 06:49:30 +00:00
|
|
|
|
</div>
|
2025-03-15 18:33:29 +00:00
|
|
|
|
<div class="control-group">
|
|
|
|
|
|
<label for="snakeCountSlider">Snake Count:</label>
|
|
|
|
|
|
<input type="range" id="snakeCountSlider" min="1" max="100" value="30" step="1">
|
|
|
|
|
|
<span id="snakeCountVal">30</span>
|
|
|
|
|
|
<div class="setting-description">
|
|
|
|
|
|
Increase or decrease the total population of snakes.
|
|
|
|
|
|
</div>
|
2025-03-15 06:49:30 +00:00
|
|
|
|
</div>
|
2025-03-15 18:33:29 +00:00
|
|
|
|
<div class="control-group">
|
|
|
|
|
|
<label for="snakeSpeedSlider">Snake Speed:</label>
|
|
|
|
|
|
<input type="range" id="snakeSpeedSlider" min="1" max="50" step="0.1" value="3.5">
|
2025-03-15 20:30:48 +00:00
|
|
|
|
<span id="snakeSpeedVal">0</span>
|
2025-03-15 18:33:29 +00:00
|
|
|
|
<div class="setting-description">
|
|
|
|
|
|
Snakes turn at a rate up to 0.15 / (lengthFactor) * speed; higher is more agile.
|
|
|
|
|
|
</div>
|
2025-03-15 06:49:30 +00:00
|
|
|
|
</div>
|
2025-03-15 18:33:29 +00:00
|
|
|
|
<div class="control-group">
|
|
|
|
|
|
<label for="brainSizeSlider">Brain Size:</label>
|
|
|
|
|
|
<input type="range" id="brainSizeSlider" min="5" max="50" value="15" step="1">
|
|
|
|
|
|
<span id="brainSizeVal">15</span>
|
|
|
|
|
|
<div class="setting-description">
|
|
|
|
|
|
The bigger the brain, the more complex the snake's decision-making.
|
|
|
|
|
|
</div>
|
2025-03-15 06:49:30 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2025-03-15 18:33:29 +00:00
|
|
|
|
<!-- Sub-tab 2: Boost & Turn -->
|
|
|
|
|
|
<div id="snakesBoostSubTab" class="snakes-sub-content">
|
|
|
|
|
|
<div class="tab-description">
|
|
|
|
|
|
Manage the base turn rate and boosting parameters.
|
2025-03-15 06:49:30 +00:00
|
|
|
|
</div>
|
2025-03-15 18:33:29 +00:00
|
|
|
|
<div class="control-group">
|
|
|
|
|
|
<label for="turnRateSlider">Base Turn Rate:</label>
|
|
|
|
|
|
<input type="range" id="turnRateSlider" min="0.01" max="0.3" step="0.01" value="0.15">
|
|
|
|
|
|
<span id="turnRateVal">0.15</span>
|
|
|
|
|
|
<div class="setting-description">
|
|
|
|
|
|
Controls how sharply snakes can turn (before factoring in size).
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="control-group">
|
|
|
|
|
|
<label for="boostCostSlider">Boost Cost (length/sec):</label>
|
|
|
|
|
|
<input type="range" id="boostCostSlider" min="0" max="5" step="0.1" value="1">
|
|
|
|
|
|
<span id="boostCostVal">1</span>
|
|
|
|
|
|
<div class="setting-description">
|
|
|
|
|
|
How many body length units are spent per second while boosting.
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="control-group">
|
|
|
|
|
|
<label for="boostMultiplierSlider">Boost Speed Multiplier:</label>
|
|
|
|
|
|
<input type="range" id="boostMultiplierSlider" min="1" max="3" step="0.1" value="2">
|
|
|
|
|
|
<span id="boostMultiplierVal">2</span>
|
|
|
|
|
|
<div class="setting-description">
|
|
|
|
|
|
How much faster the snake goes when boosting.
|
|
|
|
|
|
</div>
|
2025-03-15 06:49:30 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2025-03-15 18:33:29 +00:00
|
|
|
|
<!-- COMBINED "WORLD" TAB with 2 sub-tabs (Environment + Evolution) -->
|
|
|
|
|
|
<div id="worldTab" class="tab-content">
|
|
|
|
|
|
<div class="tab-buttons world-subtabs">
|
|
|
|
|
|
<button class="tabBtn active" data-subtab="worldEnvSubTab">Environment</button>
|
|
|
|
|
|
<button class="tabBtn" data-subtab="worldEvoSubTab">Evolution</button>
|
2025-03-15 06:49:30 +00:00
|
|
|
|
</div>
|
2025-03-15 18:33:29 +00:00
|
|
|
|
|
|
|
|
|
|
<!-- Sub-tab 1: Environment (old environmentTab content) -->
|
|
|
|
|
|
<div id="worldEnvSubTab" class="world-sub-content active">
|
|
|
|
|
|
<div class="tab-description">
|
|
|
|
|
|
Adjust environmental parameters that affect food and snake respawning.
|
2025-03-15 06:49:30 +00:00
|
|
|
|
</div>
|
2025-03-15 18:33:29 +00:00
|
|
|
|
<div class="control-group">
|
|
|
|
|
|
<label for="foodDecayTimeSlider">Food Decay Time:</label>
|
|
|
|
|
|
<input type="range" id="foodDecayTimeSlider" min="500" max="5000" value="2000" step="100">
|
|
|
|
|
|
<span id="foodDecayTimeVal">2000</span>
|
|
|
|
|
|
<div class="setting-description">
|
|
|
|
|
|
Time (ms) before dropped food disappears.
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="control-group">
|
|
|
|
|
|
<label for="respawnDelaySlider">Respawn Delay:</label>
|
|
|
|
|
|
<input type="range" id="respawnDelaySlider" min="0" max="5" value="0" step="0.5">
|
|
|
|
|
|
<span id="respawnDelayVal">0</span>
|
|
|
|
|
|
<div class="setting-description">
|
|
|
|
|
|
Delay (sec) before a new snake spawns after one dies.
|
|
|
|
|
|
</div>
|
2025-03-15 06:49:30 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2025-03-15 18:33:29 +00:00
|
|
|
|
<!-- Sub-tab 2: Evolution (old evolutionTab content) -->
|
|
|
|
|
|
<div id="worldEvoSubTab" class="world-sub-content">
|
|
|
|
|
|
<div class="tab-description">
|
|
|
|
|
|
Adjust evolutionary parameters to influence genetic changes.
|
2025-03-15 06:49:30 +00:00
|
|
|
|
</div>
|
2025-03-15 18:33:29 +00:00
|
|
|
|
<div class="control-group">
|
|
|
|
|
|
<label for="mutationRateSlider">Mutation Rate:</label>
|
|
|
|
|
|
<input type="range" id="mutationRateSlider" min="0" max="0.2" value="0.1" step="0.01">
|
|
|
|
|
|
<span id="mutationRateVal">0.1</span>
|
|
|
|
|
|
<div class="setting-description">
|
|
|
|
|
|
Probability that a brain's bit will flip during mutation.
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="control-group">
|
|
|
|
|
|
<label for="crossoverBiasSlider">Crossover Bias:</label>
|
|
|
|
|
|
<input type="range" id="crossoverBiasSlider" min="0" max="1" value="0.5" step="0.05">
|
|
|
|
|
|
<span id="crossoverBiasVal">0.5</span>
|
|
|
|
|
|
<div class="setting-description">
|
|
|
|
|
|
Likelihood of choosing a gene from the first parent during crossover.
|
|
|
|
|
|
</div>
|
2025-03-15 06:49:30 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="control-buttons">
|
|
|
|
|
|
<button id="restoreDefaultsButton">Restore Defaults</button>
|
|
|
|
|
|
<button id="resetSimButton">Reset Simulation</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Combined Time & Leaderboard Panel (Top) -->
|
|
|
|
|
|
<div id="timeAndLeaderboardPanel" class="time-panel">
|
|
|
|
|
|
<div class="header">
|
|
|
|
|
|
Time & Leaderboards
|
|
|
|
|
|
<button class="minimize">–</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="content">
|
|
|
|
|
|
<div class="tab-buttons top-level-tabs">
|
|
|
|
|
|
<button class="tabBtn active" data-tab="leaderboardTab">Leaderboard</button>
|
|
|
|
|
|
<button class="tabBtn" data-tab="timeAccelTab">Time Acceleration</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div id="leaderboardTab" class="tab-content active">
|
|
|
|
|
|
<div style="
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
margin-bottom: 5px;
|
|
|
|
|
|
">
|
|
|
|
|
|
<div class="leaderboardColumn" style="width: 48%;">
|
|
|
|
|
|
<h3 style="margin: 0; font-size: 12px;">Current Leaderboard</h3>
|
|
|
|
|
|
<div id="currentLeaderboardColumn" class="leaderboard-text"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="leaderboardColumn" style="width: 48%;">
|
|
|
|
|
|
<h3 style="margin: 0; font-size: 12px;">All-Time Leaderboard</h3>
|
|
|
|
|
|
<div id="allTimeLeaderboardColumn" class="leaderboard-text"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div id="leaderboardTime" style="
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
margin-top: 3px;
|
|
|
|
|
|
"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div id="timeAccelTab" class="tab-content">
|
|
|
|
|
|
<div class="control-group" style="text-align:center;">
|
|
|
|
|
|
<label for="timeAccelSlider">Fast-Forward (minutes):</label><br/>
|
|
|
|
|
|
<input type="range" id="timeAccelSlider" min="0" max="60" value="0" step="1">
|
|
|
|
|
|
<span id="timeAccelVal">0</span>
|
|
|
|
|
|
<div class="setting-description">
|
|
|
|
|
|
Slide to skip simulation time quickly. Great for speeding evolution!
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="control-buttons">
|
|
|
|
|
|
<button id="fastForwardButton">Fast Forward</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<script src="script.js"></script>
|
|
|
|
|
|
</body>
|
|
|
|
|
|
</html>
|