+
+ Adjust environmental parameters that affect food and snake respawning.
+
+
+
+
+
2000
+
+ Time (ms) before dropped food disappears.
+
+
+
+
+
+
0
+
+ Delay (sec) before a new snake spawns after one dies.
+
-
-
-
0
-
- Delay (sec) before a new snake spawns after one dies.
+
+
+
+
+ Adjust evolutionary parameters to influence genetic changes.
+
+
+
+
+
0.1
+
+ Probability that a brain's bit will flip during mutation.
+
+
+
+
+
+
0.5
+
+ Likelihood of choosing a gene from the first parent during crossover.
+
diff --git a/script.js b/script.js
index 51577d1..8cd3876 100644
--- a/script.js
+++ b/script.js
@@ -9,7 +9,7 @@ let lastFrameTime = null;
/* Updated defaults */
const DEFAULT_BRAIN_SIZE = 15;
-const DEFAULT_SNAKE_SPEED = 3.5;
+const DEFAULT_SNAKE_SPEED = 1;
const DEFAULT_MAX_FOOD = 120;
const DEFAULT_SPAWN_CHANCE = 3;
const DEFAULT_FOOD_POINTS = 3;
@@ -17,9 +17,9 @@ const DEFAULT_DROPPED_FOOD_POINTS = 10;
const DEFAULT_SURVIVAL_BONUS = 2;
const DEFAULT_BODY_LENGTH_INCREMENT = 10;
const DEFAULT_THICKNESS_INCREMENT = 0.05;
-const DEFAULT_SNAKE_COUNT = 30;
-const DEFAULT_LENGTH_BONUS = 1;
-const DEFAULT_KILL_BONUS = 0;
+const DEFAULT_SNAKE_COUNT = 15;
+const DEFAULT_LENGTH_BONUS = 3;
+const DEFAULT_KILL_BONUS = 3;
/* Evolution & Environment Defaults */
const DEFAULT_MUTATION_RATE = 0.1;
@@ -188,6 +188,11 @@ function removeDraggable(panel) {
attachMinimizeLogic(clone);
attachTopLevelTabLogic(clone);
attachRewardSubTabLogic(clone);
+
+ // new calls for sub-tabs:
+ attachSnakesSubTabLogic(clone);
+ attachWorldSubTabLogic(clone);
+
wireUIEvents();
}
@@ -284,6 +289,48 @@ function attachRewardSubTabLogic(panel) {
});
});
}
+/* NEW: Attach snakes sub-tab logic */
+function attachSnakesSubTabLogic(panel) {
+ const snakesTab = panel.querySelector('#snakesTab');
+ if (!snakesTab) return;
+
+ const subTabButtons = snakesTab.querySelectorAll('.snakes-subtabs .tabBtn');
+ subTabButtons.forEach(subBtn => {
+ subBtn.addEventListener('click', () => {
+ subTabButtons.forEach(b => b.classList.remove('active'));
+ const allSubContents = snakesTab.querySelectorAll('.snakes-sub-content');
+ allSubContents.forEach(s => s.classList.remove('active'));
+
+ subBtn.classList.add('active');
+ const subId = subBtn.getAttribute('data-subtab');
+ const targetSub = snakesTab.querySelector('#' + subId);
+ if (targetSub) {
+ targetSub.classList.add('active');
+ }
+ });
+ });
+}
+/* NEW: Attach world sub-tab logic */
+function attachWorldSubTabLogic(panel) {
+ const worldTab = panel.querySelector('#worldTab');
+ if (!worldTab) return;
+
+ const subTabButtons = worldTab.querySelectorAll('.world-subtabs .tabBtn');
+ subTabButtons.forEach(subBtn => {
+ subBtn.addEventListener('click', () => {
+ subTabButtons.forEach(b => b.classList.remove('active'));
+ const allSubContents = worldTab.querySelectorAll('.world-sub-content');
+ allSubContents.forEach(s => s.classList.remove('active'));
+
+ subBtn.classList.add('active');
+ const subId = subBtn.getAttribute('data-subtab');
+ const targetSub = worldTab.querySelector('#' + subId);
+ if (targetSub) {
+ targetSub.classList.add('active');
+ }
+ });
+ });
+}
/* Wire up UI events (sliders, etc.) */
function wireUIEvents() {
@@ -1107,8 +1154,23 @@ function init() {
attachTopLevelTabLogic(document.getElementById("controlPanel"));
attachRewardSubTabLogic(document.getElementById("controlPanel"));
+ attachSnakesSubTabLogic(document.getElementById("controlPanel"));
+ attachWorldSubTabLogic(document.getElementById("controlPanel"));
attachTopLevelTabLogic(document.getElementById("timeAndLeaderboardPanel"));
wireUIEvents();
+
+ // Wire up the help button to open the modal
+ const helpBtn = document.getElementById('helpButton');
+ const helpModal = document.getElementById('helpModal');
+ const helpClose = document.getElementById('helpClose');
+ if (helpBtn && helpModal && helpClose) {
+ helpBtn.onclick = () => {
+ helpModal.style.display = 'flex';
+ };
+ helpClose.onclick = () => {
+ helpModal.style.display = 'none';
+ };
+ }
}
init();
diff --git a/styles.css b/styles.css
index 6394b2a..08833a5 100644
--- a/styles.css
+++ b/styles.css
@@ -10,11 +10,24 @@ html, body {
color: #FFF;
}
-/* Canvas covers the entire window */
+/* Wrap the canvas so we can scale the entire simulation if desired */
+#simCanvasWrapper {
+ width: 100%;
+ height: 100%;
+ /* Default scale for desktop */
+ transform: scale(1.0);
+ transform-origin: center center;
+}
+
+/* On mobile (below 1000px), scale differently. Adjust as desired. */
+@media (max-width: 1000px) {
+ #simCanvasWrapper {
+ transform: scale(0.85); /* Or scale(1.2) if you want larger on mobile */
+ }
+}
+
+/* The canvas inside the wrapper */
canvas {
- position: absolute;
- top: 0;
- left: 0;
width: 100%;
height: 100%;
display: block;
@@ -34,7 +47,7 @@ canvas {
background: linear-gradient(135deg, rgba(20,0,40,0.8), rgba(0,0,0,0.6));
}
-/* widths: make both 420px to match each other in desktop */
+/* widths: make both 420px for desktop */
.control-panel {
width: 420px;
left: 50%;
@@ -165,6 +178,60 @@ canvas {
display: block;
}
+/* Sub-tabs for Snakes */
+.snakes-subtabs {
+ display: flex;
+ margin-bottom: 10px;
+}
+.snakes-subtabs .tabBtn {
+ flex: 1;
+ margin: 0 2px;
+ background: #444;
+ border: none;
+ color: #FFF;
+ cursor: pointer;
+ padding: 4px 8px;
+ font-weight: bold;
+ border-radius: 4px;
+}
+.snakes-subtabs .tabBtn.active {
+ background: linear-gradient(90deg, #8000ff 0%, #ff00ff 100%);
+ box-shadow: 0 0 5px rgba(255,0,255,0.4);
+}
+.snakes-sub-content {
+ display: none;
+}
+.snakes-sub-content.active {
+ display: block;
+}
+
+/* Sub-tabs for 'World' (Environment + Evolution) */
+.world-subtabs {
+ display: flex;
+ margin-bottom: 10px;
+}
+.world-subtabs .tabBtn {
+ flex: 1;
+ margin: 0 2px;
+ background: #444;
+ border: none;
+ color: #FFF;
+ cursor: pointer;
+ padding: 4px 8px;
+ font-weight: bold;
+ border-radius: 4px;
+}
+.world-subtabs .tabBtn.active {
+ background: linear-gradient(90deg, #8000ff 0%, #ff00ff 100%);
+ box-shadow: 0 0 5px rgba(255,0,255,0.4);
+}
+.world-sub-content {
+ display: none;
+}
+.world-sub-content.active {
+ display: block;
+}
+
/* .tab-content is used for top-level content areas */
.tab-content {
display: none; /* hidden by default */
@@ -219,21 +286,17 @@ canvas {
animation: sinewave 1s infinite;
}
-/* Center the "?" help button on the right edge */
+/* Help Button style (no longer absolutely positioned) */
.help-button {
- position: absolute;
- top: 50%;
- right: 10px;
- transform: translateY(-50%);
- z-index: 3;
+ margin-left: 8px;
background: #444;
border: 1px solid #555;
color: #FFF;
- font-size: 16px;
- padding: 4px 8px;
+ font-size: 14px;
+ padding: 2px 6px;
cursor: pointer;
- border-radius: 50%;
- box-shadow: 0 0 8px rgba(255, 0, 255, 0.5);
+ border-radius: 4px;
+ box-shadow: 0 0 8px rgba(255,0,255,0.5);
}
.help-button:hover {
background: #666;
@@ -247,7 +310,7 @@ canvas {
width: 100%;
height: 100%;
background: rgba(0,0,0,0.8);
- display: none;
+ display: none;
z-index: 9999;
align-items: center;
justify-content: center; /* center horizontally */
@@ -295,6 +358,7 @@ canvas {
left: 50%;
transform: translateX(-50%);
}
+
/* Stack the leaderboards vertically in mobile to avoid overflow */
.leaderboardColumn {
width: 100% !important;