/**** 
* Classes
****/ 
// Ensure ranged sound exists
// Simple Button Class
var Button = Container.expand(function (text, config) {
	var self = Container.call(this);
	// Methods must be defined before event handlers if called internally
	self.setText = function (newText) {
		self.label.setText(newText);
	};
	self.setEnabled = function (enabled) {
		self.interactive = enabled; // Control interactability
		// LK engine doesn't directly use obj.interactive for event routing like standard PIXI,
		// but good practice. Use alpha for visual cue.
		self.alpha = enabled ? 1.0 : 0.5;
	};
	// --- Initialize ---
	self.config = config || {};
	var width = self.config.width || 300;
	var height = self.config.height || 100;
	var bgColor = self.config.bgColor || 0x555555;
	var textColor = self.config.textColor || '#FFFFFF';
	var textSize = self.config.textSize || 40;
	var bg = self.attachAsset('buttonBg', {
		width: width,
		height: height,
		// color: bgColor, // Shape color is set at init time, cannot override here
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Tint the background shape if a color was provided in config
	bg.tint = bgColor;
	self.label = new Text2(text, {
		size: textSize,
		fill: textColor
	});
	self.label.anchor.set(0.5, 0.5);
	self.addChild(self.label);
	// Placeholder for the action, assign this after creating an instance
	self.onClick = null; // Must be assigned externally
	// LK engine automatically calls self.down if attached and interactive
	self.down = function (x, y, obj) {
		if (!self.interactive) {
			return;
		} // Respect the enabled state
		// Visual feedback for press
		self.scale.set(0.95);
	};
	// LK engine automatically calls self.up if attached and interactive
	self.up = function (x, y, obj) {
		if (!self.interactive) {
			return;
		} // Respect the enabled state
		self.scale.set(1.0); // Restore scale
		// Check bounds roughly (optional, prevents firing if dragged off significantly)
		if (x >= -width / 2 && x <= width / 2 && y >= -height / 2 && y <= height / 2) {
			if (self.onClick) {
				self.onClick(); // Execute the assigned action
			}
		}
	};
	// Initial state
	self.interactive = true; // Default to enabled
	return self;
});
// Class for the Golden Piggy
var GoldenPiggy = Container.expand(function () {
	var self = Container.call(this);
	// Constants
	var LIFETIME_TICKS = 5 * 60; // 5 seconds lifespan (at 60 FPS)
	// Properties
	self.ticksAlive = 0;
	self.isCollected = false;
	// --- Methods ---
	// Called when the piggy is tapped/clicked
	self.collect = function () {
		if (self.isCollected) {
			return;
		} // Prevent double collection
		self.isCollected = true;
		gold += 35; // Updated gold amount
		updateGoldDisplay();
		// Optional: Play a sound effect
		try {
			// Reuse recruit sound or add a dedicated 'coin' sound if available
			LK.getSound('recruit').play();
		} catch (e) {
			console.log("Sound error playing piggy collect sound: " + e);
		}
		// Remove the piggy visually (can be done in game.update)
		// self.visible = false; // Or self.destroy() handled by game.update
		console.log("Golden Piggy collected! +50 gold.");
	};
	// LK engine calls this automatically if attached
	self.up = function (x, y, obj) {
		// Check bounds roughly to ensure the tap was on the piggy
		// Assuming piggy is roughly 100x100 as per asset
		if (x >= -self.graphics.width / 2 && x <= self.graphics.width / 2 && y >= -self.graphics.height / 2 && y <= self.graphics.height / 2) {
			self.collect();
		}
	};
	// Called by game.update
	self.update = function () {
		if (self.isCollected) {
			return; // Stop updating if collected
		}
		self.ticksAlive++;
		if (self.ticksAlive > LIFETIME_TICKS) {
			// Mark for removal if lifetime expires
			self.isCollected = true; // Use the same flag to trigger removal
			console.log("Golden Piggy disappeared.");
		}
		// Optional: Add subtle movement like bobbing up and down
		self.graphics.y = Math.sin(self.ticksAlive / 20) * 10; // Bobbing effect
	};
	// --- Initialize ---
	self.graphics = self.attachAsset('Goldpiggy', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.interactive = true; // Make it tappable
	return self;
});
// var tween = LK.import('@upit/tween.v1'); // Not strictly needed for MVP
// Base class for all units
var Unit = Container.expand(function (config) {
	var self = Container.call(this);
	// Define methods first
	self.findTarget = function (enemyArray) {
		var closestTarget = null;
		var minDistance = Infinity;
		// Make sure enemyArray is defined and is an array
		if (!enemyArray || !Array.isArray(enemyArray)) {
			return null;
		}
		for (var i = 0; i < enemyArray.length; i++) {
			var enemy = enemyArray[i];
			if (enemy.isDead) {
				continue;
			}
			// Using horizontal distance for simplicity
			var distance = Math.abs(self.x - enemy.x);
			if (distance < minDistance) {
				minDistance = distance;
				closestTarget = enemy;
			}
		}
		if (closestTarget && minDistance <= self.attackRange) {
			return closestTarget; // Return target if it's within attack range
		} else {
			return null; // No target in range
		}
	};
	self.attack = function () {
		if (self.target && !self.target.isDead && self.attackCooldown <= 0) {
			try {
				// Defensive coding for sound playback
				LK.getSound(self.attackSoundId).play();
			} catch (e) {
				console.log("Sound error playing " + self.attackSoundId + ": " + e);
			}
			self.target.takeDamage(self.attackPower);
			self.attackCooldown = self.attackCooldownTime;
		}
	};
	self.move = function () {
		// Move towards the enemy side
		self.x += self.speed * (self.isEnemy ? -1 : 1);
		// Basic boundary check
		if (self.x < -100 || self.x > GAME_WIDTH + 100) {
			self.die(); // Remove if goes way off screen
		}
	};
	self.takeDamage = function (damage) {
		if (self.isDead) {
			return;
		} // Already dead
		self.hp -= damage;
		// Optional: Add a visual effect like tinting red briefly
		// LK.effects.flashObject(self, 0xFF0000, 100); // Flashing the container might work
		if (self.hp <= 0) {
			// Award gold if an enemy dies from player attack
			if (self.isEnemy) {
				// Award gold based on unit type/strength
				gold += 5; // Base gold reward
				updateGoldDisplay(); // Update the display immediately
			}
			self.die();
		}
	};
	self.die = function () {
		if (!self.isDead) {
			try {
				// Defensive coding for sound playback
				LK.getSound('unitDeath').play();
			} catch (e) {
				console.log("Sound error playing unitDeath: " + e);
			}
			self.isDead = true;
			// It will be removed from the game and array in game.update
		}
	};
	// LK calls this automatically if the instance is attached to the stage/game
	self.update = function (enemyArray) {
		// This method requires the global `isBattling` to be accessible.
		if (self.isDead || !isBattling) {
			return;
		} // Don't update if dead or battle not active
		// Update cooldown
		if (self.attackCooldown > 0) {
			self.attackCooldown--;
		}
		// Find target
		self.target = self.findTarget(enemyArray);
		// Act based on target
		if (self.target) {
			self.isMoving = false; // Stop moving when target is in range
			self.attack();
		} else {
			self.isMoving = true; // No target in range, resume moving
		}
		// Move if needed
		if (self.isMoving) {
			self.move();
		}
		self.lastX = self.x; // Update last known state
	};
	// --- Initialize ---
	self.isEnemy = config.isEnemy;
	self.hp = config.hp;
	self.maxHp = config.hp; // Store max HP
	self.attackPower = config.attackPower;
	self.attackRange = config.attackRange;
	self.attackCooldownTime = config.attackCooldownTime || 60; // Default 1 sec cooldown
	self.speed = config.speed;
	self.assetId = config.assetId;
	self.attackSoundId = config.attackSoundId || 'attackMelee';
	self.unitType = config.unitType; // Store the unit type identifier
	// Attach graphics *after* properties are set
	self.graphics = self.attachAsset(self.assetId, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// State variables
	self.target = null;
	self.attackCooldown = 0; // Start ready to attack
	self.isMoving = true;
	self.isDead = false;
	self.lastX = 0; // Initialize lastX, will be set correctly on spawn
	// Upgrade logic removed - replaced by global research system
});
// WebGL Shader initialization
var WebGLHelper = Container.expand(function () {
	var self = Container.call(this);
	// Method to initialize WebGL shaders
	self.initShaders = function (renderer) {
		if (!renderer || !renderer.gl) {
			return;
		}
		try {
			var createShader = function createShader(gl, source, type) {
				var shader = gl.createShader(type);
				gl.shaderSource(shader, source);
				gl.compileShader(shader);
				if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
					console.error('WebGL shader compilation failed: ' + gl.getShaderInfoLog(shader));
					gl.deleteShader(shader);
					return null;
				}
				return shader;
			};
			var gl = renderer.gl;
			// Vertex shader
			var vertexShaderSource = "\n\t\t\t\tattribute vec2 aVertexPosition;\n\t\t\t\tattribute vec2 aTextureCoord;\n\t\t\t\tuniform mat3 projectionMatrix;\n\t\t\t\tvarying vec2 vTextureCoord;\n\t\t\t\tvoid main(void) {\n\t\t\t\t\tgl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n\t\t\t\t\tvTextureCoord = aTextureCoord;\n\t\t\t\t}";
			// Fragment shader
			var fragmentShaderSource = "\n\t\t\t\tprecision mediump float;\n\t\t\t\tvarying vec2 vTextureCoord;\n\t\t\t\tuniform sampler2D uSampler;\n\t\t\t\tvoid main(void) {\n\t\t\t\t\tgl_FragColor = texture2D(uSampler, vTextureCoord);\n\t\t\t\t}";
			// Create shader program
			var vertexShader = createShader(gl, vertexShaderSource, gl.VERTEX_SHADER);
			var fragmentShader = createShader(gl, fragmentShaderSource, gl.FRAGMENT_SHADER);
			if (!vertexShader || !fragmentShader) {
				return;
			}
			// Create program
			var program = gl.createProgram();
			gl.attachShader(program, vertexShader);
			gl.attachShader(program, fragmentShader);
			gl.linkProgram(program);
			if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
				console.error('WebGL program linking failed: ' + gl.getProgramInfoLog(program));
				gl.deleteProgram(program);
				return;
			}
			return program;
		} catch (e) {
			console.error('WebGL shader initialization error:', e);
		}
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x101020 // Dark background for the war theme
});
/**** 
* Game Code
****/ 
// Button background
// Blue ellipse
// Green box
// Gray ellipse
// White box
// Define logical assets for units and UI.
// LK Engine automatically creates assets based on usage.
// Game constants and configuration
// Added assets for new human units
// Placeholder ID
// Placeholder ID
// Placeholder ID
// Ensure melee sound exists
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var PLAYER_SPAWN_X = 150;
var ENEMY_SPAWN_X = GAME_WIDTH - 150;
var SPAWN_Y_START = GAME_HEIGHT * 0.3; // Start spawning units lower down
var SPAWN_Y_END = GAME_HEIGHT * 0.8; // End spawning units lower down
var SPAWN_Y_STEP = 100; // Vertical distance between spawned units
// Research configuration
var MILITIA_RESEARCH_COST = 50;
var SLINGER_RESEARCH_COST = 75;
var SHIELDED_RESEARCH_COST = 60; // Cost to research Shielded Skeleton
var SWORDSMAN_RESEARCH_COST = 120; // Cost to research Swordsman
var ARCHER_RESEARCH_COST = 150; // Cost to research Archer
var HOPLITE_RESEARCH_COST = 180; // Cost to research Hoplite
var militiaResearchComplete = false; // Tier 1 Melee (Rookie)
var slingerResearchComplete = false; // Tier 1 Ranged (Trainee)
var swordsmanResearchComplete = false; // Tier 2 Melee
var archerResearchComplete = false; // Tier 2 Ranged
var shieldedResearchComplete = false; // Tier 1 Defender
var hopliteResearchComplete = false; // Tier 2 Defender
// Unit stats lookup table
var UNIT_STATS = {
	skeletonMilitia: {
		hp: 50,
		attackPower: 5,
		attackRange: 80,
		speed: 1.5,
		assetId: 'skeletonMilitia',
		cost: 10,
		// Cost to recruit base militia
		attackSoundId: 'attackMelee'
	},
	// Note: skeletonRookie stats are defined below, its cost is for recruitment *after* research.
	skeletonSlinger: {
		hp: 30,
		attackPower: 7,
		attackRange: 400,
		speed: 1.2,
		assetId: 'skeletonSlinger',
		cost: 15,
		// Cost to recruit base slinger
		attackCooldownTime: 90,
		attackSoundId: 'attackRanged'
	},
	// Note: skeletonTraineeArcher stats are defined below, its cost is for recruitment *after* research.
	humanFarmer: {
		hp: 40,
		attackPower: 4,
		attackRange: 70,
		speed: 1.3,
		assetId: 'humanFarmer',
		attackSoundId: 'attackMelee'
	},
	humanSlinger: {
		hp: 25,
		attackPower: 6,
		attackRange: 380,
		speed: 1.1,
		assetId: 'humanSlinger',
		attackCooldownTime: 90,
		attackSoundId: 'attackRanged'
	},
	// --- New Human Units ---
	humanGuard: {
		hp: 80,
		// Tougher than Farmer
		attackPower: 7,
		attackRange: 85,
		// Slightly longer reach than militia
		speed: 1.2,
		assetId: 'humanGuard',
		attackSoundId: 'attackMelee'
	},
	humanMilitiaArcher: {
		hp: 35,
		// Similar to Slinger
		attackPower: 8,
		// Slightly more damage than Slinger
		attackRange: 420,
		// Slightly longer range
		speed: 1.3,
		assetId: 'humanMilitiaArcher',
		attackCooldownTime: 80,
		// Slightly faster fire rate
		attackSoundId: 'attackRanged'
	},
	// --- New Elite Human Units ---
	humanEliteGuard: {
		hp: 120,
		// Much tougher than Guard
		attackPower: 12,
		// Significantly more damage than Guard
		attackRange: 90,
		// Slightly longer reach than Guard
		speed: 1.2,
		// Same speed as Guard
		assetId: 'humanEliteguard',
		attackSoundId: 'attackMelee'
	},
	humanArcher: {
		hp: 45,
		// Tougher than Militia Archer
		attackPower: 11,
		// More damage than Militia Archer
		attackRange: 450,
		// Better range than Militia Archer
		speed: 1.3,
		// Same speed as Militia Archer
		assetId: 'HumanArcher',
		attackCooldownTime: 70,
		// Faster fire rate than Militia Archer
		attackSoundId: 'attackRanged'
	},
	// --- New King's Guard (Melee Tier 3) ---
	"King's guard": {
		hp: 180,
		// Very tough
		attackPower: 15,
		// High damage
		attackRange: 100,
		// Good reach
		speed: 1.4,
		// Slightly faster than Elite Guard
		assetId: 'humanEliteguard',
		// Reusing asset, could be new if available
		attackSoundId: 'attackMelee'
	},
	// --- New Crossbowman (Ranged Tier 3) ---
	"Crossbowman": {
		hp: 60,
		// Fragile
		attackPower: 18,
		// Very high damage
		attackRange: 500,
		// Long range
		speed: 1.1,
		// Slower than Archer
		assetId: 'skeletonCrossbowman',
		// Reusing asset, could be new if available
		attackCooldownTime: 60,
		// Fast attack
		attackSoundId: 'attackRanged'
	},
	// --- New King's Shield (Defender Tier 3) ---
	"King's shield": {
		hp: 300,
		// Extremely tough
		attackPower: 8,
		// Moderate damage
		attackRange: 110,
		// Excellent reach
		speed: 1.3,
		// Average speed for defender
		assetId: 'humanGuardian',
		// Reusing asset, could be new if available
		attackSoundId: 'attackMelee'
	},
	// --- New Bomber (Artillery Tier 1) ---
	"Bomber": {
		hp: 20,
		// Very fragile
		attackPower: 20,
		// High AoE damage (conceptually)
		attackRange: 700,
		// Very long range
		speed: 0.6,
		// Very slow
		assetId: 'skeletonBomber',
		// Reusing asset, could be new if available
		attackCooldownTime: 180,
		// Very slow attack rate
		attackSoundId: 'attackRanged' // Placeholder, ideally an explosion sound
	},
	// --- New Cannoneer (Artillery Tier 2) ---
	"Cannoneer": {
		hp: 35,
		// Fragile
		attackPower: 30,
		// Very high AoE damage
		attackRange: 800,
		// Extremely long range
		speed: 0.5,
		// Even slower
		assetId: 'skeletonPumpkinCatapult',
		// Reusing asset, could be new if available
		attackCooldownTime: 240,
		// Very slow attack rate
		attackSoundId: 'attackRanged' // Placeholder
	},
	// --- New Trebuchet (Artillery Tier 3) ---
	"Trebuchet": {
		hp: 50,
		// Still fragile
		attackPower: 50,
		// Massive AoE damage
		attackRange: 900,
		// Supreme range
		speed: 0.4,
		// Extremely slow
		assetId: 'skeletonDragon',
		// Reusing asset, could be new if available
		attackCooldownTime: 300,
		// Extremely slow attack rate
		attackSoundId: 'attackRanged' // Placeholder
	},
	// -- Special Human Units --
	humanLocalprotector: {
		hp: 150,
		// Very tough defender unit
		attackPower: 6,
		// Moderate damage
		attackRange: 90,
		// Melee range
		speed: 1.5,
		// Same speed as melee units
		assetId: 'humanLocalprotector',
		attackSoundId: 'attackMelee'
	},
	humanGuardian: {
		hp: 220,
		// Extremely tough defender unit
		attackPower: 10,
		// Good damage for a defender
		attackRange: 100,
		// Slightly better melee range
		speed: 1.5,
		// Same speed as melee units
		assetId: 'humanGuardian',
		attackSoundId: 'attackMelee'
	},
	// --- Researched Player Units ---
	skeletonRookie: {
		hp: 70,
		attackPower: 8,
		attackRange: 90,
		speed: 1.5,
		// Match militia speed to prevent getting faster when upgraded
		assetId: 'skeletonRookie',
		// Use the dedicated rookie asset
		cost: 20,
		attackSoundId: 'attackMelee'
	},
	// Reusing militia asset for now
	skeletonTraineeArcher: {
		hp: 40,
		attackPower: 10,
		attackRange: 450,
		speed: 1.2,
		// Match slinger speed to prevent getting faster when upgraded
		assetId: 'skeletonTraineearcher',
		// Use the dedicated trainee archer asset
		cost: 25,
		attackCooldownTime: 70,
		attackSoundId: 'attackRanged'
	},
	// --- Tier 2 Researched Player Units ---
	skeletonSwordsman: {
		hp: 100,
		// Stronger than Rookie
		attackPower: 12,
		// Higher damage
		attackRange: 100,
		// Slightly better reach
		speed: 1.5,
		// Match militia/rookie speed to prevent getting faster when upgraded
		assetId: 'skeletonSwordsman',
		cost: 35,
		// Cost after research
		attackSoundId: 'attackMelee'
	},
	skeletonArcher: {
		hp: 55,
		// More durable than Trainee
		attackPower: 14,
		// Significantly more damage
		attackRange: 500,
		// Longer range
		speed: 1.2,
		// Match slinger/trainee speed to prevent getting faster when upgraded
		assetId: 'skeletonArcher',
		cost: 40,
		// Cost after research
		attackCooldownTime: 60,
		// Faster attack speed
		attackSoundId: 'attackRanged'
	},
	// --- Tier 1 & 2 Defender Player Units ---
	skeletonShielded: {
		// Tier 1 Defender
		hp: 120,
		// High health
		attackPower: 4,
		// Low damage
		attackRange: 80,
		// Melee range
		speed: 1.5,
		// Match militia/rookie speed
		assetId: 'skeletonShielded',
		cost: 25,
		// Cost after research
		attackSoundId: 'attackMelee'
	},
	skeletonHoplite: {
		// Tier 2 Defender
		hp: 180,
		// Very high health
		attackPower: 7,
		// Slightly better damage
		attackRange: 90,
		// Melee range
		speed: 1.5,
		// Match militia/rookie/swordsman speed
		assetId: 'skeletonHolpite',
		cost: 45,
		// Cost after research
		attackSoundId: 'attackMelee'
	},
	// --- Tier 3 Researched Player Units ---
	skeletonEliteswordsman: {
		hp: 150,
		// Stronger than Swordsman
		attackPower: 18,
		// Significantly higher damage
		attackRange: 110,
		// Slightly better reach
		speed: 1.5,
		// Match previous melee speed
		assetId: 'skeletonEliteswordsman',
		cost: 60,
		// Cost after research
		attackSoundId: 'attackMelee'
	},
	skeletonCrossbowman: {
		hp: 75,
		// More durable than Archer
		attackPower: 20,
		// High damage
		attackRange: 550,
		// Longest range
		speed: 1.2,
		// Match previous ranged speed
		assetId: 'skeletonCrossbowman',
		cost: 70,
		// Cost after research
		attackCooldownTime: 50,
		// Even faster attack speed
		attackSoundId: 'attackRanged'
	},
	skeletonDarkKnight: {
		hp: 250,
		// Extremely high health
		attackPower: 12,
		// Better damage than Hoplite
		attackRange: 100,
		// Melee range
		speed: 1.5,
		// Match previous melee speed
		assetId: 'skeletonDarkKnight',
		cost: 80,
		// Cost after research
		attackSoundId: 'attackMelee'
	},
	// --- Tier 1-3 Artillery Player Units ---
	skeletonBomber: {
		// Tier 1 Artillery
		hp: 20,
		// Very fragile
		attackPower: 15,
		// High damage
		attackRange: 600,
		// Long range
		speed: 0.8,
		// Very slow
		assetId: 'skeletonBomber',
		cost: 30,
		// Cost after research
		attackCooldownTime: 120,
		// Slow attack speed
		attackSoundId: 'attackRanged' // Placeholder, maybe a 'boom' sound later
	},
	skeletonPumpkinCatapult: {
		// Tier 2 Artillery
		hp: 40,
		// Still fragile
		attackPower: 25,
		// Very high damage
		attackRange: 700,
		// Longer range
		speed: 0.7,
		// Even slower
		assetId: 'skeletonPumpkinCatapult',
		cost: 55,
		// Cost after research
		attackCooldownTime: 150,
		// Slower attack speed
		attackSoundId: 'attackRanged' // Placeholder
	},
	skeletonDragon: {
		// Tier 3 Artillery
		hp: 80,
		// Moderately durable for artillery
		attackPower: 40,
		// Extremely high damage
		attackRange: 800,
		// Very long range
		speed: 1.0,
		// Slightly faster than others
		assetId: 'skeletonDragon',
		cost: 100,
		// Cost after research
		attackCooldownTime: 180,
		// Very slow attack speed
		attackSoundId: 'attackRanged' // Placeholder
	}
};
// Research configuration
var SHIELDED_RESEARCH_COST = 60;
var HOPLITE_RESEARCH_COST = 180;
// Research state
var shieldedResearchComplete = false; // Tier 1 Defender
var hopliteResearchComplete = false; // Tier 2 Defender
// Tier 3 Research Costs
var ELITESWORDSMAN_RESEARCH_COST = 250;
var CROSSBOWMAN_RESEARCH_COST = 300;
var DARKKNIGHT_RESEARCH_COST = 350;
// Tier 3 Research State
var eliteSwordsmanResearchComplete = false;
var crossbowmanResearchComplete = false;
var darkKnightResearchComplete = false;
// Artillery Research Costs
var BOMBER_RESEARCH_COST = 80;
var CATAPULT_RESEARCH_COST = 200;
var DRAGON_RESEARCH_COST = 400;
// Artillery Research State
var bomberResearchComplete = false;
var catapultResearchComplete = false;
var dragonResearchComplete = false;
// Game state variables - Defined globally for access within functions and update loop
var gold = 10;
var playerUnits = [];
var enemyUnits = [];
var isBattling = false;
var battleCounter = 0; // Tracks the number of battles won
var currentEnemyConfig = {}; // Store the config for the current battle
var goldenPiggyInstance = null; // Holds the active Golden Piggy instance
// Initial player army composition (can be modified by recruitment)
// Using an object for easier modification by type
var playerArmyRoster = {
	skeletonMilitia: 2,
	skeletonSlinger: 1
};
// --- UI Elements ---
// Gold Display
var goldTxt = new Text2('Gold: 0', {
	size: 60,
	fill: 0xFFD700
});
goldTxt.anchor.set(1.0, 0); // Anchor top-right
goldTxt.x = -50; // Offset from the right edge
goldTxt.y = 20; // Offset from the top edge
// Avoid top-left (reserved for LK menu), top-right is fine.
LK.gui.topRight.addChild(goldTxt);
// Village Counter Display
var villageTxt = new Text2('Village: 1', {
	size: 60,
	fill: 0xFFD700
});
villageTxt.anchor.set(0.0, 0); // Anchor top-left
villageTxt.x = 50; // Offset from the left edge
villageTxt.y = 20; // Offset from the top edge
LK.gui.topLeft.addChild(villageTxt);
// Buttons Container (for organizing buttons at the bottom)
var buttonContainer = new Container();
buttonContainer.x = GAME_WIDTH / 2;
buttonContainer.y = GAME_HEIGHT - 200; // Position buttons lower
game.addChild(buttonContainer); // Add to the main game scene
// Start Battle Button
var startButton = new Button('Start Battle', {
	width: 400,
	height: 120,
	textSize: 50,
	bgColor: 0x008000
}); // Greenish button
startButton.y = -80; // Position above the recruitment buttons
buttonContainer.addChild(startButton);
// Recruitment Buttons (Example: Militia)
var recruitMilitiaButton = new Button('Recruit Militia (10g)', {
	width: 400,
	height: 100,
	textSize: 40,
	bgColor: 0x404040
});
recruitMilitiaButton.x = -330; // Position further left for three buttons
recruitMilitiaButton.y = 80; // Position below start button
buttonContainer.addChild(recruitMilitiaButton);
// Example: Slinger recruitment button
var recruitSlingerButton = new Button('Recruit Slinger (15g)', {
	width: 400,
	height: 100,
	textSize: 40,
	bgColor: 0x404040
});
recruitSlingerButton.x = 330; // Position further right for three buttons
recruitSlingerButton.y = 80; // Position below start button
buttonContainer.addChild(recruitSlingerButton);
// Defender recruitment button
var recruitDefenderButton = new Button('Recruit Defender (25g)', {
	width: 400,
	height: 100,
	textSize: 40,
	bgColor: 0x404040
});
recruitDefenderButton.x = 0; // Center position
recruitDefenderButton.y = 80; // Same row as other recruitment buttons
buttonContainer.addChild(recruitDefenderButton);
// Research Buttons
var researchMilitiaButton = new Button('Research Rookie (50g)', {
	width: 400,
	height: 100,
	textSize: 40,
	bgColor: 0x004080 // Blueish button
});
researchMilitiaButton.x = -220; // Position left, above recruitment
researchMilitiaButton.y = -220; // Position above recruitment buttons
buttonContainer.addChild(researchMilitiaButton);
var researchSlingerButton = new Button('Research Trainee (75g)', {
	width: 400,
	height: 100,
	textSize: 40,
	bgColor: 0x004080 // Blueish button
});
researchSlingerButton.x = 220; // Position right, above recruitment
researchSlingerButton.y = -220; // Position above recruitment buttons
buttonContainer.addChild(researchSlingerButton);
// Tier 2 Research Buttons (Initially hidden)
var researchSwordsmanButton = new Button('Research Swordsman (' + SWORDSMAN_RESEARCH_COST + 'g)', {
	width: 400,
	height: 100,
	textSize: 35,
	// Slightly smaller text if needed
	bgColor: 0x800080 // Purpleish button
});
researchSwordsmanButton.x = -220;
researchSwordsmanButton.y = -350; // Position above Tier 1 research
researchSwordsmanButton.visible = false; // Hidden until prerequisite met
buttonContainer.addChild(researchSwordsmanButton);
var researchArcherButton = new Button('Research Archer (' + ARCHER_RESEARCH_COST + 'g)', {
	width: 400,
	height: 100,
	textSize: 35,
	// Slightly smaller text if needed
	bgColor: 0x800080 // Purpleish button
});
researchArcherButton.x = 220;
researchArcherButton.y = -350; // Position above Tier 1 research
researchArcherButton.visible = false; // Hidden until prerequisite met
buttonContainer.addChild(researchArcherButton);
buttonContainer.addChild(researchArcherButton);
// Defender Research Buttons
var researchShieldedButton = new Button('Research Shielded (' + SHIELDED_RESEARCH_COST + 'g)', {
	width: 400,
	height: 100,
	textSize: 35,
	bgColor: 0x6A5ACD // SlateBlue button
});
researchShieldedButton.x = 0; // Position center, above Tier 1 Melee/Ranged
researchShieldedButton.y = -220; // Same level as Tier 1 Melee/Ranged research
buttonContainer.addChild(researchShieldedButton);
var researchHopliteButton = new Button('Research Hoplite (' + HOPLITE_RESEARCH_COST + 'g)', {
	width: 400,
	height: 100,
	textSize: 35,
	bgColor: 0x483D8B // DarkSlateBlue button
});
researchHopliteButton.x = 0; // Position center, above Tier 2 Melee/Ranged
researchHopliteButton.y = -350; // Same level as Tier 2 Melee/Ranged research
researchHopliteButton.visible = false; // Hidden until prerequisite met
buttonContainer.addChild(researchHopliteButton);
// Adjust positions to accommodate the third column (Defender research)
// Tier 1 Research
researchMilitiaButton.x = -440; // Move left
researchMilitiaButton.y = -220;
researchSlingerButton.x = 440; // Move right
researchSlingerButton.y = -220;
researchShieldedButton.x = 0; // Center
researchShieldedButton.y = -220;
// Tier 2 Research
researchSwordsmanButton.x = -440; // Move left
researchSwordsmanButton.y = -350;
researchArcherButton.x = 440; // Move right
researchArcherButton.y = -350;
researchHopliteButton.x = 0; // Center
researchHopliteButton.y = -350;
// Adjust Start Button position further up
startButton.y = -480; // Move start button further up
// Tier 3 Research Buttons (Initially hidden)
var researchEliteSwordsmanButton = new Button('Research Elite (' + ELITESWORDSMAN_RESEARCH_COST + 'g)', {
	width: 400,
	height: 100,
	textSize: 35,
	bgColor: 0xFF4500 // Orangish-Red button
});
researchEliteSwordsmanButton.x = -440; // Position left, above Tier 2
researchEliteSwordsmanButton.y = -480; // Position above Tier 2 research
researchEliteSwordsmanButton.visible = false; // Hidden until prerequisite met
buttonContainer.addChild(researchEliteSwordsmanButton);
var researchCrossbowmanButton = new Button('Research Crossbow (' + CROSSBOWMAN_RESEARCH_COST + 'g)', {
	width: 400,
	height: 100,
	textSize: 35,
	bgColor: 0xFF4500 // Orangish-Red button
});
researchCrossbowmanButton.x = 440; // Position right, above Tier 2
researchCrossbowmanButton.y = -480; // Position above Tier 2 research
researchCrossbowmanButton.visible = false; // Hidden until prerequisite met
buttonContainer.addChild(researchCrossbowmanButton);
var researchDarkKnightButton = new Button('Research D.Knight (' + DARKKNIGHT_RESEARCH_COST + 'g)', {
	width: 400,
	height: 100,
	textSize: 35,
	bgColor: 0x8B0000 // DarkRed button
});
researchDarkKnightButton.x = 0; // Position center, above Tier 2
researchDarkKnightButton.y = -480; // Position above Tier 2 research
researchDarkKnightButton.visible = false; // Hidden until prerequisite met
buttonContainer.addChild(researchDarkKnightButton);
// Adjust Start Button position even further up to accommodate Tier 3 research
startButton.y = -610; // Move start button further up
// --- Artillery Research Buttons ---
var researchBomberButton = new Button('Research Bomber (' + BOMBER_RESEARCH_COST + 'g)', {
	width: 380,
	// Slightly narrower for 4 columns
	height: 100,
	textSize: 35,
	bgColor: 0x8A2BE2 // BlueViolet
});
researchBomberButton.x = 220; // Position between Defender and Ranged (Right side)
researchBomberButton.y = -220; // Tier 1 row
researchBomberButton.visible = true; // Initially visible
buttonContainer.addChild(researchBomberButton);
var researchCatapultButton = new Button('Research Catapult (' + CATAPULT_RESEARCH_COST + 'g)', {
	width: 380,
	height: 100,
	textSize: 35,
	bgColor: 0x9932CC // DarkOrchid
});
researchCatapultButton.x = 220; // Position between Defender and Ranged (Right side)
researchCatapultButton.y = -350; // Tier 2 row
researchCatapultButton.visible = false; // Hidden until prerequisite met
buttonContainer.addChild(researchCatapultButton);
var researchDragonButton = new Button('Research Dragon (' + DRAGON_RESEARCH_COST + 'g)', {
	width: 380,
	height: 100,
	textSize: 35,
	bgColor: 0xBA55D3 // MediumOrchid
});
researchDragonButton.x = 220; // Position between Defender and Ranged (Right side)
researchDragonButton.y = -480; // Tier 3 row
researchDragonButton.visible = false; // Hidden until prerequisite met
buttonContainer.addChild(researchDragonButton);
// --- Adjust existing button positions for 4 columns ---
var buttonXOffsetLarge = 660; // For outer buttons (Melee, Ranged)
var buttonXOffsetSmall = 220; // For inner buttons (Defender, Artillery)
// Research Buttons
researchMilitiaButton.x = -buttonXOffsetLarge; // Far Left
researchMilitiaButton.width = 380;
researchShieldedButton.x = -buttonXOffsetSmall; // Mid Left // Fix: Used correct variable name
researchShieldedButton.width = 380; // Fix: Used correct variable name
researchBomberButton.x = buttonXOffsetSmall; // Mid Right (new)
researchBomberButton.width = 380;
researchSlingerButton.x = buttonXOffsetLarge; // Far Right
researchSlingerButton.width = 380;
researchSwordsmanButton.x = -buttonXOffsetLarge; // Far Left
researchSwordsmanButton.width = 380;
researchHopliteButton.x = -buttonXOffsetSmall; // Mid Left
researchHopliteButton.width = 380;
researchCatapultButton.x = buttonXOffsetSmall; // Mid Right (new)
researchCatapultButton.width = 380;
researchArcherButton.x = buttonXOffsetLarge; // Far Right
researchArcherButton.width = 380;
researchEliteSwordsmanButton.x = -buttonXOffsetLarge; // Far Left
researchEliteSwordsmanButton.width = 380;
researchDarkKnightButton.x = -buttonXOffsetSmall; // Mid Left
researchDarkKnightButton.width = 380;
researchDragonButton.x = buttonXOffsetSmall; // Mid Right (new)
researchDragonButton.width = 380;
researchCrossbowmanButton.x = buttonXOffsetLarge; // Far Right
researchCrossbowmanButton.width = 380;
// Recruitment Buttons
recruitMilitiaButton.x = -buttonXOffsetLarge; // Far Left
recruitMilitiaButton.width = 380;
recruitDefenderButton.x = -buttonXOffsetSmall; // Mid Left
recruitDefenderButton.width = 380;
// recruitArtilleryButton needs to be created first, then positioned
recruitSlingerButton.x = buttonXOffsetLarge; // Far Right
recruitSlingerButton.width = 380;
// Adjust Start Button position further up
startButton.y = -610; // Keep this adjustment
// --- Add Artillery Recruitment Button ---
var recruitArtilleryButton = new Button('Research Required', {
	// Initial text
	width: 380,
	// Match other buttons
	height: 100,
	textSize: 35,
	// Match research buttons
	bgColor: 0x404040
});
recruitArtilleryButton.x = buttonXOffsetSmall; // Position Mid Right
recruitArtilleryButton.y = 80; // Same row as other recruitment buttons
recruitArtilleryButton.setEnabled(false); // Initially disabled
buttonContainer.addChild(recruitArtilleryButton);
// --- Game Logic Functions ---
function updateGoldDisplay() {
	goldTxt.setText('Gold: ' + gold);
	var canAffordMilitiaResearch = gold >= MILITIA_RESEARCH_COST;
	var canAffordSlingerResearch = gold >= SLINGER_RESEARCH_COST;
	var canAffordShieldedResearch = gold >= SHIELDED_RESEARCH_COST; // New Defender cost check
	var canAffordSwordsmanResearch = gold >= SWORDSMAN_RESEARCH_COST;
	var canAffordArcherResearch = gold >= ARCHER_RESEARCH_COST;
	var canAffordHopliteResearch = gold >= HOPLITE_RESEARCH_COST;
	var canAffordEliteSwordsmanResearch = gold >= ELITESWORDSMAN_RESEARCH_COST;
	var canAffordCrossbowmanResearch = gold >= CROSSBOWMAN_RESEARCH_COST;
	var canAffordDarkKnightResearch = gold >= DARKKNIGHT_RESEARCH_COST;
	// Artillery research cost checks
	var canAffordBomberResearch = gold >= BOMBER_RESEARCH_COST;
	var canAffordCatapultResearch = gold >= CATAPULT_RESEARCH_COST;
	var canAffordDragonResearch = gold >= DRAGON_RESEARCH_COST;
	// --- Update Research Buttons ---
	// Tier 1: Militia -> Rookie
	if (militiaResearchComplete) {
		researchMilitiaButton.visible = false; // Hide Tier 1 when complete
		researchMilitiaButton.setEnabled(false);
	} else {
		researchMilitiaButton.visible = true;
		researchMilitiaButton.setEnabled(canAffordMilitiaResearch && !isBattling);
	}
	// Tier 1: Slinger -> Trainee
	if (slingerResearchComplete) {
		researchSlingerButton.visible = false; // Hide Tier 1 when complete
		researchSlingerButton.setEnabled(false);
	} else {
		researchSlingerButton.visible = true;
		researchSlingerButton.setEnabled(canAffordSlingerResearch && !isBattling);
	}
	// Tier 1: Defender -> Shielded Skeleton
	if (shieldedResearchComplete) {
		researchShieldedButton.visible = false;
		researchShieldedButton.setEnabled(false);
	} else {
		researchShieldedButton.visible = true;
		researchShieldedButton.setEnabled(canAffordShieldedResearch && !isBattling);
	}
	// Tier 2: Rookie -> Swordsman
	if (swordsmanResearchComplete) {
		researchSwordsmanButton.visible = false; // Hide Tier 2 when complete
		researchSwordsmanButton.setEnabled(false);
	} else {
		// Show Tier 2 only if Tier 1 is complete
		researchSwordsmanButton.visible = militiaResearchComplete;
		researchSwordsmanButton.setEnabled(militiaResearchComplete && canAffordSwordsmanResearch && !isBattling);
	}
	// Tier 2: Trainee -> Archer
	if (archerResearchComplete) {
		researchArcherButton.visible = false; // Hide Tier 2 when complete
		researchArcherButton.setEnabled(false);
	} else {
		// Show Tier 2 only if Tier 1 is complete
		researchArcherButton.visible = slingerResearchComplete;
		researchArcherButton.setEnabled(slingerResearchComplete && canAffordArcherResearch && !isBattling);
	}
	// Tier 2: Shielded -> Hoplite
	if (hopliteResearchComplete) {
		researchHopliteButton.visible = false;
		researchHopliteButton.setEnabled(false);
	} else {
		// Show Tier 2 only if Tier 1 is complete
		researchHopliteButton.visible = shieldedResearchComplete;
		researchHopliteButton.setEnabled(shieldedResearchComplete && canAffordHopliteResearch && !isBattling);
	}
	// Tier 3: Swordsman -> Elite Swordsman
	if (eliteSwordsmanResearchComplete) {
		researchEliteSwordsmanButton.visible = false;
		researchEliteSwordsmanButton.setEnabled(false);
	} else {
		// Show Tier 3 only if Tier 2 is complete
		researchEliteSwordsmanButton.visible = swordsmanResearchComplete;
		researchEliteSwordsmanButton.setEnabled(swordsmanResearchComplete && canAffordEliteSwordsmanResearch && !isBattling);
	}
	// Tier 3: Archer -> Crossbowman
	if (crossbowmanResearchComplete) {
		researchCrossbowmanButton.visible = false;
		researchCrossbowmanButton.setEnabled(false);
	} else {
		// Show Tier 3 only if Tier 2 is complete
		researchCrossbowmanButton.visible = archerResearchComplete;
		researchCrossbowmanButton.setEnabled(archerResearchComplete && canAffordCrossbowmanResearch && !isBattling);
	}
	// Tier 3: Hoplite -> Dark Knight
	if (darkKnightResearchComplete) {
		researchDarkKnightButton.visible = false;
		researchDarkKnightButton.setEnabled(false);
	} else {
		// Show Tier 3 only if Tier 2 is complete
		researchDarkKnightButton.visible = hopliteResearchComplete;
		researchDarkKnightButton.setEnabled(hopliteResearchComplete && canAffordDarkKnightResearch && !isBattling);
	}
	// Tier 1: Artillery -> Bomber
	if (bomberResearchComplete) {
		researchBomberButton.visible = false;
		researchBomberButton.setEnabled(false);
	} else {
		researchBomberButton.visible = true;
		researchBomberButton.setEnabled(canAffordBomberResearch && !isBattling);
	}
	// Tier 2: Bomber -> Catapult
	if (catapultResearchComplete) {
		researchCatapultButton.visible = false;
		researchCatapultButton.setEnabled(false);
	} else {
		// Show Tier 2 only if Tier 1 is complete
		researchCatapultButton.visible = bomberResearchComplete;
		researchCatapultButton.setEnabled(bomberResearchComplete && canAffordCatapultResearch && !isBattling);
	}
	// Tier 3: Catapult -> Dragon
	if (dragonResearchComplete) {
		researchDragonButton.visible = false;
		researchDragonButton.setEnabled(false);
	} else {
		// Show Tier 3 only if Tier 2 is complete
		researchDragonButton.visible = catapultResearchComplete;
		researchDragonButton.setEnabled(catapultResearchComplete && canAffordDragonResearch && !isBattling);
	}
	// --- Update Recruitment Buttons ---
	// Determine current highest researched MELEE unit
	var currentMilitiaType = 'skeletonMilitia';
	var militiaButtonText = 'Recruit Militia';
	if (eliteSwordsmanResearchComplete) {
		currentMilitiaType = 'skeletonEliteswordsman';
		militiaButtonText = 'Recruit Elite';
	} else if (swordsmanResearchComplete) {
		currentMilitiaType = 'skeletonSwordsman';
		militiaButtonText = 'Recruit Swordsman';
	} else if (militiaResearchComplete) {
		currentMilitiaType = 'skeletonRookie';
		militiaButtonText = 'Recruit Rookie';
	}
	var currentMilitiaStats = UNIT_STATS[currentMilitiaType];
	recruitMilitiaButton.setText(militiaButtonText + ' (' + currentMilitiaStats.cost + 'g)');
	recruitMilitiaButton.setEnabled(gold >= currentMilitiaStats.cost && !isBattling);
	// Determine current highest researched RANGED unit
	var currentSlingerType = 'skeletonSlinger';
	var slingerButtonText = 'Recruit Slinger';
	if (crossbowmanResearchComplete) {
		currentSlingerType = 'skeletonCrossbowman';
		slingerButtonText = 'Recruit Crossbow';
	} else if (archerResearchComplete) {
		currentSlingerType = 'skeletonArcher';
		slingerButtonText = 'Recruit Archer';
	} else if (slingerResearchComplete) {
		currentSlingerType = 'skeletonTraineeArcher';
		slingerButtonText = 'Recruit Trainee';
	}
	var currentSlingerStats = UNIT_STATS[currentSlingerType];
	recruitSlingerButton.setText(slingerButtonText + ' (' + currentSlingerStats.cost + 'g)');
	recruitSlingerButton.setEnabled(gold >= currentSlingerStats.cost && !isBattling);
	// Determine current highest researched DEFENDER unit
	var currentDefenderType = null;
	var defenderButtonText = 'Research Required';
	if (darkKnightResearchComplete) {
		currentDefenderType = 'skeletonDarkKnight';
		defenderButtonText = 'Recruit D.Knight';
	} else if (hopliteResearchComplete) {
		currentDefenderType = 'skeletonHoplite';
		defenderButtonText = 'Recruit Hoplite';
	} else if (shieldedResearchComplete) {
		currentDefenderType = 'skeletonShielded';
		defenderButtonText = 'Recruit Shielded';
	}
	// Update defender button state based on research status
	if (currentDefenderType) {
		var currentDefenderStats = UNIT_STATS[currentDefenderType];
		recruitDefenderButton.setText(defenderButtonText + ' (' + currentDefenderStats.cost + 'g)');
		recruitDefenderButton.setEnabled(gold >= currentDefenderStats.cost && !isBattling);
	} else {
		// No defender research completed yet
		recruitDefenderButton.setText('Research Required');
		recruitDefenderButton.setEnabled(false);
	}
	// Determine current highest researched ARTILLERY unit
	var currentArtilleryType = null;
	var artilleryButtonText = 'Research Required';
	if (dragonResearchComplete) {
		currentArtilleryType = 'skeletonDragon';
		artilleryButtonText = 'Recruit Dragon';
	} else if (catapultResearchComplete) {
		currentArtilleryType = 'skeletonPumpkinCatapult';
		artilleryButtonText = 'Recruit Catapult';
	} else if (bomberResearchComplete) {
		currentArtilleryType = 'skeletonBomber';
		artilleryButtonText = 'Recruit Bomber';
	}
	// Update artillery button state based on research status
	if (currentArtilleryType) {
		var currentArtilleryStats = UNIT_STATS[currentArtilleryType];
		recruitArtilleryButton.setText(artilleryButtonText + ' (' + currentArtilleryStats.cost + 'g)');
		recruitArtilleryButton.setEnabled(gold >= currentArtilleryStats.cost && !isBattling);
	} else {
		// No artillery research completed yet
		recruitArtilleryButton.setText('Research Required');
		recruitArtilleryButton.setEnabled(false); // Ensure it's disabled
	}
}
function recruitUnit(unitType) {
	if (isBattling) {
		return;
	} // Cannot recruit during battle
	var stats = UNIT_STATS[unitType];
	if (!stats) {
		console.error("Attempted to recruit unknown unit type:", unitType);
		return;
	}
	if (gold >= stats.cost) {
		gold -= stats.cost;
		try {
			// Defensive coding for sound playback
			LK.getSound('recruit').play();
		} catch (e) {
			console.log("Sound error playing recruit: " + e);
		}
		// Safely increment the count in the roster
		playerArmyRoster[unitType] = (playerArmyRoster[unitType] || 0) + 1;
		console.log("Recruited " + unitType + ". Roster:", playerArmyRoster);
		updateGoldDisplay(); // Update UI after recruitment
	} else {
		console.log("Not enough gold to recruit " + unitType);
		// Optional: Show feedback to the player (e.g., flashing the gold red)
		LK.effects.flashObject(goldTxt, 0xFF0000, 300);
	}
}
function researchUnit(researchType) {
	if (isBattling) {
		return;
	} // Cannot research during battle
	var cost = 0;
	var cost = 0;
	var researchName = '';
	var canResearch = false;
	var setResearchFlag = null; // Function to set the correct flag
	if (researchType === 'militia' && !militiaResearchComplete) {
		cost = MILITIA_RESEARCH_COST;
		researchName = 'Rookie';
		canResearch = true; // No prerequisite
		setResearchFlag = function setResearchFlag() {
			militiaResearchComplete = true;
		};
	} else if (researchType === 'slinger' && !slingerResearchComplete) {
		cost = SLINGER_RESEARCH_COST;
		researchName = 'Trainee Archer';
		canResearch = true; // No prerequisite
		setResearchFlag = function setResearchFlag() {
			slingerResearchComplete = true;
		};
	} else if (researchType === 'swordsman' && !swordsmanResearchComplete) {
		cost = SWORDSMAN_RESEARCH_COST;
		researchName = 'Swordsman';
		canResearch = militiaResearchComplete; // Prerequisite: Rookie researched
		setResearchFlag = function setResearchFlag() {
			swordsmanResearchComplete = true;
		};
		if (!canResearch) {
			console.log("Prerequisite not met: Research Rookie first.");
		}
	} else if (researchType === 'archer' && !archerResearchComplete) {
		cost = ARCHER_RESEARCH_COST;
		researchName = 'Archer';
		canResearch = slingerResearchComplete; // Prerequisite: Trainee researched
		setResearchFlag = function setResearchFlag() {
			archerResearchComplete = true;
		};
		if (!canResearch) {
			console.log("Prerequisite not met: Research Trainee Archer first.");
		}
	} else if (researchType === 'shielded' && !shieldedResearchComplete) {
		// New Defender Tier 1
		cost = SHIELDED_RESEARCH_COST;
		researchName = 'Shielded Skeleton';
		canResearch = true; // No prerequisite
		setResearchFlag = function setResearchFlag() {
			shieldedResearchComplete = true;
		};
	} else if (researchType === 'hoplite' && !hopliteResearchComplete) {
		// New Defender Tier 2
		cost = HOPLITE_RESEARCH_COST;
		researchName = 'Skeleton Hoplite';
		canResearch = shieldedResearchComplete; // Prerequisite: Shielded researched
		setResearchFlag = function setResearchFlag() {
			hopliteResearchComplete = true;
		};
		if (!canResearch) {
			console.log("Prerequisite not met: Research Shielded Skeleton first.");
		}
	} else if (researchType === 'eliteswordsman' && !eliteSwordsmanResearchComplete) {
		// Tier 3 Melee
		cost = ELITESWORDSMAN_RESEARCH_COST;
		researchName = 'Elite Swordsman';
		canResearch = swordsmanResearchComplete; // Prerequisite: Swordsman researched
		setResearchFlag = function setResearchFlag() {
			eliteSwordsmanResearchComplete = true;
		};
		if (!canResearch) {
			console.log("Prerequisite not met: Research Swordsman first.");
		}
	} else if (researchType === 'crossbowman' && !crossbowmanResearchComplete) {
		// Tier 3 Ranged
		cost = CROSSBOWMAN_RESEARCH_COST;
		researchName = 'Crossbowman';
		canResearch = archerResearchComplete; // Prerequisite: Archer researched
		setResearchFlag = function setResearchFlag() {
			crossbowmanResearchComplete = true;
		};
		if (!canResearch) {
			console.log("Prerequisite not met: Research Archer first.");
		}
	} else if (researchType === 'darkknight' && !darkKnightResearchComplete) {
		// Tier 3 Defender
		cost = DARKKNIGHT_RESEARCH_COST;
		researchName = 'Dark Knight';
		canResearch = hopliteResearchComplete; // Prerequisite: Hoplite researched
		setResearchFlag = function setResearchFlag() {
			darkKnightResearchComplete = true;
		};
		if (!canResearch) {
			console.log("Prerequisite not met: Research Hoplite first.");
		}
	} else if (researchType === 'bomber' && !bomberResearchComplete) {
		// Artillery Tier 1
		cost = BOMBER_RESEARCH_COST;
		researchName = 'Skeleton Bomber';
		canResearch = true; // No prerequisite
		setResearchFlag = function setResearchFlag() {
			bomberResearchComplete = true;
		};
	} else if (researchType === 'catapult' && !catapultResearchComplete) {
		// Artillery Tier 2
		cost = CATAPULT_RESEARCH_COST;
		researchName = 'Pumpkin Catapult';
		canResearch = bomberResearchComplete; // Prerequisite: Bomber
		setResearchFlag = function setResearchFlag() {
			catapultResearchComplete = true;
		};
		if (!canResearch) {
			console.log("Prerequisite not met: Research Bomber first.");
		}
	} else if (researchType === 'dragon' && !dragonResearchComplete) {
		// Artillery Tier 3
		cost = DRAGON_RESEARCH_COST;
		researchName = 'Skeleton Dragon';
		canResearch = catapultResearchComplete; // Prerequisite: Catapult
		setResearchFlag = function setResearchFlag() {
			dragonResearchComplete = true;
		};
		if (!canResearch) {
			console.log("Prerequisite not met: Research Catapult first.");
		}
	} else {
		console.log("Research already complete, prerequisite not met, or invalid type:", researchType);
		return; // Invalid type, already researched, or prereq not met
	}
	if (canResearch && gold >= cost) {
		gold -= cost;
		setResearchFlag(); // Set the specific research flag to true
		try {
			// Reuse upgrade sound, or create a specific 'research' sound
			LK.getSound('upgradeUnit').play(); // Assuming 'upgradeUnit' sound is suitable
		} catch (e) {
			console.log("Sound error playing research sound: " + e);
		}
		console.log("Research complete for:", researchName);
		updateGoldDisplay(); // Update UI immediately
	} else {
		console.log("Not enough gold to research " + researchName);
		LK.effects.flashObject(goldTxt, 0xFF0000, 300);
	}
}
function clearBattlefield() {
	// Remove all existing units from the game and arrays
	for (var i = playerUnits.length - 1; i >= 0; i--) {
		if (playerUnits[i] && playerUnits[i].destroy) {
			// Check if destroy exists
			playerUnits[i].destroy();
		}
	}
	playerUnits = []; // Reset array
	for (var i = enemyUnits.length - 1; i >= 0; i--) {
		if (enemyUnits[i] && enemyUnits[i].destroy) {
			// Check if destroy exists
			enemyUnits[i].destroy();
		}
	}
	enemyUnits = []; // Reset array
	// Remove the golden piggy if it exists
	if (goldenPiggyInstance !== null) {
		goldenPiggyInstance.destroy();
		goldenPiggyInstance = null;
	}
}
function spawnUnit(unitType, isEnemy) {
	var stats = UNIT_STATS[unitType];
	if (!stats) {
		console.error("Cannot spawn unknown unit type:", unitType);
		return null;
	}
	// Prepare config for the Unit class constructor
	var config = {
		isEnemy: isEnemy,
		hp: stats.hp,
		attackPower: stats.attackPower,
		attackRange: stats.attackRange,
		speed: stats.speed,
		assetId: stats.assetId,
		attackCooldownTime: stats.attackCooldownTime,
		attackSoundId: stats.attackSoundId,
		unitType: unitType // Pass the unit type
	};
	// Create new instance of Unit
	var unit = new Unit(config);
	// Determine spawn side and array
	var armyArray = isEnemy ? enemyUnits : playerUnits;
	var spawnX = isEnemy ? ENEMY_SPAWN_X : PLAYER_SPAWN_X;
	// Calculate staggered Y position
	var currentY = SPAWN_Y_START + armyArray.length * SPAWN_Y_STEP;
	// Wrap Y position if it goes beyond the designated spawn area end
	if (currentY > SPAWN_Y_END) {
		var yRange = SPAWN_Y_END - SPAWN_Y_START;
		if (yRange <= 0) {
			yRange = SPAWN_Y_STEP;
		} // Avoid division by zero or negative range
		currentY = SPAWN_Y_START + armyArray.length * SPAWN_Y_STEP % yRange;
	}
	// Set initial position and state
	unit.x = spawnX;
	unit.y = currentY;
	unit.lastX = unit.x; // Initialize last state correctly
	// Add the unit to the game display and the logical array
	game.addChild(unit);
	armyArray.push(unit);
	return unit; // Return the created unit if needed elsewhere
}
function startBattle() {
	if (isBattling) {
		return;
	} // Prevent starting multiple battles
	console.log("Starting battle...");
	isBattling = true;
	clearBattlefield(); // Remove any units from a previous battle
	// Define enemy forces for this battle (can be made dynamic later)
	if (Object.keys(currentEnemyConfig).length === 0) {
		// Only initialize on first battle
		currentEnemyConfig = {
			humanFarmer: 3,
			humanSlinger: 1
		};
	} // Otherwise use the already incremented config from previous win
	// Spawn Player Units based on the current roster
	console.log("Spawning player units:", playerArmyRoster);
	for (var unitType in playerArmyRoster) {
		if (playerArmyRoster.hasOwnProperty(unitType)) {
			// Good practice for iterating objects
			var count = playerArmyRoster[unitType];
			for (var i = 0; i < count; i++) {
				spawnUnit(unitType, false); // Spawn player unit (not enemy)
			}
		}
	}
	// Spawn Enemy Units based on the current configuration
	console.log("Spawning enemy units:", currentEnemyConfig);
	for (var unitType in currentEnemyConfig) {
		if (currentEnemyConfig.hasOwnProperty(unitType)) {
			var count = currentEnemyConfig[unitType];
			for (var i = 0; i < count; i++) {
				spawnUnit(unitType, true); // Spawn enemy unit
			}
		}
	}
	// Hide UI elements not relevant during battle
	buttonContainer.visible = false;
	// Ensure units arrays are populated before the first update runs
	console.log("Battle started. Player units:", playerUnits.length, "Enemy units:", enemyUnits.length);
}
function endBattle(playerWon) {
	// Check if the battle hasn't already ended to prevent multiple triggers
	if (!isBattling) {
		return;
	}
	console.log("Battle ended. Player won:", playerWon);
	isBattling = false; // Set state before doing anything else
	// Explicitly remove piggy when battle ends, BEFORE showing UI again.
	// This ensures it's properly cleaned up and allows a new one to spawn in subsequent battles.
	if (goldenPiggyInstance !== null) {
		goldenPiggyInstance.destroy();
		goldenPiggyInstance = null;
	}
	// Show UI elements again
	buttonContainer.visible = true;
	if (playerWon) {
		var goldEarned = 50; // Example gold reward
		gold += goldEarned;
		try {
			// Defensive coding for sound playback
			LK.getSound('battleWon').play();
		} catch (e) {
			console.log("Sound error playing battleWon: " + e);
		}
		console.log("Earned " + goldEarned + " gold. Total gold:", gold);
		// Update display immediately after awarding gold
		updateGoldDisplay();
		battleCounter++; // Increment the battle counter on win
		villageTxt.setText('Village: ' + (battleCounter + 1)); // Update the village counter display
		console.log("Battle won! Proceeding to village: " + (battleCounter + 1));
		// Humans gain more units when player wins battles
		for (var unitType in currentEnemyConfig) {
			if (currentEnemyConfig.hasOwnProperty(unitType)) {
				// Increase each existing unit type by 1-2 for the next battle
				currentEnemyConfig[unitType] += Math.floor(Math.random() * 2) + 1;
			}
		}
		// Introduce new units starting from the 5th battle (after winning the 4th)
		if (battleCounter >= 4) {
			// 4 wins means the next battle is the 5th
			// Add Guard if not present, or increase count
			if (!currentEnemyConfig.hasOwnProperty('humanGuard')) {
				currentEnemyConfig['humanGuard'] = 1; // Start with 1
			} else {
				currentEnemyConfig['humanGuard'] += 1; // Add one more each subsequent win
			}
			// Add Militia Archer if not present, or increase count
			if (!currentEnemyConfig.hasOwnProperty('humanMilitiaArcher')) {
				currentEnemyConfig['humanMilitiaArcher'] = 1; // Start with 1
			} else {
				currentEnemyConfig['humanMilitiaArcher'] += 1; // Add one more each subsequent win
			}
			console.log("Stronger human reinforcements (Guards, Militia Archers) have arrived!");
		}
		// Introduce Local Protector starting from the 6th battle (after winning the 5th)
		if (battleCounter >= 5) {
			// 5 wins means the next battle is the 6th
			if (!currentEnemyConfig.hasOwnProperty('humanLocalprotector')) {
				currentEnemyConfig['humanLocalprotector'] = 1; // Start with 1
			} else {
				currentEnemyConfig['humanLocalprotector'] += 1; // Add one more each win
			}
			console.log("Local Protector reinforcements have arrived!");
		}
		// Introduce elite units starting from the 8th battle (after winning the 7th)
		if (battleCounter >= 7) {
			// 7 wins means the next battle is the 8th
			// Add Elite Guard if not present, or increase count
			if (!currentEnemyConfig.hasOwnProperty('humanEliteGuard')) {
				currentEnemyConfig['humanEliteGuard'] = 1; // Start with 1
			} else {
				currentEnemyConfig['humanEliteGuard'] += 1; // Add one more each subsequent win
			}
			// Add Archer if not present, or increase count
			if (!currentEnemyConfig.hasOwnProperty('humanArcher')) {
				currentEnemyConfig['humanArcher'] = 1; // Start with 1
			} else {
				currentEnemyConfig['humanArcher'] += 1; // Add one more each subsequent win
			}
			console.log("Elite human reinforcements (Elite Guards, Archers) have arrived!");
		}
		// Introduce Guardian starting from the 9th battle (after winning the 8th)
		if (battleCounter >= 8) {
			// 8 wins means the next battle is the 9th
			if (!currentEnemyConfig.hasOwnProperty('humanGuardian')) {
				currentEnemyConfig['humanGuardian'] = 1; // Start with 1
			} else {
				currentEnemyConfig['humanGuardian'] += 1; // Add one more each win
			}
			console.log("Guardian reinforcements have arrived!");
		}
		// Introduce Bomber starting from the 13th battle (after winning the 12th)
		if (battleCounter >= 12) {
			if (!currentEnemyConfig.hasOwnProperty('Bomber')) {
				currentEnemyConfig['Bomber'] = 1;
			} else {
				currentEnemyConfig['Bomber'] += 1;
			}
			console.log("Bomber reinforcements have arrived!");
		}
		// Introduce King's Guard starting from the 15th battle (after winning the 14th)
		if (battleCounter >= 14) {
			if (!currentEnemyConfig.hasOwnProperty("King's guard")) {
				currentEnemyConfig["King's guard"] = 1;
			} else {
				currentEnemyConfig["King's guard"] += 1;
			}
			console.log("King's Guard reinforcements have arrived!");
		}
		// Introduce Crossbowman starting from the 16th battle (after winning the 15th)
		if (battleCounter >= 15) {
			if (!currentEnemyConfig.hasOwnProperty("Crossbowman")) {
				currentEnemyConfig["Crossbowman"] = 1;
			} else {
				currentEnemyConfig["Crossbowman"] += 1;
			}
			console.log("Crossbowman reinforcements have arrived!");
		}
		// Introduce Cannoneer starting from the 20th battle (after winning the 19th)
		if (battleCounter >= 19) {
			if (!currentEnemyConfig.hasOwnProperty('Cannoneer')) {
				currentEnemyConfig['Cannoneer'] = 1;
			} else {
				currentEnemyConfig['Cannoneer'] += 1;
			}
			console.log("Cannoneer reinforcements have arrived!");
		}
		// Introduce King's Shield starting from the 23rd battle (after winning the 22nd)
		if (battleCounter >= 22) {
			if (!currentEnemyConfig.hasOwnProperty("King's shield")) {
				currentEnemyConfig["King's shield"] = 1;
			} else {
				currentEnemyConfig["King's shield"] += 1;
			}
			console.log("King's Shield reinforcements have arrived!");
		}
		// Introduce Trebuchet starting from the 26th battle (after winning the 25th)
		if (battleCounter >= 25) {
			if (!currentEnemyConfig.hasOwnProperty('Trebuchet')) {
				currentEnemyConfig['Trebuchet'] = 1;
			} else {
				currentEnemyConfig['Trebuchet'] += 1;
			}
			console.log("Trebuchet reinforcements have arrived!");
		}
		console.log("Enemy forces have grown stronger for the next battle:", currentEnemyConfig);
		// Game continues, player can choose to recruit or battle again
	} else {
		console.log("Player lost the battle.");
		// Game over is handled by LK engine which resets the game state
		LK.showGameOver();
		// Note: Gold and roster will reset unless storage plugin is used.
	}
	// Update button states based on new gold amount AFTER battle outcome is decided
	// This is especially important if the player lost, as LK.showGameOver might reset things
	// before this line runs if not careful. updateGoldDisplay() called inside win condition is safer.
	// If player loses, the game resets anyway, so updating buttons might not be needed here.
	if (playerWon) {
		updateGoldDisplay(); // Ensure buttons reflect new gold total after winning
	}
}
// --- Initialize Game State ---
// Assign onClick handlers to buttons *after* they are created
startButton.onClick = startBattle; // Assign the function reference
recruitMilitiaButton.onClick = function () {
	var unitToRecruit = 'skeletonMilitia'; // Default
	if (eliteSwordsmanResearchComplete) {
		unitToRecruit = 'skeletonEliteswordsman';
	} else if (swordsmanResearchComplete) {
		unitToRecruit = 'skeletonSwordsman';
	} else if (militiaResearchComplete) {
		unitToRecruit = 'skeletonRookie';
	}
	recruitUnit(unitToRecruit);
};
recruitSlingerButton.onClick = function () {
	var unitToRecruit = 'skeletonSlinger'; // Default
	if (crossbowmanResearchComplete) {
		unitToRecruit = 'skeletonCrossbowman';
	} else if (archerResearchComplete) {
		unitToRecruit = 'skeletonArcher';
	} else if (slingerResearchComplete) {
		unitToRecruit = 'skeletonTraineeArcher';
	}
	recruitUnit(unitToRecruit);
};
recruitDefenderButton.onClick = function () {
	// Default to no unit (research required)
	var unitToRecruit = null;
	// Check research status to determine which defender unit to recruit
	if (darkKnightResearchComplete) {
		unitToRecruit = 'skeletonDarkKnight';
	} else if (hopliteResearchComplete) {
		unitToRecruit = 'skeletonHoplite';
	} else if (shieldedResearchComplete) {
		unitToRecruit = 'skeletonShielded';
	}
	// Only attempt to recruit if a valid unit type is available
	if (unitToRecruit) {
		recruitUnit(unitToRecruit);
	}
};
// Tier 1 Research Button Handlers
researchMilitiaButton.onClick = function () {
	researchUnit('militia');
};
researchSlingerButton.onClick = function () {
	researchUnit('slinger');
};
// Tier 2 Research Button Handlers
researchSwordsmanButton.onClick = function () {
	researchUnit('swordsman');
};
researchArcherButton.onClick = function () {
	researchUnit('archer');
};
// Defender Research Button Handlers
researchShieldedButton.onClick = function () {
	researchUnit('shielded');
};
researchHopliteButton.onClick = function () {
	researchUnit('hoplite');
};
// Tier 3 Research Button Handlers
researchEliteSwordsmanButton.onClick = function () {
	researchUnit('eliteswordsman');
};
researchCrossbowmanButton.onClick = function () {
	researchUnit('crossbowman');
};
researchDarkKnightButton.onClick = function () {
	researchUnit('darkknight');
};
// Artillery Research Button Handlers
researchBomberButton.onClick = function () {
	researchUnit('bomber');
};
researchCatapultButton.onClick = function () {
	researchUnit('catapult');
};
researchDragonButton.onClick = function () {
	researchUnit('dragon');
};
// Artillery Recruitment Button Handler
recruitArtilleryButton.onClick = function () {
	var unitToRecruit = null;
	if (dragonResearchComplete) {
		unitToRecruit = 'skeletonDragon';
	} else if (catapultResearchComplete) {
		unitToRecruit = 'skeletonPumpkinCatapult';
	} else if (bomberResearchComplete) {
		unitToRecruit = 'skeletonBomber';
	}
	// Only attempt to recruit if a valid unit type is available
	if (unitToRecruit) {
		recruitUnit(unitToRecruit);
	}
};
updateGoldDisplay(); // Set initial gold text and button states based on starting gold (10) and research state
// --- Game Update Loop ---
// This function is called by the LK engine automatically 60 times per second.
game.update = function () {
	if (!isBattling) {
		// Game is idle, waiting for player action (recruit/start battle)
		// No unit updates needed.
		return;
	}
	// --- Battle Logic ---
	// Update Player Units (Iterate backwards for safe removal)
	for (var i = playerUnits.length - 1; i >= 0; i--) {
		var pUnit = playerUnits[i];
		// Ensure unit exists and has methods before calling them
		if (!pUnit) {
			continue;
		}
		if (pUnit.isDead) {
			if (pUnit.destroy) {
				pUnit.destroy();
			} // Remove graphics from game
			playerUnits.splice(i, 1); // Remove from logical array
			continue; // Move to the next unit
		}
		// Pass the array of enemies for target finding
		if (pUnit.update) {
			pUnit.update(enemyUnits);
		}
	}
	// Update Enemy Units (Iterate backwards for safe removal)
	for (var i = enemyUnits.length - 1; i >= 0; i--) {
		var eUnit = enemyUnits[i];
		if (!eUnit) {
			continue;
		}
		if (eUnit.isDead) {
			if (eUnit.destroy) {
				eUnit.destroy();
			}
			enemyUnits.splice(i, 1);
			continue;
		}
		// Pass the array of player units for target finding
		if (eUnit.update) {
			eUnit.update(playerUnits);
		}
	}
	// --- Golden Piggy Logic ---
	// Chance to spawn a piggy if one isn't already active
	if (isBattling && goldenPiggyInstance === null) {
		// Low chance per tick, e.g., 1 in 1000 ticks on average
		var PIGGY_SPAWN_CHANCE = 1 / (60 * 10); // Roughly once every 10 seconds average
		if (Math.random() < PIGGY_SPAWN_CHANCE) {
			console.log("Spawning Golden Piggy!");
			goldenPiggyInstance = new GoldenPiggy();
			// Spawn position (e.g., random y in the middle vertical third, center horizontally)
			var spawnY = GAME_HEIGHT * 0.33 + Math.random() * (GAME_HEIGHT * 0.33);
			goldenPiggyInstance.x = GAME_WIDTH / 2;
			goldenPiggyInstance.y = spawnY;
			game.addChild(goldenPiggyInstance); // Add to display
		}
	}
	// Update active piggy and remove if collected/timed out
	if (goldenPiggyInstance !== null) {
		if (goldenPiggyInstance.isCollected) {
			goldenPiggyInstance.destroy();
			goldenPiggyInstance = null;
		} else {
			goldenPiggyInstance.update(); // Call piggy's own update logic
		}
	}
	// Check Win/Loss Conditions *after* all units have been updated for the tick
	// Only check if the battle is currently marked as active
	if (isBattling) {
		if (enemyUnits.length === 0 && playerUnits.length > 0) {
			// Player wins: All enemies are defeated, player still has units.
			endBattle(true);
		} else if (playerUnits.length === 0) {
			// Player loses: All player units are defeated. (Enemy count doesn't matter here)
			// We might get here even if enemies also died in the same tick.
			endBattle(false);
		}
	}
};
// --- Input Handling ---
// Button clicks are managed by the Button class instances via their `up` method.
// No global game-level mouse/touch handlers needed for this MVP's interaction model. /**** 
* Classes
****/ 
// Ensure ranged sound exists
// Simple Button Class
var Button = Container.expand(function (text, config) {
	var self = Container.call(this);
	// Methods must be defined before event handlers if called internally
	self.setText = function (newText) {
		self.label.setText(newText);
	};
	self.setEnabled = function (enabled) {
		self.interactive = enabled; // Control interactability
		// LK engine doesn't directly use obj.interactive for event routing like standard PIXI,
		// but good practice. Use alpha for visual cue.
		self.alpha = enabled ? 1.0 : 0.5;
	};
	// --- Initialize ---
	self.config = config || {};
	var width = self.config.width || 300;
	var height = self.config.height || 100;
	var bgColor = self.config.bgColor || 0x555555;
	var textColor = self.config.textColor || '#FFFFFF';
	var textSize = self.config.textSize || 40;
	var bg = self.attachAsset('buttonBg', {
		width: width,
		height: height,
		// color: bgColor, // Shape color is set at init time, cannot override here
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Tint the background shape if a color was provided in config
	bg.tint = bgColor;
	self.label = new Text2(text, {
		size: textSize,
		fill: textColor
	});
	self.label.anchor.set(0.5, 0.5);
	self.addChild(self.label);
	// Placeholder for the action, assign this after creating an instance
	self.onClick = null; // Must be assigned externally
	// LK engine automatically calls self.down if attached and interactive
	self.down = function (x, y, obj) {
		if (!self.interactive) {
			return;
		} // Respect the enabled state
		// Visual feedback for press
		self.scale.set(0.95);
	};
	// LK engine automatically calls self.up if attached and interactive
	self.up = function (x, y, obj) {
		if (!self.interactive) {
			return;
		} // Respect the enabled state
		self.scale.set(1.0); // Restore scale
		// Check bounds roughly (optional, prevents firing if dragged off significantly)
		if (x >= -width / 2 && x <= width / 2 && y >= -height / 2 && y <= height / 2) {
			if (self.onClick) {
				self.onClick(); // Execute the assigned action
			}
		}
	};
	// Initial state
	self.interactive = true; // Default to enabled
	return self;
});
// Class for the Golden Piggy
var GoldenPiggy = Container.expand(function () {
	var self = Container.call(this);
	// Constants
	var LIFETIME_TICKS = 5 * 60; // 5 seconds lifespan (at 60 FPS)
	// Properties
	self.ticksAlive = 0;
	self.isCollected = false;
	// --- Methods ---
	// Called when the piggy is tapped/clicked
	self.collect = function () {
		if (self.isCollected) {
			return;
		} // Prevent double collection
		self.isCollected = true;
		gold += 35; // Updated gold amount
		updateGoldDisplay();
		// Optional: Play a sound effect
		try {
			// Reuse recruit sound or add a dedicated 'coin' sound if available
			LK.getSound('recruit').play();
		} catch (e) {
			console.log("Sound error playing piggy collect sound: " + e);
		}
		// Remove the piggy visually (can be done in game.update)
		// self.visible = false; // Or self.destroy() handled by game.update
		console.log("Golden Piggy collected! +50 gold.");
	};
	// LK engine calls this automatically if attached
	self.up = function (x, y, obj) {
		// Check bounds roughly to ensure the tap was on the piggy
		// Assuming piggy is roughly 100x100 as per asset
		if (x >= -self.graphics.width / 2 && x <= self.graphics.width / 2 && y >= -self.graphics.height / 2 && y <= self.graphics.height / 2) {
			self.collect();
		}
	};
	// Called by game.update
	self.update = function () {
		if (self.isCollected) {
			return; // Stop updating if collected
		}
		self.ticksAlive++;
		if (self.ticksAlive > LIFETIME_TICKS) {
			// Mark for removal if lifetime expires
			self.isCollected = true; // Use the same flag to trigger removal
			console.log("Golden Piggy disappeared.");
		}
		// Optional: Add subtle movement like bobbing up and down
		self.graphics.y = Math.sin(self.ticksAlive / 20) * 10; // Bobbing effect
	};
	// --- Initialize ---
	self.graphics = self.attachAsset('Goldpiggy', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.interactive = true; // Make it tappable
	return self;
});
// var tween = LK.import('@upit/tween.v1'); // Not strictly needed for MVP
// Base class for all units
var Unit = Container.expand(function (config) {
	var self = Container.call(this);
	// Define methods first
	self.findTarget = function (enemyArray) {
		var closestTarget = null;
		var minDistance = Infinity;
		// Make sure enemyArray is defined and is an array
		if (!enemyArray || !Array.isArray(enemyArray)) {
			return null;
		}
		for (var i = 0; i < enemyArray.length; i++) {
			var enemy = enemyArray[i];
			if (enemy.isDead) {
				continue;
			}
			// Using horizontal distance for simplicity
			var distance = Math.abs(self.x - enemy.x);
			if (distance < minDistance) {
				minDistance = distance;
				closestTarget = enemy;
			}
		}
		if (closestTarget && minDistance <= self.attackRange) {
			return closestTarget; // Return target if it's within attack range
		} else {
			return null; // No target in range
		}
	};
	self.attack = function () {
		if (self.target && !self.target.isDead && self.attackCooldown <= 0) {
			try {
				// Defensive coding for sound playback
				LK.getSound(self.attackSoundId).play();
			} catch (e) {
				console.log("Sound error playing " + self.attackSoundId + ": " + e);
			}
			self.target.takeDamage(self.attackPower);
			self.attackCooldown = self.attackCooldownTime;
		}
	};
	self.move = function () {
		// Move towards the enemy side
		self.x += self.speed * (self.isEnemy ? -1 : 1);
		// Basic boundary check
		if (self.x < -100 || self.x > GAME_WIDTH + 100) {
			self.die(); // Remove if goes way off screen
		}
	};
	self.takeDamage = function (damage) {
		if (self.isDead) {
			return;
		} // Already dead
		self.hp -= damage;
		// Optional: Add a visual effect like tinting red briefly
		// LK.effects.flashObject(self, 0xFF0000, 100); // Flashing the container might work
		if (self.hp <= 0) {
			// Award gold if an enemy dies from player attack
			if (self.isEnemy) {
				// Award gold based on unit type/strength
				gold += 5; // Base gold reward
				updateGoldDisplay(); // Update the display immediately
			}
			self.die();
		}
	};
	self.die = function () {
		if (!self.isDead) {
			try {
				// Defensive coding for sound playback
				LK.getSound('unitDeath').play();
			} catch (e) {
				console.log("Sound error playing unitDeath: " + e);
			}
			self.isDead = true;
			// It will be removed from the game and array in game.update
		}
	};
	// LK calls this automatically if the instance is attached to the stage/game
	self.update = function (enemyArray) {
		// This method requires the global `isBattling` to be accessible.
		if (self.isDead || !isBattling) {
			return;
		} // Don't update if dead or battle not active
		// Update cooldown
		if (self.attackCooldown > 0) {
			self.attackCooldown--;
		}
		// Find target
		self.target = self.findTarget(enemyArray);
		// Act based on target
		if (self.target) {
			self.isMoving = false; // Stop moving when target is in range
			self.attack();
		} else {
			self.isMoving = true; // No target in range, resume moving
		}
		// Move if needed
		if (self.isMoving) {
			self.move();
		}
		self.lastX = self.x; // Update last known state
	};
	// --- Initialize ---
	self.isEnemy = config.isEnemy;
	self.hp = config.hp;
	self.maxHp = config.hp; // Store max HP
	self.attackPower = config.attackPower;
	self.attackRange = config.attackRange;
	self.attackCooldownTime = config.attackCooldownTime || 60; // Default 1 sec cooldown
	self.speed = config.speed;
	self.assetId = config.assetId;
	self.attackSoundId = config.attackSoundId || 'attackMelee';
	self.unitType = config.unitType; // Store the unit type identifier
	// Attach graphics *after* properties are set
	self.graphics = self.attachAsset(self.assetId, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// State variables
	self.target = null;
	self.attackCooldown = 0; // Start ready to attack
	self.isMoving = true;
	self.isDead = false;
	self.lastX = 0; // Initialize lastX, will be set correctly on spawn
	// Upgrade logic removed - replaced by global research system
});
// WebGL Shader initialization
var WebGLHelper = Container.expand(function () {
	var self = Container.call(this);
	// Method to initialize WebGL shaders
	self.initShaders = function (renderer) {
		if (!renderer || !renderer.gl) {
			return;
		}
		try {
			var createShader = function createShader(gl, source, type) {
				var shader = gl.createShader(type);
				gl.shaderSource(shader, source);
				gl.compileShader(shader);
				if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
					console.error('WebGL shader compilation failed: ' + gl.getShaderInfoLog(shader));
					gl.deleteShader(shader);
					return null;
				}
				return shader;
			};
			var gl = renderer.gl;
			// Vertex shader
			var vertexShaderSource = "\n\t\t\t\tattribute vec2 aVertexPosition;\n\t\t\t\tattribute vec2 aTextureCoord;\n\t\t\t\tuniform mat3 projectionMatrix;\n\t\t\t\tvarying vec2 vTextureCoord;\n\t\t\t\tvoid main(void) {\n\t\t\t\t\tgl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n\t\t\t\t\tvTextureCoord = aTextureCoord;\n\t\t\t\t}";
			// Fragment shader
			var fragmentShaderSource = "\n\t\t\t\tprecision mediump float;\n\t\t\t\tvarying vec2 vTextureCoord;\n\t\t\t\tuniform sampler2D uSampler;\n\t\t\t\tvoid main(void) {\n\t\t\t\t\tgl_FragColor = texture2D(uSampler, vTextureCoord);\n\t\t\t\t}";
			// Create shader program
			var vertexShader = createShader(gl, vertexShaderSource, gl.VERTEX_SHADER);
			var fragmentShader = createShader(gl, fragmentShaderSource, gl.FRAGMENT_SHADER);
			if (!vertexShader || !fragmentShader) {
				return;
			}
			// Create program
			var program = gl.createProgram();
			gl.attachShader(program, vertexShader);
			gl.attachShader(program, fragmentShader);
			gl.linkProgram(program);
			if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
				console.error('WebGL program linking failed: ' + gl.getProgramInfoLog(program));
				gl.deleteProgram(program);
				return;
			}
			return program;
		} catch (e) {
			console.error('WebGL shader initialization error:', e);
		}
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x101020 // Dark background for the war theme
});
/**** 
* Game Code
****/ 
// Button background
// Blue ellipse
// Green box
// Gray ellipse
// White box
// Define logical assets for units and UI.
// LK Engine automatically creates assets based on usage.
// Game constants and configuration
// Added assets for new human units
// Placeholder ID
// Placeholder ID
// Placeholder ID
// Ensure melee sound exists
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var PLAYER_SPAWN_X = 150;
var ENEMY_SPAWN_X = GAME_WIDTH - 150;
var SPAWN_Y_START = GAME_HEIGHT * 0.3; // Start spawning units lower down
var SPAWN_Y_END = GAME_HEIGHT * 0.8; // End spawning units lower down
var SPAWN_Y_STEP = 100; // Vertical distance between spawned units
// Research configuration
var MILITIA_RESEARCH_COST = 50;
var SLINGER_RESEARCH_COST = 75;
var SHIELDED_RESEARCH_COST = 60; // Cost to research Shielded Skeleton
var SWORDSMAN_RESEARCH_COST = 120; // Cost to research Swordsman
var ARCHER_RESEARCH_COST = 150; // Cost to research Archer
var HOPLITE_RESEARCH_COST = 180; // Cost to research Hoplite
var militiaResearchComplete = false; // Tier 1 Melee (Rookie)
var slingerResearchComplete = false; // Tier 1 Ranged (Trainee)
var swordsmanResearchComplete = false; // Tier 2 Melee
var archerResearchComplete = false; // Tier 2 Ranged
var shieldedResearchComplete = false; // Tier 1 Defender
var hopliteResearchComplete = false; // Tier 2 Defender
// Unit stats lookup table
var UNIT_STATS = {
	skeletonMilitia: {
		hp: 50,
		attackPower: 5,
		attackRange: 80,
		speed: 1.5,
		assetId: 'skeletonMilitia',
		cost: 10,
		// Cost to recruit base militia
		attackSoundId: 'attackMelee'
	},
	// Note: skeletonRookie stats are defined below, its cost is for recruitment *after* research.
	skeletonSlinger: {
		hp: 30,
		attackPower: 7,
		attackRange: 400,
		speed: 1.2,
		assetId: 'skeletonSlinger',
		cost: 15,
		// Cost to recruit base slinger
		attackCooldownTime: 90,
		attackSoundId: 'attackRanged'
	},
	// Note: skeletonTraineeArcher stats are defined below, its cost is for recruitment *after* research.
	humanFarmer: {
		hp: 40,
		attackPower: 4,
		attackRange: 70,
		speed: 1.3,
		assetId: 'humanFarmer',
		attackSoundId: 'attackMelee'
	},
	humanSlinger: {
		hp: 25,
		attackPower: 6,
		attackRange: 380,
		speed: 1.1,
		assetId: 'humanSlinger',
		attackCooldownTime: 90,
		attackSoundId: 'attackRanged'
	},
	// --- New Human Units ---
	humanGuard: {
		hp: 80,
		// Tougher than Farmer
		attackPower: 7,
		attackRange: 85,
		// Slightly longer reach than militia
		speed: 1.2,
		assetId: 'humanGuard',
		attackSoundId: 'attackMelee'
	},
	humanMilitiaArcher: {
		hp: 35,
		// Similar to Slinger
		attackPower: 8,
		// Slightly more damage than Slinger
		attackRange: 420,
		// Slightly longer range
		speed: 1.3,
		assetId: 'humanMilitiaArcher',
		attackCooldownTime: 80,
		// Slightly faster fire rate
		attackSoundId: 'attackRanged'
	},
	// --- New Elite Human Units ---
	humanEliteGuard: {
		hp: 120,
		// Much tougher than Guard
		attackPower: 12,
		// Significantly more damage than Guard
		attackRange: 90,
		// Slightly longer reach than Guard
		speed: 1.2,
		// Same speed as Guard
		assetId: 'humanEliteguard',
		attackSoundId: 'attackMelee'
	},
	humanArcher: {
		hp: 45,
		// Tougher than Militia Archer
		attackPower: 11,
		// More damage than Militia Archer
		attackRange: 450,
		// Better range than Militia Archer
		speed: 1.3,
		// Same speed as Militia Archer
		assetId: 'HumanArcher',
		attackCooldownTime: 70,
		// Faster fire rate than Militia Archer
		attackSoundId: 'attackRanged'
	},
	// --- New King's Guard (Melee Tier 3) ---
	"King's guard": {
		hp: 180,
		// Very tough
		attackPower: 15,
		// High damage
		attackRange: 100,
		// Good reach
		speed: 1.4,
		// Slightly faster than Elite Guard
		assetId: 'humanEliteguard',
		// Reusing asset, could be new if available
		attackSoundId: 'attackMelee'
	},
	// --- New Crossbowman (Ranged Tier 3) ---
	"Crossbowman": {
		hp: 60,
		// Fragile
		attackPower: 18,
		// Very high damage
		attackRange: 500,
		// Long range
		speed: 1.1,
		// Slower than Archer
		assetId: 'skeletonCrossbowman',
		// Reusing asset, could be new if available
		attackCooldownTime: 60,
		// Fast attack
		attackSoundId: 'attackRanged'
	},
	// --- New King's Shield (Defender Tier 3) ---
	"King's shield": {
		hp: 300,
		// Extremely tough
		attackPower: 8,
		// Moderate damage
		attackRange: 110,
		// Excellent reach
		speed: 1.3,
		// Average speed for defender
		assetId: 'humanGuardian',
		// Reusing asset, could be new if available
		attackSoundId: 'attackMelee'
	},
	// --- New Bomber (Artillery Tier 1) ---
	"Bomber": {
		hp: 20,
		// Very fragile
		attackPower: 20,
		// High AoE damage (conceptually)
		attackRange: 700,
		// Very long range
		speed: 0.6,
		// Very slow
		assetId: 'skeletonBomber',
		// Reusing asset, could be new if available
		attackCooldownTime: 180,
		// Very slow attack rate
		attackSoundId: 'attackRanged' // Placeholder, ideally an explosion sound
	},
	// --- New Cannoneer (Artillery Tier 2) ---
	"Cannoneer": {
		hp: 35,
		// Fragile
		attackPower: 30,
		// Very high AoE damage
		attackRange: 800,
		// Extremely long range
		speed: 0.5,
		// Even slower
		assetId: 'skeletonPumpkinCatapult',
		// Reusing asset, could be new if available
		attackCooldownTime: 240,
		// Very slow attack rate
		attackSoundId: 'attackRanged' // Placeholder
	},
	// --- New Trebuchet (Artillery Tier 3) ---
	"Trebuchet": {
		hp: 50,
		// Still fragile
		attackPower: 50,
		// Massive AoE damage
		attackRange: 900,
		// Supreme range
		speed: 0.4,
		// Extremely slow
		assetId: 'skeletonDragon',
		// Reusing asset, could be new if available
		attackCooldownTime: 300,
		// Extremely slow attack rate
		attackSoundId: 'attackRanged' // Placeholder
	},
	// -- Special Human Units --
	humanLocalprotector: {
		hp: 150,
		// Very tough defender unit
		attackPower: 6,
		// Moderate damage
		attackRange: 90,
		// Melee range
		speed: 1.5,
		// Same speed as melee units
		assetId: 'humanLocalprotector',
		attackSoundId: 'attackMelee'
	},
	humanGuardian: {
		hp: 220,
		// Extremely tough defender unit
		attackPower: 10,
		// Good damage for a defender
		attackRange: 100,
		// Slightly better melee range
		speed: 1.5,
		// Same speed as melee units
		assetId: 'humanGuardian',
		attackSoundId: 'attackMelee'
	},
	// --- Researched Player Units ---
	skeletonRookie: {
		hp: 70,
		attackPower: 8,
		attackRange: 90,
		speed: 1.5,
		// Match militia speed to prevent getting faster when upgraded
		assetId: 'skeletonRookie',
		// Use the dedicated rookie asset
		cost: 20,
		attackSoundId: 'attackMelee'
	},
	// Reusing militia asset for now
	skeletonTraineeArcher: {
		hp: 40,
		attackPower: 10,
		attackRange: 450,
		speed: 1.2,
		// Match slinger speed to prevent getting faster when upgraded
		assetId: 'skeletonTraineearcher',
		// Use the dedicated trainee archer asset
		cost: 25,
		attackCooldownTime: 70,
		attackSoundId: 'attackRanged'
	},
	// --- Tier 2 Researched Player Units ---
	skeletonSwordsman: {
		hp: 100,
		// Stronger than Rookie
		attackPower: 12,
		// Higher damage
		attackRange: 100,
		// Slightly better reach
		speed: 1.5,
		// Match militia/rookie speed to prevent getting faster when upgraded
		assetId: 'skeletonSwordsman',
		cost: 35,
		// Cost after research
		attackSoundId: 'attackMelee'
	},
	skeletonArcher: {
		hp: 55,
		// More durable than Trainee
		attackPower: 14,
		// Significantly more damage
		attackRange: 500,
		// Longer range
		speed: 1.2,
		// Match slinger/trainee speed to prevent getting faster when upgraded
		assetId: 'skeletonArcher',
		cost: 40,
		// Cost after research
		attackCooldownTime: 60,
		// Faster attack speed
		attackSoundId: 'attackRanged'
	},
	// --- Tier 1 & 2 Defender Player Units ---
	skeletonShielded: {
		// Tier 1 Defender
		hp: 120,
		// High health
		attackPower: 4,
		// Low damage
		attackRange: 80,
		// Melee range
		speed: 1.5,
		// Match militia/rookie speed
		assetId: 'skeletonShielded',
		cost: 25,
		// Cost after research
		attackSoundId: 'attackMelee'
	},
	skeletonHoplite: {
		// Tier 2 Defender
		hp: 180,
		// Very high health
		attackPower: 7,
		// Slightly better damage
		attackRange: 90,
		// Melee range
		speed: 1.5,
		// Match militia/rookie/swordsman speed
		assetId: 'skeletonHolpite',
		cost: 45,
		// Cost after research
		attackSoundId: 'attackMelee'
	},
	// --- Tier 3 Researched Player Units ---
	skeletonEliteswordsman: {
		hp: 150,
		// Stronger than Swordsman
		attackPower: 18,
		// Significantly higher damage
		attackRange: 110,
		// Slightly better reach
		speed: 1.5,
		// Match previous melee speed
		assetId: 'skeletonEliteswordsman',
		cost: 60,
		// Cost after research
		attackSoundId: 'attackMelee'
	},
	skeletonCrossbowman: {
		hp: 75,
		// More durable than Archer
		attackPower: 20,
		// High damage
		attackRange: 550,
		// Longest range
		speed: 1.2,
		// Match previous ranged speed
		assetId: 'skeletonCrossbowman',
		cost: 70,
		// Cost after research
		attackCooldownTime: 50,
		// Even faster attack speed
		attackSoundId: 'attackRanged'
	},
	skeletonDarkKnight: {
		hp: 250,
		// Extremely high health
		attackPower: 12,
		// Better damage than Hoplite
		attackRange: 100,
		// Melee range
		speed: 1.5,
		// Match previous melee speed
		assetId: 'skeletonDarkKnight',
		cost: 80,
		// Cost after research
		attackSoundId: 'attackMelee'
	},
	// --- Tier 1-3 Artillery Player Units ---
	skeletonBomber: {
		// Tier 1 Artillery
		hp: 20,
		// Very fragile
		attackPower: 15,
		// High damage
		attackRange: 600,
		// Long range
		speed: 0.8,
		// Very slow
		assetId: 'skeletonBomber',
		cost: 30,
		// Cost after research
		attackCooldownTime: 120,
		// Slow attack speed
		attackSoundId: 'attackRanged' // Placeholder, maybe a 'boom' sound later
	},
	skeletonPumpkinCatapult: {
		// Tier 2 Artillery
		hp: 40,
		// Still fragile
		attackPower: 25,
		// Very high damage
		attackRange: 700,
		// Longer range
		speed: 0.7,
		// Even slower
		assetId: 'skeletonPumpkinCatapult',
		cost: 55,
		// Cost after research
		attackCooldownTime: 150,
		// Slower attack speed
		attackSoundId: 'attackRanged' // Placeholder
	},
	skeletonDragon: {
		// Tier 3 Artillery
		hp: 80,
		// Moderately durable for artillery
		attackPower: 40,
		// Extremely high damage
		attackRange: 800,
		// Very long range
		speed: 1.0,
		// Slightly faster than others
		assetId: 'skeletonDragon',
		cost: 100,
		// Cost after research
		attackCooldownTime: 180,
		// Very slow attack speed
		attackSoundId: 'attackRanged' // Placeholder
	}
};
// Research configuration
var SHIELDED_RESEARCH_COST = 60;
var HOPLITE_RESEARCH_COST = 180;
// Research state
var shieldedResearchComplete = false; // Tier 1 Defender
var hopliteResearchComplete = false; // Tier 2 Defender
// Tier 3 Research Costs
var ELITESWORDSMAN_RESEARCH_COST = 250;
var CROSSBOWMAN_RESEARCH_COST = 300;
var DARKKNIGHT_RESEARCH_COST = 350;
// Tier 3 Research State
var eliteSwordsmanResearchComplete = false;
var crossbowmanResearchComplete = false;
var darkKnightResearchComplete = false;
// Artillery Research Costs
var BOMBER_RESEARCH_COST = 80;
var CATAPULT_RESEARCH_COST = 200;
var DRAGON_RESEARCH_COST = 400;
// Artillery Research State
var bomberResearchComplete = false;
var catapultResearchComplete = false;
var dragonResearchComplete = false;
// Game state variables - Defined globally for access within functions and update loop
var gold = 10;
var playerUnits = [];
var enemyUnits = [];
var isBattling = false;
var battleCounter = 0; // Tracks the number of battles won
var currentEnemyConfig = {}; // Store the config for the current battle
var goldenPiggyInstance = null; // Holds the active Golden Piggy instance
// Initial player army composition (can be modified by recruitment)
// Using an object for easier modification by type
var playerArmyRoster = {
	skeletonMilitia: 2,
	skeletonSlinger: 1
};
// --- UI Elements ---
// Gold Display
var goldTxt = new Text2('Gold: 0', {
	size: 60,
	fill: 0xFFD700
});
goldTxt.anchor.set(1.0, 0); // Anchor top-right
goldTxt.x = -50; // Offset from the right edge
goldTxt.y = 20; // Offset from the top edge
// Avoid top-left (reserved for LK menu), top-right is fine.
LK.gui.topRight.addChild(goldTxt);
// Village Counter Display
var villageTxt = new Text2('Village: 1', {
	size: 60,
	fill: 0xFFD700
});
villageTxt.anchor.set(0.0, 0); // Anchor top-left
villageTxt.x = 50; // Offset from the left edge
villageTxt.y = 20; // Offset from the top edge
LK.gui.topLeft.addChild(villageTxt);
// Buttons Container (for organizing buttons at the bottom)
var buttonContainer = new Container();
buttonContainer.x = GAME_WIDTH / 2;
buttonContainer.y = GAME_HEIGHT - 200; // Position buttons lower
game.addChild(buttonContainer); // Add to the main game scene
// Start Battle Button
var startButton = new Button('Start Battle', {
	width: 400,
	height: 120,
	textSize: 50,
	bgColor: 0x008000
}); // Greenish button
startButton.y = -80; // Position above the recruitment buttons
buttonContainer.addChild(startButton);
// Recruitment Buttons (Example: Militia)
var recruitMilitiaButton = new Button('Recruit Militia (10g)', {
	width: 400,
	height: 100,
	textSize: 40,
	bgColor: 0x404040
});
recruitMilitiaButton.x = -330; // Position further left for three buttons
recruitMilitiaButton.y = 80; // Position below start button
buttonContainer.addChild(recruitMilitiaButton);
// Example: Slinger recruitment button
var recruitSlingerButton = new Button('Recruit Slinger (15g)', {
	width: 400,
	height: 100,
	textSize: 40,
	bgColor: 0x404040
});
recruitSlingerButton.x = 330; // Position further right for three buttons
recruitSlingerButton.y = 80; // Position below start button
buttonContainer.addChild(recruitSlingerButton);
// Defender recruitment button
var recruitDefenderButton = new Button('Recruit Defender (25g)', {
	width: 400,
	height: 100,
	textSize: 40,
	bgColor: 0x404040
});
recruitDefenderButton.x = 0; // Center position
recruitDefenderButton.y = 80; // Same row as other recruitment buttons
buttonContainer.addChild(recruitDefenderButton);
// Research Buttons
var researchMilitiaButton = new Button('Research Rookie (50g)', {
	width: 400,
	height: 100,
	textSize: 40,
	bgColor: 0x004080 // Blueish button
});
researchMilitiaButton.x = -220; // Position left, above recruitment
researchMilitiaButton.y = -220; // Position above recruitment buttons
buttonContainer.addChild(researchMilitiaButton);
var researchSlingerButton = new Button('Research Trainee (75g)', {
	width: 400,
	height: 100,
	textSize: 40,
	bgColor: 0x004080 // Blueish button
});
researchSlingerButton.x = 220; // Position right, above recruitment
researchSlingerButton.y = -220; // Position above recruitment buttons
buttonContainer.addChild(researchSlingerButton);
// Tier 2 Research Buttons (Initially hidden)
var researchSwordsmanButton = new Button('Research Swordsman (' + SWORDSMAN_RESEARCH_COST + 'g)', {
	width: 400,
	height: 100,
	textSize: 35,
	// Slightly smaller text if needed
	bgColor: 0x800080 // Purpleish button
});
researchSwordsmanButton.x = -220;
researchSwordsmanButton.y = -350; // Position above Tier 1 research
researchSwordsmanButton.visible = false; // Hidden until prerequisite met
buttonContainer.addChild(researchSwordsmanButton);
var researchArcherButton = new Button('Research Archer (' + ARCHER_RESEARCH_COST + 'g)', {
	width: 400,
	height: 100,
	textSize: 35,
	// Slightly smaller text if needed
	bgColor: 0x800080 // Purpleish button
});
researchArcherButton.x = 220;
researchArcherButton.y = -350; // Position above Tier 1 research
researchArcherButton.visible = false; // Hidden until prerequisite met
buttonContainer.addChild(researchArcherButton);
buttonContainer.addChild(researchArcherButton);
// Defender Research Buttons
var researchShieldedButton = new Button('Research Shielded (' + SHIELDED_RESEARCH_COST + 'g)', {
	width: 400,
	height: 100,
	textSize: 35,
	bgColor: 0x6A5ACD // SlateBlue button
});
researchShieldedButton.x = 0; // Position center, above Tier 1 Melee/Ranged
researchShieldedButton.y = -220; // Same level as Tier 1 Melee/Ranged research
buttonContainer.addChild(researchShieldedButton);
var researchHopliteButton = new Button('Research Hoplite (' + HOPLITE_RESEARCH_COST + 'g)', {
	width: 400,
	height: 100,
	textSize: 35,
	bgColor: 0x483D8B // DarkSlateBlue button
});
researchHopliteButton.x = 0; // Position center, above Tier 2 Melee/Ranged
researchHopliteButton.y = -350; // Same level as Tier 2 Melee/Ranged research
researchHopliteButton.visible = false; // Hidden until prerequisite met
buttonContainer.addChild(researchHopliteButton);
// Adjust positions to accommodate the third column (Defender research)
// Tier 1 Research
researchMilitiaButton.x = -440; // Move left
researchMilitiaButton.y = -220;
researchSlingerButton.x = 440; // Move right
researchSlingerButton.y = -220;
researchShieldedButton.x = 0; // Center
researchShieldedButton.y = -220;
// Tier 2 Research
researchSwordsmanButton.x = -440; // Move left
researchSwordsmanButton.y = -350;
researchArcherButton.x = 440; // Move right
researchArcherButton.y = -350;
researchHopliteButton.x = 0; // Center
researchHopliteButton.y = -350;
// Adjust Start Button position further up
startButton.y = -480; // Move start button further up
// Tier 3 Research Buttons (Initially hidden)
var researchEliteSwordsmanButton = new Button('Research Elite (' + ELITESWORDSMAN_RESEARCH_COST + 'g)', {
	width: 400,
	height: 100,
	textSize: 35,
	bgColor: 0xFF4500 // Orangish-Red button
});
researchEliteSwordsmanButton.x = -440; // Position left, above Tier 2
researchEliteSwordsmanButton.y = -480; // Position above Tier 2 research
researchEliteSwordsmanButton.visible = false; // Hidden until prerequisite met
buttonContainer.addChild(researchEliteSwordsmanButton);
var researchCrossbowmanButton = new Button('Research Crossbow (' + CROSSBOWMAN_RESEARCH_COST + 'g)', {
	width: 400,
	height: 100,
	textSize: 35,
	bgColor: 0xFF4500 // Orangish-Red button
});
researchCrossbowmanButton.x = 440; // Position right, above Tier 2
researchCrossbowmanButton.y = -480; // Position above Tier 2 research
researchCrossbowmanButton.visible = false; // Hidden until prerequisite met
buttonContainer.addChild(researchCrossbowmanButton);
var researchDarkKnightButton = new Button('Research D.Knight (' + DARKKNIGHT_RESEARCH_COST + 'g)', {
	width: 400,
	height: 100,
	textSize: 35,
	bgColor: 0x8B0000 // DarkRed button
});
researchDarkKnightButton.x = 0; // Position center, above Tier 2
researchDarkKnightButton.y = -480; // Position above Tier 2 research
researchDarkKnightButton.visible = false; // Hidden until prerequisite met
buttonContainer.addChild(researchDarkKnightButton);
// Adjust Start Button position even further up to accommodate Tier 3 research
startButton.y = -610; // Move start button further up
// --- Artillery Research Buttons ---
var researchBomberButton = new Button('Research Bomber (' + BOMBER_RESEARCH_COST + 'g)', {
	width: 380,
	// Slightly narrower for 4 columns
	height: 100,
	textSize: 35,
	bgColor: 0x8A2BE2 // BlueViolet
});
researchBomberButton.x = 220; // Position between Defender and Ranged (Right side)
researchBomberButton.y = -220; // Tier 1 row
researchBomberButton.visible = true; // Initially visible
buttonContainer.addChild(researchBomberButton);
var researchCatapultButton = new Button('Research Catapult (' + CATAPULT_RESEARCH_COST + 'g)', {
	width: 380,
	height: 100,
	textSize: 35,
	bgColor: 0x9932CC // DarkOrchid
});
researchCatapultButton.x = 220; // Position between Defender and Ranged (Right side)
researchCatapultButton.y = -350; // Tier 2 row
researchCatapultButton.visible = false; // Hidden until prerequisite met
buttonContainer.addChild(researchCatapultButton);
var researchDragonButton = new Button('Research Dragon (' + DRAGON_RESEARCH_COST + 'g)', {
	width: 380,
	height: 100,
	textSize: 35,
	bgColor: 0xBA55D3 // MediumOrchid
});
researchDragonButton.x = 220; // Position between Defender and Ranged (Right side)
researchDragonButton.y = -480; // Tier 3 row
researchDragonButton.visible = false; // Hidden until prerequisite met
buttonContainer.addChild(researchDragonButton);
// --- Adjust existing button positions for 4 columns ---
var buttonXOffsetLarge = 660; // For outer buttons (Melee, Ranged)
var buttonXOffsetSmall = 220; // For inner buttons (Defender, Artillery)
// Research Buttons
researchMilitiaButton.x = -buttonXOffsetLarge; // Far Left
researchMilitiaButton.width = 380;
researchShieldedButton.x = -buttonXOffsetSmall; // Mid Left // Fix: Used correct variable name
researchShieldedButton.width = 380; // Fix: Used correct variable name
researchBomberButton.x = buttonXOffsetSmall; // Mid Right (new)
researchBomberButton.width = 380;
researchSlingerButton.x = buttonXOffsetLarge; // Far Right
researchSlingerButton.width = 380;
researchSwordsmanButton.x = -buttonXOffsetLarge; // Far Left
researchSwordsmanButton.width = 380;
researchHopliteButton.x = -buttonXOffsetSmall; // Mid Left
researchHopliteButton.width = 380;
researchCatapultButton.x = buttonXOffsetSmall; // Mid Right (new)
researchCatapultButton.width = 380;
researchArcherButton.x = buttonXOffsetLarge; // Far Right
researchArcherButton.width = 380;
researchEliteSwordsmanButton.x = -buttonXOffsetLarge; // Far Left
researchEliteSwordsmanButton.width = 380;
researchDarkKnightButton.x = -buttonXOffsetSmall; // Mid Left
researchDarkKnightButton.width = 380;
researchDragonButton.x = buttonXOffsetSmall; // Mid Right (new)
researchDragonButton.width = 380;
researchCrossbowmanButton.x = buttonXOffsetLarge; // Far Right
researchCrossbowmanButton.width = 380;
// Recruitment Buttons
recruitMilitiaButton.x = -buttonXOffsetLarge; // Far Left
recruitMilitiaButton.width = 380;
recruitDefenderButton.x = -buttonXOffsetSmall; // Mid Left
recruitDefenderButton.width = 380;
// recruitArtilleryButton needs to be created first, then positioned
recruitSlingerButton.x = buttonXOffsetLarge; // Far Right
recruitSlingerButton.width = 380;
// Adjust Start Button position further up
startButton.y = -610; // Keep this adjustment
// --- Add Artillery Recruitment Button ---
var recruitArtilleryButton = new Button('Research Required', {
	// Initial text
	width: 380,
	// Match other buttons
	height: 100,
	textSize: 35,
	// Match research buttons
	bgColor: 0x404040
});
recruitArtilleryButton.x = buttonXOffsetSmall; // Position Mid Right
recruitArtilleryButton.y = 80; // Same row as other recruitment buttons
recruitArtilleryButton.setEnabled(false); // Initially disabled
buttonContainer.addChild(recruitArtilleryButton);
// --- Game Logic Functions ---
function updateGoldDisplay() {
	goldTxt.setText('Gold: ' + gold);
	var canAffordMilitiaResearch = gold >= MILITIA_RESEARCH_COST;
	var canAffordSlingerResearch = gold >= SLINGER_RESEARCH_COST;
	var canAffordShieldedResearch = gold >= SHIELDED_RESEARCH_COST; // New Defender cost check
	var canAffordSwordsmanResearch = gold >= SWORDSMAN_RESEARCH_COST;
	var canAffordArcherResearch = gold >= ARCHER_RESEARCH_COST;
	var canAffordHopliteResearch = gold >= HOPLITE_RESEARCH_COST;
	var canAffordEliteSwordsmanResearch = gold >= ELITESWORDSMAN_RESEARCH_COST;
	var canAffordCrossbowmanResearch = gold >= CROSSBOWMAN_RESEARCH_COST;
	var canAffordDarkKnightResearch = gold >= DARKKNIGHT_RESEARCH_COST;
	// Artillery research cost checks
	var canAffordBomberResearch = gold >= BOMBER_RESEARCH_COST;
	var canAffordCatapultResearch = gold >= CATAPULT_RESEARCH_COST;
	var canAffordDragonResearch = gold >= DRAGON_RESEARCH_COST;
	// --- Update Research Buttons ---
	// Tier 1: Militia -> Rookie
	if (militiaResearchComplete) {
		researchMilitiaButton.visible = false; // Hide Tier 1 when complete
		researchMilitiaButton.setEnabled(false);
	} else {
		researchMilitiaButton.visible = true;
		researchMilitiaButton.setEnabled(canAffordMilitiaResearch && !isBattling);
	}
	// Tier 1: Slinger -> Trainee
	if (slingerResearchComplete) {
		researchSlingerButton.visible = false; // Hide Tier 1 when complete
		researchSlingerButton.setEnabled(false);
	} else {
		researchSlingerButton.visible = true;
		researchSlingerButton.setEnabled(canAffordSlingerResearch && !isBattling);
	}
	// Tier 1: Defender -> Shielded Skeleton
	if (shieldedResearchComplete) {
		researchShieldedButton.visible = false;
		researchShieldedButton.setEnabled(false);
	} else {
		researchShieldedButton.visible = true;
		researchShieldedButton.setEnabled(canAffordShieldedResearch && !isBattling);
	}
	// Tier 2: Rookie -> Swordsman
	if (swordsmanResearchComplete) {
		researchSwordsmanButton.visible = false; // Hide Tier 2 when complete
		researchSwordsmanButton.setEnabled(false);
	} else {
		// Show Tier 2 only if Tier 1 is complete
		researchSwordsmanButton.visible = militiaResearchComplete;
		researchSwordsmanButton.setEnabled(militiaResearchComplete && canAffordSwordsmanResearch && !isBattling);
	}
	// Tier 2: Trainee -> Archer
	if (archerResearchComplete) {
		researchArcherButton.visible = false; // Hide Tier 2 when complete
		researchArcherButton.setEnabled(false);
	} else {
		// Show Tier 2 only if Tier 1 is complete
		researchArcherButton.visible = slingerResearchComplete;
		researchArcherButton.setEnabled(slingerResearchComplete && canAffordArcherResearch && !isBattling);
	}
	// Tier 2: Shielded -> Hoplite
	if (hopliteResearchComplete) {
		researchHopliteButton.visible = false;
		researchHopliteButton.setEnabled(false);
	} else {
		// Show Tier 2 only if Tier 1 is complete
		researchHopliteButton.visible = shieldedResearchComplete;
		researchHopliteButton.setEnabled(shieldedResearchComplete && canAffordHopliteResearch && !isBattling);
	}
	// Tier 3: Swordsman -> Elite Swordsman
	if (eliteSwordsmanResearchComplete) {
		researchEliteSwordsmanButton.visible = false;
		researchEliteSwordsmanButton.setEnabled(false);
	} else {
		// Show Tier 3 only if Tier 2 is complete
		researchEliteSwordsmanButton.visible = swordsmanResearchComplete;
		researchEliteSwordsmanButton.setEnabled(swordsmanResearchComplete && canAffordEliteSwordsmanResearch && !isBattling);
	}
	// Tier 3: Archer -> Crossbowman
	if (crossbowmanResearchComplete) {
		researchCrossbowmanButton.visible = false;
		researchCrossbowmanButton.setEnabled(false);
	} else {
		// Show Tier 3 only if Tier 2 is complete
		researchCrossbowmanButton.visible = archerResearchComplete;
		researchCrossbowmanButton.setEnabled(archerResearchComplete && canAffordCrossbowmanResearch && !isBattling);
	}
	// Tier 3: Hoplite -> Dark Knight
	if (darkKnightResearchComplete) {
		researchDarkKnightButton.visible = false;
		researchDarkKnightButton.setEnabled(false);
	} else {
		// Show Tier 3 only if Tier 2 is complete
		researchDarkKnightButton.visible = hopliteResearchComplete;
		researchDarkKnightButton.setEnabled(hopliteResearchComplete && canAffordDarkKnightResearch && !isBattling);
	}
	// Tier 1: Artillery -> Bomber
	if (bomberResearchComplete) {
		researchBomberButton.visible = false;
		researchBomberButton.setEnabled(false);
	} else {
		researchBomberButton.visible = true;
		researchBomberButton.setEnabled(canAffordBomberResearch && !isBattling);
	}
	// Tier 2: Bomber -> Catapult
	if (catapultResearchComplete) {
		researchCatapultButton.visible = false;
		researchCatapultButton.setEnabled(false);
	} else {
		// Show Tier 2 only if Tier 1 is complete
		researchCatapultButton.visible = bomberResearchComplete;
		researchCatapultButton.setEnabled(bomberResearchComplete && canAffordCatapultResearch && !isBattling);
	}
	// Tier 3: Catapult -> Dragon
	if (dragonResearchComplete) {
		researchDragonButton.visible = false;
		researchDragonButton.setEnabled(false);
	} else {
		// Show Tier 3 only if Tier 2 is complete
		researchDragonButton.visible = catapultResearchComplete;
		researchDragonButton.setEnabled(catapultResearchComplete && canAffordDragonResearch && !isBattling);
	}
	// --- Update Recruitment Buttons ---
	// Determine current highest researched MELEE unit
	var currentMilitiaType = 'skeletonMilitia';
	var militiaButtonText = 'Recruit Militia';
	if (eliteSwordsmanResearchComplete) {
		currentMilitiaType = 'skeletonEliteswordsman';
		militiaButtonText = 'Recruit Elite';
	} else if (swordsmanResearchComplete) {
		currentMilitiaType = 'skeletonSwordsman';
		militiaButtonText = 'Recruit Swordsman';
	} else if (militiaResearchComplete) {
		currentMilitiaType = 'skeletonRookie';
		militiaButtonText = 'Recruit Rookie';
	}
	var currentMilitiaStats = UNIT_STATS[currentMilitiaType];
	recruitMilitiaButton.setText(militiaButtonText + ' (' + currentMilitiaStats.cost + 'g)');
	recruitMilitiaButton.setEnabled(gold >= currentMilitiaStats.cost && !isBattling);
	// Determine current highest researched RANGED unit
	var currentSlingerType = 'skeletonSlinger';
	var slingerButtonText = 'Recruit Slinger';
	if (crossbowmanResearchComplete) {
		currentSlingerType = 'skeletonCrossbowman';
		slingerButtonText = 'Recruit Crossbow';
	} else if (archerResearchComplete) {
		currentSlingerType = 'skeletonArcher';
		slingerButtonText = 'Recruit Archer';
	} else if (slingerResearchComplete) {
		currentSlingerType = 'skeletonTraineeArcher';
		slingerButtonText = 'Recruit Trainee';
	}
	var currentSlingerStats = UNIT_STATS[currentSlingerType];
	recruitSlingerButton.setText(slingerButtonText + ' (' + currentSlingerStats.cost + 'g)');
	recruitSlingerButton.setEnabled(gold >= currentSlingerStats.cost && !isBattling);
	// Determine current highest researched DEFENDER unit
	var currentDefenderType = null;
	var defenderButtonText = 'Research Required';
	if (darkKnightResearchComplete) {
		currentDefenderType = 'skeletonDarkKnight';
		defenderButtonText = 'Recruit D.Knight';
	} else if (hopliteResearchComplete) {
		currentDefenderType = 'skeletonHoplite';
		defenderButtonText = 'Recruit Hoplite';
	} else if (shieldedResearchComplete) {
		currentDefenderType = 'skeletonShielded';
		defenderButtonText = 'Recruit Shielded';
	}
	// Update defender button state based on research status
	if (currentDefenderType) {
		var currentDefenderStats = UNIT_STATS[currentDefenderType];
		recruitDefenderButton.setText(defenderButtonText + ' (' + currentDefenderStats.cost + 'g)');
		recruitDefenderButton.setEnabled(gold >= currentDefenderStats.cost && !isBattling);
	} else {
		// No defender research completed yet
		recruitDefenderButton.setText('Research Required');
		recruitDefenderButton.setEnabled(false);
	}
	// Determine current highest researched ARTILLERY unit
	var currentArtilleryType = null;
	var artilleryButtonText = 'Research Required';
	if (dragonResearchComplete) {
		currentArtilleryType = 'skeletonDragon';
		artilleryButtonText = 'Recruit Dragon';
	} else if (catapultResearchComplete) {
		currentArtilleryType = 'skeletonPumpkinCatapult';
		artilleryButtonText = 'Recruit Catapult';
	} else if (bomberResearchComplete) {
		currentArtilleryType = 'skeletonBomber';
		artilleryButtonText = 'Recruit Bomber';
	}
	// Update artillery button state based on research status
	if (currentArtilleryType) {
		var currentArtilleryStats = UNIT_STATS[currentArtilleryType];
		recruitArtilleryButton.setText(artilleryButtonText + ' (' + currentArtilleryStats.cost + 'g)');
		recruitArtilleryButton.setEnabled(gold >= currentArtilleryStats.cost && !isBattling);
	} else {
		// No artillery research completed yet
		recruitArtilleryButton.setText('Research Required');
		recruitArtilleryButton.setEnabled(false); // Ensure it's disabled
	}
}
function recruitUnit(unitType) {
	if (isBattling) {
		return;
	} // Cannot recruit during battle
	var stats = UNIT_STATS[unitType];
	if (!stats) {
		console.error("Attempted to recruit unknown unit type:", unitType);
		return;
	}
	if (gold >= stats.cost) {
		gold -= stats.cost;
		try {
			// Defensive coding for sound playback
			LK.getSound('recruit').play();
		} catch (e) {
			console.log("Sound error playing recruit: " + e);
		}
		// Safely increment the count in the roster
		playerArmyRoster[unitType] = (playerArmyRoster[unitType] || 0) + 1;
		console.log("Recruited " + unitType + ". Roster:", playerArmyRoster);
		updateGoldDisplay(); // Update UI after recruitment
	} else {
		console.log("Not enough gold to recruit " + unitType);
		// Optional: Show feedback to the player (e.g., flashing the gold red)
		LK.effects.flashObject(goldTxt, 0xFF0000, 300);
	}
}
function researchUnit(researchType) {
	if (isBattling) {
		return;
	} // Cannot research during battle
	var cost = 0;
	var cost = 0;
	var researchName = '';
	var canResearch = false;
	var setResearchFlag = null; // Function to set the correct flag
	if (researchType === 'militia' && !militiaResearchComplete) {
		cost = MILITIA_RESEARCH_COST;
		researchName = 'Rookie';
		canResearch = true; // No prerequisite
		setResearchFlag = function setResearchFlag() {
			militiaResearchComplete = true;
		};
	} else if (researchType === 'slinger' && !slingerResearchComplete) {
		cost = SLINGER_RESEARCH_COST;
		researchName = 'Trainee Archer';
		canResearch = true; // No prerequisite
		setResearchFlag = function setResearchFlag() {
			slingerResearchComplete = true;
		};
	} else if (researchType === 'swordsman' && !swordsmanResearchComplete) {
		cost = SWORDSMAN_RESEARCH_COST;
		researchName = 'Swordsman';
		canResearch = militiaResearchComplete; // Prerequisite: Rookie researched
		setResearchFlag = function setResearchFlag() {
			swordsmanResearchComplete = true;
		};
		if (!canResearch) {
			console.log("Prerequisite not met: Research Rookie first.");
		}
	} else if (researchType === 'archer' && !archerResearchComplete) {
		cost = ARCHER_RESEARCH_COST;
		researchName = 'Archer';
		canResearch = slingerResearchComplete; // Prerequisite: Trainee researched
		setResearchFlag = function setResearchFlag() {
			archerResearchComplete = true;
		};
		if (!canResearch) {
			console.log("Prerequisite not met: Research Trainee Archer first.");
		}
	} else if (researchType === 'shielded' && !shieldedResearchComplete) {
		// New Defender Tier 1
		cost = SHIELDED_RESEARCH_COST;
		researchName = 'Shielded Skeleton';
		canResearch = true; // No prerequisite
		setResearchFlag = function setResearchFlag() {
			shieldedResearchComplete = true;
		};
	} else if (researchType === 'hoplite' && !hopliteResearchComplete) {
		// New Defender Tier 2
		cost = HOPLITE_RESEARCH_COST;
		researchName = 'Skeleton Hoplite';
		canResearch = shieldedResearchComplete; // Prerequisite: Shielded researched
		setResearchFlag = function setResearchFlag() {
			hopliteResearchComplete = true;
		};
		if (!canResearch) {
			console.log("Prerequisite not met: Research Shielded Skeleton first.");
		}
	} else if (researchType === 'eliteswordsman' && !eliteSwordsmanResearchComplete) {
		// Tier 3 Melee
		cost = ELITESWORDSMAN_RESEARCH_COST;
		researchName = 'Elite Swordsman';
		canResearch = swordsmanResearchComplete; // Prerequisite: Swordsman researched
		setResearchFlag = function setResearchFlag() {
			eliteSwordsmanResearchComplete = true;
		};
		if (!canResearch) {
			console.log("Prerequisite not met: Research Swordsman first.");
		}
	} else if (researchType === 'crossbowman' && !crossbowmanResearchComplete) {
		// Tier 3 Ranged
		cost = CROSSBOWMAN_RESEARCH_COST;
		researchName = 'Crossbowman';
		canResearch = archerResearchComplete; // Prerequisite: Archer researched
		setResearchFlag = function setResearchFlag() {
			crossbowmanResearchComplete = true;
		};
		if (!canResearch) {
			console.log("Prerequisite not met: Research Archer first.");
		}
	} else if (researchType === 'darkknight' && !darkKnightResearchComplete) {
		// Tier 3 Defender
		cost = DARKKNIGHT_RESEARCH_COST;
		researchName = 'Dark Knight';
		canResearch = hopliteResearchComplete; // Prerequisite: Hoplite researched
		setResearchFlag = function setResearchFlag() {
			darkKnightResearchComplete = true;
		};
		if (!canResearch) {
			console.log("Prerequisite not met: Research Hoplite first.");
		}
	} else if (researchType === 'bomber' && !bomberResearchComplete) {
		// Artillery Tier 1
		cost = BOMBER_RESEARCH_COST;
		researchName = 'Skeleton Bomber';
		canResearch = true; // No prerequisite
		setResearchFlag = function setResearchFlag() {
			bomberResearchComplete = true;
		};
	} else if (researchType === 'catapult' && !catapultResearchComplete) {
		// Artillery Tier 2
		cost = CATAPULT_RESEARCH_COST;
		researchName = 'Pumpkin Catapult';
		canResearch = bomberResearchComplete; // Prerequisite: Bomber
		setResearchFlag = function setResearchFlag() {
			catapultResearchComplete = true;
		};
		if (!canResearch) {
			console.log("Prerequisite not met: Research Bomber first.");
		}
	} else if (researchType === 'dragon' && !dragonResearchComplete) {
		// Artillery Tier 3
		cost = DRAGON_RESEARCH_COST;
		researchName = 'Skeleton Dragon';
		canResearch = catapultResearchComplete; // Prerequisite: Catapult
		setResearchFlag = function setResearchFlag() {
			dragonResearchComplete = true;
		};
		if (!canResearch) {
			console.log("Prerequisite not met: Research Catapult first.");
		}
	} else {
		console.log("Research already complete, prerequisite not met, or invalid type:", researchType);
		return; // Invalid type, already researched, or prereq not met
	}
	if (canResearch && gold >= cost) {
		gold -= cost;
		setResearchFlag(); // Set the specific research flag to true
		try {
			// Reuse upgrade sound, or create a specific 'research' sound
			LK.getSound('upgradeUnit').play(); // Assuming 'upgradeUnit' sound is suitable
		} catch (e) {
			console.log("Sound error playing research sound: " + e);
		}
		console.log("Research complete for:", researchName);
		updateGoldDisplay(); // Update UI immediately
	} else {
		console.log("Not enough gold to research " + researchName);
		LK.effects.flashObject(goldTxt, 0xFF0000, 300);
	}
}
function clearBattlefield() {
	// Remove all existing units from the game and arrays
	for (var i = playerUnits.length - 1; i >= 0; i--) {
		if (playerUnits[i] && playerUnits[i].destroy) {
			// Check if destroy exists
			playerUnits[i].destroy();
		}
	}
	playerUnits = []; // Reset array
	for (var i = enemyUnits.length - 1; i >= 0; i--) {
		if (enemyUnits[i] && enemyUnits[i].destroy) {
			// Check if destroy exists
			enemyUnits[i].destroy();
		}
	}
	enemyUnits = []; // Reset array
	// Remove the golden piggy if it exists
	if (goldenPiggyInstance !== null) {
		goldenPiggyInstance.destroy();
		goldenPiggyInstance = null;
	}
}
function spawnUnit(unitType, isEnemy) {
	var stats = UNIT_STATS[unitType];
	if (!stats) {
		console.error("Cannot spawn unknown unit type:", unitType);
		return null;
	}
	// Prepare config for the Unit class constructor
	var config = {
		isEnemy: isEnemy,
		hp: stats.hp,
		attackPower: stats.attackPower,
		attackRange: stats.attackRange,
		speed: stats.speed,
		assetId: stats.assetId,
		attackCooldownTime: stats.attackCooldownTime,
		attackSoundId: stats.attackSoundId,
		unitType: unitType // Pass the unit type
	};
	// Create new instance of Unit
	var unit = new Unit(config);
	// Determine spawn side and array
	var armyArray = isEnemy ? enemyUnits : playerUnits;
	var spawnX = isEnemy ? ENEMY_SPAWN_X : PLAYER_SPAWN_X;
	// Calculate staggered Y position
	var currentY = SPAWN_Y_START + armyArray.length * SPAWN_Y_STEP;
	// Wrap Y position if it goes beyond the designated spawn area end
	if (currentY > SPAWN_Y_END) {
		var yRange = SPAWN_Y_END - SPAWN_Y_START;
		if (yRange <= 0) {
			yRange = SPAWN_Y_STEP;
		} // Avoid division by zero or negative range
		currentY = SPAWN_Y_START + armyArray.length * SPAWN_Y_STEP % yRange;
	}
	// Set initial position and state
	unit.x = spawnX;
	unit.y = currentY;
	unit.lastX = unit.x; // Initialize last state correctly
	// Add the unit to the game display and the logical array
	game.addChild(unit);
	armyArray.push(unit);
	return unit; // Return the created unit if needed elsewhere
}
function startBattle() {
	if (isBattling) {
		return;
	} // Prevent starting multiple battles
	console.log("Starting battle...");
	isBattling = true;
	clearBattlefield(); // Remove any units from a previous battle
	// Define enemy forces for this battle (can be made dynamic later)
	if (Object.keys(currentEnemyConfig).length === 0) {
		// Only initialize on first battle
		currentEnemyConfig = {
			humanFarmer: 3,
			humanSlinger: 1
		};
	} // Otherwise use the already incremented config from previous win
	// Spawn Player Units based on the current roster
	console.log("Spawning player units:", playerArmyRoster);
	for (var unitType in playerArmyRoster) {
		if (playerArmyRoster.hasOwnProperty(unitType)) {
			// Good practice for iterating objects
			var count = playerArmyRoster[unitType];
			for (var i = 0; i < count; i++) {
				spawnUnit(unitType, false); // Spawn player unit (not enemy)
			}
		}
	}
	// Spawn Enemy Units based on the current configuration
	console.log("Spawning enemy units:", currentEnemyConfig);
	for (var unitType in currentEnemyConfig) {
		if (currentEnemyConfig.hasOwnProperty(unitType)) {
			var count = currentEnemyConfig[unitType];
			for (var i = 0; i < count; i++) {
				spawnUnit(unitType, true); // Spawn enemy unit
			}
		}
	}
	// Hide UI elements not relevant during battle
	buttonContainer.visible = false;
	// Ensure units arrays are populated before the first update runs
	console.log("Battle started. Player units:", playerUnits.length, "Enemy units:", enemyUnits.length);
}
function endBattle(playerWon) {
	// Check if the battle hasn't already ended to prevent multiple triggers
	if (!isBattling) {
		return;
	}
	console.log("Battle ended. Player won:", playerWon);
	isBattling = false; // Set state before doing anything else
	// Explicitly remove piggy when battle ends, BEFORE showing UI again.
	// This ensures it's properly cleaned up and allows a new one to spawn in subsequent battles.
	if (goldenPiggyInstance !== null) {
		goldenPiggyInstance.destroy();
		goldenPiggyInstance = null;
	}
	// Show UI elements again
	buttonContainer.visible = true;
	if (playerWon) {
		var goldEarned = 50; // Example gold reward
		gold += goldEarned;
		try {
			// Defensive coding for sound playback
			LK.getSound('battleWon').play();
		} catch (e) {
			console.log("Sound error playing battleWon: " + e);
		}
		console.log("Earned " + goldEarned + " gold. Total gold:", gold);
		// Update display immediately after awarding gold
		updateGoldDisplay();
		battleCounter++; // Increment the battle counter on win
		villageTxt.setText('Village: ' + (battleCounter + 1)); // Update the village counter display
		console.log("Battle won! Proceeding to village: " + (battleCounter + 1));
		// Humans gain more units when player wins battles
		for (var unitType in currentEnemyConfig) {
			if (currentEnemyConfig.hasOwnProperty(unitType)) {
				// Increase each existing unit type by 1-2 for the next battle
				currentEnemyConfig[unitType] += Math.floor(Math.random() * 2) + 1;
			}
		}
		// Introduce new units starting from the 5th battle (after winning the 4th)
		if (battleCounter >= 4) {
			// 4 wins means the next battle is the 5th
			// Add Guard if not present, or increase count
			if (!currentEnemyConfig.hasOwnProperty('humanGuard')) {
				currentEnemyConfig['humanGuard'] = 1; // Start with 1
			} else {
				currentEnemyConfig['humanGuard'] += 1; // Add one more each subsequent win
			}
			// Add Militia Archer if not present, or increase count
			if (!currentEnemyConfig.hasOwnProperty('humanMilitiaArcher')) {
				currentEnemyConfig['humanMilitiaArcher'] = 1; // Start with 1
			} else {
				currentEnemyConfig['humanMilitiaArcher'] += 1; // Add one more each subsequent win
			}
			console.log("Stronger human reinforcements (Guards, Militia Archers) have arrived!");
		}
		// Introduce Local Protector starting from the 6th battle (after winning the 5th)
		if (battleCounter >= 5) {
			// 5 wins means the next battle is the 6th
			if (!currentEnemyConfig.hasOwnProperty('humanLocalprotector')) {
				currentEnemyConfig['humanLocalprotector'] = 1; // Start with 1
			} else {
				currentEnemyConfig['humanLocalprotector'] += 1; // Add one more each win
			}
			console.log("Local Protector reinforcements have arrived!");
		}
		// Introduce elite units starting from the 8th battle (after winning the 7th)
		if (battleCounter >= 7) {
			// 7 wins means the next battle is the 8th
			// Add Elite Guard if not present, or increase count
			if (!currentEnemyConfig.hasOwnProperty('humanEliteGuard')) {
				currentEnemyConfig['humanEliteGuard'] = 1; // Start with 1
			} else {
				currentEnemyConfig['humanEliteGuard'] += 1; // Add one more each subsequent win
			}
			// Add Archer if not present, or increase count
			if (!currentEnemyConfig.hasOwnProperty('humanArcher')) {
				currentEnemyConfig['humanArcher'] = 1; // Start with 1
			} else {
				currentEnemyConfig['humanArcher'] += 1; // Add one more each subsequent win
			}
			console.log("Elite human reinforcements (Elite Guards, Archers) have arrived!");
		}
		// Introduce Guardian starting from the 9th battle (after winning the 8th)
		if (battleCounter >= 8) {
			// 8 wins means the next battle is the 9th
			if (!currentEnemyConfig.hasOwnProperty('humanGuardian')) {
				currentEnemyConfig['humanGuardian'] = 1; // Start with 1
			} else {
				currentEnemyConfig['humanGuardian'] += 1; // Add one more each win
			}
			console.log("Guardian reinforcements have arrived!");
		}
		// Introduce Bomber starting from the 13th battle (after winning the 12th)
		if (battleCounter >= 12) {
			if (!currentEnemyConfig.hasOwnProperty('Bomber')) {
				currentEnemyConfig['Bomber'] = 1;
			} else {
				currentEnemyConfig['Bomber'] += 1;
			}
			console.log("Bomber reinforcements have arrived!");
		}
		// Introduce King's Guard starting from the 15th battle (after winning the 14th)
		if (battleCounter >= 14) {
			if (!currentEnemyConfig.hasOwnProperty("King's guard")) {
				currentEnemyConfig["King's guard"] = 1;
			} else {
				currentEnemyConfig["King's guard"] += 1;
			}
			console.log("King's Guard reinforcements have arrived!");
		}
		// Introduce Crossbowman starting from the 16th battle (after winning the 15th)
		if (battleCounter >= 15) {
			if (!currentEnemyConfig.hasOwnProperty("Crossbowman")) {
				currentEnemyConfig["Crossbowman"] = 1;
			} else {
				currentEnemyConfig["Crossbowman"] += 1;
			}
			console.log("Crossbowman reinforcements have arrived!");
		}
		// Introduce Cannoneer starting from the 20th battle (after winning the 19th)
		if (battleCounter >= 19) {
			if (!currentEnemyConfig.hasOwnProperty('Cannoneer')) {
				currentEnemyConfig['Cannoneer'] = 1;
			} else {
				currentEnemyConfig['Cannoneer'] += 1;
			}
			console.log("Cannoneer reinforcements have arrived!");
		}
		// Introduce King's Shield starting from the 23rd battle (after winning the 22nd)
		if (battleCounter >= 22) {
			if (!currentEnemyConfig.hasOwnProperty("King's shield")) {
				currentEnemyConfig["King's shield"] = 1;
			} else {
				currentEnemyConfig["King's shield"] += 1;
			}
			console.log("King's Shield reinforcements have arrived!");
		}
		// Introduce Trebuchet starting from the 26th battle (after winning the 25th)
		if (battleCounter >= 25) {
			if (!currentEnemyConfig.hasOwnProperty('Trebuchet')) {
				currentEnemyConfig['Trebuchet'] = 1;
			} else {
				currentEnemyConfig['Trebuchet'] += 1;
			}
			console.log("Trebuchet reinforcements have arrived!");
		}
		console.log("Enemy forces have grown stronger for the next battle:", currentEnemyConfig);
		// Game continues, player can choose to recruit or battle again
	} else {
		console.log("Player lost the battle.");
		// Game over is handled by LK engine which resets the game state
		LK.showGameOver();
		// Note: Gold and roster will reset unless storage plugin is used.
	}
	// Update button states based on new gold amount AFTER battle outcome is decided
	// This is especially important if the player lost, as LK.showGameOver might reset things
	// before this line runs if not careful. updateGoldDisplay() called inside win condition is safer.
	// If player loses, the game resets anyway, so updating buttons might not be needed here.
	if (playerWon) {
		updateGoldDisplay(); // Ensure buttons reflect new gold total after winning
	}
}
// --- Initialize Game State ---
// Assign onClick handlers to buttons *after* they are created
startButton.onClick = startBattle; // Assign the function reference
recruitMilitiaButton.onClick = function () {
	var unitToRecruit = 'skeletonMilitia'; // Default
	if (eliteSwordsmanResearchComplete) {
		unitToRecruit = 'skeletonEliteswordsman';
	} else if (swordsmanResearchComplete) {
		unitToRecruit = 'skeletonSwordsman';
	} else if (militiaResearchComplete) {
		unitToRecruit = 'skeletonRookie';
	}
	recruitUnit(unitToRecruit);
};
recruitSlingerButton.onClick = function () {
	var unitToRecruit = 'skeletonSlinger'; // Default
	if (crossbowmanResearchComplete) {
		unitToRecruit = 'skeletonCrossbowman';
	} else if (archerResearchComplete) {
		unitToRecruit = 'skeletonArcher';
	} else if (slingerResearchComplete) {
		unitToRecruit = 'skeletonTraineeArcher';
	}
	recruitUnit(unitToRecruit);
};
recruitDefenderButton.onClick = function () {
	// Default to no unit (research required)
	var unitToRecruit = null;
	// Check research status to determine which defender unit to recruit
	if (darkKnightResearchComplete) {
		unitToRecruit = 'skeletonDarkKnight';
	} else if (hopliteResearchComplete) {
		unitToRecruit = 'skeletonHoplite';
	} else if (shieldedResearchComplete) {
		unitToRecruit = 'skeletonShielded';
	}
	// Only attempt to recruit if a valid unit type is available
	if (unitToRecruit) {
		recruitUnit(unitToRecruit);
	}
};
// Tier 1 Research Button Handlers
researchMilitiaButton.onClick = function () {
	researchUnit('militia');
};
researchSlingerButton.onClick = function () {
	researchUnit('slinger');
};
// Tier 2 Research Button Handlers
researchSwordsmanButton.onClick = function () {
	researchUnit('swordsman');
};
researchArcherButton.onClick = function () {
	researchUnit('archer');
};
// Defender Research Button Handlers
researchShieldedButton.onClick = function () {
	researchUnit('shielded');
};
researchHopliteButton.onClick = function () {
	researchUnit('hoplite');
};
// Tier 3 Research Button Handlers
researchEliteSwordsmanButton.onClick = function () {
	researchUnit('eliteswordsman');
};
researchCrossbowmanButton.onClick = function () {
	researchUnit('crossbowman');
};
researchDarkKnightButton.onClick = function () {
	researchUnit('darkknight');
};
// Artillery Research Button Handlers
researchBomberButton.onClick = function () {
	researchUnit('bomber');
};
researchCatapultButton.onClick = function () {
	researchUnit('catapult');
};
researchDragonButton.onClick = function () {
	researchUnit('dragon');
};
// Artillery Recruitment Button Handler
recruitArtilleryButton.onClick = function () {
	var unitToRecruit = null;
	if (dragonResearchComplete) {
		unitToRecruit = 'skeletonDragon';
	} else if (catapultResearchComplete) {
		unitToRecruit = 'skeletonPumpkinCatapult';
	} else if (bomberResearchComplete) {
		unitToRecruit = 'skeletonBomber';
	}
	// Only attempt to recruit if a valid unit type is available
	if (unitToRecruit) {
		recruitUnit(unitToRecruit);
	}
};
updateGoldDisplay(); // Set initial gold text and button states based on starting gold (10) and research state
// --- Game Update Loop ---
// This function is called by the LK engine automatically 60 times per second.
game.update = function () {
	if (!isBattling) {
		// Game is idle, waiting for player action (recruit/start battle)
		// No unit updates needed.
		return;
	}
	// --- Battle Logic ---
	// Update Player Units (Iterate backwards for safe removal)
	for (var i = playerUnits.length - 1; i >= 0; i--) {
		var pUnit = playerUnits[i];
		// Ensure unit exists and has methods before calling them
		if (!pUnit) {
			continue;
		}
		if (pUnit.isDead) {
			if (pUnit.destroy) {
				pUnit.destroy();
			} // Remove graphics from game
			playerUnits.splice(i, 1); // Remove from logical array
			continue; // Move to the next unit
		}
		// Pass the array of enemies for target finding
		if (pUnit.update) {
			pUnit.update(enemyUnits);
		}
	}
	// Update Enemy Units (Iterate backwards for safe removal)
	for (var i = enemyUnits.length - 1; i >= 0; i--) {
		var eUnit = enemyUnits[i];
		if (!eUnit) {
			continue;
		}
		if (eUnit.isDead) {
			if (eUnit.destroy) {
				eUnit.destroy();
			}
			enemyUnits.splice(i, 1);
			continue;
		}
		// Pass the array of player units for target finding
		if (eUnit.update) {
			eUnit.update(playerUnits);
		}
	}
	// --- Golden Piggy Logic ---
	// Chance to spawn a piggy if one isn't already active
	if (isBattling && goldenPiggyInstance === null) {
		// Low chance per tick, e.g., 1 in 1000 ticks on average
		var PIGGY_SPAWN_CHANCE = 1 / (60 * 10); // Roughly once every 10 seconds average
		if (Math.random() < PIGGY_SPAWN_CHANCE) {
			console.log("Spawning Golden Piggy!");
			goldenPiggyInstance = new GoldenPiggy();
			// Spawn position (e.g., random y in the middle vertical third, center horizontally)
			var spawnY = GAME_HEIGHT * 0.33 + Math.random() * (GAME_HEIGHT * 0.33);
			goldenPiggyInstance.x = GAME_WIDTH / 2;
			goldenPiggyInstance.y = spawnY;
			game.addChild(goldenPiggyInstance); // Add to display
		}
	}
	// Update active piggy and remove if collected/timed out
	if (goldenPiggyInstance !== null) {
		if (goldenPiggyInstance.isCollected) {
			goldenPiggyInstance.destroy();
			goldenPiggyInstance = null;
		} else {
			goldenPiggyInstance.update(); // Call piggy's own update logic
		}
	}
	// Check Win/Loss Conditions *after* all units have been updated for the tick
	// Only check if the battle is currently marked as active
	if (isBattling) {
		if (enemyUnits.length === 0 && playerUnits.length > 0) {
			// Player wins: All enemies are defeated, player still has units.
			endBattle(true);
		} else if (playerUnits.length === 0) {
			// Player loses: All player units are defeated. (Enemy count doesn't matter here)
			// We might get here even if enemies also died in the same tick.
			endBattle(false);
		}
	}
};
// --- Input Handling ---
// Button clicks are managed by the Button class instances via their `up` method.
// No global game-level mouse/touch handlers needed for this MVP's interaction model.
 Skeleton with a wooden sword. In-Game asset. 2d. High contrast. No shadows
 Skeleton facing left with a slingshot. In-Game asset. 2d. High contrast. No shadows
 Farmer with a pitchfork. In-Game asset. 2d. High contrast. No shadows
 Farmer with a slingshot. In-Game asset. 2d. High contrast. No shadows
 Skeleton with copper sword, copper helmet and copper shield. In-Game asset. 2d. High contrast. No shadows
 A skeleton with a bow. In-Game asset. 2d. High contrast. No shadows
 Skeleton with Iron sword, iron helmet and a Reinforced wooden shield. In-Game asset. 2d. High contrast. No shadows
 Skeleton with a reinforced bow and a hood. In-Game asset. 2d. High contrast. No shadows
 Human with copper Armor, a copper sword and shield. In-Game asset. 2d. High contrast. No shadows
 A human with a bow and a quiver. In-Game asset. 2d. High contrast. No shadows
 Human with Iron Armor, iron sword and iron shield. In-Game asset. 2d. High contrast. No shadows
 A human with a reinforced bow, iron helmet and a bucket full of arrows. In-Game asset. 2d. High contrast. No shadows
 Skeleton holding a big copper shield with both hands. In-Game asset. 2d. High contrast. No shadows
 Skeleton with an Iron helmet, Iron spear and a big iron shield. In-Game asset. 2d. High contrast. No shadows
 A golden pig. In-Game asset. 2d. High contrast. No shadows
 Human with a big iron shield. In-Game asset. 2d. High contrast. No shadows
 Human with a big Copper shield. In-Game asset. 2d. High contrast. No shadows
 Skeleton with a blue hoodie and cape, golden sword and a reinforced iron shield. In-Game asset. 2d. High contrast. No shadows
 Skeleton with a dead wolf's head as a hood, a Crossbow and a big quiver. In-Game asset. 2d. High contrast. No shadows
 Skeleton with it's skull covered with a dark helmet, a dark axe and a shield with a red skull in the middle. In-Game asset. 2d. High contrast. No shadows
 Skeleton with a bomb. In-Game asset. 2d. High contrast. No shadows
 Pumpkin catapult made out of bones. In-Game asset. 2d. High contrast. No shadows
 Skeleton with a blue hoodie and cape riding a skeleton dragon. In-Game asset. 2d. High contrast. No shadows
 A knight with golden armour, golden shield and golden sword. In-Game asset. 2d. High contrast. No shadows
 A human with a golden helmet, crossbow and a big bucket full of arrows in his back. In-Game asset. 2d. High contrast. No shadows
 Human with a BIG golden shield and shining reinforced golden armor. In-Game asset. 2d. High contrast. No shadows
 Human with a bomb. In-Game asset. 2d. High contrast. No shadows
 Cannon. In-Game asset. 2d. High contrast. No shadows
 Trebuchet on wheels. In-Game asset. 2d. High contrast. No shadows