/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var BackwardPea = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('pea', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Tint green to show it's from splitpea
	graphics.tint = 0x44ff44;
	self.speed = -8; // Negative speed to go backwards 
	self.damage = 15;
	self.gridY = 0;
	self.update = function () {
		self.x += self.speed;
		// Check collision with zombies 
		for (var i = 0; i < zombies.length; i++) {
			var zombie = zombies[i];
			if (zombie.gridY === self.gridY && self.intersects(zombie)) {
				// Check if it's a JesterZombie 
				if (zombie.isJester) {
					// Create reflected pea going forward 
					var reflectedPea = new ReflectedPea();
					reflectedPea.x = zombie.x + 50;
					reflectedPea.y = zombie.y;
					reflectedPea.gridY = zombie.gridY;
					reflectedpeas.push(reflectedPea);
					game.addChild(reflectedPea);
					// Flash jester zombie to show deflection 
					LK.effects.flashObject(zombie, 0xffff00, 200);
				} else {
					zombie.takeDamage(self.damage, 'pea');
					LK.getSound('zombie_hit').play();
				}
				self.destroy();
				for (var j = 0; j < backwardpeas.length; j++) {
					if (backwardpeas[j] === self) {
						backwardpeas.splice(j, 1);
						break;
					}
				}
				return;
			}
		}
		// Remove if off screen (left side) 
		if (self.x < -100) {
			self.destroy();
			for (var k = 0; k < backwardpeas.length; k++) {
				if (backwardpeas[k] === self) {
					backwardpeas.splice(k, 1);
					break;
				}
			}
		}
	};
	return self;
});
var BasicZombie = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('basicZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 0.5;
	self.health = 100;
	self.maxHealth = 100;
	self.damage = 40;
	self.gridY = 0;
	self.attackTimer = 0;
	self.attackDelay = 60;
	self.update = function () {
		// Check if there's a plant to attack
		var plantToAttack = null;
		for (var i = 0; i < plants.length; i++) {
			var plant = plants[i];
			if (plant.gridY === self.gridY && Math.abs(plant.x - self.x) < 80) {
				plantToAttack = plant;
				break;
			}
		}
		if (plantToAttack) {
			self.attackTimer++;
			if (self.attackTimer >= self.attackDelay) {
				if (plantToAttack.takeDamage) {
					plantToAttack.takeDamage(self.damage);
					LK.getSound('zombie_eat').play();
				}
				self.attackTimer = 0;
			}
		} else {
			self.x -= self.speed;
			self.attackTimer = 0;
		}
		// Check if reached house
		if (self.x < 150) {
			LK.showGameOver();
		}
	};
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		LK.getSound('zombie_hit').play();
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < zombies.length; i++) {
				if (zombies[i] === self) {
					zombies.splice(i, 1);
					break;
				}
			}
			zombiesKilled++;
		}
	};
	return self;
});
var Zomboni = BasicZombie.expand(function () {
	var self = BasicZombie.call(this);
	// Replace the graphics with zomboni asset
	self.removeChild(self.children[0]);
	var graphics = self.attachAsset('zomboni', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 1.5; // Fast movement
	self.health = 150;
	self.maxHealth = 150;
	self.damage = 100;
	self.gridY = 0;
	self.attackTimer = 0;
	self.attackDelay = 30; // Faster elimination
	self.update = function () {
		// Move forward continuously
		self.x -= self.speed;
		// Check for plants to eliminate (in a wider area due to size)
		for (var i = plants.length - 1; i >= 0; i--) {
			var plant = plants[i];
			if (plant.gridY === self.gridY && Math.abs(plant.x - self.x) < 100) {
				// Instantly eliminate the plant
				LK.effects.flashObject(plant, 0xff0000, 200);
				// Remove from plant grid
				var gridKey = plant.gridX + ',' + plant.gridY;
				delete plantGrid[gridKey];
				plant.destroy();
				plants.splice(i, 1);
			}
		}
		// Check if reached house
		if (self.x < 150) {
			LK.showGameOver();
		}
	};
	return self;
});
var VeteranNewspaperZombie = BasicZombie.expand(function () {
	var self = BasicZombie.call(this);
	// Replace the graphics with veteran newspaper zombie asset
	self.removeChild(self.children[0]);
	var graphics = self.attachAsset('veteranewspaperZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 0.5;
	self.health = 200; // Double the life of basic zombie (100 * 2)
	self.maxHealth = 200;
	self.damage = 40;
	self.gridY = 0;
	self.attackTimer = 0;
	self.attackDelay = 60;
	self.hasRaged = false;
	self.takeDamage = function (damage) {
		// Veteran newspaper zombie is now unstoppable - no damage taken
		LK.effects.flashObject(self, 0xff0000, 200);
		LK.getSound('zombie_hit').play();
		// Always rage mode - increase speed and damage by 5x permanently
		if (!self.hasRaged) {
			self.hasRaged = true;
			self.speed = 2.5; // 0.5 * 5
			self.damage = 200; // 40 * 5
			// Visual effect for rage mode - flash red and change tint
			LK.effects.flashObject(self, 0xff0000, 500);
			tween(graphics, {
				tint: 0xff0000
			}, {
				duration: 300,
				easing: tween.easeOut
			});
		}
		// Veteran newspaper zombie never dies
	};
	return self;
});
var TankZombie = BasicZombie.expand(function () {
	var self = BasicZombie.call(this);
	// Replace the graphics with tank zombie asset
	self.removeChild(self.children[0]);
	var graphics = self.attachAsset('tankZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 0.3;
	self.health = 200;
	self.maxHealth = 200;
	self.damage = 80;
	self.gridY = 0;
	self.attackTimer = 0;
	self.attackDelay = 60;
	return self;
});
var NewspaperZombie = BasicZombie.expand(function () {
	var self = BasicZombie.call(this);
	// Replace the graphics with newspaper zombie asset
	self.removeChild(self.children[0]);
	var graphics = self.attachAsset('newspaperZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 0.5;
	self.health = 100;
	self.maxHealth = 100;
	self.damage = 40;
	self.gridY = 0;
	self.attackTimer = 0;
	self.attackDelay = 60;
	self.hasRaged = false;
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		LK.getSound('zombie_hit').play();
		// Check if health dropped to half or below and hasn't raged yet
		if (self.health <= self.maxHealth / 2 && !self.hasRaged) {
			self.hasRaged = true;
			// Increase speed and damage
			self.speed = 1.5;
			self.damage = 80;
			// Visual effect for rage mode - flash red and change tint
			LK.effects.flashObject(self, 0xff0000, 500);
			tween(graphics, {
				tint: 0xff4444
			}, {
				duration: 300,
				easing: tween.easeOut
			});
		}
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < zombies.length; i++) {
				if (zombies[i] === self) {
					zombies.splice(i, 1);
					break;
				}
			}
			zombiesKilled++;
		}
	};
	return self;
});
var MinerZombie = BasicZombie.expand(function () {
	var self = BasicZombie.call(this);
	// Replace the graphics with miner zombie asset (appears as normal zombie)
	self.removeChild(self.children[0]);
	var graphics = self.attachAsset('minerZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 0.5;
	self.health = 80;
	self.maxHealth = 80;
	self.damage = 40;
	self.gridY = 0;
	self.attackTimer = 0;
	self.attackDelay = 60;
	self.teleportTimer = 0;
	self.teleportDelay = 300; // 5 seconds at 60fps
	self.hasTeleported = false;
	self.update = function () {
		// If not teleported yet, count down to teleport
		if (!self.hasTeleported) {
			self.teleportTimer++;
			if (self.teleportTimer >= self.teleportDelay) {
				self.teleport();
			} else {
				// Move normally before teleporting
				self.x -= self.speed;
			}
		} else {
			// After teleporting, behave like normal zombie but attacking from behind
			var plantToAttack = null;
			for (var i = 0; i < plants.length; i++) {
				var plant = plants[i];
				if (plant.gridY === self.gridY && Math.abs(plant.x - self.x) < 80) {
					plantToAttack = plant;
					break;
				}
			}
			if (plantToAttack) {
				self.attackTimer++;
				if (self.attackTimer >= self.attackDelay) {
					if (plantToAttack.takeDamage) {
						plantToAttack.takeDamage(self.damage);
						LK.getSound('zombie_eat').play();
						LK.getSound('zombie_eat').play();
					}
					self.attackTimer = 0;
				}
			} else {
				self.x += self.speed; // Move forward (right) after teleporting
				self.attackTimer = 0;
			}
		}
		// Check if reached house (only matters before teleporting)
		if (!self.hasTeleported && self.x < 150) {
			LK.showGameOver();
		}
		// Check if moved off screen after teleporting
		if (self.hasTeleported && self.x > 2200) {
			self.destroy();
			for (var i = 0; i < zombies.length; i++) {
				if (zombies[i] === self) {
					zombies.splice(i, 1);
					break;
				}
			}
		}
	};
	self.teleport = function () {
		if (self.hasTeleported) return;
		self.hasTeleported = true;
		// Flash effect before teleporting
		LK.effects.flashObject(self, 0xffff00, 300);
		// Teleport to the first column (leftmost position behind plants)
		var newX = gridStartX + gridWidth / 2;
		var newY = gridStartY + self.gridY * gridHeight + gridHeight / 2;
		// Animate teleportation with tween
		tween(self, {
			alpha: 0,
			scaleX: 0.5,
			scaleY: 0.5
		}, {
			duration: 500,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				// Move to new position
				self.x = newX;
				self.y = newY;
				// Animate appearing at new location
				tween(self, {
					alpha: 1,
					scaleX: 1,
					scaleY: 1
				}, {
					duration: 500,
					easing: tween.easeOut
				});
				// Flash effect when appearing
				LK.effects.flashObject(self, 0x00ff00, 300);
			}
		});
	};
	return self;
});
var JesterZombie = BasicZombie.expand(function () {
	var self = BasicZombie.call(this);
	// Replace the graphics with jester zombie asset
	self.removeChild(self.children[0]);
	var graphics = self.attachAsset('jesterZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 0.8;
	self.health = 120;
	self.maxHealth = 120;
	self.damage = 50;
	self.gridY = 0;
	self.attackTimer = 0;
	self.attackDelay = 60;
	self.isJester = true; // Flag to identify this zombie type
	// Override takeDamage to be immune to peas
	self.takeDamage = function (damage, source) {
		// Only take damage from non-pea sources
		if (source !== 'pea' && source !== 'frozenpea') {
			self.health -= damage;
			LK.effects.flashObject(self, 0xff0000, 200);
			LK.getSound('zombie_hit').play();
			if (self.health <= 0) {
				self.destroy();
				for (var i = 0; i < zombies.length; i++) {
					if (zombies[i] === self) {
						zombies.splice(i, 1);
						break;
					}
				}
				zombiesKilled++;
			}
		}
	};
	return self;
});
var JackInBoxZombie = BasicZombie.expand(function () {
	var self = BasicZombie.call(this);
	// Replace the graphics with jack in box zombie asset
	self.removeChild(self.children[0]);
	var graphics = self.attachAsset('jackInBoxZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 0.7;
	self.health = 80;
	self.maxHealth = 80;
	self.damage = 60;
	self.hasExploded = false;
	self.explode = function () {
		if (self.hasExploded) return;
		self.hasExploded = true;
		// Play explosion sound
		LK.getSound('explosion').play();
		// Flash the jack in box zombie white before exploding
		LK.effects.flashObject(self, 0xffffff, 200);
		// Scale up effect for explosion
		tween(graphics, {
			scaleX: 3,
			scaleY: 3,
			alpha: 0
		}, {
			duration: 500,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				// Remove from zombies array
				for (var i = 0; i < zombies.length; i++) {
					if (zombies[i] === self) {
						zombies.splice(i, 1);
						break;
					}
				}
				// Destroy the jack in box zombie
				self.destroy();
			}
		});
		// Eliminate plants in a 250 pixel radius
		var explosionRadius = 250;
		for (var i = plants.length - 1; i >= 0; i--) {
			var plant = plants[i];
			var distance = Math.sqrt(Math.pow(plant.x - self.x, 2) + Math.pow(plant.y - self.y, 2));
			if (distance <= explosionRadius) {
				// Flash plant red before destroying
				LK.effects.flashObject(plant, 0xff0000, 200);
				// Remove from plant grid
				var gridKey = plant.gridX + ',' + plant.gridY;
				delete plantGrid[gridKey];
				plant.destroy();
				plants.splice(i, 1);
			}
		}
	};
	self.update = function () {
		// Check if there's a plant to explode on
		var plantToExplode = null;
		for (var i = 0; i < plants.length; i++) {
			var plant = plants[i];
			if (plant.gridY === self.gridY && Math.abs(plant.x - self.x) < 80) {
				plantToExplode = plant;
				break;
			}
		}
		if (plantToExplode && !self.hasExploded) {
			self.explode();
		} else {
			self.x -= self.speed;
		}
		// Check if reached house
		if (self.x < 150) {
			LK.showGameOver();
		}
	};
	return self;
});
var Gargantuar = BasicZombie.expand(function () {
	var self = BasicZombie.call(this);
	// Replace the graphics with gargantuar asset
	self.removeChild(self.children[0]);
	var graphics = self.attachAsset('gargantuar', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 0.2; // Very slow
	self.health = 400; // Very resistant
	self.maxHealth = 400;
	self.damage = 200; // High damage to eliminate plants instantly
	self.gridY = 0;
	self.attackTimer = 0;
	self.attackDelay = 30; // Fast elimination
	self.hasSpawnedFastZombie = false;
	self.isResistantToExplosion = true; // Flag for cherry popper resistance
	self.update = function () {
		// Check if there's a plant to eliminate
		var plantToEliminate = null;
		for (var i = 0; i < plants.length; i++) {
			var plant = plants[i];
			if (plant.gridY === self.gridY && Math.abs(plant.x - self.x) < 120) {
				plantToEliminate = plant;
				break;
			}
		}
		if (plantToEliminate) {
			self.attackTimer++;
			if (self.attackTimer >= self.attackDelay) {
				// Instantly eliminate the plant
				LK.effects.flashObject(plantToEliminate, 0xff0000, 200);
				// Remove from plant grid
				var gridKey = plantToEliminate.gridX + ',' + plantToEliminate.gridY;
				delete plantGrid[gridKey];
				plantToEliminate.destroy();
				for (var j = 0; j < plants.length; j++) {
					if (plants[j] === plantToEliminate) {
						plants.splice(j, 1);
						break;
					}
				}
				LK.getSound('zombie_eat').play();
				self.attackTimer = 0;
			}
		} else {
			self.x -= self.speed;
			self.attackTimer = 0;
		}
		// Spawn FastZombie when at half health
		if (self.health <= self.maxHealth / 2 && !self.hasSpawnedFastZombie) {
			self.hasSpawnedFastZombie = true;
			var fastZombie = new FastZombie();
			// Spawn in the third square of the garden (gridStartX + 2 * gridWidth for third column)
			fastZombie.x = gridStartX + 2 * gridWidth + gridWidth / 2;
			fastZombie.y = gridStartY + self.gridY * gridHeight + gridHeight / 2;
			fastZombie.gridY = self.gridY;
			zombies.push(fastZombie);
			game.addChild(fastZombie);
			// Visual effect for spawning
			LK.effects.flashObject(self, 0xffff00, 500);
		}
		// Check if reached house
		if (self.x < 150) {
			LK.showGameOver();
		}
	};
	return self;
});
var FastZombie = BasicZombie.expand(function () {
	var self = BasicZombie.call(this);
	// Replace the graphics with fast zombie asset
	self.removeChild(self.children[0]);
	var graphics = self.attachAsset('fastZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 1.2;
	self.health = 60;
	self.maxHealth = 60;
	self.damage = 40;
	self.gridY = 0;
	self.attackTimer = 0;
	self.attackDelay = 60;
	return self;
});
var CherryPopper = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('cherrypopper', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 150;
	self.gridX = 0;
	self.gridY = 0;
	self.hasExploded = false;
	self.explode = function () {
		if (self.hasExploded) return;
		self.hasExploded = true;
		// Play explosion sound
		LK.getSound('explosion').play();
		// Flash the cherry popper white before exploding
		LK.effects.flashObject(self, 0xffffff, 200);
		// Scale up effect for explosion
		tween(graphics, {
			scaleX: 3,
			scaleY: 3,
			alpha: 0
		}, {
			duration: 500,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				// Remove from plants array
				for (var i = 0; i < plants.length; i++) {
					if (plants[i] === self) {
						plants.splice(i, 1);
						break;
					}
				}
				// Remove from plant grid
				var gridKey = self.gridX + ',' + self.gridY;
				delete plantGrid[gridKey];
				// Destroy the cherry popper
				self.destroy();
			}
		});
		// Eliminate zombies in a 300 pixel radius
		var explosionRadius = 300;
		for (var i = zombies.length - 1; i >= 0; i--) {
			var zombie = zombies[i];
			var distance = Math.sqrt(Math.pow(zombie.x - self.x, 2) + Math.pow(zombie.y - self.y, 2));
			if (distance <= explosionRadius) {
				// Special handling for Gargantuar
				if (zombie.constructor === Gargantuar) {
					// Flash zombie red
					LK.effects.flashObject(zombie, 0xff0000, 200);
					// If at full health or more than half, reduce to half
					if (zombie.health > zombie.maxHealth / 2) {
						zombie.health = zombie.maxHealth / 2;
						// Visual effect for being damaged but not destroyed
						tween(zombie, {
							tint: 0xff4444
						}, {
							duration: 500,
							easing: tween.easeOut
						});
					} else {
						// Second explosion - eliminate Gargantuar
						zombie.destroy();
						zombies.splice(i, 1);
						zombiesKilled++;
					}
				} else {
					// Normal zombies - eliminate immediately
					LK.effects.flashObject(zombie, 0xff0000, 200);
					zombie.destroy();
					zombies.splice(i, 1);
					zombiesKilled++;
				}
			}
		}
	};
	// Auto-explode when planted (immediately after placement)
	self.update = function () {
		if (!self.hasExploded) {
			self.explode();
		}
	};
	return self;
});
var Chomper = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('chomper', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 150;
	self.health = 100;
	self.maxHealth = 100;
	self.gridX = 0;
	self.gridY = 0;
	self.eatCooldown = 0;
	self.maxEatCooldown = 900; // 15 seconds at 60fps
	self.isOnCooldown = false;
	self.digestionTimer = 0;
	self.maxDigestionTime = 180; // 3 seconds to digest
	self.isDigesting = false;
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	self.update = function () {
		// Handle digestion timer
		if (self.isDigesting) {
			self.digestionTimer++;
			if (self.digestionTimer >= self.maxDigestionTime) {
				self.isDigesting = false;
				self.digestionTimer = 0;
				// Reset color after digesting
				tween(graphics, {
					tint: 0xffffff
				}, {
					duration: 300,
					easing: tween.easeOut
				});
			}
			return; // Don't eat while digesting
		}
		// Handle cooldown
		if (self.isOnCooldown) {
			self.eatCooldown--;
			if (self.eatCooldown <= 0) {
				self.isOnCooldown = false;
				// Reset color when cooldown ends
				tween(graphics, {
					tint: 0xffffff
				}, {
					duration: 300,
					easing: tween.easeOut
				});
			} else {
				// Ensure black color is maintained during cooldown
				if (graphics.tint !== 0x000000) {
					tween(graphics, {
						tint: 0x000000
					}, {
						duration: 100,
						easing: tween.easeOut
					});
				}
			}
			return; // Don't eat while on cooldown
		}
		// Look for the nearest zombie in adjacent squares (two square range)
		var nearestZombie = null;
		var nearestDistance = Infinity;
		var nearestIndex = -1;
		for (var i = zombies.length - 1; i >= 0; i--) {
			var zombie = zombies[i];
			// Check if zombie is in same lane and within two grid square range
			var gridDistance = Math.abs(zombie.x - self.x) / gridWidth;
			if (zombie.gridY === self.gridY && gridDistance <= 2.2) {
				var distance = Math.abs(zombie.x - self.x);
				if (distance < nearestDistance) {
					nearestDistance = distance;
					nearestZombie = zombie;
					nearestIndex = i;
				}
			}
		}
		// Eat the nearest zombie if found
		if (nearestZombie) {
			self.eatZombie(nearestZombie, nearestIndex);
		}
	};
	self.eatZombie = function (zombie, zombieIndex) {
		// Check if zombie is a Gargantuar - cannot be eaten
		if (zombie.constructor === Gargantuar) {
			// Flash red to show chomper can't eat this zombie
			LK.effects.flashObject(self, 0xff0000, 300);
			return; // Exit without eating
		}
		// Flash white to show eating action
		LK.effects.flashObject(self, 0xffffff, 300);
		// Remove zombie immediately
		zombie.destroy();
		zombies.splice(zombieIndex, 1);
		zombiesKilled++;
		// Start digestion period
		self.isDigesting = true;
		self.digestionTimer = 0;
		// Visual feedback for digesting (green tint)
		tween(graphics, {
			tint: 0x44ff44
		}, {
			duration: 300,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				// Start cooldown after digestion
				self.isOnCooldown = true;
				self.eatCooldown = self.maxEatCooldown;
				// Visual feedback for cooldown (black tint)
				tween(graphics, {
					tint: 0x000000
				}, {
					duration: 300,
					easing: tween.easeOut
				});
			}
		});
	};
	return self;
});
var FrozenPea = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('frozenpea', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 8;
	self.damage = 15;
	self.gridY = 0;
	self.slowDuration = 300; // 5 seconds at 60fps
	self.slowFactor = 0.6; // Reduce speed to 60%
	self.update = function () {
		self.x += self.speed;
		// Check collision with zombies
		for (var i = 0; i < zombies.length; i++) {
			var zombie = zombies[i];
			if (zombie.gridY === self.gridY && self.intersects(zombie)) {
				// Check if it's a JesterZombie
				if (zombie.isJester) {
					// Create reflected frozen pea going back towards plants
					var reflectedFrozenPea = new ReflectedFrozenPea();
					reflectedFrozenPea.x = zombie.x - 50;
					reflectedFrozenPea.y = zombie.y;
					reflectedFrozenPea.gridY = zombie.gridY;
					reflectedfrozenpeas.push(reflectedFrozenPea);
					game.addChild(reflectedFrozenPea);
					// Flash jester zombie to show deflection
					LK.effects.flashObject(zombie, 0xffff00, 200);
				} else {
					zombie.takeDamage(self.damage, 'frozenpea');
					LK.getSound('zombie_hit').play();
					// Apply slow effect only if not a Zomboni or NewspaperZombie
					if (zombie.constructor !== Zomboni && zombie.constructor !== NewspaperZombie) {
						if (!zombie.originalSpeed) {
							zombie.originalSpeed = zombie.speed;
						}
						zombie.speed = zombie.originalSpeed * self.slowFactor;
						zombie.slowTimer = self.slowDuration;
						// Play zombie_freezed sound when slowing
						LK.getSound('zombie_freezed').play();
						// Visual effect for slowed zombie
						tween(zombie, {
							tint: 0x87ceeb
						}, {
							duration: 300,
							easing: tween.easeOut
						});
					}
				}
				self.destroy();
				for (var j = 0; j < frozenpeas.length; j++) {
					if (frozenpeas[j] === self) {
						frozenpeas.splice(j, 1);
						break;
					}
				}
				return;
			}
		}
		// Remove if off screen
		if (self.x > 2200) {
			self.destroy();
			for (var k = 0; k < frozenpeas.length; k++) {
				if (frozenpeas[k] === self) {
					frozenpeas.splice(k, 1);
					break;
				}
			}
		}
	};
	return self;
});
var Pea = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('pea', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 8;
	self.damage = 15;
	self.gridY = 0;
	self.update = function () {
		self.x += self.speed;
		// Check collision with zombies
		for (var i = 0; i < zombies.length; i++) {
			var zombie = zombies[i];
			if (zombie.gridY === self.gridY && self.intersects(zombie)) {
				// Check if it's a JesterZombie
				if (zombie.isJester) {
					// Create reflected pea going back towards plants
					var reflectedPea = new ReflectedPea();
					reflectedPea.x = zombie.x - 50;
					reflectedPea.y = zombie.y;
					reflectedPea.gridY = zombie.gridY;
					reflectedpeas.push(reflectedPea);
					game.addChild(reflectedPea);
					// Flash jester zombie to show deflection
					LK.effects.flashObject(zombie, 0xffff00, 200);
				} else {
					zombie.takeDamage(self.damage, 'pea');
					LK.getSound('zombie_hit').play();
				}
				self.destroy();
				for (var j = 0; j < peas.length; j++) {
					if (peas[j] === self) {
						peas.splice(j, 1);
						break;
					}
				}
				return;
			}
		}
		// Remove if off screen
		if (self.x > 2200) {
			self.destroy();
			for (var k = 0; k < peas.length; k++) {
				if (peas[k] === self) {
					peas.splice(k, 1);
					break;
				}
			}
		}
	};
	return self;
});
var Peashooter = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('peashooter', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 100;
	self.health = 100;
	self.maxHealth = 100;
	self.shootTimer = 0;
	self.shootDelay = 90; // 1.5 seconds at 60fps
	self.gridX = 0;
	self.gridY = 0;
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	self.update = function () {
		self.shootTimer++;
		if (self.shootTimer >= self.shootDelay) {
			// Check if there's a zombie in this lane
			var hasZombieInLane = false;
			for (var i = 0; i < zombies.length; i++) {
				if (zombies[i].gridY === self.gridY && zombies[i].x > self.x) {
					hasZombieInLane = true;
					break;
				}
			}
			if (hasZombieInLane) {
				self.shoot();
				self.shootTimer = 0;
			}
		}
	};
	self.shoot = function () {
		var pea = new Pea();
		pea.x = self.x + 60;
		pea.y = self.y;
		pea.gridY = self.gridY;
		peas.push(pea);
		game.addChild(pea);
		LK.getSound('shoot').play();
	};
	return self;
});
var Potatomine = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('potatomine', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 25;
	self.health = 100;
	self.maxHealth = 100;
	self.gridX = 0;
	self.gridY = 0;
	self.chargeTimer = 0;
	self.maxChargeTime = 900; // 15 seconds at 60fps
	self.isCharged = false;
	self.hasExploded = false;
	// Start with black color (charging state)
	graphics.tint = 0x000000;
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	self.update = function () {
		// Handle charging timer
		if (!self.isCharged && !self.hasExploded) {
			self.chargeTimer++;
			if (self.chargeTimer >= self.maxChargeTime) {
				self.isCharged = true;
				// Change to normal color when charged
				tween(graphics, {
					tint: 0xffffff
				}, {
					duration: 500,
					easing: tween.easeOut
				});
			}
			return; // Don't explode while charging
		}
		// Check for zombies touching this potatomine
		if (self.isCharged && !self.hasExploded) {
			for (var i = 0; i < zombies.length; i++) {
				var zombie = zombies[i];
				if (zombie.gridY === self.gridY && self.intersects(zombie)) {
					self.explode();
					break;
				}
			}
		}
	};
	self.explode = function () {
		if (self.hasExploded) return;
		self.hasExploded = true;
		// Flash white before exploding
		LK.effects.flashObject(self, 0xffffff, 200);
		// Scale up effect for explosion
		tween(graphics, {
			scaleX: 3,
			scaleY: 3,
			alpha: 0
		}, {
			duration: 500,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				// Remove from plants array
				for (var i = 0; i < plants.length; i++) {
					if (plants[i] === self) {
						plants.splice(i, 1);
						break;
					}
				}
				// Remove from plant grid
				var gridKey = self.gridX + ',' + self.gridY;
				delete plantGrid[gridKey];
				// Destroy the potatomine
				self.destroy();
			}
		});
		// Eliminate zombies in a 200 pixel radius
		var explosionRadius = 200;
		for (var i = zombies.length - 1; i >= 0; i--) {
			var zombie = zombies[i];
			var distance = Math.sqrt(Math.pow(zombie.x - self.x, 2) + Math.pow(zombie.y - self.y, 2));
			if (distance <= explosionRadius) {
				// Special handling for Gargantuar and NewspaperZombie
				if (zombie.constructor === Gargantuar || zombie.constructor === NewspaperZombie) {
					// Flash zombie red
					LK.effects.flashObject(zombie, 0xff0000, 200);
					// Reduce to half health
					zombie.health = zombie.maxHealth / 2;
					// Visual effect for being damaged but not destroyed
					tween(zombie, {
						tint: 0xff4444
					}, {
						duration: 500,
						easing: tween.easeOut
					});
					// Check if zombie should be eliminated after damage
					if (zombie.health <= 0) {
						zombie.destroy();
						zombies.splice(i, 1);
						zombiesKilled++;
					}
				} else {
					// Normal zombies - eliminate immediately
					LK.effects.flashObject(zombie, 0xff0000, 200);
					zombie.destroy();
					zombies.splice(i, 1);
					zombiesKilled++;
				}
			}
		}
	};
	return self;
});
var Puffshroom = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('puffshroom', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 0;
	self.health = 100;
	self.maxHealth = 100;
	self.shootTimer = 0;
	self.shootDelay = 120; // 2 seconds at 60fps
	self.gridX = 0;
	self.gridY = 0;
	self.detectionRange = 3; // 3 tiles
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	self.update = function () {
		self.shootTimer++;
		if (self.shootTimer >= self.shootDelay) {
			// Check if there's a zombie within 3 tiles in this lane
			var hasZombieInRange = false;
			for (var i = 0; i < zombies.length; i++) {
				var zombie = zombies[i];
				if (zombie.gridY === self.gridY && zombie.x > self.x) {
					var distance = Math.abs(zombie.x - self.x);
					var tileDistance = distance / gridWidth;
					if (tileDistance <= self.detectionRange) {
						hasZombieInRange = true;
						break;
					}
				}
			}
			if (hasZombieInRange) {
				self.shoot();
				self.shootTimer = 0;
			}
		}
	};
	self.shoot = function () {
		var spore = new Spore();
		spore.x = self.x + 40;
		spore.y = self.y;
		spore.gridY = self.gridY;
		spores.push(spore);
		game.addChild(spore);
		LK.getSound('shoot').play();
	};
	return self;
});
var ReflectedFrozenPea = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('frozenpea', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Tint dark red to show it's reflected
	graphics.tint = 0xaa2222;
	self.speed = -8; // Negative speed to go backwards
	self.damage = 20; // Slightly more damage than regular frozen peas
	self.gridY = 0;
	self.update = function () {
		self.x += self.speed;
		// Check collision with plants
		for (var i = 0; i < plants.length; i++) {
			var plant = plants[i];
			if (plant.gridY === self.gridY && self.intersects(plant)) {
				if (plant.takeDamage) {
					plant.takeDamage(self.damage);
				}
				self.destroy();
				for (var j = 0; j < reflectedfrozenpeas.length; j++) {
					if (reflectedfrozenpeas[j] === self) {
						reflectedfrozenpeas.splice(j, 1);
						break;
					}
				}
				return;
			}
		}
		// Remove if off screen (left side)
		if (self.x < -100) {
			self.destroy();
			for (var k = 0; k < reflectedfrozenpeas.length; k++) {
				if (reflectedfrozenpeas[k] === self) {
					reflectedfrozenpeas.splice(k, 1);
					break;
				}
			}
		}
	};
	return self;
});
var ReflectedPea = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('pea', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Tint red to show it's reflected
	graphics.tint = 0xff4444;
	self.speed = -8; // Negative speed to go backwards
	self.damage = 20; // Slightly more damage than regular peas
	self.gridY = 0;
	self.update = function () {
		self.x += self.speed;
		// Check collision with plants
		for (var i = 0; i < plants.length; i++) {
			var plant = plants[i];
			if (plant.gridY === self.gridY && self.intersects(plant)) {
				if (plant.takeDamage) {
					plant.takeDamage(self.damage);
				}
				self.destroy();
				for (var j = 0; j < reflectedpeas.length; j++) {
					if (reflectedpeas[j] === self) {
						reflectedpeas.splice(j, 1);
						break;
					}
				}
				return;
			}
		}
		// Remove if off screen (left side)
		if (self.x < -100) {
			self.destroy();
			for (var k = 0; k < reflectedpeas.length; k++) {
				if (reflectedpeas[k] === self) {
					reflectedpeas.splice(k, 1);
					break;
				}
			}
		}
	};
	return self;
});
var ReflectedSpore = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('spore', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Tint dark brown to show it's reflected
	graphics.tint = 0x654321;
	self.speed = -6;
	self.damage = 15;
	self.gridY = 0;
	self.update = function () {
		self.x += self.speed;
		// Check collision with plants
		for (var i = 0; i < plants.length; i++) {
			var plant = plants[i];
			if (plant.gridY === self.gridY && self.intersects(plant)) {
				if (plant.takeDamage) {
					plant.takeDamage(self.damage);
				}
				self.destroy();
				for (var j = 0; j < reflectedspores.length; j++) {
					if (reflectedspores[j] === self) {
						reflectedspores.splice(j, 1);
						break;
					}
				}
				return;
			}
		}
		// Remove if off screen (left side)
		if (self.x < -100) {
			self.destroy();
			for (var k = 0; k < reflectedspores.length; k++) {
				if (reflectedspores[k] === self) {
					reflectedspores.splice(k, 1);
					break;
				}
			}
		}
	};
	return self;
});
var Repeater = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('repeater', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 200;
	self.health = 100;
	self.maxHealth = 100;
	self.shootTimer = 0;
	self.shootDelay = 90; // 1.5 seconds at 60fps
	self.secondShotTimer = 0;
	self.secondShotDelay = 15; // 0.25 seconds delay between shots
	self.waitingForSecondShot = false;
	self.gridX = 0;
	self.gridY = 0;
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	self.update = function () {
		// Handle second shot timing
		if (self.waitingForSecondShot) {
			self.secondShotTimer++;
			if (self.secondShotTimer >= self.secondShotDelay) {
				self.shoot(); // Fire second pea
				self.waitingForSecondShot = false;
				self.secondShotTimer = 0;
			}
		} else {
			self.shootTimer++;
			if (self.shootTimer >= self.shootDelay) {
				// Check if there's a zombie in this lane
				var hasZombieInLane = false;
				for (var i = 0; i < zombies.length; i++) {
					if (zombies[i].gridY === self.gridY && zombies[i].x > self.x) {
						hasZombieInLane = true;
						break;
					}
				}
				if (hasZombieInLane) {
					self.shoot(); // Fire first pea
					self.waitingForSecondShot = true; // Queue second shot
					self.shootTimer = 0;
				}
			}
		}
	};
	self.shoot = function () {
		var pea = new Pea();
		pea.x = self.x + 60;
		pea.y = self.y;
		pea.gridY = self.gridY;
		peas.push(pea);
		game.addChild(pea);
		LK.getSound('shoot').play();
	};
	return self;
});
var Snowshooter = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('snowshooter', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 175;
	self.health = 100;
	self.maxHealth = 100;
	self.shootTimer = 0;
	self.shootDelay = 90; // 1.5 seconds at 60fps
	self.gridX = 0;
	self.gridY = 0;
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	self.update = function () {
		self.shootTimer++;
		if (self.shootTimer >= self.shootDelay) {
			// Check if there's a zombie in this lane
			var hasZombieInLane = false;
			for (var i = 0; i < zombies.length; i++) {
				if (zombies[i].gridY === self.gridY && zombies[i].x > self.x) {
					hasZombieInLane = true;
					break;
				}
			}
			if (hasZombieInLane) {
				self.shoot();
				self.shootTimer = 0;
			}
		}
	};
	self.shoot = function () {
		var frozenpea = new FrozenPea();
		frozenpea.x = self.x + 60;
		frozenpea.y = self.y;
		frozenpea.gridY = self.gridY;
		frozenpeas.push(frozenpea);
		game.addChild(frozenpea);
		LK.getSound('shoot').play();
	};
	return self;
});
var SplitPea = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('splitpea', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 125;
	self.health = 100;
	self.maxHealth = 100;
	self.shootTimer = 0;
	self.shootDelay = 90; // 1.5 seconds at 60fps 
	self.gridX = 0;
	self.gridY = 0;
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback 
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	self.update = function () {
		self.shootTimer++;
		if (self.shootTimer >= self.shootDelay) {
			// Check if there's a zombie in this lane (both front and back) 
			var hasZombieInLane = false;
			for (var i = 0; i < zombies.length; i++) {
				if (zombies[i].gridY === self.gridY) {
					hasZombieInLane = true;
					break;
				}
			}
			if (hasZombieInLane) {
				self.shoot();
				self.shootTimer = 0;
			}
		}
	};
	self.shoot = function () {
		// Shoot one pea forward 
		var forwardPea = new Pea();
		forwardPea.x = self.x + 60;
		forwardPea.y = self.y;
		forwardPea.gridY = self.gridY;
		peas.push(forwardPea);
		game.addChild(forwardPea);
		// Shoot two peas backward 
		var backwardPea1 = new BackwardPea();
		backwardPea1.x = self.x - 60;
		backwardPea1.y = self.y - 20;
		backwardPea1.gridY = self.gridY;
		backwardpeas.push(backwardPea1);
		game.addChild(backwardPea1);
		var backwardPea2 = new BackwardPea();
		backwardPea2.x = self.x - 60;
		backwardPea2.y = self.y + 20;
		backwardPea2.gridY = self.gridY;
		backwardpeas.push(backwardPea2);
		game.addChild(backwardPea2);
		LK.getSound('shoot').play();
	};
	return self;
});
var Spore = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('spore', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 6;
	self.damage = 10;
	self.gridY = 0;
	self.update = function () {
		self.x += self.speed;
		// Check collision with zombies
		for (var i = 0; i < zombies.length; i++) {
			var zombie = zombies[i];
			if (zombie.gridY === self.gridY && self.intersects(zombie)) {
				// Check if it's a JesterZombie
				if (zombie.isJester) {
					// Create reflected spore going back towards plants
					var reflectedSpore = new ReflectedSpore();
					reflectedSpore.x = zombie.x - 50;
					reflectedSpore.y = zombie.y;
					reflectedSpore.gridY = zombie.gridY;
					reflectedspores.push(reflectedSpore);
					game.addChild(reflectedSpore);
					// Flash jester zombie to show deflection
					LK.effects.flashObject(zombie, 0xffff00, 200);
				} else {
					zombie.takeDamage(self.damage, 'spore');
					LK.getSound('zombie_hit').play();
				}
				self.destroy();
				for (var j = 0; j < spores.length; j++) {
					if (spores[j] === self) {
						spores.splice(j, 1);
						break;
					}
				}
				return;
			}
		}
		// Remove if off screen
		if (self.x > 2200) {
			self.destroy();
			for (var k = 0; k < spores.length; k++) {
				if (spores[k] === self) {
					spores.splice(k, 1);
					break;
				}
			}
		}
	};
	return self;
});
var Sun = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('sun', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.value = 25;
	self.lifeTimer = 0;
	self.maxLife = 600; // 10 seconds
	self.update = function () {
		self.lifeTimer++;
		if (self.lifeTimer > self.maxLife) {
			self.destroy();
			for (var i = 0; i < suns.length; i++) {
				if (suns[i] === self) {
					suns.splice(i, 1);
					break;
				}
			}
		}
	};
	self.down = function (x, y, obj) {
		sunPoints += self.value;
		updateSunDisplay();
		self.destroy();
		for (var i = 0; i < suns.length; i++) {
			if (suns[i] === self) {
				suns.splice(i, 1);
				break;
			}
		}
		LK.getSound('collect').play();
	};
	return self;
});
var Sunflower = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('sunflower', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 50;
	self.health = 100;
	self.maxHealth = 100;
	self.sunTimer = 0;
	self.sunDelay = 600; // 10 seconds at 60fps
	self.gridX = 0;
	self.gridY = 0;
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	self.update = function () {
		self.sunTimer++;
		if (self.sunTimer >= self.sunDelay) {
			self.produceSun();
			self.sunTimer = 0;
		}
	};
	self.produceSun = function () {
		var sun = new Sun();
		sun.x = self.x + (Math.random() - 0.5) * 50;
		sun.y = self.y + (Math.random() - 0.5) * 50;
		suns.push(sun);
		game.addChild(sun);
	};
	return self;
});
var WallNut = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('wallnut', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 50;
	self.health = 300;
	self.maxHealth = 300;
	self.gridX = 0;
	self.gridY = 0;
	self.takeDamage = function (damage) {
		self.health -= damage;
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x8BC34A
});
/**** 
* Game Code
****/ 
// Sounds
// Zombies
// Projectiles and collectibles
// Plants
// Game grid and UI elements
// Game mode variables
var gameMode = null; // 'normal' or 'endless'
var gameStarted = false;
var menuVisible = true;
// Game variables
var sunPoints = 150;
var currentWave = 1;
var maxWaves = 20;
var waveTimer = 0;
var waveDelay = 1800; // 30 seconds
var zombieSpawnTimer = 0;
var zombieSpawnDelay = 240; // 4 seconds
var zombiesPerWave = 5;
var zombiesSpawned = 0;
var zombiesKilled = 0;
var totalZombiesToKill = 0;
var waveStarted = false;
var zombieSpawnQueue = [];
// Game arrays
var plants = [];
var zombies = [];
var peas = [];
var frozenpeas = [];
var reflectedpeas = [];
var reflectedfrozenpeas = [];
var backwardpeas = [];
var spores = [];
var reflectedspores = [];
var suns = [];
var plantGrid = {}; // Track occupied grid positions
// Grid settings
var gridStartX = 400;
var gridStartY = 400;
var gridWidth = 320;
var gridHeight = 227;
var gridCols = 5;
var gridRows = 5;
// Selected plant type
var selectedPlantType = null;
// Plant selector management
var currentSelectorPage = 1;
var maxSelectorPages = 2;
// Create lawn grid
for (var row = 0; row < gridRows; row++) {
	for (var col = 0; col < gridCols; col++) {
		var tile = game.addChild(LK.getAsset('grass', {
			x: gridStartX + col * gridWidth,
			y: gridStartY + row * gridHeight,
			anchorX: 0,
			anchorY: 0
		}));
	}
}
// Create paths (zombie lanes)
for (var lane = 0; lane < gridRows; lane++) {
	var pathTile = game.addChild(LK.getAsset('path', {
		x: gridStartX + gridCols * gridWidth,
		y: gridStartY + lane * gridHeight,
		anchorX: 0,
		anchorY: 0
	}));
}
// Create house
var house = game.addChild(LK.getAsset('house', {
	x: 50,
	y: gridStartY + gridRows * gridHeight / 2 - 200,
	anchorX: 0,
	anchorY: 0
}));
// UI Setup
var sunDisplay = new Text2(sunPoints.toString(), {
	size: 80,
	fill: 0xFFD700,
	stroke: 0x000000,
	strokeThickness: 3
});
sunDisplay.anchor.set(0, 0);
LK.gui.topLeft.addChild(sunDisplay);
sunDisplay.x = 120;
sunDisplay.y = 20;
var waveDisplay = new Text2('Wave: ' + currentWave + '/' + maxWaves, {
	size: 60,
	fill: 0x000000
});
waveDisplay.anchor.set(0.5, 0);
LK.gui.top.addChild(waveDisplay);
waveDisplay.y = 20;
// Plant selection buttons - repositioned for new order
var peashooterBtn = LK.getAsset('peashooter', {
	x: 250,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(peashooterBtn);
var sunflowerBtn = LK.getAsset('sunflower', {
	x: 450,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(sunflowerBtn);
var cherrypopperBtn = LK.getAsset('cherrypopper', {
	x: 650,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(cherrypopperBtn);
var wallnutBtn = LK.getAsset('wallnut', {
	x: 850,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(wallnutBtn);
var potatomineBtn = LK.getAsset('potatomine', {
	x: 1050,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(potatomineBtn);
var snowshooterBtn = LK.getAsset('snowshooter', {
	x: 1250,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(snowshooterBtn);
var chomperBtn = LK.getAsset('chomper', {
	x: 1450,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(chomperBtn);
var repeaterBtn = LK.getAsset('repeater', {
	x: 1650,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(repeaterBtn);
var splitpeaBtn = LK.getAsset('splitpea', {
	x: 250,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(splitpeaBtn);
var puffshroomBtn = LK.getAsset('puffshroom', {
	x: 450,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(puffshroomBtn);
var shovelBtn = LK.getAsset('shovel', {
	x: 1900,
	y: 150,
	scaleX: 1.5,
	scaleY: 1.5,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(shovelBtn);
// Cost display texts - updated positions to match new layout
var peaCostTxt = new Text2('100', {
	size: 70,
	fill: 0x000000
});
peaCostTxt.anchor.set(0.5, 0);
game.addChild(peaCostTxt);
peaCostTxt.x = 250;
peaCostTxt.y = 2580;
var sunCostTxt = new Text2('50', {
	size: 70,
	fill: 0x000000
});
sunCostTxt.anchor.set(0.5, 0);
game.addChild(sunCostTxt);
sunCostTxt.x = 450;
sunCostTxt.y = 2580;
var cherryCostTxt = new Text2('150', {
	size: 70,
	fill: 0x000000
});
cherryCostTxt.anchor.set(0.5, 0);
game.addChild(cherryCostTxt);
cherryCostTxt.x = 650;
cherryCostTxt.y = 2580;
var wallCostTxt = new Text2('50', {
	size: 70,
	fill: 0x000000
});
wallCostTxt.anchor.set(0.5, 0);
game.addChild(wallCostTxt);
wallCostTxt.x = 850;
wallCostTxt.y = 2580;
var potatomineCosTxt = new Text2('25', {
	size: 70,
	fill: 0x000000
});
potatomineCosTxt.anchor.set(0.5, 0);
game.addChild(potatomineCosTxt);
potatomineCosTxt.x = 1050;
potatomineCosTxt.y = 2580;
var snowCostTxt = new Text2('175', {
	size: 70,
	fill: 0x000000
});
snowCostTxt.anchor.set(0.5, 0);
game.addChild(snowCostTxt);
snowCostTxt.x = 1250;
snowCostTxt.y = 2580;
var chomperCostTxt = new Text2('150', {
	size: 70,
	fill: 0x000000
});
chomperCostTxt.anchor.set(0.5, 0);
game.addChild(chomperCostTxt);
chomperCostTxt.x = 1450;
chomperCostTxt.y = 2580;
var repeaterCostTxt = new Text2('200', {
	size: 70,
	fill: 0x000000
});
repeaterCostTxt.anchor.set(0.5, 0);
game.addChild(repeaterCostTxt);
repeaterCostTxt.x = 1650;
repeaterCostTxt.y = 2580;
var splitpeaCostTxt = new Text2('125', {
	size: 70,
	fill: 0x000000
});
splitpeaCostTxt.anchor.set(0.5, 0);
game.addChild(splitpeaCostTxt);
splitpeaCostTxt.x = 250;
splitpeaCostTxt.y = 2580;
var puffshroomCostTxt = new Text2('0', {
	size: 70,
	fill: 0x000000
});
puffshroomCostTxt.anchor.set(0.5, 0);
game.addChild(puffshroomCostTxt);
puffshroomCostTxt.x = 450;
puffshroomCostTxt.y = 2580;
var shovelCostTxt = new Text2('Free', {
	size: 70,
	fill: 0x000000
});
shovelCostTxt.anchor.set(0.5, 0);
game.addChild(shovelCostTxt);
shovelCostTxt.x = 1900;
shovelCostTxt.y = 230;
// Add left arrow for plant selector
var leftArrow = new Text2('<', {
	size: 120,
	fill: 0x000000
});
leftArrow.anchor.set(0.5, 0.5);
game.addChild(leftArrow);
leftArrow.x = 50;
leftArrow.y = 2500;
// Add right arrow for plant selector
var rightArrow = new Text2('>', {
	size: 120,
	fill: 0x000000
});
rightArrow.anchor.set(0.5, 0.5);
game.addChild(rightArrow);
rightArrow.x = 2000;
rightArrow.y = 2500;
// Calculate total zombies for victory condition
for (var w = 1; w <= maxWaves; w++) {
	totalZombiesToKill += zombiesPerWave + Math.floor(w / 2);
}
function updateSunDisplay() {
	sunDisplay.setText(sunPoints.toString());
}
function updatePlantSelector() {
	// Hide all plants first
	peashooterBtn.visible = false;
	sunflowerBtn.visible = false;
	wallnutBtn.visible = false;
	snowshooterBtn.visible = false;
	repeaterBtn.visible = false;
	cherrypopperBtn.visible = false;
	splitpeaBtn.visible = false;
	chomperBtn.visible = false;
	potatomineBtn.visible = false;
	puffshroomBtn.visible = false;
	// Hide all cost texts
	peaCostTxt.visible = false;
	sunCostTxt.visible = false;
	wallCostTxt.visible = false;
	snowCostTxt.visible = false;
	repeaterCostTxt.visible = false;
	cherryCostTxt.visible = false;
	splitpeaCostTxt.visible = false;
	chomperCostTxt.visible = false;
	potatomineCosTxt.visible = false;
	puffshroomCostTxt.visible = false;
	if (currentSelectorPage === 1) {
		// First page - show: Peashooter, Sunflower, Cherrypopper, Wallnut, Potatomine, Snowshooter, Chomper, and Repeater
		peashooterBtn.visible = true;
		sunflowerBtn.visible = true;
		cherrypopperBtn.visible = true;
		wallnutBtn.visible = true;
		potatomineBtn.visible = true;
		snowshooterBtn.visible = true;
		chomperBtn.visible = true;
		repeaterBtn.visible = true;
		// Show corresponding cost texts
		peaCostTxt.visible = true;
		sunCostTxt.visible = true;
		cherryCostTxt.visible = true;
		wallCostTxt.visible = true;
		potatomineCosTxt.visible = true;
		snowCostTxt.visible = true;
		chomperCostTxt.visible = true;
		repeaterCostTxt.visible = true;
	} else if (currentSelectorPage === 2) {
		// Second page - show splitpea and puffshroom (only from wave 11)
		splitpeaBtn.visible = true;
		splitpeaCostTxt.visible = true;
		if (currentWave >= 11) {
			puffshroomBtn.visible = true;
			puffshroomCostTxt.visible = true;
		}
	}
}
function getGridPosition(x, y) {
	var col = Math.floor((x - gridStartX) / gridWidth);
	var row = Math.floor((y - gridStartY) / gridHeight);
	if (col >= 0 && col < gridCols && row >= 0 && row < gridRows) {
		return {
			col: col,
			row: row,
			x: gridStartX + col * gridWidth + gridWidth / 2,
			y: gridStartY + row * gridHeight + gridHeight / 2
		};
	}
	return null;
}
function spawnZombie() {
	var lane = Math.floor(Math.random() * gridRows);
	var zombieType = Math.random();
	var zombie;
	// Higher spawn rates for special zombies from wave 15 onwards
	if (currentWave >= 15) {
		if (zombieType < 0.22) {
			zombie = new Gargantuar();
		} else if (zombieType < 0.44) {
			zombie = new Zomboni();
		} else if (zombieType < 0.58) {
			zombie = new JesterZombie();
		} else if (zombieType < 0.68) {
			zombie = new TankZombie();
		} else if (zombieType < 0.73) {
			zombie = new JackInBoxZombie();
		} else if (zombieType < 0.79) {
			zombie = new MinerZombie();
		} else if (zombieType < 0.85) {
			zombie = new FastZombie();
		} else if (zombieType < 0.91) {
			zombie = new NewspaperZombie();
		} else if (zombieType < 0.97) {
			zombie = new VeteranNewspaperZombie();
		} else {
			zombie = new BasicZombie();
		}
	} else {
		// Original spawn rates for waves before 15
		if (currentWave > 8 && zombieType < 0.05) {
			zombie = new Gargantuar();
		} else if (currentWave > 6 && zombieType < 0.15) {
			zombie = new Zomboni();
		} else if (currentWave > 5 && zombieType < 0.25) {
			zombie = new TankZombie();
		} else if (currentWave > 4 && zombieType < 0.35) {
			zombie = new JesterZombie();
		} else if (currentWave > 2 && zombieType < 0.45) {
			zombie = new JackInBoxZombie();
		} else if (currentWave > 3 && zombieType < 0.60) {
			zombie = new MinerZombie();
		} else if (currentWave > 3 && zombieType < 0.75) {
			zombie = new FastZombie();
		} else if (currentWave > 1 && zombieType < 0.85) {
			zombie = new NewspaperZombie();
		} else if (currentWave > 7 && zombieType < 0.95) {
			zombie = new VeteranNewspaperZombie();
		} else {
			zombie = new BasicZombie();
		}
	}
	zombie.x = gridStartX + gridCols * gridWidth + 100;
	zombie.y = gridStartY + lane * gridHeight + gridHeight / 2;
	zombie.gridY = lane;
	// Add spawn delay animation - zombie starts invisible and fades in
	zombie.alpha = 0;
	zombie.scaleX = 0.5;
	zombie.scaleY = 0.5;
	// Animate zombie spawning in
	tween(zombie, {
		alpha: 1,
		scaleX: 1,
		scaleY: 1
	}, {
		duration: 800,
		easing: tween.easeOut
	});
	zombies.push(zombie);
	game.addChild(zombie);
	zombiesSpawned++;
}
function startNextWave() {
	// In endless mode, there's no wave limit
	var shouldStartWave = gameMode === 'normal' && currentWave <= maxWaves || gameMode === 'endless';
	if (shouldStartWave) {
		// In endless mode, increase difficulty more aggressively
		if (gameMode === 'endless') {
			zombiesPerWave = 5 + Math.floor(currentWave / 1.5); // Faster increase in endless mode
		} else {
			zombiesPerWave = 5 + Math.floor(currentWave / 2);
		}
		zombiesSpawned = 0;
		waveStarted = false;
		zombieSpawnQueue = [];
		// Display wave differently for endless mode
		if (gameMode === 'endless') {
			waveDisplay.setText('Wave: ' + currentWave + ' (Endless)');
		} else {
			waveDisplay.setText('Wave: ' + currentWave + '/' + maxWaves);
		}
		// Play Ultimate Battle music for all waves
		LK.playMusic('ultimate_battle');
		// Change background color to dark blue from wave 11
		if (currentWave >= 11) {
			game.setBackgroundColor(0x191970); // Dark blue
		}
		// Flash screen red when wave increases
		LK.effects.flashScreen(0xff0000, 1000);
		// Add delay before wave actually starts spawning zombies
		// For wave 1, add 10 second delay. For other waves, 2 second delay
		var waveStartDelay = currentWave === 1 ? 10000 : 2000;
		LK.setTimeout(function () {
			waveStarted = true;
			// Pre-queue zombie spawn times with delays
			// Use faster spawn delay from wave 5 onwards with higher spawn rate, and even faster from wave 11
			// In endless mode, spawn rate increases even more aggressively
			var currentSpawnDelay;
			if (gameMode === 'endless') {
				// Endless mode has progressively faster spawns
				if (currentWave >= 20) {
					currentSpawnDelay = 30; // Very fast from wave 20 (0.5 seconds)
				} else if (currentWave >= 15) {
					currentSpawnDelay = 45; // Faster from wave 15 (0.75 seconds)
				} else if (currentWave >= 10) {
					currentSpawnDelay = 60; // Fast from wave 10 (1 second)
				} else if (currentWave >= 5) {
					currentSpawnDelay = 90; // Medium speed from wave 5 (1.5 seconds)
				} else {
					currentSpawnDelay = zombieSpawnDelay; // Normal speed (4 seconds)
				}
			} else {
				// Normal mode spawn rates
				if (currentWave >= 11) {
					currentSpawnDelay = 60; // Even faster from wave 11 (1 second)
				} else if (currentWave >= 5) {
					currentSpawnDelay = 90; // Higher spawn rate from wave 5 (1.5 seconds)
				} else {
					currentSpawnDelay = zombieSpawnDelay; // Normal speed (4 seconds)
				}
			}
			for (var i = 0; i < zombiesPerWave; i++) {
				zombieSpawnQueue.push({
					spawnTime: LK.ticks + i * currentSpawnDelay + Math.random() * 60,
					// Add some randomness (reduced for faster waves)
					spawned: false
				});
			}
		}, waveStartDelay);
	}
}
// Generate sun periodically
var sunGenerationTimer = 0;
var sunGenerationDelay = 480; // 8 seconds
// Event handlers
peashooterBtn.down = function () {
	if (sunPoints >= 100) {
		selectedPlantType = 'peashooter';
		LK.effects.flashObject(peashooterBtn, 0x00ff00, 300);
	}
};
sunflowerBtn.down = function () {
	if (sunPoints >= 50) {
		selectedPlantType = 'sunflower';
		LK.effects.flashObject(sunflowerBtn, 0x00ff00, 300);
	}
};
wallnutBtn.down = function () {
	if (sunPoints >= 50) {
		selectedPlantType = 'wallnut';
		LK.effects.flashObject(wallnutBtn, 0x00ff00, 300);
	}
};
snowshooterBtn.down = function () {
	if (sunPoints >= 175) {
		selectedPlantType = 'snowshooter';
		LK.effects.flashObject(snowshooterBtn, 0x00ff00, 300);
	}
};
repeaterBtn.down = function () {
	if (sunPoints >= 200) {
		selectedPlantType = 'repeater';
		LK.effects.flashObject(repeaterBtn, 0x00ff00, 300);
	}
};
cherrypopperBtn.down = function () {
	if (sunPoints >= 150) {
		selectedPlantType = 'cherrypopper';
		LK.effects.flashObject(cherrypopperBtn, 0x00ff00, 300);
	}
};
splitpeaBtn.down = function () {
	if (sunPoints >= 125) {
		selectedPlantType = 'splitpea';
		LK.effects.flashObject(splitpeaBtn, 0x00ff00, 300);
	}
};
chomperBtn.down = function () {
	if (sunPoints >= 150) {
		selectedPlantType = 'chomper';
		LK.effects.flashObject(chomperBtn, 0x00ff00, 300);
	}
};
potatomineBtn.down = function () {
	if (sunPoints >= 25) {
		selectedPlantType = 'potatomine';
		LK.effects.flashObject(potatomineBtn, 0x00ff00, 300);
	}
};
puffshroomBtn.down = function () {
	if (currentWave >= 11) {
		selectedPlantType = 'puffshroom';
		LK.effects.flashObject(puffshroomBtn, 0x00ff00, 300);
	}
};
shovelBtn.down = function () {
	selectedPlantType = 'shovel';
	LK.effects.flashObject(shovelBtn, 0x00ff00, 300);
};
leftArrow.down = function () {
	if (currentSelectorPage > 1) {
		currentSelectorPage--;
		updatePlantSelector();
		LK.effects.flashObject(leftArrow, 0x00ff00, 200);
	} else {
		// Flash gray if can't go back further
		LK.effects.flashObject(leftArrow, 0x888888, 200);
	}
};
rightArrow.down = function () {
	if (currentSelectorPage < maxSelectorPages) {
		currentSelectorPage++;
		updatePlantSelector();
		LK.effects.flashObject(rightArrow, 0x00ff00, 200);
	} else {
		// Flash gray if can't go forward further
		LK.effects.flashObject(rightArrow, 0x888888, 200);
	}
};
game.down = function (x, y, obj) {
	// Don't allow plant placement if menu is visible
	if (menuVisible || !gameStarted) {
		return;
	}
	var gridPos = getGridPosition(x, y);
	if (gridPos && selectedPlantType) {
		var gridKey = gridPos.col + ',' + gridPos.row;
		// Handle shovel - remove existing plant
		if (selectedPlantType === 'shovel') {
			if (plantGrid[gridKey]) {
				var plantToRemove = plantGrid[gridKey];
				// Remove from plants array
				for (var i = 0; i < plants.length; i++) {
					if (plants[i] === plantToRemove) {
						plants.splice(i, 1);
						break;
					}
				}
				// Remove from grid
				delete plantGrid[gridKey];
				// Destroy the plant
				plantToRemove.destroy();
				selectedPlantType = null;
			}
			return;
		}
		// Check if position is already occupied
		if (plantGrid[gridKey]) {
			return;
		}
		var plant = null;
		var cost = 0;
		if (selectedPlantType === 'peashooter' && sunPoints >= 100) {
			plant = new Peashooter();
			cost = 100;
		} else if (selectedPlantType === 'sunflower' && sunPoints >= 50) {
			plant = new Sunflower();
			cost = 50;
		} else if (selectedPlantType === 'wallnut' && sunPoints >= 50) {
			plant = new WallNut();
			cost = 50;
		} else if (selectedPlantType === 'snowshooter' && sunPoints >= 175) {
			plant = new Snowshooter();
			cost = 175;
		} else if (selectedPlantType === 'repeater' && sunPoints >= 200) {
			plant = new Repeater();
			cost = 200;
		} else if (selectedPlantType === 'cherrypopper' && sunPoints >= 150) {
			plant = new CherryPopper();
			cost = 150;
		} else if (selectedPlantType === 'splitpea' && sunPoints >= 125) {
			plant = new SplitPea();
			cost = 125;
		} else if (selectedPlantType === 'chomper' && sunPoints >= 150) {
			plant = new Chomper();
			cost = 150;
		} else if (selectedPlantType === 'potatomine' && sunPoints >= 25) {
			plant = new Potatomine();
			cost = 25;
		} else if (selectedPlantType === 'puffshroom' && currentWave >= 11) {
			plant = new Puffshroom();
			cost = 0;
		}
		if (plant) {
			plant.x = gridPos.x;
			plant.y = gridPos.y;
			plant.gridX = gridPos.col;
			plant.gridY = gridPos.row;
			plants.push(plant);
			game.addChild(plant);
			plantGrid[gridKey] = plant;
			sunPoints -= cost;
			updateSunDisplay();
			selectedPlantType = null;
			// 50% chance to play either seed_plant1 or seed_plant2
			if (Math.random() < 0.5) {
				LK.getSound('seed_plant1').play();
			} else {
				LK.getSound('seed_plant2').play();
			}
		}
	}
};
game.update = function () {
	// Don't update game logic if menu is visible
	if (menuVisible || !gameStarted) {
		return;
	}
	// Generate sun periodically
	sunGenerationTimer++;
	if (sunGenerationTimer >= sunGenerationDelay) {
		var sun = new Sun();
		sun.x = 200 + Math.random() * 1600;
		sun.y = -100; // Start above screen
		sun.targetY = 200 + Math.random() * 1000; // Final position
		sun.isFalling = true; // Mark as falling sun
		// Animate falling from top to bottom
		tween(sun, {
			y: sun.targetY
		}, {
			duration: 2000,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				sun.isFalling = false;
			}
		});
		suns.push(sun);
		game.addChild(sun);
		sunGenerationTimer = 0;
	}
	// Wave management
	if (currentWave <= maxWaves) {
		waveTimer++;
		// Spawn zombies for current wave using queue system
		if (waveStarted && zombiesSpawned < zombiesPerWave) {
			for (var i = 0; i < zombieSpawnQueue.length; i++) {
				var queueItem = zombieSpawnQueue[i];
				if (!queueItem.spawned && LK.ticks >= queueItem.spawnTime) {
					spawnZombie();
					queueItem.spawned = true;
					break; // Only spawn one zombie per frame
				}
			}
		}
		// Start next wave
		if (zombiesSpawned >= zombiesPerWave && zombies.length === 0) {
			currentWave++;
			if (currentWave <= maxWaves) {
				startNextWave();
				waveTimer = 0;
			}
		}
	}
	// Check victory condition (only for normal mode)
	if (gameMode === 'normal' && currentWave > maxWaves && zombies.length === 0) {
		LK.showYouWin();
	}
	// Handle slow effects on zombies
	for (var z = 0; z < zombies.length; z++) {
		var zombie = zombies[z];
		if (zombie.slowTimer) {
			zombie.slowTimer--;
			if (zombie.slowTimer <= 0) {
				// Restore original speed
				if (zombie.originalSpeed) {
					zombie.speed = zombie.originalSpeed;
				}
				// Remove slow tint
				tween(zombie, {
					tint: 0xffffff
				}, {
					duration: 300,
					easing: tween.easeOut
				});
				zombie.slowTimer = null;
			}
		}
	}
	// Update button availability
	peashooterBtn.alpha = sunPoints >= 100 ? 1.0 : 0.5;
	sunflowerBtn.alpha = sunPoints >= 50 ? 1.0 : 0.5;
	wallnutBtn.alpha = sunPoints >= 50 ? 1.0 : 0.5;
	snowshooterBtn.alpha = sunPoints >= 175 ? 1.0 : 0.5;
	repeaterBtn.alpha = sunPoints >= 200 ? 1.0 : 0.5;
	cherrypopperBtn.alpha = sunPoints >= 150 ? 1.0 : 0.5;
	splitpeaBtn.alpha = sunPoints >= 125 ? 1.0 : 0.5;
	chomperBtn.alpha = sunPoints >= 150 ? 1.0 : 0.5;
	potatomineBtn.alpha = sunPoints >= 25 ? 1.0 : 0.5;
	puffshroomBtn.alpha = currentWave >= 11 && sunPoints >= 0 ? 1.0 : 0.5;
	shovelBtn.alpha = 1.0; // Shovel is always available
	// Update arrow button availability
	updateArrowButtons();
};
// Initialize plant selector
updatePlantSelector();
// Update arrow button availability in main update loop
function updateArrowButtons() {
	leftArrow.alpha = currentSelectorPage > 1 ? 1.0 : 0.5;
	rightArrow.alpha = currentSelectorPage < maxSelectorPages ? 1.0 : 0.5;
}
// Create menu buttons
var normalBtn = new Text2('NORMAL', {
	size: 120,
	fill: 0x00ff00,
	stroke: 0x000000,
	strokeThickness: 4
});
normalBtn.anchor.set(0.5, 0.5);
normalBtn.x = 1024;
normalBtn.y = 1200;
game.addChild(normalBtn);
var endlessBtn = new Text2('ENDLESS', {
	size: 120,
	fill: 0xff6600,
	stroke: 0x000000,
	strokeThickness: 4
});
endlessBtn.anchor.set(0.5, 0.5);
endlessBtn.x = 1024;
endlessBtn.y = 1400;
game.addChild(endlessBtn);
var modeDescriptionTxt = new Text2('Choose Game Mode:', {
	size: 100,
	fill: 0x000000
});
modeDescriptionTxt.anchor.set(0.5, 0.5);
modeDescriptionTxt.x = 1024;
modeDescriptionTxt.y = 1000;
game.addChild(modeDescriptionTxt);
var normalDescTxt = new Text2('20 waves with victory condition', {
	size: 60,
	fill: 0x333333
});
normalDescTxt.anchor.set(0.5, 0.5);
normalDescTxt.x = 1024;
normalDescTxt.y = 1280;
game.addChild(normalDescTxt);
var endlessDescTxt = new Text2('Infinite waves with increasing difficulty', {
	size: 60,
	fill: 0x333333
});
endlessDescTxt.anchor.set(0.5, 0.5);
endlessDescTxt.x = 1024;
endlessDescTxt.y = 1480;
game.addChild(endlessDescTxt);
// Menu button event handlers
normalBtn.down = function () {
	gameMode = 'normal';
	startGame();
};
endlessBtn.down = function () {
	gameMode = 'endless';
	startGame();
};
function startGame() {
	gameStarted = true;
	menuVisible = false;
	// Hide menu elements
	normalBtn.visible = false;
	endlessBtn.visible = false;
	modeDescriptionTxt.visible = false;
	normalDescTxt.visible = false;
	endlessDescTxt.visible = false;
	// Show game UI elements
	sunDisplay.visible = true;
	waveDisplay.visible = true;
	peashooterBtn.visible = true;
	sunflowerBtn.visible = true;
	cherrypopperBtn.visible = true;
	wallnutBtn.visible = true;
	potatomineBtn.visible = true;
	snowshooterBtn.visible = true;
	chomperBtn.visible = true;
	repeaterBtn.visible = true;
	splitpeaBtn.visible = true;
	puffshroomBtn.visible = true;
	shovelBtn.visible = true;
	leftArrow.visible = true;
	rightArrow.visible = true;
	// Show cost texts
	peaCostTxt.visible = true;
	sunCostTxt.visible = true;
	cherryCostTxt.visible = true;
	wallCostTxt.visible = true;
	potatomineCosTxt.visible = true;
	snowCostTxt.visible = true;
	chomperCostTxt.visible = true;
	repeaterCostTxt.visible = true;
	splitpeaCostTxt.visible = true;
	puffshroomCostTxt.visible = true;
	shovelCostTxt.visible = true;
	// Update plant selector to show correct page
	updatePlantSelector();
	// Start first wave
	startNextWave();
}
// Initially hide game UI elements
sunDisplay.visible = false;
waveDisplay.visible = false;
peashooterBtn.visible = false;
sunflowerBtn.visible = false;
cherrypopperBtn.visible = false;
wallnutBtn.visible = false;
potatomineBtn.visible = false;
snowshooterBtn.visible = false;
chomperBtn.visible = false;
repeaterBtn.visible = false;
splitpeaBtn.visible = false;
puffshroomBtn.visible = false;
shovelBtn.visible = false;
leftArrow.visible = false;
rightArrow.visible = false;
peaCostTxt.visible = false;
sunCostTxt.visible = false;
cherryCostTxt.visible = false;
wallCostTxt.visible = false;
potatomineCosTxt.visible = false;
snowCostTxt.visible = false;
chomperCostTxt.visible = false;
repeaterCostTxt.visible = false;
splitpeaCostTxt.visible = false;
puffshroomCostTxt.visible = false;
shovelCostTxt.visible = false; /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var BackwardPea = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('pea', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Tint green to show it's from splitpea
	graphics.tint = 0x44ff44;
	self.speed = -8; // Negative speed to go backwards 
	self.damage = 15;
	self.gridY = 0;
	self.update = function () {
		self.x += self.speed;
		// Check collision with zombies 
		for (var i = 0; i < zombies.length; i++) {
			var zombie = zombies[i];
			if (zombie.gridY === self.gridY && self.intersects(zombie)) {
				// Check if it's a JesterZombie 
				if (zombie.isJester) {
					// Create reflected pea going forward 
					var reflectedPea = new ReflectedPea();
					reflectedPea.x = zombie.x + 50;
					reflectedPea.y = zombie.y;
					reflectedPea.gridY = zombie.gridY;
					reflectedpeas.push(reflectedPea);
					game.addChild(reflectedPea);
					// Flash jester zombie to show deflection 
					LK.effects.flashObject(zombie, 0xffff00, 200);
				} else {
					zombie.takeDamage(self.damage, 'pea');
					LK.getSound('zombie_hit').play();
				}
				self.destroy();
				for (var j = 0; j < backwardpeas.length; j++) {
					if (backwardpeas[j] === self) {
						backwardpeas.splice(j, 1);
						break;
					}
				}
				return;
			}
		}
		// Remove if off screen (left side) 
		if (self.x < -100) {
			self.destroy();
			for (var k = 0; k < backwardpeas.length; k++) {
				if (backwardpeas[k] === self) {
					backwardpeas.splice(k, 1);
					break;
				}
			}
		}
	};
	return self;
});
var BasicZombie = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('basicZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 0.5;
	self.health = 100;
	self.maxHealth = 100;
	self.damage = 40;
	self.gridY = 0;
	self.attackTimer = 0;
	self.attackDelay = 60;
	self.update = function () {
		// Check if there's a plant to attack
		var plantToAttack = null;
		for (var i = 0; i < plants.length; i++) {
			var plant = plants[i];
			if (plant.gridY === self.gridY && Math.abs(plant.x - self.x) < 80) {
				plantToAttack = plant;
				break;
			}
		}
		if (plantToAttack) {
			self.attackTimer++;
			if (self.attackTimer >= self.attackDelay) {
				if (plantToAttack.takeDamage) {
					plantToAttack.takeDamage(self.damage);
					LK.getSound('zombie_eat').play();
				}
				self.attackTimer = 0;
			}
		} else {
			self.x -= self.speed;
			self.attackTimer = 0;
		}
		// Check if reached house
		if (self.x < 150) {
			LK.showGameOver();
		}
	};
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		LK.getSound('zombie_hit').play();
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < zombies.length; i++) {
				if (zombies[i] === self) {
					zombies.splice(i, 1);
					break;
				}
			}
			zombiesKilled++;
		}
	};
	return self;
});
var Zomboni = BasicZombie.expand(function () {
	var self = BasicZombie.call(this);
	// Replace the graphics with zomboni asset
	self.removeChild(self.children[0]);
	var graphics = self.attachAsset('zomboni', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 1.5; // Fast movement
	self.health = 150;
	self.maxHealth = 150;
	self.damage = 100;
	self.gridY = 0;
	self.attackTimer = 0;
	self.attackDelay = 30; // Faster elimination
	self.update = function () {
		// Move forward continuously
		self.x -= self.speed;
		// Check for plants to eliminate (in a wider area due to size)
		for (var i = plants.length - 1; i >= 0; i--) {
			var plant = plants[i];
			if (plant.gridY === self.gridY && Math.abs(plant.x - self.x) < 100) {
				// Instantly eliminate the plant
				LK.effects.flashObject(plant, 0xff0000, 200);
				// Remove from plant grid
				var gridKey = plant.gridX + ',' + plant.gridY;
				delete plantGrid[gridKey];
				plant.destroy();
				plants.splice(i, 1);
			}
		}
		// Check if reached house
		if (self.x < 150) {
			LK.showGameOver();
		}
	};
	return self;
});
var VeteranNewspaperZombie = BasicZombie.expand(function () {
	var self = BasicZombie.call(this);
	// Replace the graphics with veteran newspaper zombie asset
	self.removeChild(self.children[0]);
	var graphics = self.attachAsset('veteranewspaperZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 0.5;
	self.health = 200; // Double the life of basic zombie (100 * 2)
	self.maxHealth = 200;
	self.damage = 40;
	self.gridY = 0;
	self.attackTimer = 0;
	self.attackDelay = 60;
	self.hasRaged = false;
	self.takeDamage = function (damage) {
		// Veteran newspaper zombie is now unstoppable - no damage taken
		LK.effects.flashObject(self, 0xff0000, 200);
		LK.getSound('zombie_hit').play();
		// Always rage mode - increase speed and damage by 5x permanently
		if (!self.hasRaged) {
			self.hasRaged = true;
			self.speed = 2.5; // 0.5 * 5
			self.damage = 200; // 40 * 5
			// Visual effect for rage mode - flash red and change tint
			LK.effects.flashObject(self, 0xff0000, 500);
			tween(graphics, {
				tint: 0xff0000
			}, {
				duration: 300,
				easing: tween.easeOut
			});
		}
		// Veteran newspaper zombie never dies
	};
	return self;
});
var TankZombie = BasicZombie.expand(function () {
	var self = BasicZombie.call(this);
	// Replace the graphics with tank zombie asset
	self.removeChild(self.children[0]);
	var graphics = self.attachAsset('tankZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 0.3;
	self.health = 200;
	self.maxHealth = 200;
	self.damage = 80;
	self.gridY = 0;
	self.attackTimer = 0;
	self.attackDelay = 60;
	return self;
});
var NewspaperZombie = BasicZombie.expand(function () {
	var self = BasicZombie.call(this);
	// Replace the graphics with newspaper zombie asset
	self.removeChild(self.children[0]);
	var graphics = self.attachAsset('newspaperZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 0.5;
	self.health = 100;
	self.maxHealth = 100;
	self.damage = 40;
	self.gridY = 0;
	self.attackTimer = 0;
	self.attackDelay = 60;
	self.hasRaged = false;
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		LK.getSound('zombie_hit').play();
		// Check if health dropped to half or below and hasn't raged yet
		if (self.health <= self.maxHealth / 2 && !self.hasRaged) {
			self.hasRaged = true;
			// Increase speed and damage
			self.speed = 1.5;
			self.damage = 80;
			// Visual effect for rage mode - flash red and change tint
			LK.effects.flashObject(self, 0xff0000, 500);
			tween(graphics, {
				tint: 0xff4444
			}, {
				duration: 300,
				easing: tween.easeOut
			});
		}
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < zombies.length; i++) {
				if (zombies[i] === self) {
					zombies.splice(i, 1);
					break;
				}
			}
			zombiesKilled++;
		}
	};
	return self;
});
var MinerZombie = BasicZombie.expand(function () {
	var self = BasicZombie.call(this);
	// Replace the graphics with miner zombie asset (appears as normal zombie)
	self.removeChild(self.children[0]);
	var graphics = self.attachAsset('minerZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 0.5;
	self.health = 80;
	self.maxHealth = 80;
	self.damage = 40;
	self.gridY = 0;
	self.attackTimer = 0;
	self.attackDelay = 60;
	self.teleportTimer = 0;
	self.teleportDelay = 300; // 5 seconds at 60fps
	self.hasTeleported = false;
	self.update = function () {
		// If not teleported yet, count down to teleport
		if (!self.hasTeleported) {
			self.teleportTimer++;
			if (self.teleportTimer >= self.teleportDelay) {
				self.teleport();
			} else {
				// Move normally before teleporting
				self.x -= self.speed;
			}
		} else {
			// After teleporting, behave like normal zombie but attacking from behind
			var plantToAttack = null;
			for (var i = 0; i < plants.length; i++) {
				var plant = plants[i];
				if (plant.gridY === self.gridY && Math.abs(plant.x - self.x) < 80) {
					plantToAttack = plant;
					break;
				}
			}
			if (plantToAttack) {
				self.attackTimer++;
				if (self.attackTimer >= self.attackDelay) {
					if (plantToAttack.takeDamage) {
						plantToAttack.takeDamage(self.damage);
						LK.getSound('zombie_eat').play();
						LK.getSound('zombie_eat').play();
					}
					self.attackTimer = 0;
				}
			} else {
				self.x += self.speed; // Move forward (right) after teleporting
				self.attackTimer = 0;
			}
		}
		// Check if reached house (only matters before teleporting)
		if (!self.hasTeleported && self.x < 150) {
			LK.showGameOver();
		}
		// Check if moved off screen after teleporting
		if (self.hasTeleported && self.x > 2200) {
			self.destroy();
			for (var i = 0; i < zombies.length; i++) {
				if (zombies[i] === self) {
					zombies.splice(i, 1);
					break;
				}
			}
		}
	};
	self.teleport = function () {
		if (self.hasTeleported) return;
		self.hasTeleported = true;
		// Flash effect before teleporting
		LK.effects.flashObject(self, 0xffff00, 300);
		// Teleport to the first column (leftmost position behind plants)
		var newX = gridStartX + gridWidth / 2;
		var newY = gridStartY + self.gridY * gridHeight + gridHeight / 2;
		// Animate teleportation with tween
		tween(self, {
			alpha: 0,
			scaleX: 0.5,
			scaleY: 0.5
		}, {
			duration: 500,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				// Move to new position
				self.x = newX;
				self.y = newY;
				// Animate appearing at new location
				tween(self, {
					alpha: 1,
					scaleX: 1,
					scaleY: 1
				}, {
					duration: 500,
					easing: tween.easeOut
				});
				// Flash effect when appearing
				LK.effects.flashObject(self, 0x00ff00, 300);
			}
		});
	};
	return self;
});
var JesterZombie = BasicZombie.expand(function () {
	var self = BasicZombie.call(this);
	// Replace the graphics with jester zombie asset
	self.removeChild(self.children[0]);
	var graphics = self.attachAsset('jesterZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 0.8;
	self.health = 120;
	self.maxHealth = 120;
	self.damage = 50;
	self.gridY = 0;
	self.attackTimer = 0;
	self.attackDelay = 60;
	self.isJester = true; // Flag to identify this zombie type
	// Override takeDamage to be immune to peas
	self.takeDamage = function (damage, source) {
		// Only take damage from non-pea sources
		if (source !== 'pea' && source !== 'frozenpea') {
			self.health -= damage;
			LK.effects.flashObject(self, 0xff0000, 200);
			LK.getSound('zombie_hit').play();
			if (self.health <= 0) {
				self.destroy();
				for (var i = 0; i < zombies.length; i++) {
					if (zombies[i] === self) {
						zombies.splice(i, 1);
						break;
					}
				}
				zombiesKilled++;
			}
		}
	};
	return self;
});
var JackInBoxZombie = BasicZombie.expand(function () {
	var self = BasicZombie.call(this);
	// Replace the graphics with jack in box zombie asset
	self.removeChild(self.children[0]);
	var graphics = self.attachAsset('jackInBoxZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 0.7;
	self.health = 80;
	self.maxHealth = 80;
	self.damage = 60;
	self.hasExploded = false;
	self.explode = function () {
		if (self.hasExploded) return;
		self.hasExploded = true;
		// Play explosion sound
		LK.getSound('explosion').play();
		// Flash the jack in box zombie white before exploding
		LK.effects.flashObject(self, 0xffffff, 200);
		// Scale up effect for explosion
		tween(graphics, {
			scaleX: 3,
			scaleY: 3,
			alpha: 0
		}, {
			duration: 500,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				// Remove from zombies array
				for (var i = 0; i < zombies.length; i++) {
					if (zombies[i] === self) {
						zombies.splice(i, 1);
						break;
					}
				}
				// Destroy the jack in box zombie
				self.destroy();
			}
		});
		// Eliminate plants in a 250 pixel radius
		var explosionRadius = 250;
		for (var i = plants.length - 1; i >= 0; i--) {
			var plant = plants[i];
			var distance = Math.sqrt(Math.pow(plant.x - self.x, 2) + Math.pow(plant.y - self.y, 2));
			if (distance <= explosionRadius) {
				// Flash plant red before destroying
				LK.effects.flashObject(plant, 0xff0000, 200);
				// Remove from plant grid
				var gridKey = plant.gridX + ',' + plant.gridY;
				delete plantGrid[gridKey];
				plant.destroy();
				plants.splice(i, 1);
			}
		}
	};
	self.update = function () {
		// Check if there's a plant to explode on
		var plantToExplode = null;
		for (var i = 0; i < plants.length; i++) {
			var plant = plants[i];
			if (plant.gridY === self.gridY && Math.abs(plant.x - self.x) < 80) {
				plantToExplode = plant;
				break;
			}
		}
		if (plantToExplode && !self.hasExploded) {
			self.explode();
		} else {
			self.x -= self.speed;
		}
		// Check if reached house
		if (self.x < 150) {
			LK.showGameOver();
		}
	};
	return self;
});
var Gargantuar = BasicZombie.expand(function () {
	var self = BasicZombie.call(this);
	// Replace the graphics with gargantuar asset
	self.removeChild(self.children[0]);
	var graphics = self.attachAsset('gargantuar', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 0.2; // Very slow
	self.health = 400; // Very resistant
	self.maxHealth = 400;
	self.damage = 200; // High damage to eliminate plants instantly
	self.gridY = 0;
	self.attackTimer = 0;
	self.attackDelay = 30; // Fast elimination
	self.hasSpawnedFastZombie = false;
	self.isResistantToExplosion = true; // Flag for cherry popper resistance
	self.update = function () {
		// Check if there's a plant to eliminate
		var plantToEliminate = null;
		for (var i = 0; i < plants.length; i++) {
			var plant = plants[i];
			if (plant.gridY === self.gridY && Math.abs(plant.x - self.x) < 120) {
				plantToEliminate = plant;
				break;
			}
		}
		if (plantToEliminate) {
			self.attackTimer++;
			if (self.attackTimer >= self.attackDelay) {
				// Instantly eliminate the plant
				LK.effects.flashObject(plantToEliminate, 0xff0000, 200);
				// Remove from plant grid
				var gridKey = plantToEliminate.gridX + ',' + plantToEliminate.gridY;
				delete plantGrid[gridKey];
				plantToEliminate.destroy();
				for (var j = 0; j < plants.length; j++) {
					if (plants[j] === plantToEliminate) {
						plants.splice(j, 1);
						break;
					}
				}
				LK.getSound('zombie_eat').play();
				self.attackTimer = 0;
			}
		} else {
			self.x -= self.speed;
			self.attackTimer = 0;
		}
		// Spawn FastZombie when at half health
		if (self.health <= self.maxHealth / 2 && !self.hasSpawnedFastZombie) {
			self.hasSpawnedFastZombie = true;
			var fastZombie = new FastZombie();
			// Spawn in the third square of the garden (gridStartX + 2 * gridWidth for third column)
			fastZombie.x = gridStartX + 2 * gridWidth + gridWidth / 2;
			fastZombie.y = gridStartY + self.gridY * gridHeight + gridHeight / 2;
			fastZombie.gridY = self.gridY;
			zombies.push(fastZombie);
			game.addChild(fastZombie);
			// Visual effect for spawning
			LK.effects.flashObject(self, 0xffff00, 500);
		}
		// Check if reached house
		if (self.x < 150) {
			LK.showGameOver();
		}
	};
	return self;
});
var FastZombie = BasicZombie.expand(function () {
	var self = BasicZombie.call(this);
	// Replace the graphics with fast zombie asset
	self.removeChild(self.children[0]);
	var graphics = self.attachAsset('fastZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 1.2;
	self.health = 60;
	self.maxHealth = 60;
	self.damage = 40;
	self.gridY = 0;
	self.attackTimer = 0;
	self.attackDelay = 60;
	return self;
});
var CherryPopper = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('cherrypopper', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 150;
	self.gridX = 0;
	self.gridY = 0;
	self.hasExploded = false;
	self.explode = function () {
		if (self.hasExploded) return;
		self.hasExploded = true;
		// Play explosion sound
		LK.getSound('explosion').play();
		// Flash the cherry popper white before exploding
		LK.effects.flashObject(self, 0xffffff, 200);
		// Scale up effect for explosion
		tween(graphics, {
			scaleX: 3,
			scaleY: 3,
			alpha: 0
		}, {
			duration: 500,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				// Remove from plants array
				for (var i = 0; i < plants.length; i++) {
					if (plants[i] === self) {
						plants.splice(i, 1);
						break;
					}
				}
				// Remove from plant grid
				var gridKey = self.gridX + ',' + self.gridY;
				delete plantGrid[gridKey];
				// Destroy the cherry popper
				self.destroy();
			}
		});
		// Eliminate zombies in a 300 pixel radius
		var explosionRadius = 300;
		for (var i = zombies.length - 1; i >= 0; i--) {
			var zombie = zombies[i];
			var distance = Math.sqrt(Math.pow(zombie.x - self.x, 2) + Math.pow(zombie.y - self.y, 2));
			if (distance <= explosionRadius) {
				// Special handling for Gargantuar
				if (zombie.constructor === Gargantuar) {
					// Flash zombie red
					LK.effects.flashObject(zombie, 0xff0000, 200);
					// If at full health or more than half, reduce to half
					if (zombie.health > zombie.maxHealth / 2) {
						zombie.health = zombie.maxHealth / 2;
						// Visual effect for being damaged but not destroyed
						tween(zombie, {
							tint: 0xff4444
						}, {
							duration: 500,
							easing: tween.easeOut
						});
					} else {
						// Second explosion - eliminate Gargantuar
						zombie.destroy();
						zombies.splice(i, 1);
						zombiesKilled++;
					}
				} else {
					// Normal zombies - eliminate immediately
					LK.effects.flashObject(zombie, 0xff0000, 200);
					zombie.destroy();
					zombies.splice(i, 1);
					zombiesKilled++;
				}
			}
		}
	};
	// Auto-explode when planted (immediately after placement)
	self.update = function () {
		if (!self.hasExploded) {
			self.explode();
		}
	};
	return self;
});
var Chomper = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('chomper', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 150;
	self.health = 100;
	self.maxHealth = 100;
	self.gridX = 0;
	self.gridY = 0;
	self.eatCooldown = 0;
	self.maxEatCooldown = 900; // 15 seconds at 60fps
	self.isOnCooldown = false;
	self.digestionTimer = 0;
	self.maxDigestionTime = 180; // 3 seconds to digest
	self.isDigesting = false;
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	self.update = function () {
		// Handle digestion timer
		if (self.isDigesting) {
			self.digestionTimer++;
			if (self.digestionTimer >= self.maxDigestionTime) {
				self.isDigesting = false;
				self.digestionTimer = 0;
				// Reset color after digesting
				tween(graphics, {
					tint: 0xffffff
				}, {
					duration: 300,
					easing: tween.easeOut
				});
			}
			return; // Don't eat while digesting
		}
		// Handle cooldown
		if (self.isOnCooldown) {
			self.eatCooldown--;
			if (self.eatCooldown <= 0) {
				self.isOnCooldown = false;
				// Reset color when cooldown ends
				tween(graphics, {
					tint: 0xffffff
				}, {
					duration: 300,
					easing: tween.easeOut
				});
			} else {
				// Ensure black color is maintained during cooldown
				if (graphics.tint !== 0x000000) {
					tween(graphics, {
						tint: 0x000000
					}, {
						duration: 100,
						easing: tween.easeOut
					});
				}
			}
			return; // Don't eat while on cooldown
		}
		// Look for the nearest zombie in adjacent squares (two square range)
		var nearestZombie = null;
		var nearestDistance = Infinity;
		var nearestIndex = -1;
		for (var i = zombies.length - 1; i >= 0; i--) {
			var zombie = zombies[i];
			// Check if zombie is in same lane and within two grid square range
			var gridDistance = Math.abs(zombie.x - self.x) / gridWidth;
			if (zombie.gridY === self.gridY && gridDistance <= 2.2) {
				var distance = Math.abs(zombie.x - self.x);
				if (distance < nearestDistance) {
					nearestDistance = distance;
					nearestZombie = zombie;
					nearestIndex = i;
				}
			}
		}
		// Eat the nearest zombie if found
		if (nearestZombie) {
			self.eatZombie(nearestZombie, nearestIndex);
		}
	};
	self.eatZombie = function (zombie, zombieIndex) {
		// Check if zombie is a Gargantuar - cannot be eaten
		if (zombie.constructor === Gargantuar) {
			// Flash red to show chomper can't eat this zombie
			LK.effects.flashObject(self, 0xff0000, 300);
			return; // Exit without eating
		}
		// Flash white to show eating action
		LK.effects.flashObject(self, 0xffffff, 300);
		// Remove zombie immediately
		zombie.destroy();
		zombies.splice(zombieIndex, 1);
		zombiesKilled++;
		// Start digestion period
		self.isDigesting = true;
		self.digestionTimer = 0;
		// Visual feedback for digesting (green tint)
		tween(graphics, {
			tint: 0x44ff44
		}, {
			duration: 300,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				// Start cooldown after digestion
				self.isOnCooldown = true;
				self.eatCooldown = self.maxEatCooldown;
				// Visual feedback for cooldown (black tint)
				tween(graphics, {
					tint: 0x000000
				}, {
					duration: 300,
					easing: tween.easeOut
				});
			}
		});
	};
	return self;
});
var FrozenPea = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('frozenpea', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 8;
	self.damage = 15;
	self.gridY = 0;
	self.slowDuration = 300; // 5 seconds at 60fps
	self.slowFactor = 0.6; // Reduce speed to 60%
	self.update = function () {
		self.x += self.speed;
		// Check collision with zombies
		for (var i = 0; i < zombies.length; i++) {
			var zombie = zombies[i];
			if (zombie.gridY === self.gridY && self.intersects(zombie)) {
				// Check if it's a JesterZombie
				if (zombie.isJester) {
					// Create reflected frozen pea going back towards plants
					var reflectedFrozenPea = new ReflectedFrozenPea();
					reflectedFrozenPea.x = zombie.x - 50;
					reflectedFrozenPea.y = zombie.y;
					reflectedFrozenPea.gridY = zombie.gridY;
					reflectedfrozenpeas.push(reflectedFrozenPea);
					game.addChild(reflectedFrozenPea);
					// Flash jester zombie to show deflection
					LK.effects.flashObject(zombie, 0xffff00, 200);
				} else {
					zombie.takeDamage(self.damage, 'frozenpea');
					LK.getSound('zombie_hit').play();
					// Apply slow effect only if not a Zomboni or NewspaperZombie
					if (zombie.constructor !== Zomboni && zombie.constructor !== NewspaperZombie) {
						if (!zombie.originalSpeed) {
							zombie.originalSpeed = zombie.speed;
						}
						zombie.speed = zombie.originalSpeed * self.slowFactor;
						zombie.slowTimer = self.slowDuration;
						// Play zombie_freezed sound when slowing
						LK.getSound('zombie_freezed').play();
						// Visual effect for slowed zombie
						tween(zombie, {
							tint: 0x87ceeb
						}, {
							duration: 300,
							easing: tween.easeOut
						});
					}
				}
				self.destroy();
				for (var j = 0; j < frozenpeas.length; j++) {
					if (frozenpeas[j] === self) {
						frozenpeas.splice(j, 1);
						break;
					}
				}
				return;
			}
		}
		// Remove if off screen
		if (self.x > 2200) {
			self.destroy();
			for (var k = 0; k < frozenpeas.length; k++) {
				if (frozenpeas[k] === self) {
					frozenpeas.splice(k, 1);
					break;
				}
			}
		}
	};
	return self;
});
var Pea = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('pea', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 8;
	self.damage = 15;
	self.gridY = 0;
	self.update = function () {
		self.x += self.speed;
		// Check collision with zombies
		for (var i = 0; i < zombies.length; i++) {
			var zombie = zombies[i];
			if (zombie.gridY === self.gridY && self.intersects(zombie)) {
				// Check if it's a JesterZombie
				if (zombie.isJester) {
					// Create reflected pea going back towards plants
					var reflectedPea = new ReflectedPea();
					reflectedPea.x = zombie.x - 50;
					reflectedPea.y = zombie.y;
					reflectedPea.gridY = zombie.gridY;
					reflectedpeas.push(reflectedPea);
					game.addChild(reflectedPea);
					// Flash jester zombie to show deflection
					LK.effects.flashObject(zombie, 0xffff00, 200);
				} else {
					zombie.takeDamage(self.damage, 'pea');
					LK.getSound('zombie_hit').play();
				}
				self.destroy();
				for (var j = 0; j < peas.length; j++) {
					if (peas[j] === self) {
						peas.splice(j, 1);
						break;
					}
				}
				return;
			}
		}
		// Remove if off screen
		if (self.x > 2200) {
			self.destroy();
			for (var k = 0; k < peas.length; k++) {
				if (peas[k] === self) {
					peas.splice(k, 1);
					break;
				}
			}
		}
	};
	return self;
});
var Peashooter = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('peashooter', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 100;
	self.health = 100;
	self.maxHealth = 100;
	self.shootTimer = 0;
	self.shootDelay = 90; // 1.5 seconds at 60fps
	self.gridX = 0;
	self.gridY = 0;
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	self.update = function () {
		self.shootTimer++;
		if (self.shootTimer >= self.shootDelay) {
			// Check if there's a zombie in this lane
			var hasZombieInLane = false;
			for (var i = 0; i < zombies.length; i++) {
				if (zombies[i].gridY === self.gridY && zombies[i].x > self.x) {
					hasZombieInLane = true;
					break;
				}
			}
			if (hasZombieInLane) {
				self.shoot();
				self.shootTimer = 0;
			}
		}
	};
	self.shoot = function () {
		var pea = new Pea();
		pea.x = self.x + 60;
		pea.y = self.y;
		pea.gridY = self.gridY;
		peas.push(pea);
		game.addChild(pea);
		LK.getSound('shoot').play();
	};
	return self;
});
var Potatomine = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('potatomine', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 25;
	self.health = 100;
	self.maxHealth = 100;
	self.gridX = 0;
	self.gridY = 0;
	self.chargeTimer = 0;
	self.maxChargeTime = 900; // 15 seconds at 60fps
	self.isCharged = false;
	self.hasExploded = false;
	// Start with black color (charging state)
	graphics.tint = 0x000000;
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	self.update = function () {
		// Handle charging timer
		if (!self.isCharged && !self.hasExploded) {
			self.chargeTimer++;
			if (self.chargeTimer >= self.maxChargeTime) {
				self.isCharged = true;
				// Change to normal color when charged
				tween(graphics, {
					tint: 0xffffff
				}, {
					duration: 500,
					easing: tween.easeOut
				});
			}
			return; // Don't explode while charging
		}
		// Check for zombies touching this potatomine
		if (self.isCharged && !self.hasExploded) {
			for (var i = 0; i < zombies.length; i++) {
				var zombie = zombies[i];
				if (zombie.gridY === self.gridY && self.intersects(zombie)) {
					self.explode();
					break;
				}
			}
		}
	};
	self.explode = function () {
		if (self.hasExploded) return;
		self.hasExploded = true;
		// Flash white before exploding
		LK.effects.flashObject(self, 0xffffff, 200);
		// Scale up effect for explosion
		tween(graphics, {
			scaleX: 3,
			scaleY: 3,
			alpha: 0
		}, {
			duration: 500,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				// Remove from plants array
				for (var i = 0; i < plants.length; i++) {
					if (plants[i] === self) {
						plants.splice(i, 1);
						break;
					}
				}
				// Remove from plant grid
				var gridKey = self.gridX + ',' + self.gridY;
				delete plantGrid[gridKey];
				// Destroy the potatomine
				self.destroy();
			}
		});
		// Eliminate zombies in a 200 pixel radius
		var explosionRadius = 200;
		for (var i = zombies.length - 1; i >= 0; i--) {
			var zombie = zombies[i];
			var distance = Math.sqrt(Math.pow(zombie.x - self.x, 2) + Math.pow(zombie.y - self.y, 2));
			if (distance <= explosionRadius) {
				// Special handling for Gargantuar and NewspaperZombie
				if (zombie.constructor === Gargantuar || zombie.constructor === NewspaperZombie) {
					// Flash zombie red
					LK.effects.flashObject(zombie, 0xff0000, 200);
					// Reduce to half health
					zombie.health = zombie.maxHealth / 2;
					// Visual effect for being damaged but not destroyed
					tween(zombie, {
						tint: 0xff4444
					}, {
						duration: 500,
						easing: tween.easeOut
					});
					// Check if zombie should be eliminated after damage
					if (zombie.health <= 0) {
						zombie.destroy();
						zombies.splice(i, 1);
						zombiesKilled++;
					}
				} else {
					// Normal zombies - eliminate immediately
					LK.effects.flashObject(zombie, 0xff0000, 200);
					zombie.destroy();
					zombies.splice(i, 1);
					zombiesKilled++;
				}
			}
		}
	};
	return self;
});
var Puffshroom = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('puffshroom', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 0;
	self.health = 100;
	self.maxHealth = 100;
	self.shootTimer = 0;
	self.shootDelay = 120; // 2 seconds at 60fps
	self.gridX = 0;
	self.gridY = 0;
	self.detectionRange = 3; // 3 tiles
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	self.update = function () {
		self.shootTimer++;
		if (self.shootTimer >= self.shootDelay) {
			// Check if there's a zombie within 3 tiles in this lane
			var hasZombieInRange = false;
			for (var i = 0; i < zombies.length; i++) {
				var zombie = zombies[i];
				if (zombie.gridY === self.gridY && zombie.x > self.x) {
					var distance = Math.abs(zombie.x - self.x);
					var tileDistance = distance / gridWidth;
					if (tileDistance <= self.detectionRange) {
						hasZombieInRange = true;
						break;
					}
				}
			}
			if (hasZombieInRange) {
				self.shoot();
				self.shootTimer = 0;
			}
		}
	};
	self.shoot = function () {
		var spore = new Spore();
		spore.x = self.x + 40;
		spore.y = self.y;
		spore.gridY = self.gridY;
		spores.push(spore);
		game.addChild(spore);
		LK.getSound('shoot').play();
	};
	return self;
});
var ReflectedFrozenPea = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('frozenpea', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Tint dark red to show it's reflected
	graphics.tint = 0xaa2222;
	self.speed = -8; // Negative speed to go backwards
	self.damage = 20; // Slightly more damage than regular frozen peas
	self.gridY = 0;
	self.update = function () {
		self.x += self.speed;
		// Check collision with plants
		for (var i = 0; i < plants.length; i++) {
			var plant = plants[i];
			if (plant.gridY === self.gridY && self.intersects(plant)) {
				if (plant.takeDamage) {
					plant.takeDamage(self.damage);
				}
				self.destroy();
				for (var j = 0; j < reflectedfrozenpeas.length; j++) {
					if (reflectedfrozenpeas[j] === self) {
						reflectedfrozenpeas.splice(j, 1);
						break;
					}
				}
				return;
			}
		}
		// Remove if off screen (left side)
		if (self.x < -100) {
			self.destroy();
			for (var k = 0; k < reflectedfrozenpeas.length; k++) {
				if (reflectedfrozenpeas[k] === self) {
					reflectedfrozenpeas.splice(k, 1);
					break;
				}
			}
		}
	};
	return self;
});
var ReflectedPea = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('pea', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Tint red to show it's reflected
	graphics.tint = 0xff4444;
	self.speed = -8; // Negative speed to go backwards
	self.damage = 20; // Slightly more damage than regular peas
	self.gridY = 0;
	self.update = function () {
		self.x += self.speed;
		// Check collision with plants
		for (var i = 0; i < plants.length; i++) {
			var plant = plants[i];
			if (plant.gridY === self.gridY && self.intersects(plant)) {
				if (plant.takeDamage) {
					plant.takeDamage(self.damage);
				}
				self.destroy();
				for (var j = 0; j < reflectedpeas.length; j++) {
					if (reflectedpeas[j] === self) {
						reflectedpeas.splice(j, 1);
						break;
					}
				}
				return;
			}
		}
		// Remove if off screen (left side)
		if (self.x < -100) {
			self.destroy();
			for (var k = 0; k < reflectedpeas.length; k++) {
				if (reflectedpeas[k] === self) {
					reflectedpeas.splice(k, 1);
					break;
				}
			}
		}
	};
	return self;
});
var ReflectedSpore = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('spore', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Tint dark brown to show it's reflected
	graphics.tint = 0x654321;
	self.speed = -6;
	self.damage = 15;
	self.gridY = 0;
	self.update = function () {
		self.x += self.speed;
		// Check collision with plants
		for (var i = 0; i < plants.length; i++) {
			var plant = plants[i];
			if (plant.gridY === self.gridY && self.intersects(plant)) {
				if (plant.takeDamage) {
					plant.takeDamage(self.damage);
				}
				self.destroy();
				for (var j = 0; j < reflectedspores.length; j++) {
					if (reflectedspores[j] === self) {
						reflectedspores.splice(j, 1);
						break;
					}
				}
				return;
			}
		}
		// Remove if off screen (left side)
		if (self.x < -100) {
			self.destroy();
			for (var k = 0; k < reflectedspores.length; k++) {
				if (reflectedspores[k] === self) {
					reflectedspores.splice(k, 1);
					break;
				}
			}
		}
	};
	return self;
});
var Repeater = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('repeater', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 200;
	self.health = 100;
	self.maxHealth = 100;
	self.shootTimer = 0;
	self.shootDelay = 90; // 1.5 seconds at 60fps
	self.secondShotTimer = 0;
	self.secondShotDelay = 15; // 0.25 seconds delay between shots
	self.waitingForSecondShot = false;
	self.gridX = 0;
	self.gridY = 0;
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	self.update = function () {
		// Handle second shot timing
		if (self.waitingForSecondShot) {
			self.secondShotTimer++;
			if (self.secondShotTimer >= self.secondShotDelay) {
				self.shoot(); // Fire second pea
				self.waitingForSecondShot = false;
				self.secondShotTimer = 0;
			}
		} else {
			self.shootTimer++;
			if (self.shootTimer >= self.shootDelay) {
				// Check if there's a zombie in this lane
				var hasZombieInLane = false;
				for (var i = 0; i < zombies.length; i++) {
					if (zombies[i].gridY === self.gridY && zombies[i].x > self.x) {
						hasZombieInLane = true;
						break;
					}
				}
				if (hasZombieInLane) {
					self.shoot(); // Fire first pea
					self.waitingForSecondShot = true; // Queue second shot
					self.shootTimer = 0;
				}
			}
		}
	};
	self.shoot = function () {
		var pea = new Pea();
		pea.x = self.x + 60;
		pea.y = self.y;
		pea.gridY = self.gridY;
		peas.push(pea);
		game.addChild(pea);
		LK.getSound('shoot').play();
	};
	return self;
});
var Snowshooter = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('snowshooter', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 175;
	self.health = 100;
	self.maxHealth = 100;
	self.shootTimer = 0;
	self.shootDelay = 90; // 1.5 seconds at 60fps
	self.gridX = 0;
	self.gridY = 0;
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	self.update = function () {
		self.shootTimer++;
		if (self.shootTimer >= self.shootDelay) {
			// Check if there's a zombie in this lane
			var hasZombieInLane = false;
			for (var i = 0; i < zombies.length; i++) {
				if (zombies[i].gridY === self.gridY && zombies[i].x > self.x) {
					hasZombieInLane = true;
					break;
				}
			}
			if (hasZombieInLane) {
				self.shoot();
				self.shootTimer = 0;
			}
		}
	};
	self.shoot = function () {
		var frozenpea = new FrozenPea();
		frozenpea.x = self.x + 60;
		frozenpea.y = self.y;
		frozenpea.gridY = self.gridY;
		frozenpeas.push(frozenpea);
		game.addChild(frozenpea);
		LK.getSound('shoot').play();
	};
	return self;
});
var SplitPea = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('splitpea', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 125;
	self.health = 100;
	self.maxHealth = 100;
	self.shootTimer = 0;
	self.shootDelay = 90; // 1.5 seconds at 60fps 
	self.gridX = 0;
	self.gridY = 0;
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback 
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	self.update = function () {
		self.shootTimer++;
		if (self.shootTimer >= self.shootDelay) {
			// Check if there's a zombie in this lane (both front and back) 
			var hasZombieInLane = false;
			for (var i = 0; i < zombies.length; i++) {
				if (zombies[i].gridY === self.gridY) {
					hasZombieInLane = true;
					break;
				}
			}
			if (hasZombieInLane) {
				self.shoot();
				self.shootTimer = 0;
			}
		}
	};
	self.shoot = function () {
		// Shoot one pea forward 
		var forwardPea = new Pea();
		forwardPea.x = self.x + 60;
		forwardPea.y = self.y;
		forwardPea.gridY = self.gridY;
		peas.push(forwardPea);
		game.addChild(forwardPea);
		// Shoot two peas backward 
		var backwardPea1 = new BackwardPea();
		backwardPea1.x = self.x - 60;
		backwardPea1.y = self.y - 20;
		backwardPea1.gridY = self.gridY;
		backwardpeas.push(backwardPea1);
		game.addChild(backwardPea1);
		var backwardPea2 = new BackwardPea();
		backwardPea2.x = self.x - 60;
		backwardPea2.y = self.y + 20;
		backwardPea2.gridY = self.gridY;
		backwardpeas.push(backwardPea2);
		game.addChild(backwardPea2);
		LK.getSound('shoot').play();
	};
	return self;
});
var Spore = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('spore', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 6;
	self.damage = 10;
	self.gridY = 0;
	self.update = function () {
		self.x += self.speed;
		// Check collision with zombies
		for (var i = 0; i < zombies.length; i++) {
			var zombie = zombies[i];
			if (zombie.gridY === self.gridY && self.intersects(zombie)) {
				// Check if it's a JesterZombie
				if (zombie.isJester) {
					// Create reflected spore going back towards plants
					var reflectedSpore = new ReflectedSpore();
					reflectedSpore.x = zombie.x - 50;
					reflectedSpore.y = zombie.y;
					reflectedSpore.gridY = zombie.gridY;
					reflectedspores.push(reflectedSpore);
					game.addChild(reflectedSpore);
					// Flash jester zombie to show deflection
					LK.effects.flashObject(zombie, 0xffff00, 200);
				} else {
					zombie.takeDamage(self.damage, 'spore');
					LK.getSound('zombie_hit').play();
				}
				self.destroy();
				for (var j = 0; j < spores.length; j++) {
					if (spores[j] === self) {
						spores.splice(j, 1);
						break;
					}
				}
				return;
			}
		}
		// Remove if off screen
		if (self.x > 2200) {
			self.destroy();
			for (var k = 0; k < spores.length; k++) {
				if (spores[k] === self) {
					spores.splice(k, 1);
					break;
				}
			}
		}
	};
	return self;
});
var Sun = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('sun', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.value = 25;
	self.lifeTimer = 0;
	self.maxLife = 600; // 10 seconds
	self.update = function () {
		self.lifeTimer++;
		if (self.lifeTimer > self.maxLife) {
			self.destroy();
			for (var i = 0; i < suns.length; i++) {
				if (suns[i] === self) {
					suns.splice(i, 1);
					break;
				}
			}
		}
	};
	self.down = function (x, y, obj) {
		sunPoints += self.value;
		updateSunDisplay();
		self.destroy();
		for (var i = 0; i < suns.length; i++) {
			if (suns[i] === self) {
				suns.splice(i, 1);
				break;
			}
		}
		LK.getSound('collect').play();
	};
	return self;
});
var Sunflower = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('sunflower', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 50;
	self.health = 100;
	self.maxHealth = 100;
	self.sunTimer = 0;
	self.sunDelay = 600; // 10 seconds at 60fps
	self.gridX = 0;
	self.gridY = 0;
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	self.update = function () {
		self.sunTimer++;
		if (self.sunTimer >= self.sunDelay) {
			self.produceSun();
			self.sunTimer = 0;
		}
	};
	self.produceSun = function () {
		var sun = new Sun();
		sun.x = self.x + (Math.random() - 0.5) * 50;
		sun.y = self.y + (Math.random() - 0.5) * 50;
		suns.push(sun);
		game.addChild(sun);
	};
	return self;
});
var WallNut = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('wallnut', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 50;
	self.health = 300;
	self.maxHealth = 300;
	self.gridX = 0;
	self.gridY = 0;
	self.takeDamage = function (damage) {
		self.health -= damage;
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x8BC34A
});
/**** 
* Game Code
****/ 
// Sounds
// Zombies
// Projectiles and collectibles
// Plants
// Game grid and UI elements
// Game mode variables
var gameMode = null; // 'normal' or 'endless'
var gameStarted = false;
var menuVisible = true;
// Game variables
var sunPoints = 150;
var currentWave = 1;
var maxWaves = 20;
var waveTimer = 0;
var waveDelay = 1800; // 30 seconds
var zombieSpawnTimer = 0;
var zombieSpawnDelay = 240; // 4 seconds
var zombiesPerWave = 5;
var zombiesSpawned = 0;
var zombiesKilled = 0;
var totalZombiesToKill = 0;
var waveStarted = false;
var zombieSpawnQueue = [];
// Game arrays
var plants = [];
var zombies = [];
var peas = [];
var frozenpeas = [];
var reflectedpeas = [];
var reflectedfrozenpeas = [];
var backwardpeas = [];
var spores = [];
var reflectedspores = [];
var suns = [];
var plantGrid = {}; // Track occupied grid positions
// Grid settings
var gridStartX = 400;
var gridStartY = 400;
var gridWidth = 320;
var gridHeight = 227;
var gridCols = 5;
var gridRows = 5;
// Selected plant type
var selectedPlantType = null;
// Plant selector management
var currentSelectorPage = 1;
var maxSelectorPages = 2;
// Create lawn grid
for (var row = 0; row < gridRows; row++) {
	for (var col = 0; col < gridCols; col++) {
		var tile = game.addChild(LK.getAsset('grass', {
			x: gridStartX + col * gridWidth,
			y: gridStartY + row * gridHeight,
			anchorX: 0,
			anchorY: 0
		}));
	}
}
// Create paths (zombie lanes)
for (var lane = 0; lane < gridRows; lane++) {
	var pathTile = game.addChild(LK.getAsset('path', {
		x: gridStartX + gridCols * gridWidth,
		y: gridStartY + lane * gridHeight,
		anchorX: 0,
		anchorY: 0
	}));
}
// Create house
var house = game.addChild(LK.getAsset('house', {
	x: 50,
	y: gridStartY + gridRows * gridHeight / 2 - 200,
	anchorX: 0,
	anchorY: 0
}));
// UI Setup
var sunDisplay = new Text2(sunPoints.toString(), {
	size: 80,
	fill: 0xFFD700,
	stroke: 0x000000,
	strokeThickness: 3
});
sunDisplay.anchor.set(0, 0);
LK.gui.topLeft.addChild(sunDisplay);
sunDisplay.x = 120;
sunDisplay.y = 20;
var waveDisplay = new Text2('Wave: ' + currentWave + '/' + maxWaves, {
	size: 60,
	fill: 0x000000
});
waveDisplay.anchor.set(0.5, 0);
LK.gui.top.addChild(waveDisplay);
waveDisplay.y = 20;
// Plant selection buttons - repositioned for new order
var peashooterBtn = LK.getAsset('peashooter', {
	x: 250,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(peashooterBtn);
var sunflowerBtn = LK.getAsset('sunflower', {
	x: 450,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(sunflowerBtn);
var cherrypopperBtn = LK.getAsset('cherrypopper', {
	x: 650,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(cherrypopperBtn);
var wallnutBtn = LK.getAsset('wallnut', {
	x: 850,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(wallnutBtn);
var potatomineBtn = LK.getAsset('potatomine', {
	x: 1050,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(potatomineBtn);
var snowshooterBtn = LK.getAsset('snowshooter', {
	x: 1250,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(snowshooterBtn);
var chomperBtn = LK.getAsset('chomper', {
	x: 1450,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(chomperBtn);
var repeaterBtn = LK.getAsset('repeater', {
	x: 1650,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(repeaterBtn);
var splitpeaBtn = LK.getAsset('splitpea', {
	x: 250,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(splitpeaBtn);
var puffshroomBtn = LK.getAsset('puffshroom', {
	x: 450,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(puffshroomBtn);
var shovelBtn = LK.getAsset('shovel', {
	x: 1900,
	y: 150,
	scaleX: 1.5,
	scaleY: 1.5,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(shovelBtn);
// Cost display texts - updated positions to match new layout
var peaCostTxt = new Text2('100', {
	size: 70,
	fill: 0x000000
});
peaCostTxt.anchor.set(0.5, 0);
game.addChild(peaCostTxt);
peaCostTxt.x = 250;
peaCostTxt.y = 2580;
var sunCostTxt = new Text2('50', {
	size: 70,
	fill: 0x000000
});
sunCostTxt.anchor.set(0.5, 0);
game.addChild(sunCostTxt);
sunCostTxt.x = 450;
sunCostTxt.y = 2580;
var cherryCostTxt = new Text2('150', {
	size: 70,
	fill: 0x000000
});
cherryCostTxt.anchor.set(0.5, 0);
game.addChild(cherryCostTxt);
cherryCostTxt.x = 650;
cherryCostTxt.y = 2580;
var wallCostTxt = new Text2('50', {
	size: 70,
	fill: 0x000000
});
wallCostTxt.anchor.set(0.5, 0);
game.addChild(wallCostTxt);
wallCostTxt.x = 850;
wallCostTxt.y = 2580;
var potatomineCosTxt = new Text2('25', {
	size: 70,
	fill: 0x000000
});
potatomineCosTxt.anchor.set(0.5, 0);
game.addChild(potatomineCosTxt);
potatomineCosTxt.x = 1050;
potatomineCosTxt.y = 2580;
var snowCostTxt = new Text2('175', {
	size: 70,
	fill: 0x000000
});
snowCostTxt.anchor.set(0.5, 0);
game.addChild(snowCostTxt);
snowCostTxt.x = 1250;
snowCostTxt.y = 2580;
var chomperCostTxt = new Text2('150', {
	size: 70,
	fill: 0x000000
});
chomperCostTxt.anchor.set(0.5, 0);
game.addChild(chomperCostTxt);
chomperCostTxt.x = 1450;
chomperCostTxt.y = 2580;
var repeaterCostTxt = new Text2('200', {
	size: 70,
	fill: 0x000000
});
repeaterCostTxt.anchor.set(0.5, 0);
game.addChild(repeaterCostTxt);
repeaterCostTxt.x = 1650;
repeaterCostTxt.y = 2580;
var splitpeaCostTxt = new Text2('125', {
	size: 70,
	fill: 0x000000
});
splitpeaCostTxt.anchor.set(0.5, 0);
game.addChild(splitpeaCostTxt);
splitpeaCostTxt.x = 250;
splitpeaCostTxt.y = 2580;
var puffshroomCostTxt = new Text2('0', {
	size: 70,
	fill: 0x000000
});
puffshroomCostTxt.anchor.set(0.5, 0);
game.addChild(puffshroomCostTxt);
puffshroomCostTxt.x = 450;
puffshroomCostTxt.y = 2580;
var shovelCostTxt = new Text2('Free', {
	size: 70,
	fill: 0x000000
});
shovelCostTxt.anchor.set(0.5, 0);
game.addChild(shovelCostTxt);
shovelCostTxt.x = 1900;
shovelCostTxt.y = 230;
// Add left arrow for plant selector
var leftArrow = new Text2('<', {
	size: 120,
	fill: 0x000000
});
leftArrow.anchor.set(0.5, 0.5);
game.addChild(leftArrow);
leftArrow.x = 50;
leftArrow.y = 2500;
// Add right arrow for plant selector
var rightArrow = new Text2('>', {
	size: 120,
	fill: 0x000000
});
rightArrow.anchor.set(0.5, 0.5);
game.addChild(rightArrow);
rightArrow.x = 2000;
rightArrow.y = 2500;
// Calculate total zombies for victory condition
for (var w = 1; w <= maxWaves; w++) {
	totalZombiesToKill += zombiesPerWave + Math.floor(w / 2);
}
function updateSunDisplay() {
	sunDisplay.setText(sunPoints.toString());
}
function updatePlantSelector() {
	// Hide all plants first
	peashooterBtn.visible = false;
	sunflowerBtn.visible = false;
	wallnutBtn.visible = false;
	snowshooterBtn.visible = false;
	repeaterBtn.visible = false;
	cherrypopperBtn.visible = false;
	splitpeaBtn.visible = false;
	chomperBtn.visible = false;
	potatomineBtn.visible = false;
	puffshroomBtn.visible = false;
	// Hide all cost texts
	peaCostTxt.visible = false;
	sunCostTxt.visible = false;
	wallCostTxt.visible = false;
	snowCostTxt.visible = false;
	repeaterCostTxt.visible = false;
	cherryCostTxt.visible = false;
	splitpeaCostTxt.visible = false;
	chomperCostTxt.visible = false;
	potatomineCosTxt.visible = false;
	puffshroomCostTxt.visible = false;
	if (currentSelectorPage === 1) {
		// First page - show: Peashooter, Sunflower, Cherrypopper, Wallnut, Potatomine, Snowshooter, Chomper, and Repeater
		peashooterBtn.visible = true;
		sunflowerBtn.visible = true;
		cherrypopperBtn.visible = true;
		wallnutBtn.visible = true;
		potatomineBtn.visible = true;
		snowshooterBtn.visible = true;
		chomperBtn.visible = true;
		repeaterBtn.visible = true;
		// Show corresponding cost texts
		peaCostTxt.visible = true;
		sunCostTxt.visible = true;
		cherryCostTxt.visible = true;
		wallCostTxt.visible = true;
		potatomineCosTxt.visible = true;
		snowCostTxt.visible = true;
		chomperCostTxt.visible = true;
		repeaterCostTxt.visible = true;
	} else if (currentSelectorPage === 2) {
		// Second page - show splitpea and puffshroom (only from wave 11)
		splitpeaBtn.visible = true;
		splitpeaCostTxt.visible = true;
		if (currentWave >= 11) {
			puffshroomBtn.visible = true;
			puffshroomCostTxt.visible = true;
		}
	}
}
function getGridPosition(x, y) {
	var col = Math.floor((x - gridStartX) / gridWidth);
	var row = Math.floor((y - gridStartY) / gridHeight);
	if (col >= 0 && col < gridCols && row >= 0 && row < gridRows) {
		return {
			col: col,
			row: row,
			x: gridStartX + col * gridWidth + gridWidth / 2,
			y: gridStartY + row * gridHeight + gridHeight / 2
		};
	}
	return null;
}
function spawnZombie() {
	var lane = Math.floor(Math.random() * gridRows);
	var zombieType = Math.random();
	var zombie;
	// Higher spawn rates for special zombies from wave 15 onwards
	if (currentWave >= 15) {
		if (zombieType < 0.22) {
			zombie = new Gargantuar();
		} else if (zombieType < 0.44) {
			zombie = new Zomboni();
		} else if (zombieType < 0.58) {
			zombie = new JesterZombie();
		} else if (zombieType < 0.68) {
			zombie = new TankZombie();
		} else if (zombieType < 0.73) {
			zombie = new JackInBoxZombie();
		} else if (zombieType < 0.79) {
			zombie = new MinerZombie();
		} else if (zombieType < 0.85) {
			zombie = new FastZombie();
		} else if (zombieType < 0.91) {
			zombie = new NewspaperZombie();
		} else if (zombieType < 0.97) {
			zombie = new VeteranNewspaperZombie();
		} else {
			zombie = new BasicZombie();
		}
	} else {
		// Original spawn rates for waves before 15
		if (currentWave > 8 && zombieType < 0.05) {
			zombie = new Gargantuar();
		} else if (currentWave > 6 && zombieType < 0.15) {
			zombie = new Zomboni();
		} else if (currentWave > 5 && zombieType < 0.25) {
			zombie = new TankZombie();
		} else if (currentWave > 4 && zombieType < 0.35) {
			zombie = new JesterZombie();
		} else if (currentWave > 2 && zombieType < 0.45) {
			zombie = new JackInBoxZombie();
		} else if (currentWave > 3 && zombieType < 0.60) {
			zombie = new MinerZombie();
		} else if (currentWave > 3 && zombieType < 0.75) {
			zombie = new FastZombie();
		} else if (currentWave > 1 && zombieType < 0.85) {
			zombie = new NewspaperZombie();
		} else if (currentWave > 7 && zombieType < 0.95) {
			zombie = new VeteranNewspaperZombie();
		} else {
			zombie = new BasicZombie();
		}
	}
	zombie.x = gridStartX + gridCols * gridWidth + 100;
	zombie.y = gridStartY + lane * gridHeight + gridHeight / 2;
	zombie.gridY = lane;
	// Add spawn delay animation - zombie starts invisible and fades in
	zombie.alpha = 0;
	zombie.scaleX = 0.5;
	zombie.scaleY = 0.5;
	// Animate zombie spawning in
	tween(zombie, {
		alpha: 1,
		scaleX: 1,
		scaleY: 1
	}, {
		duration: 800,
		easing: tween.easeOut
	});
	zombies.push(zombie);
	game.addChild(zombie);
	zombiesSpawned++;
}
function startNextWave() {
	// In endless mode, there's no wave limit
	var shouldStartWave = gameMode === 'normal' && currentWave <= maxWaves || gameMode === 'endless';
	if (shouldStartWave) {
		// In endless mode, increase difficulty more aggressively
		if (gameMode === 'endless') {
			zombiesPerWave = 5 + Math.floor(currentWave / 1.5); // Faster increase in endless mode
		} else {
			zombiesPerWave = 5 + Math.floor(currentWave / 2);
		}
		zombiesSpawned = 0;
		waveStarted = false;
		zombieSpawnQueue = [];
		// Display wave differently for endless mode
		if (gameMode === 'endless') {
			waveDisplay.setText('Wave: ' + currentWave + ' (Endless)');
		} else {
			waveDisplay.setText('Wave: ' + currentWave + '/' + maxWaves);
		}
		// Play Ultimate Battle music for all waves
		LK.playMusic('ultimate_battle');
		// Change background color to dark blue from wave 11
		if (currentWave >= 11) {
			game.setBackgroundColor(0x191970); // Dark blue
		}
		// Flash screen red when wave increases
		LK.effects.flashScreen(0xff0000, 1000);
		// Add delay before wave actually starts spawning zombies
		// For wave 1, add 10 second delay. For other waves, 2 second delay
		var waveStartDelay = currentWave === 1 ? 10000 : 2000;
		LK.setTimeout(function () {
			waveStarted = true;
			// Pre-queue zombie spawn times with delays
			// Use faster spawn delay from wave 5 onwards with higher spawn rate, and even faster from wave 11
			// In endless mode, spawn rate increases even more aggressively
			var currentSpawnDelay;
			if (gameMode === 'endless') {
				// Endless mode has progressively faster spawns
				if (currentWave >= 20) {
					currentSpawnDelay = 30; // Very fast from wave 20 (0.5 seconds)
				} else if (currentWave >= 15) {
					currentSpawnDelay = 45; // Faster from wave 15 (0.75 seconds)
				} else if (currentWave >= 10) {
					currentSpawnDelay = 60; // Fast from wave 10 (1 second)
				} else if (currentWave >= 5) {
					currentSpawnDelay = 90; // Medium speed from wave 5 (1.5 seconds)
				} else {
					currentSpawnDelay = zombieSpawnDelay; // Normal speed (4 seconds)
				}
			} else {
				// Normal mode spawn rates
				if (currentWave >= 11) {
					currentSpawnDelay = 60; // Even faster from wave 11 (1 second)
				} else if (currentWave >= 5) {
					currentSpawnDelay = 90; // Higher spawn rate from wave 5 (1.5 seconds)
				} else {
					currentSpawnDelay = zombieSpawnDelay; // Normal speed (4 seconds)
				}
			}
			for (var i = 0; i < zombiesPerWave; i++) {
				zombieSpawnQueue.push({
					spawnTime: LK.ticks + i * currentSpawnDelay + Math.random() * 60,
					// Add some randomness (reduced for faster waves)
					spawned: false
				});
			}
		}, waveStartDelay);
	}
}
// Generate sun periodically
var sunGenerationTimer = 0;
var sunGenerationDelay = 480; // 8 seconds
// Event handlers
peashooterBtn.down = function () {
	if (sunPoints >= 100) {
		selectedPlantType = 'peashooter';
		LK.effects.flashObject(peashooterBtn, 0x00ff00, 300);
	}
};
sunflowerBtn.down = function () {
	if (sunPoints >= 50) {
		selectedPlantType = 'sunflower';
		LK.effects.flashObject(sunflowerBtn, 0x00ff00, 300);
	}
};
wallnutBtn.down = function () {
	if (sunPoints >= 50) {
		selectedPlantType = 'wallnut';
		LK.effects.flashObject(wallnutBtn, 0x00ff00, 300);
	}
};
snowshooterBtn.down = function () {
	if (sunPoints >= 175) {
		selectedPlantType = 'snowshooter';
		LK.effects.flashObject(snowshooterBtn, 0x00ff00, 300);
	}
};
repeaterBtn.down = function () {
	if (sunPoints >= 200) {
		selectedPlantType = 'repeater';
		LK.effects.flashObject(repeaterBtn, 0x00ff00, 300);
	}
};
cherrypopperBtn.down = function () {
	if (sunPoints >= 150) {
		selectedPlantType = 'cherrypopper';
		LK.effects.flashObject(cherrypopperBtn, 0x00ff00, 300);
	}
};
splitpeaBtn.down = function () {
	if (sunPoints >= 125) {
		selectedPlantType = 'splitpea';
		LK.effects.flashObject(splitpeaBtn, 0x00ff00, 300);
	}
};
chomperBtn.down = function () {
	if (sunPoints >= 150) {
		selectedPlantType = 'chomper';
		LK.effects.flashObject(chomperBtn, 0x00ff00, 300);
	}
};
potatomineBtn.down = function () {
	if (sunPoints >= 25) {
		selectedPlantType = 'potatomine';
		LK.effects.flashObject(potatomineBtn, 0x00ff00, 300);
	}
};
puffshroomBtn.down = function () {
	if (currentWave >= 11) {
		selectedPlantType = 'puffshroom';
		LK.effects.flashObject(puffshroomBtn, 0x00ff00, 300);
	}
};
shovelBtn.down = function () {
	selectedPlantType = 'shovel';
	LK.effects.flashObject(shovelBtn, 0x00ff00, 300);
};
leftArrow.down = function () {
	if (currentSelectorPage > 1) {
		currentSelectorPage--;
		updatePlantSelector();
		LK.effects.flashObject(leftArrow, 0x00ff00, 200);
	} else {
		// Flash gray if can't go back further
		LK.effects.flashObject(leftArrow, 0x888888, 200);
	}
};
rightArrow.down = function () {
	if (currentSelectorPage < maxSelectorPages) {
		currentSelectorPage++;
		updatePlantSelector();
		LK.effects.flashObject(rightArrow, 0x00ff00, 200);
	} else {
		// Flash gray if can't go forward further
		LK.effects.flashObject(rightArrow, 0x888888, 200);
	}
};
game.down = function (x, y, obj) {
	// Don't allow plant placement if menu is visible
	if (menuVisible || !gameStarted) {
		return;
	}
	var gridPos = getGridPosition(x, y);
	if (gridPos && selectedPlantType) {
		var gridKey = gridPos.col + ',' + gridPos.row;
		// Handle shovel - remove existing plant
		if (selectedPlantType === 'shovel') {
			if (plantGrid[gridKey]) {
				var plantToRemove = plantGrid[gridKey];
				// Remove from plants array
				for (var i = 0; i < plants.length; i++) {
					if (plants[i] === plantToRemove) {
						plants.splice(i, 1);
						break;
					}
				}
				// Remove from grid
				delete plantGrid[gridKey];
				// Destroy the plant
				plantToRemove.destroy();
				selectedPlantType = null;
			}
			return;
		}
		// Check if position is already occupied
		if (plantGrid[gridKey]) {
			return;
		}
		var plant = null;
		var cost = 0;
		if (selectedPlantType === 'peashooter' && sunPoints >= 100) {
			plant = new Peashooter();
			cost = 100;
		} else if (selectedPlantType === 'sunflower' && sunPoints >= 50) {
			plant = new Sunflower();
			cost = 50;
		} else if (selectedPlantType === 'wallnut' && sunPoints >= 50) {
			plant = new WallNut();
			cost = 50;
		} else if (selectedPlantType === 'snowshooter' && sunPoints >= 175) {
			plant = new Snowshooter();
			cost = 175;
		} else if (selectedPlantType === 'repeater' && sunPoints >= 200) {
			plant = new Repeater();
			cost = 200;
		} else if (selectedPlantType === 'cherrypopper' && sunPoints >= 150) {
			plant = new CherryPopper();
			cost = 150;
		} else if (selectedPlantType === 'splitpea' && sunPoints >= 125) {
			plant = new SplitPea();
			cost = 125;
		} else if (selectedPlantType === 'chomper' && sunPoints >= 150) {
			plant = new Chomper();
			cost = 150;
		} else if (selectedPlantType === 'potatomine' && sunPoints >= 25) {
			plant = new Potatomine();
			cost = 25;
		} else if (selectedPlantType === 'puffshroom' && currentWave >= 11) {
			plant = new Puffshroom();
			cost = 0;
		}
		if (plant) {
			plant.x = gridPos.x;
			plant.y = gridPos.y;
			plant.gridX = gridPos.col;
			plant.gridY = gridPos.row;
			plants.push(plant);
			game.addChild(plant);
			plantGrid[gridKey] = plant;
			sunPoints -= cost;
			updateSunDisplay();
			selectedPlantType = null;
			// 50% chance to play either seed_plant1 or seed_plant2
			if (Math.random() < 0.5) {
				LK.getSound('seed_plant1').play();
			} else {
				LK.getSound('seed_plant2').play();
			}
		}
	}
};
game.update = function () {
	// Don't update game logic if menu is visible
	if (menuVisible || !gameStarted) {
		return;
	}
	// Generate sun periodically
	sunGenerationTimer++;
	if (sunGenerationTimer >= sunGenerationDelay) {
		var sun = new Sun();
		sun.x = 200 + Math.random() * 1600;
		sun.y = -100; // Start above screen
		sun.targetY = 200 + Math.random() * 1000; // Final position
		sun.isFalling = true; // Mark as falling sun
		// Animate falling from top to bottom
		tween(sun, {
			y: sun.targetY
		}, {
			duration: 2000,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				sun.isFalling = false;
			}
		});
		suns.push(sun);
		game.addChild(sun);
		sunGenerationTimer = 0;
	}
	// Wave management
	if (currentWave <= maxWaves) {
		waveTimer++;
		// Spawn zombies for current wave using queue system
		if (waveStarted && zombiesSpawned < zombiesPerWave) {
			for (var i = 0; i < zombieSpawnQueue.length; i++) {
				var queueItem = zombieSpawnQueue[i];
				if (!queueItem.spawned && LK.ticks >= queueItem.spawnTime) {
					spawnZombie();
					queueItem.spawned = true;
					break; // Only spawn one zombie per frame
				}
			}
		}
		// Start next wave
		if (zombiesSpawned >= zombiesPerWave && zombies.length === 0) {
			currentWave++;
			if (currentWave <= maxWaves) {
				startNextWave();
				waveTimer = 0;
			}
		}
	}
	// Check victory condition (only for normal mode)
	if (gameMode === 'normal' && currentWave > maxWaves && zombies.length === 0) {
		LK.showYouWin();
	}
	// Handle slow effects on zombies
	for (var z = 0; z < zombies.length; z++) {
		var zombie = zombies[z];
		if (zombie.slowTimer) {
			zombie.slowTimer--;
			if (zombie.slowTimer <= 0) {
				// Restore original speed
				if (zombie.originalSpeed) {
					zombie.speed = zombie.originalSpeed;
				}
				// Remove slow tint
				tween(zombie, {
					tint: 0xffffff
				}, {
					duration: 300,
					easing: tween.easeOut
				});
				zombie.slowTimer = null;
			}
		}
	}
	// Update button availability
	peashooterBtn.alpha = sunPoints >= 100 ? 1.0 : 0.5;
	sunflowerBtn.alpha = sunPoints >= 50 ? 1.0 : 0.5;
	wallnutBtn.alpha = sunPoints >= 50 ? 1.0 : 0.5;
	snowshooterBtn.alpha = sunPoints >= 175 ? 1.0 : 0.5;
	repeaterBtn.alpha = sunPoints >= 200 ? 1.0 : 0.5;
	cherrypopperBtn.alpha = sunPoints >= 150 ? 1.0 : 0.5;
	splitpeaBtn.alpha = sunPoints >= 125 ? 1.0 : 0.5;
	chomperBtn.alpha = sunPoints >= 150 ? 1.0 : 0.5;
	potatomineBtn.alpha = sunPoints >= 25 ? 1.0 : 0.5;
	puffshroomBtn.alpha = currentWave >= 11 && sunPoints >= 0 ? 1.0 : 0.5;
	shovelBtn.alpha = 1.0; // Shovel is always available
	// Update arrow button availability
	updateArrowButtons();
};
// Initialize plant selector
updatePlantSelector();
// Update arrow button availability in main update loop
function updateArrowButtons() {
	leftArrow.alpha = currentSelectorPage > 1 ? 1.0 : 0.5;
	rightArrow.alpha = currentSelectorPage < maxSelectorPages ? 1.0 : 0.5;
}
// Create menu buttons
var normalBtn = new Text2('NORMAL', {
	size: 120,
	fill: 0x00ff00,
	stroke: 0x000000,
	strokeThickness: 4
});
normalBtn.anchor.set(0.5, 0.5);
normalBtn.x = 1024;
normalBtn.y = 1200;
game.addChild(normalBtn);
var endlessBtn = new Text2('ENDLESS', {
	size: 120,
	fill: 0xff6600,
	stroke: 0x000000,
	strokeThickness: 4
});
endlessBtn.anchor.set(0.5, 0.5);
endlessBtn.x = 1024;
endlessBtn.y = 1400;
game.addChild(endlessBtn);
var modeDescriptionTxt = new Text2('Choose Game Mode:', {
	size: 100,
	fill: 0x000000
});
modeDescriptionTxt.anchor.set(0.5, 0.5);
modeDescriptionTxt.x = 1024;
modeDescriptionTxt.y = 1000;
game.addChild(modeDescriptionTxt);
var normalDescTxt = new Text2('20 waves with victory condition', {
	size: 60,
	fill: 0x333333
});
normalDescTxt.anchor.set(0.5, 0.5);
normalDescTxt.x = 1024;
normalDescTxt.y = 1280;
game.addChild(normalDescTxt);
var endlessDescTxt = new Text2('Infinite waves with increasing difficulty', {
	size: 60,
	fill: 0x333333
});
endlessDescTxt.anchor.set(0.5, 0.5);
endlessDescTxt.x = 1024;
endlessDescTxt.y = 1480;
game.addChild(endlessDescTxt);
// Menu button event handlers
normalBtn.down = function () {
	gameMode = 'normal';
	startGame();
};
endlessBtn.down = function () {
	gameMode = 'endless';
	startGame();
};
function startGame() {
	gameStarted = true;
	menuVisible = false;
	// Hide menu elements
	normalBtn.visible = false;
	endlessBtn.visible = false;
	modeDescriptionTxt.visible = false;
	normalDescTxt.visible = false;
	endlessDescTxt.visible = false;
	// Show game UI elements
	sunDisplay.visible = true;
	waveDisplay.visible = true;
	peashooterBtn.visible = true;
	sunflowerBtn.visible = true;
	cherrypopperBtn.visible = true;
	wallnutBtn.visible = true;
	potatomineBtn.visible = true;
	snowshooterBtn.visible = true;
	chomperBtn.visible = true;
	repeaterBtn.visible = true;
	splitpeaBtn.visible = true;
	puffshroomBtn.visible = true;
	shovelBtn.visible = true;
	leftArrow.visible = true;
	rightArrow.visible = true;
	// Show cost texts
	peaCostTxt.visible = true;
	sunCostTxt.visible = true;
	cherryCostTxt.visible = true;
	wallCostTxt.visible = true;
	potatomineCosTxt.visible = true;
	snowCostTxt.visible = true;
	chomperCostTxt.visible = true;
	repeaterCostTxt.visible = true;
	splitpeaCostTxt.visible = true;
	puffshroomCostTxt.visible = true;
	shovelCostTxt.visible = true;
	// Update plant selector to show correct page
	updatePlantSelector();
	// Start first wave
	startNextWave();
}
// Initially hide game UI elements
sunDisplay.visible = false;
waveDisplay.visible = false;
peashooterBtn.visible = false;
sunflowerBtn.visible = false;
cherrypopperBtn.visible = false;
wallnutBtn.visible = false;
potatomineBtn.visible = false;
snowshooterBtn.visible = false;
chomperBtn.visible = false;
repeaterBtn.visible = false;
splitpeaBtn.visible = false;
puffshroomBtn.visible = false;
shovelBtn.visible = false;
leftArrow.visible = false;
rightArrow.visible = false;
peaCostTxt.visible = false;
sunCostTxt.visible = false;
cherryCostTxt.visible = false;
wallCostTxt.visible = false;
potatomineCosTxt.visible = false;
snowCostTxt.visible = false;
chomperCostTxt.visible = false;
repeaterCostTxt.visible = false;
splitpeaCostTxt.visible = false;
puffshroomCostTxt.visible = false;
shovelCostTxt.visible = false;