User prompt
implement possible moves highlighted with a pink border on the board for all cards βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
modify all cards so that when they are dragged onto the play area they are always shown above everything else (at the moment they sometimes dissapear below cards already in play before the mouse button is released, while dragging
User prompt
there is an issue when placing an advanced terrain onto a stack with a basic creature: the terrain is correctly placed but the creature moves up for some reason, please prevent this from happening when a terrain is added βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
change the rules for advanced terrain so that when they are placed, they will always go on top of the basic terrain card but beneath any and all the creature cards also present there
User prompt
perfect - well done! please change the rules for basic herbivore cards so that they cannot be played onto another basic herbivore card
User prompt
creature cards still do not scale up correctly when played...they must scale up to completely cover the terrain card beneath it βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
the creature cards must scale up when played in order to correctly match the size/scale of the card they are being played upon. make them follow the same scaling rules as the advanced terrain cards use please βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
please match the way that all creature cards resize when played onto the board with the way that advanced terrain cards currently work - the advanced terrain cards increase in scale when played correctly, the other card types must match this please βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
please make the creature cards scale up just like the advanced lands do when being placed βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
this is brilliant! well done on solving the issues! a similar issue with the card being too small when placed, is happening with the creature cards, so please make them also resize to the same size as the basic terrain cards which are on the board, but also - when a creature is placed it should be offset down by the height of the colour bar at the top of the terrain cards, so that the colour bar of the land it is being placed upon will still be visible. please implement now βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
please remove the 'health' parameter from all creature cards. this is not part of my game
User prompt
good, now make it so that when an advanced terrain is placed it completely covers the basic terrain (adopts its dimentions and scale)
User prompt
good, now the advanced terrain can be played but they make the existing basic terrain disappear, they should go on top of the basic terrain completely covering the basic terrain card. please implement
User prompt
i still cannot place advanced territories on the board...troubleshoot problems please
User prompt
implement code to allow advanced herbivores to be placed onto basic herbivores if terrain requirements are also satisfied
User prompt
i keep getting an error when attempting to place any advanced land card - please fix
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'terrainRequirement')' in or related to this line: 'if (creature.terrainRequirement !== 'any') {' Line Number: 748
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'terrainRequirement')' in or related to this line: 'if (creature.terrainRequirement !== 'any') {' Line Number: 748
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'terrainRequirement')' in or related to this line: 'if (creature.terrainRequirement !== 'any') {' Line Number: 748
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'terrainRequirement')' in or related to this line: 'if (creature.terrainRequirement !== 'any') {' Line Number: 746
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'terrainRequirement')' in or related to this line: 'if (creature.terrainRequirement !== 'any') {' Line Number: 746
User prompt
please fix issue where the info text for the card in hand on mouse-over does not change to the new card havered over. It should change to reflect the information on whatever card the pointer is hovering over
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'terrainRequirement')' in or related to this line: 'if (creature.terrainRequirement !== 'any') {' Line Number: 728
User prompt
the cards are too small to see in the hand zone, please implement an information function which triggers when the player mouses over a card in hand, where the cards information is displayed in text along the bottom of the screen
User prompt
good, the basic creatures seem to function well and can be dragged to relevant spaces on the board but the advanced terrain cards have 2 problems: they appear larger in the hand, and they cannot be clicked or dragged at all. please fix these issues. Also, please add text to the creature cards and advanced terrain cards to display their requirements
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var CreatureCard = Container.expand(function (creatureData) {
var self = Container.call(this);
self.creatureData = creatureData || {
type: 'basic',
dietType: 'herbivore',
name: 'Basic Herbivore',
terrainRequirement: 'land',
climateRequirement: 'any'
};
// Create creature visual
var creatureAsset;
if (self.creatureData.type === 'basic' && self.creatureData.dietType === 'herbivore') {
creatureAsset = self.attachAsset('creatureBasicHerbivore', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (self.creatureData.type === 'advanced' && self.creatureData.dietType === 'herbivore') {
creatureAsset = self.attachAsset('creatureAdvancedHerbivore', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (self.creatureData.type === 'basic' && self.creatureData.dietType === 'carnivore') {
creatureAsset = self.attachAsset('creatureBasicCarnivore', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (self.creatureData.type === 'advanced' && self.creatureData.dietType === 'carnivore') {
creatureAsset = self.attachAsset('creatureAdvancedCarnivore', {
anchorX: 0.5,
anchorY: 0.5
});
}
// Add creature type color band at bottom
var typeStripAsset;
if (self.creatureData.type === 'basic' && self.creatureData.dietType === 'herbivore') {
typeStripAsset = 'creatureTypeBasicHerbivore';
} else if (self.creatureData.type === 'advanced' && self.creatureData.dietType === 'herbivore') {
typeStripAsset = 'creatureTypeAdvancedHerbivore';
} else if (self.creatureData.type === 'basic' && self.creatureData.dietType === 'carnivore') {
typeStripAsset = 'creatureTypeBasicCarnivore';
} else if (self.creatureData.type === 'advanced' && self.creatureData.dietType === 'carnivore') {
typeStripAsset = 'creatureTypeAdvancedCarnivore';
}
if (typeStripAsset) {
var typeStrip = self.attachAsset(typeStripAsset, {
anchorX: 0.5,
anchorY: 0.5
});
typeStrip.y = 95; // Position at bottom of creature card
}
// Add creature name
self.nameText = new Text2(self.creatureData.name, {
size: 18,
fill: 0xFFFFFF
});
self.nameText.anchor.set(0.5, 0);
self.nameText.x = 0;
self.nameText.y = -100;
self.addChild(self.nameText);
// Add requirement text
var reqText = "Req: ";
if (self.creatureData.terrainRequirement && self.creatureData.terrainRequirement !== 'any') {
reqText += self.creatureData.terrainRequirement;
}
if (self.creatureData.climateRequirement && self.creatureData.climateRequirement !== 'any') {
if (reqText !== "Req: ") reqText += ", ";
reqText += self.creatureData.climateRequirement;
}
if (reqText !== "Req: ") {
self.requirementText = new Text2(reqText, {
size: 14,
fill: 0xFFFFFF
});
self.requirementText.anchor.set(0.5, 0);
self.requirementText.x = 0;
self.requirementText.y = 100;
self.addChild(self.requirementText);
}
self.isInPlay = false;
self.die = function () {
if (self.isInPlay) {
// 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.move = function (x, y, obj) {
if (!self.isInPlay && playerHand.indexOf(self) !== -1) {
// Check if mouse is actually over this card
var cardBounds = 80; // Half card width for hit detection
if (Math.abs(x) < cardBounds && Math.abs(y) < 110) {
// Half card height
showCardInfo(self);
} else {
// Mouse moved away from this card
if (hoveredCard === self) {
hideCardInfo();
}
}
}
};
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 PlanetSlot = Container.expand(function (slotX, slotY) {
var self = Container.call(this);
self.slotX = slotX;
self.slotY = slotY;
self.terrainCard = null;
self.isHighlighted = false;
self.highlight = function () {
if (!self.isHighlighted && self.terrainCard) {
self.isHighlighted = true;
self.terrainCard.alpha = 0.8;
}
};
self.unhighlight = function () {
if (self.isHighlighted && self.terrainCard) {
self.isHighlighted = false;
self.terrainCard.alpha = 1.0;
}
};
self.down = function (x, y, obj) {
if (selectedCard && selectedCard.creatureData && self.terrainCard && canPlaceCreatureOnTerrain(selectedCard, self.terrainCard)) {
placeCreatureOnTerrain(selectedCard, self.terrainCard, self.slotX, self.slotY);
}
};
return self;
});
var TerrainCard = Container.expand(function (terrainData) {
var self = Container.call(this);
self.terrainData = terrainData || {
type: 'basic',
subtype: 'land',
landType: 'flat',
waterType: null,
climate: 'temperate'
};
// Create terrain card visual based on subtype and landType/waterType
var terrainAsset;
if (self.terrainData.subtype === 'land') {
if (self.terrainData.landType === 'flat') {
terrainAsset = self.attachAsset('terrainLandFlat', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (self.terrainData.landType === 'hills') {
terrainAsset = self.attachAsset('terrainLandHills', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (self.terrainData.landType === 'mountain') {
terrainAsset = self.attachAsset('terrainLandMountain', {
anchorX: 0.5,
anchorY: 0.5
});
}
} else if (self.terrainData.subtype === 'water') {
if (self.terrainData.waterType === 'sea') {
terrainAsset = self.attachAsset('terrainWaterSea', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (self.terrainData.waterType === 'fresh') {
terrainAsset = self.attachAsset('terrainWaterFresh', {
anchorX: 0.5,
anchorY: 0.5
});
}
}
// Add terrain type indicator strip at top
var terrainStripAsset = self.terrainData.type === 'advanced' ? 'advancedTerrainStrip' : 'basicTerrainStrip';
var terrainStrip = self.attachAsset(terrainStripAsset, {
anchorX: 0.5,
anchorY: 0.5
});
terrainStrip.y = -147;
// Add terrain type text
var terrainTypeText = self.terrainData.subtype === 'land' ? self.terrainData.landType : self.terrainData.waterType;
self.typeText = new Text2(terrainTypeText.toUpperCase(), {
size: 24,
fill: 0xFFFFFF,
font: "'Arial Black', 'Impact', 'Tahoma', sans-serif"
});
self.typeText.anchor.set(0.5, 0.5);
self.typeText.x = 0;
self.typeText.y = -84;
self.addChild(self.typeText);
// Add requirement text for advanced terrain cards
if (self.terrainData.type === 'advanced' && self.terrainData.climateRequirement) {
self.requirementText = new Text2("Req: " + self.terrainData.climateRequirement, {
size: 16,
fill: 0xFFFFFF
});
self.requirementText.anchor.set(0.5, 0);
self.requirementText.x = 0;
self.requirementText.y = 120;
self.addChild(self.requirementText);
}
// Climate will be displayed as row background instead of on individual cards
self.gridX = -1;
self.gridY = -1;
self.creatureStack = [];
self.move = function (x, y, obj) {
if (!self.isInPlay && playerHand.indexOf(self) !== -1) {
// Check if mouse is actually over this card (scaled terrain cards are smaller)
var cardBounds = 75; // Adjusted for scaled terrain cards
if (Math.abs(x) < cardBounds && Math.abs(y) < 100) {
showCardInfo(self);
} else {
// Mouse moved away from this card
if (hoveredCard === self) {
hideCardInfo();
}
}
}
};
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;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a252f
});
/****
* Game Code
****/
// UI elements
// Event card asset
// Creature card assets
// Climate indicator strips
// Terrain card assets - Water types with blue/grey strip
// Terrain card assets - Land types with green strip
// Game state variables
var currentRound = 0;
var maxRounds = 5;
var cardsDrawnThisTurn = 0;
var maxCardsPerTurn = 3;
var planetBoard = [];
var planetSlots = [];
var playerHand = [];
var maxHandSize = 5;
var mainDeck = [];
var basicTerrainPool = [];
var selectedCard = null;
var draggedCard = null;
var originalCardPosition = null;
var scryTokenActive = true;
var cardInfoText = null;
var hoveredCard = null;
// Planet layout: 2-4-6-4-2 formation
var planetLayout = [2, 4, 6, 4, 2];
var planetWidth = 6; // Max cards in any row
var planetHeight = 5; // Number of rows
// 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;
var scryText = new Text2("Scry", {
size: 32,
fill: 0x00FF00
});
scryText.anchor.set(0, 0);
LK.gui.topRight.addChild(scryText);
scryText.x = -300;
scryText.y = 190;
// Initialize basic terrain pool (23 cards total)
function createBasicTerrainPool() {
basicTerrainPool = [];
// Add 9 water cards: 6 sea, 3 fresh
for (var i = 0; i < 6; i++) {
basicTerrainPool.push({
type: 'basic',
subtype: 'water',
waterType: 'sea',
climate: null // Will be assigned during setup
});
}
for (var i = 0; i < 3; i++) {
basicTerrainPool.push({
type: 'basic',
subtype: 'water',
waterType: 'fresh',
climate: null // Will be assigned during setup
});
}
// Add 14 land cards: 4 mountain, 5 hills, 5 flat
for (var i = 0; i < 4; i++) {
basicTerrainPool.push({
type: 'basic',
subtype: 'land',
landType: 'mountain',
climate: null // Will be assigned during setup
});
}
for (var i = 0; i < 5; i++) {
basicTerrainPool.push({
type: 'basic',
subtype: 'land',
landType: 'hills',
climate: null // Will be assigned during setup
});
}
for (var i = 0; i < 5; i++) {
basicTerrainPool.push({
type: 'basic',
subtype: 'land',
landType: 'flat',
climate: null // Will be assigned during setup
});
}
// Shuffle terrain pool
for (var i = basicTerrainPool.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = basicTerrainPool[i];
basicTerrainPool[i] = basicTerrainPool[j];
basicTerrainPool[j] = temp;
}
}
// Setup planet board with terrain cards
function setupPlanet() {
// Create 2D array for planet board
for (var y = 0; y < planetHeight; y++) {
planetBoard[y] = [];
planetSlots[y] = [];
for (var x = 0; x < planetWidth; x++) {
planetBoard[y][x] = null;
planetSlots[y][x] = null;
}
}
// Place terrain cards according to 2-4-6-4-2 layout
var terrainIndex = 0;
var startY = 400;
var cardSpacing = 320;
// Add climate row backgrounds first
for (var row = 0; row < planetLayout.length; row++) {
var climate;
if (row === 0 || row === 4) {
climate = 'cold'; // Rows 1 & 5
} else if (row === 1 || row === 3) {
climate = 'temperate'; // Rows 2 & 4
} else {
climate = 'hot'; // Row 3
}
// Create climate row background
var climateRowAsset = 'climateRow' + climate.charAt(0).toUpperCase() + climate.slice(1);
var climateRowBg = LK.getAsset(climateRowAsset, {
anchorX: 0.5,
anchorY: 0.5
});
climateRowBg.x = 1024; // Center of screen
climateRowBg.y = startY + row * 420;
climateRowBg.alpha = 0.3; // Semi-transparent background
game.addChild(climateRowBg);
// Add climate label text
var climateLabel = new Text2(climate.toUpperCase(), {
size: 32,
fill: 0x000000,
font: "'Arial Black', 'Impact', 'Tahoma', sans-serif"
});
climateLabel.anchor.set(0.5, 0.5);
climateLabel.rotation = -Math.PI / 2; // Rotate 90 degrees counter-clockwise to make vertical
climateLabel.x = 50; // Move left to make fully visible
climateLabel.y = startY + row * 420;
game.addChild(climateLabel);
}
for (var row = 0; row < planetLayout.length; row++) {
var cardsInRow = planetLayout[row];
var startX = 1024 - cardsInRow * cardSpacing / 2 + cardSpacing / 2 + 50; // Shift cards right by 50px
// Assign climate based on row
var climate;
if (row === 0 || row === 4) {
climate = 'cold'; // Rows 1 & 5
} else if (row === 1 || row === 3) {
climate = 'temperate'; // Rows 2 & 4
} else {
climate = 'hot'; // Row 3
}
for (var col = 0; col < cardsInRow && terrainIndex < basicTerrainPool.length; col++) {
// Assign climate to terrain card
var terrainData = basicTerrainPool[terrainIndex];
terrainData.climate = climate;
// Create terrain card
var terrainCard = new TerrainCard(terrainData);
terrainCard.x = startX + col * cardSpacing;
terrainCard.y = startY + row * 420;
terrainCard.gridX = col;
terrainCard.gridY = row;
game.addChild(terrainCard);
// Store in board
var boardX = Math.floor((planetWidth - cardsInRow) / 2) + col;
planetBoard[row][boardX] = terrainCard;
// Create slot for this position
var slot = new PlanetSlot(boardX, row);
slot.terrainCard = terrainCard;
planetSlots[row][boardX] = slot;
terrainIndex++;
}
}
}
// Create main deck with advanced terrain cards and creature cards
function createInitialDeck() {
mainDeck = [];
// Add 20 Advanced Terrain Cards
// 2x Fresh Water (no climate requirement)
for (var i = 0; i < 2; i++) {
mainDeck.push({
type: 'advanced',
cardType: 'terrain',
subtype: 'water',
waterType: 'fresh',
name: 'Advanced Fresh Water ' + (i + 1),
climateRequirement: 'any'
});
}
// 5x Sea Water (1 cold, 1 hot, 1 temperate, 1 temperate/hot, 1 any)
var seaClimateReqs = ['cold', 'hot', 'temperate', 'temperate/hot', 'any'];
for (var i = 0; i < 5; i++) {
mainDeck.push({
type: 'advanced',
cardType: 'terrain',
subtype: 'water',
waterType: 'sea',
name: 'Advanced Sea Water ' + (i + 1),
climateRequirement: seaClimateReqs[i]
});
}
// 3x Mountain (1 any, 1 temperate/cold, 1 temperate/hot)
var mountainClimateReqs = ['any', 'temperate/cold', 'temperate/hot'];
for (var i = 0; i < 3; i++) {
mainDeck.push({
type: 'advanced',
cardType: 'terrain',
subtype: 'land',
landType: 'mountain',
name: 'Advanced Mountain ' + (i + 1),
climateRequirement: mountainClimateReqs[i]
});
}
// 5x Hills (1 hot, 1 cold, 1 temperate, 1 temperate/hot, 1 temperate/cold)
var hillsClimateReqs = ['hot', 'cold', 'temperate', 'temperate/hot', 'temperate/cold'];
for (var i = 0; i < 5; i++) {
mainDeck.push({
type: 'advanced',
cardType: 'terrain',
subtype: 'land',
landType: 'hills',
name: 'Advanced Hills ' + (i + 1),
climateRequirement: hillsClimateReqs[i]
});
}
// 5x Flat Land (1 cold, 1 temperate, 1 hot, 1 temperate/hot, 1 temperate/cold)
var flatClimateReqs = ['cold', 'temperate', 'hot', 'temperate/hot', 'temperate/cold'];
for (var i = 0; i < 5; i++) {
mainDeck.push({
type: 'advanced',
cardType: 'terrain',
subtype: 'land',
landType: 'flat',
name: 'Advanced Flat Land ' + (i + 1),
climateRequirement: flatClimateReqs[i]
});
}
// Add 32 Basic Herbivore Cards
var herbivoreClimateReqs = ['cold', 'temperate', 'hot', 'temperate/hot', 'temperate/cold', 'any'];
for (var i = 0; i < 32; i++) {
var climateReq = herbivoreClimateReqs[i % herbivoreClimateReqs.length];
mainDeck.push({
type: 'basic',
cardType: 'creature',
dietType: 'herbivore',
name: 'Basic Herbivore ' + (i + 1),
terrainRequirement: 'land',
climateRequirement: climateReq
});
}
// Add 12 Advanced Herbivore Cards
var advHerbClimateReqs = ['cold', 'temperate', 'hot', 'temperate/hot'];
for (var i = 0; i < 12; i++) {
var climateReq = advHerbClimateReqs[i % advHerbClimateReqs.length];
mainDeck.push({
type: 'advanced',
cardType: 'creature',
dietType: 'herbivore',
name: 'Advanced Herbivore ' + (i + 1),
terrainRequirement: 'land',
climateRequirement: climateReq
});
}
// Add 10 Basic Carnivore Cards
var carnivoreClimateReqs = ['cold', 'temperate', 'hot', 'temperate/cold', 'any'];
for (var i = 0; i < 10; i++) {
var climateReq = carnivoreClimateReqs[i % carnivoreClimateReqs.length];
mainDeck.push({
type: 'basic',
cardType: 'creature',
dietType: 'carnivore',
name: 'Basic Carnivore ' + (i + 1),
terrainRequirement: 'any',
climateRequirement: climateReq
});
}
// Add 8 Advanced Carnivore Cards
var advCarnClimateReqs = ['cold', 'hot', 'temperate/hot', 'any'];
for (var i = 0; i < 8; i++) {
var climateReq = advCarnClimateReqs[i % advCarnClimateReqs.length];
mainDeck.push({
type: 'advanced',
cardType: 'creature',
dietType: 'carnivore',
name: 'Advanced Carnivore ' + (i + 1),
terrainRequirement: 'any',
climateRequirement: climateReq
});
}
// 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 showCardInfo(card) {
hoveredCard = card;
// Remove existing info text if any
if (cardInfoText && cardInfoText.parent) {
cardInfoText.parent.removeChild(cardInfoText);
}
var infoString = "";
if (card.creatureData) {
// Creature card information
var creature = card.creatureData;
if (creature) {
infoString = creature.name + " | Type: " + creature.type + " " + creature.dietType;
if (creature && creature.terrainRequirement && creature.terrainRequirement !== 'any') {
infoString += " | Terrain: " + creature.terrainRequirement;
}
if (creature && creature.climateRequirement && creature.climateRequirement !== 'any') {
infoString += " | Climate: " + creature.climateRequirement;
}
}
} else if (card.terrainData) {
// Terrain card information
var terrain = card.terrainData;
if (terrain) {
infoString = terrain.name || terrain.type + " " + (terrain.landType || terrain.waterType);
infoString += " | Type: " + terrain.type + " terrain";
if (terrain.climateRequirement && terrain.climateRequirement !== 'any') {
infoString += " | Climate Required: " + terrain.climateRequirement;
}
}
}
// Create info text at bottom of screen
cardInfoText = new Text2(infoString, {
size: 28,
fill: 0xFFFFFF
});
cardInfoText.anchor.set(0.5, 1);
cardInfoText.x = 1024; // Center of screen
cardInfoText.y = 2700; // Bottom of screen
game.addChild(cardInfoText);
}
function hideCardInfo() {
if (cardInfoText && cardInfoText.parent) {
cardInfoText.parent.removeChild(cardInfoText);
cardInfoText = null;
}
hoveredCard = null;
}
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;
// Create appropriate card type based on cardType
if (cardData.cardType === 'terrain') {
card = new TerrainCard(cardData);
// Scale terrain cards in hand to match creature cards
card.scaleX = 0.6;
card.scaleY = 0.6;
} else {
// Default to creature card
card = new CreatureCard(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 canPlaceTerrainOnTerrain(advancedTerrainCard, basicTerrainCard) {
if (!advancedTerrainCard || !basicTerrainCard) return false;
var advancedTerrain = advancedTerrainCard.terrainData;
var basicTerrain = basicTerrainCard.terrainData;
// Check if this is actually an advanced terrain card
if (!advancedTerrain || advancedTerrain.type !== 'advanced') return false;
// Check if target is a basic terrain card
if (!basicTerrain || basicTerrain.type !== 'basic') return false;
// Check if terrain types match (land on land, water on water)
if (advancedTerrain.subtype !== basicTerrain.subtype) return false;
// Check if specific terrain types match
if (advancedTerrain.subtype === 'land') {
if (advancedTerrain.landType !== basicTerrain.landType) return false;
} else if (advancedTerrain.subtype === 'water') {
if (advancedTerrain.waterType !== basicTerrain.waterType) return false;
}
// Check climate requirements
if (advancedTerrain.climateRequirement && advancedTerrain.climateRequirement !== 'any') {
var climateMatches = false;
if (advancedTerrain.climateRequirement.indexOf('/') !== -1) {
// Handle multiple climate requirements (e.g., "temperate/hot")
var allowedClimates = advancedTerrain.climateRequirement.split('/');
for (var k = 0; k < allowedClimates.length; k++) {
if (allowedClimates[k] === basicTerrain.climate) {
climateMatches = true;
break;
}
}
} else {
// Single climate requirement
climateMatches = advancedTerrain.climateRequirement === basicTerrain.climate;
}
if (!climateMatches) return false;
}
return true;
}
function canPlaceCreatureOnTerrain(creatureCard, terrainCard) {
if (!creatureCard || !terrainCard) return false;
var creature = creatureCard.creatureData;
var terrain = terrainCard.terrainData;
// Check if this is actually a creature card
if (!creature) return false;
// Check advanced creature placement rules first
if (creature.type === 'advanced') {
// Advanced creatures require advanced terrain underneath
if (terrain.type !== 'advanced') return false;
// Advanced herbivores can only be placed on basic herbivores
if (creature.dietType === 'herbivore') {
if (terrainCard.creatureStack.length === 0) return false;
var topCreature = terrainCard.creatureStack[terrainCard.creatureStack.length - 1];
if (topCreature.creatureData.type !== 'basic' || topCreature.creatureData.dietType !== 'herbivore') return false;
}
// Advanced carnivores can be placed on basic carnivores OR advanced herbivores
else if (creature.dietType === 'carnivore') {
if (terrainCard.creatureStack.length === 0) return false;
var topCreature = terrainCard.creatureStack[terrainCard.creatureStack.length - 1];
var validTarget = topCreature.creatureData.type === 'basic' && topCreature.creatureData.dietType === 'carnivore' || topCreature.creatureData.type === 'advanced' && topCreature.creatureData.dietType === 'herbivore';
if (!validTarget) return false;
}
}
// Check terrain requirements
if (creature.terrainRequirement !== 'any') {
if (creature.terrainRequirement === 'land' && terrain.subtype !== 'land') return false;
if (creature.terrainRequirement === 'water' && terrain.subtype !== 'water') return false;
}
// Check climate requirements
if (creature.climateRequirement !== 'any') {
var climateMatches = false;
if (creature.climateRequirement.indexOf('/') !== -1) {
// Handle multiple climate requirements (e.g., "temperate/hot")
var allowedClimates = creature.climateRequirement.split('/');
for (var k = 0; k < allowedClimates.length; k++) {
if (allowedClimates[k] === terrain.climate) {
climateMatches = true;
break;
}
}
} else {
// Single climate requirement
climateMatches = creature.climateRequirement === terrain.climate;
}
if (!climateMatches) return false;
}
return true;
}
function placeTerrainOnTerrain(advancedTerrainCard, basicTerrainCard, gridX, gridY) {
if (!canPlaceTerrainOnTerrain(advancedTerrainCard, basicTerrainCard)) {
return false;
}
// Remove card from hand
var handIndex = playerHand.indexOf(advancedTerrainCard);
if (handIndex !== -1) {
playerHand.splice(handIndex, 1);
}
// Set up advanced terrain card
advancedTerrainCard.gridX = gridX;
advancedTerrainCard.gridY = gridY;
advancedTerrainCard.isInPlay = true;
// Copy creature stack from basic terrain to advanced terrain
advancedTerrainCard.creatureStack = basicTerrainCard.creatureStack || [];
// Position advanced terrain card on top of basic terrain and adopt its dimensions
var targetX = basicTerrainCard.x;
var targetY = basicTerrainCard.y;
var targetScaleX = basicTerrainCard.scaleX;
var targetScaleY = basicTerrainCard.scaleY;
tween(advancedTerrainCard, {
x: targetX,
y: targetY,
scaleX: targetScaleX,
scaleY: targetScaleY
}, {
duration: 300
});
// Keep basic terrain underneath but update board references to advanced terrain
planetBoard[gridY][gridX] = advancedTerrainCard;
planetSlots[gridY][gridX].terrainCard = advancedTerrainCard;
// Store reference to basic terrain underneath
advancedTerrainCard.basicTerrainUnderneath = basicTerrainCard;
// Add advanced terrain to game (this will render on top of basic terrain)
game.addChild(advancedTerrainCard);
// Update creature positions if any exist
for (var i = 0; i < advancedTerrainCard.creatureStack.length; i++) {
var creature = advancedTerrainCard.creatureStack[i];
tween(creature, {
x: targetX,
y: targetY - (i + 1) * 20
}, {
duration: 300
});
}
// 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 placeCreatureOnTerrain(creatureCard, terrainCard, gridX, gridY) {
if (!canPlaceCreatureOnTerrain(creatureCard, terrainCard)) {
return false;
}
// Remove card from hand
var handIndex = playerHand.indexOf(creatureCard);
if (handIndex !== -1) {
playerHand.splice(handIndex, 1);
}
// Add to terrain's creature stack
terrainCard.creatureStack.push(creatureCard);
creatureCard.gridX = gridX;
creatureCard.gridY = gridY;
creatureCard.isInPlay = true;
// Position creature card on terrain
var targetX = terrainCard.x;
// Offset down by the height of the color bar (42px) plus stack offset
var colorBarHeight = 42;
var targetY = terrainCard.y + colorBarHeight - terrainCard.creatureStack.length * 20; // Stack offset
// Make creature adopt terrain card dimensions and scale
var targetScaleX = terrainCard.scaleX;
var targetScaleY = terrainCard.scaleY;
tween(creatureCard, {
x: targetX,
y: targetY,
scaleX: targetScaleX,
scaleY: targetScaleY
}, {
duration: 300
});
// Apply creature effects
applyCreatureEffect(creatureCard);
// 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 applyCreatureEffect(creatureCard) {
var creature = creatureCard.creatureData;
// Creature effects can be implemented here without health mechanics
}
function getAdjacentTerrains(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 < planetWidth && newY >= 0 && newY < planetHeight) {
neighbors.push(planetBoard[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
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('terrainLandFlat', {
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;
// Handle creature card highlighting
if (draggedCard.creatureData) {
// Highlight valid terrain placement for creatures
for (var gridY = 0; gridY < planetHeight; gridY++) {
for (var gridX = 0; gridX < planetWidth; gridX++) {
var terrain = planetBoard[gridY][gridX];
if (terrain && canPlaceCreatureOnTerrain(draggedCard, terrain)) {
if (Math.abs(terrain.x - x) < 140 && Math.abs(terrain.y - y) < 168) {
planetSlots[gridY][gridX].highlight();
} else {
planetSlots[gridY][gridX].unhighlight();
}
} else if (terrain) {
planetSlots[gridY][gridX].unhighlight();
}
}
}
} else if (draggedCard.terrainData) {
// Handle terrain card highlighting - check for valid placement spots
for (var gridY = 0; gridY < planetHeight; gridY++) {
for (var gridX = 0; gridX < planetWidth; gridX++) {
var existingTerrain = planetBoard[gridY][gridX];
if (existingTerrain && canPlaceTerrainOnTerrain(draggedCard, existingTerrain)) {
if (Math.abs(existingTerrain.x - x) < 140 && Math.abs(existingTerrain.y - y) < 168) {
planetSlots[gridY][gridX].highlight();
} else {
planetSlots[gridY][gridX].unhighlight();
}
} else if (existingTerrain) {
planetSlots[gridY][gridX].unhighlight();
}
}
}
}
} else {
// Check if mouse is over hand area, if not, hide card info
var handY = 2400;
var inHandArea = y > handY - 150 && y < handY + 150;
if (!inHandArea) {
hideCardInfo();
}
}
};
game.up = function (x, y, obj) {
if (draggedCard) {
var placed = false;
// Check if card was dropped on valid terrain
for (var gridY = 0; gridY < planetHeight && !placed; gridY++) {
for (var gridX = 0; gridX < planetWidth && !placed; gridX++) {
var terrain = planetBoard[gridY][gridX];
if (terrain) {
if (draggedCard.creatureData && canPlaceCreatureOnTerrain(draggedCard, terrain)) {
if (Math.abs(terrain.x - x) < 140 && Math.abs(terrain.y - y) < 168) {
placed = placeCreatureOnTerrain(draggedCard, terrain, gridX, gridY);
}
} else if (draggedCard.terrainData && canPlaceTerrainOnTerrain(draggedCard, terrain)) {
if (Math.abs(terrain.x - x) < 140 && Math.abs(terrain.y - y) < 168) {
placed = placeTerrainOnTerrain(draggedCard, terrain, gridX, gridY);
}
}
}
}
}
// If not placed, return to original position
if (!placed && originalCardPosition) {
tween(draggedCard, originalCardPosition, {
duration: 300
});
}
// Clear all highlights
for (var gridY = 0; gridY < planetHeight; gridY++) {
for (var gridX = 0; gridX < planetWidth; gridX++) {
if (planetSlots[gridY][gridX]) {
planetSlots[gridY][gridX].unhighlight();
}
}
}
draggedCard = null;
originalCardPosition = null;
}
};
// Initialize terrain-based game
createBasicTerrainPool();
setupPlanet();
createInitialDeck();
// Round starts at 0, no initial cards drawn
currentRound = 0;
roundText.setText("Round: " + currentRound);
game.update = function () {
// Update UI elements
deckCountText.setText("Deck: " + mainDeck.length);
// Update scry token display
if (scryTokenActive) {
scryText.setText("Scry");
scryText.fill = 0x00FF00;
} else {
scryText.setText("Scry");
scryText.fill = 0xFF0000;
}
// Check round end conditions
if (mainDeck.length === 0 && playerHand.length === 0) {
endRound();
}
}; ===================================================================
--- original.js
+++ change.js
@@ -839,12 +839,19 @@
creatureCard.gridY = gridY;
creatureCard.isInPlay = true;
// Position creature card on terrain
var targetX = terrainCard.x;
- var targetY = terrainCard.y - terrainCard.creatureStack.length * 20; // Stack offset
+ // Offset down by the height of the color bar (42px) plus stack offset
+ var colorBarHeight = 42;
+ var targetY = terrainCard.y + colorBarHeight - terrainCard.creatureStack.length * 20; // Stack offset
+ // Make creature adopt terrain card dimensions and scale
+ var targetScaleX = terrainCard.scaleX;
+ var targetScaleY = terrainCard.scaleY;
tween(creatureCard, {
x: targetX,
- y: targetY
+ y: targetY,
+ scaleX: targetScaleX,
+ scaleY: targetScaleY
}, {
duration: 300
});
// Apply creature effects