/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Carnivore class
var Carnivore = Container.expand(function () {
	var self = Container.call(this);
	// Uncommon: 15% chance to be resistant to parasites
	self.parasiteResistant = Math.random() < 0.15;
	var carnAsset = self.attachAsset('carnivore', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 1.25,
		scaleY: 1.25
	});
	self.target = null;
	// Assign base speed, will adjust for personality below
	self.speed = 1.5 + Math.random() * 1.2;
	self.eaten = false;
	self._chaseTime = 0; // How long we've been chasing a herbivore
	self._tired = false; // Are we tired?
	self._tiredTimer = 0; // How long left to rest
	// Track tired attempts per herbivore (herbivore.id -> count)
	self._tiredAttempts = {};
	// --- Personality system ---
	// Personalities: "normal", "bloodthirsty", "weak"
	var carnPersonalities = ["normal", "bloodthirsty", "weak"];
	var rand = Math.random();
	// Make random traits more common: 30% normal, 35% bloodthirsty, 35% weak
	if (rand < 0.3) {
		self.personality = "normal";
	} else if (rand < 0.65) {
		self.personality = "bloodthirsty";
	} else {
		self.personality = "weak";
	}
	// Adjust speed for bloodthirsty carnivores
	if (self.personality === "bloodthirsty") {
		self.speed += 0.7 + Math.random() * 0.5; // noticeably faster
	}
	// For weak carnivores, no speed change, but will tire faster in update logic
	// For weak: timer for running away from other carnivores
	self._weakRunTimer = 0;
	self._weakRunAngle = 0;
	// --- State management for wandering/hungry ---
	self.state = "hungry"; // "wandering" or "hungry"
	self._eatCooldown = 0; // frames left in wandering after eating
	self.update = function () {
		if (self.eaten) return;
		// --- CARNIVORES CANNOT STARVE: No starvation logic for carnivores ---
		// --- WINTER BEHAVIOR: Wanderlust, ignore herbivores, and cannot starve ---
		var isWinter = !!window.winterState;
		if (isWinter) {
			// Always wander, never chase or eat, never get tired, never starve
			self.state = "wandering";
			self.target = null;
			self._tired = false;
			self._tiredTimer = 0;
			self._chaseTime = 0;
			// Wander constantly
			if (!self._wanderTimer || self._wanderTimer <= 0) {
				var angle = Math.random() * Math.PI * 2;
				self._wanderAngle = angle;
				self._wanderTimer = 60 + Math.floor(Math.random() * 60);
			}
			if (typeof self._wanderAngle === "number") {
				self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
				self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
				self._wanderTimer--;
				// Keep inside map bounds (strictly)
				var minX = 124 + 60;
				var maxX = 124 + 1800 - 60;
				var minY = paletteY + 320 + 60;
				var maxY = paletteY + 320 + 2000 - 60;
				if (self.x < minX) self.x = minX;
				if (self.x > maxX) self.x = maxX;
				if (self.y < minY) self.y = minY;
				if (self.y > maxY) self.y = maxY;
			}
			return;
		}
		// --- Personality: weak carnivore runs from other carnivores, can be infected by fungi ---
		if (self.personality === "weak") {
			// If running away, keep running for a short time
			if (self._weakRunTimer > 0) {
				self.x += Math.cos(self._weakRunAngle) * self.speed * 1.5;
				self.y += Math.sin(self._weakRunAngle) * self.speed * 1.5;
				self._weakRunTimer--;
				// Clamp to map area
				var minX = 124 + 60;
				var maxX = 124 + 1800 - 60;
				var minY = paletteY + 320 + 60;
				var maxY = paletteY + 320 + 2000 - 60;
				if (self.x < minX) self.x = minX;
				if (self.x > maxX) self.x = maxX;
				if (self.y < minY) self.y = minY;
				if (self.y > maxY) self.y = maxY;
				// While running, don't do anything else
				return;
			}
			// Check for nearby other carnivores (not self)
			var nearestCarn = null;
			var minCarnDist = 999999;
			for (var ci = 0; ci < carnivores.length; ci++) {
				var c = carnivores[ci];
				if (c === self || c.eaten) continue;
				var dx = c.x - self.x;
				var dy = c.y - self.y;
				var dist = dx * dx + dy * dy;
				if (dist < minCarnDist) {
					minCarnDist = dist;
					nearestCarn = c;
				}
			}
			if (nearestCarn && Math.sqrt(minCarnDist) < 220) {
				// Run away from the other carnivore for 60-120 frames
				var dx = self.x - nearestCarn.x;
				var dy = self.y - nearestCarn.y;
				var angle = Math.atan2(dy, dx);
				self._weakRunAngle = angle;
				self._weakRunTimer = 60 + Math.floor(Math.random() * 60);
				// Move immediately this frame
				self.x += Math.cos(self._weakRunAngle) * self.speed * 1.5;
				self.y += Math.sin(self._weakRunAngle) * self.speed * 1.5;
				// Clamp to map area
				var minX = 124 + 60;
				var maxX = 124 + 1800 - 60;
				var minY = paletteY + 320 + 60;
				var maxY = paletteY + 320 + 2000 - 60;
				if (self.x < minX) self.x = minX;
				if (self.x > maxX) self.x = maxX;
				if (self.y < minY) self.y = minY;
				if (self.y > maxY) self.y = maxY;
				return;
			}
			// Weak carnivores can be infected by fungi (handled in Parasite/Fungi logic)
		}
		// Handle tired state
		// Bloodthirsty carnivores never get tired
		if (self.personality === "bloodthirsty") {
			self._tired = false;
			self._tiredTimer = 0;
		} else {
			if (self._tired) {
				self._tiredTimer--;
				if (self._tiredTimer <= 0) {
					self._tired = false;
					self._chaseTime = 0;
				}
				// While tired, don't chase or wander, just stand still
				return;
			}
		}
		// Handle eat cooldown (wandering after eating)
		if (self._eatCooldown > 0) {
			self._eatCooldown--;
			if (self._eatCooldown === 0) {
				self.state = "hungry";
			}
		}
		// State: wandering (ignore prey)
		if (self.state === "wandering") {
			self.target = null; // Don't chase
			// --- Random wandering when not chasing herbivores ---
			if (!self._wanderTimer || self._wanderTimer <= 0) {
				var angle = Math.random() * Math.PI * 2;
				self._wanderAngle = angle;
				self._wanderTimer = 60 + Math.floor(Math.random() * 60);
			}
			if (typeof self._wanderAngle === "number") {
				self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
				self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
				self._wanderTimer--;
				// Keep inside map bounds (strictly)
				var minX = 124 + 60;
				var maxX = 124 + 1800 - 60;
				var minY = paletteY + 320 + 60;
				var maxY = paletteY + 320 + 2000 - 60;
				if (self.x < minX) self.x = minX;
				if (self.x > maxX) self.x = maxX;
				if (self.y < minY) self.y = minY;
				if (self.y > maxY) self.y = maxY;
			}
			self._chaseTime = 0; // Not chasing, reset chase timer
			return;
		}
		// State: hungry (look for prey)
		if (self.state === "hungry") {
			// --- CARNIVORE POPULATION CONTROL: If at max, hunt less frequently ---
			if (typeof carnivores !== "undefined" && carnivores.length >= 4) {
				// Only hunt every 120 frames (2 seconds)
				if (typeof self._huntDelay === "undefined") self._huntDelay = Math.floor(Math.random() * 120);
				self._huntDelay++;
				if (self._huntDelay < 120) {
					// Wander instead of hunting
					self.state = "wandering";
					self._huntDelay = self._huntDelay % 120;
					return;
				}
				self._huntDelay = 0;
			}
			// Find nearest prey if not already targeting
			if (!self.target || self.target.eaten) {
				var minDist = 999999,
					closest = null;
				// --- Bloodthirsty: can hunt herbivores and other carnivores (except self) ---
				if (self.personality === "bloodthirsty") {
					// Hunt herbivores
					for (var i = 0; i < herbivores.length; i++) {
						var h = herbivores[i];
						if (h.eaten) continue;
						var dx = h.x - self.x,
							dy = h.y - self.y;
						var dist = dx * dx + dy * dy;
						if (dist < minDist) {
							minDist = dist;
							closest = h;
						}
					}
					// Hunt other carnivores (not self, not eaten)
					for (var i = 0; i < carnivores.length; i++) {
						var c = carnivores[i];
						if (c === self || c.eaten) continue;
						var dx = c.x - self.x,
							dy = c.y - self.y;
						var dist = dx * dx + dy * dy;
						if (dist < minDist) {
							minDist = dist;
							closest = c;
						}
					}
				} else if (self.personality === "weak") {
					// Weak carnivores do not hunt other carnivores, only herbivores
					for (var i = 0; i < herbivores.length; i++) {
						var h = herbivores[i];
						if (h.eaten) continue;
						// Ignore this herbivore if we've gotten tired chasing it 2 or more times this cycle
						if (h._uniqueId === undefined) {
							// Assign a unique id to each herbivore if not present
							h._uniqueId = "herb_" + Math.floor(Math.random() * 1e9) + "_" + Math.floor(Math.random() * 1e9);
						}
						if (self._tiredAttempts[h._uniqueId] >= 2) continue;
						var dx = h.x - self.x,
							dy = h.y - self.y;
						var dist = dx * dx + dy * dy;
						if (dist < minDist) {
							minDist = dist;
							closest = h;
						}
					}
				} else {
					// Normal: only hunt herbivores
					for (var i = 0; i < herbivores.length; i++) {
						var h = herbivores[i];
						if (h.eaten) continue;
						// Ignore this herbivore if we've gotten tired chasing it 2 or more times this cycle
						if (h._uniqueId === undefined) {
							// Assign a unique id to each herbivore if not present
							h._uniqueId = "herb_" + Math.floor(Math.random() * 1e9) + "_" + Math.floor(Math.random() * 1e9);
						}
						if (self._tiredAttempts[h._uniqueId] >= 2) continue;
						var dx = h.x - self.x,
							dy = h.y - self.y;
						var dist = dx * dx + dy * dy;
						if (dist < minDist) {
							minDist = dist;
							closest = h;
						}
					}
				}
				// (Carnivores ignore pollinators)
				self.target = closest;
			}
			// --- Random wandering when not chasing herbivores ---
			if ((!self.target || self.target.eaten) && (!self._wanderTimer || self._wanderTimer <= 0)) {
				var angle = Math.random() * Math.PI * 2;
				self._wanderAngle = angle;
				self._wanderTimer = 60 + Math.floor(Math.random() * 60);
			}
			if (!self.target || self.target.eaten) {
				if (typeof self._wanderAngle === "number") {
					self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
					self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
					self._wanderTimer--;
					var minX = 124 + 60;
					var maxX = 124 + 1800 - 60;
					var minY = paletteY + 320 + 60;
					var maxY = paletteY + 320 + 2000 - 60;
					if (self.x < minX) self.x = minX;
					if (self.x > maxX) self.x = maxX;
					if (self.y < minY) self.y = minY;
					if (self.y > maxY) self.y = maxY;
				}
				self._chaseTime = 0; // Not chasing, reset chase timer
			}
			// Move toward target herbivore
			if (self.target && !self.target.eaten) {
				var dx = self.target.x - self.x;
				var dy = self.target.y - self.y;
				var dist = Math.sqrt(dx * dx + dy * dy);
				if (dist > 1) {
					self.x += dx / dist * self.speed;
					self.y += dy / dist * self.speed;
				}
				// Track how long we've been chasing
				self._chaseTime++;
				// If we've been chasing for more than X seconds, get tired
				var chaseLimit = 360; // default 6 seconds
				var tiredDuration = 600; // default 10 seconds
				if (self.personality === "weak") {
					chaseLimit = 180; // 3 seconds for weak carnivores
					tiredDuration = 900; // weak carnivores rest longer (15 seconds)
				}
				if (self._chaseTime > chaseLimit) {
					self._tired = true;
					self._tiredTimer = tiredDuration;
					self._chaseTime = 0;
					// Track tired attempts for this herbivore
					if (self.target && self.target._uniqueId !== undefined) {
						if (!self._tiredAttempts[self.target._uniqueId]) self._tiredAttempts[self.target._uniqueId] = 0;
						self._tiredAttempts[self.target._uniqueId]++;
						// If tired 2 or more times, ignore this herbivore for the rest of the cycle
						if (self._tiredAttempts[self.target._uniqueId] >= 2) {
							self.target = null;
							self.state = "wandering";
						}
					}
					return;
				}
				// Eat target if close enough
				// Prevent eating in autumn
				if (dist < 60 && !self.target.eaten) {
					if (window.autumnState) {
						// In autumn, do not eat, just wander
						self.target = null;
						self.state = "wandering";
						self._eatCooldown = 3600;
						self._chaseTime = 0;
						return;
					}
					// --- Bloodthirsty: can eat other carnivores or herbivores ---
					// --- Normal/Weak: only eat herbivores ---
					var ateCarnivore = false;
					if (self.personality === "bloodthirsty" && carnivores.indexOf(self.target) !== -1 && self.target !== self) {
						// Eat other carnivore
						if (typeof self.target.die === "function") self.target.die();
						ateCarnivore = true;
					} else if (herbivores.indexOf(self.target) !== -1) {
						// Eat herbivore
						if (typeof self.target.die === "function") self.target.die();
					} else {
						// Not a valid target, do nothing
						self.target = null;
						return;
					}
					// Move away from the eaten target
					if (self.target) {
						var awayDX = self.x - self.target.x;
						var awayDY = self.y - self.target.y;
						var awayDist = Math.sqrt(awayDX * awayDX + awayDY * awayDY);
						if (awayDist > 0) {
							// Move 100px away in the opposite direction
							self.x += awayDX / awayDist * 100;
							self.y += awayDY / awayDist * 100;
							// Clamp to map area
							var minX = 124 + 60;
							var maxX = 124 + 1800 - 60;
							var minY = paletteY + 320 + 60;
							var maxY = paletteY + 320 + 2000 - 60;
							if (self.x < minX) self.x = minX;
							if (self.x > maxX) self.x = maxX;
							if (self.y < minY) self.y = minY;
							if (self.y > maxY) self.y = maxY;
						}
					}
					// Track herbivores/carnivores eaten for egg laying
					if (ateCarnivore) {
						self._herbivoresEaten = (self._herbivoresEaten || 0) + 1;
					} else {
						self._herbivoresEaten = (self._herbivoresEaten || 0) + 1;
					}
					// Lay an egg if 3 prey have been eaten, then reset counter
					// --- CARNIVORE POPULATION CONTROL: Only lay egg if < 4 carnivores ---
					if (self._herbivoresEaten >= 3) {
						if (typeof carnivores !== "undefined" && carnivores.length < 4) {
							var egg = new Egg();
							egg.x = self.x;
							egg.y = self.y;
							egg.scaleX = 0.5;
							egg.scaleY = 0.5;
							egg.alpha = 1;
							egg._isCarnivoreEgg = true;
							egg._carnivoreHatch = true;
							if (self.parent) self.parent.addChild(egg);
							if (typeof eggs !== "undefined") eggs.push(egg);
						}
						self._herbivoresEaten = 0;
					}
					self.target = null;
					self._chaseTime = 0; // Reset chase timer after eating
					// Animate carnivore "eating"
					tween(self, {
						scaleX: 1.2,
						scaleY: 1.2
					}, {
						duration: 120,
						easing: tween.easeOut,
						onFinish: function onFinish() {
							tween(self, {
								scaleX: 1,
								scaleY: 1
							}, {
								duration: 120,
								easing: tween.easeIn
							});
						}
					});
					// After eating, enter wandering state for 1 minute (3600 frames)
					self.state = "wandering";
					self._eatCooldown = 3600;
				}
			}
		} // end hungry state
	};
	// Carnivores are not eaten in this MVP
	return self;
});
// Egg class
var Egg = Container.expand(function () {
	var self = Container.call(this);
	// Always use carnivore_egg asset if this is a carnivore egg, pollinator_egg if pollinator, else normal egg
	var eggAsset;
	if (self._isCarnivoreEgg === true || self._carnivoreHatch === true) {
		eggAsset = self.attachAsset('carnivore_egg', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: 1,
			scaleY: 1
		});
	} else if (self._isPollinatorEgg === true || self._pollinatorHatch === true) {
		eggAsset = self.attachAsset('pollinator_egg', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: 1,
			scaleY: 1
		});
	} else {
		eggAsset = self.attachAsset('egg', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: 1,
			scaleY: 1
		});
	}
	self.hatched = false;
	self._hatchTimer = 420 + Math.floor(Math.random() * 180); // 7-10 seconds
	self.update = function () {
		if (self.hatched) return;
		// Pause hatching if it's summer or winter
		var isSummer = !!window.summerState;
		var isWinter = !!window.winterState;
		if (isSummer || isWinter) {
			// Do not decrement hatch timer, eggs are dormant
			return;
		}
		// --- POLLINATOR POPULATION CONTROL: Prevent pollinator eggs from hatching if there are already 10 pollinators ---
		if ((self._isPollinatorEgg || self._pollinatorHatch) && typeof pollinators !== "undefined" && pollinators.length >= 10) {
			// Do not decrement hatch timer, do not hatch, just wait
			return;
		}
		// --- CARNIVORE POPULATION CONTROL: Prevent carnivore eggs from hatching if there are already 4 carnivores ---
		if ((self._isCarnivoreEgg || self._carnivoreHatch) && typeof carnivores !== "undefined" && carnivores.length >= 4) {
			// Do not decrement hatch timer, do not hatch, just wait
			return;
		}
		self._hatchTimer--;
		// --- PARASITE POPULATION CONTROL: Prevent parasite eggs from hatching if there are already 4 parasites ---
		if ((self._isParasiteEgg || self._parasiteHatch) && typeof parasites !== "undefined" && parasites.length >= 4) {
			// Do not decrement hatch timer, do not hatch, just wait
			return;
		}
		// --- HERBIVORE POPULATION CONTROL: Prevent herbivore eggs from hatching if there are already 6 herbivores ---
		if (!self._isCarnivoreEgg && !self._carnivoreHatch && !self._isPollinatorEgg && !self._pollinatorHatch && !self._isParasiteEgg && !self._parasiteHatch && typeof herbivores !== "undefined" && herbivores.length >= 6) {
			// Do not decrement hatch timer, do not hatch, just wait
			return;
		}
		if (self._hatchTimer <= 0) {
			// In autumn, eggs have a reduced chance to hatch (e.g. 60% hatch, 40% fail)
			if (window.autumnState && Math.random() < 0.4) {
				// Egg fails to hatch, animate and destroy
				self.eaten = true;
				tween(self, {
					scaleX: 0,
					scaleY: 0,
					alpha: 0
				}, {
					duration: 200,
					easing: tween.easeIn,
					onFinish: function onFinish() {
						self.destroy();
					}
				});
				return;
			}
			self.hatched = true;
			// Animate egg hatching
			tween(self, {
				scaleX: 1.2,
				scaleY: 1.2,
				alpha: 0.5
			}, {
				duration: 200,
				easing: tween.easeOut,
				onFinish: function onFinish() {
					// Spawn a new carnivore if this is a carnivore egg, pollinator if pollinator egg, parasite if parasite egg, otherwise herbivore
					var popSnd = LK.getSound('Hatch');
					if (self._isCarnivoreEgg && self._carnivoreHatch) {
						var carn = new Carnivore();
						carn.x = self.x;
						carn.y = self.y;
						carn.scaleX = 1;
						carn.scaleY = 1;
						carn.alpha = 1;
						if (self.parent) self.parent.addChild(carn);
						if (typeof carnivores !== "undefined") carnivores.push(carn);
						if (popSnd && typeof popSnd.play === "function") popSnd.play();
					} else if (self._isPollinatorEgg && self._pollinatorHatch) {
						var poll = new Pollinator();
						poll.x = self.x;
						poll.y = self.y;
						poll.scaleX = 1;
						poll.scaleY = 1;
						poll.alpha = 1;
						// Reset pollinator starve timer on hatch
						poll._starveTimer = 3000 + Math.floor(Math.random() * 1200);
						// Set pollinator to hungry state after hatching
						poll.state = "hungry";
						poll.target = null;
						if (self.parent) self.parent.addChild(poll);
						if (typeof pollinators !== "undefined") pollinators.push(poll);
						if (popSnd && typeof popSnd.play === "function") popSnd.play();
					} else if (self._isParasiteEgg && self._parasiteHatch) {
						// If this egg was laid by a parasite attached to a resistant host, always inherit resistance
						var inheritResistance = false;
						if (typeof self._parentHost !== "undefined" && self._parentHost && self._parentHost.parasiteResistant === true) {
							inheritResistance = true;
						}
						var parasite = new Parasite();
						parasite.x = self.x;
						parasite.y = self.y;
						parasite.scaleX = 1;
						parasite.scaleY = 1;
						parasite.alpha = 1;
						if (inheritResistance) {
							parasite.parasiteResistant = true;
						}
						if (self.parent) self.parent.addChild(parasite);
						if (typeof parasites !== "undefined") parasites.push(parasite);
						if (popSnd && typeof popSnd.play === "function") popSnd.play();
					} else {
						// Spawn a new Nummer at this position
						var herb = new Nummer();
						herb._uniqueId = "herb_" + Math.floor(Math.random() * 1e9) + "_" + Math.floor(Math.random() * 1e9);
						herb.x = self.x;
						herb.y = self.y;
						herb.scaleX = 1;
						herb.scaleY = 1;
						herb.alpha = 1;
						// If this egg was laid by a parasite attached to a resistant host, always inherit resistance
						if (typeof self._parentHost !== "undefined" && self._parentHost && self._parentHost.parasiteResistant === true) {
							herb.parasiteResistant = true;
						}
						if (self.parent) self.parent.addChild(herb);
						herbivores.push(herb);
						if (popSnd && typeof popSnd.play === "function") popSnd.play();
					}
					self.destroy();
				}
			});
		}
	};
	return self;
});
// Fungi class
var Fungi = Container.expand(function () {
	var self = Container.call(this);
	// Track the cycle the fungi was created in
	self._bornCycle = typeof cycleCount !== "undefined" ? cycleCount : 0;
	// Use fungi asset
	var fungiAsset = self.attachAsset('fungi', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Fungi AI: shoot spores at nearby herbivores
	self._sporeCooldown = 0;
	self.update = function () {
		// Fungi lifespan removed: fungi no longer die after 1 cycle
		// Only shoot if cooldown is 0
		if (self._sporeCooldown > 0) {
			self._sporeCooldown--;
			return;
		}
		// --- FUNGI POPULATION CONTROL: Prevent infecting with spores if 20 or more fungi ---
		if (typeof fungis !== "undefined" && fungis.length >= 20) {
			return;
		}
		// Find nearest herbivore within 400px
		var minDist = 999999,
			closest = null;
		for (var i = 0; i < herbivores.length; i++) {
			var h = herbivores[i];
			if (h.eaten || h.spored) continue;
			var dx = h.x - self.x,
				dy = h.y - self.y;
			var dist = dx * dx + dy * dy;
			if (dist < minDist && Math.sqrt(dist) < 400) {
				minDist = dist;
				closest = h;
			}
		}
		if (closest) {
			// Shoot a spore at the herbivore
			var spore = new FungiSpore();
			spore.x = self.x;
			spore.y = self.y;
			spore.target = closest;
			game.addChild(spore);
			if (!fungiSpores) fungiSpores = [];
			fungiSpores.push(spore);
			self._sporeCooldown = 120 + Math.floor(Math.random() * 60); // 2-3 seconds cooldown
		}
	};
	// Track if this fungi is currently 'blocked' from respawning after being eaten
	self._blockedRespawn = false;
	// Add die method so fungi disappear when eaten
	self.die = function () {
		if (self.eaten) return;
		self.eaten = true;
		// Animate shrink and fade out, then destroy
		tween(self, {
			scaleX: 0,
			scaleY: 0,
			alpha: 0
		}, {
			duration: 200,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				self.destroy();
			}
		});
	};
	return self;
});
// Nummer class (formerly Herbivore)
var Nummer = Container.expand(function () {
	var self = Container.call(this);
	// Uncommon: 15% chance to be resistant to parasites
	self.parasiteResistant = Math.random() < 0.15;
	// Track if this Nummer was hit by a spore
	self.spored = false;
	var herbAsset = self.attachAsset('herbivore', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.target = null;
	self.speed = 1.2 + Math.random() * 1.0;
	self.eaten = false;
	// Track number of plants eaten for egg laying
	self._plantsEaten = 0;
	// --- State management for hungry/sleepy ---
	self.state = "hungry"; // "hungry" or "sleepy"
	self._sleepTimer = 0; // frames left in sleepy state
	// --- Starvation timer: die if not eating for 2 cycles (80 seconds = 4800 frames) ---
	self._starveTimer = 4800; // 80 seconds at 60fps
	// --- Personality system ---
	// Personalities: "normal", "curious", "grumpy"
	var personalities = ["normal", "curious", "grumpy"];
	// Assign a random personality at creation
	var rand = Math.random();
	// Make random traits more common: 30% normal, 35% curious, 35% grumpy
	if (rand < 0.3) {
		self.personality = "normal";
	} else if (rand < 0.65) {
		self.personality = "curious";
	} else {
		self.personality = "grumpy";
	}
	// For curious: timer for following pollinators
	self._curiousFollowTimer = 0;
	self._curiousPollinatorTarget = null;
	// For grumpy: scare cooldown
	self._grumpyScareCooldown = 0;
	self.update = function () {
		if (self.eaten) return;
		// --- HERBIVORE HUNGER QUEUE LOGIC ---
		// Only 2 herbivores can be in "hungry" state at a time. Others must wait in "waiting" state.
		if (!self._hungerQueueState) self._hungerQueueState = "unset"; // "unset", "waiting", "hungry"
		if (self.state === "hungry" && self._hungerQueueState !== "hungry") {
			// Try to enter the hunger queue
			if (herbivoreHungerQueue.indexOf(self) === -1) {
				herbivoreHungerQueue.push(self);
			}
			// If not in the first 2, set to waiting
			if (herbivoreHungerQueue[0] !== self && herbivoreHungerQueue[1] !== self) {
				self._hungerQueueState = "waiting";
				self.state = "waiting";
				// Don't do hungry logic this frame
			} else {
				self._hungerQueueState = "hungry";
				// Continue as hungry
			}
		} else if (self.state === "waiting" && self._hungerQueueState !== "waiting") {
			// Enter waiting queue if not already
			if (herbivoreHungerQueue.indexOf(self) === -1) {
				herbivoreHungerQueue.push(self);
			}
			// If now in first 2, become hungry
			if (herbivoreHungerQueue[0] === self || herbivoreHungerQueue[1] === self) {
				self.state = "hungry";
				self._hungerQueueState = "hungry";
			} else {
				self._hungerQueueState = "waiting";
				// Don't do hungry logic this frame
			}
		} else if (self.state === "hungry" && (herbivoreHungerQueue[0] === self || herbivoreHungerQueue[1] === self)) {
			self._hungerQueueState = "hungry";
		} else if (self.state === "hungry" && herbivoreHungerQueue.indexOf(self) > 1) {
			// If somehow in hungry state but not allowed, set to waiting
			self.state = "waiting";
			self._hungerQueueState = "waiting";
		}
		// If in waiting state, just wander
		if (self.state === "waiting") {
			// --- Random wandering ---
			if (!self._wanderTimer || self._wanderTimer <= 0) {
				var angle = Math.random() * Math.PI * 2;
				self._wanderAngle = angle;
				self._wanderTimer = 60 + Math.floor(Math.random() * 60);
			}
			if (typeof self._wanderAngle === "number") {
				self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
				self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
				self._wanderTimer--;
				// Keep inside map bounds (strictly)
				var minX = 124 + 60;
				var maxX = 124 + 1800 - 60;
				var minY = paletteY + 320 + 60;
				var maxY = paletteY + 320 + 2000 - 60;
				if (self.x < minX) self.x = minX;
				if (self.x > maxX) self.x = maxX;
				if (self.y < minY) self.y = minY;
				if (self.y > maxY) self.y = maxY;
			}
			// Don't do hungry logic
			return;
		}
		// --- HERBIVORE RANDOM SOUND LOGIC ---
		// Only make sound if not eaten and not in winter (optional: you can allow in winter if desired)
		if (typeof self._nextHerbSoundTimer === "undefined") {
			// Set initial timer to random 6-10 seconds (360-600 frames)
			self._nextHerbSoundTimer = 360 + Math.floor(Math.random() * 241);
		}
		if (self._nextHerbSoundTimer > 0) {
			self._nextHerbSoundTimer--;
		} else {
			// Play the 'Herbivore' sound
			var snd = LK.getSound('Herbivore');
			if (snd && typeof snd.play === "function") snd.play();
			// Reset timer to next random interval (6-10 seconds)
			self._nextHerbSoundTimer = 360 + Math.floor(Math.random() * 241);
		}
		// --- WINTER BEHAVIOR: Move slower, avoid eating, and halt starvation meter ---
		var isWinter = !!window.winterState;
		var originalSpeed = self.speed;
		if (isWinter) {
			// Move slower in winter
			self.speed = originalSpeed * 0.4;
		} else {
			self.speed = originalSpeed;
		}
		// Starvation logic: decrement timer if alive and hungry/wandering, but not in winter
		if ((self.state === "hungry" || self.state === "wandering") && !isWinter) {
			self._starveTimer--;
			if (self._starveTimer <= 0 && !self.eaten) {
				// Starve and die
				self.die();
				return;
			}
		}
		// Handle infected state
		if (self.infected) {
			self.infectedTimer = (self.infectedTimer || 0) + 1;
			// Future: add infected behavior here (e.g. slow, animation, etc)
		}
		// If infection was pending from summer, and now it's not summer, apply infection
		if (self._pendingFungiInfection && !window.summerState) {
			self._pendingFungiInfection = false;
			self.infected = true;
			self.infectedTimer = 0;
			// Tint permanently purple
			tween(self, {
				tint: 0xbb88ff
			}, {
				duration: 80
			});
		}
		// Handle sleepy state
		// If just left hungry state (became wandering or sleepy), remove from hunger queue and allow next in queue to become hungry
		if ((self.state === "wandering" || self.state === "sleepy") && self._hungerQueueState === "hungry") {
			var idx = herbivoreHungerQueue.indexOf(self);
			if (idx !== -1) {
				herbivoreHungerQueue.splice(idx, 1);
			}
			self._hungerQueueState = "unset";
			// Next in queue (if any) becomes hungry
			for (var i = 0; i < herbivoreHungerQueue.length; i++) {
				var h = herbivoreHungerQueue[i];
				if (h && h.state === "waiting") {
					h.state = "hungry";
					h._hungerQueueState = "hungry";
					break;
				}
			}
		}
		if (self.state === "sleepy") {
			// Check for nearby carnivore and possibly wake up
			var nearestCarn = null;
			var minCarnDist = 999999;
			for (var ci = 0; ci < carnivores.length; ci++) {
				var carn = carnivores[ci];
				if (carn.eaten) continue;
				var cdx = carn.x - self.x;
				var cdy = carn.y - self.y;
				var cdist = cdx * cdx + cdy * cdy;
				if (cdist < minCarnDist) {
					minCarnDist = cdist;
					nearestCarn = carn;
				}
			}
			// If carnivore is within 300px, 50% chance to wake up and run away
			if (nearestCarn && Math.sqrt(minCarnDist) < 300) {
				// Only try to wake up once per frame if still sleepy
				if (!self._triedWakeThisFrame) {
					self._triedWakeThisFrame = true;
					if (Math.random() < 0.5) {
						// Wake up and run away from carnivore
						self.state = "hungry";
						// Move away from carnivore immediately
						var dx = self.x - nearestCarn.x;
						var dy = self.y - nearestCarn.y;
						var dist = Math.sqrt(dx * dx + dy * dy);
						if (dist > 1) {
							// Move a burst away (3x speed for one frame)
							self.x += dx / dist * (self.speed * 3);
							self.y += dy / dist * (self.speed * 3);
						}
						// Clamp to map area
						var minX = 124 + 60;
						var maxX = 124 + 1800 - 60;
						var minY = paletteY + 320 + 60;
						var maxY = paletteY + 320 + 2000 - 60;
						if (self.x < minX) self.x = minX;
						if (self.x > maxX) self.x = maxX;
						if (self.y < minY) self.y = minY;
						if (self.y > maxY) self.y = maxY;
						// Don't continue sleeping
						return;
					}
				}
			} else {
				self._triedWakeThisFrame = false;
			}
			self._sleepTimer--;
			if (self._sleepTimer <= 0) {
				self.state = "wandering";
				self._wanderAfterSleepTimer = 600; // 10 seconds at 60fps
			}
			// While sleepy, don't move or seek food
			return;
		}
		// Wandering state after sleep: ignore plants, just wander for 10s, then become hungry
		if (self.state === "wandering") {
			if (typeof self._wanderAfterSleepTimer === "undefined") self._wanderAfterSleepTimer = 600;
			self._wanderAfterSleepTimer--;
			// --- Random wandering ---
			if (!self._wanderTimer || self._wanderTimer <= 0) {
				var angle = Math.random() * Math.PI * 2;
				self._wanderAngle = angle;
				self._wanderTimer = 60 + Math.floor(Math.random() * 60);
			}
			if (typeof self._wanderAngle === "number") {
				self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
				self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
				self._wanderTimer--;
				// Keep inside map bounds (strictly)
				var minX = 124 + 60;
				var maxX = 124 + 1800 - 60;
				var minY = paletteY + 320 + 60;
				var maxY = paletteY + 320 + 2000 - 60;
				if (self.x < minX) self.x = minX;
				if (self.x > maxX) self.x = maxX;
				if (self.y < minY) self.y = minY;
				if (self.y > maxY) self.y = maxY;
			}
			if (self._wanderAfterSleepTimer <= 0) {
				self.state = "hungry";
			}
			return;
		}
		// Only seek food if hungry
		if (self.state === "hungry") {
			var isWinter = !!window.winterState;
			// --- PERSONALITY: CURIOUS ---
			// If curious, sometimes follow pollinators for a few seconds
			if (self.personality === "curious") {
				// If not already following, 1% chance per frame to start following a pollinator
				if (self._curiousFollowTimer <= 0 && Math.random() < 0.01 && pollinators.length > 0) {
					// Pick a random pollinator to follow
					var idx = Math.floor(Math.random() * pollinators.length);
					var poll = pollinators[idx];
					if (poll && !poll.eaten) {
						self._curiousPollinatorTarget = poll;
						self._curiousFollowTimer = 120 + Math.floor(Math.random() * 120); // 2-4 seconds
					}
				}
				// If following a pollinator
				if (self._curiousFollowTimer > 0 && self._curiousPollinatorTarget && !self._curiousPollinatorTarget.eaten) {
					var dx = self._curiousPollinatorTarget.x - self.x;
					var dy = self._curiousPollinatorTarget.y - self.y;
					var dist = Math.sqrt(dx * dx + dy * dy);
					if (dist > 1) {
						self.x += dx / dist * self.speed;
						self.y += dy / dist * self.speed;
					}
					self._curiousFollowTimer--;
					// Clamp to map area
					var minX = 124 + 60;
					var maxX = 124 + 1800 - 60;
					var minY = paletteY + 320 + 60;
					var maxY = paletteY + 320 + 2000 - 60;
					if (self.x < minX) self.x = minX;
					if (self.x > maxX) self.x = maxX;
					if (self.y < minY) self.y = minY;
					if (self.y > maxY) self.y = maxY;
					// If timer runs out or pollinator is gone, stop following
					if (self._curiousFollowTimer <= 0 || self._curiousPollinatorTarget.eaten) {
						self._curiousFollowTimer = 0;
						self._curiousPollinatorTarget = null;
					}
					// While following, do not seek plants
					return;
				}
				// If not following, proceed as normal below
			}
			// --- PERSONALITY: GRUMPY ---
			// If grumpy, check for carnivore within 120px and scare it away if it is targeting this herbivore
			if (self.personality === "grumpy" && self._grumpyScareCooldown <= 0) {
				for (var ci = 0; ci < carnivores.length; ci++) {
					var carn = carnivores[ci];
					if (carn.eaten) continue;
					var dx = carn.x - self.x;
					var dy = carn.y - self.y;
					var dist = Math.sqrt(dx * dx + dy * dy);
					// If carnivore is close and targeting this herbivore
					// Bloodthirsty carnivores are not scared of grumpy herbivores
					if (dist < 120 && carn.target === self && !carn._tired && carn.personality !== "bloodthirsty") {
						// Scare the carnivore away: set it to wandering, clear its target, and make it tired
						carn.state = "wandering";
						carn.target = null;
						carn._tired = true;
						carn._tiredTimer = 300 + Math.floor(Math.random() * 200); // 5-8 seconds
						carn._chaseTime = 0;
						// Grumpy herbivore enters a short cooldown before it can scare again
						self._grumpyScareCooldown = 300; // 5 seconds
						// Optional: animate the herbivore (e.g. scale up briefly)
						tween(self, {
							scaleX: 1.3,
							scaleY: 1.3
						}, {
							duration: 80,
							easing: tween.easeOut,
							onFinish: function onFinish() {
								tween(self, {
									scaleX: 1,
									scaleY: 1
								}, {
									duration: 80,
									easing: tween.easeIn
								});
							}
						});
						break;
					}
				}
			}
			if (self._grumpyScareCooldown > 0) self._grumpyScareCooldown--;
			// --- END PERSONALITY LOGIC ---
			// Normal hungry logic
			// In winter, do not seek or eat plants, but wander randomly
			if (isWinter) {
				// Wander only, do not target plants
				self.target = null;
				// --- Random wandering in winter ---
				if (!self._wanderTimer || self._wanderTimer <= 0) {
					var angle = Math.random() * Math.PI * 2;
					self._wanderAngle = angle;
					self._wanderTimer = 60 + Math.floor(Math.random() * 60);
				}
				if (typeof self._wanderAngle === "number") {
					self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
					self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
					self._wanderTimer--;
					// Keep inside map bounds (strictly)
					var minX = 124 + 60;
					var maxX = 124 + 1800 - 60;
					var minY = paletteY + 320 + 60;
					var maxY = paletteY + 320 + 2000 - 60;
					if (self.x < minX) self.x = minX;
					if (self.x > maxX) self.x = maxX;
					if (self.y < minY) self.y = minY;
					if (self.y > maxY) self.y = maxY;
				}
			} else {
				// Always target the nearest plant when hungry
				var minDist = 999999,
					closest = null;
				for (var i = 0; i < plants.length; i++) {
					var p = plants[i];
					if (p.eaten) continue;
					var dx = p.x - self.x,
						dy = p.y - self.y;
					var dist = dx * dx + dy * dy;
					if (dist < minDist) {
						minDist = dist;
						closest = p;
					}
				}
				self.target = closest;
			}
			// Nummer can walk over fungi as if it is not there: do not treat fungi as obstacles, so do not check for collision or avoid them at all in movement logic.
			// Check for nearest carnivore
			var nearestCarn = null;
			var minCarnDist = 999999;
			var tiredCarnivore = null;
			var tiredCarnDist = 999999;
			for (var ci = 0; ci < carnivores.length; ci++) {
				var carn = carnivores[ci];
				if (carn.eaten) continue;
				var cdx = carn.x - self.x;
				var cdy = carn.y - self.y;
				var cdist = cdx * cdx + cdy * cdy;
				if (cdist < minCarnDist) {
					minCarnDist = cdist;
					nearestCarn = carn;
				}
				// Track tired carnivore chasing this herbivore
				if (carn._tired && carn.target === self && cdist < tiredCarnDist) {
					tiredCarnivore = carn;
					tiredCarnDist = cdist;
				}
			}
			var carnivoreTooClose = false;
			var carnDist = 0;
			var runAwayDX = 0,
				runAwayDY = 0;
			if (nearestCarn) {
				carnDist = Math.sqrt((nearestCarn.x - self.x) * (nearestCarn.x - self.x) + (nearestCarn.y - self.y) * (nearestCarn.y - self.y));
				if (nearestCarn._tired && nearestCarn.target === self) {
					// If a tired carnivore was chasing this herbivore, teleport a tiny distance in front of it (away from carnivore)
					// Only teleport once per tired state
					if (!self._teleportedFromTiredCarnivore) {
						var dx = self.x - nearestCarn.x;
						var dy = self.y - nearestCarn.y;
						var dist = Math.sqrt(dx * dx + dy * dy);
						if (dist < 200) {
							// Only teleport if not already far away
							// Teleport 80px away in the direction away from carnivore
							var teleportDist = 80;
							var tx = nearestCarn.x + dx / (dist || 1) * teleportDist;
							var ty = nearestCarn.y + dy / (dist || 1) * teleportDist;
							// Clamp to map area
							var minX = 124 + 60;
							var maxX = 124 + 1800 - 60;
							var minY = paletteY + 320 + 60;
							var maxY = paletteY + 320 + 2000 - 60;
							if (tx < minX) tx = minX;
							if (tx > maxX) tx = maxX;
							if (ty < minY) ty = minY;
							if (ty > maxY) ty = maxY;
							self.x = tx;
							self.y = ty;
						}
						self._teleportedFromTiredCarnivore = true;
						// After teleport, set a run away timer so it keeps running for a while
						self._runAwayFromTiredCarnivoreTimer = 60 + Math.floor(Math.random() * 60); // 1-2 seconds
						// Pick a run direction directly away from carnivore
						if (dist > 0) {
							self._runAwayAngle = Math.atan2(dy, dx);
						} else {
							self._runAwayAngle = Math.random() * Math.PI * 2;
						}
					}
					carnivoreTooClose = true;
					runAwayDX = self.x - nearestCarn.x;
					runAwayDY = self.y - nearestCarn.y;
				} else if (carnDist < 300) {
					// If carnivore is within 300px, run away
					carnivoreTooClose = true;
					runAwayDX = self.x - nearestCarn.x;
					runAwayDY = self.y - nearestCarn.y;
					// Reset teleport flag if not being chased by tired carnivore
					self._teleportedFromTiredCarnivore = false;
				}
			}
			// --- New: If a tired carnivore was chasing this herbivore, charge away until far enough ---
			// (Removed barrier logic: herbivores can always run away from tired carnivores)
			if (carnivoreTooClose && carnDist > 1) {
				// If running from a tired carnivore and we have a run timer, keep running in the set direction
				if (typeof self._runAwayFromTiredCarnivoreTimer !== "undefined" && self._runAwayFromTiredCarnivoreTimer > 0) {
					self.x += Math.cos(self._runAwayAngle) * self.speed * 2.2;
					self.y += Math.sin(self._runAwayAngle) * self.speed * 2.2;
					self._runAwayFromTiredCarnivoreTimer--;
					// Clamp to map area
					var minX = 124 + 60;
					var maxX = 124 + 1800 - 60;
					var minY = paletteY + 320 + 60;
					var maxY = paletteY + 320 + 2000 - 60;
					if (self.x < minX) self.x = minX;
					if (self.x > maxX) self.x = maxX;
					if (self.y < minY) self.y = minY;
					if (self.y > maxY) self.y = maxY;
					// When timer runs out, clear teleport/run state so it can look for food again
					if (self._runAwayFromTiredCarnivoreTimer <= 0) {
						self._runAwayFromTiredCarnivoreTimer = 0;
						self._teleportedFromTiredCarnivore = false;
					}
					// While running, do not seek food
					return;
				} else {
					// Run away from carnivore (normal, not tired chase)
					self.x += runAwayDX / carnDist * (self.speed * 1.5);
					self.y += runAwayDY / carnDist * (self.speed * 1.5);
					// Reset teleport/run state if not running from tired carnivore
					self._teleportedFromTiredCarnivore = false;
					self._runAwayFromTiredCarnivoreTimer = 0;
				}
			} else {
				// --- Random wandering when not chasing plant ---
				if ((!self.target || self.target.eaten) && (!self._wanderTimer || self._wanderTimer <= 0)) {
					// Pick a new random direction every 60-120 frames
					var angle = Math.random() * Math.PI * 2;
					self._wanderAngle = angle;
					self._wanderTimer = 60 + Math.floor(Math.random() * 60);
				}
				if (!self.target || self.target.eaten) {
					// Wander in the chosen direction
					if (typeof self._wanderAngle === "number") {
						self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
						self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
						self._wanderTimer--;
						// Keep inside map bounds (strictly)
						var minX = 124 + 60;
						var maxX = 124 + 1800 - 60;
						var minY = paletteY + 320 + 60;
						var maxY = paletteY + 320 + 2000 - 60;
						if (self.x < minX) self.x = minX;
						if (self.x > maxX) self.x = maxX;
						if (self.y < minY) self.y = minY;
						if (self.y > maxY) self.y = maxY;
					}
				}
				// Move toward target plant
				if (self.target && !self.target.eaten) {
					var isWinter = !!window.winterState;
					var dx = self.target.x - self.x;
					var dy = self.target.y - self.y;
					var dist = Math.sqrt(dx * dx + dy * dy);
					if (dist > 1) {
						self.x += dx / dist * self.speed;
						self.y += dy / dist * self.speed;
					}
					// Eat plant if close enough, but not in winter
					if (!isWinter && dist < 60 && !self.target.eaten) {
						var eatenPlant = self.target;
						// Play chomp sound when a herbivore eats a plant
						var chompSnd = LK.getSound('Chomp');
						if (chompSnd && typeof chompSnd.play === "function") chompSnd.play();
						self.target.die();
						self.target = null;
						// Animate Nummer "eating"
						tween(self, {
							scaleX: 1.2,
							scaleY: 1.2
						}, {
							duration: 120,
							easing: tween.easeOut,
							onFinish: function onFinish() {
								tween(self, {
									scaleX: 1,
									scaleY: 1
								}, {
									duration: 120,
									easing: tween.easeIn
								});
							}
						});
						// After eating, enter sleepy state for 10 seconds (600 frames) with a chance to skip sleep
						if (Math.random() < 0.7) {
							// 70% chance to sleep, 30% chance to skip
							self.state = "sleepy";
							self._sleepTimer = 600;
						} else {
							// Skip sleep, go straight to wandering
							self.state = "wandering";
							self._wanderAfterSleepTimer = 600; // 10 seconds wandering
						}
						// Reset starvation timer after eating only if plant is not brown
						if (!(eatenPlant && eatenPlant._isBrown)) {
							self._starveTimer = 4800; // 80 seconds at 60fps
						}
						// Increment plants eaten counter
						self._plantsEaten = (self._plantsEaten || 0) + 1;
						// Lay an egg if 4 plants have been eaten, then reset counter
						// --- HERBIVORE POPULATION CONTROL: Only lay egg if < 6 herbivores ---
						if (self._plantsEaten >= 4) {
							if (typeof herbivores !== "undefined" && herbivores.length < 6) {
								var egg = new Egg();
								egg.x = self.x;
								egg.y = self.y;
								egg.scaleX = 0.5;
								egg.scaleY = 0.5;
								egg.alpha = 1;
								if (self.parent) self.parent.addChild(egg);
								if (typeof eggs !== "undefined") eggs.push(egg);
							}
							self._plantsEaten = 0;
						}
					}
				}
			}
		}
	};
	// Called when eaten by carnivore
	self.die = function (_onFinish) {
		if (self.eaten) return;
		self.eaten = true;
		// Remove from hunger queue if present
		var idx = herbivoreHungerQueue.indexOf(self);
		if (idx !== -1) {
			herbivoreHungerQueue.splice(idx, 1);
		}
		// If infected, spawn a fungi at this position
		// --- FUNGI POPULATION CONTROL: Prevent dropping fungi at death if 20 or more fungi ---
		if (self.infected && (typeof fungis === "undefined" || fungis.length < 20)) {
			var newFungi = new Fungi();
			// If fungi is spawned by Nummer death, set its _bornCycle to the next cycle so it lives a full cycle
			if (typeof cycleCount !== "undefined") {
				newFungi._bornCycle = cycleCount + 1;
			}
			newFungi.x = self.x;
			newFungi.y = self.y;
			newFungi.scaleX = 1;
			newFungi.scaleY = 1;
			newFungi.alpha = 1;
			if (self.parent) self.parent.addChild(newFungi);
			if (typeof fungis !== "undefined") fungis.push(newFungi);
		}
		tween(self, {
			scaleX: 0,
			scaleY: 0,
			alpha: 0
		}, {
			duration: 400,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				self.destroy();
				if (_onFinish) _onFinish();
			}
		});
	};
	// Called when hit by a spore
	self.sporeHit = function () {
		if (self.spored) return; // Only allow once
		self.spored = true;
		// If it's summer, delay infection until next winter or spring
		if (window.summerState) {
			// Mark as pending infection, but do not infect yet
			self._pendingFungiInfection = true;
			// Optionally, you could tint a different color to show pending state, or do nothing
			return;
		}
		// Enter infected state immediately if not summer
		self.infected = true;
		self.infectedTimer = 0;
		// Tint permanently purple
		tween(self, {
			tint: 0xbb88ff
		}, {
			duration: 80
		});
	};
	return self;
});
// Parasite class (seeks and attaches to herbivores or carnivores)
var Parasite = Container.expand(function () {
	var self = Container.call(this);
	var parasiteAsset = self.attachAsset('Parasite', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.5,
		scaleY: 0.5
	});
	// State: "seek", "attached"
	self.state = "seek";
	self.target = null;
	self.attachedTo = null;
	self.offsetX = 0;
	self.offsetY = 0;
	self.speed = 1.5 + Math.random() * 0.7;
	// Track last intersecting for attach logic
	self._lastIntersecting = false;
	self.update = function () {
		// If attached, follow the host
		if (self.state === "attached" && self.attachedTo) {
			// AUTUMN: Detach immediately in autumn
			if (window.autumnState) {
				// Detach from host
				if (self.attachedTo._parasiteAttached === self) {
					self.attachedTo._parasiteAttached = null;
				}
				self.state = "seek";
				self.attachedTo = null;
				self.target = null;
				self._wanderTimer = 0;
				// Allow laying an egg only once per parasite in autumn
				if (!self._laidAutumnEgg) {
					var egg = new Egg();
					egg.x = self.x;
					egg.y = self.y;
					egg.scaleX = 0.5;
					egg.scaleY = 0.5;
					egg.alpha = 1;
					egg._isParasiteEgg = true;
					egg._parasiteHatch = true;
					if (self.parent) self.parent.addChild(egg);
					if (typeof eggs !== "undefined") eggs.push(egg);
					self._laidAutumnEgg = true;
				}
				return;
			}
			// If host is eaten, parasite dies with host
			if (self.attachedTo.eaten) {
				// Animate parasite dying and remove from array
				tween(self, {
					scaleX: 0,
					scaleY: 0,
					alpha: 0
				}, {
					duration: 200,
					easing: tween.easeIn,
					onFinish: function onFinish() {
						self.destroy();
						// Remove from parasites array if present
						if (typeof parasites !== "undefined") {
							var idx = parasites.indexOf(self);
							if (idx !== -1) parasites.splice(idx, 1);
						}
					}
				});
				return;
			}
			// If host is a herbivore and is infected by shrooms, let go immediately
			if (typeof self.attachedTo.spored !== "undefined" && self.attachedTo.spored === true) {
				// Detach from host
				if (self.attachedTo._parasiteAttached === self) {
					self.attachedTo._parasiteAttached = null;
				}
				self.state = "seek";
				self.attachedTo = null;
				self.target = null;
				// Wander in a new random direction
				self._wanderTimer = 0;
				return;
			}
			// Stay at the same offset from host
			self.x = self.attachedTo.x + self.offsetX;
			self.y = self.attachedTo.y + self.offsetY;
			// --- Parasite lays an egg every cycle if attached to a host, but only if < 4 parasites ---
			if (typeof self._lastCycle === "undefined") self._lastCycle = -1;
			if (typeof cycleCount !== "undefined" && self._lastCycle !== cycleCount) {
				self._lastCycle = cycleCount;
				if (typeof parasites !== "undefined" && parasites.length < 4) {
					// Lay a parasite egg at current position
					var egg = new Egg();
					egg.x = self.x;
					egg.y = self.y;
					egg.scaleX = 0.5;
					egg.scaleY = 0.5;
					egg.alpha = 1;
					egg._isParasiteEgg = true;
					egg._parasiteHatch = true;
					// Pass parent host resistance to egg for inheritance
					if (self.attachedTo && self.attachedTo.parasiteResistant === true) {
						egg._parentHost = self.attachedTo;
					}
					if (self.parent) self.parent.addChild(egg);
					if (typeof eggs !== "undefined") eggs.push(egg);
				}
			}
			return;
		}
		// If seeking, look for nearest herbivore or carnivore
		if (self.state === "seek") {
			// In autumn, cannot infect, so just wander
			if (window.autumnState) {
				// Wander randomly if no target
				if (!self._wanderTimer || self._wanderTimer <= 0) {
					self._wanderAngle = Math.random() * Math.PI * 2;
					self._wanderTimer = 60 + Math.floor(Math.random() * 60);
				}
				if (typeof self._wanderAngle === "number") {
					self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
					self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
					self._wanderTimer--;
					// Keep inside map bounds
					var minX = 124 + 60;
					var maxX = 124 + 1800 - 60;
					var minY = paletteY + 320 + 60;
					var maxY = paletteY + 320 + 2000 - 60;
					if (self.x < minX) self.x = minX;
					if (self.x > maxX) self.x = maxX;
					if (self.y < minY) self.y = minY;
					if (self.y > maxY) self.y = maxY;
				}
				self._lastIntersecting = false;
				return;
			}
			// If no target or target is eaten or already has a parasite attached (not self), find new target
			if (!self.target || self.target.eaten || self.target._parasiteAttached && self.target._parasiteAttached !== self) {
				var minDist = 999999,
					closest = null;
				// Search herbivores first
				for (var i = 0; i < herbivores.length; i++) {
					var h = herbivores[i];
					if (h.eaten) continue;
					// Only attach if not already parasitized
					if (h._parasiteAttached) continue;
					// Avoid targeting spore-infected herbivores
					if (h.spored === true) continue;
					// Avoid parasite-resistant herbivores
					if (h.parasiteResistant === true) continue;
					var dx = h.x - self.x,
						dy = h.y - self.y;
					var dist = dx * dx + dy * dy;
					if (dist < minDist) {
						minDist = dist;
						closest = h;
					}
				}
				// If no herbivore, search carnivores
				if (!closest) {
					for (var i = 0; i < carnivores.length; i++) {
						var c = carnivores[i];
						if (c.eaten) continue;
						if (c._parasiteAttached) continue;
						// Only infect weak carnivores (personality === "weak")
						if (c.personality !== "weak") continue;
						// Avoid parasite-resistant carnivores
						if (c.parasiteResistant === true) continue;
						var dx = c.x - self.x,
							dy = c.y - self.y;
						var dist = dx * dx + dy * dy;
						if (dist < minDist) {
							minDist = dist;
							closest = c;
						}
					}
				}
				self.target = closest;
			}
			// If we have a target, move toward it
			if (self.target && !self.target.eaten && !self.target._parasiteAttached) {
				var dx = self.target.x - self.x;
				var dy = self.target.y - self.y;
				var dist = Math.sqrt(dx * dx + dy * dy);
				if (dist > 1) {
					self.x += dx / dist * self.speed;
					self.y += dy / dist * self.speed;
				}
				// Attach if close enough and not already attached
				var isIntersecting = self.intersects(self.target);
				if (!self._lastIntersecting && isIntersecting && !self.target._parasiteAttached) {
					// Attach to host
					self.state = "attached";
					self.attachedTo = self.target;
					// Store offset so parasite stays visually attached
					self.offsetX = self.x - self.attachedTo.x;
					self.offsetY = self.y - self.attachedTo.y;
					// Mark host as parasitized
					self.attachedTo._parasiteAttached = self;
				}
				self._lastIntersecting = isIntersecting;
			} else {
				// Wander randomly if no target
				if (!self._wanderTimer || self._wanderTimer <= 0) {
					self._wanderAngle = Math.random() * Math.PI * 2;
					self._wanderTimer = 60 + Math.floor(Math.random() * 60);
				}
				if (typeof self._wanderAngle === "number") {
					self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
					self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
					self._wanderTimer--;
					// Keep inside map bounds
					var minX = 124 + 60;
					var maxX = 124 + 1800 - 60;
					var minY = paletteY + 320 + 60;
					var maxY = paletteY + 320 + 2000 - 60;
					if (self.x < minX) self.x = minX;
					if (self.x > maxX) self.x = maxX;
					if (self.y < minY) self.y = minY;
					if (self.y > maxY) self.y = maxY;
				}
				self._lastIntersecting = false;
			}
		}
	};
	return self;
});
// Plant class
var Plant = Container.expand(function () {
	var self = Container.call(this);
	var plantAsset = self.attachAsset('plant', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.plantAsset = plantAsset; // Expose for tinting
	self._canDie = true; // Track if plant can die
	// Plants are static, but we can animate them when eaten
	self.eaten = false;
	// Track the cycle the plant was created in
	self._bornCycle = typeof cycleCount !== "undefined" ? cycleCount : 0;
	self.die = function (_onFinish2) {
		if (self.eaten) return;
		if (self._canDie === false) return; // Prevent dying if not allowed
		self.eaten = true;
		tween(self, {
			scaleX: 0,
			scaleY: 0,
			alpha: 0
		}, {
			duration: 400,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				self.destroy();
				if (_onFinish2) _onFinish2();
			}
		});
	};
	// Plants die after 1 cycle
	self.update = function () {
		if (self.eaten) return;
		// --- Summer: chance to turn brown and become unpollinatable ---
		if (self._invulnerable) {
			// While invulnerable, never turn brown or die
			self._isBrown = false;
			if (self.plantAsset && typeof self.plantAsset.tint !== "undefined") {
				self.plantAsset.tint = 0xffffff;
			}
		} else {
			if ((window.summerState || window.springState) && !self._isBrown && !self.eaten) {
				// Only roll once per plant per summer or spring
				if (typeof self._brownChecked === "undefined" || self._brownChecked !== cycleCount) {
					self._brownChecked = cycleCount;
					if (window.summerState && Math.random() < 0.12) {
						// ~12% chance per cycle in summer
						self._isBrown = true;
						if (self.plantAsset && typeof self.plantAsset.tint !== "undefined") {
							self.plantAsset.tint = 0x996633; // brown
						}
					} else if (window.springState && Math.random() < 0.002) {
						// ~0.2% chance per cycle in spring (VERY low)
						self._isBrown = true;
						if (self.plantAsset && typeof self.plantAsset.tint !== "undefined") {
							self.plantAsset.tint = 0x996633; // brown
						}
					}
				}
			}
			// If not summer, reset brown state
			if (!window.summerState && self._isBrown) {
				self._isBrown = false;
				if (self.plantAsset && typeof self.plantAsset.tint !== "undefined") {
					self.plantAsset.tint = 0xffffff;
				}
			}
			// Only die if at least one full cycle has passed since birth
			if (typeof cycleCount !== "undefined" && typeof self._bornCycle !== "undefined") {
				// Brown plants in summer: die after 1/2 cycle (shorter lifespan)
				if (self._isBrown && window.summerState && self._canDie !== false) {
					if (cycleCount > self._bornCycle + 0.5) {
						self.die();
					}
				} else if (cycleCount > self._bornCycle + 1 && self._canDie !== false) {
					self.die();
				}
			}
		}
	};
	return self;
});
// Pollinator class
var Pollinator = Container.expand(function () {
	var self = Container.call(this);
	var pollAsset = self.attachAsset('pollinator', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// --- Pollinator Starvation Logic ---
	self.state = "seek"; // "seek", "scatter", "planting", "hungry"
	self.target = null;
	self.speed = 2 + Math.random();
	self._scatterTimer = 0;
	self._scatterAngle = 0;
	self._plantSeedTimer = 0;
	self._hasSeed = true;
	self.eaten = false;
	self.lastWasTouchingPlant = false;
	// --- Pollinator Starve Timer ---
	self._starveTimer = 3000 + Math.floor(Math.random() * 1200); // 1 cycle = 50s = 3000 frames, randomize a bit
	self._lastCycle = typeof cycleCount !== "undefined" ? cycleCount : 0;
	// --- Pollination counter for egg laying ---
	self._pollinations = 0;
	self._layingEgg = false;
	self._eggObj = null;
	// --- After eating shroom, next pollination is a shroom ---
	self._nextPollinationIsShroom = false;
	self._didShroomPollination = false;
	self.update = function () {
		if (self.eaten) return;
		// --- POLLINATOR STARVATION LOGIC (handled in constructor patch above) ---
		// --- POLLINATOR HUNGRY STATE: Seek fungi and eat if hungry ---
		if (self.state === "hungry") {
			// Prevent pollinators from eating fungi during autumn, winter, and summer
			var isAutumn = !!window.autumnState;
			var isWinter = !!window.winterState;
			var isSummer = !!window.summerState;
			if (isAutumn || isWinter || isSummer) {
				// Just wander randomly, do not seek or eat fungi, and do not decrement starve timer
				if (!self._wanderTimer || self._wanderTimer <= 0) {
					self._wanderAngle = Math.random() * Math.PI * 2;
					self._wanderTimer = 60 + Math.floor(Math.random() * 60);
				}
				if (typeof self._wanderAngle === "number") {
					self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
					self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
					self._wanderTimer--;
				}
				// Clamp to map area
				var minX = 124 + 60;
				var maxX = 124 + 1800 - 60;
				var minY = paletteY + 320 + 60;
				var maxY = paletteY + 320 + 2000 - 60;
				if (self.x < minX) self.x = minX;
				if (self.x > maxX) self.x = maxX;
				if (self.y < minY) self.y = minY;
				if (self.y > maxY) self.y = maxY;
				return;
			}
			// Randomly (1 in 8 chance per frame) pick a new fungi to seek, or keep current
			if (!self.target || self.target.eaten || Math.random() < 0.125) {
				// Find nearest fungi
				var minDist = 999999,
					closest = null;
				for (var i = 0; i < fungis.length; i++) {
					var f = fungis[i];
					if (f.eaten) continue;
					var dx = f.x - self.x,
						dy = f.y - self.y;
					var dist = dx * dx + dy * dy;
					if (dist < minDist) {
						minDist = dist;
						closest = f;
					}
				}
				self.target = closest;
			}
			// Move toward fungi if any
			if (self.target && !self.target.eaten) {
				var dx = self.target.x - self.x,
					dy = self.target.y - self.y;
				var dist = Math.sqrt(dx * dx + dy * dy);
				if (dist > 1) {
					self.x += dx / dist * self.speed;
					self.y += dy / dist * self.speed;
				}
				// Eat fungi if close enough
				if (dist < 60 && !self.target.eaten) {
					// Play chomp sound when pollinator eats fungi
					var chompSnd = LK.getSound('Chomp');
					if (chompSnd && typeof chompSnd.play === "function") chompSnd.play();
					// Track how many times this fungi has been eaten by pollinators
					if (typeof self.target._pollinatorEatCount === "undefined") {
						self.target._pollinatorEatCount = 0;
					}
					self.target._pollinatorEatCount++;
					// If eaten 3 times, do nothing (fungi does not disappear anymore)
					if (self.target._pollinatorEatCount >= 3) {
						// Fungi no longer disappears after being eaten 3 times
						// Optionally, you could add a visual effect or reset the counter, but do nothing here
					}
					// Reset starve timer
					self._starveTimer = 3000 + Math.floor(Math.random() * 1200);
					// After eating, return to normal pollinator state
					self.state = "seek";
					self.target = null;
					// Set flag so next pollination is a shroom
					self._nextPollinationIsShroom = true;
					self._didShroomPollination = false;
					// Animate pollinator "eating"
					tween(self, {
						scaleX: 1.2,
						scaleY: 1.2
					}, {
						duration: 120,
						easing: tween.easeOut,
						onFinish: function onFinish() {
							tween(self, {
								scaleX: 1,
								scaleY: 1
							}, {
								duration: 120,
								easing: tween.easeIn
							});
						}
					});
					return;
				}
			} else {
				// If no fungi, wander randomly
				if (!self._wanderTimer || self._wanderTimer <= 0) {
					self._wanderAngle = Math.random() * Math.PI * 2;
					self._wanderTimer = 60 + Math.floor(Math.random() * 60);
				}
				if (typeof self._wanderAngle === "number") {
					self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
					self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
					self._wanderTimer--;
				}
			}
			// Clamp to map area
			var minX = 124 + 60;
			var maxX = 124 + 1800 - 60;
			var minY = paletteY + 320 + 60;
			var maxY = paletteY + 320 + 2000 - 60;
			if (self.x < minX) self.x = minX;
			if (self.x > maxX) self.x = maxX;
			if (self.y < minY) self.y = minY;
			if (self.y > maxY) self.y = maxY;
			return;
		}
		// --- POLLINATOR STARVATION: decrement timer unless hibernating or in autumn, winter, or summer ---
		var isAutumn = !!window.autumnState;
		var isWinter = !!window.winterState;
		var isSummer = !!window.summerState;
		if (!(typeof pollinatorsHibernating !== "undefined" && pollinatorsHibernating) && !isAutumn && !isWinter && !isSummer) {
			// Only decrement if not hibernating and not in autumn, winter, or summer
			self._starveTimer--;
			if (self._starveTimer <= 0 && !self.eaten) {
				// Die of starvation!
				self.eaten = true;
				tween(self, {
					scaleX: 0,
					scaleY: 0,
					alpha: 0
				}, {
					duration: 200,
					easing: tween.easeIn,
					onFinish: function onFinish() {
						self.destroy();
					}
				});
				return;
			}
		}
		// --- POLLINATOR HUNGRY STATE: If timer is low, become hungry and seek fungi ---
		if (self.state !== "hungry" && self._starveTimer < 900) {
			self.state = "hungry";
			self.target = null;
		}
		// --- If pollinator eats fungi, reset timer ---
		self._tryEatFungi = function () {
			// Find nearest fungi
			var minDist = 999999,
				closest = null;
			for (var i = 0; i < fungis.length; i++) {
				var f = fungis[i];
				if (f.eaten) continue;
				var dx = f.x - self.x,
					dy = f.y - self.y;
				var dist = dx * dx + dy * dy;
				if (dist < minDist) {
					minDist = dist;
					closest = f;
				}
			}
			if (closest) {
				self.target = closest;
				var dx = closest.x - self.x,
					dy = closest.y - self.y;
				var dist = Math.sqrt(dx * dx + dy * dy);
				if (dist > 1) {
					self.x += dx / dist * self.speed;
					self.y += dy / dist * self.speed;
				}
				// Eat fungi if close enough
				if (dist < 60 && !closest.eaten) {
					if (typeof closest.die === "function") closest.die();
					// Reset starve timer
					self._starveTimer = 3000 + Math.floor(Math.random() * 1200);
					// After eating, return to normal pollinator state
					self.state = "seek";
					self.target = null;
					// Animate pollinator "eating"
					tween(self, {
						scaleX: 1.2,
						scaleY: 1.2
					}, {
						duration: 120,
						easing: tween.easeOut,
						onFinish: function onFinish() {
							tween(self, {
								scaleX: 1,
								scaleY: 1
							}, {
								duration: 120,
								easing: tween.easeIn
							});
						}
					});
					return true;
				}
			}
			return false;
		};
		// --- POLLINATOR ACTIVE/NONACTIVE BEHAVIOR ---
		// If more than 5 pollinators, only 3 are 'active' and make sound, others are 'nonactive'
		if (typeof pollinators !== "undefined" && pollinators.length > 5) {
			// Assign active/nonactive roles once per frame for all pollinators
			if (typeof window._activePollinatorIds === "undefined") window._activePollinatorIds = [];
			// Only recalculate once per frame
			if (typeof window._activePollinatorFrame !== "number" || window._activePollinatorFrame !== LK.ticks) {
				// Pick 3 unique random pollinators to be active
				var ids = [];
				var pool = [];
				for (var i = 0; i < pollinators.length; i++) {
					if (!pollinators[i].eaten) pool.push(i);
				}
				// Shuffle pool
				for (var i = pool.length - 1; i > 0; i--) {
					var j = Math.floor(Math.random() * (i + 1));
					var tmp = pool[i];
					pool[i] = pool[j];
					pool[j] = tmp;
				}
				ids = pool.slice(0, 3);
				window._activePollinatorIds = ids;
				window._activePollinatorFrame = LK.ticks;
			}
			// Set self.activeBehavior based on selection
			var myIdx = -1;
			for (var i = 0; i < pollinators.length; i++) {
				if (pollinators[i] === self) {
					myIdx = i;
					break;
				}
			}
			self.behavior = window._activePollinatorIds.indexOf(myIdx) !== -1 ? "active" : "nonactive";
		} else {
			// If 5 or fewer, all are active
			self.behavior = "active";
		}
		// --- POLLINATOR NOISE: Play sound at random intervals, only if active ---
		// Nonactive pollinators are incapable of making sound unless population is reduced to 3 or fewer
		if (typeof self._nextNoiseTimer === "undefined") {
			// Set initial timer to random 1-4 seconds (60-240 frames)
			self._nextNoiseTimer = 60 + Math.floor(Math.random() * 180);
		}
		if (self._nextNoiseTimer > 0) {
			self._nextNoiseTimer--;
		} else {
			var canMakeSound = false;
			if (typeof pollinators !== "undefined" && pollinators.length <= 3) {
				// All pollinators can make sound if population is 3 or fewer
				canMakeSound = true;
			} else if (self.behavior === "active") {
				// Only active pollinators can make sound if more than 3
				canMakeSound = true;
			}
			if (canMakeSound && !(typeof pollinatorsHibernating !== "undefined" && pollinatorsHibernating)) {
				// Play the 'Bug' sound
				var snd = LK.getSound('Bug');
				if (snd && typeof snd.play === "function") snd.play();
			}
			// Reset timer to next random interval (1-4 seconds)
			self._nextNoiseTimer = 60 + Math.floor(Math.random() * 180);
		}
		// --- HIBERNATION: If background is white, pollinators do nothing, don't move, don't die, don't act ---
		if (typeof pollinatorsHibernating !== "undefined" && pollinatorsHibernating) {
			// Do not decrement lifetime, do not move, do not die, do not lay eggs, do not plant seeds
			return;
		}
		// If currently laying an egg, wait for egg to hatch before continuing
		if (self._layingEgg && self._eggObj) {
			// If it's summer or winter, eggs will not hatch, so pollinator should move away and continue pollinating
			var isSummer = !!window.summerState;
			var isWinter = !!window.winterState;
			if (isSummer || isWinter) {
				// Move away from the egg and resume pollinating
				if (self._eggObj) {
					// Move pollinator a bit away from the egg (random direction)
					var angle = Math.random() * Math.PI * 2;
					self.x += Math.cos(angle) * 80;
					self.y += Math.sin(angle) * 80;
					// Clamp to map area
					var minX = 124 + 60;
					var maxX = 124 + 1800 - 60;
					var minY = paletteY + 320 + 60;
					var maxY = paletteY + 320 + 2000 - 60;
					if (self.x < minX) self.x = minX;
					if (self.x > maxX) self.x = maxX;
					if (self.y < minY) self.y = minY;
					if (self.y > maxY) self.y = maxY;
				}
				self._eggObj = null;
				self._layingEgg = false;
				self._pollinations = 0; // Reset counter
				// Resume pollinating
				self.state = "seek";
				self.target = null;
				// Continue with rest of update
			} else {
				// Wait for egg to hatch, then continue pollinating
				if (self._eggObj.hatched) {
					// Spawn a new pollinator at egg position
					var newPoll = new Pollinator();
					newPoll.x = self._eggObj.x;
					newPoll.y = self._eggObj.y;
					newPoll.scaleX = 1;
					newPoll.scaleY = 1;
					newPoll.alpha = 1;
					if (self.parent) self.parent.addChild(newPoll);
					if (typeof pollinators !== "undefined") pollinators.push(newPoll);
					// Remove egg from global eggs array
					var idx = eggs.indexOf(self._eggObj);
					if (idx !== -1) eggs.splice(idx, 1);
					self._eggObj.destroy();
					self._eggObj = null;
					self._layingEgg = false;
					self._pollinations = 0; // Reset counter
				} else {
					// Wait for egg to hatch, do nothing else
					return;
				}
			}
		}
		// SEEK: Find nearest plant and move to it, but run from carnivores if close
		if (self.state === "seek") {
			// Check for nearest carnivore
			var nearestCarn = null;
			var minCarnDist = 999999;
			for (var ci = 0; ci < carnivores.length; ci++) {
				var carn = carnivores[ci];
				if (carn.eaten) continue;
				var cdx = carn.x - self.x;
				var cdy = carn.y - self.y;
				var cdist = cdx * cdx + cdy * cdy;
				if (cdist < minCarnDist) {
					minCarnDist = cdist;
					nearestCarn = carn;
				}
			}
			var carnivoreTooClose = false;
			var carnDist = 0;
			var runAwayDX = 0,
				runAwayDY = 0;
			if (nearestCarn) {
				carnDist = Math.sqrt((nearestCarn.x - self.x) * (nearestCarn.x - self.x) + (nearestCarn.y - self.y) * (nearestCarn.y - self.y));
				if (carnDist < 220) {
					// Run if carnivore is within 220px
					carnivoreTooClose = true;
					runAwayDX = self.x - nearestCarn.x;
					runAwayDY = self.y - nearestCarn.y;
				}
			}
			if (carnivoreTooClose && carnDist > 1) {
				// Run away from carnivore (burst speed)
				self.x += runAwayDX / carnDist * (self.speed * 2.2);
				self.y += runAwayDY / carnDist * (self.speed * 2.2);
			} else {
				// Find nearest plant
				if (!self.target || self.target.eaten) {
					var minDist = 999999,
						closest = null;
					for (var i = 0; i < plants.length; i++) {
						var p = plants[i];
						if (p.eaten) continue;
						// Ignore brown plants in summer
						if (window.summerState && p._isBrown) continue;
						var dx = p.x - self.x,
							dy = p.y - self.y;
						var dist = dx * dx + dy * dy;
						if (dist < minDist) {
							minDist = dist;
							closest = p;
						}
					}
					self.target = closest;
				}
				// Move toward target plant
				if (self.target && !self.target.eaten) {
					var dx = self.target.x - self.x;
					var dy = self.target.y - self.y;
					var dist = Math.sqrt(dx * dx + dy * dy);
					if (dist > 1) {
						self.x += dx / dist * self.speed;
						self.y += dy / dist * self.speed;
					}
					// Check for touching plant (within 60px)
					var isTouching = dist < 60;
					if (!self.lastWasTouchingPlant && isTouching) {
						// If plant is brown, skip and immediately seek a new healthy plant
						if (self.target && self.target._isBrown) {
							// Find next healthy plant (not brown, not eaten)
							var minDist2 = 999999,
								closest2 = null;
							for (var j = 0; j < plants.length; j++) {
								var p2 = plants[j];
								if (p2.eaten) continue;
								if (window.summerState && p2._isBrown) continue;
								var dx2 = p2.x - self.x,
									dy2 = p2.y - self.y;
								var dist2 = dx2 * dx2 + dy2 * dy2;
								if (dist2 < minDist2) {
									minDist2 = dist2;
									closest2 = p2;
								}
							}
							self.target = closest2;
							// Do not pollinate, just move on
							self.lastWasTouchingPlant = isTouching;
							return;
						}
						// Just touched plant
						// --- Pollinate a shroom instead of a plant if flag is set ---
						// (Removed: pollinators no longer spawn fungi or delete shrooms)
						if (self._nextPollinationIsShroom && !self._didShroomPollination) {
							self._didShroomPollination = true;
							self._nextPollinationIsShroom = false;
							// After pollinating a shroom, next pollination is normal
							self.state = "scatter";
							self._scatterTimer = 60 + Math.floor(Math.random() * 60); // 1-2 seconds
							self._scatterAngle = Math.random() * Math.PI * 2;
							self.lastWasTouchingPlant = isTouching;
							return;
						}
						self._pollinations = (self._pollinations || 0) + 1;
						// If pollinated 3 times, lay an egg and continue pollinating (do not wait for egg to hatch)
						if (self._pollinations >= 3 && !self._layingEgg) {
							// In autumn, pollinators do NOT lay eggs, just pollinate and continue
							if (window.autumnState) {
								self._pollinations = 0; // Reset pollination counter in autumn
								self.state = "scatter";
								self._scatterTimer = 60 + Math.floor(Math.random() * 60); // 1-2 seconds
								self._scatterAngle = Math.random() * Math.PI * 2;
								self.lastWasTouchingPlant = isTouching;
								return;
							}
							// --- POLLINATOR POPULATION CONTROL: Only lay egg if < 10 pollinators ---
							// --- FERN POPULATION CONTROL: Only lay egg if < 20 ferns (plants) ---
							if (typeof pollinators !== "undefined" && pollinators.length >= 10 || typeof plants !== "undefined" && plants.length >= 20) {
								// Do not lay egg, just reset pollination counter and scatter
								self._pollinations = 0;
								self.state = "scatter";
								self._scatterTimer = 60 + Math.floor(Math.random() * 60);
								self._scatterAngle = Math.random() * Math.PI * 2;
								self.lastWasTouchingPlant = isTouching;
								return;
							}
							// Lay a pollinator egg at current position
							var egg = new Egg();
							egg.x = self.x;
							egg.y = self.y;
							egg.scaleX = 0.5;
							egg.scaleY = 0.5;
							egg.alpha = 1;
							egg._isPollinatorEgg = true;
							egg._pollinatorHatch = true;
							if (self.parent) self.parent.addChild(egg);
							if (typeof eggs !== "undefined") eggs.push(egg);
							// Reset pollination counter and continue pollinating
							self._pollinations = 0;
							// Set pollinator to hungry state after laying an egg
							self.state = "hungry";
							self.target = null;
							self.lastWasTouchingPlant = isTouching;
							return;
						}
						self.state = "scatter";
						self._scatterTimer = 60 + Math.floor(Math.random() * 60); // 1-2 seconds
						self._scatterAngle = Math.random() * Math.PI * 2;
					}
					self.lastWasTouchingPlant = isTouching;
				} else {
					// No plant to go to, wander randomly
					if (!self._wanderTimer || self._wanderTimer <= 0) {
						self._wanderAngle = Math.random() * Math.PI * 2;
						self._wanderTimer = 60 + Math.floor(Math.random() * 60);
					}
					if (typeof self._wanderAngle === "number") {
						self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
						self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
						self._wanderTimer--;
					}
				}
			}
		}
		// SCATTER: Move in a random direction for a short time
		else if (self.state === "scatter") {
			self.x += Math.cos(self._scatterAngle) * self.speed * 2;
			self.y += Math.sin(self._scatterAngle) * self.speed * 2;
			self._scatterTimer--;
			if (self._scatterTimer <= 0) {
				self.state = "planting";
				self._plantSeedTimer = 30 + Math.floor(Math.random() * 30); // short pause before planting
			}
		}
		// PLANTING: Pause, then plant a seed
		else if (self.state === "planting") {
			self._plantSeedTimer--;
			if (self._plantSeedTimer <= 0 && self._hasSeed) {
				// Place a seed at current position
				var seed = new Seed();
				seed.x = self.x;
				seed.y = self.y;
				seed.scaleX = 0.4;
				seed.scaleY = 0.4;
				seed.alpha = 1;
				seeds.push(seed);
				if (self.parent) self.parent.addChild(seed);
				// Play plop sound when pollinator places a seed
				var plopSnd = LK.getSound('Plop');
				if (plopSnd && typeof plopSnd.play === "function") plopSnd.play();
				self._hasSeed = false;
				// After planting, look for another plant
				self.state = "seek";
				self.target = null;
				self._hasSeed = true;
			}
		}
		// Keep inside map bounds
		var minX = 124 + 60;
		var maxX = 124 + 1800 - 60;
		var minY = paletteY + 320 + 60;
		var maxY = paletteY + 320 + 2000 - 60;
		if (self.x < minX) self.x = minX;
		if (self.x > maxX) self.x = maxX;
		if (self.y < minY) self.y = minY;
		if (self.y > maxY) self.y = maxY;
	};
	self.die = function () {
		if (self.eaten) return;
		self.eaten = true;
		tween(self, {
			scaleX: 0,
			scaleY: 0,
			alpha: 0
		}, {
			duration: 200,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				self.destroy();
			}
		});
	};
	return self;
});
// Seed class
var Seed = Container.expand(function () {
	var self = Container.call(this);
	// Use dedicated brown seed asset
	var seedAsset = self.attachAsset('seed', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.4,
		scaleY: 0.4
	});
	self.growing = false;
	self.eaten = false;
	self._growTimer = 600; // 10 seconds at 60fps
	self.update = function () {
		if (self.eaten) return;
		if (!self.growing) {
			self._growTimer--;
			// --- FERN POPULATION CONTROL: If 20 or more ferns, seed always fails to germinate ---
			if (typeof plants !== "undefined" && plants.length >= 20) {
				// 100% fail to germinate
				self.eaten = true;
				tween(self, {
					scaleX: 0,
					scaleY: 0,
					alpha: 0
				}, {
					duration: 200,
					easing: tween.easeIn,
					onFinish: function onFinish() {
						self.destroy();
					}
				});
				return;
			}
			if (self._growTimer <= 0) {
				// --- 30% chance for seed to not germinate and disappear ---
				if (Math.random() < 0.3) {
					self.eaten = true;
					tween(self, {
						scaleX: 0,
						scaleY: 0,
						alpha: 0
					}, {
						duration: 200,
						easing: tween.easeIn,
						onFinish: function onFinish() {
							self.destroy();
						}
					});
					return;
				}
				// --- Summer or Autumn state: chance for seed to fail germination and disappear ---
				if (window.summerState && Math.random() < 0.4) {
					// 40% chance to fail in summer, just disappear
					self.eaten = true;
					tween(self, {
						scaleX: 0,
						scaleY: 0,
						alpha: 0
					}, {
						duration: 200,
						easing: tween.easeIn,
						onFinish: function onFinish() {
							self.destroy();
						}
					});
					return;
				} else if (window.autumnState && Math.random() < 0.55) {
					// 55% chance to fail in autumn, just disappear
					self.eaten = true;
					tween(self, {
						scaleX: 0,
						scaleY: 0,
						alpha: 0
					}, {
						duration: 200,
						easing: tween.easeIn,
						onFinish: function onFinish() {
							self.destroy();
						}
					});
					return;
				}
				self.growing = true;
				// Animate seed growing into plant
				tween(self, {
					scaleX: 1,
					scaleY: 1,
					alpha: 0.7
				}, {
					duration: 300,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						// Play grow sound when seed germinates
						var growSnd = LK.getSound('Grow');
						if (growSnd && typeof growSnd.play === "function") growSnd.play();
						// Replace seed with a new plant at same position
						var newPlant = new Plant();
						newPlant.x = self.x;
						newPlant.y = self.y;
						newPlant.scaleX = 1;
						newPlant.scaleY = 1;
						newPlant.alpha = 1;
						// Set the plant's _bornCycle to the current cycleCount so its cycle restarts
						if (typeof cycleCount !== "undefined") {
							newPlant._bornCycle = cycleCount;
						}
						plants.push(newPlant);
						if (self.parent) self.parent.addChild(newPlant);
						self.eaten = true;
						self.destroy();
					}
				});
			}
		}
	};
	// If something eats the seed (future-proof)
	self.die = function () {
		if (self.eaten) return;
		self.eaten = true;
		tween(self, {
			scaleX: 0,
			scaleY: 0,
			alpha: 0
		}, {
			duration: 200,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				self.destroy();
			}
		});
	};
	return self;
});
// Spore class (projectile shot by fungi)
var Spore = Container.expand(function () {
	var self = Container.call(this);
	// Use a simple green circle for the spore
	var sporeAsset = self.attachAsset('plant', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.25,
		scaleY: 0.25
	});
	self.target = null;
	self.speed = 2.5;
	self._alive = true;
	self.update = function () {
		if (!self.target || self.target.eaten || !self._alive) {
			self.destroy();
			self._alive = false;
			return;
		}
		var dx = self.target.x - self.x;
		var dy = self.target.y - self.y;
		var dist = Math.sqrt(dx * dx + dy * dy);
		if (dist > 1) {
			self.x += dx / dist * self.speed;
			self.y += dy / dist * self.speed;
		}
		// Check collision with target herbivore
		if (!self._lastIntersecting && self.intersects(self.target)) {
			// "Hit" the herbivore: destroy spore, animate herbivore, but do not kill
			if (self.target && typeof self.target.sporeHit === "function") {
				self.target.sporeHit();
			}
			self.destroy();
			self._alive = false;
		}
		self._lastIntersecting = self.intersects(self.target);
	};
	return self;
});
// FungiSpore class for future extensibility (could add poison, etc)
// Modified: FungiSpore now takes a straight path (direction set at spawn)
var FungiSpore = Spore.expand(function () {
	var self = Spore.call(this);
	// Store initial direction at spawn
	self._vx = 0;
	self._vy = 0;
	// Set direction only once at spawn, toward target
	self.setDirection = function () {
		if (self.target) {
			var dx = self.target.x - self.x;
			var dy = self.target.y - self.y;
			var dist = Math.sqrt(dx * dx + dy * dy);
			if (dist > 0) {
				self._vx = dx / dist * self.speed;
				self._vy = dy / dist * self.speed;
			} else {
				self._vx = 0;
				self._vy = 0;
			}
		} else {
			self._vx = 0;
			self._vy = 0;
		}
	};
	// Call setDirection at spawn
	self.setDirection();
	// Override update to move in a straight line
	self.update = function () {
		if (!self.target || self.target.eaten || !self._alive) {
			self.destroy();
			self._alive = false;
			return;
		}
		self.x += self._vx;
		self.y += self._vy;
		// Check collision with target herbivore
		if (!self._lastIntersecting && self.intersects(self.target)) {
			if (self.target && typeof self.target.sporeHit === "function") {
				self.target.sporeHit();
			}
			self.destroy();
			self._alive = false;
		}
		self._lastIntersecting = self.intersects(self.target);
	};
	return self;
});
// Worm class (moves only in summer and winter, buried in autumn and spring)
var Worm = Container.expand(function () {
	var self = Container.call(this);
	// Determine if worm is buried at spawn
	self.buried = false;
	var isAutumn = !!window.autumnState;
	var isSpring = !!window.springState;
	if (isAutumn || isSpring) {
		self.buried = true;
	}
	// Use the worm image asset for the worm, or buried asset if buried
	self._wormAsset = null;
	if (self.buried) {
		self._wormAsset = self.attachAsset('Buried_worm', {
			anchorX: 0.5,
			anchorY: 0.5
		});
	} else {
		self._wormAsset = self.attachAsset('Worm', {
			anchorX: 0.5,
			anchorY: 0.5
		});
	}
	// Movement speed for worms
	self.speed = 1 + Math.random() * 0.5;
	// Track wander direction and timer
	self._wanderAngle = Math.random() * Math.PI * 2;
	self._wanderTimer = 60 + Math.floor(Math.random() * 60);
	// Track brown plants eaten in summer
	self._brownPlantsEaten = 0;
	// Track last brown plant intersected (for collision detection)
	self._lastIntersectingBrownPlant = null;
	self.update = function () {
		var isSummer = !!window.summerState;
		var isWinter = !!window.winterState;
		var isAutumn = !!window.autumnState;
		var isSpring = !!window.springState;
		// If currently buried but season changed to summer/winter, unbury and swap asset
		if (self.buried && (isSummer || isWinter)) {
			self.buried = false;
			if (self._wormAsset) {
				self.removeChild(self._wormAsset);
			}
			self._wormAsset = self.attachAsset('Worm', {
				anchorX: 0.5,
				anchorY: 0.5
			});
		}
		// If currently not buried but season changed to autumn/spring, bury and swap asset
		if (!self.buried && (isAutumn || isSpring)) {
			self.buried = true;
			if (self._wormAsset) {
				self.removeChild(self._wormAsset);
			}
			self._wormAsset = self.attachAsset('Buried_worm', {
				anchorX: 0.5,
				anchorY: 0.5
			});
		}
		// --- Worm AI: In summer, seek and eat brown plants, then bury after 3 eaten ---
		if (isSummer && !self.buried) {
			// Find nearest brown plant
			var minDist = 999999,
				closest = null;
			for (var i = 0; i < plants.length; i++) {
				var p = plants[i];
				if (p.eaten) continue;
				if (!p._isBrown) continue;
				var dx = p.x - self.x,
					dy = p.y - self.y;
				var dist = dx * dx + dy * dy;
				if (dist < minDist) {
					minDist = dist;
					closest = p;
				}
			}
			if (closest) {
				// Move toward brown plant
				var dx = closest.x - self.x;
				var dy = closest.y - self.y;
				var dist = Math.sqrt(dx * dx + dy * dy);
				if (dist > 1) {
					self.x += dx / dist * self.speed;
					self.y += dy / dist * self.speed;
				}
				// Eat brown plant if close enough and not already eaten
				var isIntersecting = self.intersects(closest);
				if ((!self._lastIntersectingBrownPlant || self._lastIntersectingBrownPlant !== closest) && isIntersecting && !closest.eaten) {
					if (typeof closest.die === "function") {
						closest.die();
					}
					self._brownPlantsEaten = (self._brownPlantsEaten || 0) + 1;
					// After eating 3 brown plants, bury and swap asset
					if (self._brownPlantsEaten >= 3) {
						self.buried = true;
						if (self._wormAsset) {
							self.removeChild(self._wormAsset);
						}
						self._wormAsset = self.attachAsset('Buried_worm', {
							anchorX: 0.5,
							anchorY: 0.5
						});
						self._brownPlantsEaten = 0;
						// Immediately stop moving after burying
						self._wanderTimer = 0;
						self._wanderAngle = 0;
					}
				}
				self._lastIntersectingBrownPlant = isIntersecting ? closest : null;
			} else {
				// No brown plant: wander randomly
				if (!self._wanderTimer || self._wanderTimer <= 0) {
					self._wanderAngle = Math.random() * Math.PI * 2;
					self._wanderTimer = 60 + Math.floor(Math.random() * 60);
				}
				if (typeof self._wanderAngle === "number") {
					self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
					self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
					self._wanderTimer--;
					// Keep inside map bounds (strictly)
					var minX = 124 + 60;
					var maxX = 124 + 1800 - 60;
					var minY = paletteY + 320 + 60;
					var maxY = paletteY + 320 + 2000 - 60;
					if (self.x < minX) self.x = minX;
					if (self.x > maxX) self.x = maxX;
					if (self.y < minY) self.y = minY;
					if (self.y > maxY) self.y = maxY;
				}
				self._lastIntersectingBrownPlant = null;
			}
		} else if (isWinter && !self.buried) {
			// Wander randomly in winter
			if (!self._wanderTimer || self._wanderTimer <= 0) {
				self._wanderAngle = Math.random() * Math.PI * 2;
				self._wanderTimer = 60 + Math.floor(Math.random() * 60);
			}
			if (typeof self._wanderAngle === "number") {
				self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
				self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
				self._wanderTimer--;
				// Keep inside map bounds (strictly)
				var minX = 124 + 60;
				var maxX = 124 + 1800 - 60;
				var minY = paletteY + 320 + 60;
				var maxY = paletteY + 320 + 2000 - 60;
				if (self.x < minX) self.x = minX;
				if (self.x > maxX) self.x = maxX;
				if (self.y < minY) self.y = minY;
				if (self.y > maxY) self.y = maxY;
			}
			// Reset brown plant eating state in winter
			self._brownPlantsEaten = 0;
			self._lastIntersectingBrownPlant = null;
		}
		// In autumn and spring, do nothing (no movement, buried)
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x2ecc40 //{7C} // Set to a green background
});
/**** 
* Game Code
****/ 
// Pollinator sound effects (buzz, chirp, etc)
// --- Pollinator Hibernation State ---
var pollinatorsHibernating = false;
// --- Year Counter ---
// Add a year counter above the cycle counter that increments after winter ends
var yearCount = 1;
var yearTxt = new Text2("Year: 1", {
	size: 80,
	fill: "#000"
});
yearTxt.anchor.set(0.5, 0);
// Place above the cycle counter
LK.gui.top.addChild(yearTxt);
yearTxt.x = 500;
yearTxt.y = 40;
// --- Cycle Counter ---
// Add a cycle counter at the bottom of the screen that increments every 50 seconds (3000 frames at 60fps)
var cycleCount = 0;
var cycleTxt = new Text2("Cycle: 0", {
	size: 80,
	fill: "#000"
});
cycleTxt.anchor.set(0.5, 0);
// Place at top left, but not in the top 100px reserved area
LK.gui.top.addChild(cycleTxt);
cycleTxt.x = 500;
cycleTxt.y = 120;
// --- Season Text at Bottom ---
// Helper to get current season as string
function getCurrentSeason() {
	if (window.summerState) return "Summer";
	if (window.winterState) return "Winter";
	if (window.springState) return "Spring";
	if (window.autumnState) return "Autumn";
	// Fallback: guess from background color
	if (game.backgroundColor === 0xffff00) return "Summer";
	if (game.backgroundColor === 0xffffff) return "Winter";
	if (game.backgroundColor === 0x8B5A2B) return "Autumn";
	return "Spring";
}
var seasonTxt = new Text2("Season: " + getCurrentSeason(), {
	size: 90,
	fill: "#000"
});
seasonTxt.anchor.set(0, 1);
LK.gui.bottom.addChild(seasonTxt);
seasonTxt.x = 40;
seasonTxt.y = 0;
// Helper to update season text
function updateSeasonText() {
	if (seasonTxt && typeof seasonTxt.setText === "function") {
		seasonTxt.setText("Season: " + getCurrentSeason());
		if (typeof seasonTxt.setStyle === "function") seasonTxt.setStyle({
			fill: "#000"
		});
	}
}
// --- Cycle Countdown Timer Text ---
var cycleDurationMs = 50000; // 50,000 ms = 50 seconds
var cycleTimeLeftMs = cycleDurationMs;
var cycleTimerTxt = new Text2("Next cycle: 50s", {
	size: 60,
	fill: "#000"
});
cycleTimerTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(cycleTimerTxt);
cycleTimerTxt.x = 500;
cycleTimerTxt.y = cycleTxt.y + 80; // Place under the cycle counter
// Timer to increment cycle every 50 seconds
var cycleInterval = null; // Will be started after first organism is placed
var cycleCountdownInterval = null; // For updating the countdown text
// Helper to set all on-screen text color to black
function updateTextColors(bgColor) {
	var textColor = "#000";
	if (cycleTxt && typeof cycleTxt.setStyle === "function") cycleTxt.setStyle({
		fill: textColor
	});
	if (cycleTimerTxt && typeof cycleTimerTxt.setStyle === "function") cycleTimerTxt.setStyle({
		fill: textColor
	});
	if (deleteBtnTxt && typeof deleteBtnTxt.setStyle === "function") deleteBtnTxt.setStyle({
		fill: textColor
	});
	if (skipCycleBtnTxt && typeof skipCycleBtnTxt.setStyle === "function") skipCycleBtnTxt.setStyle({
		fill: textColor
	});
	// Palette item labels
	for (var i = 0; i < paletteItems.length; i++) {
		for (var j = 0; j < paletteItems[i].children.length; j++) {
			var child = paletteItems[i].children[j];
			if (child instanceof Text2 && typeof child.setStyle === "function") {
				child.setStyle({
					fill: textColor
				});
			}
		}
	}
	// Palette scroll arrows
	if (window.paletteLeftBtn) {
		for (var i = 0; i < window.paletteLeftBtn.children.length; i++) {
			var child = window.paletteLeftBtn.children[i];
			if (child instanceof Text2 && typeof child.setStyle === "function") child.setStyle({
				fill: textColor
			});
		}
	}
	if (window.paletteRightBtn) {
		for (var i = 0; i < window.paletteRightBtn.children.length; i++) {
			var child = window.paletteRightBtn.children[i];
			if (child instanceof Text2 && typeof child.setStyle === "function") child.setStyle({
				fill: textColor
			});
		}
	}
}
function startCycleInterval() {
	if (cycleInterval !== null) return;
	cycleTimeLeftMs = cycleDurationMs;
	cycleTimerTxt.setText("Next cycle: " + Math.ceil(cycleTimeLeftMs / 1000) + "s");
	cycleInterval = LK.setInterval(function () {
		cycleCount++;
		cycleTxt.setText("Cycle: " + cycleCount);
		cycleTimeLeftMs = cycleDurationMs;
		cycleTimerTxt.setText("Next cycle: " + Math.ceil(cycleTimeLeftMs / 1000) + "s");
		// --- Streak Counter Logic ---
		// If skip was used this cycle, reset streak and clear flag
		if (streakSkipThisCycle) {
			resetStreak();
			streakSkipThisCycle = false;
		} else {
			// If at least one organism is alive, increment streak, else reset
			var anyAlive = plants.length > 0 || herbivores.length > 0 || carnivores.length > 0 || pollinators.length > 0 || fungis.length > 0 || parasites.length > 0 || worms.length > 0;
			if (anyAlive) {
				incrementStreak();
			} else {
				resetStreak();
			}
		}
		// Reset tired attempts for all carnivores at the start of each cycle
		for (var i = 0; i < carnivores.length; i++) {
			if (carnivores[i] && carnivores[i]._tiredAttempts) {
				carnivores[i]._tiredAttempts = {};
			}
		}
		// --- Extinction: If no plants, kill all herbivores, pollinators, and carnivores ---
		if (plants.length === 0) {
			// Herbivores
			for (var i = herbivores.length - 1; i >= 0; i--) {
				var h = herbivores[i];
				if (typeof h.die === "function") h.die();else if (typeof h.destroy === "function") h.destroy();
				herbivores.splice(i, 1);
			}
			// Pollinators
			for (var i = pollinators.length - 1; i >= 0; i--) {
				var p = pollinators[i];
				if (typeof p.die === "function") p.die();else if (typeof p.destroy === "function") p.destroy();
				pollinators.splice(i, 1);
			}
			// Carnivores
			for (var i = carnivores.length - 1; i >= 0; i--) {
				var c = carnivores[i];
				if (typeof c.die === "function") c.die();else if (typeof c.destroy === "function") c.destroy();
				carnivores.splice(i, 1);
			}
			// --- Make randomize button available on total extinction ---
			if (typeof randomizeBtn !== "undefined") {
				// Check if all organisms are dead (plants, herbivores, carnivores, pollinators, fungis, parasites, worms)
				var allGone = plants.length === 0 && herbivores.length === 0 && carnivores.length === 0 && pollinators.length === 0 && fungis.length === 0 && parasites.length === 0 && worms.length === 0;
				if (allGone) {
					randomizeBtn._disabled = false;
					randomizeBtnBox.color = 0x228B22;
					if (typeof randomizeBtnBox.setStyle === "function") {
						randomizeBtnBox.setStyle({
							fill: "#fff"
						});
					}
					randomizeBtnTxt.setText("Randomize");
				} else {
					// If any organisms are present, keep randomize button disabled
					randomizeBtn._disabled = true;
					randomizeBtnBox.color = 0xcc2222;
					if (typeof randomizeBtnBox.setStyle === "function") {
						randomizeBtnBox.setStyle({
							fill: "#fff"
						});
					}
					randomizeBtnTxt.setText("Randomized");
				}
			}
		}
		// Set background color every 3 cycles: green, yellow, brown, white, repeat (spring, summer, autumn, winter)
		var mod = cycleCount % 12;
		if (mod === 0) {
			// SPRING
			game.setBackgroundColor(0x2ecc40); // green
			updateTextColors(0x2ecc40);
			pollinatorsHibernating = false;
			window.summerState = false;
			window.springState = true;
			window.winterState = false;
			window.autumnState = false;
			// Play mellow music
			LK.playMusic('mellow');
			// --- YEAR COUNTER: Increment year after winter ends (when entering spring) ---
			if (cycleCount > 0) {
				yearCount++;
				if (yearTxt && typeof yearTxt.setText === "function") {
					yearTxt.setText("Year: " + yearCount);
				}
			}
			// Restore plant color to normal (green) and allow dying
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] && plants[i].plantAsset && typeof plants[i].plantAsset.tint !== "undefined") {
					plants[i].plantAsset.tint = 0xffffff;
				}
				plants[i]._canDie = true;
			}
			// --- SPRING: Hatch all parasite eggs (eggs with _isParasiteEgg and _parasiteHatch) ---
			for (var i = eggs.length - 1; i >= 0; i--) {
				var e = eggs[i];
				if (e && e._isParasiteEgg && e._parasiteHatch && !e.hatched) {
					// Instantly hatch the egg into a parasite
					e.hatched = true;
					// Animate egg hatching
					tween(e, {
						scaleX: 1.2,
						scaleY: 1.2,
						alpha: 0.5
					}, {
						duration: 200,
						easing: tween.easeOut,
						onFinish: function (egg) {
							return function () {
								var parasite = new Parasite();
								parasite.x = egg.x;
								parasite.y = egg.y;
								parasite.scaleX = 1;
								parasite.scaleY = 1;
								parasite.alpha = 1;
								if (egg.parent) egg.parent.addChild(parasite);
								if (typeof parasites !== "undefined") parasites.push(parasite);
								egg.destroy();
							};
						}(e)
					});
					eggs.splice(i, 1);
				}
			}
			// --- Resume herbivore movement after winter ends ---
			for (var i = 0; i < herbivores.length; i++) {
				if (herbivores[i] && typeof herbivores[i].speed === "number") {
					herbivores[i].speed = 1.2 + Math.random() * 1.0;
				}
			}
			// --- Resume carnivore hunting after winter ends --- (Ava)
			// Reset carnivore state to "hungry" so they resume hunting in spring
			for (var i = 0; i < carnivores.length; i++) {
				if (carnivores[i]) {
					carnivores[i].state = "hungry";
					carnivores[i]._tired = false;
					carnivores[i]._tiredTimer = 0;
					carnivores[i]._chaseTime = 0;
					carnivores[i].target = null;
				}
			}
			updateSeasonText();
		} else if (mod === 3) {
			// SUMMER
			game.setBackgroundColor(0xffff00); // yellow
			updateTextColors(0xffff00);
			pollinatorsHibernating = false;
			window.summerState = true;
			window.winterState = false;
			window.springState = false;
			window.autumnState = false;
			// Plants can die, but keep their color normal
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] && plants[i].plantAsset && typeof plants[i].plantAsset.tint !== "undefined") {
					plants[i].plantAsset.tint = 0xffffff;
				}
				plants[i]._canDie = true;
			}
			updateSeasonText();
		} else if (mod === 6) {
			// AUTUMN
			game.setBackgroundColor(0x8B5A2B); // brown
			updateTextColors(0x8B5A2B);
			pollinatorsHibernating = false;
			window.summerState = false;
			window.springState = false;
			window.winterState = false;
			window.autumnState = true;
			// Make all plants brown and allow dying
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] && plants[i].plantAsset && typeof plants[i].plantAsset.tint !== "undefined") {
					plants[i].plantAsset.tint = 0x996633; // brown
				}
				plants[i]._canDie = true;
				plants[i]._isBrown = true;
			}
			updateSeasonText();
		} else if (mod === 9) {
			// WINTER
			game.setBackgroundColor(0xffffff); // white
			updateTextColors(0xffffff);
			pollinatorsHibernating = true;
			window.summerState = false;
			window.springState = false;
			window.winterState = true;
			window.autumnState = false;
			// --- WINTER: Parasites die and lay eggs before death ---
			for (var i = parasites.length - 1; i >= 0; i--) {
				var parasite = parasites[i];
				if (parasite && !parasite.eaten) {
					// Lay a parasite egg at current position before dying
					var egg = new Egg();
					egg.x = parasite.x;
					egg.y = parasite.y;
					egg.scaleX = 0.5;
					egg.scaleY = 0.5;
					egg.alpha = 1;
					egg._isParasiteEgg = true;
					egg._parasiteHatch = true;
					if (parasite.parent) parasite.parent.addChild(egg);
					if (typeof eggs !== "undefined") eggs.push(egg);
					// Animate parasite dying and remove from array
					tween(parasite, {
						scaleX: 0,
						scaleY: 0,
						alpha: 0
					}, {
						duration: 200,
						easing: tween.easeIn,
						onFinish: function (p) {
							return function () {
								if (typeof parasites !== "undefined") {
									var idx = parasites.indexOf(p);
									if (idx !== -1) parasites.splice(idx, 1);
								}
								p.destroy();
							};
						}(parasite)
					});
				}
			}
			// Kill all brown plants when winter starts
			for (var i = plants.length - 1; i >= 0; i--) {
				var p = plants[i];
				// Only kill brown plants; healthy plants do not die in winter
				if (p && p._isBrown && !p.eaten && typeof p.die === "function") {
					p.die();
				}
			}
			// Make all plants blue and prevent dying
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] && plants[i].plantAsset && typeof plants[i].plantAsset.tint !== "undefined") {
					plants[i].plantAsset.tint = 0x3399ff;
				}
				plants[i]._canDie = false;
			}
			// Cull a random portion of eggs during winter to reduce lag
			if (eggs && eggs.length > 0) {
				// Remove up to 40% of eggs at random, but always leave at least 3 eggs if possible
				var eggsToCull = Math.floor(eggs.length * 0.4);
				var minEggsLeft = 3;
				if (eggs.length - eggsToCull < minEggsLeft) {
					eggsToCull = Math.max(0, eggs.length - minEggsLeft);
				}
				for (var i = 0; i < eggsToCull; i++) {
					// Pick a random egg index
					var idx = Math.floor(Math.random() * eggs.length);
					var e = eggs[idx];
					if (e && typeof e.destroy === "function") {
						e.destroy();
					}
					eggs.splice(idx, 1);
				}
			}
			updateSeasonText();
		}
	}, cycleDurationMs);
	// Start countdown updater (every 100ms for smoothness)
	if (cycleCountdownInterval === null) {
		cycleCountdownInterval = LK.setInterval(function () {
			if (cycleTimeLeftMs > 0) {
				cycleTimeLeftMs -= 100;
				if (cycleTimeLeftMs < 0) cycleTimeLeftMs = 0;
				cycleTimerTxt.setText("Next cycle: " + Math.ceil(cycleTimeLeftMs / 1000) + "s");
			}
		}, 100);
	}
}
// --- End of Game Code ---;;
// --- Asset Initialization ---
// new carnivore egg texture
var plants = [];
var herbivores = [];
// --- Herbivore Hunger Queue: Only 2 can be hungry at a time ---
var herbivoreHungerQueue = []; // Array of herbivores waiting to be hungry
var carnivores = [];
var seeds = [];
var eggs = []; // Track all eggs globally
var pollinators = [];
var fungis = []; // Track all fungi globally
var parasites = []; // Track all parasites globally
var fungiSpores = []; // Track all spores shot by fungi
// --- Worms spawned at game start ---
// If you want worms to be present at game start, add them here and set them buried until the next season
var worms = [];
// Worms are not spawned at the top of the screen at game start
// --- Palette UI ---
var paletteY = 180; // y position for palette
var paletteSpacing = 260;
var paletteItems = [];
// --- Delete Mode Button ---
var deleteMode = false;
var deleteBtn = new Container();
var deleteBtnBox = deleteBtn.attachAsset('box', {
	anchorX: 0.5,
	anchorY: 0.5,
	width: 220,
	height: 100,
	color: 0xcc3333,
	shape: 'box'
});
var deleteBtnTxt = new Text2("Delete: OFF", {
	size: 54,
	fill: "#000"
});
deleteBtnTxt.anchor.set(0.5, 0.5);
deleteBtn.addChild(deleteBtnTxt);
// Place delete button under the cycle counter and timer
deleteBtn.x = 500;
deleteBtn.y = cycleTimerTxt.y + 140; // Move further down (was 90px, now 140px below the timer text)
deleteBtn.interactive = true;
deleteBtn.visible = true;
deleteBtn.down = function () {
	var clickSnd = LK.getSound('Click');
	if (clickSnd && typeof clickSnd.play === "function") clickSnd.play();
	deleteMode = !deleteMode;
	deleteBtnBox.color = deleteMode ? 0xff4444 : 0xcc3333;
	deleteBtnTxt.setText(deleteMode ? "Delete: ON" : "Delete: OFF");
};
LK.gui.top.addChild(deleteBtn);
// --- Skip Cycle Button --- 
var skipCycleBtn = new Container();
var skipCycleBtnBox = skipCycleBtn.attachAsset('box', {
	anchorX: 0.5,
	anchorY: 0.5,
	width: 220,
	height: 100,
	color: 0x3388cc,
	shape: 'box'
});
var skipCycleBtnTxt = new Text2("Skip Cycle", {
	size: 54,
	fill: "#000"
});
skipCycleBtnTxt.anchor.set(0.5, 0.5);
skipCycleBtn.addChild(skipCycleBtnTxt);
// Place skip button under the delete button
skipCycleBtn.x = 500;
skipCycleBtn.y = deleteBtn.y + 120;
skipCycleBtn.interactive = true;
skipCycleBtn.visible = true;
// --- Skip Cycle Cooldown State ---
var skipCycleCooldownActive = false;
var skipCycleCooldownTimeout = null;
// --- Skip Cycle Cooldown Counter Text ---
var skipCycleCountdownTxt = new Text2("", {
	size: 54,
	fill: "#fff"
});
skipCycleCountdownTxt.anchor.set(0, 0.5);
// Position to the right of the skip button (visually next to it)
skipCycleCountdownTxt.x = 130;
skipCycleCountdownTxt.y = 0;
skipCycleCountdownTxt.visible = false;
skipCycleBtn.addChild(skipCycleCountdownTxt);
var skipCycleCountdownInterval = null;
var skipCycleCountdownValue = 0;
// --- Extinction Button ---
var extinctionBtn = new Container();
var extinctionBtnBox = extinctionBtn.attachAsset('box', {
	anchorX: 0.5,
	anchorY: 0.5,
	width: 220,
	height: 100,
	color: 0x555555,
	shape: 'box'
});
var extinctionBtnTxt = new Text2("Extinction", {
	size: 54,
	fill: "#000"
});
extinctionBtnTxt.anchor.set(0.5, 0.5);
extinctionBtn.addChild(extinctionBtnTxt);
// Place extinction button under the skip cycle button
extinctionBtn.x = 500;
extinctionBtn.y = skipCycleBtn.y + 120;
extinctionBtn.interactive = true;
extinctionBtn.visible = true;
LK.gui.top.addChild(extinctionBtn);
// --- Achievements Button and Menu removed ---
// --- Randomize Button ---
var randomizeBtn = new Container();
var randomizeBtnBox = randomizeBtn.attachAsset('box', {
	anchorX: 0.5,
	anchorY: 0.5,
	width: 220,
	height: 100,
	color: 0x228B22,
	shape: 'box'
});
var randomizeBtnTxt = new Text2("Randomize", {
	size: 54,
	fill: "#000"
});
randomizeBtnTxt.anchor.set(0.5, 0.5);
randomizeBtn.addChild(randomizeBtnTxt);
// Place randomize button under the extinction button
randomizeBtn.x = 500;
randomizeBtn.y = extinctionBtn.y + 120;
randomizeBtn.interactive = true;
randomizeBtn.visible = true;
LK.gui.top.addChild(randomizeBtn);
// --- Personality Reveal Button ---
var personalityBtn = new Container();
var personalityBtnBox = personalityBtn.attachAsset('box', {
	anchorX: 0.5,
	anchorY: 0.5,
	width: 220,
	height: 100,
	color: 0x8e44ad,
	shape: 'box'
});
var personalityBtnTxt = new Text2("Personality", {
	size: 54,
	fill: "#000"
});
personalityBtnTxt.anchor.set(0.5, 0.5);
personalityBtn.addChild(personalityBtnTxt);
// Place personality button under the randomize button
personalityBtn.x = 500;
personalityBtn.y = randomizeBtn.y + 120;
personalityBtn.interactive = true;
personalityBtn.visible = true;
LK.gui.top.addChild(personalityBtn);
// --- Personality Reveal Text Above Each Organism ---
var personalityPopup = null;
var personalityTextNodes = []; // Track all personality text objects
// --- Streak Counter UI and Variables ---
// Streak: counts how many cycles at least one organism is alive, resets if all die or if you skip a cycle
var streakCount = 0;
var streakTxt = new Text2("Streak: 0", {
	size: 60,
	fill: "#000"
});
streakTxt.anchor.set(0.5, 0.5);
// Place streak counter under the personality button (y + 120)
streakTxt.x = personalityBtn.x;
streakTxt.y = personalityBtn.y + 120;
LK.gui.top.addChild(streakTxt);
// --- Score Counter UI and Variables ---
var scoreCount = 0;
var scoreTxt = new Text2("Score: 0", {
	size: 60,
	fill: "#000"
});
scoreTxt.anchor.set(0.5, 0.5);
// Place score counter under the streak counter
scoreTxt.x = streakTxt.x;
scoreTxt.y = streakTxt.y + 80;
LK.gui.top.addChild(scoreTxt);
// Helper to update score text
function updateScoreText() {
	if (scoreTxt && typeof scoreTxt.setText === "function") {
		scoreTxt.setText("Score: " + scoreCount);
		if (typeof scoreTxt.setStyle === "function") scoreTxt.setStyle({
			fill: "#000"
		});
	}
}
// --- Retract/Expand Streak and Score Counter with Top Buttons ---
// Patch updateTopButtonsRetracted to also move/hide streakTxt and scoreTxt
var _originalUpdateTopButtonsRetracted = updateTopButtonsRetracted;
updateTopButtonsRetracted = function updateTopButtonsRetracted() {
	if (topButtonsRetracted) {
		// Move streak counter offscreen and hide
		var offX = 2048 + 300;
		tween(streakTxt, {
			x: offX
		}, {
			duration: 200,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				streakTxt.visible = false;
			}
		});
		// Move score counter offscreen and hide
		tween(scoreTxt, {
			x: offX
		}, {
			duration: 200,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				scoreTxt.visible = false;
			}
		});
	} else {
		// Move streak counter back and show
		streakTxt.visible = true;
		tween(streakTxt, {
			x: 500
		}, {
			duration: 200,
			easing: tween.easeOut
		});
		// Move score counter back and show
		scoreTxt.visible = true;
		tween(scoreTxt, {
			x: 500
		}, {
			duration: 200,
			easing: tween.easeOut
		});
	}
	// Call original for other buttons
	if (typeof _originalUpdateTopButtonsRetracted === "function") {
		_originalUpdateTopButtonsRetracted();
	}
};
// Track if a skip happened this cycle (reset streak if so)
var streakSkipThisCycle = false;
// Helper to update streak text
function updateStreakText() {
	if (streakTxt && typeof streakTxt.setText === "function") {
		streakTxt.setText("Streak: " + streakCount);
		if (typeof streakTxt.setStyle === "function") streakTxt.setStyle({
			fill: "#000"
		});
	}
}
function resetStreak() {
	streakCount = 0;
	updateStreakText();
	// Reset score to 0 when streak is reset
	scoreCount = 0;
	updateScoreText();
	// Play the 'Lost' sound every time the streak is reset
	var lostSnd = LK.getSound('Lost');
	if (lostSnd && typeof lostSnd.play === "function") lostSnd.play();
	// Show "streak lost!" text in the middle of the screen in red for 5 seconds
	if (typeof window._streakLostTxt !== "undefined" && window._streakLostTxt && window._streakLostTxt.parent) {
		window._streakLostTxt.parent.removeChild(window._streakLostTxt);
		if (typeof window._streakLostTxt.destroy === "function") window._streakLostTxt.destroy();
		window._streakLostTxt = null;
	}
	var streakLostTxt = new Text2("streak lost!", {
		size: 160,
		fill: "#c00",
		font: "'GillSans-Bold',Impact,'Arial Black',Tahoma"
	});
	streakLostTxt.anchor.set(0.5, 0.5);
	streakLostTxt.x = 2048 / 2;
	streakLostTxt.y = 2732 / 2;
	game.addChild(streakLostTxt);
	window._streakLostTxt = streakLostTxt;
	if (typeof window._streakLostTimeout !== "undefined" && window._streakLostTimeout) {
		LK.clearTimeout(window._streakLostTimeout);
	}
	window._streakLostTimeout = LK.setTimeout(function () {
		if (window._streakLostTxt && window._streakLostTxt.parent) {
			window._streakLostTxt.parent.removeChild(window._streakLostTxt);
			if (typeof window._streakLostTxt.destroy === "function") window._streakLostTxt.destroy();
		}
		window._streakLostTxt = null;
		window._streakLostTimeout = null;
	}, 5000);
}
function incrementStreak() {
	streakCount++;
	updateStreakText();
	// Increment score by 50 every time the streak increases
	scoreCount += 50;
	updateScoreText();
	// Play the 'Streak' sound every time the streak counter increases
	var streakSnd = LK.getSound('Streak');
	if (streakSnd && typeof streakSnd.play === "function") streakSnd.play();
}
function showPersonalityPopup() {
	// Remove any previous personality text nodes
	if (personalityTextNodes && personalityTextNodes.length) {
		for (var i = 0; i < personalityTextNodes.length; i++) {
			var node = personalityTextNodes[i];
			if (node && node.parent) node.parent.removeChild(node);
			if (node && typeof node.destroy === "function") node.destroy();
		}
		personalityTextNodes = [];
	}
	// For each organism, show a floating text above it with its personality
	function addPersonalityTextFor(arr, getType, getPers) {
		for (var i = 0; i < arr.length; i++) {
			var org = arr[i];
			if (!org || typeof org.x !== "number" || typeof org.y !== "number") continue;
			var type = getType(org);
			var pers = getPers(org);
			var txt = new Text2(pers, {
				size: 44,
				fill: pers === "N/A" ? "#888" : "#2c3e50"
			});
			txt.anchor.set(0.5, 1);
			txt.x = org.x;
			txt.y = org.y - 70;
			txt._personalityTarget = org;
			txt._personalityType = type;
			game.addChild(txt);
			personalityTextNodes.push(txt);
		}
	}
	// Ferns (plants)
	addPersonalityTextFor(plants, function () {
		return "Fern";
	}, function () {
		return "N/A";
	});
	// Nummer (herbivores)
	addPersonalityTextFor(herbivores, function () {
		return "Nummer";
	}, function (org) {
		// Only show personality if actually placed (on map, not destroyed)
		if (typeof org.eaten !== "undefined" && org.eaten) return "N/A";
		return org.personality || "N/A";
	});
	// Hunter (carnivores)
	addPersonalityTextFor(carnivores, function () {
		return "Hunter";
	}, function (org) {
		// Only show personality if actually placed (on map, not destroyed)
		if (typeof org.eaten !== "undefined" && org.eaten) return "N/A";
		return org.personality || "N/A";
	});
	// Pollinator
	addPersonalityTextFor(pollinators, function () {
		return "Pollinator";
	}, function (org) {
		return org.personality || "N/A";
	});
	// Shroom (fungi)
	addPersonalityTextFor(fungis, function () {
		return "Shroom";
	}, function () {
		return "N/A";
	});
	// Parasite
	addPersonalityTextFor(parasites, function () {
		return "Parasite";
	}, function () {
		return "N/A";
	});
	// Worm
	addPersonalityTextFor(worms, function () {
		return "Worm";
	}, function () {
		return "N/A";
	});
	// Patch game.update to keep personality text above each organism while visible
	if (!game._personalityTextPatched) {
		var _originalGameUpdate = game.update;
		game.update = function () {
			// Move each personality text to follow its organism
			if (personalityTextNodes && personalityTextNodes.length) {
				for (var i = personalityTextNodes.length - 1; i >= 0; i--) {
					var txt = personalityTextNodes[i];
					var org = txt && txt._personalityTarget;
					if (!org || typeof org.x !== "number" || typeof org.y !== "number" || org.eaten) {
						// Remove text if organism is gone
						if (txt.parent) txt.parent.removeChild(txt);
						if (typeof txt.destroy === "function") txt.destroy();
						personalityTextNodes.splice(i, 1);
						continue;
					}
					txt.x = org.x;
					txt.y = org.y - 70;
				}
			}
			if (_originalGameUpdate) _originalGameUpdate.apply(this, arguments);
		};
		game._personalityTextPatched = true;
	}
	// Add a close button in the top right to remove all personality text
	if (!window._personalityTextCloseBtn) {
		var closeBtn = new Container();
		var closeBtnBox = closeBtn.attachAsset('box', {
			anchorX: 0.5,
			anchorY: 0.5,
			width: 180,
			height: 80,
			color: 0x8e44ad,
			shape: 'box'
		});
		var closeBtnTxt = new Text2("Hide", {
			size: 44,
			fill: "#fff"
		});
		closeBtnTxt.anchor.set(0.5, 0.5);
		closeBtn.addChild(closeBtnTxt);
		closeBtn.x = 2048 - 200;
		closeBtn.y = 180;
		closeBtn.interactive = true;
		closeBtn.visible = true;
		closeBtn.down = function () {
			// Remove all personality text nodes
			if (personalityTextNodes && personalityTextNodes.length) {
				for (var i = 0; i < personalityTextNodes.length; i++) {
					var node = personalityTextNodes[i];
					if (node && node.parent) node.parent.removeChild(node);
					if (node && typeof node.destroy === "function") node.destroy();
				}
				personalityTextNodes = [];
			}
			if (closeBtn && closeBtn.parent) closeBtn.parent.removeChild(closeBtn);
			window._personalityTextCloseBtn = null;
		};
		LK.gui.top.addChild(closeBtn);
		window._personalityTextCloseBtn = closeBtn;
	}
}
// Button handler
// Track if personality text is currently shown
var personalityTextVisible = false;
personalityBtn.down = function () {
	var clickSnd = LK.getSound('Click');
	if (clickSnd && typeof clickSnd.play === "function") clickSnd.play();
	if (personalityTextVisible) {
		// Hide all personality text nodes
		if (personalityTextNodes && personalityTextNodes.length) {
			for (var i = 0; i < personalityTextNodes.length; i++) {
				var node = personalityTextNodes[i];
				if (node && node.parent) node.parent.removeChild(node);
				if (node && typeof node.destroy === "function") node.destroy();
			}
			personalityTextNodes = [];
		}
		// Remove close button if present
		if (window._personalityTextCloseBtn) {
			if (window._personalityTextCloseBtn.parent) window._personalityTextCloseBtn.parent.removeChild(window._personalityTextCloseBtn);
			window._personalityTextCloseBtn = null;
		}
		personalityTextVisible = false;
	} else {
		showPersonalityPopup();
		personalityTextVisible = true;
	}
};
// --- Randomize Button Handler ---
randomizeBtn.down = function () {
	var clickSnd = LK.getSound('Click');
	if (clickSnd && typeof clickSnd.play === "function") clickSnd.play();
	// Only randomize if not retracted or already disabled
	if (topButtonsRetracted || randomizeBtn._disabled) return;
	// Helper to get a random position in the map area
	function getRandomPos() {
		var minX = 124 + 60;
		var maxX = 124 + 1800 - 60;
		var minY = paletteY + 320 + 60;
		var maxY = paletteY + 320 + 2000 - 60;
		return {
			x: minX + Math.random() * (maxX - minX),
			y: minY + Math.random() * (maxY - minY)
		};
	}
	// Add 3-5 ferns
	var fernCount = 3 + Math.floor(Math.random() * 3); // 3,4,5
	for (var i = 0; i < fernCount; i++) {
		var pos = getRandomPos();
		var fern = new Plant();
		fern.x = pos.x;
		fern.y = pos.y;
		fern.scaleX = 1;
		fern.scaleY = 1;
		fern.alpha = 1;
		plants.push(fern);
		game.addChild(fern);
	}
	// Add 3-5 herbivores
	var herbCount = 3 + Math.floor(Math.random() * 3);
	for (var i = 0; i < herbCount; i++) {
		var pos = getRandomPos();
		var herb = new Nummer();
		herb._uniqueId = "herb_" + Math.floor(Math.random() * 1e9) + "_" + Math.floor(Math.random() * 1e9);
		herb.x = pos.x;
		herb.y = pos.y;
		herb.scaleX = 1;
		herb.scaleY = 1;
		herb.alpha = 1;
		// Start in wandering state when spawned by randomize button
		herb.state = "wandering";
		herb._wanderAfterSleepTimer = 600; // 10 seconds wandering
		// --- Randomize herbivore personality ---
		var personalities = ["normal", "curious", "grumpy"];
		var rand = Math.random();
		// Make random traits more common: 30% normal, 35% curious, 35% grumpy
		if (rand < 0.3) {
			herb.personality = "normal";
		} else if (rand < 0.65) {
			herb.personality = "curious";
		} else {
			herb.personality = "grumpy";
		}
		herbivores.push(herb);
		game.addChild(herb);
	}
	// Add 3-5 pollinators
	var pollCount = 3 + Math.floor(Math.random() * 3);
	for (var i = 0; i < pollCount; i++) {
		var pos = getRandomPos();
		var poll = new Pollinator();
		poll.x = pos.x;
		poll.y = pos.y;
		poll.scaleX = 1;
		poll.scaleY = 1;
		poll.alpha = 1;
		pollinators.push(poll);
		game.addChild(poll);
	}
	// Add 0-1 carnivores
	var carnCount = Math.floor(Math.random() * 2); // 0 or 1
	for (var i = 0; i < carnCount; i++) {
		var pos = getRandomPos();
		var carn = new Carnivore();
		// --- Randomize carnivore personality ---
		var carnPersonalities = ["normal", "bloodthirsty", "weak"];
		var rand = Math.random();
		// Make random traits more common: 30% normal, 35% bloodthirsty, 35% weak
		if (rand < 0.3) {
			carn.personality = "normal";
		} else if (rand < 0.65) {
			carn.personality = "bloodthirsty";
		} else {
			carn.personality = "weak";
		}
		// Adjust speed for bloodthirsty carnivores
		if (carn.personality === "bloodthirsty") {
			carn.speed = 1.5 + Math.random() * 1.2 + 0.7 + Math.random() * 0.5;
		}
		carn.x = pos.x;
		carn.y = pos.y;
		carn.scaleX = 1.25;
		carn.scaleY = 1.25;
		carn.alpha = 1;
		carnivores.push(carn);
		game.addChild(carn);
	}
	// Play plop sound for feedback
	var plopSnd = LK.getSound('Plop');
	if (plopSnd && typeof plopSnd.play === "function") plopSnd.play();
	// --- Unlock skip cycle button when randomize is pressed ---
	skipCycleBtn._skipLocked = false;
	firstOrganismPlaced = true;
	// --- Restart the cycle timer when randomize is pressed ---
	if (cycleInterval !== null) {
		LK.clearInterval(cycleInterval);
		cycleInterval = null;
	}
	if (cycleCountdownInterval !== null) {
		LK.clearInterval(cycleCountdownInterval);
		cycleCountdownInterval = null;
	}
	cycleTimeLeftMs = cycleDurationMs;
	cycleTimerTxt.setText("Next cycle: " + Math.ceil(cycleTimeLeftMs / 1000) + "s");
	startCycleInterval();
	// --- Disable and color the randomize button red ---
	randomizeBtn._disabled = true;
	randomizeBtnBox.color = 0xcc2222;
	if (typeof randomizeBtnBox.setStyle === "function") {
		randomizeBtnBox.setStyle({
			fill: "#fff"
		});
	}
	randomizeBtnTxt.setText("Randomized");
	// --- Disable randomize button if any organisms are present ---
	if (plants.length > 0 || herbivores.length > 0 || carnivores.length > 0 || pollinators.length > 0 || fungis.length > 0 || parasites.length > 0 || worms.length > 0) {
		randomizeBtn._disabled = true;
		randomizeBtnBox.color = 0xcc2222;
		if (typeof randomizeBtnBox.setStyle === "function") {
			randomizeBtnBox.setStyle({
				fill: "#fff"
			});
		}
		randomizeBtnTxt.setText("Randomized");
	}
};
// Asteroid extinction event handler
// --- Extinction Event Rate Limiting ---
// Track timestamps (in ms) of recent extinction events
if (typeof window._extinctionEventTimes === "undefined") window._extinctionEventTimes = [];
extinctionBtn.down = function () {
	var clickSnd = LK.getSound('Click');
	if (clickSnd && typeof clickSnd.play === "function") clickSnd.play();
	LK.getSound('explosion').play();
	// Asteroid visual: big circle in center of map
	var asteroid = LK.getAsset('box', {
		anchorX: 0.5,
		anchorY: 0.5,
		width: 400,
		height: 400,
		color: 0x888888,
		shape: 'ellipse'
	});
	asteroid.x = 124 + 1800 / 2;
	asteroid.y = paletteY + 320 + 2000 / 2;
	asteroid.alpha = 0.0;
	game.addChild(asteroid);
	// Animate asteroid fade in, then out
	tween(asteroid, {
		alpha: 1
	}, {
		duration: 300,
		easing: tween.easeIn,
		onFinish: function onFinish() {
			tween(asteroid, {
				alpha: 0
			}, {
				duration: 700,
				easing: tween.easeOut,
				onFinish: function onFinish() {
					asteroid.destroy();
				}
			});
		}
	});
	// Flash screen for dramatic effect
	LK.effects.flashScreen(0xff6600, 800);
	// --- Extinction Event Rate Limiting Logic ---
	// Add current timestamp to the event list
	var now = Date.now();
	window._extinctionEventTimes.push(now);
	// Only keep events in the last 10 seconds (10000 ms)
	var cutoff = now - 10000;
	for (var i = window._extinctionEventTimes.length - 1; i >= 0; i--) {
		if (window._extinctionEventTimes[i] < cutoff) {
			window._extinctionEventTimes.splice(i, 1);
		}
	}
	// If more than 3 extinction events in last 10 seconds, kill all creatures
	if (window._extinctionEventTimes.length > 3) {
		// Gather all organisms (plants, herbivores, carnivores, pollinators, fungis, seeds, eggs, worms, parasites)
		var allGroups = [plants, herbivores, carnivores, pollinators, fungis, seeds, eggs, worms, parasites];
		for (var g = 0; g < allGroups.length; g++) {
			var arr = allGroups[g];
			for (var i = arr.length - 1; i >= 0; i--) {
				var org = arr[i];
				arr.splice(i, 1);
				if (org && typeof org.die === "function") {
					org.die();
				} else if (org && typeof org.destroy === "function") {
					org.destroy();
				}
			}
		}
		// Optionally, flash the screen again for drama
		LK.effects.flashScreen(0x000000, 1200);
		// Clear the event times to prevent repeated wipes
		window._extinctionEventTimes = [];
		return;
	}
	// Gather all organisms (plants, herbivores, carnivores, pollinators, fungis, seeds, eggs, worms, parasites)
	var allGroups = [plants, herbivores, carnivores, pollinators, fungis, seeds, eggs, worms, parasites];
	for (var g = 0; g < allGroups.length; g++) {
		var arr = allGroups[g];
		if (arr.length === 0) continue;
		// If the group has 3 or fewer, kill 1 or 2 at random (never all)
		if (arr.length <= 3) {
			var toKill = Math.floor(Math.random() * arr.length); // 0, 1, or 2
			for (var i = 0; i < toKill; i++) {
				if (arr.length === 0) break;
				var idx = Math.floor(Math.random() * arr.length);
				var org = arr[idx];
				arr.splice(idx, 1);
				if (org && typeof org.die === "function") {
					org.die();
				} else if (org && typeof org.destroy === "function") {
					org.destroy();
				}
			}
		} else if (arr.length % 2 !== 0) {
			// If uneven, kill a random number between 1 and half the group (rounded down)
			var maxKill = Math.floor(arr.length / 2);
			var toKill = 1 + Math.floor(Math.random() * maxKill);
			for (var i = 0; i < toKill; i++) {
				if (arr.length === 0) break;
				var idx = Math.floor(Math.random() * arr.length);
				var org = arr[idx];
				arr.splice(idx, 1);
				if (org && typeof org.die === "function") {
					org.die();
				} else if (org && typeof org.destroy === "function") {
					org.destroy();
				}
			}
		} else {
			// Even and more than 3: kill half (rounded down), random selection
			var survivors = Math.ceil(arr.length / 2);
			var toKill = arr.length - survivors;
			for (var i = 0; i < toKill; i++) {
				if (arr.length === 0) break;
				var idx = Math.floor(Math.random() * arr.length);
				var org = arr[idx];
				arr.splice(idx, 1);
				if (org && typeof org.die === "function") {
					org.die();
				} else if (org && typeof org.destroy === "function") {
					org.destroy();
				}
			}
		}
	}
};
// --- Prevent skipping cycle until first organism is placed ---
var firstOrganismPlaced = false;
skipCycleBtn._skipLocked = true; // Lock skipping at start
skipCycleBtn.down = function () {
	var clickSnd = LK.getSound('Click');
	if (clickSnd && typeof clickSnd.play === "function") clickSnd.play();
	// --- Streak: Reset streak and play lost sound immediately when skip is pressed ---
	streakCount = 0;
	updateStreakText();
	var lostSnd = LK.getSound('Lost');
	if (lostSnd && typeof lostSnd.play === "function") lostSnd.play();
	// --- Prevent skipping if all organisms are gone (plants, herbivores, carnivores, pollinators, fungis, parasites, worms) ---
	var allGone = plants.length === 0 && herbivores.length === 0 && carnivores.length === 0 && pollinators.length === 0 && fungis.length === 0 && parasites.length === 0 && worms.length === 0;
	if (allGone) {
		// --- Streak: Reset streak if all organisms die on skip ---
		resetStreak();
		// Flash skip button red for 2 seconds
		var originalColor = skipCycleBtnBox.color;
		skipCycleBtnBox.color = 0xff4444;
		if (typeof skipCycleBtnBox.setStyle === "function") {
			skipCycleBtnBox.setStyle({
				fill: "#fff"
			});
		}
		LK.setTimeout(function () {
			skipCycleBtnBox.color = originalColor;
			if (typeof skipCycleBtnBox.setStyle === "function") {
				skipCycleBtnBox.setStyle({
					fill: "#000"
				});
			}
		}, 2000);
		return;
	}
	if (skipCycleBtn._skipLocked) {
		// Flash skip button red for 2 seconds
		var originalColor = skipCycleBtnBox.color;
		skipCycleBtnBox.color = 0xff4444;
		if (typeof skipCycleBtnBox.setStyle === "function") {
			skipCycleBtnBox.setStyle({
				fill: "#fff"
			});
		}
		// Restore color after 2 seconds
		LK.setTimeout(function () {
			skipCycleBtnBox.color = originalColor;
			if (typeof skipCycleBtnBox.setStyle === "function") {
				skipCycleBtnBox.setStyle({
					fill: "#000"
				});
			}
		}, 2000);
		return;
	}
	// --- 3 Second Cooldown Logic ---
	if (skipCycleCooldownActive) {
		// --- Streak: Reset streak if skip is attempted during cooldown (optional, but for safety) ---
		resetStreak();
		// Flash skip button red for 1 second if on cooldown
		var originalColor = skipCycleBtnBox.color;
		skipCycleBtnBox.color = 0xff4444;
		if (typeof skipCycleBtnBox.setStyle === "function") {
			skipCycleBtnBox.setStyle({
				fill: "#fff"
			});
		}
		LK.setTimeout(function () {
			skipCycleBtnBox.color = originalColor;
			if (typeof skipCycleBtnBox.setStyle === "function") {
				skipCycleBtnBox.setStyle({
					fill: "#000"
				});
			}
		}, 1000);
		return;
	}
	skipCycleCooldownActive = true;
	skipCycleBtnBox.color = 0xaaaaaa;
	skipCycleBtnTxt.setText("Cooldown");
	// Show and start the white countdown
	skipCycleCountdownValue = 3;
	skipCycleCountdownTxt.setText("" + skipCycleCountdownValue);
	skipCycleCountdownTxt.visible = true;
	// Clear any previous interval
	if (skipCycleCountdownInterval) {
		LK.clearInterval(skipCycleCountdownInterval);
		skipCycleCountdownInterval = null;
	}
	// Start interval to update countdown every 1s
	skipCycleCountdownInterval = LK.setInterval(function () {
		skipCycleCountdownValue--;
		if (skipCycleCountdownValue > 0) {
			skipCycleCountdownTxt.setText("" + skipCycleCountdownValue);
		} else {
			skipCycleCountdownTxt.visible = false;
			skipCycleCountdownTxt.setText("");
			if (skipCycleCountdownInterval) {
				LK.clearInterval(skipCycleCountdownInterval);
				skipCycleCountdownInterval = null;
			}
		}
	}, 1000);
	// Restore after 3 seconds
	if (skipCycleCooldownTimeout) {
		LK.clearTimeout(skipCycleCooldownTimeout);
	}
	skipCycleCooldownTimeout = LK.setTimeout(function () {
		skipCycleCooldownActive = false;
		skipCycleBtnBox.color = 0x3388cc;
		skipCycleBtnTxt.setText("Skip Cycle");
		if (typeof skipCycleBtnBox.setStyle === "function") {
			skipCycleBtnBox.setStyle({
				fill: "#000"
			});
		}
		// Hide the countdown if still visible
		skipCycleCountdownTxt.visible = false;
		skipCycleCountdownTxt.setText("");
		if (skipCycleCountdownInterval) {
			LK.clearInterval(skipCycleCountdownInterval);
			skipCycleCountdownInterval = null;
		}
	}, 3000);
	// --- Streak: Mark that skip was used this cycle (will reset streak on next cycle) ---
	streakSkipThisCycle = true;
	// Increment cycle and update UI
	cycleCount++;
	cycleTxt.setText("Cycle: " + cycleCount);
	cycleTimeLeftMs = cycleDurationMs;
	cycleTimerTxt.setText("Next cycle: " + Math.ceil(cycleTimeLeftMs / 1000) + "s");
	// --- Extinction: If no plants, kill all herbivores, pollinators, and carnivores ---
	if (plants.length === 0) {
		// Herbivores
		for (var i = herbivores.length - 1; i >= 0; i--) {
			var h = herbivores[i];
			if (typeof h.die === "function") h.die();else if (typeof h.destroy === "function") h.destroy();
			herbivores.splice(i, 1);
		}
		// Pollinators
		for (var i = pollinators.length - 1; i >= 0; i--) {
			var p = pollinators[i];
			if (typeof p.die === "function") p.die();else if (typeof p.destroy === "function") p.destroy();
			pollinators.splice(i, 1);
		}
		// Carnivores
		for (var i = carnivores.length - 1; i >= 0; i--) {
			var c = carnivores[i];
			if (typeof c.die === "function") c.die();else if (typeof c.destroy === "function") c.destroy();
			carnivores.splice(i, 1);
		}
	}
	// Set background color every 3 cycles: green, yellow, brown, white, repeat (spring, summer, autumn, winter)
	var mod = cycleCount % 12;
	if (mod === 0) {
		// SPRING
		game.setBackgroundColor(0x2ecc40); // green
		updateTextColors(0x2ecc40);
		pollinatorsHibernating = false;
		window.summerState = false;
		window.springState = true;
		window.winterState = false;
		window.autumnState = false;
		// Play mellow music
		LK.playMusic('mellow');
		// --- YEAR COUNTER: Increment year after winter ends (when entering spring) ---
		if (cycleCount > 0) {
			yearCount++;
			if (yearTxt && typeof yearTxt.setText === "function") {
				yearTxt.setText("Year: " + yearCount);
			}
		}
		for (var i = 0; i < plants.length; i++) {
			if (plants[i] && plants[i].plantAsset && typeof plants[i].plantAsset.tint !== "undefined") {
				plants[i].plantAsset.tint = 0xffffff;
			}
			plants[i]._canDie = true;
		}
		for (var i = 0; i < herbivores.length; i++) {
			if (herbivores[i] && typeof herbivores[i].speed === "number") {
				herbivores[i].speed = 1.2 + Math.random() * 1.0;
			}
		}
		for (var i = 0; i < carnivores.length; i++) {
			if (carnivores[i]) {
				carnivores[i].state = "hungry";
				carnivores[i]._tired = false;
				carnivores[i]._tiredTimer = 0;
				carnivores[i]._chaseTime = 0;
				carnivores[i].target = null;
			}
		}
		updateSeasonText();
	} else if (mod === 3) {
		// SUMMER
		game.setBackgroundColor(0xffff00); // yellow
		updateTextColors(0xffff00);
		pollinatorsHibernating = false;
		window.summerState = true;
		window.winterState = false;
		window.springState = false;
		window.autumnState = false;
		for (var i = 0; i < plants.length; i++) {
			if (plants[i] && plants[i].plantAsset && typeof plants[i].plantAsset.tint !== "undefined") {
				plants[i].plantAsset.tint = 0xffffff;
			}
			plants[i]._canDie = true;
		}
		updateSeasonText();
	} else if (mod === 6) {
		// AUTUMN
		game.setBackgroundColor(0x8B5A2B); // brown
		updateTextColors(0x8B5A2B);
		pollinatorsHibernating = false;
		window.summerState = false;
		window.springState = false;
		window.winterState = false;
		window.autumnState = true;
		for (var i = 0; i < plants.length; i++) {
			if (plants[i] && plants[i].plantAsset && typeof plants[i].plantAsset.tint !== "undefined") {
				plants[i].plantAsset.tint = 0x996633; // brown
			}
			plants[i]._canDie = true;
			plants[i]._isBrown = true;
		}
		updateSeasonText();
	} else if (mod === 9) {
		// WINTER
		game.setBackgroundColor(0xffffff); // white
		updateTextColors(0xffffff);
		pollinatorsHibernating = true;
		window.summerState = false;
		window.springState = false;
		window.winterState = true;
		window.autumnState = false;
		for (var i = plants.length - 1; i >= 0; i--) {
			var p = plants[i];
			if (p && p._isBrown && !p.eaten && typeof p.die === "function") {
				p.die();
			}
		}
		for (var i = 0; i < plants.length; i++) {
			if (plants[i] && plants[i].plantAsset && typeof plants[i].plantAsset.tint !== "undefined") {
				plants[i].plantAsset.tint = 0x3399ff;
			}
			plants[i]._canDie = false;
		}
		updateSeasonText();
	}
	// Randomize all organism positions except fungi, plants, and lichen
	var minX = 124 + 60;
	var maxX = 124 + 1800 - 60;
	var minY = paletteY + 320 + 60;
	var maxY = paletteY + 320 + 2000 - 60;
	// Helper to randomize array of organisms
	function randomizeOrganisms(arr) {
		for (var i = 0; i < arr.length; i++) {
			var org = arr[i];
			// If this is a host with a parasite attached, skip randomizing its position
			if (org && typeof org.x === "number" && typeof org.y === "number" && !org.eaten && !org._parasiteAttached // Only randomize if not hosting a parasite
			) {
				org.x = minX + Math.random() * (maxX - minX);
				org.y = minY + Math.random() * (maxY - minY);
			}
		}
	}
	// When randomizing parasites, only randomize those not attached to a host
	function randomizeFreeParasites(arr) {
		for (var i = 0; i < arr.length; i++) {
			var parasite = arr[i];
			if (parasite && typeof parasite.x === "number" && typeof parasite.y === "number" && !parasite.eaten && parasite.state !== "attached") {
				parasite.x = minX + Math.random() * (maxX - minX);
				parasite.y = minY + Math.random() * (maxY - minY);
			}
		}
	}
	randomizeOrganisms(herbivores);
	randomizeOrganisms(carnivores);
	randomizeOrganisms(pollinators);
	randomizeOrganisms(seeds);
	randomizeOrganisms(eggs);
	randomizeOrganisms(worms);
	randomizeFreeParasites(parasites);
	// Fungi, plants, and lichen are NOT moved
	// (fungis, plants, window.lichens)
};
// --- Patch createOrganism to unlock skip after first organism placed ---
var _originalCreateOrganism = createOrganism;
createOrganism = function createOrganism(type, x, y) {
	var obj = _originalCreateOrganism(type, x, y);
	if (!firstOrganismPlaced) {
		firstOrganismPlaced = true;
		skipCycleBtn._skipLocked = false;
	}
	return obj;
};
// --- Retract/Expand Widget for Top Buttons ---
// State for retraction
var topButtonsRetracted = false;
// Widget button (a small round button at the right of the top buttons)
var retractWidget = new Container();
var retractWidgetBox = retractWidget.attachAsset('box', {
	anchorX: 0.5,
	anchorY: 0.5,
	width: 90,
	height: 90,
	color: 0x888888,
	shape: 'ellipse'
});
var retractWidgetTxt = new Text2("β‘", {
	size: 60,
	fill: "#fff"
});
retractWidgetTxt.anchor.set(0.5, 0.5);
retractWidget.addChild(retractWidgetTxt);
// Place widget to the right of the top buttons
retractWidget.x = 300;
retractWidget.y = deleteBtn.y + 50;
retractWidget.interactive = true;
retractWidget.visible = true;
// Helper to update button visibility/position
function updateTopButtonsRetracted() {
	if (topButtonsRetracted) {
		// Move buttons offscreen right, hide text, and set visible to false
		var offX = 2048 + 300;
		tween(skipCycleBtn, {
			x: offX
		}, {
			duration: 200,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				skipCycleBtn.visible = false;
			}
		});
		tween(deleteBtn, {
			x: offX
		}, {
			duration: 200,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				deleteBtn.visible = false;
			}
		});
		tween(extinctionBtn, {
			x: offX
		}, {
			duration: 200,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				extinctionBtn.visible = false;
			}
		});
		// Hide randomize button as well
		if (typeof randomizeBtn !== "undefined") {
			tween(randomizeBtn, {
				x: offX
			}, {
				duration: 200,
				easing: tween.easeIn,
				onFinish: function onFinish() {
					randomizeBtn.visible = false;
				}
			});
		}
		// Hide personality button as well
		if (typeof personalityBtn !== "undefined") {
			tween(personalityBtn, {
				x: offX
			}, {
				duration: 200,
				easing: tween.easeIn,
				onFinish: function onFinish() {
					personalityBtn.visible = false;
				}
			});
		}
		retractWidgetTxt.setText("βΆ");
		// Also move retractWidget to the right when retracted
		tween(retractWidget, {
			x: 700 //{Fe} // Move even further right
		}, {
			duration: 200,
			easing: tween.easeIn
		});
	} else {
		// Move buttons back to original positions and set visible to true
		tween(retractWidget, {
			x: 300
		}, {
			duration: 200,
			easing: tween.easeOut
		});
		skipCycleBtn.visible = true;
		deleteBtn.visible = true;
		extinctionBtn.visible = true;
		if (typeof randomizeBtn !== "undefined") {
			randomizeBtn.visible = true;
			tween(randomizeBtn, {
				x: 500
			}, {
				duration: 200,
				easing: tween.easeOut
			});
		}
		// Show and move personality button back
		if (typeof personalityBtn !== "undefined") {
			personalityBtn.visible = true;
			tween(personalityBtn, {
				x: 500
			}, {
				duration: 200,
				easing: tween.easeOut
			});
		}
		tween(skipCycleBtn, {
			x: 500
		}, {
			duration: 200,
			easing: tween.easeOut
		});
		tween(deleteBtn, {
			x: 500
		}, {
			duration: 200,
			easing: tween.easeOut
		});
		tween(extinctionBtn, {
			x: 500
		}, {
			duration: 200,
			easing: tween.easeOut
		});
		retractWidgetTxt.setText("β‘");
	}
}
// Widget click toggles retraction
retractWidget.down = function () {
	var clickSnd = LK.getSound('Click');
	if (clickSnd && typeof clickSnd.play === "function") clickSnd.play();
	topButtonsRetracted = !topButtonsRetracted;
	// Animate widget itself to the right when retracting, back to original when expanding
	if (topButtonsRetracted) {
		tween(retractWidget, {
			x: 500
		}, {
			duration: 200,
			easing: tween.easeIn
		});
	} else {
		tween(retractWidget, {
			x: 300
		}, {
			duration: 200,
			easing: tween.easeOut
		});
	}
	updateTopButtonsRetracted();
};
// Add widget to GUI
LK.gui.top.addChild(skipCycleBtn);
LK.gui.top.addChild(extinctionBtn);
LK.gui.top.addChild(randomizeBtn);
LK.gui.top.addChild(retractWidget);
// On game start, ensure buttons are expanded
updateTopButtonsRetracted();
// Shift the palette even further left so it is not offscreen
var paletteTotalWidth = paletteSpacing * 2;
var paletteXStart = 2048 / 2 - paletteTotalWidth / 2 - 1300;
// Create palette items for drag-and-drop
function createPaletteItem(type, x, y) {
	var assetId, color, label;
	if (type === 'plant') {
		assetId = 'plant';
		color = 0x6adf60;
		label = 'Fern';
	} else if (type === 'herbivore') {
		assetId = 'herbivore';
		color = 0xf7e26b;
		label = 'Nummer';
	} else if (type === 'pollinator') {
		assetId = 'pollinator';
		color = 0xffc300;
		label = 'Pollinator';
	} else if (type === 'fungi') {
		assetId = 'fungi';
		color = 0xbb88ff;
		label = 'Shroom';
	} else if (type === 'parasite') {
		assetId = 'Parasite';
		color = 0x8888ff;
		label = 'Parasite';
	} else if (type === 'worm') {
		assetId = 'Worm';
		color = 0x888888;
		label = 'Worm';
	} else {
		assetId = 'carnivore';
		color = 0xe74c3c;
		label = 'Hunter';
	}
	;
	// Update all eggs
	for (var i = eggs.length - 1; i >= 0; i--) {
		var e = eggs[i];
		if (!e.parent || e.hatched) {
			eggs.splice(i, 1);
			continue;
		}
		if (e.update) e.update();
	}
	;
	// Update all pollinators
	for (var i = pollinators.length - 1; i >= 0; i--) {
		var p = pollinators[i];
		if (p.eaten) {
			pollinators.splice(i, 1);
			continue;
		}
		if (p.update) p.update();
	}
	var node = new Container();
	var icon;
	if (type === 'parasite') {
		icon = node.attachAsset(assetId, {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: 0.5,
			scaleY: 0.5
		});
	} else {
		icon = node.attachAsset(assetId, {
			anchorX: 0.5,
			anchorY: 0.5
		});
	}
	node.x = x;
	node.y = y;
	node.type = type;
	// --- Population Counter Above Icon ---
	var popCount = 0;
	if (type === 'plant') popCount = plants.length;else if (type === 'herbivore') popCount = herbivores.length;else if (type === 'carnivore') popCount = carnivores.length;else if (type === 'pollinator') popCount = pollinators.length;else if (type === 'fungi') popCount = fungis.length;else if (type === 'parasite') popCount = parasites.length;
	var popTxt = new Text2("" + popCount, {
		size: 54,
		fill: "#000"
	});
	popTxt.anchor.set(0.5, 1);
	popTxt.y = -70;
	node.addChild(popTxt);
	node._popTxt = popTxt; // Store for update
	// Add label
	var txt = new Text2(label, {
		size: 60,
		fill: "#000"
	});
	txt.anchor.set(0.5, 0);
	txt.y = 60;
	node.addChild(txt);
	// Add to GUI overlay (so it stays on top)
	LK.gui.top.addChild(node);
	paletteItems.push(node);
	return node;
}
// --- Palette Scroll Bar ---
// All available organism types in palette
var paletteTypes = ['plant', 'herbivore', 'carnivore', 'pollinator', 'fungi', 'parasite', 'worm'];
var paletteScrollOffset = 0; // How much the palette is scrolled (in px)
var paletteScrollMin = 0;
var paletteScrollMax = Math.max(0, paletteTypes.length * paletteSpacing - paletteSpacing * 3); // Show 3 at a time
// Remove old palette items if any
for (var i = 0; i < paletteItems.length; i++) {
	if (paletteItems[i].parent) paletteItems[i].parent.removeChild(paletteItems[i]);
}
paletteItems = [];
// Helper to render palette items based on scroll offset
function renderPaletteItems() {
	// Remove all current palette items from GUI
	for (var i = 0; i < paletteItems.length; i++) {
		if (paletteItems[i].parent) paletteItems[i].parent.removeChild(paletteItems[i]);
	}
	paletteItems = [];
	// Only show up to 3 at a time, centered
	var visibleCount = 3;
	var startIdx = Math.floor(paletteScrollOffset / paletteSpacing);
	var offsetPx = paletteScrollOffset % paletteSpacing;
	for (var i = 0; i < visibleCount; i++) {
		var idx = startIdx + i;
		if (idx >= 0 && idx < paletteTypes.length) {
			var px = paletteXStart + i * paletteSpacing - offsetPx;
			var node = createPaletteItem(paletteTypes[idx], px, paletteY);
			paletteItems.push(node);
		}
	}
	// Draw left/right scroll buttons
	if (!window.paletteLeftBtn) {
		window.paletteLeftBtn = new Container();
		var leftIcon = window.paletteLeftBtn.attachAsset('box', {
			anchorX: 0.5,
			anchorY: 0.5,
			width: 80,
			height: 120,
			color: 0x444444,
			shape: 'box'
		});
		var leftArrow = new Text2("<", {
			size: 80,
			fill: "#000"
		});
		leftArrow.anchor.set(0.5, 0.5);
		leftArrow.x = 0;
		leftArrow.y = 0;
		window.paletteLeftBtn.addChild(leftArrow);
		window.paletteLeftBtn.x = paletteXStart - 120;
		window.paletteLeftBtn.y = paletteY;
		window.paletteLeftBtn.interactive = true;
		LK.gui.top.addChild(window.paletteLeftBtn);
		window.paletteLeftBtn.visible = false;
	}
	if (!window.paletteRightBtn) {
		window.paletteRightBtn = new Container();
		var rightIcon = window.paletteRightBtn.attachAsset('box', {
			anchorX: 0.5,
			anchorY: 0.5,
			width: 80,
			height: 120,
			color: 0x444444,
			shape: 'box'
		});
		var rightArrow = new Text2(">", {
			size: 80,
			fill: "#000"
		});
		rightArrow.anchor.set(0.5, 0.5);
		rightArrow.x = 0;
		rightArrow.y = 0;
		window.paletteRightBtn.addChild(rightArrow);
		window.paletteRightBtn.x = paletteXStart + paletteSpacing * visibleCount + 40;
		window.paletteRightBtn.y = paletteY;
		window.paletteRightBtn.interactive = true;
		LK.gui.top.addChild(window.paletteRightBtn);
		window.paletteRightBtn.visible = false;
	}
	// Show/hide buttons
	window.paletteLeftBtn.visible = paletteScrollOffset > paletteScrollMin;
	window.paletteRightBtn.visible = paletteScrollOffset < paletteScrollMax;
}
renderPaletteItems();
// --- Palette Scroll Button Handlers ---
window.paletteLeftBtn.down = function () {
	var clickSnd = LK.getSound('Click');
	if (clickSnd && typeof clickSnd.play === "function") clickSnd.play();
	if (paletteScrollOffset > paletteScrollMin) {
		paletteScrollOffset -= paletteSpacing;
		if (paletteScrollOffset < paletteScrollMin) paletteScrollOffset = paletteScrollMin;
		renderPaletteItems();
	}
};
window.paletteRightBtn.down = function () {
	var clickSnd = LK.getSound('Click');
	if (clickSnd && typeof clickSnd.play === "function") clickSnd.play();
	if (paletteScrollOffset < paletteScrollMax) {
		paletteScrollOffset += paletteSpacing;
		if (paletteScrollOffset > paletteScrollMax) paletteScrollOffset = paletteScrollMax;
		renderPaletteItems();
	}
};
// --- End Palette Scroll Bar ---
// --- Drag and Drop Logic ---
var dragging = null; // {type, node, paletteRef}
var dragOffsetX = 0,
	dragOffsetY = 0;
// Helper: create organism at x,y
function createOrganism(type, x, y) {
	var obj;
	if (type === 'plant') {
		obj = new Plant();
		plants.push(obj);
		// If background is white, make plant blue and undying
		if (game.backgroundColor === 0xffffff) {
			if (obj.plantAsset && typeof obj.plantAsset.tint !== "undefined") {
				obj.plantAsset.tint = 0x3399ff;
			}
			obj._canDie = false;
		}
		// If placed in summer, make plant invulnerable for 10 seconds
		if (game.backgroundColor === 0xffff00 || window.summerState) {
			obj._invulnerable = true;
			obj._canDie = false;
			// Remove invulnerability after 10 seconds (600 frames)
			LK.setTimeout(function () {
				if (plants.indexOf(obj) !== -1) {
					obj._invulnerable = false;
					obj._canDie = true;
				}
			}, 10000);
		}
	} else if (type === 'herbivore') {
		obj = new Nummer();
		obj._uniqueId = "herb_" + Math.floor(Math.random() * 1e9) + "_" + Math.floor(Math.random() * 1e9);
		herbivores.push(obj);
	} else if (type === 'pollinator') {
		obj = new Pollinator();
		pollinators.push(obj);
	} else if (type === 'fungi') {
		obj = new Fungi();
		// If fungi is spawned after the cycle has started, set its _bornCycle to the next cycle so it lives a full cycle
		if (typeof cycleCount !== "undefined") {
			obj._bornCycle = cycleCount + 1;
		}
		fungis.push(obj);
	} else if (type === 'parasite') {
		obj = new Parasite();
		parasites.push(obj);
		// If spawned in winter, kill parasite immediately
		if (window.winterState) {
			// Animate parasite dying and remove from array
			tween(obj, {
				scaleX: 0,
				scaleY: 0,
				alpha: 0
			}, {
				duration: 200,
				easing: tween.easeIn,
				onFinish: function onFinish() {
					if (typeof parasites !== "undefined") {
						var idx = parasites.indexOf(obj);
						if (idx !== -1) parasites.splice(idx, 1);
					}
					obj.destroy();
				}
			});
		}
	} else if (type === 'worm') {
		obj = new Worm();
		worms.push(obj);
		// If spawned in autumn or spring, set buried state (handled in Worm class, but ensure correct state at spawn)
		if ((window.autumnState || window.springState) && obj) {
			obj.buried = true;
			if (obj._wormAsset) {
				obj.removeChild(obj._wormAsset);
			}
			obj._wormAsset = obj.attachAsset('Buried_worm', {
				anchorX: 0.5,
				anchorY: 0.5
			});
		}
		// If spawned in the first 2 cycles, set buried state
		if (typeof cycleCount !== "undefined" && cycleCount < 2 && obj) {
			obj.buried = true;
			if (obj._wormAsset) {
				obj.removeChild(obj._wormAsset);
			}
			obj._wormAsset = obj.attachAsset('Buried_worm', {
				anchorX: 0.5,
				anchorY: 0.5
			});
		}
	} else {
		obj = new Carnivore();
		carnivores.push(obj);
	}
	obj.x = x;
	obj.y = y;
	obj.scaleX = 1;
	obj.scaleY = 1;
	obj.alpha = 1;
	game.addChild(obj);
	// Play plop sound when placing an organism from the palette
	var plopSnd = LK.getSound('Plop');
	if (plopSnd && typeof plopSnd.play === "function") plopSnd.play();
	// Start the cycle interval if not already started
	if (typeof startCycleInterval === "function") startCycleInterval();
	// If personality button is enabled (personality text nodes are present), show personality text for this organism
	if (personalityTextNodes && personalityTextNodes.length > 0) {
		// Helper to add personality text for a single organism
		var addPersonalityTextForSingle = function addPersonalityTextForSingle(org, type, pers) {
			var txt = new Text2(pers, {
				size: 44,
				fill: pers === "N/A" ? "#888" : "#2c3e50"
			});
			txt.anchor.set(0.5, 1);
			txt.x = org.x;
			txt.y = org.y - 70;
			txt._personalityTarget = org;
			txt._personalityType = type;
			game.addChild(txt);
			personalityTextNodes.push(txt);
		}; // Determine type and personality string
		var type = null,
			pers = "N/A";
		if (obj instanceof Plant) {
			type = "Fern";
			pers = "N/A";
		} else if (obj instanceof Nummer) {
			type = "Nummer";
			pers = obj.personality || "N/A";
		} else if (obj instanceof Carnivore) {
			type = "Hunter";
			pers = obj.personality || "N/A";
		} else if (obj instanceof Pollinator) {
			type = "Pollinator";
			pers = obj.personality || "N/A";
		} else if (obj instanceof Fungi) {
			type = "Shroom";
			pers = "N/A";
		} else if (obj instanceof Parasite) {
			type = "Parasite";
			pers = "N/A";
		} else if (obj instanceof Worm) {
			type = "Worm";
			pers = "N/A";
		}
		addPersonalityTextForSingle(obj, type, pers);
	}
	return obj;
}
// Helper: check if point is inside a palette item
function isInPalette(x, y, node) {
	var bounds = {
		x: node.x - 60,
		y: node.y - 60,
		w: 120,
		h: 120
	};
	return x >= bounds.x && x <= bounds.x + bounds.w && y >= bounds.y && y <= bounds.y + bounds.h;
}
// --- Event Handlers ---
// Global button click sound handler: play click sound for any button on screen
if (typeof window._globalButtonClickHandlerAttached === "undefined") {
	window._globalButtonClickHandlerAttached = true;
	// Patch LK.gui.top's down event to play click sound for any button
	var _originalGuiTopDown = LK.gui.top.down;
	LK.gui.top.down = function (x, y, obj) {
		var clickSnd = LK.getSound('Click');
		if (clickSnd && typeof clickSnd.play === "function") clickSnd.play();
		if (typeof _originalGuiTopDown === "function") _originalGuiTopDown.call(this, x, y, obj);
	};
	// Patch LK.gui.bottom's down event to play click sound for any button
	var _originalGuiBottomDown = LK.gui.bottom.down;
	LK.gui.bottom.down = function (x, y, obj) {
		var clickSnd = LK.getSound('Click');
		if (clickSnd && typeof clickSnd.play === "function") clickSnd.play();
		if (typeof _originalGuiBottomDown === "function") _originalGuiBottomDown.call(this, x, y, obj);
	};
}
// Down: start drag if on palette
game.down = function (x, y, obj) {
	// If delete mode is ON, check if click is on an organism and delete it
	if (deleteMode) {
		// Include lichens in allOrganisms if present
		var allOrganisms = plants.concat(herbivores, carnivores, pollinators, fungis, parasites, worms);
		for (var i = allOrganisms.length - 1; i >= 0; i--) {
			var org = allOrganisms[i];
			var dx = x - org.x;
			var dy = y - org.y;
			var dist = Math.sqrt(dx * dx + dy * dy);
			var isFungi = fungis.indexOf(org) !== -1;
			var canDelete = isFungi || !org.eaten;
			if (canDelete && dist < 60) {
				// Remove from correct array
				if (plants.indexOf(org) !== -1) {
					var idx = plants.indexOf(org);
					if (idx !== -1) plants.splice(idx, 1);
				} else if (herbivores.indexOf(org) !== -1) {
					var idx = herbivores.indexOf(org);
					if (idx !== -1) {
						// Remove from hunger queue if present
						var hqidx = herbivoreHungerQueue.indexOf(org);
						if (hqidx !== -1) {
							herbivoreHungerQueue.splice(hqidx, 1);
							// Next in queue (if any) becomes hungry
							for (var j = 0; j < herbivoreHungerQueue.length; j++) {
								var nextH = herbivoreHungerQueue[j];
								if (nextH && nextH.state === "waiting") {
									nextH.state = "hungry";
									nextH._hungerQueueState = "hungry";
									break;
								}
							}
						}
						herbivores.splice(idx, 1);
					}
				} else if (carnivores.indexOf(org) !== -1) {
					var idx = carnivores.indexOf(org);
					if (idx !== -1) carnivores.splice(idx, 1);
				} else if (pollinators.indexOf(org) !== -1) {
					var idx = pollinators.indexOf(org);
					if (idx !== -1) pollinators.splice(idx, 1);
				} else if (fungis.indexOf(org) !== -1) {
					var idx = fungis.indexOf(org);
					if (idx !== -1) fungis.splice(idx, 1);
				}
				if (typeof org.die === "function") {
					org.die();
				} else if (typeof org.destroy === "function") {
					org.destroy();
				}
				return;
			}
		}
		// If not on an organism, do nothing in delete mode
		return;
	}
	// Check if touch/click is on a palette item
	for (var i = 0; i < paletteItems.length; i++) {
		var p = paletteItems[i];
		// Convert GUI coordinates to game coordinates
		var guiPos = LK.gui.top.toLocal({
			x: x,
			y: y
		}, game);
		if (isInPalette(guiPos.x, guiPos.y, p)) {
			// Start dragging a new organism
			dragging = {
				type: p.type,
				node: createOrganism(p.type, x, y),
				paletteRef: p
			};
			dragOffsetX = 0;
			dragOffsetY = 0;
			// Make it semi-transparent while dragging
			dragging.node.alpha = 0.7;
			return;
		}
	}
	// If not on palette, check if on an organism to move it
	// Check if touch/click is on an organism to move it
	var found = false;
	var allOrganisms = plants.concat(herbivores, carnivores, pollinators, fungis, parasites, worms);
	for (var i = allOrganisms.length - 1; i >= 0; i--) {
		var org = allOrganisms[i];
		// Only allow moving if not eaten and touch is within 60px radius of center
		var dx = x - org.x;
		var dy = y - org.y;
		var dist = Math.sqrt(dx * dx + dy * dy);
		var isFungi = fungis.indexOf(org) !== -1;
		var isParasite = parasites.indexOf(org) !== -1;
		var canDrag = isFungi || isParasite || !org.eaten;
		if (canDrag && dist < 60) {
			var type;
			if (plants.indexOf(org) !== -1) type = 'plant';else if (herbivores.indexOf(org) !== -1) type = 'herbivore';else if (carnivores.indexOf(org) !== -1) type = 'carnivore';else if (pollinators.indexOf(org) !== -1) type = 'pollinator';else if (fungis.indexOf(org) !== -1) type = 'fungi';else if (parasites.indexOf(org) !== -1) type = 'parasite';
			// (UI label is handled in createPaletteItem, so no change needed here for type)
			dragging = {
				type: type,
				node: org,
				paletteRef: null
			};
			dragOffsetX = org.x - x;
			dragOffsetY = org.y - y;
			org.alpha = 0.7;
			found = true;
			break;
		}
	}
	if (!found) {
		dragging = null;
	}
};
// Move: update drag position
game.move = function (x, y, obj) {
	if (dragging && dragging.node) {
		var minX = 124 + 60;
		var maxX = 124 + 1800 - 60;
		var minY = paletteY + 320 + 60;
		var maxY = paletteY + 320 + 2000 - 60;
		var newX = x + dragOffsetX;
		var newY = y + dragOffsetY;
		// Clamp to map area
		if (newX < minX) newX = minX;
		if (newX > maxX) newX = maxX;
		if (newY < minY) newY = minY;
		if (newY > maxY) newY = maxY;
		dragging.node.x = newX;
		dragging.node.y = newY;
	}
};
// Up: drop organism if dragging
game.up = function (x, y, obj) {
	if (dragging && dragging.node) {
		// If dropped inside palette area, destroy (cancel)
		var guiPos = LK.gui.top.toLocal({
			x: x,
			y: y
		}, game);
		var cancel = false;
		for (var i = 0; i < paletteItems.length; i++) {
			if (isInPalette(guiPos.x, guiPos.y, paletteItems[i])) {
				cancel = true;
				break;
			}
		}
		if (cancel) {
			// Remove organism
			dragging.node.destroy();
			if (dragging.type === 'plant') {
				var idx = plants.indexOf(dragging.node);
				if (idx !== -1) plants.splice(idx, 1);
			} else if (dragging.type === 'herbivore') {
				var idx = herbivores.indexOf(dragging.node);
				if (idx !== -1) {
					// Remove from hunger queue if present
					var hqidx = herbivoreHungerQueue.indexOf(dragging.node);
					if (hqidx !== -1) {
						herbivoreHungerQueue.splice(hqidx, 1);
						// Next in queue (if any) becomes hungry
						for (var j = 0; j < herbivoreHungerQueue.length; j++) {
							var nextH = herbivoreHungerQueue[j];
							if (nextH && nextH.state === "waiting") {
								nextH.state = "hungry";
								nextH._hungerQueueState = "hungry";
								break;
							}
						}
					}
					herbivores.splice(idx, 1);
				}
			} else if (dragging.type === 'carnivore') {
				var idx = carnivores.indexOf(dragging.node);
				if (idx !== -1) carnivores.splice(idx, 1);
			} else if (dragging.type === 'pollinator') {
				var idx = pollinators.indexOf(dragging.node);
				if (idx !== -1) pollinators.splice(idx, 1);
			} else if (dragging.type === 'fungi') {
				var idx = fungis.indexOf(dragging.node);
				if (idx !== -1) fungis.splice(idx, 1);
			} else if (dragging.type === 'parasite') {
				var idx = parasites.indexOf(dragging.node);
				if (idx !== -1) parasites.splice(idx, 1);
			} else if (dragging.type === 'worm') {
				var idx = worms.indexOf(dragging.node);
				if (idx !== -1) worms.splice(idx, 1);
			}
		} else {
			// Place organism: snap alpha to 1
			dragging.node.alpha = 1;
			// If dropping a parasite, set state to 'seek' and detach from host if needed
			if (dragging.type === 'parasite') {
				// If attached, detach
				if (dragging.node.state === "attached") {
					if (dragging.node.attachedTo && dragging.node.attachedTo._parasiteAttached === dragging.node) {
						dragging.node.attachedTo._parasiteAttached = null;
					}
					dragging.node.attachedTo = null;
				}
				dragging.node.state = "seek";
				dragging.node.target = null;
			}
		}
		dragging = null;
	}
};
// --- Main Update Loop ---
game.update = function () {
	// Update all herbivores
	for (var i = herbivores.length - 1; i >= 0; i--) {
		var h = herbivores[i];
		if (h.eaten) {
			// Remove from hunger queue if present
			var idx = herbivoreHungerQueue.indexOf(h);
			if (idx !== -1) {
				herbivoreHungerQueue.splice(idx, 1);
				// Next in queue (if any) becomes hungry
				for (var j = 0; j < herbivoreHungerQueue.length; j++) {
					var nextH = herbivoreHungerQueue[j];
					if (nextH && nextH.state === "waiting") {
						nextH.state = "hungry";
						nextH._hungerQueueState = "hungry";
						break;
					}
				}
			}
			herbivores.splice(i, 1);
			continue;
		}
		if (h.update) h.update();
	}
	// Update all carnivores
	for (var i = carnivores.length - 1; i >= 0; i--) {
		var c = carnivores[i];
		if (c.eaten) {
			carnivores.splice(i, 1);
			continue;
		}
		if (c.update) c.update();
	}
	// Update all worms
	for (var i = worms.length - 1; i >= 0; i--) {
		var w = worms[i];
		if (w.update) w.update();
	}
	// In summer, randomly turn some healthy plants brown
	if (window.summerState) {
		for (var i = 0; i < plants.length; i++) {
			var p = plants[i];
			// Only affect healthy, non-brown, non-eaten plants
			if (!p.eaten && !p._isBrown) {
				// Smaller chance per frame (e.g. 0.0005 = ~0.05% per frame)
				if (Math.random() < 0.0005) {
					p._isBrown = true;
					if (p.plantAsset && typeof p.plantAsset.tint !== "undefined") {
						p.plantAsset.tint = 0x996633; // brown
					}
				}
			}
		}
	}
	// Clean up dead plants
	for (var i = plants.length - 1; i >= 0; i--) {
		var p = plants[i];
		if (p.eaten) {
			plants.splice(i, 1);
		}
	}
	// Update all seeds
	for (var i = seeds.length - 1; i >= 0; i--) {
		var s = seeds[i];
		if (s.eaten) {
			seeds.splice(i, 1);
			continue;
		}
		if (s.update) s.update();
	}
	;
	// Update all fungi
	for (var i = fungis.length - 1; i >= 0; i--) {
		var f = fungis[i];
		if (f.update) f.update();
	}
	// Update all fungi spores
	for (var i = fungiSpores.length - 1; i >= 0; i--) {
		var s = fungiSpores[i];
		if (!s.parent || !s._alive) {
			fungiSpores.splice(i, 1);
			continue;
		}
		if (s.update) s.update();
	}
	// Update all parasites
	for (var i = parasites.length - 1; i >= 0; i--) {
		var b = parasites[i];
		if (b.update) b.update();
	}
	// --- Update palette population counters ---
	for (var i = 0; i < paletteItems.length; i++) {
		var node = paletteItems[i];
		if (!node._popTxt) continue;
		var type = node.type;
		var popCount = 0;
		var maxCount = null;
		if (type === 'plant') {
			popCount = plants.length;
			maxCount = 20;
		} else if (type === 'herbivore') {
			popCount = herbivores.length;
			maxCount = 6;
		} else if (type === 'carnivore') {
			popCount = carnivores.length;
			maxCount = 4;
		} else if (type === 'pollinator') {
			popCount = pollinators.length;
			maxCount = 10;
		} else if (type === 'fungi') {
			popCount = fungis.length;
		} else if (type === 'parasite') {
			popCount = parasites.length;
			maxCount = 4;
		} else if (type === 'worm') {
			popCount = worms.length;
		}
		node._popTxt.setText("" + popCount);
		// Set counter color to red if at population control max, else black
		if (type === 'herbivore' && popCount >= 6 || type === 'pollinator' && popCount >= 10 || type === 'plant' && popCount >= 20 || type === 'carnivore' && popCount >= 4 || type === 'parasite' && popCount >= 4) {
			if (typeof node._popTxt.setStyle === "function") node._popTxt.setStyle({
				fill: "#c00"
			});
		} else {
			if (typeof node._popTxt.setStyle === "function") node._popTxt.setStyle({
				fill: "#000"
			});
		}
	}
	// --- Continuously keep randomize button disabled if organisms are present ---
	if (plants.length > 0 || herbivores.length > 0 || carnivores.length > 0 || pollinators.length > 0 || fungis.length > 0 || parasites.length > 0 || worms.length > 0) {
		randomizeBtn._disabled = true;
		randomizeBtnBox.color = 0xcc2222;
		if (typeof randomizeBtnBox.setStyle === "function") {
			randomizeBtnBox.setStyle({
				fill: "#fff"
			});
		}
		randomizeBtnTxt.setText("Randomized");
	} else {
		randomizeBtn._disabled = false;
		randomizeBtnBox.color = 0x228B22;
		if (typeof randomizeBtnBox.setStyle === "function") {
			randomizeBtnBox.setStyle({
				fill: "#fff"
			});
		}
		randomizeBtnTxt.setText("Randomize");
	}
};
// --- Instructions Text --- 
// --- Random seed spawning around the map if there are any plants ---
var randomSeedSpawnTimer = null;
function startRandomSeedSpawning() {
	if (randomSeedSpawnTimer !== null) return;
	randomSeedSpawnTimer = LK.setInterval(function () {
		// Only spawn if there are any plants
		if (plants.length > 0) {
			// 40% chance per interval to spawn a seed
			if (Math.random() < 0.4) {
				// Pick a random position inside the map area
				var minX = 124 + 60;
				var maxX = 124 + 1800 - 60;
				var minY = paletteY + 320 + 60;
				var maxY = paletteY + 320 + 2000 - 60;
				var sx = minX + Math.random() * (maxX - minX);
				var sy = minY + Math.random() * (maxY - minY);
				var seed = new Seed();
				seed.x = sx;
				seed.y = sy;
				seed.scaleX = 0.4;
				seed.scaleY = 0.4;
				seed.alpha = 1;
				seeds.push(seed);
				game.addChild(seed);
			}
		}
		// If no plants, stop spawning
		if (plants.length === 0 && randomSeedSpawnTimer !== null) {
			LK.clearInterval(randomSeedSpawnTimer);
			randomSeedSpawnTimer = null;
		}
	}, 120); // Try every 2 seconds
}
// Start random seed spawning at game start
startRandomSeedSpawning();
LK.playMusic('mellow', {
	loop: true
});
// --- Map Area Border (for visual feedback) ---
// Use a simple colored rectangle instead of a plant asset for the map border background
var mapBorder = LK.getAsset('box', {
	anchorX: 0,
	anchorY: 0,
	width: 1800,
	height: 2000,
	color: 0x2e8b57,
	shape: 'box'
});
mapBorder.alpha = 0.12;
game.addChild(mapBorder);
mapBorder.x = 124;
mapBorder.y = paletteY + 320;
// --- Add invisible border walls to prevent creatures from exiting the map area ---
var borderThickness = 40;
var borderAlpha = 0; // fully invisible
// Left border
var borderLeft = LK.getAsset('box', {
	anchorX: 0,
	anchorY: 0,
	width: borderThickness,
	height: 2000,
	color: 0x000000,
	shape: 'box'
});
borderLeft.alpha = borderAlpha;
game.addChild(borderLeft);
borderLeft.x = 124 - borderThickness;
borderLeft.y = paletteY + 320;
// Right border
var borderRight = LK.getAsset('box', {
	anchorX: 0,
	anchorY: 0,
	width: borderThickness,
	height: 2000,
	color: 0x000000,
	shape: 'box'
});
borderRight.alpha = borderAlpha;
game.addChild(borderRight);
borderRight.x = 124 + 1800;
borderRight.y = paletteY + 320;
// Top border
var borderTop = LK.getAsset('box', {
	anchorX: 0,
	anchorY: 0,
	width: 1800 + borderThickness * 2,
	height: borderThickness,
	color: 0x000000,
	shape: 'box'
});
borderTop.alpha = borderAlpha;
game.addChild(borderTop);
borderTop.x = 124 - borderThickness;
borderTop.y = paletteY + 320 - borderThickness;
// Bottom border
var borderBottom = LK.getAsset('box', {
	anchorX: 0,
	anchorY: 0,
	width: 1800 + borderThickness * 2,
	height: borderThickness,
	color: 0x000000,
	shape: 'box'
});
borderBottom.alpha = borderAlpha;
game.addChild(borderBottom);
borderBottom.x = 124 - borderThickness;
borderBottom.y = paletteY + 320 + 2000;
// --- End of Game Code ---; /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Carnivore class
var Carnivore = Container.expand(function () {
	var self = Container.call(this);
	// Uncommon: 15% chance to be resistant to parasites
	self.parasiteResistant = Math.random() < 0.15;
	var carnAsset = self.attachAsset('carnivore', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 1.25,
		scaleY: 1.25
	});
	self.target = null;
	// Assign base speed, will adjust for personality below
	self.speed = 1.5 + Math.random() * 1.2;
	self.eaten = false;
	self._chaseTime = 0; // How long we've been chasing a herbivore
	self._tired = false; // Are we tired?
	self._tiredTimer = 0; // How long left to rest
	// Track tired attempts per herbivore (herbivore.id -> count)
	self._tiredAttempts = {};
	// --- Personality system ---
	// Personalities: "normal", "bloodthirsty", "weak"
	var carnPersonalities = ["normal", "bloodthirsty", "weak"];
	var rand = Math.random();
	// Make random traits more common: 30% normal, 35% bloodthirsty, 35% weak
	if (rand < 0.3) {
		self.personality = "normal";
	} else if (rand < 0.65) {
		self.personality = "bloodthirsty";
	} else {
		self.personality = "weak";
	}
	// Adjust speed for bloodthirsty carnivores
	if (self.personality === "bloodthirsty") {
		self.speed += 0.7 + Math.random() * 0.5; // noticeably faster
	}
	// For weak carnivores, no speed change, but will tire faster in update logic
	// For weak: timer for running away from other carnivores
	self._weakRunTimer = 0;
	self._weakRunAngle = 0;
	// --- State management for wandering/hungry ---
	self.state = "hungry"; // "wandering" or "hungry"
	self._eatCooldown = 0; // frames left in wandering after eating
	self.update = function () {
		if (self.eaten) return;
		// --- CARNIVORES CANNOT STARVE: No starvation logic for carnivores ---
		// --- WINTER BEHAVIOR: Wanderlust, ignore herbivores, and cannot starve ---
		var isWinter = !!window.winterState;
		if (isWinter) {
			// Always wander, never chase or eat, never get tired, never starve
			self.state = "wandering";
			self.target = null;
			self._tired = false;
			self._tiredTimer = 0;
			self._chaseTime = 0;
			// Wander constantly
			if (!self._wanderTimer || self._wanderTimer <= 0) {
				var angle = Math.random() * Math.PI * 2;
				self._wanderAngle = angle;
				self._wanderTimer = 60 + Math.floor(Math.random() * 60);
			}
			if (typeof self._wanderAngle === "number") {
				self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
				self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
				self._wanderTimer--;
				// Keep inside map bounds (strictly)
				var minX = 124 + 60;
				var maxX = 124 + 1800 - 60;
				var minY = paletteY + 320 + 60;
				var maxY = paletteY + 320 + 2000 - 60;
				if (self.x < minX) self.x = minX;
				if (self.x > maxX) self.x = maxX;
				if (self.y < minY) self.y = minY;
				if (self.y > maxY) self.y = maxY;
			}
			return;
		}
		// --- Personality: weak carnivore runs from other carnivores, can be infected by fungi ---
		if (self.personality === "weak") {
			// If running away, keep running for a short time
			if (self._weakRunTimer > 0) {
				self.x += Math.cos(self._weakRunAngle) * self.speed * 1.5;
				self.y += Math.sin(self._weakRunAngle) * self.speed * 1.5;
				self._weakRunTimer--;
				// Clamp to map area
				var minX = 124 + 60;
				var maxX = 124 + 1800 - 60;
				var minY = paletteY + 320 + 60;
				var maxY = paletteY + 320 + 2000 - 60;
				if (self.x < minX) self.x = minX;
				if (self.x > maxX) self.x = maxX;
				if (self.y < minY) self.y = minY;
				if (self.y > maxY) self.y = maxY;
				// While running, don't do anything else
				return;
			}
			// Check for nearby other carnivores (not self)
			var nearestCarn = null;
			var minCarnDist = 999999;
			for (var ci = 0; ci < carnivores.length; ci++) {
				var c = carnivores[ci];
				if (c === self || c.eaten) continue;
				var dx = c.x - self.x;
				var dy = c.y - self.y;
				var dist = dx * dx + dy * dy;
				if (dist < minCarnDist) {
					minCarnDist = dist;
					nearestCarn = c;
				}
			}
			if (nearestCarn && Math.sqrt(minCarnDist) < 220) {
				// Run away from the other carnivore for 60-120 frames
				var dx = self.x - nearestCarn.x;
				var dy = self.y - nearestCarn.y;
				var angle = Math.atan2(dy, dx);
				self._weakRunAngle = angle;
				self._weakRunTimer = 60 + Math.floor(Math.random() * 60);
				// Move immediately this frame
				self.x += Math.cos(self._weakRunAngle) * self.speed * 1.5;
				self.y += Math.sin(self._weakRunAngle) * self.speed * 1.5;
				// Clamp to map area
				var minX = 124 + 60;
				var maxX = 124 + 1800 - 60;
				var minY = paletteY + 320 + 60;
				var maxY = paletteY + 320 + 2000 - 60;
				if (self.x < minX) self.x = minX;
				if (self.x > maxX) self.x = maxX;
				if (self.y < minY) self.y = minY;
				if (self.y > maxY) self.y = maxY;
				return;
			}
			// Weak carnivores can be infected by fungi (handled in Parasite/Fungi logic)
		}
		// Handle tired state
		// Bloodthirsty carnivores never get tired
		if (self.personality === "bloodthirsty") {
			self._tired = false;
			self._tiredTimer = 0;
		} else {
			if (self._tired) {
				self._tiredTimer--;
				if (self._tiredTimer <= 0) {
					self._tired = false;
					self._chaseTime = 0;
				}
				// While tired, don't chase or wander, just stand still
				return;
			}
		}
		// Handle eat cooldown (wandering after eating)
		if (self._eatCooldown > 0) {
			self._eatCooldown--;
			if (self._eatCooldown === 0) {
				self.state = "hungry";
			}
		}
		// State: wandering (ignore prey)
		if (self.state === "wandering") {
			self.target = null; // Don't chase
			// --- Random wandering when not chasing herbivores ---
			if (!self._wanderTimer || self._wanderTimer <= 0) {
				var angle = Math.random() * Math.PI * 2;
				self._wanderAngle = angle;
				self._wanderTimer = 60 + Math.floor(Math.random() * 60);
			}
			if (typeof self._wanderAngle === "number") {
				self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
				self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
				self._wanderTimer--;
				// Keep inside map bounds (strictly)
				var minX = 124 + 60;
				var maxX = 124 + 1800 - 60;
				var minY = paletteY + 320 + 60;
				var maxY = paletteY + 320 + 2000 - 60;
				if (self.x < minX) self.x = minX;
				if (self.x > maxX) self.x = maxX;
				if (self.y < minY) self.y = minY;
				if (self.y > maxY) self.y = maxY;
			}
			self._chaseTime = 0; // Not chasing, reset chase timer
			return;
		}
		// State: hungry (look for prey)
		if (self.state === "hungry") {
			// --- CARNIVORE POPULATION CONTROL: If at max, hunt less frequently ---
			if (typeof carnivores !== "undefined" && carnivores.length >= 4) {
				// Only hunt every 120 frames (2 seconds)
				if (typeof self._huntDelay === "undefined") self._huntDelay = Math.floor(Math.random() * 120);
				self._huntDelay++;
				if (self._huntDelay < 120) {
					// Wander instead of hunting
					self.state = "wandering";
					self._huntDelay = self._huntDelay % 120;
					return;
				}
				self._huntDelay = 0;
			}
			// Find nearest prey if not already targeting
			if (!self.target || self.target.eaten) {
				var minDist = 999999,
					closest = null;
				// --- Bloodthirsty: can hunt herbivores and other carnivores (except self) ---
				if (self.personality === "bloodthirsty") {
					// Hunt herbivores
					for (var i = 0; i < herbivores.length; i++) {
						var h = herbivores[i];
						if (h.eaten) continue;
						var dx = h.x - self.x,
							dy = h.y - self.y;
						var dist = dx * dx + dy * dy;
						if (dist < minDist) {
							minDist = dist;
							closest = h;
						}
					}
					// Hunt other carnivores (not self, not eaten)
					for (var i = 0; i < carnivores.length; i++) {
						var c = carnivores[i];
						if (c === self || c.eaten) continue;
						var dx = c.x - self.x,
							dy = c.y - self.y;
						var dist = dx * dx + dy * dy;
						if (dist < minDist) {
							minDist = dist;
							closest = c;
						}
					}
				} else if (self.personality === "weak") {
					// Weak carnivores do not hunt other carnivores, only herbivores
					for (var i = 0; i < herbivores.length; i++) {
						var h = herbivores[i];
						if (h.eaten) continue;
						// Ignore this herbivore if we've gotten tired chasing it 2 or more times this cycle
						if (h._uniqueId === undefined) {
							// Assign a unique id to each herbivore if not present
							h._uniqueId = "herb_" + Math.floor(Math.random() * 1e9) + "_" + Math.floor(Math.random() * 1e9);
						}
						if (self._tiredAttempts[h._uniqueId] >= 2) continue;
						var dx = h.x - self.x,
							dy = h.y - self.y;
						var dist = dx * dx + dy * dy;
						if (dist < minDist) {
							minDist = dist;
							closest = h;
						}
					}
				} else {
					// Normal: only hunt herbivores
					for (var i = 0; i < herbivores.length; i++) {
						var h = herbivores[i];
						if (h.eaten) continue;
						// Ignore this herbivore if we've gotten tired chasing it 2 or more times this cycle
						if (h._uniqueId === undefined) {
							// Assign a unique id to each herbivore if not present
							h._uniqueId = "herb_" + Math.floor(Math.random() * 1e9) + "_" + Math.floor(Math.random() * 1e9);
						}
						if (self._tiredAttempts[h._uniqueId] >= 2) continue;
						var dx = h.x - self.x,
							dy = h.y - self.y;
						var dist = dx * dx + dy * dy;
						if (dist < minDist) {
							minDist = dist;
							closest = h;
						}
					}
				}
				// (Carnivores ignore pollinators)
				self.target = closest;
			}
			// --- Random wandering when not chasing herbivores ---
			if ((!self.target || self.target.eaten) && (!self._wanderTimer || self._wanderTimer <= 0)) {
				var angle = Math.random() * Math.PI * 2;
				self._wanderAngle = angle;
				self._wanderTimer = 60 + Math.floor(Math.random() * 60);
			}
			if (!self.target || self.target.eaten) {
				if (typeof self._wanderAngle === "number") {
					self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
					self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
					self._wanderTimer--;
					var minX = 124 + 60;
					var maxX = 124 + 1800 - 60;
					var minY = paletteY + 320 + 60;
					var maxY = paletteY + 320 + 2000 - 60;
					if (self.x < minX) self.x = minX;
					if (self.x > maxX) self.x = maxX;
					if (self.y < minY) self.y = minY;
					if (self.y > maxY) self.y = maxY;
				}
				self._chaseTime = 0; // Not chasing, reset chase timer
			}
			// Move toward target herbivore
			if (self.target && !self.target.eaten) {
				var dx = self.target.x - self.x;
				var dy = self.target.y - self.y;
				var dist = Math.sqrt(dx * dx + dy * dy);
				if (dist > 1) {
					self.x += dx / dist * self.speed;
					self.y += dy / dist * self.speed;
				}
				// Track how long we've been chasing
				self._chaseTime++;
				// If we've been chasing for more than X seconds, get tired
				var chaseLimit = 360; // default 6 seconds
				var tiredDuration = 600; // default 10 seconds
				if (self.personality === "weak") {
					chaseLimit = 180; // 3 seconds for weak carnivores
					tiredDuration = 900; // weak carnivores rest longer (15 seconds)
				}
				if (self._chaseTime > chaseLimit) {
					self._tired = true;
					self._tiredTimer = tiredDuration;
					self._chaseTime = 0;
					// Track tired attempts for this herbivore
					if (self.target && self.target._uniqueId !== undefined) {
						if (!self._tiredAttempts[self.target._uniqueId]) self._tiredAttempts[self.target._uniqueId] = 0;
						self._tiredAttempts[self.target._uniqueId]++;
						// If tired 2 or more times, ignore this herbivore for the rest of the cycle
						if (self._tiredAttempts[self.target._uniqueId] >= 2) {
							self.target = null;
							self.state = "wandering";
						}
					}
					return;
				}
				// Eat target if close enough
				// Prevent eating in autumn
				if (dist < 60 && !self.target.eaten) {
					if (window.autumnState) {
						// In autumn, do not eat, just wander
						self.target = null;
						self.state = "wandering";
						self._eatCooldown = 3600;
						self._chaseTime = 0;
						return;
					}
					// --- Bloodthirsty: can eat other carnivores or herbivores ---
					// --- Normal/Weak: only eat herbivores ---
					var ateCarnivore = false;
					if (self.personality === "bloodthirsty" && carnivores.indexOf(self.target) !== -1 && self.target !== self) {
						// Eat other carnivore
						if (typeof self.target.die === "function") self.target.die();
						ateCarnivore = true;
					} else if (herbivores.indexOf(self.target) !== -1) {
						// Eat herbivore
						if (typeof self.target.die === "function") self.target.die();
					} else {
						// Not a valid target, do nothing
						self.target = null;
						return;
					}
					// Move away from the eaten target
					if (self.target) {
						var awayDX = self.x - self.target.x;
						var awayDY = self.y - self.target.y;
						var awayDist = Math.sqrt(awayDX * awayDX + awayDY * awayDY);
						if (awayDist > 0) {
							// Move 100px away in the opposite direction
							self.x += awayDX / awayDist * 100;
							self.y += awayDY / awayDist * 100;
							// Clamp to map area
							var minX = 124 + 60;
							var maxX = 124 + 1800 - 60;
							var minY = paletteY + 320 + 60;
							var maxY = paletteY + 320 + 2000 - 60;
							if (self.x < minX) self.x = minX;
							if (self.x > maxX) self.x = maxX;
							if (self.y < minY) self.y = minY;
							if (self.y > maxY) self.y = maxY;
						}
					}
					// Track herbivores/carnivores eaten for egg laying
					if (ateCarnivore) {
						self._herbivoresEaten = (self._herbivoresEaten || 0) + 1;
					} else {
						self._herbivoresEaten = (self._herbivoresEaten || 0) + 1;
					}
					// Lay an egg if 3 prey have been eaten, then reset counter
					// --- CARNIVORE POPULATION CONTROL: Only lay egg if < 4 carnivores ---
					if (self._herbivoresEaten >= 3) {
						if (typeof carnivores !== "undefined" && carnivores.length < 4) {
							var egg = new Egg();
							egg.x = self.x;
							egg.y = self.y;
							egg.scaleX = 0.5;
							egg.scaleY = 0.5;
							egg.alpha = 1;
							egg._isCarnivoreEgg = true;
							egg._carnivoreHatch = true;
							if (self.parent) self.parent.addChild(egg);
							if (typeof eggs !== "undefined") eggs.push(egg);
						}
						self._herbivoresEaten = 0;
					}
					self.target = null;
					self._chaseTime = 0; // Reset chase timer after eating
					// Animate carnivore "eating"
					tween(self, {
						scaleX: 1.2,
						scaleY: 1.2
					}, {
						duration: 120,
						easing: tween.easeOut,
						onFinish: function onFinish() {
							tween(self, {
								scaleX: 1,
								scaleY: 1
							}, {
								duration: 120,
								easing: tween.easeIn
							});
						}
					});
					// After eating, enter wandering state for 1 minute (3600 frames)
					self.state = "wandering";
					self._eatCooldown = 3600;
				}
			}
		} // end hungry state
	};
	// Carnivores are not eaten in this MVP
	return self;
});
// Egg class
var Egg = Container.expand(function () {
	var self = Container.call(this);
	// Always use carnivore_egg asset if this is a carnivore egg, pollinator_egg if pollinator, else normal egg
	var eggAsset;
	if (self._isCarnivoreEgg === true || self._carnivoreHatch === true) {
		eggAsset = self.attachAsset('carnivore_egg', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: 1,
			scaleY: 1
		});
	} else if (self._isPollinatorEgg === true || self._pollinatorHatch === true) {
		eggAsset = self.attachAsset('pollinator_egg', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: 1,
			scaleY: 1
		});
	} else {
		eggAsset = self.attachAsset('egg', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: 1,
			scaleY: 1
		});
	}
	self.hatched = false;
	self._hatchTimer = 420 + Math.floor(Math.random() * 180); // 7-10 seconds
	self.update = function () {
		if (self.hatched) return;
		// Pause hatching if it's summer or winter
		var isSummer = !!window.summerState;
		var isWinter = !!window.winterState;
		if (isSummer || isWinter) {
			// Do not decrement hatch timer, eggs are dormant
			return;
		}
		// --- POLLINATOR POPULATION CONTROL: Prevent pollinator eggs from hatching if there are already 10 pollinators ---
		if ((self._isPollinatorEgg || self._pollinatorHatch) && typeof pollinators !== "undefined" && pollinators.length >= 10) {
			// Do not decrement hatch timer, do not hatch, just wait
			return;
		}
		// --- CARNIVORE POPULATION CONTROL: Prevent carnivore eggs from hatching if there are already 4 carnivores ---
		if ((self._isCarnivoreEgg || self._carnivoreHatch) && typeof carnivores !== "undefined" && carnivores.length >= 4) {
			// Do not decrement hatch timer, do not hatch, just wait
			return;
		}
		self._hatchTimer--;
		// --- PARASITE POPULATION CONTROL: Prevent parasite eggs from hatching if there are already 4 parasites ---
		if ((self._isParasiteEgg || self._parasiteHatch) && typeof parasites !== "undefined" && parasites.length >= 4) {
			// Do not decrement hatch timer, do not hatch, just wait
			return;
		}
		// --- HERBIVORE POPULATION CONTROL: Prevent herbivore eggs from hatching if there are already 6 herbivores ---
		if (!self._isCarnivoreEgg && !self._carnivoreHatch && !self._isPollinatorEgg && !self._pollinatorHatch && !self._isParasiteEgg && !self._parasiteHatch && typeof herbivores !== "undefined" && herbivores.length >= 6) {
			// Do not decrement hatch timer, do not hatch, just wait
			return;
		}
		if (self._hatchTimer <= 0) {
			// In autumn, eggs have a reduced chance to hatch (e.g. 60% hatch, 40% fail)
			if (window.autumnState && Math.random() < 0.4) {
				// Egg fails to hatch, animate and destroy
				self.eaten = true;
				tween(self, {
					scaleX: 0,
					scaleY: 0,
					alpha: 0
				}, {
					duration: 200,
					easing: tween.easeIn,
					onFinish: function onFinish() {
						self.destroy();
					}
				});
				return;
			}
			self.hatched = true;
			// Animate egg hatching
			tween(self, {
				scaleX: 1.2,
				scaleY: 1.2,
				alpha: 0.5
			}, {
				duration: 200,
				easing: tween.easeOut,
				onFinish: function onFinish() {
					// Spawn a new carnivore if this is a carnivore egg, pollinator if pollinator egg, parasite if parasite egg, otherwise herbivore
					var popSnd = LK.getSound('Hatch');
					if (self._isCarnivoreEgg && self._carnivoreHatch) {
						var carn = new Carnivore();
						carn.x = self.x;
						carn.y = self.y;
						carn.scaleX = 1;
						carn.scaleY = 1;
						carn.alpha = 1;
						if (self.parent) self.parent.addChild(carn);
						if (typeof carnivores !== "undefined") carnivores.push(carn);
						if (popSnd && typeof popSnd.play === "function") popSnd.play();
					} else if (self._isPollinatorEgg && self._pollinatorHatch) {
						var poll = new Pollinator();
						poll.x = self.x;
						poll.y = self.y;
						poll.scaleX = 1;
						poll.scaleY = 1;
						poll.alpha = 1;
						// Reset pollinator starve timer on hatch
						poll._starveTimer = 3000 + Math.floor(Math.random() * 1200);
						// Set pollinator to hungry state after hatching
						poll.state = "hungry";
						poll.target = null;
						if (self.parent) self.parent.addChild(poll);
						if (typeof pollinators !== "undefined") pollinators.push(poll);
						if (popSnd && typeof popSnd.play === "function") popSnd.play();
					} else if (self._isParasiteEgg && self._parasiteHatch) {
						// If this egg was laid by a parasite attached to a resistant host, always inherit resistance
						var inheritResistance = false;
						if (typeof self._parentHost !== "undefined" && self._parentHost && self._parentHost.parasiteResistant === true) {
							inheritResistance = true;
						}
						var parasite = new Parasite();
						parasite.x = self.x;
						parasite.y = self.y;
						parasite.scaleX = 1;
						parasite.scaleY = 1;
						parasite.alpha = 1;
						if (inheritResistance) {
							parasite.parasiteResistant = true;
						}
						if (self.parent) self.parent.addChild(parasite);
						if (typeof parasites !== "undefined") parasites.push(parasite);
						if (popSnd && typeof popSnd.play === "function") popSnd.play();
					} else {
						// Spawn a new Nummer at this position
						var herb = new Nummer();
						herb._uniqueId = "herb_" + Math.floor(Math.random() * 1e9) + "_" + Math.floor(Math.random() * 1e9);
						herb.x = self.x;
						herb.y = self.y;
						herb.scaleX = 1;
						herb.scaleY = 1;
						herb.alpha = 1;
						// If this egg was laid by a parasite attached to a resistant host, always inherit resistance
						if (typeof self._parentHost !== "undefined" && self._parentHost && self._parentHost.parasiteResistant === true) {
							herb.parasiteResistant = true;
						}
						if (self.parent) self.parent.addChild(herb);
						herbivores.push(herb);
						if (popSnd && typeof popSnd.play === "function") popSnd.play();
					}
					self.destroy();
				}
			});
		}
	};
	return self;
});
// Fungi class
var Fungi = Container.expand(function () {
	var self = Container.call(this);
	// Track the cycle the fungi was created in
	self._bornCycle = typeof cycleCount !== "undefined" ? cycleCount : 0;
	// Use fungi asset
	var fungiAsset = self.attachAsset('fungi', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Fungi AI: shoot spores at nearby herbivores
	self._sporeCooldown = 0;
	self.update = function () {
		// Fungi lifespan removed: fungi no longer die after 1 cycle
		// Only shoot if cooldown is 0
		if (self._sporeCooldown > 0) {
			self._sporeCooldown--;
			return;
		}
		// --- FUNGI POPULATION CONTROL: Prevent infecting with spores if 20 or more fungi ---
		if (typeof fungis !== "undefined" && fungis.length >= 20) {
			return;
		}
		// Find nearest herbivore within 400px
		var minDist = 999999,
			closest = null;
		for (var i = 0; i < herbivores.length; i++) {
			var h = herbivores[i];
			if (h.eaten || h.spored) continue;
			var dx = h.x - self.x,
				dy = h.y - self.y;
			var dist = dx * dx + dy * dy;
			if (dist < minDist && Math.sqrt(dist) < 400) {
				minDist = dist;
				closest = h;
			}
		}
		if (closest) {
			// Shoot a spore at the herbivore
			var spore = new FungiSpore();
			spore.x = self.x;
			spore.y = self.y;
			spore.target = closest;
			game.addChild(spore);
			if (!fungiSpores) fungiSpores = [];
			fungiSpores.push(spore);
			self._sporeCooldown = 120 + Math.floor(Math.random() * 60); // 2-3 seconds cooldown
		}
	};
	// Track if this fungi is currently 'blocked' from respawning after being eaten
	self._blockedRespawn = false;
	// Add die method so fungi disappear when eaten
	self.die = function () {
		if (self.eaten) return;
		self.eaten = true;
		// Animate shrink and fade out, then destroy
		tween(self, {
			scaleX: 0,
			scaleY: 0,
			alpha: 0
		}, {
			duration: 200,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				self.destroy();
			}
		});
	};
	return self;
});
// Nummer class (formerly Herbivore)
var Nummer = Container.expand(function () {
	var self = Container.call(this);
	// Uncommon: 15% chance to be resistant to parasites
	self.parasiteResistant = Math.random() < 0.15;
	// Track if this Nummer was hit by a spore
	self.spored = false;
	var herbAsset = self.attachAsset('herbivore', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.target = null;
	self.speed = 1.2 + Math.random() * 1.0;
	self.eaten = false;
	// Track number of plants eaten for egg laying
	self._plantsEaten = 0;
	// --- State management for hungry/sleepy ---
	self.state = "hungry"; // "hungry" or "sleepy"
	self._sleepTimer = 0; // frames left in sleepy state
	// --- Starvation timer: die if not eating for 2 cycles (80 seconds = 4800 frames) ---
	self._starveTimer = 4800; // 80 seconds at 60fps
	// --- Personality system ---
	// Personalities: "normal", "curious", "grumpy"
	var personalities = ["normal", "curious", "grumpy"];
	// Assign a random personality at creation
	var rand = Math.random();
	// Make random traits more common: 30% normal, 35% curious, 35% grumpy
	if (rand < 0.3) {
		self.personality = "normal";
	} else if (rand < 0.65) {
		self.personality = "curious";
	} else {
		self.personality = "grumpy";
	}
	// For curious: timer for following pollinators
	self._curiousFollowTimer = 0;
	self._curiousPollinatorTarget = null;
	// For grumpy: scare cooldown
	self._grumpyScareCooldown = 0;
	self.update = function () {
		if (self.eaten) return;
		// --- HERBIVORE HUNGER QUEUE LOGIC ---
		// Only 2 herbivores can be in "hungry" state at a time. Others must wait in "waiting" state.
		if (!self._hungerQueueState) self._hungerQueueState = "unset"; // "unset", "waiting", "hungry"
		if (self.state === "hungry" && self._hungerQueueState !== "hungry") {
			// Try to enter the hunger queue
			if (herbivoreHungerQueue.indexOf(self) === -1) {
				herbivoreHungerQueue.push(self);
			}
			// If not in the first 2, set to waiting
			if (herbivoreHungerQueue[0] !== self && herbivoreHungerQueue[1] !== self) {
				self._hungerQueueState = "waiting";
				self.state = "waiting";
				// Don't do hungry logic this frame
			} else {
				self._hungerQueueState = "hungry";
				// Continue as hungry
			}
		} else if (self.state === "waiting" && self._hungerQueueState !== "waiting") {
			// Enter waiting queue if not already
			if (herbivoreHungerQueue.indexOf(self) === -1) {
				herbivoreHungerQueue.push(self);
			}
			// If now in first 2, become hungry
			if (herbivoreHungerQueue[0] === self || herbivoreHungerQueue[1] === self) {
				self.state = "hungry";
				self._hungerQueueState = "hungry";
			} else {
				self._hungerQueueState = "waiting";
				// Don't do hungry logic this frame
			}
		} else if (self.state === "hungry" && (herbivoreHungerQueue[0] === self || herbivoreHungerQueue[1] === self)) {
			self._hungerQueueState = "hungry";
		} else if (self.state === "hungry" && herbivoreHungerQueue.indexOf(self) > 1) {
			// If somehow in hungry state but not allowed, set to waiting
			self.state = "waiting";
			self._hungerQueueState = "waiting";
		}
		// If in waiting state, just wander
		if (self.state === "waiting") {
			// --- Random wandering ---
			if (!self._wanderTimer || self._wanderTimer <= 0) {
				var angle = Math.random() * Math.PI * 2;
				self._wanderAngle = angle;
				self._wanderTimer = 60 + Math.floor(Math.random() * 60);
			}
			if (typeof self._wanderAngle === "number") {
				self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
				self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
				self._wanderTimer--;
				// Keep inside map bounds (strictly)
				var minX = 124 + 60;
				var maxX = 124 + 1800 - 60;
				var minY = paletteY + 320 + 60;
				var maxY = paletteY + 320 + 2000 - 60;
				if (self.x < minX) self.x = minX;
				if (self.x > maxX) self.x = maxX;
				if (self.y < minY) self.y = minY;
				if (self.y > maxY) self.y = maxY;
			}
			// Don't do hungry logic
			return;
		}
		// --- HERBIVORE RANDOM SOUND LOGIC ---
		// Only make sound if not eaten and not in winter (optional: you can allow in winter if desired)
		if (typeof self._nextHerbSoundTimer === "undefined") {
			// Set initial timer to random 6-10 seconds (360-600 frames)
			self._nextHerbSoundTimer = 360 + Math.floor(Math.random() * 241);
		}
		if (self._nextHerbSoundTimer > 0) {
			self._nextHerbSoundTimer--;
		} else {
			// Play the 'Herbivore' sound
			var snd = LK.getSound('Herbivore');
			if (snd && typeof snd.play === "function") snd.play();
			// Reset timer to next random interval (6-10 seconds)
			self._nextHerbSoundTimer = 360 + Math.floor(Math.random() * 241);
		}
		// --- WINTER BEHAVIOR: Move slower, avoid eating, and halt starvation meter ---
		var isWinter = !!window.winterState;
		var originalSpeed = self.speed;
		if (isWinter) {
			// Move slower in winter
			self.speed = originalSpeed * 0.4;
		} else {
			self.speed = originalSpeed;
		}
		// Starvation logic: decrement timer if alive and hungry/wandering, but not in winter
		if ((self.state === "hungry" || self.state === "wandering") && !isWinter) {
			self._starveTimer--;
			if (self._starveTimer <= 0 && !self.eaten) {
				// Starve and die
				self.die();
				return;
			}
		}
		// Handle infected state
		if (self.infected) {
			self.infectedTimer = (self.infectedTimer || 0) + 1;
			// Future: add infected behavior here (e.g. slow, animation, etc)
		}
		// If infection was pending from summer, and now it's not summer, apply infection
		if (self._pendingFungiInfection && !window.summerState) {
			self._pendingFungiInfection = false;
			self.infected = true;
			self.infectedTimer = 0;
			// Tint permanently purple
			tween(self, {
				tint: 0xbb88ff
			}, {
				duration: 80
			});
		}
		// Handle sleepy state
		// If just left hungry state (became wandering or sleepy), remove from hunger queue and allow next in queue to become hungry
		if ((self.state === "wandering" || self.state === "sleepy") && self._hungerQueueState === "hungry") {
			var idx = herbivoreHungerQueue.indexOf(self);
			if (idx !== -1) {
				herbivoreHungerQueue.splice(idx, 1);
			}
			self._hungerQueueState = "unset";
			// Next in queue (if any) becomes hungry
			for (var i = 0; i < herbivoreHungerQueue.length; i++) {
				var h = herbivoreHungerQueue[i];
				if (h && h.state === "waiting") {
					h.state = "hungry";
					h._hungerQueueState = "hungry";
					break;
				}
			}
		}
		if (self.state === "sleepy") {
			// Check for nearby carnivore and possibly wake up
			var nearestCarn = null;
			var minCarnDist = 999999;
			for (var ci = 0; ci < carnivores.length; ci++) {
				var carn = carnivores[ci];
				if (carn.eaten) continue;
				var cdx = carn.x - self.x;
				var cdy = carn.y - self.y;
				var cdist = cdx * cdx + cdy * cdy;
				if (cdist < minCarnDist) {
					minCarnDist = cdist;
					nearestCarn = carn;
				}
			}
			// If carnivore is within 300px, 50% chance to wake up and run away
			if (nearestCarn && Math.sqrt(minCarnDist) < 300) {
				// Only try to wake up once per frame if still sleepy
				if (!self._triedWakeThisFrame) {
					self._triedWakeThisFrame = true;
					if (Math.random() < 0.5) {
						// Wake up and run away from carnivore
						self.state = "hungry";
						// Move away from carnivore immediately
						var dx = self.x - nearestCarn.x;
						var dy = self.y - nearestCarn.y;
						var dist = Math.sqrt(dx * dx + dy * dy);
						if (dist > 1) {
							// Move a burst away (3x speed for one frame)
							self.x += dx / dist * (self.speed * 3);
							self.y += dy / dist * (self.speed * 3);
						}
						// Clamp to map area
						var minX = 124 + 60;
						var maxX = 124 + 1800 - 60;
						var minY = paletteY + 320 + 60;
						var maxY = paletteY + 320 + 2000 - 60;
						if (self.x < minX) self.x = minX;
						if (self.x > maxX) self.x = maxX;
						if (self.y < minY) self.y = minY;
						if (self.y > maxY) self.y = maxY;
						// Don't continue sleeping
						return;
					}
				}
			} else {
				self._triedWakeThisFrame = false;
			}
			self._sleepTimer--;
			if (self._sleepTimer <= 0) {
				self.state = "wandering";
				self._wanderAfterSleepTimer = 600; // 10 seconds at 60fps
			}
			// While sleepy, don't move or seek food
			return;
		}
		// Wandering state after sleep: ignore plants, just wander for 10s, then become hungry
		if (self.state === "wandering") {
			if (typeof self._wanderAfterSleepTimer === "undefined") self._wanderAfterSleepTimer = 600;
			self._wanderAfterSleepTimer--;
			// --- Random wandering ---
			if (!self._wanderTimer || self._wanderTimer <= 0) {
				var angle = Math.random() * Math.PI * 2;
				self._wanderAngle = angle;
				self._wanderTimer = 60 + Math.floor(Math.random() * 60);
			}
			if (typeof self._wanderAngle === "number") {
				self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
				self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
				self._wanderTimer--;
				// Keep inside map bounds (strictly)
				var minX = 124 + 60;
				var maxX = 124 + 1800 - 60;
				var minY = paletteY + 320 + 60;
				var maxY = paletteY + 320 + 2000 - 60;
				if (self.x < minX) self.x = minX;
				if (self.x > maxX) self.x = maxX;
				if (self.y < minY) self.y = minY;
				if (self.y > maxY) self.y = maxY;
			}
			if (self._wanderAfterSleepTimer <= 0) {
				self.state = "hungry";
			}
			return;
		}
		// Only seek food if hungry
		if (self.state === "hungry") {
			var isWinter = !!window.winterState;
			// --- PERSONALITY: CURIOUS ---
			// If curious, sometimes follow pollinators for a few seconds
			if (self.personality === "curious") {
				// If not already following, 1% chance per frame to start following a pollinator
				if (self._curiousFollowTimer <= 0 && Math.random() < 0.01 && pollinators.length > 0) {
					// Pick a random pollinator to follow
					var idx = Math.floor(Math.random() * pollinators.length);
					var poll = pollinators[idx];
					if (poll && !poll.eaten) {
						self._curiousPollinatorTarget = poll;
						self._curiousFollowTimer = 120 + Math.floor(Math.random() * 120); // 2-4 seconds
					}
				}
				// If following a pollinator
				if (self._curiousFollowTimer > 0 && self._curiousPollinatorTarget && !self._curiousPollinatorTarget.eaten) {
					var dx = self._curiousPollinatorTarget.x - self.x;
					var dy = self._curiousPollinatorTarget.y - self.y;
					var dist = Math.sqrt(dx * dx + dy * dy);
					if (dist > 1) {
						self.x += dx / dist * self.speed;
						self.y += dy / dist * self.speed;
					}
					self._curiousFollowTimer--;
					// Clamp to map area
					var minX = 124 + 60;
					var maxX = 124 + 1800 - 60;
					var minY = paletteY + 320 + 60;
					var maxY = paletteY + 320 + 2000 - 60;
					if (self.x < minX) self.x = minX;
					if (self.x > maxX) self.x = maxX;
					if (self.y < minY) self.y = minY;
					if (self.y > maxY) self.y = maxY;
					// If timer runs out or pollinator is gone, stop following
					if (self._curiousFollowTimer <= 0 || self._curiousPollinatorTarget.eaten) {
						self._curiousFollowTimer = 0;
						self._curiousPollinatorTarget = null;
					}
					// While following, do not seek plants
					return;
				}
				// If not following, proceed as normal below
			}
			// --- PERSONALITY: GRUMPY ---
			// If grumpy, check for carnivore within 120px and scare it away if it is targeting this herbivore
			if (self.personality === "grumpy" && self._grumpyScareCooldown <= 0) {
				for (var ci = 0; ci < carnivores.length; ci++) {
					var carn = carnivores[ci];
					if (carn.eaten) continue;
					var dx = carn.x - self.x;
					var dy = carn.y - self.y;
					var dist = Math.sqrt(dx * dx + dy * dy);
					// If carnivore is close and targeting this herbivore
					// Bloodthirsty carnivores are not scared of grumpy herbivores
					if (dist < 120 && carn.target === self && !carn._tired && carn.personality !== "bloodthirsty") {
						// Scare the carnivore away: set it to wandering, clear its target, and make it tired
						carn.state = "wandering";
						carn.target = null;
						carn._tired = true;
						carn._tiredTimer = 300 + Math.floor(Math.random() * 200); // 5-8 seconds
						carn._chaseTime = 0;
						// Grumpy herbivore enters a short cooldown before it can scare again
						self._grumpyScareCooldown = 300; // 5 seconds
						// Optional: animate the herbivore (e.g. scale up briefly)
						tween(self, {
							scaleX: 1.3,
							scaleY: 1.3
						}, {
							duration: 80,
							easing: tween.easeOut,
							onFinish: function onFinish() {
								tween(self, {
									scaleX: 1,
									scaleY: 1
								}, {
									duration: 80,
									easing: tween.easeIn
								});
							}
						});
						break;
					}
				}
			}
			if (self._grumpyScareCooldown > 0) self._grumpyScareCooldown--;
			// --- END PERSONALITY LOGIC ---
			// Normal hungry logic
			// In winter, do not seek or eat plants, but wander randomly
			if (isWinter) {
				// Wander only, do not target plants
				self.target = null;
				// --- Random wandering in winter ---
				if (!self._wanderTimer || self._wanderTimer <= 0) {
					var angle = Math.random() * Math.PI * 2;
					self._wanderAngle = angle;
					self._wanderTimer = 60 + Math.floor(Math.random() * 60);
				}
				if (typeof self._wanderAngle === "number") {
					self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
					self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
					self._wanderTimer--;
					// Keep inside map bounds (strictly)
					var minX = 124 + 60;
					var maxX = 124 + 1800 - 60;
					var minY = paletteY + 320 + 60;
					var maxY = paletteY + 320 + 2000 - 60;
					if (self.x < minX) self.x = minX;
					if (self.x > maxX) self.x = maxX;
					if (self.y < minY) self.y = minY;
					if (self.y > maxY) self.y = maxY;
				}
			} else {
				// Always target the nearest plant when hungry
				var minDist = 999999,
					closest = null;
				for (var i = 0; i < plants.length; i++) {
					var p = plants[i];
					if (p.eaten) continue;
					var dx = p.x - self.x,
						dy = p.y - self.y;
					var dist = dx * dx + dy * dy;
					if (dist < minDist) {
						minDist = dist;
						closest = p;
					}
				}
				self.target = closest;
			}
			// Nummer can walk over fungi as if it is not there: do not treat fungi as obstacles, so do not check for collision or avoid them at all in movement logic.
			// Check for nearest carnivore
			var nearestCarn = null;
			var minCarnDist = 999999;
			var tiredCarnivore = null;
			var tiredCarnDist = 999999;
			for (var ci = 0; ci < carnivores.length; ci++) {
				var carn = carnivores[ci];
				if (carn.eaten) continue;
				var cdx = carn.x - self.x;
				var cdy = carn.y - self.y;
				var cdist = cdx * cdx + cdy * cdy;
				if (cdist < minCarnDist) {
					minCarnDist = cdist;
					nearestCarn = carn;
				}
				// Track tired carnivore chasing this herbivore
				if (carn._tired && carn.target === self && cdist < tiredCarnDist) {
					tiredCarnivore = carn;
					tiredCarnDist = cdist;
				}
			}
			var carnivoreTooClose = false;
			var carnDist = 0;
			var runAwayDX = 0,
				runAwayDY = 0;
			if (nearestCarn) {
				carnDist = Math.sqrt((nearestCarn.x - self.x) * (nearestCarn.x - self.x) + (nearestCarn.y - self.y) * (nearestCarn.y - self.y));
				if (nearestCarn._tired && nearestCarn.target === self) {
					// If a tired carnivore was chasing this herbivore, teleport a tiny distance in front of it (away from carnivore)
					// Only teleport once per tired state
					if (!self._teleportedFromTiredCarnivore) {
						var dx = self.x - nearestCarn.x;
						var dy = self.y - nearestCarn.y;
						var dist = Math.sqrt(dx * dx + dy * dy);
						if (dist < 200) {
							// Only teleport if not already far away
							// Teleport 80px away in the direction away from carnivore
							var teleportDist = 80;
							var tx = nearestCarn.x + dx / (dist || 1) * teleportDist;
							var ty = nearestCarn.y + dy / (dist || 1) * teleportDist;
							// Clamp to map area
							var minX = 124 + 60;
							var maxX = 124 + 1800 - 60;
							var minY = paletteY + 320 + 60;
							var maxY = paletteY + 320 + 2000 - 60;
							if (tx < minX) tx = minX;
							if (tx > maxX) tx = maxX;
							if (ty < minY) ty = minY;
							if (ty > maxY) ty = maxY;
							self.x = tx;
							self.y = ty;
						}
						self._teleportedFromTiredCarnivore = true;
						// After teleport, set a run away timer so it keeps running for a while
						self._runAwayFromTiredCarnivoreTimer = 60 + Math.floor(Math.random() * 60); // 1-2 seconds
						// Pick a run direction directly away from carnivore
						if (dist > 0) {
							self._runAwayAngle = Math.atan2(dy, dx);
						} else {
							self._runAwayAngle = Math.random() * Math.PI * 2;
						}
					}
					carnivoreTooClose = true;
					runAwayDX = self.x - nearestCarn.x;
					runAwayDY = self.y - nearestCarn.y;
				} else if (carnDist < 300) {
					// If carnivore is within 300px, run away
					carnivoreTooClose = true;
					runAwayDX = self.x - nearestCarn.x;
					runAwayDY = self.y - nearestCarn.y;
					// Reset teleport flag if not being chased by tired carnivore
					self._teleportedFromTiredCarnivore = false;
				}
			}
			// --- New: If a tired carnivore was chasing this herbivore, charge away until far enough ---
			// (Removed barrier logic: herbivores can always run away from tired carnivores)
			if (carnivoreTooClose && carnDist > 1) {
				// If running from a tired carnivore and we have a run timer, keep running in the set direction
				if (typeof self._runAwayFromTiredCarnivoreTimer !== "undefined" && self._runAwayFromTiredCarnivoreTimer > 0) {
					self.x += Math.cos(self._runAwayAngle) * self.speed * 2.2;
					self.y += Math.sin(self._runAwayAngle) * self.speed * 2.2;
					self._runAwayFromTiredCarnivoreTimer--;
					// Clamp to map area
					var minX = 124 + 60;
					var maxX = 124 + 1800 - 60;
					var minY = paletteY + 320 + 60;
					var maxY = paletteY + 320 + 2000 - 60;
					if (self.x < minX) self.x = minX;
					if (self.x > maxX) self.x = maxX;
					if (self.y < minY) self.y = minY;
					if (self.y > maxY) self.y = maxY;
					// When timer runs out, clear teleport/run state so it can look for food again
					if (self._runAwayFromTiredCarnivoreTimer <= 0) {
						self._runAwayFromTiredCarnivoreTimer = 0;
						self._teleportedFromTiredCarnivore = false;
					}
					// While running, do not seek food
					return;
				} else {
					// Run away from carnivore (normal, not tired chase)
					self.x += runAwayDX / carnDist * (self.speed * 1.5);
					self.y += runAwayDY / carnDist * (self.speed * 1.5);
					// Reset teleport/run state if not running from tired carnivore
					self._teleportedFromTiredCarnivore = false;
					self._runAwayFromTiredCarnivoreTimer = 0;
				}
			} else {
				// --- Random wandering when not chasing plant ---
				if ((!self.target || self.target.eaten) && (!self._wanderTimer || self._wanderTimer <= 0)) {
					// Pick a new random direction every 60-120 frames
					var angle = Math.random() * Math.PI * 2;
					self._wanderAngle = angle;
					self._wanderTimer = 60 + Math.floor(Math.random() * 60);
				}
				if (!self.target || self.target.eaten) {
					// Wander in the chosen direction
					if (typeof self._wanderAngle === "number") {
						self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
						self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
						self._wanderTimer--;
						// Keep inside map bounds (strictly)
						var minX = 124 + 60;
						var maxX = 124 + 1800 - 60;
						var minY = paletteY + 320 + 60;
						var maxY = paletteY + 320 + 2000 - 60;
						if (self.x < minX) self.x = minX;
						if (self.x > maxX) self.x = maxX;
						if (self.y < minY) self.y = minY;
						if (self.y > maxY) self.y = maxY;
					}
				}
				// Move toward target plant
				if (self.target && !self.target.eaten) {
					var isWinter = !!window.winterState;
					var dx = self.target.x - self.x;
					var dy = self.target.y - self.y;
					var dist = Math.sqrt(dx * dx + dy * dy);
					if (dist > 1) {
						self.x += dx / dist * self.speed;
						self.y += dy / dist * self.speed;
					}
					// Eat plant if close enough, but not in winter
					if (!isWinter && dist < 60 && !self.target.eaten) {
						var eatenPlant = self.target;
						// Play chomp sound when a herbivore eats a plant
						var chompSnd = LK.getSound('Chomp');
						if (chompSnd && typeof chompSnd.play === "function") chompSnd.play();
						self.target.die();
						self.target = null;
						// Animate Nummer "eating"
						tween(self, {
							scaleX: 1.2,
							scaleY: 1.2
						}, {
							duration: 120,
							easing: tween.easeOut,
							onFinish: function onFinish() {
								tween(self, {
									scaleX: 1,
									scaleY: 1
								}, {
									duration: 120,
									easing: tween.easeIn
								});
							}
						});
						// After eating, enter sleepy state for 10 seconds (600 frames) with a chance to skip sleep
						if (Math.random() < 0.7) {
							// 70% chance to sleep, 30% chance to skip
							self.state = "sleepy";
							self._sleepTimer = 600;
						} else {
							// Skip sleep, go straight to wandering
							self.state = "wandering";
							self._wanderAfterSleepTimer = 600; // 10 seconds wandering
						}
						// Reset starvation timer after eating only if plant is not brown
						if (!(eatenPlant && eatenPlant._isBrown)) {
							self._starveTimer = 4800; // 80 seconds at 60fps
						}
						// Increment plants eaten counter
						self._plantsEaten = (self._plantsEaten || 0) + 1;
						// Lay an egg if 4 plants have been eaten, then reset counter
						// --- HERBIVORE POPULATION CONTROL: Only lay egg if < 6 herbivores ---
						if (self._plantsEaten >= 4) {
							if (typeof herbivores !== "undefined" && herbivores.length < 6) {
								var egg = new Egg();
								egg.x = self.x;
								egg.y = self.y;
								egg.scaleX = 0.5;
								egg.scaleY = 0.5;
								egg.alpha = 1;
								if (self.parent) self.parent.addChild(egg);
								if (typeof eggs !== "undefined") eggs.push(egg);
							}
							self._plantsEaten = 0;
						}
					}
				}
			}
		}
	};
	// Called when eaten by carnivore
	self.die = function (_onFinish) {
		if (self.eaten) return;
		self.eaten = true;
		// Remove from hunger queue if present
		var idx = herbivoreHungerQueue.indexOf(self);
		if (idx !== -1) {
			herbivoreHungerQueue.splice(idx, 1);
		}
		// If infected, spawn a fungi at this position
		// --- FUNGI POPULATION CONTROL: Prevent dropping fungi at death if 20 or more fungi ---
		if (self.infected && (typeof fungis === "undefined" || fungis.length < 20)) {
			var newFungi = new Fungi();
			// If fungi is spawned by Nummer death, set its _bornCycle to the next cycle so it lives a full cycle
			if (typeof cycleCount !== "undefined") {
				newFungi._bornCycle = cycleCount + 1;
			}
			newFungi.x = self.x;
			newFungi.y = self.y;
			newFungi.scaleX = 1;
			newFungi.scaleY = 1;
			newFungi.alpha = 1;
			if (self.parent) self.parent.addChild(newFungi);
			if (typeof fungis !== "undefined") fungis.push(newFungi);
		}
		tween(self, {
			scaleX: 0,
			scaleY: 0,
			alpha: 0
		}, {
			duration: 400,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				self.destroy();
				if (_onFinish) _onFinish();
			}
		});
	};
	// Called when hit by a spore
	self.sporeHit = function () {
		if (self.spored) return; // Only allow once
		self.spored = true;
		// If it's summer, delay infection until next winter or spring
		if (window.summerState) {
			// Mark as pending infection, but do not infect yet
			self._pendingFungiInfection = true;
			// Optionally, you could tint a different color to show pending state, or do nothing
			return;
		}
		// Enter infected state immediately if not summer
		self.infected = true;
		self.infectedTimer = 0;
		// Tint permanently purple
		tween(self, {
			tint: 0xbb88ff
		}, {
			duration: 80
		});
	};
	return self;
});
// Parasite class (seeks and attaches to herbivores or carnivores)
var Parasite = Container.expand(function () {
	var self = Container.call(this);
	var parasiteAsset = self.attachAsset('Parasite', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.5,
		scaleY: 0.5
	});
	// State: "seek", "attached"
	self.state = "seek";
	self.target = null;
	self.attachedTo = null;
	self.offsetX = 0;
	self.offsetY = 0;
	self.speed = 1.5 + Math.random() * 0.7;
	// Track last intersecting for attach logic
	self._lastIntersecting = false;
	self.update = function () {
		// If attached, follow the host
		if (self.state === "attached" && self.attachedTo) {
			// AUTUMN: Detach immediately in autumn
			if (window.autumnState) {
				// Detach from host
				if (self.attachedTo._parasiteAttached === self) {
					self.attachedTo._parasiteAttached = null;
				}
				self.state = "seek";
				self.attachedTo = null;
				self.target = null;
				self._wanderTimer = 0;
				// Allow laying an egg only once per parasite in autumn
				if (!self._laidAutumnEgg) {
					var egg = new Egg();
					egg.x = self.x;
					egg.y = self.y;
					egg.scaleX = 0.5;
					egg.scaleY = 0.5;
					egg.alpha = 1;
					egg._isParasiteEgg = true;
					egg._parasiteHatch = true;
					if (self.parent) self.parent.addChild(egg);
					if (typeof eggs !== "undefined") eggs.push(egg);
					self._laidAutumnEgg = true;
				}
				return;
			}
			// If host is eaten, parasite dies with host
			if (self.attachedTo.eaten) {
				// Animate parasite dying and remove from array
				tween(self, {
					scaleX: 0,
					scaleY: 0,
					alpha: 0
				}, {
					duration: 200,
					easing: tween.easeIn,
					onFinish: function onFinish() {
						self.destroy();
						// Remove from parasites array if present
						if (typeof parasites !== "undefined") {
							var idx = parasites.indexOf(self);
							if (idx !== -1) parasites.splice(idx, 1);
						}
					}
				});
				return;
			}
			// If host is a herbivore and is infected by shrooms, let go immediately
			if (typeof self.attachedTo.spored !== "undefined" && self.attachedTo.spored === true) {
				// Detach from host
				if (self.attachedTo._parasiteAttached === self) {
					self.attachedTo._parasiteAttached = null;
				}
				self.state = "seek";
				self.attachedTo = null;
				self.target = null;
				// Wander in a new random direction
				self._wanderTimer = 0;
				return;
			}
			// Stay at the same offset from host
			self.x = self.attachedTo.x + self.offsetX;
			self.y = self.attachedTo.y + self.offsetY;
			// --- Parasite lays an egg every cycle if attached to a host, but only if < 4 parasites ---
			if (typeof self._lastCycle === "undefined") self._lastCycle = -1;
			if (typeof cycleCount !== "undefined" && self._lastCycle !== cycleCount) {
				self._lastCycle = cycleCount;
				if (typeof parasites !== "undefined" && parasites.length < 4) {
					// Lay a parasite egg at current position
					var egg = new Egg();
					egg.x = self.x;
					egg.y = self.y;
					egg.scaleX = 0.5;
					egg.scaleY = 0.5;
					egg.alpha = 1;
					egg._isParasiteEgg = true;
					egg._parasiteHatch = true;
					// Pass parent host resistance to egg for inheritance
					if (self.attachedTo && self.attachedTo.parasiteResistant === true) {
						egg._parentHost = self.attachedTo;
					}
					if (self.parent) self.parent.addChild(egg);
					if (typeof eggs !== "undefined") eggs.push(egg);
				}
			}
			return;
		}
		// If seeking, look for nearest herbivore or carnivore
		if (self.state === "seek") {
			// In autumn, cannot infect, so just wander
			if (window.autumnState) {
				// Wander randomly if no target
				if (!self._wanderTimer || self._wanderTimer <= 0) {
					self._wanderAngle = Math.random() * Math.PI * 2;
					self._wanderTimer = 60 + Math.floor(Math.random() * 60);
				}
				if (typeof self._wanderAngle === "number") {
					self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
					self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
					self._wanderTimer--;
					// Keep inside map bounds
					var minX = 124 + 60;
					var maxX = 124 + 1800 - 60;
					var minY = paletteY + 320 + 60;
					var maxY = paletteY + 320 + 2000 - 60;
					if (self.x < minX) self.x = minX;
					if (self.x > maxX) self.x = maxX;
					if (self.y < minY) self.y = minY;
					if (self.y > maxY) self.y = maxY;
				}
				self._lastIntersecting = false;
				return;
			}
			// If no target or target is eaten or already has a parasite attached (not self), find new target
			if (!self.target || self.target.eaten || self.target._parasiteAttached && self.target._parasiteAttached !== self) {
				var minDist = 999999,
					closest = null;
				// Search herbivores first
				for (var i = 0; i < herbivores.length; i++) {
					var h = herbivores[i];
					if (h.eaten) continue;
					// Only attach if not already parasitized
					if (h._parasiteAttached) continue;
					// Avoid targeting spore-infected herbivores
					if (h.spored === true) continue;
					// Avoid parasite-resistant herbivores
					if (h.parasiteResistant === true) continue;
					var dx = h.x - self.x,
						dy = h.y - self.y;
					var dist = dx * dx + dy * dy;
					if (dist < minDist) {
						minDist = dist;
						closest = h;
					}
				}
				// If no herbivore, search carnivores
				if (!closest) {
					for (var i = 0; i < carnivores.length; i++) {
						var c = carnivores[i];
						if (c.eaten) continue;
						if (c._parasiteAttached) continue;
						// Only infect weak carnivores (personality === "weak")
						if (c.personality !== "weak") continue;
						// Avoid parasite-resistant carnivores
						if (c.parasiteResistant === true) continue;
						var dx = c.x - self.x,
							dy = c.y - self.y;
						var dist = dx * dx + dy * dy;
						if (dist < minDist) {
							minDist = dist;
							closest = c;
						}
					}
				}
				self.target = closest;
			}
			// If we have a target, move toward it
			if (self.target && !self.target.eaten && !self.target._parasiteAttached) {
				var dx = self.target.x - self.x;
				var dy = self.target.y - self.y;
				var dist = Math.sqrt(dx * dx + dy * dy);
				if (dist > 1) {
					self.x += dx / dist * self.speed;
					self.y += dy / dist * self.speed;
				}
				// Attach if close enough and not already attached
				var isIntersecting = self.intersects(self.target);
				if (!self._lastIntersecting && isIntersecting && !self.target._parasiteAttached) {
					// Attach to host
					self.state = "attached";
					self.attachedTo = self.target;
					// Store offset so parasite stays visually attached
					self.offsetX = self.x - self.attachedTo.x;
					self.offsetY = self.y - self.attachedTo.y;
					// Mark host as parasitized
					self.attachedTo._parasiteAttached = self;
				}
				self._lastIntersecting = isIntersecting;
			} else {
				// Wander randomly if no target
				if (!self._wanderTimer || self._wanderTimer <= 0) {
					self._wanderAngle = Math.random() * Math.PI * 2;
					self._wanderTimer = 60 + Math.floor(Math.random() * 60);
				}
				if (typeof self._wanderAngle === "number") {
					self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
					self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
					self._wanderTimer--;
					// Keep inside map bounds
					var minX = 124 + 60;
					var maxX = 124 + 1800 - 60;
					var minY = paletteY + 320 + 60;
					var maxY = paletteY + 320 + 2000 - 60;
					if (self.x < minX) self.x = minX;
					if (self.x > maxX) self.x = maxX;
					if (self.y < minY) self.y = minY;
					if (self.y > maxY) self.y = maxY;
				}
				self._lastIntersecting = false;
			}
		}
	};
	return self;
});
// Plant class
var Plant = Container.expand(function () {
	var self = Container.call(this);
	var plantAsset = self.attachAsset('plant', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.plantAsset = plantAsset; // Expose for tinting
	self._canDie = true; // Track if plant can die
	// Plants are static, but we can animate them when eaten
	self.eaten = false;
	// Track the cycle the plant was created in
	self._bornCycle = typeof cycleCount !== "undefined" ? cycleCount : 0;
	self.die = function (_onFinish2) {
		if (self.eaten) return;
		if (self._canDie === false) return; // Prevent dying if not allowed
		self.eaten = true;
		tween(self, {
			scaleX: 0,
			scaleY: 0,
			alpha: 0
		}, {
			duration: 400,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				self.destroy();
				if (_onFinish2) _onFinish2();
			}
		});
	};
	// Plants die after 1 cycle
	self.update = function () {
		if (self.eaten) return;
		// --- Summer: chance to turn brown and become unpollinatable ---
		if (self._invulnerable) {
			// While invulnerable, never turn brown or die
			self._isBrown = false;
			if (self.plantAsset && typeof self.plantAsset.tint !== "undefined") {
				self.plantAsset.tint = 0xffffff;
			}
		} else {
			if ((window.summerState || window.springState) && !self._isBrown && !self.eaten) {
				// Only roll once per plant per summer or spring
				if (typeof self._brownChecked === "undefined" || self._brownChecked !== cycleCount) {
					self._brownChecked = cycleCount;
					if (window.summerState && Math.random() < 0.12) {
						// ~12% chance per cycle in summer
						self._isBrown = true;
						if (self.plantAsset && typeof self.plantAsset.tint !== "undefined") {
							self.plantAsset.tint = 0x996633; // brown
						}
					} else if (window.springState && Math.random() < 0.002) {
						// ~0.2% chance per cycle in spring (VERY low)
						self._isBrown = true;
						if (self.plantAsset && typeof self.plantAsset.tint !== "undefined") {
							self.plantAsset.tint = 0x996633; // brown
						}
					}
				}
			}
			// If not summer, reset brown state
			if (!window.summerState && self._isBrown) {
				self._isBrown = false;
				if (self.plantAsset && typeof self.plantAsset.tint !== "undefined") {
					self.plantAsset.tint = 0xffffff;
				}
			}
			// Only die if at least one full cycle has passed since birth
			if (typeof cycleCount !== "undefined" && typeof self._bornCycle !== "undefined") {
				// Brown plants in summer: die after 1/2 cycle (shorter lifespan)
				if (self._isBrown && window.summerState && self._canDie !== false) {
					if (cycleCount > self._bornCycle + 0.5) {
						self.die();
					}
				} else if (cycleCount > self._bornCycle + 1 && self._canDie !== false) {
					self.die();
				}
			}
		}
	};
	return self;
});
// Pollinator class
var Pollinator = Container.expand(function () {
	var self = Container.call(this);
	var pollAsset = self.attachAsset('pollinator', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// --- Pollinator Starvation Logic ---
	self.state = "seek"; // "seek", "scatter", "planting", "hungry"
	self.target = null;
	self.speed = 2 + Math.random();
	self._scatterTimer = 0;
	self._scatterAngle = 0;
	self._plantSeedTimer = 0;
	self._hasSeed = true;
	self.eaten = false;
	self.lastWasTouchingPlant = false;
	// --- Pollinator Starve Timer ---
	self._starveTimer = 3000 + Math.floor(Math.random() * 1200); // 1 cycle = 50s = 3000 frames, randomize a bit
	self._lastCycle = typeof cycleCount !== "undefined" ? cycleCount : 0;
	// --- Pollination counter for egg laying ---
	self._pollinations = 0;
	self._layingEgg = false;
	self._eggObj = null;
	// --- After eating shroom, next pollination is a shroom ---
	self._nextPollinationIsShroom = false;
	self._didShroomPollination = false;
	self.update = function () {
		if (self.eaten) return;
		// --- POLLINATOR STARVATION LOGIC (handled in constructor patch above) ---
		// --- POLLINATOR HUNGRY STATE: Seek fungi and eat if hungry ---
		if (self.state === "hungry") {
			// Prevent pollinators from eating fungi during autumn, winter, and summer
			var isAutumn = !!window.autumnState;
			var isWinter = !!window.winterState;
			var isSummer = !!window.summerState;
			if (isAutumn || isWinter || isSummer) {
				// Just wander randomly, do not seek or eat fungi, and do not decrement starve timer
				if (!self._wanderTimer || self._wanderTimer <= 0) {
					self._wanderAngle = Math.random() * Math.PI * 2;
					self._wanderTimer = 60 + Math.floor(Math.random() * 60);
				}
				if (typeof self._wanderAngle === "number") {
					self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
					self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
					self._wanderTimer--;
				}
				// Clamp to map area
				var minX = 124 + 60;
				var maxX = 124 + 1800 - 60;
				var minY = paletteY + 320 + 60;
				var maxY = paletteY + 320 + 2000 - 60;
				if (self.x < minX) self.x = minX;
				if (self.x > maxX) self.x = maxX;
				if (self.y < minY) self.y = minY;
				if (self.y > maxY) self.y = maxY;
				return;
			}
			// Randomly (1 in 8 chance per frame) pick a new fungi to seek, or keep current
			if (!self.target || self.target.eaten || Math.random() < 0.125) {
				// Find nearest fungi
				var minDist = 999999,
					closest = null;
				for (var i = 0; i < fungis.length; i++) {
					var f = fungis[i];
					if (f.eaten) continue;
					var dx = f.x - self.x,
						dy = f.y - self.y;
					var dist = dx * dx + dy * dy;
					if (dist < minDist) {
						minDist = dist;
						closest = f;
					}
				}
				self.target = closest;
			}
			// Move toward fungi if any
			if (self.target && !self.target.eaten) {
				var dx = self.target.x - self.x,
					dy = self.target.y - self.y;
				var dist = Math.sqrt(dx * dx + dy * dy);
				if (dist > 1) {
					self.x += dx / dist * self.speed;
					self.y += dy / dist * self.speed;
				}
				// Eat fungi if close enough
				if (dist < 60 && !self.target.eaten) {
					// Play chomp sound when pollinator eats fungi
					var chompSnd = LK.getSound('Chomp');
					if (chompSnd && typeof chompSnd.play === "function") chompSnd.play();
					// Track how many times this fungi has been eaten by pollinators
					if (typeof self.target._pollinatorEatCount === "undefined") {
						self.target._pollinatorEatCount = 0;
					}
					self.target._pollinatorEatCount++;
					// If eaten 3 times, do nothing (fungi does not disappear anymore)
					if (self.target._pollinatorEatCount >= 3) {
						// Fungi no longer disappears after being eaten 3 times
						// Optionally, you could add a visual effect or reset the counter, but do nothing here
					}
					// Reset starve timer
					self._starveTimer = 3000 + Math.floor(Math.random() * 1200);
					// After eating, return to normal pollinator state
					self.state = "seek";
					self.target = null;
					// Set flag so next pollination is a shroom
					self._nextPollinationIsShroom = true;
					self._didShroomPollination = false;
					// Animate pollinator "eating"
					tween(self, {
						scaleX: 1.2,
						scaleY: 1.2
					}, {
						duration: 120,
						easing: tween.easeOut,
						onFinish: function onFinish() {
							tween(self, {
								scaleX: 1,
								scaleY: 1
							}, {
								duration: 120,
								easing: tween.easeIn
							});
						}
					});
					return;
				}
			} else {
				// If no fungi, wander randomly
				if (!self._wanderTimer || self._wanderTimer <= 0) {
					self._wanderAngle = Math.random() * Math.PI * 2;
					self._wanderTimer = 60 + Math.floor(Math.random() * 60);
				}
				if (typeof self._wanderAngle === "number") {
					self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
					self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
					self._wanderTimer--;
				}
			}
			// Clamp to map area
			var minX = 124 + 60;
			var maxX = 124 + 1800 - 60;
			var minY = paletteY + 320 + 60;
			var maxY = paletteY + 320 + 2000 - 60;
			if (self.x < minX) self.x = minX;
			if (self.x > maxX) self.x = maxX;
			if (self.y < minY) self.y = minY;
			if (self.y > maxY) self.y = maxY;
			return;
		}
		// --- POLLINATOR STARVATION: decrement timer unless hibernating or in autumn, winter, or summer ---
		var isAutumn = !!window.autumnState;
		var isWinter = !!window.winterState;
		var isSummer = !!window.summerState;
		if (!(typeof pollinatorsHibernating !== "undefined" && pollinatorsHibernating) && !isAutumn && !isWinter && !isSummer) {
			// Only decrement if not hibernating and not in autumn, winter, or summer
			self._starveTimer--;
			if (self._starveTimer <= 0 && !self.eaten) {
				// Die of starvation!
				self.eaten = true;
				tween(self, {
					scaleX: 0,
					scaleY: 0,
					alpha: 0
				}, {
					duration: 200,
					easing: tween.easeIn,
					onFinish: function onFinish() {
						self.destroy();
					}
				});
				return;
			}
		}
		// --- POLLINATOR HUNGRY STATE: If timer is low, become hungry and seek fungi ---
		if (self.state !== "hungry" && self._starveTimer < 900) {
			self.state = "hungry";
			self.target = null;
		}
		// --- If pollinator eats fungi, reset timer ---
		self._tryEatFungi = function () {
			// Find nearest fungi
			var minDist = 999999,
				closest = null;
			for (var i = 0; i < fungis.length; i++) {
				var f = fungis[i];
				if (f.eaten) continue;
				var dx = f.x - self.x,
					dy = f.y - self.y;
				var dist = dx * dx + dy * dy;
				if (dist < minDist) {
					minDist = dist;
					closest = f;
				}
			}
			if (closest) {
				self.target = closest;
				var dx = closest.x - self.x,
					dy = closest.y - self.y;
				var dist = Math.sqrt(dx * dx + dy * dy);
				if (dist > 1) {
					self.x += dx / dist * self.speed;
					self.y += dy / dist * self.speed;
				}
				// Eat fungi if close enough
				if (dist < 60 && !closest.eaten) {
					if (typeof closest.die === "function") closest.die();
					// Reset starve timer
					self._starveTimer = 3000 + Math.floor(Math.random() * 1200);
					// After eating, return to normal pollinator state
					self.state = "seek";
					self.target = null;
					// Animate pollinator "eating"
					tween(self, {
						scaleX: 1.2,
						scaleY: 1.2
					}, {
						duration: 120,
						easing: tween.easeOut,
						onFinish: function onFinish() {
							tween(self, {
								scaleX: 1,
								scaleY: 1
							}, {
								duration: 120,
								easing: tween.easeIn
							});
						}
					});
					return true;
				}
			}
			return false;
		};
		// --- POLLINATOR ACTIVE/NONACTIVE BEHAVIOR ---
		// If more than 5 pollinators, only 3 are 'active' and make sound, others are 'nonactive'
		if (typeof pollinators !== "undefined" && pollinators.length > 5) {
			// Assign active/nonactive roles once per frame for all pollinators
			if (typeof window._activePollinatorIds === "undefined") window._activePollinatorIds = [];
			// Only recalculate once per frame
			if (typeof window._activePollinatorFrame !== "number" || window._activePollinatorFrame !== LK.ticks) {
				// Pick 3 unique random pollinators to be active
				var ids = [];
				var pool = [];
				for (var i = 0; i < pollinators.length; i++) {
					if (!pollinators[i].eaten) pool.push(i);
				}
				// Shuffle pool
				for (var i = pool.length - 1; i > 0; i--) {
					var j = Math.floor(Math.random() * (i + 1));
					var tmp = pool[i];
					pool[i] = pool[j];
					pool[j] = tmp;
				}
				ids = pool.slice(0, 3);
				window._activePollinatorIds = ids;
				window._activePollinatorFrame = LK.ticks;
			}
			// Set self.activeBehavior based on selection
			var myIdx = -1;
			for (var i = 0; i < pollinators.length; i++) {
				if (pollinators[i] === self) {
					myIdx = i;
					break;
				}
			}
			self.behavior = window._activePollinatorIds.indexOf(myIdx) !== -1 ? "active" : "nonactive";
		} else {
			// If 5 or fewer, all are active
			self.behavior = "active";
		}
		// --- POLLINATOR NOISE: Play sound at random intervals, only if active ---
		// Nonactive pollinators are incapable of making sound unless population is reduced to 3 or fewer
		if (typeof self._nextNoiseTimer === "undefined") {
			// Set initial timer to random 1-4 seconds (60-240 frames)
			self._nextNoiseTimer = 60 + Math.floor(Math.random() * 180);
		}
		if (self._nextNoiseTimer > 0) {
			self._nextNoiseTimer--;
		} else {
			var canMakeSound = false;
			if (typeof pollinators !== "undefined" && pollinators.length <= 3) {
				// All pollinators can make sound if population is 3 or fewer
				canMakeSound = true;
			} else if (self.behavior === "active") {
				// Only active pollinators can make sound if more than 3
				canMakeSound = true;
			}
			if (canMakeSound && !(typeof pollinatorsHibernating !== "undefined" && pollinatorsHibernating)) {
				// Play the 'Bug' sound
				var snd = LK.getSound('Bug');
				if (snd && typeof snd.play === "function") snd.play();
			}
			// Reset timer to next random interval (1-4 seconds)
			self._nextNoiseTimer = 60 + Math.floor(Math.random() * 180);
		}
		// --- HIBERNATION: If background is white, pollinators do nothing, don't move, don't die, don't act ---
		if (typeof pollinatorsHibernating !== "undefined" && pollinatorsHibernating) {
			// Do not decrement lifetime, do not move, do not die, do not lay eggs, do not plant seeds
			return;
		}
		// If currently laying an egg, wait for egg to hatch before continuing
		if (self._layingEgg && self._eggObj) {
			// If it's summer or winter, eggs will not hatch, so pollinator should move away and continue pollinating
			var isSummer = !!window.summerState;
			var isWinter = !!window.winterState;
			if (isSummer || isWinter) {
				// Move away from the egg and resume pollinating
				if (self._eggObj) {
					// Move pollinator a bit away from the egg (random direction)
					var angle = Math.random() * Math.PI * 2;
					self.x += Math.cos(angle) * 80;
					self.y += Math.sin(angle) * 80;
					// Clamp to map area
					var minX = 124 + 60;
					var maxX = 124 + 1800 - 60;
					var minY = paletteY + 320 + 60;
					var maxY = paletteY + 320 + 2000 - 60;
					if (self.x < minX) self.x = minX;
					if (self.x > maxX) self.x = maxX;
					if (self.y < minY) self.y = minY;
					if (self.y > maxY) self.y = maxY;
				}
				self._eggObj = null;
				self._layingEgg = false;
				self._pollinations = 0; // Reset counter
				// Resume pollinating
				self.state = "seek";
				self.target = null;
				// Continue with rest of update
			} else {
				// Wait for egg to hatch, then continue pollinating
				if (self._eggObj.hatched) {
					// Spawn a new pollinator at egg position
					var newPoll = new Pollinator();
					newPoll.x = self._eggObj.x;
					newPoll.y = self._eggObj.y;
					newPoll.scaleX = 1;
					newPoll.scaleY = 1;
					newPoll.alpha = 1;
					if (self.parent) self.parent.addChild(newPoll);
					if (typeof pollinators !== "undefined") pollinators.push(newPoll);
					// Remove egg from global eggs array
					var idx = eggs.indexOf(self._eggObj);
					if (idx !== -1) eggs.splice(idx, 1);
					self._eggObj.destroy();
					self._eggObj = null;
					self._layingEgg = false;
					self._pollinations = 0; // Reset counter
				} else {
					// Wait for egg to hatch, do nothing else
					return;
				}
			}
		}
		// SEEK: Find nearest plant and move to it, but run from carnivores if close
		if (self.state === "seek") {
			// Check for nearest carnivore
			var nearestCarn = null;
			var minCarnDist = 999999;
			for (var ci = 0; ci < carnivores.length; ci++) {
				var carn = carnivores[ci];
				if (carn.eaten) continue;
				var cdx = carn.x - self.x;
				var cdy = carn.y - self.y;
				var cdist = cdx * cdx + cdy * cdy;
				if (cdist < minCarnDist) {
					minCarnDist = cdist;
					nearestCarn = carn;
				}
			}
			var carnivoreTooClose = false;
			var carnDist = 0;
			var runAwayDX = 0,
				runAwayDY = 0;
			if (nearestCarn) {
				carnDist = Math.sqrt((nearestCarn.x - self.x) * (nearestCarn.x - self.x) + (nearestCarn.y - self.y) * (nearestCarn.y - self.y));
				if (carnDist < 220) {
					// Run if carnivore is within 220px
					carnivoreTooClose = true;
					runAwayDX = self.x - nearestCarn.x;
					runAwayDY = self.y - nearestCarn.y;
				}
			}
			if (carnivoreTooClose && carnDist > 1) {
				// Run away from carnivore (burst speed)
				self.x += runAwayDX / carnDist * (self.speed * 2.2);
				self.y += runAwayDY / carnDist * (self.speed * 2.2);
			} else {
				// Find nearest plant
				if (!self.target || self.target.eaten) {
					var minDist = 999999,
						closest = null;
					for (var i = 0; i < plants.length; i++) {
						var p = plants[i];
						if (p.eaten) continue;
						// Ignore brown plants in summer
						if (window.summerState && p._isBrown) continue;
						var dx = p.x - self.x,
							dy = p.y - self.y;
						var dist = dx * dx + dy * dy;
						if (dist < minDist) {
							minDist = dist;
							closest = p;
						}
					}
					self.target = closest;
				}
				// Move toward target plant
				if (self.target && !self.target.eaten) {
					var dx = self.target.x - self.x;
					var dy = self.target.y - self.y;
					var dist = Math.sqrt(dx * dx + dy * dy);
					if (dist > 1) {
						self.x += dx / dist * self.speed;
						self.y += dy / dist * self.speed;
					}
					// Check for touching plant (within 60px)
					var isTouching = dist < 60;
					if (!self.lastWasTouchingPlant && isTouching) {
						// If plant is brown, skip and immediately seek a new healthy plant
						if (self.target && self.target._isBrown) {
							// Find next healthy plant (not brown, not eaten)
							var minDist2 = 999999,
								closest2 = null;
							for (var j = 0; j < plants.length; j++) {
								var p2 = plants[j];
								if (p2.eaten) continue;
								if (window.summerState && p2._isBrown) continue;
								var dx2 = p2.x - self.x,
									dy2 = p2.y - self.y;
								var dist2 = dx2 * dx2 + dy2 * dy2;
								if (dist2 < minDist2) {
									minDist2 = dist2;
									closest2 = p2;
								}
							}
							self.target = closest2;
							// Do not pollinate, just move on
							self.lastWasTouchingPlant = isTouching;
							return;
						}
						// Just touched plant
						// --- Pollinate a shroom instead of a plant if flag is set ---
						// (Removed: pollinators no longer spawn fungi or delete shrooms)
						if (self._nextPollinationIsShroom && !self._didShroomPollination) {
							self._didShroomPollination = true;
							self._nextPollinationIsShroom = false;
							// After pollinating a shroom, next pollination is normal
							self.state = "scatter";
							self._scatterTimer = 60 + Math.floor(Math.random() * 60); // 1-2 seconds
							self._scatterAngle = Math.random() * Math.PI * 2;
							self.lastWasTouchingPlant = isTouching;
							return;
						}
						self._pollinations = (self._pollinations || 0) + 1;
						// If pollinated 3 times, lay an egg and continue pollinating (do not wait for egg to hatch)
						if (self._pollinations >= 3 && !self._layingEgg) {
							// In autumn, pollinators do NOT lay eggs, just pollinate and continue
							if (window.autumnState) {
								self._pollinations = 0; // Reset pollination counter in autumn
								self.state = "scatter";
								self._scatterTimer = 60 + Math.floor(Math.random() * 60); // 1-2 seconds
								self._scatterAngle = Math.random() * Math.PI * 2;
								self.lastWasTouchingPlant = isTouching;
								return;
							}
							// --- POLLINATOR POPULATION CONTROL: Only lay egg if < 10 pollinators ---
							// --- FERN POPULATION CONTROL: Only lay egg if < 20 ferns (plants) ---
							if (typeof pollinators !== "undefined" && pollinators.length >= 10 || typeof plants !== "undefined" && plants.length >= 20) {
								// Do not lay egg, just reset pollination counter and scatter
								self._pollinations = 0;
								self.state = "scatter";
								self._scatterTimer = 60 + Math.floor(Math.random() * 60);
								self._scatterAngle = Math.random() * Math.PI * 2;
								self.lastWasTouchingPlant = isTouching;
								return;
							}
							// Lay a pollinator egg at current position
							var egg = new Egg();
							egg.x = self.x;
							egg.y = self.y;
							egg.scaleX = 0.5;
							egg.scaleY = 0.5;
							egg.alpha = 1;
							egg._isPollinatorEgg = true;
							egg._pollinatorHatch = true;
							if (self.parent) self.parent.addChild(egg);
							if (typeof eggs !== "undefined") eggs.push(egg);
							// Reset pollination counter and continue pollinating
							self._pollinations = 0;
							// Set pollinator to hungry state after laying an egg
							self.state = "hungry";
							self.target = null;
							self.lastWasTouchingPlant = isTouching;
							return;
						}
						self.state = "scatter";
						self._scatterTimer = 60 + Math.floor(Math.random() * 60); // 1-2 seconds
						self._scatterAngle = Math.random() * Math.PI * 2;
					}
					self.lastWasTouchingPlant = isTouching;
				} else {
					// No plant to go to, wander randomly
					if (!self._wanderTimer || self._wanderTimer <= 0) {
						self._wanderAngle = Math.random() * Math.PI * 2;
						self._wanderTimer = 60 + Math.floor(Math.random() * 60);
					}
					if (typeof self._wanderAngle === "number") {
						self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
						self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
						self._wanderTimer--;
					}
				}
			}
		}
		// SCATTER: Move in a random direction for a short time
		else if (self.state === "scatter") {
			self.x += Math.cos(self._scatterAngle) * self.speed * 2;
			self.y += Math.sin(self._scatterAngle) * self.speed * 2;
			self._scatterTimer--;
			if (self._scatterTimer <= 0) {
				self.state = "planting";
				self._plantSeedTimer = 30 + Math.floor(Math.random() * 30); // short pause before planting
			}
		}
		// PLANTING: Pause, then plant a seed
		else if (self.state === "planting") {
			self._plantSeedTimer--;
			if (self._plantSeedTimer <= 0 && self._hasSeed) {
				// Place a seed at current position
				var seed = new Seed();
				seed.x = self.x;
				seed.y = self.y;
				seed.scaleX = 0.4;
				seed.scaleY = 0.4;
				seed.alpha = 1;
				seeds.push(seed);
				if (self.parent) self.parent.addChild(seed);
				// Play plop sound when pollinator places a seed
				var plopSnd = LK.getSound('Plop');
				if (plopSnd && typeof plopSnd.play === "function") plopSnd.play();
				self._hasSeed = false;
				// After planting, look for another plant
				self.state = "seek";
				self.target = null;
				self._hasSeed = true;
			}
		}
		// Keep inside map bounds
		var minX = 124 + 60;
		var maxX = 124 + 1800 - 60;
		var minY = paletteY + 320 + 60;
		var maxY = paletteY + 320 + 2000 - 60;
		if (self.x < minX) self.x = minX;
		if (self.x > maxX) self.x = maxX;
		if (self.y < minY) self.y = minY;
		if (self.y > maxY) self.y = maxY;
	};
	self.die = function () {
		if (self.eaten) return;
		self.eaten = true;
		tween(self, {
			scaleX: 0,
			scaleY: 0,
			alpha: 0
		}, {
			duration: 200,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				self.destroy();
			}
		});
	};
	return self;
});
// Seed class
var Seed = Container.expand(function () {
	var self = Container.call(this);
	// Use dedicated brown seed asset
	var seedAsset = self.attachAsset('seed', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.4,
		scaleY: 0.4
	});
	self.growing = false;
	self.eaten = false;
	self._growTimer = 600; // 10 seconds at 60fps
	self.update = function () {
		if (self.eaten) return;
		if (!self.growing) {
			self._growTimer--;
			// --- FERN POPULATION CONTROL: If 20 or more ferns, seed always fails to germinate ---
			if (typeof plants !== "undefined" && plants.length >= 20) {
				// 100% fail to germinate
				self.eaten = true;
				tween(self, {
					scaleX: 0,
					scaleY: 0,
					alpha: 0
				}, {
					duration: 200,
					easing: tween.easeIn,
					onFinish: function onFinish() {
						self.destroy();
					}
				});
				return;
			}
			if (self._growTimer <= 0) {
				// --- 30% chance for seed to not germinate and disappear ---
				if (Math.random() < 0.3) {
					self.eaten = true;
					tween(self, {
						scaleX: 0,
						scaleY: 0,
						alpha: 0
					}, {
						duration: 200,
						easing: tween.easeIn,
						onFinish: function onFinish() {
							self.destroy();
						}
					});
					return;
				}
				// --- Summer or Autumn state: chance for seed to fail germination and disappear ---
				if (window.summerState && Math.random() < 0.4) {
					// 40% chance to fail in summer, just disappear
					self.eaten = true;
					tween(self, {
						scaleX: 0,
						scaleY: 0,
						alpha: 0
					}, {
						duration: 200,
						easing: tween.easeIn,
						onFinish: function onFinish() {
							self.destroy();
						}
					});
					return;
				} else if (window.autumnState && Math.random() < 0.55) {
					// 55% chance to fail in autumn, just disappear
					self.eaten = true;
					tween(self, {
						scaleX: 0,
						scaleY: 0,
						alpha: 0
					}, {
						duration: 200,
						easing: tween.easeIn,
						onFinish: function onFinish() {
							self.destroy();
						}
					});
					return;
				}
				self.growing = true;
				// Animate seed growing into plant
				tween(self, {
					scaleX: 1,
					scaleY: 1,
					alpha: 0.7
				}, {
					duration: 300,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						// Play grow sound when seed germinates
						var growSnd = LK.getSound('Grow');
						if (growSnd && typeof growSnd.play === "function") growSnd.play();
						// Replace seed with a new plant at same position
						var newPlant = new Plant();
						newPlant.x = self.x;
						newPlant.y = self.y;
						newPlant.scaleX = 1;
						newPlant.scaleY = 1;
						newPlant.alpha = 1;
						// Set the plant's _bornCycle to the current cycleCount so its cycle restarts
						if (typeof cycleCount !== "undefined") {
							newPlant._bornCycle = cycleCount;
						}
						plants.push(newPlant);
						if (self.parent) self.parent.addChild(newPlant);
						self.eaten = true;
						self.destroy();
					}
				});
			}
		}
	};
	// If something eats the seed (future-proof)
	self.die = function () {
		if (self.eaten) return;
		self.eaten = true;
		tween(self, {
			scaleX: 0,
			scaleY: 0,
			alpha: 0
		}, {
			duration: 200,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				self.destroy();
			}
		});
	};
	return self;
});
// Spore class (projectile shot by fungi)
var Spore = Container.expand(function () {
	var self = Container.call(this);
	// Use a simple green circle for the spore
	var sporeAsset = self.attachAsset('plant', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.25,
		scaleY: 0.25
	});
	self.target = null;
	self.speed = 2.5;
	self._alive = true;
	self.update = function () {
		if (!self.target || self.target.eaten || !self._alive) {
			self.destroy();
			self._alive = false;
			return;
		}
		var dx = self.target.x - self.x;
		var dy = self.target.y - self.y;
		var dist = Math.sqrt(dx * dx + dy * dy);
		if (dist > 1) {
			self.x += dx / dist * self.speed;
			self.y += dy / dist * self.speed;
		}
		// Check collision with target herbivore
		if (!self._lastIntersecting && self.intersects(self.target)) {
			// "Hit" the herbivore: destroy spore, animate herbivore, but do not kill
			if (self.target && typeof self.target.sporeHit === "function") {
				self.target.sporeHit();
			}
			self.destroy();
			self._alive = false;
		}
		self._lastIntersecting = self.intersects(self.target);
	};
	return self;
});
// FungiSpore class for future extensibility (could add poison, etc)
// Modified: FungiSpore now takes a straight path (direction set at spawn)
var FungiSpore = Spore.expand(function () {
	var self = Spore.call(this);
	// Store initial direction at spawn
	self._vx = 0;
	self._vy = 0;
	// Set direction only once at spawn, toward target
	self.setDirection = function () {
		if (self.target) {
			var dx = self.target.x - self.x;
			var dy = self.target.y - self.y;
			var dist = Math.sqrt(dx * dx + dy * dy);
			if (dist > 0) {
				self._vx = dx / dist * self.speed;
				self._vy = dy / dist * self.speed;
			} else {
				self._vx = 0;
				self._vy = 0;
			}
		} else {
			self._vx = 0;
			self._vy = 0;
		}
	};
	// Call setDirection at spawn
	self.setDirection();
	// Override update to move in a straight line
	self.update = function () {
		if (!self.target || self.target.eaten || !self._alive) {
			self.destroy();
			self._alive = false;
			return;
		}
		self.x += self._vx;
		self.y += self._vy;
		// Check collision with target herbivore
		if (!self._lastIntersecting && self.intersects(self.target)) {
			if (self.target && typeof self.target.sporeHit === "function") {
				self.target.sporeHit();
			}
			self.destroy();
			self._alive = false;
		}
		self._lastIntersecting = self.intersects(self.target);
	};
	return self;
});
// Worm class (moves only in summer and winter, buried in autumn and spring)
var Worm = Container.expand(function () {
	var self = Container.call(this);
	// Determine if worm is buried at spawn
	self.buried = false;
	var isAutumn = !!window.autumnState;
	var isSpring = !!window.springState;
	if (isAutumn || isSpring) {
		self.buried = true;
	}
	// Use the worm image asset for the worm, or buried asset if buried
	self._wormAsset = null;
	if (self.buried) {
		self._wormAsset = self.attachAsset('Buried_worm', {
			anchorX: 0.5,
			anchorY: 0.5
		});
	} else {
		self._wormAsset = self.attachAsset('Worm', {
			anchorX: 0.5,
			anchorY: 0.5
		});
	}
	// Movement speed for worms
	self.speed = 1 + Math.random() * 0.5;
	// Track wander direction and timer
	self._wanderAngle = Math.random() * Math.PI * 2;
	self._wanderTimer = 60 + Math.floor(Math.random() * 60);
	// Track brown plants eaten in summer
	self._brownPlantsEaten = 0;
	// Track last brown plant intersected (for collision detection)
	self._lastIntersectingBrownPlant = null;
	self.update = function () {
		var isSummer = !!window.summerState;
		var isWinter = !!window.winterState;
		var isAutumn = !!window.autumnState;
		var isSpring = !!window.springState;
		// If currently buried but season changed to summer/winter, unbury and swap asset
		if (self.buried && (isSummer || isWinter)) {
			self.buried = false;
			if (self._wormAsset) {
				self.removeChild(self._wormAsset);
			}
			self._wormAsset = self.attachAsset('Worm', {
				anchorX: 0.5,
				anchorY: 0.5
			});
		}
		// If currently not buried but season changed to autumn/spring, bury and swap asset
		if (!self.buried && (isAutumn || isSpring)) {
			self.buried = true;
			if (self._wormAsset) {
				self.removeChild(self._wormAsset);
			}
			self._wormAsset = self.attachAsset('Buried_worm', {
				anchorX: 0.5,
				anchorY: 0.5
			});
		}
		// --- Worm AI: In summer, seek and eat brown plants, then bury after 3 eaten ---
		if (isSummer && !self.buried) {
			// Find nearest brown plant
			var minDist = 999999,
				closest = null;
			for (var i = 0; i < plants.length; i++) {
				var p = plants[i];
				if (p.eaten) continue;
				if (!p._isBrown) continue;
				var dx = p.x - self.x,
					dy = p.y - self.y;
				var dist = dx * dx + dy * dy;
				if (dist < minDist) {
					minDist = dist;
					closest = p;
				}
			}
			if (closest) {
				// Move toward brown plant
				var dx = closest.x - self.x;
				var dy = closest.y - self.y;
				var dist = Math.sqrt(dx * dx + dy * dy);
				if (dist > 1) {
					self.x += dx / dist * self.speed;
					self.y += dy / dist * self.speed;
				}
				// Eat brown plant if close enough and not already eaten
				var isIntersecting = self.intersects(closest);
				if ((!self._lastIntersectingBrownPlant || self._lastIntersectingBrownPlant !== closest) && isIntersecting && !closest.eaten) {
					if (typeof closest.die === "function") {
						closest.die();
					}
					self._brownPlantsEaten = (self._brownPlantsEaten || 0) + 1;
					// After eating 3 brown plants, bury and swap asset
					if (self._brownPlantsEaten >= 3) {
						self.buried = true;
						if (self._wormAsset) {
							self.removeChild(self._wormAsset);
						}
						self._wormAsset = self.attachAsset('Buried_worm', {
							anchorX: 0.5,
							anchorY: 0.5
						});
						self._brownPlantsEaten = 0;
						// Immediately stop moving after burying
						self._wanderTimer = 0;
						self._wanderAngle = 0;
					}
				}
				self._lastIntersectingBrownPlant = isIntersecting ? closest : null;
			} else {
				// No brown plant: wander randomly
				if (!self._wanderTimer || self._wanderTimer <= 0) {
					self._wanderAngle = Math.random() * Math.PI * 2;
					self._wanderTimer = 60 + Math.floor(Math.random() * 60);
				}
				if (typeof self._wanderAngle === "number") {
					self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
					self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
					self._wanderTimer--;
					// Keep inside map bounds (strictly)
					var minX = 124 + 60;
					var maxX = 124 + 1800 - 60;
					var minY = paletteY + 320 + 60;
					var maxY = paletteY + 320 + 2000 - 60;
					if (self.x < minX) self.x = minX;
					if (self.x > maxX) self.x = maxX;
					if (self.y < minY) self.y = minY;
					if (self.y > maxY) self.y = maxY;
				}
				self._lastIntersectingBrownPlant = null;
			}
		} else if (isWinter && !self.buried) {
			// Wander randomly in winter
			if (!self._wanderTimer || self._wanderTimer <= 0) {
				self._wanderAngle = Math.random() * Math.PI * 2;
				self._wanderTimer = 60 + Math.floor(Math.random() * 60);
			}
			if (typeof self._wanderAngle === "number") {
				self.x += Math.cos(self._wanderAngle) * self.speed * 0.5;
				self.y += Math.sin(self._wanderAngle) * self.speed * 0.5;
				self._wanderTimer--;
				// Keep inside map bounds (strictly)
				var minX = 124 + 60;
				var maxX = 124 + 1800 - 60;
				var minY = paletteY + 320 + 60;
				var maxY = paletteY + 320 + 2000 - 60;
				if (self.x < minX) self.x = minX;
				if (self.x > maxX) self.x = maxX;
				if (self.y < minY) self.y = minY;
				if (self.y > maxY) self.y = maxY;
			}
			// Reset brown plant eating state in winter
			self._brownPlantsEaten = 0;
			self._lastIntersectingBrownPlant = null;
		}
		// In autumn and spring, do nothing (no movement, buried)
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x2ecc40 //{7C} // Set to a green background
});
/**** 
* Game Code
****/ 
// Pollinator sound effects (buzz, chirp, etc)
// --- Pollinator Hibernation State ---
var pollinatorsHibernating = false;
// --- Year Counter ---
// Add a year counter above the cycle counter that increments after winter ends
var yearCount = 1;
var yearTxt = new Text2("Year: 1", {
	size: 80,
	fill: "#000"
});
yearTxt.anchor.set(0.5, 0);
// Place above the cycle counter
LK.gui.top.addChild(yearTxt);
yearTxt.x = 500;
yearTxt.y = 40;
// --- Cycle Counter ---
// Add a cycle counter at the bottom of the screen that increments every 50 seconds (3000 frames at 60fps)
var cycleCount = 0;
var cycleTxt = new Text2("Cycle: 0", {
	size: 80,
	fill: "#000"
});
cycleTxt.anchor.set(0.5, 0);
// Place at top left, but not in the top 100px reserved area
LK.gui.top.addChild(cycleTxt);
cycleTxt.x = 500;
cycleTxt.y = 120;
// --- Season Text at Bottom ---
// Helper to get current season as string
function getCurrentSeason() {
	if (window.summerState) return "Summer";
	if (window.winterState) return "Winter";
	if (window.springState) return "Spring";
	if (window.autumnState) return "Autumn";
	// Fallback: guess from background color
	if (game.backgroundColor === 0xffff00) return "Summer";
	if (game.backgroundColor === 0xffffff) return "Winter";
	if (game.backgroundColor === 0x8B5A2B) return "Autumn";
	return "Spring";
}
var seasonTxt = new Text2("Season: " + getCurrentSeason(), {
	size: 90,
	fill: "#000"
});
seasonTxt.anchor.set(0, 1);
LK.gui.bottom.addChild(seasonTxt);
seasonTxt.x = 40;
seasonTxt.y = 0;
// Helper to update season text
function updateSeasonText() {
	if (seasonTxt && typeof seasonTxt.setText === "function") {
		seasonTxt.setText("Season: " + getCurrentSeason());
		if (typeof seasonTxt.setStyle === "function") seasonTxt.setStyle({
			fill: "#000"
		});
	}
}
// --- Cycle Countdown Timer Text ---
var cycleDurationMs = 50000; // 50,000 ms = 50 seconds
var cycleTimeLeftMs = cycleDurationMs;
var cycleTimerTxt = new Text2("Next cycle: 50s", {
	size: 60,
	fill: "#000"
});
cycleTimerTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(cycleTimerTxt);
cycleTimerTxt.x = 500;
cycleTimerTxt.y = cycleTxt.y + 80; // Place under the cycle counter
// Timer to increment cycle every 50 seconds
var cycleInterval = null; // Will be started after first organism is placed
var cycleCountdownInterval = null; // For updating the countdown text
// Helper to set all on-screen text color to black
function updateTextColors(bgColor) {
	var textColor = "#000";
	if (cycleTxt && typeof cycleTxt.setStyle === "function") cycleTxt.setStyle({
		fill: textColor
	});
	if (cycleTimerTxt && typeof cycleTimerTxt.setStyle === "function") cycleTimerTxt.setStyle({
		fill: textColor
	});
	if (deleteBtnTxt && typeof deleteBtnTxt.setStyle === "function") deleteBtnTxt.setStyle({
		fill: textColor
	});
	if (skipCycleBtnTxt && typeof skipCycleBtnTxt.setStyle === "function") skipCycleBtnTxt.setStyle({
		fill: textColor
	});
	// Palette item labels
	for (var i = 0; i < paletteItems.length; i++) {
		for (var j = 0; j < paletteItems[i].children.length; j++) {
			var child = paletteItems[i].children[j];
			if (child instanceof Text2 && typeof child.setStyle === "function") {
				child.setStyle({
					fill: textColor
				});
			}
		}
	}
	// Palette scroll arrows
	if (window.paletteLeftBtn) {
		for (var i = 0; i < window.paletteLeftBtn.children.length; i++) {
			var child = window.paletteLeftBtn.children[i];
			if (child instanceof Text2 && typeof child.setStyle === "function") child.setStyle({
				fill: textColor
			});
		}
	}
	if (window.paletteRightBtn) {
		for (var i = 0; i < window.paletteRightBtn.children.length; i++) {
			var child = window.paletteRightBtn.children[i];
			if (child instanceof Text2 && typeof child.setStyle === "function") child.setStyle({
				fill: textColor
			});
		}
	}
}
function startCycleInterval() {
	if (cycleInterval !== null) return;
	cycleTimeLeftMs = cycleDurationMs;
	cycleTimerTxt.setText("Next cycle: " + Math.ceil(cycleTimeLeftMs / 1000) + "s");
	cycleInterval = LK.setInterval(function () {
		cycleCount++;
		cycleTxt.setText("Cycle: " + cycleCount);
		cycleTimeLeftMs = cycleDurationMs;
		cycleTimerTxt.setText("Next cycle: " + Math.ceil(cycleTimeLeftMs / 1000) + "s");
		// --- Streak Counter Logic ---
		// If skip was used this cycle, reset streak and clear flag
		if (streakSkipThisCycle) {
			resetStreak();
			streakSkipThisCycle = false;
		} else {
			// If at least one organism is alive, increment streak, else reset
			var anyAlive = plants.length > 0 || herbivores.length > 0 || carnivores.length > 0 || pollinators.length > 0 || fungis.length > 0 || parasites.length > 0 || worms.length > 0;
			if (anyAlive) {
				incrementStreak();
			} else {
				resetStreak();
			}
		}
		// Reset tired attempts for all carnivores at the start of each cycle
		for (var i = 0; i < carnivores.length; i++) {
			if (carnivores[i] && carnivores[i]._tiredAttempts) {
				carnivores[i]._tiredAttempts = {};
			}
		}
		// --- Extinction: If no plants, kill all herbivores, pollinators, and carnivores ---
		if (plants.length === 0) {
			// Herbivores
			for (var i = herbivores.length - 1; i >= 0; i--) {
				var h = herbivores[i];
				if (typeof h.die === "function") h.die();else if (typeof h.destroy === "function") h.destroy();
				herbivores.splice(i, 1);
			}
			// Pollinators
			for (var i = pollinators.length - 1; i >= 0; i--) {
				var p = pollinators[i];
				if (typeof p.die === "function") p.die();else if (typeof p.destroy === "function") p.destroy();
				pollinators.splice(i, 1);
			}
			// Carnivores
			for (var i = carnivores.length - 1; i >= 0; i--) {
				var c = carnivores[i];
				if (typeof c.die === "function") c.die();else if (typeof c.destroy === "function") c.destroy();
				carnivores.splice(i, 1);
			}
			// --- Make randomize button available on total extinction ---
			if (typeof randomizeBtn !== "undefined") {
				// Check if all organisms are dead (plants, herbivores, carnivores, pollinators, fungis, parasites, worms)
				var allGone = plants.length === 0 && herbivores.length === 0 && carnivores.length === 0 && pollinators.length === 0 && fungis.length === 0 && parasites.length === 0 && worms.length === 0;
				if (allGone) {
					randomizeBtn._disabled = false;
					randomizeBtnBox.color = 0x228B22;
					if (typeof randomizeBtnBox.setStyle === "function") {
						randomizeBtnBox.setStyle({
							fill: "#fff"
						});
					}
					randomizeBtnTxt.setText("Randomize");
				} else {
					// If any organisms are present, keep randomize button disabled
					randomizeBtn._disabled = true;
					randomizeBtnBox.color = 0xcc2222;
					if (typeof randomizeBtnBox.setStyle === "function") {
						randomizeBtnBox.setStyle({
							fill: "#fff"
						});
					}
					randomizeBtnTxt.setText("Randomized");
				}
			}
		}
		// Set background color every 3 cycles: green, yellow, brown, white, repeat (spring, summer, autumn, winter)
		var mod = cycleCount % 12;
		if (mod === 0) {
			// SPRING
			game.setBackgroundColor(0x2ecc40); // green
			updateTextColors(0x2ecc40);
			pollinatorsHibernating = false;
			window.summerState = false;
			window.springState = true;
			window.winterState = false;
			window.autumnState = false;
			// Play mellow music
			LK.playMusic('mellow');
			// --- YEAR COUNTER: Increment year after winter ends (when entering spring) ---
			if (cycleCount > 0) {
				yearCount++;
				if (yearTxt && typeof yearTxt.setText === "function") {
					yearTxt.setText("Year: " + yearCount);
				}
			}
			// Restore plant color to normal (green) and allow dying
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] && plants[i].plantAsset && typeof plants[i].plantAsset.tint !== "undefined") {
					plants[i].plantAsset.tint = 0xffffff;
				}
				plants[i]._canDie = true;
			}
			// --- SPRING: Hatch all parasite eggs (eggs with _isParasiteEgg and _parasiteHatch) ---
			for (var i = eggs.length - 1; i >= 0; i--) {
				var e = eggs[i];
				if (e && e._isParasiteEgg && e._parasiteHatch && !e.hatched) {
					// Instantly hatch the egg into a parasite
					e.hatched = true;
					// Animate egg hatching
					tween(e, {
						scaleX: 1.2,
						scaleY: 1.2,
						alpha: 0.5
					}, {
						duration: 200,
						easing: tween.easeOut,
						onFinish: function (egg) {
							return function () {
								var parasite = new Parasite();
								parasite.x = egg.x;
								parasite.y = egg.y;
								parasite.scaleX = 1;
								parasite.scaleY = 1;
								parasite.alpha = 1;
								if (egg.parent) egg.parent.addChild(parasite);
								if (typeof parasites !== "undefined") parasites.push(parasite);
								egg.destroy();
							};
						}(e)
					});
					eggs.splice(i, 1);
				}
			}
			// --- Resume herbivore movement after winter ends ---
			for (var i = 0; i < herbivores.length; i++) {
				if (herbivores[i] && typeof herbivores[i].speed === "number") {
					herbivores[i].speed = 1.2 + Math.random() * 1.0;
				}
			}
			// --- Resume carnivore hunting after winter ends --- (Ava)
			// Reset carnivore state to "hungry" so they resume hunting in spring
			for (var i = 0; i < carnivores.length; i++) {
				if (carnivores[i]) {
					carnivores[i].state = "hungry";
					carnivores[i]._tired = false;
					carnivores[i]._tiredTimer = 0;
					carnivores[i]._chaseTime = 0;
					carnivores[i].target = null;
				}
			}
			updateSeasonText();
		} else if (mod === 3) {
			// SUMMER
			game.setBackgroundColor(0xffff00); // yellow
			updateTextColors(0xffff00);
			pollinatorsHibernating = false;
			window.summerState = true;
			window.winterState = false;
			window.springState = false;
			window.autumnState = false;
			// Plants can die, but keep their color normal
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] && plants[i].plantAsset && typeof plants[i].plantAsset.tint !== "undefined") {
					plants[i].plantAsset.tint = 0xffffff;
				}
				plants[i]._canDie = true;
			}
			updateSeasonText();
		} else if (mod === 6) {
			// AUTUMN
			game.setBackgroundColor(0x8B5A2B); // brown
			updateTextColors(0x8B5A2B);
			pollinatorsHibernating = false;
			window.summerState = false;
			window.springState = false;
			window.winterState = false;
			window.autumnState = true;
			// Make all plants brown and allow dying
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] && plants[i].plantAsset && typeof plants[i].plantAsset.tint !== "undefined") {
					plants[i].plantAsset.tint = 0x996633; // brown
				}
				plants[i]._canDie = true;
				plants[i]._isBrown = true;
			}
			updateSeasonText();
		} else if (mod === 9) {
			// WINTER
			game.setBackgroundColor(0xffffff); // white
			updateTextColors(0xffffff);
			pollinatorsHibernating = true;
			window.summerState = false;
			window.springState = false;
			window.winterState = true;
			window.autumnState = false;
			// --- WINTER: Parasites die and lay eggs before death ---
			for (var i = parasites.length - 1; i >= 0; i--) {
				var parasite = parasites[i];
				if (parasite && !parasite.eaten) {
					// Lay a parasite egg at current position before dying
					var egg = new Egg();
					egg.x = parasite.x;
					egg.y = parasite.y;
					egg.scaleX = 0.5;
					egg.scaleY = 0.5;
					egg.alpha = 1;
					egg._isParasiteEgg = true;
					egg._parasiteHatch = true;
					if (parasite.parent) parasite.parent.addChild(egg);
					if (typeof eggs !== "undefined") eggs.push(egg);
					// Animate parasite dying and remove from array
					tween(parasite, {
						scaleX: 0,
						scaleY: 0,
						alpha: 0
					}, {
						duration: 200,
						easing: tween.easeIn,
						onFinish: function (p) {
							return function () {
								if (typeof parasites !== "undefined") {
									var idx = parasites.indexOf(p);
									if (idx !== -1) parasites.splice(idx, 1);
								}
								p.destroy();
							};
						}(parasite)
					});
				}
			}
			// Kill all brown plants when winter starts
			for (var i = plants.length - 1; i >= 0; i--) {
				var p = plants[i];
				// Only kill brown plants; healthy plants do not die in winter
				if (p && p._isBrown && !p.eaten && typeof p.die === "function") {
					p.die();
				}
			}
			// Make all plants blue and prevent dying
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] && plants[i].plantAsset && typeof plants[i].plantAsset.tint !== "undefined") {
					plants[i].plantAsset.tint = 0x3399ff;
				}
				plants[i]._canDie = false;
			}
			// Cull a random portion of eggs during winter to reduce lag
			if (eggs && eggs.length > 0) {
				// Remove up to 40% of eggs at random, but always leave at least 3 eggs if possible
				var eggsToCull = Math.floor(eggs.length * 0.4);
				var minEggsLeft = 3;
				if (eggs.length - eggsToCull < minEggsLeft) {
					eggsToCull = Math.max(0, eggs.length - minEggsLeft);
				}
				for (var i = 0; i < eggsToCull; i++) {
					// Pick a random egg index
					var idx = Math.floor(Math.random() * eggs.length);
					var e = eggs[idx];
					if (e && typeof e.destroy === "function") {
						e.destroy();
					}
					eggs.splice(idx, 1);
				}
			}
			updateSeasonText();
		}
	}, cycleDurationMs);
	// Start countdown updater (every 100ms for smoothness)
	if (cycleCountdownInterval === null) {
		cycleCountdownInterval = LK.setInterval(function () {
			if (cycleTimeLeftMs > 0) {
				cycleTimeLeftMs -= 100;
				if (cycleTimeLeftMs < 0) cycleTimeLeftMs = 0;
				cycleTimerTxt.setText("Next cycle: " + Math.ceil(cycleTimeLeftMs / 1000) + "s");
			}
		}, 100);
	}
}
// --- End of Game Code ---;;
// --- Asset Initialization ---
// new carnivore egg texture
var plants = [];
var herbivores = [];
// --- Herbivore Hunger Queue: Only 2 can be hungry at a time ---
var herbivoreHungerQueue = []; // Array of herbivores waiting to be hungry
var carnivores = [];
var seeds = [];
var eggs = []; // Track all eggs globally
var pollinators = [];
var fungis = []; // Track all fungi globally
var parasites = []; // Track all parasites globally
var fungiSpores = []; // Track all spores shot by fungi
// --- Worms spawned at game start ---
// If you want worms to be present at game start, add them here and set them buried until the next season
var worms = [];
// Worms are not spawned at the top of the screen at game start
// --- Palette UI ---
var paletteY = 180; // y position for palette
var paletteSpacing = 260;
var paletteItems = [];
// --- Delete Mode Button ---
var deleteMode = false;
var deleteBtn = new Container();
var deleteBtnBox = deleteBtn.attachAsset('box', {
	anchorX: 0.5,
	anchorY: 0.5,
	width: 220,
	height: 100,
	color: 0xcc3333,
	shape: 'box'
});
var deleteBtnTxt = new Text2("Delete: OFF", {
	size: 54,
	fill: "#000"
});
deleteBtnTxt.anchor.set(0.5, 0.5);
deleteBtn.addChild(deleteBtnTxt);
// Place delete button under the cycle counter and timer
deleteBtn.x = 500;
deleteBtn.y = cycleTimerTxt.y + 140; // Move further down (was 90px, now 140px below the timer text)
deleteBtn.interactive = true;
deleteBtn.visible = true;
deleteBtn.down = function () {
	var clickSnd = LK.getSound('Click');
	if (clickSnd && typeof clickSnd.play === "function") clickSnd.play();
	deleteMode = !deleteMode;
	deleteBtnBox.color = deleteMode ? 0xff4444 : 0xcc3333;
	deleteBtnTxt.setText(deleteMode ? "Delete: ON" : "Delete: OFF");
};
LK.gui.top.addChild(deleteBtn);
// --- Skip Cycle Button --- 
var skipCycleBtn = new Container();
var skipCycleBtnBox = skipCycleBtn.attachAsset('box', {
	anchorX: 0.5,
	anchorY: 0.5,
	width: 220,
	height: 100,
	color: 0x3388cc,
	shape: 'box'
});
var skipCycleBtnTxt = new Text2("Skip Cycle", {
	size: 54,
	fill: "#000"
});
skipCycleBtnTxt.anchor.set(0.5, 0.5);
skipCycleBtn.addChild(skipCycleBtnTxt);
// Place skip button under the delete button
skipCycleBtn.x = 500;
skipCycleBtn.y = deleteBtn.y + 120;
skipCycleBtn.interactive = true;
skipCycleBtn.visible = true;
// --- Skip Cycle Cooldown State ---
var skipCycleCooldownActive = false;
var skipCycleCooldownTimeout = null;
// --- Skip Cycle Cooldown Counter Text ---
var skipCycleCountdownTxt = new Text2("", {
	size: 54,
	fill: "#fff"
});
skipCycleCountdownTxt.anchor.set(0, 0.5);
// Position to the right of the skip button (visually next to it)
skipCycleCountdownTxt.x = 130;
skipCycleCountdownTxt.y = 0;
skipCycleCountdownTxt.visible = false;
skipCycleBtn.addChild(skipCycleCountdownTxt);
var skipCycleCountdownInterval = null;
var skipCycleCountdownValue = 0;
// --- Extinction Button ---
var extinctionBtn = new Container();
var extinctionBtnBox = extinctionBtn.attachAsset('box', {
	anchorX: 0.5,
	anchorY: 0.5,
	width: 220,
	height: 100,
	color: 0x555555,
	shape: 'box'
});
var extinctionBtnTxt = new Text2("Extinction", {
	size: 54,
	fill: "#000"
});
extinctionBtnTxt.anchor.set(0.5, 0.5);
extinctionBtn.addChild(extinctionBtnTxt);
// Place extinction button under the skip cycle button
extinctionBtn.x = 500;
extinctionBtn.y = skipCycleBtn.y + 120;
extinctionBtn.interactive = true;
extinctionBtn.visible = true;
LK.gui.top.addChild(extinctionBtn);
// --- Achievements Button and Menu removed ---
// --- Randomize Button ---
var randomizeBtn = new Container();
var randomizeBtnBox = randomizeBtn.attachAsset('box', {
	anchorX: 0.5,
	anchorY: 0.5,
	width: 220,
	height: 100,
	color: 0x228B22,
	shape: 'box'
});
var randomizeBtnTxt = new Text2("Randomize", {
	size: 54,
	fill: "#000"
});
randomizeBtnTxt.anchor.set(0.5, 0.5);
randomizeBtn.addChild(randomizeBtnTxt);
// Place randomize button under the extinction button
randomizeBtn.x = 500;
randomizeBtn.y = extinctionBtn.y + 120;
randomizeBtn.interactive = true;
randomizeBtn.visible = true;
LK.gui.top.addChild(randomizeBtn);
// --- Personality Reveal Button ---
var personalityBtn = new Container();
var personalityBtnBox = personalityBtn.attachAsset('box', {
	anchorX: 0.5,
	anchorY: 0.5,
	width: 220,
	height: 100,
	color: 0x8e44ad,
	shape: 'box'
});
var personalityBtnTxt = new Text2("Personality", {
	size: 54,
	fill: "#000"
});
personalityBtnTxt.anchor.set(0.5, 0.5);
personalityBtn.addChild(personalityBtnTxt);
// Place personality button under the randomize button
personalityBtn.x = 500;
personalityBtn.y = randomizeBtn.y + 120;
personalityBtn.interactive = true;
personalityBtn.visible = true;
LK.gui.top.addChild(personalityBtn);
// --- Personality Reveal Text Above Each Organism ---
var personalityPopup = null;
var personalityTextNodes = []; // Track all personality text objects
// --- Streak Counter UI and Variables ---
// Streak: counts how many cycles at least one organism is alive, resets if all die or if you skip a cycle
var streakCount = 0;
var streakTxt = new Text2("Streak: 0", {
	size: 60,
	fill: "#000"
});
streakTxt.anchor.set(0.5, 0.5);
// Place streak counter under the personality button (y + 120)
streakTxt.x = personalityBtn.x;
streakTxt.y = personalityBtn.y + 120;
LK.gui.top.addChild(streakTxt);
// --- Score Counter UI and Variables ---
var scoreCount = 0;
var scoreTxt = new Text2("Score: 0", {
	size: 60,
	fill: "#000"
});
scoreTxt.anchor.set(0.5, 0.5);
// Place score counter under the streak counter
scoreTxt.x = streakTxt.x;
scoreTxt.y = streakTxt.y + 80;
LK.gui.top.addChild(scoreTxt);
// Helper to update score text
function updateScoreText() {
	if (scoreTxt && typeof scoreTxt.setText === "function") {
		scoreTxt.setText("Score: " + scoreCount);
		if (typeof scoreTxt.setStyle === "function") scoreTxt.setStyle({
			fill: "#000"
		});
	}
}
// --- Retract/Expand Streak and Score Counter with Top Buttons ---
// Patch updateTopButtonsRetracted to also move/hide streakTxt and scoreTxt
var _originalUpdateTopButtonsRetracted = updateTopButtonsRetracted;
updateTopButtonsRetracted = function updateTopButtonsRetracted() {
	if (topButtonsRetracted) {
		// Move streak counter offscreen and hide
		var offX = 2048 + 300;
		tween(streakTxt, {
			x: offX
		}, {
			duration: 200,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				streakTxt.visible = false;
			}
		});
		// Move score counter offscreen and hide
		tween(scoreTxt, {
			x: offX
		}, {
			duration: 200,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				scoreTxt.visible = false;
			}
		});
	} else {
		// Move streak counter back and show
		streakTxt.visible = true;
		tween(streakTxt, {
			x: 500
		}, {
			duration: 200,
			easing: tween.easeOut
		});
		// Move score counter back and show
		scoreTxt.visible = true;
		tween(scoreTxt, {
			x: 500
		}, {
			duration: 200,
			easing: tween.easeOut
		});
	}
	// Call original for other buttons
	if (typeof _originalUpdateTopButtonsRetracted === "function") {
		_originalUpdateTopButtonsRetracted();
	}
};
// Track if a skip happened this cycle (reset streak if so)
var streakSkipThisCycle = false;
// Helper to update streak text
function updateStreakText() {
	if (streakTxt && typeof streakTxt.setText === "function") {
		streakTxt.setText("Streak: " + streakCount);
		if (typeof streakTxt.setStyle === "function") streakTxt.setStyle({
			fill: "#000"
		});
	}
}
function resetStreak() {
	streakCount = 0;
	updateStreakText();
	// Reset score to 0 when streak is reset
	scoreCount = 0;
	updateScoreText();
	// Play the 'Lost' sound every time the streak is reset
	var lostSnd = LK.getSound('Lost');
	if (lostSnd && typeof lostSnd.play === "function") lostSnd.play();
	// Show "streak lost!" text in the middle of the screen in red for 5 seconds
	if (typeof window._streakLostTxt !== "undefined" && window._streakLostTxt && window._streakLostTxt.parent) {
		window._streakLostTxt.parent.removeChild(window._streakLostTxt);
		if (typeof window._streakLostTxt.destroy === "function") window._streakLostTxt.destroy();
		window._streakLostTxt = null;
	}
	var streakLostTxt = new Text2("streak lost!", {
		size: 160,
		fill: "#c00",
		font: "'GillSans-Bold',Impact,'Arial Black',Tahoma"
	});
	streakLostTxt.anchor.set(0.5, 0.5);
	streakLostTxt.x = 2048 / 2;
	streakLostTxt.y = 2732 / 2;
	game.addChild(streakLostTxt);
	window._streakLostTxt = streakLostTxt;
	if (typeof window._streakLostTimeout !== "undefined" && window._streakLostTimeout) {
		LK.clearTimeout(window._streakLostTimeout);
	}
	window._streakLostTimeout = LK.setTimeout(function () {
		if (window._streakLostTxt && window._streakLostTxt.parent) {
			window._streakLostTxt.parent.removeChild(window._streakLostTxt);
			if (typeof window._streakLostTxt.destroy === "function") window._streakLostTxt.destroy();
		}
		window._streakLostTxt = null;
		window._streakLostTimeout = null;
	}, 5000);
}
function incrementStreak() {
	streakCount++;
	updateStreakText();
	// Increment score by 50 every time the streak increases
	scoreCount += 50;
	updateScoreText();
	// Play the 'Streak' sound every time the streak counter increases
	var streakSnd = LK.getSound('Streak');
	if (streakSnd && typeof streakSnd.play === "function") streakSnd.play();
}
function showPersonalityPopup() {
	// Remove any previous personality text nodes
	if (personalityTextNodes && personalityTextNodes.length) {
		for (var i = 0; i < personalityTextNodes.length; i++) {
			var node = personalityTextNodes[i];
			if (node && node.parent) node.parent.removeChild(node);
			if (node && typeof node.destroy === "function") node.destroy();
		}
		personalityTextNodes = [];
	}
	// For each organism, show a floating text above it with its personality
	function addPersonalityTextFor(arr, getType, getPers) {
		for (var i = 0; i < arr.length; i++) {
			var org = arr[i];
			if (!org || typeof org.x !== "number" || typeof org.y !== "number") continue;
			var type = getType(org);
			var pers = getPers(org);
			var txt = new Text2(pers, {
				size: 44,
				fill: pers === "N/A" ? "#888" : "#2c3e50"
			});
			txt.anchor.set(0.5, 1);
			txt.x = org.x;
			txt.y = org.y - 70;
			txt._personalityTarget = org;
			txt._personalityType = type;
			game.addChild(txt);
			personalityTextNodes.push(txt);
		}
	}
	// Ferns (plants)
	addPersonalityTextFor(plants, function () {
		return "Fern";
	}, function () {
		return "N/A";
	});
	// Nummer (herbivores)
	addPersonalityTextFor(herbivores, function () {
		return "Nummer";
	}, function (org) {
		// Only show personality if actually placed (on map, not destroyed)
		if (typeof org.eaten !== "undefined" && org.eaten) return "N/A";
		return org.personality || "N/A";
	});
	// Hunter (carnivores)
	addPersonalityTextFor(carnivores, function () {
		return "Hunter";
	}, function (org) {
		// Only show personality if actually placed (on map, not destroyed)
		if (typeof org.eaten !== "undefined" && org.eaten) return "N/A";
		return org.personality || "N/A";
	});
	// Pollinator
	addPersonalityTextFor(pollinators, function () {
		return "Pollinator";
	}, function (org) {
		return org.personality || "N/A";
	});
	// Shroom (fungi)
	addPersonalityTextFor(fungis, function () {
		return "Shroom";
	}, function () {
		return "N/A";
	});
	// Parasite
	addPersonalityTextFor(parasites, function () {
		return "Parasite";
	}, function () {
		return "N/A";
	});
	// Worm
	addPersonalityTextFor(worms, function () {
		return "Worm";
	}, function () {
		return "N/A";
	});
	// Patch game.update to keep personality text above each organism while visible
	if (!game._personalityTextPatched) {
		var _originalGameUpdate = game.update;
		game.update = function () {
			// Move each personality text to follow its organism
			if (personalityTextNodes && personalityTextNodes.length) {
				for (var i = personalityTextNodes.length - 1; i >= 0; i--) {
					var txt = personalityTextNodes[i];
					var org = txt && txt._personalityTarget;
					if (!org || typeof org.x !== "number" || typeof org.y !== "number" || org.eaten) {
						// Remove text if organism is gone
						if (txt.parent) txt.parent.removeChild(txt);
						if (typeof txt.destroy === "function") txt.destroy();
						personalityTextNodes.splice(i, 1);
						continue;
					}
					txt.x = org.x;
					txt.y = org.y - 70;
				}
			}
			if (_originalGameUpdate) _originalGameUpdate.apply(this, arguments);
		};
		game._personalityTextPatched = true;
	}
	// Add a close button in the top right to remove all personality text
	if (!window._personalityTextCloseBtn) {
		var closeBtn = new Container();
		var closeBtnBox = closeBtn.attachAsset('box', {
			anchorX: 0.5,
			anchorY: 0.5,
			width: 180,
			height: 80,
			color: 0x8e44ad,
			shape: 'box'
		});
		var closeBtnTxt = new Text2("Hide", {
			size: 44,
			fill: "#fff"
		});
		closeBtnTxt.anchor.set(0.5, 0.5);
		closeBtn.addChild(closeBtnTxt);
		closeBtn.x = 2048 - 200;
		closeBtn.y = 180;
		closeBtn.interactive = true;
		closeBtn.visible = true;
		closeBtn.down = function () {
			// Remove all personality text nodes
			if (personalityTextNodes && personalityTextNodes.length) {
				for (var i = 0; i < personalityTextNodes.length; i++) {
					var node = personalityTextNodes[i];
					if (node && node.parent) node.parent.removeChild(node);
					if (node && typeof node.destroy === "function") node.destroy();
				}
				personalityTextNodes = [];
			}
			if (closeBtn && closeBtn.parent) closeBtn.parent.removeChild(closeBtn);
			window._personalityTextCloseBtn = null;
		};
		LK.gui.top.addChild(closeBtn);
		window._personalityTextCloseBtn = closeBtn;
	}
}
// Button handler
// Track if personality text is currently shown
var personalityTextVisible = false;
personalityBtn.down = function () {
	var clickSnd = LK.getSound('Click');
	if (clickSnd && typeof clickSnd.play === "function") clickSnd.play();
	if (personalityTextVisible) {
		// Hide all personality text nodes
		if (personalityTextNodes && personalityTextNodes.length) {
			for (var i = 0; i < personalityTextNodes.length; i++) {
				var node = personalityTextNodes[i];
				if (node && node.parent) node.parent.removeChild(node);
				if (node && typeof node.destroy === "function") node.destroy();
			}
			personalityTextNodes = [];
		}
		// Remove close button if present
		if (window._personalityTextCloseBtn) {
			if (window._personalityTextCloseBtn.parent) window._personalityTextCloseBtn.parent.removeChild(window._personalityTextCloseBtn);
			window._personalityTextCloseBtn = null;
		}
		personalityTextVisible = false;
	} else {
		showPersonalityPopup();
		personalityTextVisible = true;
	}
};
// --- Randomize Button Handler ---
randomizeBtn.down = function () {
	var clickSnd = LK.getSound('Click');
	if (clickSnd && typeof clickSnd.play === "function") clickSnd.play();
	// Only randomize if not retracted or already disabled
	if (topButtonsRetracted || randomizeBtn._disabled) return;
	// Helper to get a random position in the map area
	function getRandomPos() {
		var minX = 124 + 60;
		var maxX = 124 + 1800 - 60;
		var minY = paletteY + 320 + 60;
		var maxY = paletteY + 320 + 2000 - 60;
		return {
			x: minX + Math.random() * (maxX - minX),
			y: minY + Math.random() * (maxY - minY)
		};
	}
	// Add 3-5 ferns
	var fernCount = 3 + Math.floor(Math.random() * 3); // 3,4,5
	for (var i = 0; i < fernCount; i++) {
		var pos = getRandomPos();
		var fern = new Plant();
		fern.x = pos.x;
		fern.y = pos.y;
		fern.scaleX = 1;
		fern.scaleY = 1;
		fern.alpha = 1;
		plants.push(fern);
		game.addChild(fern);
	}
	// Add 3-5 herbivores
	var herbCount = 3 + Math.floor(Math.random() * 3);
	for (var i = 0; i < herbCount; i++) {
		var pos = getRandomPos();
		var herb = new Nummer();
		herb._uniqueId = "herb_" + Math.floor(Math.random() * 1e9) + "_" + Math.floor(Math.random() * 1e9);
		herb.x = pos.x;
		herb.y = pos.y;
		herb.scaleX = 1;
		herb.scaleY = 1;
		herb.alpha = 1;
		// Start in wandering state when spawned by randomize button
		herb.state = "wandering";
		herb._wanderAfterSleepTimer = 600; // 10 seconds wandering
		// --- Randomize herbivore personality ---
		var personalities = ["normal", "curious", "grumpy"];
		var rand = Math.random();
		// Make random traits more common: 30% normal, 35% curious, 35% grumpy
		if (rand < 0.3) {
			herb.personality = "normal";
		} else if (rand < 0.65) {
			herb.personality = "curious";
		} else {
			herb.personality = "grumpy";
		}
		herbivores.push(herb);
		game.addChild(herb);
	}
	// Add 3-5 pollinators
	var pollCount = 3 + Math.floor(Math.random() * 3);
	for (var i = 0; i < pollCount; i++) {
		var pos = getRandomPos();
		var poll = new Pollinator();
		poll.x = pos.x;
		poll.y = pos.y;
		poll.scaleX = 1;
		poll.scaleY = 1;
		poll.alpha = 1;
		pollinators.push(poll);
		game.addChild(poll);
	}
	// Add 0-1 carnivores
	var carnCount = Math.floor(Math.random() * 2); // 0 or 1
	for (var i = 0; i < carnCount; i++) {
		var pos = getRandomPos();
		var carn = new Carnivore();
		// --- Randomize carnivore personality ---
		var carnPersonalities = ["normal", "bloodthirsty", "weak"];
		var rand = Math.random();
		// Make random traits more common: 30% normal, 35% bloodthirsty, 35% weak
		if (rand < 0.3) {
			carn.personality = "normal";
		} else if (rand < 0.65) {
			carn.personality = "bloodthirsty";
		} else {
			carn.personality = "weak";
		}
		// Adjust speed for bloodthirsty carnivores
		if (carn.personality === "bloodthirsty") {
			carn.speed = 1.5 + Math.random() * 1.2 + 0.7 + Math.random() * 0.5;
		}
		carn.x = pos.x;
		carn.y = pos.y;
		carn.scaleX = 1.25;
		carn.scaleY = 1.25;
		carn.alpha = 1;
		carnivores.push(carn);
		game.addChild(carn);
	}
	// Play plop sound for feedback
	var plopSnd = LK.getSound('Plop');
	if (plopSnd && typeof plopSnd.play === "function") plopSnd.play();
	// --- Unlock skip cycle button when randomize is pressed ---
	skipCycleBtn._skipLocked = false;
	firstOrganismPlaced = true;
	// --- Restart the cycle timer when randomize is pressed ---
	if (cycleInterval !== null) {
		LK.clearInterval(cycleInterval);
		cycleInterval = null;
	}
	if (cycleCountdownInterval !== null) {
		LK.clearInterval(cycleCountdownInterval);
		cycleCountdownInterval = null;
	}
	cycleTimeLeftMs = cycleDurationMs;
	cycleTimerTxt.setText("Next cycle: " + Math.ceil(cycleTimeLeftMs / 1000) + "s");
	startCycleInterval();
	// --- Disable and color the randomize button red ---
	randomizeBtn._disabled = true;
	randomizeBtnBox.color = 0xcc2222;
	if (typeof randomizeBtnBox.setStyle === "function") {
		randomizeBtnBox.setStyle({
			fill: "#fff"
		});
	}
	randomizeBtnTxt.setText("Randomized");
	// --- Disable randomize button if any organisms are present ---
	if (plants.length > 0 || herbivores.length > 0 || carnivores.length > 0 || pollinators.length > 0 || fungis.length > 0 || parasites.length > 0 || worms.length > 0) {
		randomizeBtn._disabled = true;
		randomizeBtnBox.color = 0xcc2222;
		if (typeof randomizeBtnBox.setStyle === "function") {
			randomizeBtnBox.setStyle({
				fill: "#fff"
			});
		}
		randomizeBtnTxt.setText("Randomized");
	}
};
// Asteroid extinction event handler
// --- Extinction Event Rate Limiting ---
// Track timestamps (in ms) of recent extinction events
if (typeof window._extinctionEventTimes === "undefined") window._extinctionEventTimes = [];
extinctionBtn.down = function () {
	var clickSnd = LK.getSound('Click');
	if (clickSnd && typeof clickSnd.play === "function") clickSnd.play();
	LK.getSound('explosion').play();
	// Asteroid visual: big circle in center of map
	var asteroid = LK.getAsset('box', {
		anchorX: 0.5,
		anchorY: 0.5,
		width: 400,
		height: 400,
		color: 0x888888,
		shape: 'ellipse'
	});
	asteroid.x = 124 + 1800 / 2;
	asteroid.y = paletteY + 320 + 2000 / 2;
	asteroid.alpha = 0.0;
	game.addChild(asteroid);
	// Animate asteroid fade in, then out
	tween(asteroid, {
		alpha: 1
	}, {
		duration: 300,
		easing: tween.easeIn,
		onFinish: function onFinish() {
			tween(asteroid, {
				alpha: 0
			}, {
				duration: 700,
				easing: tween.easeOut,
				onFinish: function onFinish() {
					asteroid.destroy();
				}
			});
		}
	});
	// Flash screen for dramatic effect
	LK.effects.flashScreen(0xff6600, 800);
	// --- Extinction Event Rate Limiting Logic ---
	// Add current timestamp to the event list
	var now = Date.now();
	window._extinctionEventTimes.push(now);
	// Only keep events in the last 10 seconds (10000 ms)
	var cutoff = now - 10000;
	for (var i = window._extinctionEventTimes.length - 1; i >= 0; i--) {
		if (window._extinctionEventTimes[i] < cutoff) {
			window._extinctionEventTimes.splice(i, 1);
		}
	}
	// If more than 3 extinction events in last 10 seconds, kill all creatures
	if (window._extinctionEventTimes.length > 3) {
		// Gather all organisms (plants, herbivores, carnivores, pollinators, fungis, seeds, eggs, worms, parasites)
		var allGroups = [plants, herbivores, carnivores, pollinators, fungis, seeds, eggs, worms, parasites];
		for (var g = 0; g < allGroups.length; g++) {
			var arr = allGroups[g];
			for (var i = arr.length - 1; i >= 0; i--) {
				var org = arr[i];
				arr.splice(i, 1);
				if (org && typeof org.die === "function") {
					org.die();
				} else if (org && typeof org.destroy === "function") {
					org.destroy();
				}
			}
		}
		// Optionally, flash the screen again for drama
		LK.effects.flashScreen(0x000000, 1200);
		// Clear the event times to prevent repeated wipes
		window._extinctionEventTimes = [];
		return;
	}
	// Gather all organisms (plants, herbivores, carnivores, pollinators, fungis, seeds, eggs, worms, parasites)
	var allGroups = [plants, herbivores, carnivores, pollinators, fungis, seeds, eggs, worms, parasites];
	for (var g = 0; g < allGroups.length; g++) {
		var arr = allGroups[g];
		if (arr.length === 0) continue;
		// If the group has 3 or fewer, kill 1 or 2 at random (never all)
		if (arr.length <= 3) {
			var toKill = Math.floor(Math.random() * arr.length); // 0, 1, or 2
			for (var i = 0; i < toKill; i++) {
				if (arr.length === 0) break;
				var idx = Math.floor(Math.random() * arr.length);
				var org = arr[idx];
				arr.splice(idx, 1);
				if (org && typeof org.die === "function") {
					org.die();
				} else if (org && typeof org.destroy === "function") {
					org.destroy();
				}
			}
		} else if (arr.length % 2 !== 0) {
			// If uneven, kill a random number between 1 and half the group (rounded down)
			var maxKill = Math.floor(arr.length / 2);
			var toKill = 1 + Math.floor(Math.random() * maxKill);
			for (var i = 0; i < toKill; i++) {
				if (arr.length === 0) break;
				var idx = Math.floor(Math.random() * arr.length);
				var org = arr[idx];
				arr.splice(idx, 1);
				if (org && typeof org.die === "function") {
					org.die();
				} else if (org && typeof org.destroy === "function") {
					org.destroy();
				}
			}
		} else {
			// Even and more than 3: kill half (rounded down), random selection
			var survivors = Math.ceil(arr.length / 2);
			var toKill = arr.length - survivors;
			for (var i = 0; i < toKill; i++) {
				if (arr.length === 0) break;
				var idx = Math.floor(Math.random() * arr.length);
				var org = arr[idx];
				arr.splice(idx, 1);
				if (org && typeof org.die === "function") {
					org.die();
				} else if (org && typeof org.destroy === "function") {
					org.destroy();
				}
			}
		}
	}
};
// --- Prevent skipping cycle until first organism is placed ---
var firstOrganismPlaced = false;
skipCycleBtn._skipLocked = true; // Lock skipping at start
skipCycleBtn.down = function () {
	var clickSnd = LK.getSound('Click');
	if (clickSnd && typeof clickSnd.play === "function") clickSnd.play();
	// --- Streak: Reset streak and play lost sound immediately when skip is pressed ---
	streakCount = 0;
	updateStreakText();
	var lostSnd = LK.getSound('Lost');
	if (lostSnd && typeof lostSnd.play === "function") lostSnd.play();
	// --- Prevent skipping if all organisms are gone (plants, herbivores, carnivores, pollinators, fungis, parasites, worms) ---
	var allGone = plants.length === 0 && herbivores.length === 0 && carnivores.length === 0 && pollinators.length === 0 && fungis.length === 0 && parasites.length === 0 && worms.length === 0;
	if (allGone) {
		// --- Streak: Reset streak if all organisms die on skip ---
		resetStreak();
		// Flash skip button red for 2 seconds
		var originalColor = skipCycleBtnBox.color;
		skipCycleBtnBox.color = 0xff4444;
		if (typeof skipCycleBtnBox.setStyle === "function") {
			skipCycleBtnBox.setStyle({
				fill: "#fff"
			});
		}
		LK.setTimeout(function () {
			skipCycleBtnBox.color = originalColor;
			if (typeof skipCycleBtnBox.setStyle === "function") {
				skipCycleBtnBox.setStyle({
					fill: "#000"
				});
			}
		}, 2000);
		return;
	}
	if (skipCycleBtn._skipLocked) {
		// Flash skip button red for 2 seconds
		var originalColor = skipCycleBtnBox.color;
		skipCycleBtnBox.color = 0xff4444;
		if (typeof skipCycleBtnBox.setStyle === "function") {
			skipCycleBtnBox.setStyle({
				fill: "#fff"
			});
		}
		// Restore color after 2 seconds
		LK.setTimeout(function () {
			skipCycleBtnBox.color = originalColor;
			if (typeof skipCycleBtnBox.setStyle === "function") {
				skipCycleBtnBox.setStyle({
					fill: "#000"
				});
			}
		}, 2000);
		return;
	}
	// --- 3 Second Cooldown Logic ---
	if (skipCycleCooldownActive) {
		// --- Streak: Reset streak if skip is attempted during cooldown (optional, but for safety) ---
		resetStreak();
		// Flash skip button red for 1 second if on cooldown
		var originalColor = skipCycleBtnBox.color;
		skipCycleBtnBox.color = 0xff4444;
		if (typeof skipCycleBtnBox.setStyle === "function") {
			skipCycleBtnBox.setStyle({
				fill: "#fff"
			});
		}
		LK.setTimeout(function () {
			skipCycleBtnBox.color = originalColor;
			if (typeof skipCycleBtnBox.setStyle === "function") {
				skipCycleBtnBox.setStyle({
					fill: "#000"
				});
			}
		}, 1000);
		return;
	}
	skipCycleCooldownActive = true;
	skipCycleBtnBox.color = 0xaaaaaa;
	skipCycleBtnTxt.setText("Cooldown");
	// Show and start the white countdown
	skipCycleCountdownValue = 3;
	skipCycleCountdownTxt.setText("" + skipCycleCountdownValue);
	skipCycleCountdownTxt.visible = true;
	// Clear any previous interval
	if (skipCycleCountdownInterval) {
		LK.clearInterval(skipCycleCountdownInterval);
		skipCycleCountdownInterval = null;
	}
	// Start interval to update countdown every 1s
	skipCycleCountdownInterval = LK.setInterval(function () {
		skipCycleCountdownValue--;
		if (skipCycleCountdownValue > 0) {
			skipCycleCountdownTxt.setText("" + skipCycleCountdownValue);
		} else {
			skipCycleCountdownTxt.visible = false;
			skipCycleCountdownTxt.setText("");
			if (skipCycleCountdownInterval) {
				LK.clearInterval(skipCycleCountdownInterval);
				skipCycleCountdownInterval = null;
			}
		}
	}, 1000);
	// Restore after 3 seconds
	if (skipCycleCooldownTimeout) {
		LK.clearTimeout(skipCycleCooldownTimeout);
	}
	skipCycleCooldownTimeout = LK.setTimeout(function () {
		skipCycleCooldownActive = false;
		skipCycleBtnBox.color = 0x3388cc;
		skipCycleBtnTxt.setText("Skip Cycle");
		if (typeof skipCycleBtnBox.setStyle === "function") {
			skipCycleBtnBox.setStyle({
				fill: "#000"
			});
		}
		// Hide the countdown if still visible
		skipCycleCountdownTxt.visible = false;
		skipCycleCountdownTxt.setText("");
		if (skipCycleCountdownInterval) {
			LK.clearInterval(skipCycleCountdownInterval);
			skipCycleCountdownInterval = null;
		}
	}, 3000);
	// --- Streak: Mark that skip was used this cycle (will reset streak on next cycle) ---
	streakSkipThisCycle = true;
	// Increment cycle and update UI
	cycleCount++;
	cycleTxt.setText("Cycle: " + cycleCount);
	cycleTimeLeftMs = cycleDurationMs;
	cycleTimerTxt.setText("Next cycle: " + Math.ceil(cycleTimeLeftMs / 1000) + "s");
	// --- Extinction: If no plants, kill all herbivores, pollinators, and carnivores ---
	if (plants.length === 0) {
		// Herbivores
		for (var i = herbivores.length - 1; i >= 0; i--) {
			var h = herbivores[i];
			if (typeof h.die === "function") h.die();else if (typeof h.destroy === "function") h.destroy();
			herbivores.splice(i, 1);
		}
		// Pollinators
		for (var i = pollinators.length - 1; i >= 0; i--) {
			var p = pollinators[i];
			if (typeof p.die === "function") p.die();else if (typeof p.destroy === "function") p.destroy();
			pollinators.splice(i, 1);
		}
		// Carnivores
		for (var i = carnivores.length - 1; i >= 0; i--) {
			var c = carnivores[i];
			if (typeof c.die === "function") c.die();else if (typeof c.destroy === "function") c.destroy();
			carnivores.splice(i, 1);
		}
	}
	// Set background color every 3 cycles: green, yellow, brown, white, repeat (spring, summer, autumn, winter)
	var mod = cycleCount % 12;
	if (mod === 0) {
		// SPRING
		game.setBackgroundColor(0x2ecc40); // green
		updateTextColors(0x2ecc40);
		pollinatorsHibernating = false;
		window.summerState = false;
		window.springState = true;
		window.winterState = false;
		window.autumnState = false;
		// Play mellow music
		LK.playMusic('mellow');
		// --- YEAR COUNTER: Increment year after winter ends (when entering spring) ---
		if (cycleCount > 0) {
			yearCount++;
			if (yearTxt && typeof yearTxt.setText === "function") {
				yearTxt.setText("Year: " + yearCount);
			}
		}
		for (var i = 0; i < plants.length; i++) {
			if (plants[i] && plants[i].plantAsset && typeof plants[i].plantAsset.tint !== "undefined") {
				plants[i].plantAsset.tint = 0xffffff;
			}
			plants[i]._canDie = true;
		}
		for (var i = 0; i < herbivores.length; i++) {
			if (herbivores[i] && typeof herbivores[i].speed === "number") {
				herbivores[i].speed = 1.2 + Math.random() * 1.0;
			}
		}
		for (var i = 0; i < carnivores.length; i++) {
			if (carnivores[i]) {
				carnivores[i].state = "hungry";
				carnivores[i]._tired = false;
				carnivores[i]._tiredTimer = 0;
				carnivores[i]._chaseTime = 0;
				carnivores[i].target = null;
			}
		}
		updateSeasonText();
	} else if (mod === 3) {
		// SUMMER
		game.setBackgroundColor(0xffff00); // yellow
		updateTextColors(0xffff00);
		pollinatorsHibernating = false;
		window.summerState = true;
		window.winterState = false;
		window.springState = false;
		window.autumnState = false;
		for (var i = 0; i < plants.length; i++) {
			if (plants[i] && plants[i].plantAsset && typeof plants[i].plantAsset.tint !== "undefined") {
				plants[i].plantAsset.tint = 0xffffff;
			}
			plants[i]._canDie = true;
		}
		updateSeasonText();
	} else if (mod === 6) {
		// AUTUMN
		game.setBackgroundColor(0x8B5A2B); // brown
		updateTextColors(0x8B5A2B);
		pollinatorsHibernating = false;
		window.summerState = false;
		window.springState = false;
		window.winterState = false;
		window.autumnState = true;
		for (var i = 0; i < plants.length; i++) {
			if (plants[i] && plants[i].plantAsset && typeof plants[i].plantAsset.tint !== "undefined") {
				plants[i].plantAsset.tint = 0x996633; // brown
			}
			plants[i]._canDie = true;
			plants[i]._isBrown = true;
		}
		updateSeasonText();
	} else if (mod === 9) {
		// WINTER
		game.setBackgroundColor(0xffffff); // white
		updateTextColors(0xffffff);
		pollinatorsHibernating = true;
		window.summerState = false;
		window.springState = false;
		window.winterState = true;
		window.autumnState = false;
		for (var i = plants.length - 1; i >= 0; i--) {
			var p = plants[i];
			if (p && p._isBrown && !p.eaten && typeof p.die === "function") {
				p.die();
			}
		}
		for (var i = 0; i < plants.length; i++) {
			if (plants[i] && plants[i].plantAsset && typeof plants[i].plantAsset.tint !== "undefined") {
				plants[i].plantAsset.tint = 0x3399ff;
			}
			plants[i]._canDie = false;
		}
		updateSeasonText();
	}
	// Randomize all organism positions except fungi, plants, and lichen
	var minX = 124 + 60;
	var maxX = 124 + 1800 - 60;
	var minY = paletteY + 320 + 60;
	var maxY = paletteY + 320 + 2000 - 60;
	// Helper to randomize array of organisms
	function randomizeOrganisms(arr) {
		for (var i = 0; i < arr.length; i++) {
			var org = arr[i];
			// If this is a host with a parasite attached, skip randomizing its position
			if (org && typeof org.x === "number" && typeof org.y === "number" && !org.eaten && !org._parasiteAttached // Only randomize if not hosting a parasite
			) {
				org.x = minX + Math.random() * (maxX - minX);
				org.y = minY + Math.random() * (maxY - minY);
			}
		}
	}
	// When randomizing parasites, only randomize those not attached to a host
	function randomizeFreeParasites(arr) {
		for (var i = 0; i < arr.length; i++) {
			var parasite = arr[i];
			if (parasite && typeof parasite.x === "number" && typeof parasite.y === "number" && !parasite.eaten && parasite.state !== "attached") {
				parasite.x = minX + Math.random() * (maxX - minX);
				parasite.y = minY + Math.random() * (maxY - minY);
			}
		}
	}
	randomizeOrganisms(herbivores);
	randomizeOrganisms(carnivores);
	randomizeOrganisms(pollinators);
	randomizeOrganisms(seeds);
	randomizeOrganisms(eggs);
	randomizeOrganisms(worms);
	randomizeFreeParasites(parasites);
	// Fungi, plants, and lichen are NOT moved
	// (fungis, plants, window.lichens)
};
// --- Patch createOrganism to unlock skip after first organism placed ---
var _originalCreateOrganism = createOrganism;
createOrganism = function createOrganism(type, x, y) {
	var obj = _originalCreateOrganism(type, x, y);
	if (!firstOrganismPlaced) {
		firstOrganismPlaced = true;
		skipCycleBtn._skipLocked = false;
	}
	return obj;
};
// --- Retract/Expand Widget for Top Buttons ---
// State for retraction
var topButtonsRetracted = false;
// Widget button (a small round button at the right of the top buttons)
var retractWidget = new Container();
var retractWidgetBox = retractWidget.attachAsset('box', {
	anchorX: 0.5,
	anchorY: 0.5,
	width: 90,
	height: 90,
	color: 0x888888,
	shape: 'ellipse'
});
var retractWidgetTxt = new Text2("β‘", {
	size: 60,
	fill: "#fff"
});
retractWidgetTxt.anchor.set(0.5, 0.5);
retractWidget.addChild(retractWidgetTxt);
// Place widget to the right of the top buttons
retractWidget.x = 300;
retractWidget.y = deleteBtn.y + 50;
retractWidget.interactive = true;
retractWidget.visible = true;
// Helper to update button visibility/position
function updateTopButtonsRetracted() {
	if (topButtonsRetracted) {
		// Move buttons offscreen right, hide text, and set visible to false
		var offX = 2048 + 300;
		tween(skipCycleBtn, {
			x: offX
		}, {
			duration: 200,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				skipCycleBtn.visible = false;
			}
		});
		tween(deleteBtn, {
			x: offX
		}, {
			duration: 200,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				deleteBtn.visible = false;
			}
		});
		tween(extinctionBtn, {
			x: offX
		}, {
			duration: 200,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				extinctionBtn.visible = false;
			}
		});
		// Hide randomize button as well
		if (typeof randomizeBtn !== "undefined") {
			tween(randomizeBtn, {
				x: offX
			}, {
				duration: 200,
				easing: tween.easeIn,
				onFinish: function onFinish() {
					randomizeBtn.visible = false;
				}
			});
		}
		// Hide personality button as well
		if (typeof personalityBtn !== "undefined") {
			tween(personalityBtn, {
				x: offX
			}, {
				duration: 200,
				easing: tween.easeIn,
				onFinish: function onFinish() {
					personalityBtn.visible = false;
				}
			});
		}
		retractWidgetTxt.setText("βΆ");
		// Also move retractWidget to the right when retracted
		tween(retractWidget, {
			x: 700 //{Fe} // Move even further right
		}, {
			duration: 200,
			easing: tween.easeIn
		});
	} else {
		// Move buttons back to original positions and set visible to true
		tween(retractWidget, {
			x: 300
		}, {
			duration: 200,
			easing: tween.easeOut
		});
		skipCycleBtn.visible = true;
		deleteBtn.visible = true;
		extinctionBtn.visible = true;
		if (typeof randomizeBtn !== "undefined") {
			randomizeBtn.visible = true;
			tween(randomizeBtn, {
				x: 500
			}, {
				duration: 200,
				easing: tween.easeOut
			});
		}
		// Show and move personality button back
		if (typeof personalityBtn !== "undefined") {
			personalityBtn.visible = true;
			tween(personalityBtn, {
				x: 500
			}, {
				duration: 200,
				easing: tween.easeOut
			});
		}
		tween(skipCycleBtn, {
			x: 500
		}, {
			duration: 200,
			easing: tween.easeOut
		});
		tween(deleteBtn, {
			x: 500
		}, {
			duration: 200,
			easing: tween.easeOut
		});
		tween(extinctionBtn, {
			x: 500
		}, {
			duration: 200,
			easing: tween.easeOut
		});
		retractWidgetTxt.setText("β‘");
	}
}
// Widget click toggles retraction
retractWidget.down = function () {
	var clickSnd = LK.getSound('Click');
	if (clickSnd && typeof clickSnd.play === "function") clickSnd.play();
	topButtonsRetracted = !topButtonsRetracted;
	// Animate widget itself to the right when retracting, back to original when expanding
	if (topButtonsRetracted) {
		tween(retractWidget, {
			x: 500
		}, {
			duration: 200,
			easing: tween.easeIn
		});
	} else {
		tween(retractWidget, {
			x: 300
		}, {
			duration: 200,
			easing: tween.easeOut
		});
	}
	updateTopButtonsRetracted();
};
// Add widget to GUI
LK.gui.top.addChild(skipCycleBtn);
LK.gui.top.addChild(extinctionBtn);
LK.gui.top.addChild(randomizeBtn);
LK.gui.top.addChild(retractWidget);
// On game start, ensure buttons are expanded
updateTopButtonsRetracted();
// Shift the palette even further left so it is not offscreen
var paletteTotalWidth = paletteSpacing * 2;
var paletteXStart = 2048 / 2 - paletteTotalWidth / 2 - 1300;
// Create palette items for drag-and-drop
function createPaletteItem(type, x, y) {
	var assetId, color, label;
	if (type === 'plant') {
		assetId = 'plant';
		color = 0x6adf60;
		label = 'Fern';
	} else if (type === 'herbivore') {
		assetId = 'herbivore';
		color = 0xf7e26b;
		label = 'Nummer';
	} else if (type === 'pollinator') {
		assetId = 'pollinator';
		color = 0xffc300;
		label = 'Pollinator';
	} else if (type === 'fungi') {
		assetId = 'fungi';
		color = 0xbb88ff;
		label = 'Shroom';
	} else if (type === 'parasite') {
		assetId = 'Parasite';
		color = 0x8888ff;
		label = 'Parasite';
	} else if (type === 'worm') {
		assetId = 'Worm';
		color = 0x888888;
		label = 'Worm';
	} else {
		assetId = 'carnivore';
		color = 0xe74c3c;
		label = 'Hunter';
	}
	;
	// Update all eggs
	for (var i = eggs.length - 1; i >= 0; i--) {
		var e = eggs[i];
		if (!e.parent || e.hatched) {
			eggs.splice(i, 1);
			continue;
		}
		if (e.update) e.update();
	}
	;
	// Update all pollinators
	for (var i = pollinators.length - 1; i >= 0; i--) {
		var p = pollinators[i];
		if (p.eaten) {
			pollinators.splice(i, 1);
			continue;
		}
		if (p.update) p.update();
	}
	var node = new Container();
	var icon;
	if (type === 'parasite') {
		icon = node.attachAsset(assetId, {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: 0.5,
			scaleY: 0.5
		});
	} else {
		icon = node.attachAsset(assetId, {
			anchorX: 0.5,
			anchorY: 0.5
		});
	}
	node.x = x;
	node.y = y;
	node.type = type;
	// --- Population Counter Above Icon ---
	var popCount = 0;
	if (type === 'plant') popCount = plants.length;else if (type === 'herbivore') popCount = herbivores.length;else if (type === 'carnivore') popCount = carnivores.length;else if (type === 'pollinator') popCount = pollinators.length;else if (type === 'fungi') popCount = fungis.length;else if (type === 'parasite') popCount = parasites.length;
	var popTxt = new Text2("" + popCount, {
		size: 54,
		fill: "#000"
	});
	popTxt.anchor.set(0.5, 1);
	popTxt.y = -70;
	node.addChild(popTxt);
	node._popTxt = popTxt; // Store for update
	// Add label
	var txt = new Text2(label, {
		size: 60,
		fill: "#000"
	});
	txt.anchor.set(0.5, 0);
	txt.y = 60;
	node.addChild(txt);
	// Add to GUI overlay (so it stays on top)
	LK.gui.top.addChild(node);
	paletteItems.push(node);
	return node;
}
// --- Palette Scroll Bar ---
// All available organism types in palette
var paletteTypes = ['plant', 'herbivore', 'carnivore', 'pollinator', 'fungi', 'parasite', 'worm'];
var paletteScrollOffset = 0; // How much the palette is scrolled (in px)
var paletteScrollMin = 0;
var paletteScrollMax = Math.max(0, paletteTypes.length * paletteSpacing - paletteSpacing * 3); // Show 3 at a time
// Remove old palette items if any
for (var i = 0; i < paletteItems.length; i++) {
	if (paletteItems[i].parent) paletteItems[i].parent.removeChild(paletteItems[i]);
}
paletteItems = [];
// Helper to render palette items based on scroll offset
function renderPaletteItems() {
	// Remove all current palette items from GUI
	for (var i = 0; i < paletteItems.length; i++) {
		if (paletteItems[i].parent) paletteItems[i].parent.removeChild(paletteItems[i]);
	}
	paletteItems = [];
	// Only show up to 3 at a time, centered
	var visibleCount = 3;
	var startIdx = Math.floor(paletteScrollOffset / paletteSpacing);
	var offsetPx = paletteScrollOffset % paletteSpacing;
	for (var i = 0; i < visibleCount; i++) {
		var idx = startIdx + i;
		if (idx >= 0 && idx < paletteTypes.length) {
			var px = paletteXStart + i * paletteSpacing - offsetPx;
			var node = createPaletteItem(paletteTypes[idx], px, paletteY);
			paletteItems.push(node);
		}
	}
	// Draw left/right scroll buttons
	if (!window.paletteLeftBtn) {
		window.paletteLeftBtn = new Container();
		var leftIcon = window.paletteLeftBtn.attachAsset('box', {
			anchorX: 0.5,
			anchorY: 0.5,
			width: 80,
			height: 120,
			color: 0x444444,
			shape: 'box'
		});
		var leftArrow = new Text2("<", {
			size: 80,
			fill: "#000"
		});
		leftArrow.anchor.set(0.5, 0.5);
		leftArrow.x = 0;
		leftArrow.y = 0;
		window.paletteLeftBtn.addChild(leftArrow);
		window.paletteLeftBtn.x = paletteXStart - 120;
		window.paletteLeftBtn.y = paletteY;
		window.paletteLeftBtn.interactive = true;
		LK.gui.top.addChild(window.paletteLeftBtn);
		window.paletteLeftBtn.visible = false;
	}
	if (!window.paletteRightBtn) {
		window.paletteRightBtn = new Container();
		var rightIcon = window.paletteRightBtn.attachAsset('box', {
			anchorX: 0.5,
			anchorY: 0.5,
			width: 80,
			height: 120,
			color: 0x444444,
			shape: 'box'
		});
		var rightArrow = new Text2(">", {
			size: 80,
			fill: "#000"
		});
		rightArrow.anchor.set(0.5, 0.5);
		rightArrow.x = 0;
		rightArrow.y = 0;
		window.paletteRightBtn.addChild(rightArrow);
		window.paletteRightBtn.x = paletteXStart + paletteSpacing * visibleCount + 40;
		window.paletteRightBtn.y = paletteY;
		window.paletteRightBtn.interactive = true;
		LK.gui.top.addChild(window.paletteRightBtn);
		window.paletteRightBtn.visible = false;
	}
	// Show/hide buttons
	window.paletteLeftBtn.visible = paletteScrollOffset > paletteScrollMin;
	window.paletteRightBtn.visible = paletteScrollOffset < paletteScrollMax;
}
renderPaletteItems();
// --- Palette Scroll Button Handlers ---
window.paletteLeftBtn.down = function () {
	var clickSnd = LK.getSound('Click');
	if (clickSnd && typeof clickSnd.play === "function") clickSnd.play();
	if (paletteScrollOffset > paletteScrollMin) {
		paletteScrollOffset -= paletteSpacing;
		if (paletteScrollOffset < paletteScrollMin) paletteScrollOffset = paletteScrollMin;
		renderPaletteItems();
	}
};
window.paletteRightBtn.down = function () {
	var clickSnd = LK.getSound('Click');
	if (clickSnd && typeof clickSnd.play === "function") clickSnd.play();
	if (paletteScrollOffset < paletteScrollMax) {
		paletteScrollOffset += paletteSpacing;
		if (paletteScrollOffset > paletteScrollMax) paletteScrollOffset = paletteScrollMax;
		renderPaletteItems();
	}
};
// --- End Palette Scroll Bar ---
// --- Drag and Drop Logic ---
var dragging = null; // {type, node, paletteRef}
var dragOffsetX = 0,
	dragOffsetY = 0;
// Helper: create organism at x,y
function createOrganism(type, x, y) {
	var obj;
	if (type === 'plant') {
		obj = new Plant();
		plants.push(obj);
		// If background is white, make plant blue and undying
		if (game.backgroundColor === 0xffffff) {
			if (obj.plantAsset && typeof obj.plantAsset.tint !== "undefined") {
				obj.plantAsset.tint = 0x3399ff;
			}
			obj._canDie = false;
		}
		// If placed in summer, make plant invulnerable for 10 seconds
		if (game.backgroundColor === 0xffff00 || window.summerState) {
			obj._invulnerable = true;
			obj._canDie = false;
			// Remove invulnerability after 10 seconds (600 frames)
			LK.setTimeout(function () {
				if (plants.indexOf(obj) !== -1) {
					obj._invulnerable = false;
					obj._canDie = true;
				}
			}, 10000);
		}
	} else if (type === 'herbivore') {
		obj = new Nummer();
		obj._uniqueId = "herb_" + Math.floor(Math.random() * 1e9) + "_" + Math.floor(Math.random() * 1e9);
		herbivores.push(obj);
	} else if (type === 'pollinator') {
		obj = new Pollinator();
		pollinators.push(obj);
	} else if (type === 'fungi') {
		obj = new Fungi();
		// If fungi is spawned after the cycle has started, set its _bornCycle to the next cycle so it lives a full cycle
		if (typeof cycleCount !== "undefined") {
			obj._bornCycle = cycleCount + 1;
		}
		fungis.push(obj);
	} else if (type === 'parasite') {
		obj = new Parasite();
		parasites.push(obj);
		// If spawned in winter, kill parasite immediately
		if (window.winterState) {
			// Animate parasite dying and remove from array
			tween(obj, {
				scaleX: 0,
				scaleY: 0,
				alpha: 0
			}, {
				duration: 200,
				easing: tween.easeIn,
				onFinish: function onFinish() {
					if (typeof parasites !== "undefined") {
						var idx = parasites.indexOf(obj);
						if (idx !== -1) parasites.splice(idx, 1);
					}
					obj.destroy();
				}
			});
		}
	} else if (type === 'worm') {
		obj = new Worm();
		worms.push(obj);
		// If spawned in autumn or spring, set buried state (handled in Worm class, but ensure correct state at spawn)
		if ((window.autumnState || window.springState) && obj) {
			obj.buried = true;
			if (obj._wormAsset) {
				obj.removeChild(obj._wormAsset);
			}
			obj._wormAsset = obj.attachAsset('Buried_worm', {
				anchorX: 0.5,
				anchorY: 0.5
			});
		}
		// If spawned in the first 2 cycles, set buried state
		if (typeof cycleCount !== "undefined" && cycleCount < 2 && obj) {
			obj.buried = true;
			if (obj._wormAsset) {
				obj.removeChild(obj._wormAsset);
			}
			obj._wormAsset = obj.attachAsset('Buried_worm', {
				anchorX: 0.5,
				anchorY: 0.5
			});
		}
	} else {
		obj = new Carnivore();
		carnivores.push(obj);
	}
	obj.x = x;
	obj.y = y;
	obj.scaleX = 1;
	obj.scaleY = 1;
	obj.alpha = 1;
	game.addChild(obj);
	// Play plop sound when placing an organism from the palette
	var plopSnd = LK.getSound('Plop');
	if (plopSnd && typeof plopSnd.play === "function") plopSnd.play();
	// Start the cycle interval if not already started
	if (typeof startCycleInterval === "function") startCycleInterval();
	// If personality button is enabled (personality text nodes are present), show personality text for this organism
	if (personalityTextNodes && personalityTextNodes.length > 0) {
		// Helper to add personality text for a single organism
		var addPersonalityTextForSingle = function addPersonalityTextForSingle(org, type, pers) {
			var txt = new Text2(pers, {
				size: 44,
				fill: pers === "N/A" ? "#888" : "#2c3e50"
			});
			txt.anchor.set(0.5, 1);
			txt.x = org.x;
			txt.y = org.y - 70;
			txt._personalityTarget = org;
			txt._personalityType = type;
			game.addChild(txt);
			personalityTextNodes.push(txt);
		}; // Determine type and personality string
		var type = null,
			pers = "N/A";
		if (obj instanceof Plant) {
			type = "Fern";
			pers = "N/A";
		} else if (obj instanceof Nummer) {
			type = "Nummer";
			pers = obj.personality || "N/A";
		} else if (obj instanceof Carnivore) {
			type = "Hunter";
			pers = obj.personality || "N/A";
		} else if (obj instanceof Pollinator) {
			type = "Pollinator";
			pers = obj.personality || "N/A";
		} else if (obj instanceof Fungi) {
			type = "Shroom";
			pers = "N/A";
		} else if (obj instanceof Parasite) {
			type = "Parasite";
			pers = "N/A";
		} else if (obj instanceof Worm) {
			type = "Worm";
			pers = "N/A";
		}
		addPersonalityTextForSingle(obj, type, pers);
	}
	return obj;
}
// Helper: check if point is inside a palette item
function isInPalette(x, y, node) {
	var bounds = {
		x: node.x - 60,
		y: node.y - 60,
		w: 120,
		h: 120
	};
	return x >= bounds.x && x <= bounds.x + bounds.w && y >= bounds.y && y <= bounds.y + bounds.h;
}
// --- Event Handlers ---
// Global button click sound handler: play click sound for any button on screen
if (typeof window._globalButtonClickHandlerAttached === "undefined") {
	window._globalButtonClickHandlerAttached = true;
	// Patch LK.gui.top's down event to play click sound for any button
	var _originalGuiTopDown = LK.gui.top.down;
	LK.gui.top.down = function (x, y, obj) {
		var clickSnd = LK.getSound('Click');
		if (clickSnd && typeof clickSnd.play === "function") clickSnd.play();
		if (typeof _originalGuiTopDown === "function") _originalGuiTopDown.call(this, x, y, obj);
	};
	// Patch LK.gui.bottom's down event to play click sound for any button
	var _originalGuiBottomDown = LK.gui.bottom.down;
	LK.gui.bottom.down = function (x, y, obj) {
		var clickSnd = LK.getSound('Click');
		if (clickSnd && typeof clickSnd.play === "function") clickSnd.play();
		if (typeof _originalGuiBottomDown === "function") _originalGuiBottomDown.call(this, x, y, obj);
	};
}
// Down: start drag if on palette
game.down = function (x, y, obj) {
	// If delete mode is ON, check if click is on an organism and delete it
	if (deleteMode) {
		// Include lichens in allOrganisms if present
		var allOrganisms = plants.concat(herbivores, carnivores, pollinators, fungis, parasites, worms);
		for (var i = allOrganisms.length - 1; i >= 0; i--) {
			var org = allOrganisms[i];
			var dx = x - org.x;
			var dy = y - org.y;
			var dist = Math.sqrt(dx * dx + dy * dy);
			var isFungi = fungis.indexOf(org) !== -1;
			var canDelete = isFungi || !org.eaten;
			if (canDelete && dist < 60) {
				// Remove from correct array
				if (plants.indexOf(org) !== -1) {
					var idx = plants.indexOf(org);
					if (idx !== -1) plants.splice(idx, 1);
				} else if (herbivores.indexOf(org) !== -1) {
					var idx = herbivores.indexOf(org);
					if (idx !== -1) {
						// Remove from hunger queue if present
						var hqidx = herbivoreHungerQueue.indexOf(org);
						if (hqidx !== -1) {
							herbivoreHungerQueue.splice(hqidx, 1);
							// Next in queue (if any) becomes hungry
							for (var j = 0; j < herbivoreHungerQueue.length; j++) {
								var nextH = herbivoreHungerQueue[j];
								if (nextH && nextH.state === "waiting") {
									nextH.state = "hungry";
									nextH._hungerQueueState = "hungry";
									break;
								}
							}
						}
						herbivores.splice(idx, 1);
					}
				} else if (carnivores.indexOf(org) !== -1) {
					var idx = carnivores.indexOf(org);
					if (idx !== -1) carnivores.splice(idx, 1);
				} else if (pollinators.indexOf(org) !== -1) {
					var idx = pollinators.indexOf(org);
					if (idx !== -1) pollinators.splice(idx, 1);
				} else if (fungis.indexOf(org) !== -1) {
					var idx = fungis.indexOf(org);
					if (idx !== -1) fungis.splice(idx, 1);
				}
				if (typeof org.die === "function") {
					org.die();
				} else if (typeof org.destroy === "function") {
					org.destroy();
				}
				return;
			}
		}
		// If not on an organism, do nothing in delete mode
		return;
	}
	// Check if touch/click is on a palette item
	for (var i = 0; i < paletteItems.length; i++) {
		var p = paletteItems[i];
		// Convert GUI coordinates to game coordinates
		var guiPos = LK.gui.top.toLocal({
			x: x,
			y: y
		}, game);
		if (isInPalette(guiPos.x, guiPos.y, p)) {
			// Start dragging a new organism
			dragging = {
				type: p.type,
				node: createOrganism(p.type, x, y),
				paletteRef: p
			};
			dragOffsetX = 0;
			dragOffsetY = 0;
			// Make it semi-transparent while dragging
			dragging.node.alpha = 0.7;
			return;
		}
	}
	// If not on palette, check if on an organism to move it
	// Check if touch/click is on an organism to move it
	var found = false;
	var allOrganisms = plants.concat(herbivores, carnivores, pollinators, fungis, parasites, worms);
	for (var i = allOrganisms.length - 1; i >= 0; i--) {
		var org = allOrganisms[i];
		// Only allow moving if not eaten and touch is within 60px radius of center
		var dx = x - org.x;
		var dy = y - org.y;
		var dist = Math.sqrt(dx * dx + dy * dy);
		var isFungi = fungis.indexOf(org) !== -1;
		var isParasite = parasites.indexOf(org) !== -1;
		var canDrag = isFungi || isParasite || !org.eaten;
		if (canDrag && dist < 60) {
			var type;
			if (plants.indexOf(org) !== -1) type = 'plant';else if (herbivores.indexOf(org) !== -1) type = 'herbivore';else if (carnivores.indexOf(org) !== -1) type = 'carnivore';else if (pollinators.indexOf(org) !== -1) type = 'pollinator';else if (fungis.indexOf(org) !== -1) type = 'fungi';else if (parasites.indexOf(org) !== -1) type = 'parasite';
			// (UI label is handled in createPaletteItem, so no change needed here for type)
			dragging = {
				type: type,
				node: org,
				paletteRef: null
			};
			dragOffsetX = org.x - x;
			dragOffsetY = org.y - y;
			org.alpha = 0.7;
			found = true;
			break;
		}
	}
	if (!found) {
		dragging = null;
	}
};
// Move: update drag position
game.move = function (x, y, obj) {
	if (dragging && dragging.node) {
		var minX = 124 + 60;
		var maxX = 124 + 1800 - 60;
		var minY = paletteY + 320 + 60;
		var maxY = paletteY + 320 + 2000 - 60;
		var newX = x + dragOffsetX;
		var newY = y + dragOffsetY;
		// Clamp to map area
		if (newX < minX) newX = minX;
		if (newX > maxX) newX = maxX;
		if (newY < minY) newY = minY;
		if (newY > maxY) newY = maxY;
		dragging.node.x = newX;
		dragging.node.y = newY;
	}
};
// Up: drop organism if dragging
game.up = function (x, y, obj) {
	if (dragging && dragging.node) {
		// If dropped inside palette area, destroy (cancel)
		var guiPos = LK.gui.top.toLocal({
			x: x,
			y: y
		}, game);
		var cancel = false;
		for (var i = 0; i < paletteItems.length; i++) {
			if (isInPalette(guiPos.x, guiPos.y, paletteItems[i])) {
				cancel = true;
				break;
			}
		}
		if (cancel) {
			// Remove organism
			dragging.node.destroy();
			if (dragging.type === 'plant') {
				var idx = plants.indexOf(dragging.node);
				if (idx !== -1) plants.splice(idx, 1);
			} else if (dragging.type === 'herbivore') {
				var idx = herbivores.indexOf(dragging.node);
				if (idx !== -1) {
					// Remove from hunger queue if present
					var hqidx = herbivoreHungerQueue.indexOf(dragging.node);
					if (hqidx !== -1) {
						herbivoreHungerQueue.splice(hqidx, 1);
						// Next in queue (if any) becomes hungry
						for (var j = 0; j < herbivoreHungerQueue.length; j++) {
							var nextH = herbivoreHungerQueue[j];
							if (nextH && nextH.state === "waiting") {
								nextH.state = "hungry";
								nextH._hungerQueueState = "hungry";
								break;
							}
						}
					}
					herbivores.splice(idx, 1);
				}
			} else if (dragging.type === 'carnivore') {
				var idx = carnivores.indexOf(dragging.node);
				if (idx !== -1) carnivores.splice(idx, 1);
			} else if (dragging.type === 'pollinator') {
				var idx = pollinators.indexOf(dragging.node);
				if (idx !== -1) pollinators.splice(idx, 1);
			} else if (dragging.type === 'fungi') {
				var idx = fungis.indexOf(dragging.node);
				if (idx !== -1) fungis.splice(idx, 1);
			} else if (dragging.type === 'parasite') {
				var idx = parasites.indexOf(dragging.node);
				if (idx !== -1) parasites.splice(idx, 1);
			} else if (dragging.type === 'worm') {
				var idx = worms.indexOf(dragging.node);
				if (idx !== -1) worms.splice(idx, 1);
			}
		} else {
			// Place organism: snap alpha to 1
			dragging.node.alpha = 1;
			// If dropping a parasite, set state to 'seek' and detach from host if needed
			if (dragging.type === 'parasite') {
				// If attached, detach
				if (dragging.node.state === "attached") {
					if (dragging.node.attachedTo && dragging.node.attachedTo._parasiteAttached === dragging.node) {
						dragging.node.attachedTo._parasiteAttached = null;
					}
					dragging.node.attachedTo = null;
				}
				dragging.node.state = "seek";
				dragging.node.target = null;
			}
		}
		dragging = null;
	}
};
// --- Main Update Loop ---
game.update = function () {
	// Update all herbivores
	for (var i = herbivores.length - 1; i >= 0; i--) {
		var h = herbivores[i];
		if (h.eaten) {
			// Remove from hunger queue if present
			var idx = herbivoreHungerQueue.indexOf(h);
			if (idx !== -1) {
				herbivoreHungerQueue.splice(idx, 1);
				// Next in queue (if any) becomes hungry
				for (var j = 0; j < herbivoreHungerQueue.length; j++) {
					var nextH = herbivoreHungerQueue[j];
					if (nextH && nextH.state === "waiting") {
						nextH.state = "hungry";
						nextH._hungerQueueState = "hungry";
						break;
					}
				}
			}
			herbivores.splice(i, 1);
			continue;
		}
		if (h.update) h.update();
	}
	// Update all carnivores
	for (var i = carnivores.length - 1; i >= 0; i--) {
		var c = carnivores[i];
		if (c.eaten) {
			carnivores.splice(i, 1);
			continue;
		}
		if (c.update) c.update();
	}
	// Update all worms
	for (var i = worms.length - 1; i >= 0; i--) {
		var w = worms[i];
		if (w.update) w.update();
	}
	// In summer, randomly turn some healthy plants brown
	if (window.summerState) {
		for (var i = 0; i < plants.length; i++) {
			var p = plants[i];
			// Only affect healthy, non-brown, non-eaten plants
			if (!p.eaten && !p._isBrown) {
				// Smaller chance per frame (e.g. 0.0005 = ~0.05% per frame)
				if (Math.random() < 0.0005) {
					p._isBrown = true;
					if (p.plantAsset && typeof p.plantAsset.tint !== "undefined") {
						p.plantAsset.tint = 0x996633; // brown
					}
				}
			}
		}
	}
	// Clean up dead plants
	for (var i = plants.length - 1; i >= 0; i--) {
		var p = plants[i];
		if (p.eaten) {
			plants.splice(i, 1);
		}
	}
	// Update all seeds
	for (var i = seeds.length - 1; i >= 0; i--) {
		var s = seeds[i];
		if (s.eaten) {
			seeds.splice(i, 1);
			continue;
		}
		if (s.update) s.update();
	}
	;
	// Update all fungi
	for (var i = fungis.length - 1; i >= 0; i--) {
		var f = fungis[i];
		if (f.update) f.update();
	}
	// Update all fungi spores
	for (var i = fungiSpores.length - 1; i >= 0; i--) {
		var s = fungiSpores[i];
		if (!s.parent || !s._alive) {
			fungiSpores.splice(i, 1);
			continue;
		}
		if (s.update) s.update();
	}
	// Update all parasites
	for (var i = parasites.length - 1; i >= 0; i--) {
		var b = parasites[i];
		if (b.update) b.update();
	}
	// --- Update palette population counters ---
	for (var i = 0; i < paletteItems.length; i++) {
		var node = paletteItems[i];
		if (!node._popTxt) continue;
		var type = node.type;
		var popCount = 0;
		var maxCount = null;
		if (type === 'plant') {
			popCount = plants.length;
			maxCount = 20;
		} else if (type === 'herbivore') {
			popCount = herbivores.length;
			maxCount = 6;
		} else if (type === 'carnivore') {
			popCount = carnivores.length;
			maxCount = 4;
		} else if (type === 'pollinator') {
			popCount = pollinators.length;
			maxCount = 10;
		} else if (type === 'fungi') {
			popCount = fungis.length;
		} else if (type === 'parasite') {
			popCount = parasites.length;
			maxCount = 4;
		} else if (type === 'worm') {
			popCount = worms.length;
		}
		node._popTxt.setText("" + popCount);
		// Set counter color to red if at population control max, else black
		if (type === 'herbivore' && popCount >= 6 || type === 'pollinator' && popCount >= 10 || type === 'plant' && popCount >= 20 || type === 'carnivore' && popCount >= 4 || type === 'parasite' && popCount >= 4) {
			if (typeof node._popTxt.setStyle === "function") node._popTxt.setStyle({
				fill: "#c00"
			});
		} else {
			if (typeof node._popTxt.setStyle === "function") node._popTxt.setStyle({
				fill: "#000"
			});
		}
	}
	// --- Continuously keep randomize button disabled if organisms are present ---
	if (plants.length > 0 || herbivores.length > 0 || carnivores.length > 0 || pollinators.length > 0 || fungis.length > 0 || parasites.length > 0 || worms.length > 0) {
		randomizeBtn._disabled = true;
		randomizeBtnBox.color = 0xcc2222;
		if (typeof randomizeBtnBox.setStyle === "function") {
			randomizeBtnBox.setStyle({
				fill: "#fff"
			});
		}
		randomizeBtnTxt.setText("Randomized");
	} else {
		randomizeBtn._disabled = false;
		randomizeBtnBox.color = 0x228B22;
		if (typeof randomizeBtnBox.setStyle === "function") {
			randomizeBtnBox.setStyle({
				fill: "#fff"
			});
		}
		randomizeBtnTxt.setText("Randomize");
	}
};
// --- Instructions Text --- 
// --- Random seed spawning around the map if there are any plants ---
var randomSeedSpawnTimer = null;
function startRandomSeedSpawning() {
	if (randomSeedSpawnTimer !== null) return;
	randomSeedSpawnTimer = LK.setInterval(function () {
		// Only spawn if there are any plants
		if (plants.length > 0) {
			// 40% chance per interval to spawn a seed
			if (Math.random() < 0.4) {
				// Pick a random position inside the map area
				var minX = 124 + 60;
				var maxX = 124 + 1800 - 60;
				var minY = paletteY + 320 + 60;
				var maxY = paletteY + 320 + 2000 - 60;
				var sx = minX + Math.random() * (maxX - minX);
				var sy = minY + Math.random() * (maxY - minY);
				var seed = new Seed();
				seed.x = sx;
				seed.y = sy;
				seed.scaleX = 0.4;
				seed.scaleY = 0.4;
				seed.alpha = 1;
				seeds.push(seed);
				game.addChild(seed);
			}
		}
		// If no plants, stop spawning
		if (plants.length === 0 && randomSeedSpawnTimer !== null) {
			LK.clearInterval(randomSeedSpawnTimer);
			randomSeedSpawnTimer = null;
		}
	}, 120); // Try every 2 seconds
}
// Start random seed spawning at game start
startRandomSeedSpawning();
LK.playMusic('mellow', {
	loop: true
});
// --- Map Area Border (for visual feedback) ---
// Use a simple colored rectangle instead of a plant asset for the map border background
var mapBorder = LK.getAsset('box', {
	anchorX: 0,
	anchorY: 0,
	width: 1800,
	height: 2000,
	color: 0x2e8b57,
	shape: 'box'
});
mapBorder.alpha = 0.12;
game.addChild(mapBorder);
mapBorder.x = 124;
mapBorder.y = paletteY + 320;
// --- Add invisible border walls to prevent creatures from exiting the map area ---
var borderThickness = 40;
var borderAlpha = 0; // fully invisible
// Left border
var borderLeft = LK.getAsset('box', {
	anchorX: 0,
	anchorY: 0,
	width: borderThickness,
	height: 2000,
	color: 0x000000,
	shape: 'box'
});
borderLeft.alpha = borderAlpha;
game.addChild(borderLeft);
borderLeft.x = 124 - borderThickness;
borderLeft.y = paletteY + 320;
// Right border
var borderRight = LK.getAsset('box', {
	anchorX: 0,
	anchorY: 0,
	width: borderThickness,
	height: 2000,
	color: 0x000000,
	shape: 'box'
});
borderRight.alpha = borderAlpha;
game.addChild(borderRight);
borderRight.x = 124 + 1800;
borderRight.y = paletteY + 320;
// Top border
var borderTop = LK.getAsset('box', {
	anchorX: 0,
	anchorY: 0,
	width: 1800 + borderThickness * 2,
	height: borderThickness,
	color: 0x000000,
	shape: 'box'
});
borderTop.alpha = borderAlpha;
game.addChild(borderTop);
borderTop.x = 124 - borderThickness;
borderTop.y = paletteY + 320 - borderThickness;
// Bottom border
var borderBottom = LK.getAsset('box', {
	anchorX: 0,
	anchorY: 0,
	width: 1800 + borderThickness * 2,
	height: borderThickness,
	color: 0x000000,
	shape: 'box'
});
borderBottom.alpha = borderAlpha;
game.addChild(borderBottom);
borderBottom.x = 124 - borderThickness;
borderBottom.y = paletteY + 320 + 2000;
// --- End of Game Code ---;
:quality(85)/https://cdn.frvr.ai/6840fbb2054b31d898d619e4.png%3F3) 
 tentacled red circle with a mouth and no eyes. In-Game asset. 2d. High contrast. No shadows. Very simple
:quality(85)/https://cdn.frvr.ai/6840fbf3054b31d898d619ed.png%3F3) 
 A plant. In-Game asset. 2d. High contrast. No shadows. Very simple
:quality(85)/https://cdn.frvr.ai/6840fdc4054b31d898d61a2a.png%3F3) 
 Brown Seed. In-Game asset. 2d. High contrast. No shadows. Very simple
:quality(85)/https://cdn.frvr.ai/6840fe32054b31d898d61a38.png%3F3) 
 A small orange circle with spider legs 1 cute eye and no mouth. In-Game asset. 2d. High contrast. No shadows. Very very simple
:quality(85)/https://cdn.frvr.ai/684106d2054b31d898d61a75.png%3F3) 
 Make a red egg with dark red spots. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/68410c0b054b31d898d61a8f.png%3F3) 
 Purple mushroom. In-Game asset. 2d. High contrast. No shadows. Very simple
:quality(85)/https://cdn.frvr.ai/684116ee054b31d898d61aab.png%3F3) 
 A green shiny orb with a black circle. In-Game asset. 2d. High contrast. No shadows. Very simple
:quality(85)/https://cdn.frvr.ai/6841bf9d648535a74a56a5d7.png%3F3) 
 make a cyan lichen. In-Game asset. 2d. High contrast. No shadows. very simple
:quality(85)/https://cdn.frvr.ai/6841d974e43e12372f196cdf.png%3F3) 
 Just the color blue filling the entire space. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/6841dd59e43e12372f196d01.png%3F3) 
 A brown circle with bug like antennas and bug legs with bug jaws and no eyes. In-Game asset. 2d. High contrast. No shadows. Very simple
:quality(85)/https://cdn.frvr.ai/6841eef5dcea7f5eba9f73ff.png%3F3) 
 A venus flytrap with one mouth and is looking up side view. In-Game asset. 2d. High contrast. No shadows VERY SIMPLE
:quality(85)/https://cdn.frvr.ai/6841fb43dcea7f5eba9f7488.png%3F3) 
 Short brown worm. In-Game asset. 2d. High contrast. No shadows. Very simple
:quality(85)/https://cdn.frvr.ai/6841fb83dcea7f5eba9f7492.png%3F3) 
 Pile of dirt. In-Game asset. 2d. High contrast. No shadows. Very simple
:quality(85)/https://cdn.frvr.ai/684257a24412131eb0862983.png%3F3) 
 A yellow circle with 3 eyes no mouth and the eyes are in a triangle orientation. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/68425f744412131eb086299d.png%3F3) 
 Shrub. In-Game asset. 2d. High contrast. No shadows. Very simple