/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x000000
});
/**** 
* Game Code
****/ 
// Add full screen background
var backgroundImage = LK.getAsset('background', {
	anchorX: 0,
	anchorY: 0,
	x: 150,
	y: 0
});
game.addChild(backgroundImage);
// --- Tetris Game Implementation ---
// Board configuration
var BOARD_COLS = 10;
var BOARD_ROWS = 20;
var CELL_SIZE = 80; // Larger cells for better visibility
var BOARD_WIDTH = BOARD_COLS * CELL_SIZE;
var BOARD_HEIGHT = BOARD_ROWS * CELL_SIZE;
var PLAYER_BOARD_X = 1024 + 100; // Right side with more spacing
var AI_BOARD_X = 1024 - BOARD_WIDTH - 100; // Left side with more spacing
var BOARD_Y = 900;
// Add AI background (left half)
var aiBackgroundImage = LK.getAsset('aiBackground', {
	anchorX: 0,
	anchorY: 0,
	x: 6,
	y: BOARD_Y,
	alpha: 1,
	tint: 0xa80000
});
game.addChild(aiBackgroundImage);
// Add Player background (right half)
var playerBackgroundImage = LK.getAsset('playerBackground', {
	anchorX: 0,
	anchorY: 0,
	x: 1025,
	y: BOARD_Y,
	alpha: 1,
	tint: 0xffdd00
});
game.addChild(playerBackgroundImage);
// Tetrimino definitions
var TETROMINOS = [
// I - Light Blue
{
	color: 0x9acde3,
	blocks: [[0, 1], [1, 1], [2, 1], [3, 1]]
},
// O - Yellow
{
	color: 0xffe800,
	blocks: [[1, 0], [2, 0], [1, 1], [2, 1]]
},
// T - Red
{
	color: 0xcc0000,
	blocks: [[1, 0], [0, 1], [1, 1], [2, 1]]
},
// S - Dark Green
{
	color: 0x008000,
	blocks: [[1, 0], [2, 0], [0, 1], [1, 1]]
},
// Z - Brown
{
	color: 0x8b4513,
	blocks: [[0, 0], [1, 0], [1, 1], [2, 1]]
},
// J - Blue
{
	color: 0x0000cd,
	blocks: [[0, 0], [0, 1], [1, 1], [2, 1]]
},
// L - Dark Orange
{
	color: 0xff8c00,
	blocks: [[2, 0], [0, 1], [1, 1], [2, 1]]
}];
// Board states for player and AI
var playerBoard = [];
var aiBoard = [];
for (var r = 0; r < BOARD_ROWS; r++) {
	playerBoard[r] = [];
	aiBoard[r] = [];
	for (var c = 0; c < BOARD_COLS; c++) {
		playerBoard[r][c] = null;
		aiBoard[r][c] = null;
	}
}
// Score
var playerScore = 0;
var aiScore = 0;
// Labels for boards
// Next piece preview container and label
var nextPieceContainer = new Container();
nextPieceContainer.x = PLAYER_BOARD_X + BOARD_WIDTH / 2 - 120;
nextPieceContainer.y = BOARD_Y - 350;
game.addChild(nextPieceContainer);
var nextPieceLabel = new Text2('NEXT', {
	size: 50,
	fill: 0xffd900
});
nextPieceLabel.anchor.set(0.5, 0);
nextPieceLabel.x = 120;
nextPieceLabel.y = -60;
nextPieceContainer.addChild(nextPieceLabel);
var playerLabel = new Text2('PLAYER', {
	size: 70,
	fill: 0xffd900
});
playerLabel.anchor.set(0.5, 0);
playerLabel.x = PLAYER_BOARD_X + BOARD_WIDTH / 2;
playerLabel.y = BOARD_Y - 100;
game.addChild(playerLabel);
var aiLabel = new Text2('AI', {
	size: 70,
	fill: 0xFF0000
});
aiLabel.anchor.set(0.5, 0);
aiLabel.x = AI_BOARD_X + BOARD_WIDTH / 2;
aiLabel.y = 2525;
game.addChild(aiLabel);
// Player board container and graphics
var playerContainer = new Container();
playerContainer.x = PLAYER_BOARD_X;
playerContainer.y = BOARD_Y;
game.addChild(playerContainer);
var playerCellGraphics = [];
for (var r = 0; r < BOARD_ROWS; r++) {
	playerCellGraphics[r] = [];
	for (var c = 0; c < BOARD_COLS; c++) {
		var cell = LK.getAsset('cell', {
			anchorX: 0,
			anchorY: 0
		});
		cell.width = CELL_SIZE - 2;
		cell.height = CELL_SIZE - 2;
		cell.x = c * CELL_SIZE + 1;
		cell.y = r * CELL_SIZE + 1;
		cell.visible = false;
		playerContainer.addChild(cell);
		playerCellGraphics[r][c] = cell;
	}
}
// AI board container and graphics
var aiContainer = new Container();
aiContainer.x = AI_BOARD_X;
aiContainer.y = BOARD_Y;
game.addChild(aiContainer);
var aiCellGraphics = [];
for (var r = 0; r < BOARD_ROWS; r++) {
	aiCellGraphics[r] = [];
	for (var c = 0; c < BOARD_COLS; c++) {
		var cell = LK.getAsset('cell', {
			anchorX: 0,
			anchorY: 0
		});
		cell.width = CELL_SIZE - 2;
		cell.height = CELL_SIZE - 2;
		cell.x = c * CELL_SIZE + 1;
		cell.y = r * CELL_SIZE + 1;
		cell.visible = false;
		aiContainer.addChild(cell);
		aiCellGraphics[r][c] = cell;
	}
}
// Active piece states
var playerPiece = null;
var playerX = 0;
var playerY = 0;
var aiPiece = null;
var aiX = 0;
var aiY = 0;
// Next piece preview for player
var nextPlayerPiece = null;
var nextPieceBlocks = [];
var nextPieceGraphics = [];
// Helper: draw next piece preview in nextPieceContainer
function drawNextPiecePreview(piece) {
	// Remove previous preview blocks
	for (var i = 0; i < nextPieceBlocks.length; i++) {
		nextPieceContainer.removeChild(nextPieceBlocks[i]);
	}
	nextPieceBlocks = [];
	if (!piece) {
		return;
	}
	// Find minX/minY to center the piece
	var minX = Math.min(piece.blocks[0][0], piece.blocks[1][0], piece.blocks[2][0], piece.blocks[3][0]);
	var minY = Math.min(piece.blocks[0][1], piece.blocks[1][1], piece.blocks[2][1], piece.blocks[3][1]);
	var maxX = Math.max(piece.blocks[0][0], piece.blocks[1][0], piece.blocks[2][0], piece.blocks[3][0]);
	var maxY = Math.max(piece.blocks[0][1], piece.blocks[1][1], piece.blocks[2][1], piece.blocks[3][1]);
	var previewCellSize = 60;
	var offsetX = 120 - (maxX - minX + 1) * previewCellSize / 2;
	var offsetY = 0;
	for (var i = 0; i < 4; i++) {
		var block = piece.blocks[i];
		var cell = LK.getAsset('cell', {
			anchorX: 0,
			anchorY: 0
		});
		cell.width = previewCellSize - 2;
		cell.height = previewCellSize - 2;
		cell.x = offsetX + (block[0] - minX) * previewCellSize + 1;
		cell.y = offsetY + (block[1] - minY) * previewCellSize + 1;
		cell.tint = piece.color;
		cell.alpha = 1;
		nextPieceContainer.addChild(cell);
		nextPieceBlocks.push(cell);
	}
}
// Helper: update board graphics
function updateBoardGraphics(board, graphics) {
	for (var r = 0; r < BOARD_ROWS; r++) {
		for (var c = 0; c < BOARD_COLS; c++) {
			if (board[r][c]) {
				graphics[r][c].visible = true;
				graphics[r][c].tint = board[r][c];
				graphics[r][c].alpha = 1;
			} else {
				graphics[r][c].visible = false;
				graphics[r][c].alpha = 1;
			}
		}
	}
}
// Helper: draw active piece
function drawActivePiece(piece, x, y, graphics, show) {
	if (!piece) {
		return;
	}
	for (var i = 0; i < 4; i++) {
		var block = piece.blocks[i];
		var r = y + block[1];
		var c = x + block[0];
		if (r >= 0 && r < BOARD_ROWS && c >= 0 && c < BOARD_COLS) {
			graphics[r][c].visible = show;
			if (show) {
				graphics[r][c].tint = piece.color;
				graphics[r][c].alpha = 1;
			} else {
				graphics[r][c].alpha = 1;
			}
		}
	}
}
// Helper: draw ghost piece for player
function drawGhostPiece(piece, x, y, board, graphics, show) {
	if (!piece) {
		return;
	}
	// Find drop Y
	var ghostY = y;
	while (!collides(piece.blocks, x, ghostY + 1, board)) {
		ghostY++;
	}
	// Draw ghost piece (only if not overlapping with current piece)
	for (var i = 0; i < 4; i++) {
		var block = piece.blocks[i];
		var r = ghostY + block[1];
		var c = x + block[0];
		if (r >= 0 && r < BOARD_ROWS && c >= 0 && c < BOARD_COLS) {
			// Only draw ghost if not overlapping with current piece
			if (!(ghostY === y && block[1] === 0)) {
				graphics[r][c].visible = show;
				if (show) {
					// Use a semi-transparent white tint for ghost
					graphics[r][c].tint = 0xffffff;
					graphics[r][c].alpha = 0.3;
				} else {
					graphics[r][c].alpha = 1;
				}
			}
		}
	}
}
// Helper: rotate blocks
function rotateBlocks(blocks) {
	var rotated = [];
	for (var i = 0; i < blocks.length; i++) {
		rotated.push([blocks[i][1], -blocks[i][0]]);
	}
	// Normalize to top-left
	var minX = Math.min(rotated[0][0], rotated[1][0], rotated[2][0], rotated[3][0]);
	var minY = Math.min(rotated[0][1], rotated[1][1], rotated[2][1], rotated[3][1]);
	for (var i = 0; i < rotated.length; i++) {
		rotated[i][0] -= minX;
		rotated[i][1] -= minY;
	}
	return rotated;
}
// Helper: check collision
function collides(blocks, x, y, board) {
	for (var i = 0; i < 4; i++) {
		var bx = x + blocks[i][0];
		var by = y + blocks[i][1];
		if (bx < 0 || bx >= BOARD_COLS || by >= BOARD_ROWS) {
			return true;
		}
		if (by >= 0 && board[by][bx]) {
			// Only collide with real blocks (not null/undefined, not ghost overlays)
			return true;
		}
	}
	return false;
}
// Spawn a new piece
function spawnPiece(isAI) {
	if (isAI) {
		var shapeIdx = Math.floor(Math.random() * TETROMINOS.length);
		var shape = TETROMINOS[shapeIdx];
		var piece = {
			color: shape.color,
			blocks: [[shape.blocks[0][0], shape.blocks[0][1]], [shape.blocks[1][0], shape.blocks[1][1]], [shape.blocks[2][0], shape.blocks[2][1]], [shape.blocks[3][0], shape.blocks[3][1]]]
		};
		aiPiece = piece;
		aiX = 3;
		aiY = -2;
		if (collides(aiPiece.blocks, aiX, aiY + 1, aiBoard)) {
			// AI lost, player wins!
			LK.showYouWin();
			return;
		}
	} else {
		// Use nextPlayerPiece if available, otherwise random
		var piece;
		if (nextPlayerPiece) {
			piece = {
				color: nextPlayerPiece.color,
				blocks: [[nextPlayerPiece.blocks[0][0], nextPlayerPiece.blocks[0][1]], [nextPlayerPiece.blocks[1][0], nextPlayerPiece.blocks[1][1]], [nextPlayerPiece.blocks[2][0], nextPlayerPiece.blocks[2][1]], [nextPlayerPiece.blocks[3][0], nextPlayerPiece.blocks[3][1]]]
			};
		} else {
			var shapeIdx = Math.floor(Math.random() * TETROMINOS.length);
			var shape = TETROMINOS[shapeIdx];
			piece = {
				color: shape.color,
				blocks: [[shape.blocks[0][0], shape.blocks[0][1]], [shape.blocks[1][0], shape.blocks[1][1]], [shape.blocks[2][0], shape.blocks[2][1]], [shape.blocks[3][0], shape.blocks[3][1]]]
			};
		}
		playerPiece = piece;
		playerX = 3;
		playerY = -2;
		// Generate next piece for preview
		var nextIdx = Math.floor(Math.random() * TETROMINOS.length);
		var nextShape = TETROMINOS[nextIdx];
		nextPlayerPiece = {
			color: nextShape.color,
			blocks: [[nextShape.blocks[0][0], nextShape.blocks[0][1]], [nextShape.blocks[1][0], nextShape.blocks[1][1]], [nextShape.blocks[2][0], nextShape.blocks[2][1]], [nextShape.blocks[3][0], nextShape.blocks[3][1]]]
		};
		drawNextPiecePreview(nextPlayerPiece);
		if (collides(playerPiece.blocks, playerX, playerY + 1, playerBoard)) {
			LK.showGameOver();
		}
	}
}
// Reset AI board when AI loses
function resetAIBoard() {
	for (var r = 0; r < BOARD_ROWS; r++) {
		for (var c = 0; c < BOARD_COLS; c++) {
			aiBoard[r][c] = null;
		}
	}
	aiScore = 0;
	playerLabel.setText('PLAYER(' + playerScore + ')');
	aiLabel.setText('AI(' + aiScore + ')');
}
// Lock the active piece into the board
function lockPiece(piece, x, y, board) {
	for (var i = 0; i < 4; i++) {
		var block = piece.blocks[i];
		var r = y + block[1];
		var c = x + block[0];
		if (r >= 0 && r < BOARD_ROWS && c >= 0 && c < BOARD_COLS) {
			board[r][c] = piece.color;
		}
	}
}
// Clear full lines
function clearLines(board, isAI) {
	var lines = 0;
	var clearedLineData = []; // Store the cleared lines for transfer
	for (var r = BOARD_ROWS - 1; r >= 0; r--) {
		var full = true;
		for (var c = 0; c < BOARD_COLS; c++) {
			// Only count as filled if it's a real block (not null/undefined, not a ghost, not alpha < 1)
			if (!board[r][c]) {
				full = false;
				break;
			}
		}
		if (full) {
			// Check if this line contains any transferred blocks (gray blocks)
			var isTransferredLine = true;
			for (var cc = 0; cc < BOARD_COLS; cc++) {
				if (board[r][cc] !== 0x808080) {
					isTransferredLine = false;
					break;
				}
			}
			// Skip clearing if this is a transferred line - gray lines stay forever
			if (isTransferredLine) {
				continue; // Don't clear gray lines, move to next row
			}
			lines++;
			// Store line data for transfer (only non-gray lines)
			var lineData = [];
			for (var cc = 0; cc < BOARD_COLS; cc++) {
				lineData[cc] = board[r][cc];
			}
			clearedLineData.push(lineData);
			// Move all rows above down
			for (var rr = r; rr > 0; rr--) {
				for (var cc = 0; cc < BOARD_COLS; cc++) {
					board[rr][cc] = board[rr - 1][cc];
				}
			}
			for (var cc = 0; cc < BOARD_COLS; cc++) {
				board[0][cc] = null;
			}
			r++; // Check this row again
		}
	}
	if (lines > 0) {
		// Play line clear sound, but only if at least 7 seconds have passed since last play
		if (typeof lastLineSoundTime === "undefined") {
			lastLineSoundTime = 0;
		}
		var now = Date.now();
		if (now - lastLineSoundTime > 7000) {
			LK.getSound('lineclear').play();
			lastLineSoundTime = now;
		}
		if (isAI) {
			aiScore += lines * 100;
			// Only transfer lines that are not from previous transfers
			if (clearedLineData.length > 0) {
				transferLinesToBoard(clearedLineData, playerBoard);
			}
		} else {
			playerScore += lines * 100;
			// Only transfer lines that are not from previous transfers
			if (clearedLineData.length > 0) {
				transferLinesToBoard(clearedLineData, aiBoard);
			}
		}
		playerLabel.setText('PLAYER(' + playerScore + ')');
		aiLabel.setText('AI(' + aiScore + ')');
	}
}
// Try to move player piece
function tryMovePlayer(dx, dy, rotate) {
	var newBlocks = [];
	if (rotate) {
		newBlocks = rotateBlocks(playerPiece.blocks);
	} else {
		for (var i = 0; i < 4; i++) {
			newBlocks[i] = [playerPiece.blocks[i][0], playerPiece.blocks[i][1]];
		}
	}
	var nx = playerX + dx;
	var ny = playerY + dy;
	if (!collides(newBlocks, nx, ny, playerBoard)) {
		drawActivePiece(playerPiece, playerX, playerY, playerCellGraphics, false);
		playerX = nx;
		playerY = ny;
		if (rotate) {
			playerPiece.blocks = newBlocks;
		}
		drawActivePiece(playerPiece, playerX, playerY, playerCellGraphics, true);
		return true;
	}
	return false;
}
// AI logic functions
function getHeight(board) {
	for (var r = 0; r < BOARD_ROWS; r++) {
		for (var c = 0; c < BOARD_COLS; c++) {
			if (board[r][c]) {
				return BOARD_ROWS - r;
			}
		}
	}
	return 0;
}
function countHoles(board) {
	var holes = 0;
	for (var c = 0; c < BOARD_COLS; c++) {
		var blockFound = false;
		for (var r = 0; r < BOARD_ROWS; r++) {
			if (board[r][c]) {
				blockFound = true;
			} else if (blockFound) {
				holes++;
			}
		}
	}
	return holes;
}
function evaluateBoard(board) {
	var height = getHeight(board);
	var holes = countHoles(board);
	var lines = 0;
	for (var r = 0; r < BOARD_ROWS; r++) {
		var full = true;
		for (var c = 0; c < BOARD_COLS; c++) {
			if (!board[r][c]) {
				full = false;
				break;
			}
		}
		if (full) {
			lines++;
		}
	}
	return lines * 1000 - height * 10 - holes * 30;
}
function simulateMove(piece, x, y, board) {
	var testBoard = [];
	for (var r = 0; r < BOARD_ROWS; r++) {
		testBoard[r] = [];
		for (var c = 0; c < BOARD_COLS; c++) {
			testBoard[r][c] = board[r][c];
		}
	}
	// Drop piece to bottom
	while (!collides(piece.blocks, x, y + 1, testBoard)) {
		y++;
	}
	// Lock piece
	for (var i = 0; i < 4; i++) {
		var block = piece.blocks[i];
		var r = y + block[1];
		var c = x + block[0];
		if (r >= 0 && r < BOARD_ROWS && c >= 0 && c < BOARD_COLS) {
			testBoard[r][c] = piece.color;
		}
	}
	return evaluateBoard(testBoard);
}
function findBestMove() {
	if (!aiPiece) {
		return null;
	}
	var bestScore = -99999;
	var bestX = aiX;
	var bestRotation = 0;
	// Try all rotations
	var testPiece = {
		color: aiPiece.color,
		blocks: []
	};
	for (var rot = 0; rot < 4; rot++) {
		// Copy blocks
		for (var i = 0; i < 4; i++) {
			testPiece.blocks[i] = [aiPiece.blocks[i][0], aiPiece.blocks[i][1]];
		}
		// Apply rotation
		for (var r = 0; r < rot; r++) {
			testPiece.blocks = rotateBlocks(testPiece.blocks);
		}
		// Try all positions
		for (var x = -2; x < BOARD_COLS + 2; x++) {
			if (!collides(testPiece.blocks, x, aiY, aiBoard)) {
				var score = simulateMove(testPiece, x, aiY, aiBoard);
				if (score > bestScore) {
					bestScore = score;
					bestX = x;
					bestRotation = rot;
				}
			}
		}
	}
	return {
		x: bestX,
		rotation: bestRotation
	};
}
// Add variable to track fast drop mode
var fastDropMode = false;
// Control widgets at bottom of screen
var WIDGET_HEIGHT = 200;
var WIDGET_Y = 2500;
var WIDGET_WIDTH = 150;
var WIDGET_START = 1150;
var WIDGET_SEP = 50;
// Left button
var leftButton = LK.getAsset('left', {
	anchorX: 0,
	anchorY: 0,
	x: WIDGET_START,
	y: WIDGET_Y,
	width: WIDGET_WIDTH,
	height: WIDGET_HEIGHT
});
game.addChild(leftButton);
// Right button
var rightButton = LK.getAsset('right', {
	anchorX: 0,
	anchorY: 0,
	x: WIDGET_START + WIDGET_SEP + WIDGET_WIDTH,
	y: WIDGET_Y,
	width: WIDGET_WIDTH,
	height: WIDGET_HEIGHT
});
game.addChild(rightButton);
// Rotate button
var rotateButton = LK.getAsset('rotate', {
	anchorX: 0,
	anchorY: 0,
	x: WIDGET_START + WIDGET_SEP * 2 + WIDGET_WIDTH * 2,
	y: WIDGET_Y,
	width: WIDGET_WIDTH,
	height: WIDGET_HEIGHT
});
game.addChild(rotateButton);
// Down button
var downButton = LK.getAsset('down', {
	anchorX: 0,
	anchorY: 0,
	x: WIDGET_START + WIDGET_SEP * 3 + WIDGET_WIDTH * 3,
	y: WIDGET_Y,
	width: WIDGET_WIDTH,
	height: WIDGET_HEIGHT
});
game.addChild(downButton);
// Add click handlers for widgets
leftButton.down = function (x, y, obj) {
	if (playerPiece) {
		tryMovePlayer(-1, 0, false);
	}
};
rightButton.down = function (x, y, obj) {
	if (playerPiece) {
		tryMovePlayer(1, 0, false);
	}
};
rotateButton.down = function (x, y, obj) {
	if (playerPiece) {
		tryMovePlayer(0, 0, true);
	}
};
downButton.down = function (x, y, obj) {
	if (playerPiece) {
		fastDropMode = true;
	}
};
downButton.up = function (x, y, obj) {
	fastDropMode = false;
};
// Control widgets - no direct piece controls
game.down = function (x, y, obj) {
	// Controls are now handled by widgets
};
// Release fast drop mode when mouse/touch is released
game.up = function (x, y, obj) {
	fastDropMode = false;
};
// Main game update
var dropCounter = 0;
var aiMoveCounter = 0;
var aiTargetX = null;
var aiTargetRotation = 0;
game.update = function () {
	dropCounter++;
	// Player update - use faster drop speed when fastDropMode is active
	var dropSpeed = fastDropMode ? 3 : 30; // Drop every 3 frames when fast, every 30 frames normally
	if (dropCounter >= dropSpeed) {
		dropCounter = 0;
		if (!tryMovePlayer(0, 1, false)) {
			drawActivePiece(playerPiece, playerX, playerY, playerCellGraphics, false);
			lockPiece(playerPiece, playerX, playerY, playerBoard);
			clearLines(playerBoard, false);
			updateBoardGraphics(playerBoard, playerCellGraphics);
			spawnPiece(false);
			drawActivePiece(playerPiece, playerX, playerY, playerCellGraphics, true);
			// Reset fast drop mode when piece locks
			fastDropMode = false;
		}
	}
	// AI update
	aiMoveCounter++;
	if (aiMoveCounter >= 25) {
		// AI moves faster
		aiMoveCounter = 0;
		// Get best move if not already calculated
		if (aiTargetX === null && aiPiece) {
			var bestMove = findBestMove();
			if (bestMove) {
				aiTargetX = bestMove.x;
				aiTargetRotation = bestMove.rotation;
			}
		}
		// Execute AI moves
		if (aiPiece && aiTargetX !== null) {
			// Rotate first
			if (aiTargetRotation > 0) {
				var rotatedBlocks = rotateBlocks(aiPiece.blocks);
				if (!collides(rotatedBlocks, aiX, aiY, aiBoard)) {
					drawActivePiece(aiPiece, aiX, aiY, aiCellGraphics, false);
					aiPiece.blocks = rotatedBlocks;
					drawActivePiece(aiPiece, aiX, aiY, aiCellGraphics, true);
					aiTargetRotation--;
				}
			}
			// Then move horizontally
			else if (aiX < aiTargetX) {
				if (!collides(aiPiece.blocks, aiX + 1, aiY, aiBoard)) {
					drawActivePiece(aiPiece, aiX, aiY, aiCellGraphics, false);
					aiX++;
					drawActivePiece(aiPiece, aiX, aiY, aiCellGraphics, true);
				}
			} else if (aiX > aiTargetX) {
				if (!collides(aiPiece.blocks, aiX - 1, aiY, aiBoard)) {
					drawActivePiece(aiPiece, aiX, aiY, aiCellGraphics, false);
					aiX--;
					drawActivePiece(aiPiece, aiX, aiY, aiCellGraphics, true);
				}
			}
			// Drop when in position
			else {
				if (!collides(aiPiece.blocks, aiX, aiY + 1, aiBoard)) {
					drawActivePiece(aiPiece, aiX, aiY, aiCellGraphics, false);
					aiY++;
					drawActivePiece(aiPiece, aiX, aiY, aiCellGraphics, true);
				} else {
					// Lock piece
					drawActivePiece(aiPiece, aiX, aiY, aiCellGraphics, false);
					lockPiece(aiPiece, aiX, aiY, aiBoard);
					clearLines(aiBoard, true);
					updateBoardGraphics(aiBoard, aiCellGraphics);
					spawnPiece(true);
					aiTargetX = null;
					aiTargetRotation = 0;
				}
			}
		}
	}
	updateBoardGraphics(playerBoard, playerCellGraphics);
	updateBoardGraphics(aiBoard, aiCellGraphics);
	// Draw ghost piece for player (clear previous ghost first)
	drawGhostPiece(playerPiece, playerX, playerY, playerBoard, playerCellGraphics, false);
	// Draw ghost piece for player (show new ghost)
	drawGhostPiece(playerPiece, playerX, playerY, playerBoard, playerCellGraphics, true);
	drawActivePiece(playerPiece, playerX, playerY, playerCellGraphics, true);
	drawActivePiece(aiPiece, aiX, aiY, aiCellGraphics, true);
};
// Start game
LK.playMusic('moscow');
// Generate first next piece for player before spawning
var firstIdx = Math.floor(Math.random() * TETROMINOS.length);
var firstShape = TETROMINOS[firstIdx];
nextPlayerPiece = {
	color: firstShape.color,
	blocks: [[firstShape.blocks[0][0], firstShape.blocks[0][1]], [firstShape.blocks[1][0], firstShape.blocks[1][1]], [firstShape.blocks[2][0], firstShape.blocks[2][1]], [firstShape.blocks[3][0], firstShape.blocks[3][1]]]
};
drawNextPiecePreview(nextPlayerPiece);
// Spawn both player and AI pieces in the same frame to start at the same time
spawnPiece(false); // Player piece
spawnPiece(true); // AI piece
drawActivePiece(playerPiece, playerX, playerY, playerCellGraphics, true);
drawActivePiece(aiPiece, aiX, aiY, aiCellGraphics, true);
updateBoardGraphics(playerBoard, playerCellGraphics);
updateBoardGraphics(aiBoard, aiCellGraphics);
// Transfer lines to opponent's board (competitive mode)
function transferLinesToBoard(lineData, targetBoard) {
	// Move all existing rows up by the number of transferred lines
	var numLines = lineData.length;
	for (var r = 0; r < BOARD_ROWS - numLines; r++) {
		for (var c = 0; c < BOARD_COLS; c++) {
			// Only copy real blocks, not ghost piece overlays (ghosts are not stored in board, but just in case)
			if (targetBoard[r + numLines][c] !== undefined && targetBoard[r + numLines][c] !== null) {
				targetBoard[r][c] = targetBoard[r + numLines][c];
			} else {
				targetBoard[r][c] = null;
			}
		}
	}
	// Add the transferred lines at the bottom
	for (var i = 0; i < numLines; i++) {
		var targetRow = BOARD_ROWS - numLines + i;
		for (var c = 0; c < BOARD_COLS; c++) {
			// Use a neutral gray color for transferred lines to distinguish them
			targetBoard[targetRow][c] = 0x808080;
		}
	}
} /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x000000
});
/**** 
* Game Code
****/ 
// Add full screen background
var backgroundImage = LK.getAsset('background', {
	anchorX: 0,
	anchorY: 0,
	x: 150,
	y: 0
});
game.addChild(backgroundImage);
// --- Tetris Game Implementation ---
// Board configuration
var BOARD_COLS = 10;
var BOARD_ROWS = 20;
var CELL_SIZE = 80; // Larger cells for better visibility
var BOARD_WIDTH = BOARD_COLS * CELL_SIZE;
var BOARD_HEIGHT = BOARD_ROWS * CELL_SIZE;
var PLAYER_BOARD_X = 1024 + 100; // Right side with more spacing
var AI_BOARD_X = 1024 - BOARD_WIDTH - 100; // Left side with more spacing
var BOARD_Y = 900;
// Add AI background (left half)
var aiBackgroundImage = LK.getAsset('aiBackground', {
	anchorX: 0,
	anchorY: 0,
	x: 6,
	y: BOARD_Y,
	alpha: 1,
	tint: 0xa80000
});
game.addChild(aiBackgroundImage);
// Add Player background (right half)
var playerBackgroundImage = LK.getAsset('playerBackground', {
	anchorX: 0,
	anchorY: 0,
	x: 1025,
	y: BOARD_Y,
	alpha: 1,
	tint: 0xffdd00
});
game.addChild(playerBackgroundImage);
// Tetrimino definitions
var TETROMINOS = [
// I - Light Blue
{
	color: 0x9acde3,
	blocks: [[0, 1], [1, 1], [2, 1], [3, 1]]
},
// O - Yellow
{
	color: 0xffe800,
	blocks: [[1, 0], [2, 0], [1, 1], [2, 1]]
},
// T - Red
{
	color: 0xcc0000,
	blocks: [[1, 0], [0, 1], [1, 1], [2, 1]]
},
// S - Dark Green
{
	color: 0x008000,
	blocks: [[1, 0], [2, 0], [0, 1], [1, 1]]
},
// Z - Brown
{
	color: 0x8b4513,
	blocks: [[0, 0], [1, 0], [1, 1], [2, 1]]
},
// J - Blue
{
	color: 0x0000cd,
	blocks: [[0, 0], [0, 1], [1, 1], [2, 1]]
},
// L - Dark Orange
{
	color: 0xff8c00,
	blocks: [[2, 0], [0, 1], [1, 1], [2, 1]]
}];
// Board states for player and AI
var playerBoard = [];
var aiBoard = [];
for (var r = 0; r < BOARD_ROWS; r++) {
	playerBoard[r] = [];
	aiBoard[r] = [];
	for (var c = 0; c < BOARD_COLS; c++) {
		playerBoard[r][c] = null;
		aiBoard[r][c] = null;
	}
}
// Score
var playerScore = 0;
var aiScore = 0;
// Labels for boards
// Next piece preview container and label
var nextPieceContainer = new Container();
nextPieceContainer.x = PLAYER_BOARD_X + BOARD_WIDTH / 2 - 120;
nextPieceContainer.y = BOARD_Y - 350;
game.addChild(nextPieceContainer);
var nextPieceLabel = new Text2('NEXT', {
	size: 50,
	fill: 0xffd900
});
nextPieceLabel.anchor.set(0.5, 0);
nextPieceLabel.x = 120;
nextPieceLabel.y = -60;
nextPieceContainer.addChild(nextPieceLabel);
var playerLabel = new Text2('PLAYER', {
	size: 70,
	fill: 0xffd900
});
playerLabel.anchor.set(0.5, 0);
playerLabel.x = PLAYER_BOARD_X + BOARD_WIDTH / 2;
playerLabel.y = BOARD_Y - 100;
game.addChild(playerLabel);
var aiLabel = new Text2('AI', {
	size: 70,
	fill: 0xFF0000
});
aiLabel.anchor.set(0.5, 0);
aiLabel.x = AI_BOARD_X + BOARD_WIDTH / 2;
aiLabel.y = 2525;
game.addChild(aiLabel);
// Player board container and graphics
var playerContainer = new Container();
playerContainer.x = PLAYER_BOARD_X;
playerContainer.y = BOARD_Y;
game.addChild(playerContainer);
var playerCellGraphics = [];
for (var r = 0; r < BOARD_ROWS; r++) {
	playerCellGraphics[r] = [];
	for (var c = 0; c < BOARD_COLS; c++) {
		var cell = LK.getAsset('cell', {
			anchorX: 0,
			anchorY: 0
		});
		cell.width = CELL_SIZE - 2;
		cell.height = CELL_SIZE - 2;
		cell.x = c * CELL_SIZE + 1;
		cell.y = r * CELL_SIZE + 1;
		cell.visible = false;
		playerContainer.addChild(cell);
		playerCellGraphics[r][c] = cell;
	}
}
// AI board container and graphics
var aiContainer = new Container();
aiContainer.x = AI_BOARD_X;
aiContainer.y = BOARD_Y;
game.addChild(aiContainer);
var aiCellGraphics = [];
for (var r = 0; r < BOARD_ROWS; r++) {
	aiCellGraphics[r] = [];
	for (var c = 0; c < BOARD_COLS; c++) {
		var cell = LK.getAsset('cell', {
			anchorX: 0,
			anchorY: 0
		});
		cell.width = CELL_SIZE - 2;
		cell.height = CELL_SIZE - 2;
		cell.x = c * CELL_SIZE + 1;
		cell.y = r * CELL_SIZE + 1;
		cell.visible = false;
		aiContainer.addChild(cell);
		aiCellGraphics[r][c] = cell;
	}
}
// Active piece states
var playerPiece = null;
var playerX = 0;
var playerY = 0;
var aiPiece = null;
var aiX = 0;
var aiY = 0;
// Next piece preview for player
var nextPlayerPiece = null;
var nextPieceBlocks = [];
var nextPieceGraphics = [];
// Helper: draw next piece preview in nextPieceContainer
function drawNextPiecePreview(piece) {
	// Remove previous preview blocks
	for (var i = 0; i < nextPieceBlocks.length; i++) {
		nextPieceContainer.removeChild(nextPieceBlocks[i]);
	}
	nextPieceBlocks = [];
	if (!piece) {
		return;
	}
	// Find minX/minY to center the piece
	var minX = Math.min(piece.blocks[0][0], piece.blocks[1][0], piece.blocks[2][0], piece.blocks[3][0]);
	var minY = Math.min(piece.blocks[0][1], piece.blocks[1][1], piece.blocks[2][1], piece.blocks[3][1]);
	var maxX = Math.max(piece.blocks[0][0], piece.blocks[1][0], piece.blocks[2][0], piece.blocks[3][0]);
	var maxY = Math.max(piece.blocks[0][1], piece.blocks[1][1], piece.blocks[2][1], piece.blocks[3][1]);
	var previewCellSize = 60;
	var offsetX = 120 - (maxX - minX + 1) * previewCellSize / 2;
	var offsetY = 0;
	for (var i = 0; i < 4; i++) {
		var block = piece.blocks[i];
		var cell = LK.getAsset('cell', {
			anchorX: 0,
			anchorY: 0
		});
		cell.width = previewCellSize - 2;
		cell.height = previewCellSize - 2;
		cell.x = offsetX + (block[0] - minX) * previewCellSize + 1;
		cell.y = offsetY + (block[1] - minY) * previewCellSize + 1;
		cell.tint = piece.color;
		cell.alpha = 1;
		nextPieceContainer.addChild(cell);
		nextPieceBlocks.push(cell);
	}
}
// Helper: update board graphics
function updateBoardGraphics(board, graphics) {
	for (var r = 0; r < BOARD_ROWS; r++) {
		for (var c = 0; c < BOARD_COLS; c++) {
			if (board[r][c]) {
				graphics[r][c].visible = true;
				graphics[r][c].tint = board[r][c];
				graphics[r][c].alpha = 1;
			} else {
				graphics[r][c].visible = false;
				graphics[r][c].alpha = 1;
			}
		}
	}
}
// Helper: draw active piece
function drawActivePiece(piece, x, y, graphics, show) {
	if (!piece) {
		return;
	}
	for (var i = 0; i < 4; i++) {
		var block = piece.blocks[i];
		var r = y + block[1];
		var c = x + block[0];
		if (r >= 0 && r < BOARD_ROWS && c >= 0 && c < BOARD_COLS) {
			graphics[r][c].visible = show;
			if (show) {
				graphics[r][c].tint = piece.color;
				graphics[r][c].alpha = 1;
			} else {
				graphics[r][c].alpha = 1;
			}
		}
	}
}
// Helper: draw ghost piece for player
function drawGhostPiece(piece, x, y, board, graphics, show) {
	if (!piece) {
		return;
	}
	// Find drop Y
	var ghostY = y;
	while (!collides(piece.blocks, x, ghostY + 1, board)) {
		ghostY++;
	}
	// Draw ghost piece (only if not overlapping with current piece)
	for (var i = 0; i < 4; i++) {
		var block = piece.blocks[i];
		var r = ghostY + block[1];
		var c = x + block[0];
		if (r >= 0 && r < BOARD_ROWS && c >= 0 && c < BOARD_COLS) {
			// Only draw ghost if not overlapping with current piece
			if (!(ghostY === y && block[1] === 0)) {
				graphics[r][c].visible = show;
				if (show) {
					// Use a semi-transparent white tint for ghost
					graphics[r][c].tint = 0xffffff;
					graphics[r][c].alpha = 0.3;
				} else {
					graphics[r][c].alpha = 1;
				}
			}
		}
	}
}
// Helper: rotate blocks
function rotateBlocks(blocks) {
	var rotated = [];
	for (var i = 0; i < blocks.length; i++) {
		rotated.push([blocks[i][1], -blocks[i][0]]);
	}
	// Normalize to top-left
	var minX = Math.min(rotated[0][0], rotated[1][0], rotated[2][0], rotated[3][0]);
	var minY = Math.min(rotated[0][1], rotated[1][1], rotated[2][1], rotated[3][1]);
	for (var i = 0; i < rotated.length; i++) {
		rotated[i][0] -= minX;
		rotated[i][1] -= minY;
	}
	return rotated;
}
// Helper: check collision
function collides(blocks, x, y, board) {
	for (var i = 0; i < 4; i++) {
		var bx = x + blocks[i][0];
		var by = y + blocks[i][1];
		if (bx < 0 || bx >= BOARD_COLS || by >= BOARD_ROWS) {
			return true;
		}
		if (by >= 0 && board[by][bx]) {
			// Only collide with real blocks (not null/undefined, not ghost overlays)
			return true;
		}
	}
	return false;
}
// Spawn a new piece
function spawnPiece(isAI) {
	if (isAI) {
		var shapeIdx = Math.floor(Math.random() * TETROMINOS.length);
		var shape = TETROMINOS[shapeIdx];
		var piece = {
			color: shape.color,
			blocks: [[shape.blocks[0][0], shape.blocks[0][1]], [shape.blocks[1][0], shape.blocks[1][1]], [shape.blocks[2][0], shape.blocks[2][1]], [shape.blocks[3][0], shape.blocks[3][1]]]
		};
		aiPiece = piece;
		aiX = 3;
		aiY = -2;
		if (collides(aiPiece.blocks, aiX, aiY + 1, aiBoard)) {
			// AI lost, player wins!
			LK.showYouWin();
			return;
		}
	} else {
		// Use nextPlayerPiece if available, otherwise random
		var piece;
		if (nextPlayerPiece) {
			piece = {
				color: nextPlayerPiece.color,
				blocks: [[nextPlayerPiece.blocks[0][0], nextPlayerPiece.blocks[0][1]], [nextPlayerPiece.blocks[1][0], nextPlayerPiece.blocks[1][1]], [nextPlayerPiece.blocks[2][0], nextPlayerPiece.blocks[2][1]], [nextPlayerPiece.blocks[3][0], nextPlayerPiece.blocks[3][1]]]
			};
		} else {
			var shapeIdx = Math.floor(Math.random() * TETROMINOS.length);
			var shape = TETROMINOS[shapeIdx];
			piece = {
				color: shape.color,
				blocks: [[shape.blocks[0][0], shape.blocks[0][1]], [shape.blocks[1][0], shape.blocks[1][1]], [shape.blocks[2][0], shape.blocks[2][1]], [shape.blocks[3][0], shape.blocks[3][1]]]
			};
		}
		playerPiece = piece;
		playerX = 3;
		playerY = -2;
		// Generate next piece for preview
		var nextIdx = Math.floor(Math.random() * TETROMINOS.length);
		var nextShape = TETROMINOS[nextIdx];
		nextPlayerPiece = {
			color: nextShape.color,
			blocks: [[nextShape.blocks[0][0], nextShape.blocks[0][1]], [nextShape.blocks[1][0], nextShape.blocks[1][1]], [nextShape.blocks[2][0], nextShape.blocks[2][1]], [nextShape.blocks[3][0], nextShape.blocks[3][1]]]
		};
		drawNextPiecePreview(nextPlayerPiece);
		if (collides(playerPiece.blocks, playerX, playerY + 1, playerBoard)) {
			LK.showGameOver();
		}
	}
}
// Reset AI board when AI loses
function resetAIBoard() {
	for (var r = 0; r < BOARD_ROWS; r++) {
		for (var c = 0; c < BOARD_COLS; c++) {
			aiBoard[r][c] = null;
		}
	}
	aiScore = 0;
	playerLabel.setText('PLAYER(' + playerScore + ')');
	aiLabel.setText('AI(' + aiScore + ')');
}
// Lock the active piece into the board
function lockPiece(piece, x, y, board) {
	for (var i = 0; i < 4; i++) {
		var block = piece.blocks[i];
		var r = y + block[1];
		var c = x + block[0];
		if (r >= 0 && r < BOARD_ROWS && c >= 0 && c < BOARD_COLS) {
			board[r][c] = piece.color;
		}
	}
}
// Clear full lines
function clearLines(board, isAI) {
	var lines = 0;
	var clearedLineData = []; // Store the cleared lines for transfer
	for (var r = BOARD_ROWS - 1; r >= 0; r--) {
		var full = true;
		for (var c = 0; c < BOARD_COLS; c++) {
			// Only count as filled if it's a real block (not null/undefined, not a ghost, not alpha < 1)
			if (!board[r][c]) {
				full = false;
				break;
			}
		}
		if (full) {
			// Check if this line contains any transferred blocks (gray blocks)
			var isTransferredLine = true;
			for (var cc = 0; cc < BOARD_COLS; cc++) {
				if (board[r][cc] !== 0x808080) {
					isTransferredLine = false;
					break;
				}
			}
			// Skip clearing if this is a transferred line - gray lines stay forever
			if (isTransferredLine) {
				continue; // Don't clear gray lines, move to next row
			}
			lines++;
			// Store line data for transfer (only non-gray lines)
			var lineData = [];
			for (var cc = 0; cc < BOARD_COLS; cc++) {
				lineData[cc] = board[r][cc];
			}
			clearedLineData.push(lineData);
			// Move all rows above down
			for (var rr = r; rr > 0; rr--) {
				for (var cc = 0; cc < BOARD_COLS; cc++) {
					board[rr][cc] = board[rr - 1][cc];
				}
			}
			for (var cc = 0; cc < BOARD_COLS; cc++) {
				board[0][cc] = null;
			}
			r++; // Check this row again
		}
	}
	if (lines > 0) {
		// Play line clear sound, but only if at least 7 seconds have passed since last play
		if (typeof lastLineSoundTime === "undefined") {
			lastLineSoundTime = 0;
		}
		var now = Date.now();
		if (now - lastLineSoundTime > 7000) {
			LK.getSound('lineclear').play();
			lastLineSoundTime = now;
		}
		if (isAI) {
			aiScore += lines * 100;
			// Only transfer lines that are not from previous transfers
			if (clearedLineData.length > 0) {
				transferLinesToBoard(clearedLineData, playerBoard);
			}
		} else {
			playerScore += lines * 100;
			// Only transfer lines that are not from previous transfers
			if (clearedLineData.length > 0) {
				transferLinesToBoard(clearedLineData, aiBoard);
			}
		}
		playerLabel.setText('PLAYER(' + playerScore + ')');
		aiLabel.setText('AI(' + aiScore + ')');
	}
}
// Try to move player piece
function tryMovePlayer(dx, dy, rotate) {
	var newBlocks = [];
	if (rotate) {
		newBlocks = rotateBlocks(playerPiece.blocks);
	} else {
		for (var i = 0; i < 4; i++) {
			newBlocks[i] = [playerPiece.blocks[i][0], playerPiece.blocks[i][1]];
		}
	}
	var nx = playerX + dx;
	var ny = playerY + dy;
	if (!collides(newBlocks, nx, ny, playerBoard)) {
		drawActivePiece(playerPiece, playerX, playerY, playerCellGraphics, false);
		playerX = nx;
		playerY = ny;
		if (rotate) {
			playerPiece.blocks = newBlocks;
		}
		drawActivePiece(playerPiece, playerX, playerY, playerCellGraphics, true);
		return true;
	}
	return false;
}
// AI logic functions
function getHeight(board) {
	for (var r = 0; r < BOARD_ROWS; r++) {
		for (var c = 0; c < BOARD_COLS; c++) {
			if (board[r][c]) {
				return BOARD_ROWS - r;
			}
		}
	}
	return 0;
}
function countHoles(board) {
	var holes = 0;
	for (var c = 0; c < BOARD_COLS; c++) {
		var blockFound = false;
		for (var r = 0; r < BOARD_ROWS; r++) {
			if (board[r][c]) {
				blockFound = true;
			} else if (blockFound) {
				holes++;
			}
		}
	}
	return holes;
}
function evaluateBoard(board) {
	var height = getHeight(board);
	var holes = countHoles(board);
	var lines = 0;
	for (var r = 0; r < BOARD_ROWS; r++) {
		var full = true;
		for (var c = 0; c < BOARD_COLS; c++) {
			if (!board[r][c]) {
				full = false;
				break;
			}
		}
		if (full) {
			lines++;
		}
	}
	return lines * 1000 - height * 10 - holes * 30;
}
function simulateMove(piece, x, y, board) {
	var testBoard = [];
	for (var r = 0; r < BOARD_ROWS; r++) {
		testBoard[r] = [];
		for (var c = 0; c < BOARD_COLS; c++) {
			testBoard[r][c] = board[r][c];
		}
	}
	// Drop piece to bottom
	while (!collides(piece.blocks, x, y + 1, testBoard)) {
		y++;
	}
	// Lock piece
	for (var i = 0; i < 4; i++) {
		var block = piece.blocks[i];
		var r = y + block[1];
		var c = x + block[0];
		if (r >= 0 && r < BOARD_ROWS && c >= 0 && c < BOARD_COLS) {
			testBoard[r][c] = piece.color;
		}
	}
	return evaluateBoard(testBoard);
}
function findBestMove() {
	if (!aiPiece) {
		return null;
	}
	var bestScore = -99999;
	var bestX = aiX;
	var bestRotation = 0;
	// Try all rotations
	var testPiece = {
		color: aiPiece.color,
		blocks: []
	};
	for (var rot = 0; rot < 4; rot++) {
		// Copy blocks
		for (var i = 0; i < 4; i++) {
			testPiece.blocks[i] = [aiPiece.blocks[i][0], aiPiece.blocks[i][1]];
		}
		// Apply rotation
		for (var r = 0; r < rot; r++) {
			testPiece.blocks = rotateBlocks(testPiece.blocks);
		}
		// Try all positions
		for (var x = -2; x < BOARD_COLS + 2; x++) {
			if (!collides(testPiece.blocks, x, aiY, aiBoard)) {
				var score = simulateMove(testPiece, x, aiY, aiBoard);
				if (score > bestScore) {
					bestScore = score;
					bestX = x;
					bestRotation = rot;
				}
			}
		}
	}
	return {
		x: bestX,
		rotation: bestRotation
	};
}
// Add variable to track fast drop mode
var fastDropMode = false;
// Control widgets at bottom of screen
var WIDGET_HEIGHT = 200;
var WIDGET_Y = 2500;
var WIDGET_WIDTH = 150;
var WIDGET_START = 1150;
var WIDGET_SEP = 50;
// Left button
var leftButton = LK.getAsset('left', {
	anchorX: 0,
	anchorY: 0,
	x: WIDGET_START,
	y: WIDGET_Y,
	width: WIDGET_WIDTH,
	height: WIDGET_HEIGHT
});
game.addChild(leftButton);
// Right button
var rightButton = LK.getAsset('right', {
	anchorX: 0,
	anchorY: 0,
	x: WIDGET_START + WIDGET_SEP + WIDGET_WIDTH,
	y: WIDGET_Y,
	width: WIDGET_WIDTH,
	height: WIDGET_HEIGHT
});
game.addChild(rightButton);
// Rotate button
var rotateButton = LK.getAsset('rotate', {
	anchorX: 0,
	anchorY: 0,
	x: WIDGET_START + WIDGET_SEP * 2 + WIDGET_WIDTH * 2,
	y: WIDGET_Y,
	width: WIDGET_WIDTH,
	height: WIDGET_HEIGHT
});
game.addChild(rotateButton);
// Down button
var downButton = LK.getAsset('down', {
	anchorX: 0,
	anchorY: 0,
	x: WIDGET_START + WIDGET_SEP * 3 + WIDGET_WIDTH * 3,
	y: WIDGET_Y,
	width: WIDGET_WIDTH,
	height: WIDGET_HEIGHT
});
game.addChild(downButton);
// Add click handlers for widgets
leftButton.down = function (x, y, obj) {
	if (playerPiece) {
		tryMovePlayer(-1, 0, false);
	}
};
rightButton.down = function (x, y, obj) {
	if (playerPiece) {
		tryMovePlayer(1, 0, false);
	}
};
rotateButton.down = function (x, y, obj) {
	if (playerPiece) {
		tryMovePlayer(0, 0, true);
	}
};
downButton.down = function (x, y, obj) {
	if (playerPiece) {
		fastDropMode = true;
	}
};
downButton.up = function (x, y, obj) {
	fastDropMode = false;
};
// Control widgets - no direct piece controls
game.down = function (x, y, obj) {
	// Controls are now handled by widgets
};
// Release fast drop mode when mouse/touch is released
game.up = function (x, y, obj) {
	fastDropMode = false;
};
// Main game update
var dropCounter = 0;
var aiMoveCounter = 0;
var aiTargetX = null;
var aiTargetRotation = 0;
game.update = function () {
	dropCounter++;
	// Player update - use faster drop speed when fastDropMode is active
	var dropSpeed = fastDropMode ? 3 : 30; // Drop every 3 frames when fast, every 30 frames normally
	if (dropCounter >= dropSpeed) {
		dropCounter = 0;
		if (!tryMovePlayer(0, 1, false)) {
			drawActivePiece(playerPiece, playerX, playerY, playerCellGraphics, false);
			lockPiece(playerPiece, playerX, playerY, playerBoard);
			clearLines(playerBoard, false);
			updateBoardGraphics(playerBoard, playerCellGraphics);
			spawnPiece(false);
			drawActivePiece(playerPiece, playerX, playerY, playerCellGraphics, true);
			// Reset fast drop mode when piece locks
			fastDropMode = false;
		}
	}
	// AI update
	aiMoveCounter++;
	if (aiMoveCounter >= 25) {
		// AI moves faster
		aiMoveCounter = 0;
		// Get best move if not already calculated
		if (aiTargetX === null && aiPiece) {
			var bestMove = findBestMove();
			if (bestMove) {
				aiTargetX = bestMove.x;
				aiTargetRotation = bestMove.rotation;
			}
		}
		// Execute AI moves
		if (aiPiece && aiTargetX !== null) {
			// Rotate first
			if (aiTargetRotation > 0) {
				var rotatedBlocks = rotateBlocks(aiPiece.blocks);
				if (!collides(rotatedBlocks, aiX, aiY, aiBoard)) {
					drawActivePiece(aiPiece, aiX, aiY, aiCellGraphics, false);
					aiPiece.blocks = rotatedBlocks;
					drawActivePiece(aiPiece, aiX, aiY, aiCellGraphics, true);
					aiTargetRotation--;
				}
			}
			// Then move horizontally
			else if (aiX < aiTargetX) {
				if (!collides(aiPiece.blocks, aiX + 1, aiY, aiBoard)) {
					drawActivePiece(aiPiece, aiX, aiY, aiCellGraphics, false);
					aiX++;
					drawActivePiece(aiPiece, aiX, aiY, aiCellGraphics, true);
				}
			} else if (aiX > aiTargetX) {
				if (!collides(aiPiece.blocks, aiX - 1, aiY, aiBoard)) {
					drawActivePiece(aiPiece, aiX, aiY, aiCellGraphics, false);
					aiX--;
					drawActivePiece(aiPiece, aiX, aiY, aiCellGraphics, true);
				}
			}
			// Drop when in position
			else {
				if (!collides(aiPiece.blocks, aiX, aiY + 1, aiBoard)) {
					drawActivePiece(aiPiece, aiX, aiY, aiCellGraphics, false);
					aiY++;
					drawActivePiece(aiPiece, aiX, aiY, aiCellGraphics, true);
				} else {
					// Lock piece
					drawActivePiece(aiPiece, aiX, aiY, aiCellGraphics, false);
					lockPiece(aiPiece, aiX, aiY, aiBoard);
					clearLines(aiBoard, true);
					updateBoardGraphics(aiBoard, aiCellGraphics);
					spawnPiece(true);
					aiTargetX = null;
					aiTargetRotation = 0;
				}
			}
		}
	}
	updateBoardGraphics(playerBoard, playerCellGraphics);
	updateBoardGraphics(aiBoard, aiCellGraphics);
	// Draw ghost piece for player (clear previous ghost first)
	drawGhostPiece(playerPiece, playerX, playerY, playerBoard, playerCellGraphics, false);
	// Draw ghost piece for player (show new ghost)
	drawGhostPiece(playerPiece, playerX, playerY, playerBoard, playerCellGraphics, true);
	drawActivePiece(playerPiece, playerX, playerY, playerCellGraphics, true);
	drawActivePiece(aiPiece, aiX, aiY, aiCellGraphics, true);
};
// Start game
LK.playMusic('moscow');
// Generate first next piece for player before spawning
var firstIdx = Math.floor(Math.random() * TETROMINOS.length);
var firstShape = TETROMINOS[firstIdx];
nextPlayerPiece = {
	color: firstShape.color,
	blocks: [[firstShape.blocks[0][0], firstShape.blocks[0][1]], [firstShape.blocks[1][0], firstShape.blocks[1][1]], [firstShape.blocks[2][0], firstShape.blocks[2][1]], [firstShape.blocks[3][0], firstShape.blocks[3][1]]]
};
drawNextPiecePreview(nextPlayerPiece);
// Spawn both player and AI pieces in the same frame to start at the same time
spawnPiece(false); // Player piece
spawnPiece(true); // AI piece
drawActivePiece(playerPiece, playerX, playerY, playerCellGraphics, true);
drawActivePiece(aiPiece, aiX, aiY, aiCellGraphics, true);
updateBoardGraphics(playerBoard, playerCellGraphics);
updateBoardGraphics(aiBoard, aiCellGraphics);
// Transfer lines to opponent's board (competitive mode)
function transferLinesToBoard(lineData, targetBoard) {
	// Move all existing rows up by the number of transferred lines
	var numLines = lineData.length;
	for (var r = 0; r < BOARD_ROWS - numLines; r++) {
		for (var c = 0; c < BOARD_COLS; c++) {
			// Only copy real blocks, not ghost piece overlays (ghosts are not stored in board, but just in case)
			if (targetBoard[r + numLines][c] !== undefined && targetBoard[r + numLines][c] !== null) {
				targetBoard[r][c] = targetBoard[r + numLines][c];
			} else {
				targetBoard[r][c] = null;
			}
		}
	}
	// Add the transferred lines at the bottom
	for (var i = 0; i < numLines; i++) {
		var targetRow = BOARD_ROWS - numLines + i;
		for (var c = 0; c < BOARD_COLS; c++) {
			// Use a neutral gray color for transferred lines to distinguish them
			targetBoard[targetRow][c] = 0x808080;
		}
	}
}