User prompt
update the advanced terrain cards in the main deck to show a band of colour along the top matching the basic terrain but in purple for now. implement a colour band at the bottom of all the creatures to denote their type and sub-type: basic herbivore is yellow, advanced herbivore is green, basic carnivore is orange and advanced carnivore is red. go!
User prompt
now we need to build the main deck so that we can implement that into the game and begin the game loop, here is the main deck card split: 20x 'Advanced' 'Terrain' cards (2 x 'fresh' 'water' cards both with no climate requirement [can be placed on any climate], 5 x 'sea' 'water' cards, 1 requires 'cold', 1 requires 'hot' and 1 requires 'temperate' climates, the 4th requires either 'temperate' or 'hot' climates and the 5th has no climate requirements. Then there are the 'land' terrain cards: 3 x 'mountain' types 1 has no climate requirements, 1 needs either temperate or cold and the last needs either temperate or hot, 5 x 'hill' type, 1 needs hot, 1 needs cold and 1 needs temperate, 1 needs either temperate or hot and the 5th needs either temperate or cold, finally, there are the 'flat land' cards - 5 of them, 1 each for cold, temperate and hot as the other types, 1 for temperate of hot, and the 5th requires either temperate or cold as before. the rest of the main deck are the creature cards split into 32 x basic herbivore cards, 12 x advanced herbivore cards, 10 x basic carnivore cards and 8 x advanced carnivore cards we will leave the parameters of the creature cards until later but perhaps for now, add some place-holder information for them with basic climate requirements. go!
User prompt
move the 'scry active' text reminder to the right under the 'cards drawn' text and make it read: 'Scry' and have a small highlight
User prompt
shift the climate zone text left a little so its fully visible and shift the cards slightly right
User prompt
good, now make the climate zone text verticle as atm it dissapears behind cards
User prompt
i have realised that during gameplay, the climate parameter for each space needs to stay visible and thus i think rather than display it as a band of colour on each card, lets put it as a background for each row and change the colour bar at the top of the basic terrain cards to white to denote 'basic' status. please implement these changes
User prompt
good, now increase the text size and make it bolder as it is hard to read atm
User prompt
perfect! UI is filled but not too full, however, during game play cards will get placed upon others in a 'stack' system which will increase the y axis of each card stack so therefore, please decrease card scale by 10% and increase the amount of space between the tops and bottoms of any such card row by enough to fit the coloured strip indicators twice
User prompt
i have zoomed my screen which is good, thank you but i also feel an increase in the card size will help since there is so mucu unused space on the UI anyway, please implement card scale increase by 50%
User prompt
yes
User prompt
brilliant! lets do the setup: there is a pool of 23 basic terrain cards split thus: 9 x water-type cards (6 x sea, 3 x fresh) 14 x land-type cards (4 x mountain, 5 x hill and 5 x flat land), they are shuffled and arranged in a planet layout: 2-4-6-4-2 formation (top to bottom). Climate zones are assigned before the shuffle: Cold (rows 1&5), Temperate (rows 2&4), Hot (row 3) Cards gain climate attributes based on their row position as mentioned before. This setup is the 'basic' setup and there will be options to vary this with things like: number of cards in each row, what each rows climate is and so on that can be chosen by the user or randomised in the pre-setup step. after the drawn basic terrains are placed and climates are assigned to them, the main deck is shuffled, the round marker is set to 0 and the 'scry' token is shown in the info panel of the UI ('scry' rule to be discussed later). No cards are in the players hand at this stage. the un-used basic terrain cards are not used during game (except for some events). implement this please
Code edit (1 edits merged)
Please save this source code
User prompt
Evolution Links: Planet Builder
Initial prompt
Game is a single player, turn based card game to be created as an app to play on mobile and desktop devices. The visuals are in simple 2D and the main screen is the 'board' which is a grid of the cards dealt in setup and added to during play. Also in the UI is the player hand and a scoring/info visual helper. The game is played in turns which are split over 5 'rounds'. A round is completed when the 'main deck' runs out and is reshuffled. A turn is split into 'phases' which will be described in detail later but essentially, a turn is: draw 3 cards from the main deck, play 1 card onto a card already in play, apply any 'on-play' effect, adjust the 'links' (to be explained later), check states and finish turn. basically the game represents the evolution of a planet and the interactions between carnivores and their herbivore prey (hence the 'links'). There are also 'events' that are added to the deck if a creature dies. There is a setup step before the game begins which lays out a number of cards in position to represent the fresh planet. Perhaps 2 player integration later on in a 'hot seat' kind of way. Is that enough info for a basic reference? We can discuss card types, setup, in depth turn structure etc etc, what shall we discuss or is there info that you feel is necessary now?
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Card = Container.expand(function (cardData) {
var self = Container.call(this);
self.cardData = cardData || {
type: 'herbivore',
name: 'Basic Herbivore',
health: 3,
effect: 'none'
};
// Create card background
var cardBg = self.attachAsset('cardBase', {
anchorX: 0.5,
anchorY: 0.5
});
// Create card content based on type
var cardContent;
if (self.cardData.type === 'herbivore') {
cardContent = self.attachAsset('herbivoreCard', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (self.cardData.type === 'carnivore') {
cardContent = self.attachAsset('carnivoreCard', {
anchorX: 0.5,
anchorY: 0.5
});
} else {
cardContent = self.attachAsset('eventCard', {
anchorX: 0.5,
anchorY: 0.5
});
}
// Add text labels
self.nameText = new Text2(self.cardData.name, {
size: 24,
fill: 0xFFFFFF
});
self.nameText.anchor.set(0.5, 0);
self.nameText.x = 0;
self.nameText.y = -100;
self.addChild(self.nameText);
if (self.cardData.health) {
self.healthText = new Text2("HP: " + self.cardData.health, {
size: 20,
fill: 0xFFFFFF
});
self.healthText.anchor.set(0.5, 0);
self.healthText.x = 0;
self.healthText.y = 80;
self.addChild(self.healthText);
}
self.currentHealth = self.cardData.health || 0;
self.gridX = -1;
self.gridY = -1;
self.isInPlay = false;
self.takeDamage = function (amount) {
self.currentHealth -= amount;
if (self.healthText) {
self.healthText.setText("HP: " + self.currentHealth);
}
if (self.currentHealth <= 0) {
self.die();
}
};
self.die = function () {
if (self.isInPlay) {
// Remove from grid
if (gameBoard[self.gridY] && gameBoard[self.gridY][self.gridX]) {
gameBoard[self.gridY][self.gridX] = null;
}
// Add event card to deck
addEventCardToDeck();
// Visual death effect
tween(self, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 500,
onFinish: function onFinish() {
if (self.parent) {
self.parent.removeChild(self);
}
}
});
LK.getSound('creatureDie').play();
}
};
self.down = function (x, y, obj) {
if (!self.isInPlay && playerHand.indexOf(self) !== -1) {
selectedCard = self;
draggedCard = self;
originalCardPosition = {
x: self.x,
y: self.y
};
}
};
return self;
});
var GridCell = Container.expand(function (gridX, gridY) {
var self = Container.call(this);
self.gridX = gridX;
self.gridY = gridY;
var cellBg = self.attachAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5
});
cellBg.alpha = 0.3;
self.card = null;
self.isHighlighted = false;
self.highlight = function () {
if (!self.isHighlighted) {
self.isHighlighted = true;
cellBg.alpha = 0.6;
}
};
self.unhighlight = function () {
if (self.isHighlighted) {
self.isHighlighted = false;
cellBg.alpha = 0.3;
}
};
self.down = function (x, y, obj) {
if (selectedCard && !self.card) {
// Place card on this cell
placeCardOnGrid(selectedCard, self.gridX, self.gridY);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a252f
});
/****
* Game Code
****/
// Game state variables
var currentRound = 1;
var maxRounds = 5;
var cardsDrawnThisTurn = 0;
var maxCardsPerTurn = 3;
var gameBoard = [];
var boardWidth = 4;
var boardHeight = 3;
var gridCells = [];
var playerHand = [];
var maxHandSize = 5;
var mainDeck = [];
var selectedCard = null;
var draggedCard = null;
var originalCardPosition = null;
// UI Elements
var roundText = new Text2("Round: " + currentRound, {
size: 48,
fill: 0xFFFFFF
});
roundText.anchor.set(0.5, 0);
LK.gui.top.addChild(roundText);
roundText.y = 100;
var cardsDrawnText = new Text2("Cards Drawn: " + cardsDrawnThisTurn + "/" + maxCardsPerTurn, {
size: 36,
fill: 0xFFFFFF
});
cardsDrawnText.anchor.set(0, 0);
LK.gui.topRight.addChild(cardsDrawnText);
cardsDrawnText.x = -300;
cardsDrawnText.y = 150;
var deckCountText = new Text2("Deck: " + mainDeck.length, {
size: 36,
fill: 0xFFFFFF
});
deckCountText.anchor.set(0, 0);
LK.gui.topLeft.addChild(deckCountText);
deckCountText.x = 120;
deckCountText.y = 150;
// Initialize game board
function initializeBoard() {
// Create 2D array for board state
for (var y = 0; y < boardHeight; y++) {
gameBoard[y] = [];
for (var x = 0; x < boardWidth; x++) {
gameBoard[y][x] = null;
}
}
// Create visual grid cells
var startX = 1024 - boardWidth * 220 / 2 + 110;
var startY = 800;
for (var y = 0; y < boardHeight; y++) {
gridCells[y] = [];
for (var x = 0; x < boardWidth; x++) {
var cell = new GridCell(x, y);
cell.x = startX + x * 220;
cell.y = startY + y * 280;
game.addChild(cell);
gridCells[y][x] = cell;
}
}
}
// Create initial deck
function createInitialDeck() {
mainDeck = [];
// Add herbivores
for (var i = 0; i < 8; i++) {
mainDeck.push({
type: 'herbivore',
name: 'Herbivore ' + (i + 1),
health: 2 + Math.floor(i / 2),
effect: 'grow'
});
}
// Add carnivores
for (var i = 0; i < 6; i++) {
mainDeck.push({
type: 'carnivore',
name: 'Carnivore ' + (i + 1),
health: 3 + Math.floor(i / 2),
effect: 'hunt'
});
}
// Shuffle deck
shuffleDeck();
}
function shuffleDeck() {
for (var i = mainDeck.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = mainDeck[i];
mainDeck[i] = mainDeck[j];
mainDeck[j] = temp;
}
}
function drawCard() {
if (cardsDrawnThisTurn >= maxCardsPerTurn) {
return null;
}
if (mainDeck.length === 0) {
endRound();
return null;
}
if (playerHand.length >= maxHandSize) {
return null;
}
var cardData = mainDeck.pop();
var card = new Card(cardData);
playerHand.push(card);
cardsDrawnThisTurn++;
// Position card in hand
updateHandPositions();
game.addChild(card);
// Update UI
cardsDrawnText.setText("Cards Drawn: " + cardsDrawnThisTurn + "/" + maxCardsPerTurn);
deckCountText.setText("Deck: " + mainDeck.length);
LK.getSound('cardDraw').play();
return card;
}
function updateHandPositions() {
var handY = 2400;
var handStartX = 1024 - playerHand.length * 200 / 2 + 100;
for (var i = 0; i < playerHand.length; i++) {
var card = playerHand[i];
if (!card.isInPlay) {
tween(card, {
x: handStartX + i * 200,
y: handY
}, {
duration: 300
});
}
}
}
function placeCardOnGrid(card, gridX, gridY) {
if (!card || gameBoard[gridY][gridX] !== null) {
return false;
}
// Remove card from hand
var handIndex = playerHand.indexOf(card);
if (handIndex !== -1) {
playerHand.splice(handIndex, 1);
}
// Place on board
gameBoard[gridY][gridX] = card;
card.gridX = gridX;
card.gridY = gridY;
card.isInPlay = true;
// Position card visually
var targetX = gridCells[gridY][gridX].x;
var targetY = gridCells[gridY][gridX].y;
tween(card, {
x: targetX,
y: targetY
}, {
duration: 300
});
// Apply card effect
applyCardEffect(card);
// Update hand positions
updateHandPositions();
// Clear selection
selectedCard = null;
draggedCard = null;
// Reset turn
cardsDrawnThisTurn = 0;
cardsDrawnText.setText("Cards Drawn: " + cardsDrawnThisTurn + "/" + maxCardsPerTurn);
LK.getSound('cardPlace').play();
return true;
}
function applyCardEffect(card) {
if (card.cardData.type === 'carnivore' && card.cardData.effect === 'hunt') {
// Hunt nearby herbivores
var neighbors = getNeighbors(card.gridX, card.gridY);
for (var i = 0; i < neighbors.length; i++) {
var neighbor = neighbors[i];
if (neighbor && neighbor.cardData.type === 'herbivore') {
neighbor.takeDamage(1);
}
}
} else if (card.cardData.type === 'herbivore' && card.cardData.effect === 'grow') {
// Grow and strengthen nearby herbivores
var neighbors = getNeighbors(card.gridX, card.gridY);
for (var i = 0; i < neighbors.length; i++) {
var neighbor = neighbors[i];
if (neighbor && neighbor.cardData.type === 'herbivore') {
neighbor.currentHealth += 1;
if (neighbor.healthText) {
neighbor.healthText.setText("HP: " + neighbor.currentHealth);
}
}
}
}
}
function getNeighbors(gridX, gridY) {
var neighbors = [];
var directions = [{
x: -1,
y: 0
}, {
x: 1,
y: 0
}, {
x: 0,
y: -1
}, {
x: 0,
y: 1
}];
for (var i = 0; i < directions.length; i++) {
var newX = gridX + directions[i].x;
var newY = gridY + directions[i].y;
if (newX >= 0 && newX < boardWidth && newY >= 0 && newY < boardHeight) {
neighbors.push(gameBoard[newY][newX]);
}
}
return neighbors;
}
function addEventCardToDeck() {
var eventCard = {
type: 'event',
name: 'Environmental Change',
effect: 'disaster'
};
// Insert event card randomly in deck
var insertIndex = Math.floor(Math.random() * (mainDeck.length + 1));
mainDeck.splice(insertIndex, 0, eventCard);
deckCountText.setText("Deck: " + mainDeck.length);
}
function endRound() {
currentRound++;
if (currentRound > maxRounds) {
// Game complete
LK.showYouWin();
return;
}
// Reshuffle deck with remaining cards
var cardsOnBoard = [];
for (var y = 0; y < boardHeight; y++) {
for (var x = 0; x < boardWidth; x++) {
if (gameBoard[y][x]) {
cardsOnBoard.push(gameBoard[y][x].cardData);
}
}
}
// Create new deck for next round
createInitialDeck();
// Reset turn counter
cardsDrawnThisTurn = 0;
// Update UI
roundText.setText("Round: " + currentRound);
cardsDrawnText.setText("Cards Drawn: " + cardsDrawnThisTurn + "/" + maxCardsPerTurn);
deckCountText.setText("Deck: " + mainDeck.length);
}
// Draw card button functionality
var drawButton = LK.getAsset('cardBase', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
var drawButtonText = new Text2("DRAW", {
size: 32,
fill: 0xFFFFFF
});
drawButtonText.anchor.set(0.5, 0.5);
drawButton.addChild(drawButtonText);
drawButton.x = 1700;
drawButton.y = 2400;
game.addChild(drawButton);
drawButton.down = function () {
drawCard();
};
// Game move handler
game.move = function (x, y, obj) {
if (draggedCard) {
draggedCard.x = x;
draggedCard.y = y;
// Highlight valid placement cells
for (var gridY = 0; gridY < boardHeight; gridY++) {
for (var gridX = 0; gridX < boardWidth; gridX++) {
var cell = gridCells[gridY][gridX];
if (!gameBoard[gridY][gridX] && Math.abs(cell.x - x) < 110 && Math.abs(cell.y - y) < 130) {
cell.highlight();
} else {
cell.unhighlight();
}
}
}
}
};
game.up = function (x, y, obj) {
if (draggedCard) {
var placed = false;
// Check if card was dropped on a valid cell
for (var gridY = 0; gridY < boardHeight && !placed; gridY++) {
for (var gridX = 0; gridX < boardWidth && !placed; gridX++) {
var cell = gridCells[gridY][gridX];
if (!gameBoard[gridY][gridX] && Math.abs(cell.x - x) < 110 && Math.abs(cell.y - y) < 130) {
placed = placeCardOnGrid(draggedCard, gridX, gridY);
}
}
}
// If not placed, return to original position
if (!placed && originalCardPosition) {
tween(draggedCard, originalCardPosition, {
duration: 300
});
}
// Clear highlights
for (var gridY = 0; gridY < boardHeight; gridY++) {
for (var gridX = 0; gridX < boardWidth; gridX++) {
gridCells[gridY][gridX].unhighlight();
}
}
draggedCard = null;
originalCardPosition = null;
}
};
// Initialize game
initializeBoard();
createInitialDeck();
// Draw initial cards
for (var i = 0; i < 3; i++) {
drawCard();
}
game.update = function () {
// Update UI elements
deckCountText.setText("Deck: " + mainDeck.length);
// Check win/lose conditions
if (mainDeck.length === 0 && playerHand.length === 0) {
endRound();
}
}; ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,482 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+var Card = Container.expand(function (cardData) {
+ var self = Container.call(this);
+ self.cardData = cardData || {
+ type: 'herbivore',
+ name: 'Basic Herbivore',
+ health: 3,
+ effect: 'none'
+ };
+ // Create card background
+ var cardBg = self.attachAsset('cardBase', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Create card content based on type
+ var cardContent;
+ if (self.cardData.type === 'herbivore') {
+ cardContent = self.attachAsset('herbivoreCard', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ } else if (self.cardData.type === 'carnivore') {
+ cardContent = self.attachAsset('carnivoreCard', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ } else {
+ cardContent = self.attachAsset('eventCard', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ }
+ // Add text labels
+ self.nameText = new Text2(self.cardData.name, {
+ size: 24,
+ fill: 0xFFFFFF
+ });
+ self.nameText.anchor.set(0.5, 0);
+ self.nameText.x = 0;
+ self.nameText.y = -100;
+ self.addChild(self.nameText);
+ if (self.cardData.health) {
+ self.healthText = new Text2("HP: " + self.cardData.health, {
+ size: 20,
+ fill: 0xFFFFFF
+ });
+ self.healthText.anchor.set(0.5, 0);
+ self.healthText.x = 0;
+ self.healthText.y = 80;
+ self.addChild(self.healthText);
+ }
+ self.currentHealth = self.cardData.health || 0;
+ self.gridX = -1;
+ self.gridY = -1;
+ self.isInPlay = false;
+ self.takeDamage = function (amount) {
+ self.currentHealth -= amount;
+ if (self.healthText) {
+ self.healthText.setText("HP: " + self.currentHealth);
+ }
+ if (self.currentHealth <= 0) {
+ self.die();
+ }
+ };
+ self.die = function () {
+ if (self.isInPlay) {
+ // Remove from grid
+ if (gameBoard[self.gridY] && gameBoard[self.gridY][self.gridX]) {
+ gameBoard[self.gridY][self.gridX] = null;
+ }
+ // Add event card to deck
+ addEventCardToDeck();
+ // Visual death effect
+ tween(self, {
+ alpha: 0,
+ scaleX: 0.5,
+ scaleY: 0.5
+ }, {
+ duration: 500,
+ onFinish: function onFinish() {
+ if (self.parent) {
+ self.parent.removeChild(self);
+ }
+ }
+ });
+ LK.getSound('creatureDie').play();
+ }
+ };
+ self.down = function (x, y, obj) {
+ if (!self.isInPlay && playerHand.indexOf(self) !== -1) {
+ selectedCard = self;
+ draggedCard = self;
+ originalCardPosition = {
+ x: self.x,
+ y: self.y
+ };
+ }
+ };
+ return self;
+});
+var GridCell = Container.expand(function (gridX, gridY) {
+ var self = Container.call(this);
+ self.gridX = gridX;
+ self.gridY = gridY;
+ var cellBg = self.attachAsset('gridCell', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ cellBg.alpha = 0.3;
+ self.card = null;
+ self.isHighlighted = false;
+ self.highlight = function () {
+ if (!self.isHighlighted) {
+ self.isHighlighted = true;
+ cellBg.alpha = 0.6;
+ }
+ };
+ self.unhighlight = function () {
+ if (self.isHighlighted) {
+ self.isHighlighted = false;
+ cellBg.alpha = 0.3;
+ }
+ };
+ self.down = function (x, y, obj) {
+ if (selectedCard && !self.card) {
+ // Place card on this cell
+ placeCardOnGrid(selectedCard, self.gridX, self.gridY);
+ }
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x1a252f
+});
+
+/****
+* Game Code
+****/
+// Game state variables
+var currentRound = 1;
+var maxRounds = 5;
+var cardsDrawnThisTurn = 0;
+var maxCardsPerTurn = 3;
+var gameBoard = [];
+var boardWidth = 4;
+var boardHeight = 3;
+var gridCells = [];
+var playerHand = [];
+var maxHandSize = 5;
+var mainDeck = [];
+var selectedCard = null;
+var draggedCard = null;
+var originalCardPosition = null;
+// UI Elements
+var roundText = new Text2("Round: " + currentRound, {
+ size: 48,
+ fill: 0xFFFFFF
+});
+roundText.anchor.set(0.5, 0);
+LK.gui.top.addChild(roundText);
+roundText.y = 100;
+var cardsDrawnText = new Text2("Cards Drawn: " + cardsDrawnThisTurn + "/" + maxCardsPerTurn, {
+ size: 36,
+ fill: 0xFFFFFF
+});
+cardsDrawnText.anchor.set(0, 0);
+LK.gui.topRight.addChild(cardsDrawnText);
+cardsDrawnText.x = -300;
+cardsDrawnText.y = 150;
+var deckCountText = new Text2("Deck: " + mainDeck.length, {
+ size: 36,
+ fill: 0xFFFFFF
+});
+deckCountText.anchor.set(0, 0);
+LK.gui.topLeft.addChild(deckCountText);
+deckCountText.x = 120;
+deckCountText.y = 150;
+// Initialize game board
+function initializeBoard() {
+ // Create 2D array for board state
+ for (var y = 0; y < boardHeight; y++) {
+ gameBoard[y] = [];
+ for (var x = 0; x < boardWidth; x++) {
+ gameBoard[y][x] = null;
+ }
+ }
+ // Create visual grid cells
+ var startX = 1024 - boardWidth * 220 / 2 + 110;
+ var startY = 800;
+ for (var y = 0; y < boardHeight; y++) {
+ gridCells[y] = [];
+ for (var x = 0; x < boardWidth; x++) {
+ var cell = new GridCell(x, y);
+ cell.x = startX + x * 220;
+ cell.y = startY + y * 280;
+ game.addChild(cell);
+ gridCells[y][x] = cell;
+ }
+ }
+}
+// Create initial deck
+function createInitialDeck() {
+ mainDeck = [];
+ // Add herbivores
+ for (var i = 0; i < 8; i++) {
+ mainDeck.push({
+ type: 'herbivore',
+ name: 'Herbivore ' + (i + 1),
+ health: 2 + Math.floor(i / 2),
+ effect: 'grow'
+ });
+ }
+ // Add carnivores
+ for (var i = 0; i < 6; i++) {
+ mainDeck.push({
+ type: 'carnivore',
+ name: 'Carnivore ' + (i + 1),
+ health: 3 + Math.floor(i / 2),
+ effect: 'hunt'
+ });
+ }
+ // Shuffle deck
+ shuffleDeck();
+}
+function shuffleDeck() {
+ for (var i = mainDeck.length - 1; i > 0; i--) {
+ var j = Math.floor(Math.random() * (i + 1));
+ var temp = mainDeck[i];
+ mainDeck[i] = mainDeck[j];
+ mainDeck[j] = temp;
+ }
+}
+function drawCard() {
+ if (cardsDrawnThisTurn >= maxCardsPerTurn) {
+ return null;
+ }
+ if (mainDeck.length === 0) {
+ endRound();
+ return null;
+ }
+ if (playerHand.length >= maxHandSize) {
+ return null;
+ }
+ var cardData = mainDeck.pop();
+ var card = new Card(cardData);
+ playerHand.push(card);
+ cardsDrawnThisTurn++;
+ // Position card in hand
+ updateHandPositions();
+ game.addChild(card);
+ // Update UI
+ cardsDrawnText.setText("Cards Drawn: " + cardsDrawnThisTurn + "/" + maxCardsPerTurn);
+ deckCountText.setText("Deck: " + mainDeck.length);
+ LK.getSound('cardDraw').play();
+ return card;
+}
+function updateHandPositions() {
+ var handY = 2400;
+ var handStartX = 1024 - playerHand.length * 200 / 2 + 100;
+ for (var i = 0; i < playerHand.length; i++) {
+ var card = playerHand[i];
+ if (!card.isInPlay) {
+ tween(card, {
+ x: handStartX + i * 200,
+ y: handY
+ }, {
+ duration: 300
+ });
+ }
+ }
+}
+function placeCardOnGrid(card, gridX, gridY) {
+ if (!card || gameBoard[gridY][gridX] !== null) {
+ return false;
+ }
+ // Remove card from hand
+ var handIndex = playerHand.indexOf(card);
+ if (handIndex !== -1) {
+ playerHand.splice(handIndex, 1);
+ }
+ // Place on board
+ gameBoard[gridY][gridX] = card;
+ card.gridX = gridX;
+ card.gridY = gridY;
+ card.isInPlay = true;
+ // Position card visually
+ var targetX = gridCells[gridY][gridX].x;
+ var targetY = gridCells[gridY][gridX].y;
+ tween(card, {
+ x: targetX,
+ y: targetY
+ }, {
+ duration: 300
+ });
+ // Apply card effect
+ applyCardEffect(card);
+ // Update hand positions
+ updateHandPositions();
+ // Clear selection
+ selectedCard = null;
+ draggedCard = null;
+ // Reset turn
+ cardsDrawnThisTurn = 0;
+ cardsDrawnText.setText("Cards Drawn: " + cardsDrawnThisTurn + "/" + maxCardsPerTurn);
+ LK.getSound('cardPlace').play();
+ return true;
+}
+function applyCardEffect(card) {
+ if (card.cardData.type === 'carnivore' && card.cardData.effect === 'hunt') {
+ // Hunt nearby herbivores
+ var neighbors = getNeighbors(card.gridX, card.gridY);
+ for (var i = 0; i < neighbors.length; i++) {
+ var neighbor = neighbors[i];
+ if (neighbor && neighbor.cardData.type === 'herbivore') {
+ neighbor.takeDamage(1);
+ }
+ }
+ } else if (card.cardData.type === 'herbivore' && card.cardData.effect === 'grow') {
+ // Grow and strengthen nearby herbivores
+ var neighbors = getNeighbors(card.gridX, card.gridY);
+ for (var i = 0; i < neighbors.length; i++) {
+ var neighbor = neighbors[i];
+ if (neighbor && neighbor.cardData.type === 'herbivore') {
+ neighbor.currentHealth += 1;
+ if (neighbor.healthText) {
+ neighbor.healthText.setText("HP: " + neighbor.currentHealth);
+ }
+ }
+ }
+ }
+}
+function getNeighbors(gridX, gridY) {
+ var neighbors = [];
+ var directions = [{
+ x: -1,
+ y: 0
+ }, {
+ x: 1,
+ y: 0
+ }, {
+ x: 0,
+ y: -1
+ }, {
+ x: 0,
+ y: 1
+ }];
+ for (var i = 0; i < directions.length; i++) {
+ var newX = gridX + directions[i].x;
+ var newY = gridY + directions[i].y;
+ if (newX >= 0 && newX < boardWidth && newY >= 0 && newY < boardHeight) {
+ neighbors.push(gameBoard[newY][newX]);
+ }
+ }
+ return neighbors;
+}
+function addEventCardToDeck() {
+ var eventCard = {
+ type: 'event',
+ name: 'Environmental Change',
+ effect: 'disaster'
+ };
+ // Insert event card randomly in deck
+ var insertIndex = Math.floor(Math.random() * (mainDeck.length + 1));
+ mainDeck.splice(insertIndex, 0, eventCard);
+ deckCountText.setText("Deck: " + mainDeck.length);
+}
+function endRound() {
+ currentRound++;
+ if (currentRound > maxRounds) {
+ // Game complete
+ LK.showYouWin();
+ return;
+ }
+ // Reshuffle deck with remaining cards
+ var cardsOnBoard = [];
+ for (var y = 0; y < boardHeight; y++) {
+ for (var x = 0; x < boardWidth; x++) {
+ if (gameBoard[y][x]) {
+ cardsOnBoard.push(gameBoard[y][x].cardData);
+ }
+ }
+ }
+ // Create new deck for next round
+ createInitialDeck();
+ // Reset turn counter
+ cardsDrawnThisTurn = 0;
+ // Update UI
+ roundText.setText("Round: " + currentRound);
+ cardsDrawnText.setText("Cards Drawn: " + cardsDrawnThisTurn + "/" + maxCardsPerTurn);
+ deckCountText.setText("Deck: " + mainDeck.length);
+}
+// Draw card button functionality
+var drawButton = LK.getAsset('cardBase', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 0.8,
+ scaleY: 0.8
+});
+var drawButtonText = new Text2("DRAW", {
+ size: 32,
+ fill: 0xFFFFFF
+});
+drawButtonText.anchor.set(0.5, 0.5);
+drawButton.addChild(drawButtonText);
+drawButton.x = 1700;
+drawButton.y = 2400;
+game.addChild(drawButton);
+drawButton.down = function () {
+ drawCard();
+};
+// Game move handler
+game.move = function (x, y, obj) {
+ if (draggedCard) {
+ draggedCard.x = x;
+ draggedCard.y = y;
+ // Highlight valid placement cells
+ for (var gridY = 0; gridY < boardHeight; gridY++) {
+ for (var gridX = 0; gridX < boardWidth; gridX++) {
+ var cell = gridCells[gridY][gridX];
+ if (!gameBoard[gridY][gridX] && Math.abs(cell.x - x) < 110 && Math.abs(cell.y - y) < 130) {
+ cell.highlight();
+ } else {
+ cell.unhighlight();
+ }
+ }
+ }
+ }
+};
+game.up = function (x, y, obj) {
+ if (draggedCard) {
+ var placed = false;
+ // Check if card was dropped on a valid cell
+ for (var gridY = 0; gridY < boardHeight && !placed; gridY++) {
+ for (var gridX = 0; gridX < boardWidth && !placed; gridX++) {
+ var cell = gridCells[gridY][gridX];
+ if (!gameBoard[gridY][gridX] && Math.abs(cell.x - x) < 110 && Math.abs(cell.y - y) < 130) {
+ placed = placeCardOnGrid(draggedCard, gridX, gridY);
+ }
+ }
+ }
+ // If not placed, return to original position
+ if (!placed && originalCardPosition) {
+ tween(draggedCard, originalCardPosition, {
+ duration: 300
+ });
+ }
+ // Clear highlights
+ for (var gridY = 0; gridY < boardHeight; gridY++) {
+ for (var gridX = 0; gridX < boardWidth; gridX++) {
+ gridCells[gridY][gridX].unhighlight();
+ }
+ }
+ draggedCard = null;
+ originalCardPosition = null;
+ }
+};
+// Initialize game
+initializeBoard();
+createInitialDeck();
+// Draw initial cards
+for (var i = 0; i < 3; i++) {
+ drawCard();
+}
+game.update = function () {
+ // Update UI elements
+ deckCountText.setText("Deck: " + mainDeck.length);
+ // Check win/lose conditions
+ if (mainDeck.length === 0 && playerHand.length === 0) {
+ endRound();
+ }
+};
\ No newline at end of file