User prompt
when the player adds a new card to play any links that are already in place that go to that cards position must be checked. if the card has changed from herbivore to carnivore then all the links are now invalid and must 'fall off'. think of any similar 'fall off' triggers and implement code to handle the checks and the fall off animation etc βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
ok lets add that later on when all the mechanics are properly in place - remind me later on please. Next step is the link markers...I want them to be more user-controlled. Do not create the links, just have the markers 'light up' during the 'dusk' phase and then allow the player to mouse over them and show a highlight for all valid cards to link to. then the player should be able to hold left mouse and drag each link 1 at a time to the valid card that they want and then release the link marker when the cursor is above the chosen card and then a graphical 'link' should be created from the carnivore to the herbivore chosen if valid. if a link marker cannot be legally linked at all then it should highlight in a different colour and should have text appear within it saying 'N/A'. please implement βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
nice - a few things: one time during play i received 6 or 8 cards in the draw phase for some reason, implement code so that maximum hand is 3. Extinction markers 'persist' meaning that once an extinction marker is placed upon a creature it stays until the creature leaves play or another creature is played on top of it. lets also implement the 'scry' rule: If a round is completed by the player without any creatures 'going extinct' then during the 'draw' phase as the new round is set up, the player receives the 'scry' marker (light up the work in the UI). the player may 'spend' the scry marker at any time during the turn that they want, it allows them to take the top 3 cards of the main deck into their hand for their viewing, when ready the player clicks the 'ready to return cards' pop up that appears and for each of the 3 cards added to their hand the player returns it either to the top of the main deck, the bottom of the main deck or the main deck discard pile, the scry word in the UI goes dim again and is once again available to 'win' if the player finishes a round having no creatures gone extinct. if this all makes sense then please go ahead and implement βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'indexOf')' in or related to this line: 'if (creature.climateRequirement.indexOf('/') !== -1) {' Line Number: 1060
User prompt
implement code to move automatically thru any phases where no action can be taken, with visual cues to the player. Also create placeholder decks for the event cards (basic deck and advanced deck) 10 cards in each please with a number added to the UI which displays how many are in the main deck discard and how many are in the main deck βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
implement code so that when player plays the last card they must play (if they reveal multiple event cards) or plays the 1 card they can, the other cards are discarded and the phase progresses to 'noon'
User prompt
Please fix the bug: 'TypeError: setTimeout is not a function' in or related to this line: 'setTimeout(function () {' Line Number: 1809
User prompt
excellent! implement the turn structure please and also remove the 8 card hand limit we put in to debug βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
perfect, 1 small note - carnivores only receive 1 'extinction marker' a turn no matter how many links they are under their 'sated' state. now go ahead and implement the link mechanic and then I will give you the rules for turn phases. βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
advanced creatures should only be placed on stacks where no other creature is present, at the moment they can be placed on empty advanced terrain cards which is incorrect. is the best way to fix this either: 1 - add code to prevent advanced creatures from being placed on stacks without creatures or 2 - add code which makes advanced creature cards perform a 'check' for required creature cards before placement?
User prompt
excellent! almost all fixed! Modify code so that basic carnivore cards cannot be placed onto advanced carnivore cards
User prompt
the advanced terrain cards are still causing placement issues. it seems that no creature cards can be placed upon them at the moment. please fix this issue
User prompt
please fix issue where player cannot place a creature cards correctly onto advanced terrain cards
User prompt
modify code on 'basic creature carnivore' cards to allow placement directly onto advanced terrain cards. also modify code on 'advanced creature herbivore' cards to only allow placement on 'advanced terrain' cards with a 'basic creature herbivore' on the top of the stack.
User prompt
in accordance then with your above reply, go ahead and implement the new property for all cards to incorporate: 'Level' at either 'Basic' or 'Advanced'. thank you
User prompt
now the basic creature cards cannot be placed upon advanced terrain cards again. they should be able to be placed upon advanced terrain. fix please
User prompt
whatever you changed in the last step has now made advanced carnivore cards have a placement issue too, please look at what you modified just now and find out why the advanced carnivores broke. the advanced herbivores are still not placing properly
User prompt
good we are almost there! now the advanced carnivores work correctly but the advanced herbivores still do not. i cant think why this may be so please look at their code and compare it to the advanced carnivore code. why not copy the code for the placement logic from the advanced carnivore onto the advanced herbivore cards, changing the part that says they can be placed on basic carnivores to say basic herbivores and remove the part where they can be placed upon advanced herbivores too.
User prompt
neither the advanced carnivores nor the advanced herbivores can be placed correctly yet. there is an issue somewhere in their code...both types of basic creatures work fine so lets simply copy their placement logic and add a requirement for the terrain to be 'advanced' and a further requirement for the top creature card of the stack to be either a basic herbivore when placing an advanced herbivore, or a basic carnivore/advanced herbivore when placing an advanced carnivore. would you like me to re-iterate the rules here or try to clarify?
User prompt
i still have the same issue: unable to place advanced herbivore cards when i should be able to
User prompt
i still cannot place advanced herbivores at all. they should be allowed to be placed according to these rules: 1: They may only be placed if the stack contains an advanced terrain card and there is a basic herbivore card on the top. 2: all their terrain and climate requirements must be met.
User prompt
there is an issue: i cannot place advanced herbivores at all, please check their code and make sure i can place them
User prompt
good. we have an issue where a basic carnivore card should be allowed to be placed upon a basic herbivore card but because the herbivore is on top of an advanced Terrain it is not allowing it. So modify the code for placing creatures thus: when placing a basic creature, the type 'Basic' or 'Advanced' with reference to 'terrain' does not matter since a basic creature can be placed upon either a basic or advanced terrain card, so perhaps basic creatures should not have a 'check' for whether the terrain is basic or advanced but just the check for type and sub-type and climate. also debug/modify basic herbivore cards so that they cannot be placed upon basic herbivore cards
User prompt
still an issue with placing basic creatures onto empty advanced terrain. perhaps i have caused an error in the code by at times calling the 'terrain' cards 'land' cards? they are 'terrain' cards and I have accidently written 'land' a few times before (such as in the previous command). The 'terrain' cards hierarchy thus; Type: 'Terrain' card; Sub types: 'Land' or 'Water'; Sub-sub-types: nested in 'water': 'Fresh' or 'sea', nested in 'land': 'Mountains', 'Hills' or 'Flat land'. please check code for any incorrect wording and adjust
User prompt
there is still a problem when attempting to place a basic creature onto an advanced land if there is no creature already present. please debug and make this possible: a basic creature can be placed onto a basic or an advanced land whether there is a creature already present or not
/****
* 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',
level: 'Basic',
dietType: 'herbivore',
name: 'Basic Herbivore',
terrainRequirement: 'land',
climateRequirement: 'any'
};
// Create creature visual
var creatureAsset;
if (self.creatureData.level === 'Basic' && self.creatureData.dietType === 'herbivore') {
creatureAsset = self.attachAsset('creatureBasicHerbivore', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (self.creatureData.level === 'Advanced' && self.creatureData.dietType === 'herbivore') {
creatureAsset = self.attachAsset('creatureAdvancedHerbivore', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (self.creatureData.level === 'Basic' && self.creatureData.dietType === 'carnivore') {
creatureAsset = self.attachAsset('creatureBasicCarnivore', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (self.creatureData.level === '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.level === 'Basic' && self.creatureData.dietType === 'herbivore') {
typeStripAsset = 'creatureTypeBasicHerbivore';
} else if (self.creatureData.level === 'Advanced' && self.creatureData.dietType === 'herbivore') {
typeStripAsset = 'creatureTypeAdvancedHerbivore';
} else if (self.creatureData.level === 'Basic' && self.creatureData.dietType === 'carnivore') {
typeStripAsset = 'creatureTypeBasicCarnivore';
} else if (self.creatureData.level === '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 = 60;
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);
showPossibleMoves(self);
} else {
// Mouse moved away from this card
if (hoveredCard === self) {
hideCardInfo();
hidePossibleMoves();
}
}
}
};
self.down = function (x, y, obj) {
if (!self.isInPlay && playerHand.indexOf(self) !== -1) {
selectedCard = self;
draggedCard = self;
originalCardPosition = {
x: self.x,
y: self.y
};
showPossibleMoves(self);
}
};
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.pinkBorder = null;
self.highlight = function () {
if (!self.isHighlighted && self.terrainCard) {
self.isHighlighted = true;
// Create pink border around the terrain card
if (!self.pinkBorder) {
self.pinkBorder = LK.getAsset('terrainLandFlat', {
anchorX: 0.5,
anchorY: 0.5
});
self.pinkBorder.tint = 0xFF1493; // Brighter deep pink color
self.pinkBorder.alpha = 0.9;
// Scale border to be larger than terrain card
self.pinkBorder.scaleX = self.terrainCard.scaleX * 1.3;
self.pinkBorder.scaleY = self.terrainCard.scaleY * 1.3;
self.pinkBorder.x = self.terrainCard.x;
self.pinkBorder.y = self.terrainCard.y;
// Add border behind terrain card
var terrainIndex = game.getChildIndex(self.terrainCard);
game.addChildAt(self.pinkBorder, terrainIndex);
}
}
};
self.unhighlight = function () {
if (self.isHighlighted) {
self.isHighlighted = false;
// Remove pink border
if (self.pinkBorder && self.pinkBorder.parent) {
self.pinkBorder.parent.removeChild(self.pinkBorder);
self.pinkBorder = null;
}
}
};
self.down = function (x, y, obj) {
if (selectedCard && selectedCard.creatureData && self.terrainCard && canPlaceCreatureOnTerrain(selectedCard, self.terrainCard)) {
placeCreatureOnStack(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',
level: '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.level === '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: 0x000000,
font: "'Arial Black', 'Impact', 'Tahoma', sans-serif"
});
self.typeText.anchor.set(0.5, 0.5);
self.typeText.x = 0;
self.typeText.y = -147;
self.addChild(self.typeText);
// Advanced terrain cards already have the terrain type text, no need for duplicate text
// Add requirement text for advanced terrain cards
if (self.terrainData.level === '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);
showPossibleMoves(self);
} else {
// Mouse moved away from this card
if (hoveredCard === self) {
hideCardInfo();
hidePossibleMoves();
}
}
}
};
self.down = function (x, y, obj) {
if (!self.isInPlay && playerHand.indexOf(self) !== -1) {
selectedCard = self;
draggedCard = self;
originalCardPosition = {
x: self.x,
y: self.y
};
showPossibleMoves(self);
}
};
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 = 8;
var mainDeck = [];
var basicTerrainPool = [];
var selectedCard = null;
var draggedCard = null;
var originalCardPosition = null;
var scryTokenActive = true;
var cardInfoText = null;
var hoveredCard = null;
var drawPhase = 'initial'; // 'initial', 'forced'
var cardsDrawnInPhase = [];
var discardPile = [];
// 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',
level: 'Basic',
subtype: 'water',
waterType: 'sea',
climate: null // Will be assigned during setup
});
}
for (var i = 0; i < 3; i++) {
basicTerrainPool.push({
type: 'basic',
level: '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',
level: 'Basic',
subtype: 'land',
landType: 'mountain',
climate: null // Will be assigned during setup
});
}
for (var i = 0; i < 5; i++) {
basicTerrainPool.push({
type: 'basic',
level: 'Basic',
subtype: 'land',
landType: 'hills',
climate: null // Will be assigned during setup
});
}
for (var i = 0; i < 5; i++) {
basicTerrainPool.push({
type: 'basic',
level: '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',
level: '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',
level: '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',
level: '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',
level: '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',
level: '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',
level: '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',
level: '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',
level: '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',
level: '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 + " | Level: " + creature.level + " " + 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.level + " " + (terrain.landType || terrain.waterType);
infoString += " | Level: " + terrain.level + " 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 showPossibleMoves(card) {
if (card.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(card, terrain)) {
planetSlots[gridY][gridX].highlight();
}
}
}
} else if (card.terrainData) {
// Highlight valid terrain placement for advanced terrain
for (var gridY = 0; gridY < planetHeight; gridY++) {
for (var gridX = 0; gridX < planetWidth; gridX++) {
var existingTerrain = planetBoard[gridY][gridX];
if (existingTerrain && canPlaceTerrainOnTerrain(card, existingTerrain)) {
planetSlots[gridY][gridX].highlight();
}
}
}
}
}
function hidePossibleMoves() {
for (var gridY = 0; gridY < planetHeight; gridY++) {
for (var gridX = 0; gridX < planetWidth; gridX++) {
if (planetSlots[gridY][gridX]) {
planetSlots[gridY][gridX].unhighlight();
}
}
}
}
function hasValidPlacements(cards) {
for (var i = 0; i < cards.length; i++) {
var card = cards[i];
if (card.creatureData) {
// Check creature placements
for (var gridY = 0; gridY < planetHeight; gridY++) {
for (var gridX = 0; gridX < planetWidth; gridX++) {
var terrain = planetBoard[gridY][gridX];
if (terrain && canPlaceCreatureOnTerrain(card, terrain)) {
return true;
}
}
}
} else if (card.terrainData) {
// Check terrain placements
for (var gridY = 0; gridY < planetHeight; gridY++) {
for (var gridX = 0; gridX < planetWidth; gridX++) {
var terrain = planetBoard[gridY][gridX];
if (terrain && canPlaceTerrainOnTerrain(card, terrain)) {
return true;
}
}
}
}
}
return false;
}
function discardCards(cards) {
for (var i = 0; i < cards.length; i++) {
var card = cards[i];
// Remove from hand
var handIndex = playerHand.indexOf(card);
if (handIndex !== -1) {
playerHand.splice(handIndex, 1);
}
// Remove from game
if (card.parent) {
card.parent.removeChild(card);
}
// Add to discard pile
discardPile.push(card);
}
updateHandPositions();
}
function drawCard() {
if (mainDeck.length === 0) {
endRound();
return null;
}
if (playerHand.length >= maxHandSize && drawPhase !== 'forced') {
return null;
}
if (drawPhase === 'complete') {
return null; // Draw phase already complete
}
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);
}
if (drawPhase === 'initial') {
// Initial draw phase - draw up to 3 cards
playerHand.push(card);
cardsDrawnInPhase.push(card);
cardsDrawnThisTurn++;
if (cardsDrawnInPhase.length >= 3) {
// Check if any of the 3 cards have valid placements
if (!hasValidPlacements(cardsDrawnInPhase)) {
// Discard all 3 cards and enter forced draw phase
discardCards(cardsDrawnInPhase);
cardsDrawnInPhase = [];
drawPhase = 'forced';
// Continue drawing in forced phase
return drawCard();
} else {
// At least one card has valid placement, end draw phase
drawPhase = 'complete';
}
}
} else if (drawPhase === 'forced') {
// Forced draw phase - draw one card at a time until playable
if (hasValidPlacements([card])) {
// This card can be played, add to hand and must be played
playerHand.push(card);
drawPhase = 'complete';
// Mark this card as must play
card.mustPlay = true;
} else {
// Card cannot be played, discard it and draw another
discardCards([card]);
return drawCard();
}
} else {
return null; // Draw phase complete
}
// 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 startDrawPhase() {
if (mainDeck.length === 0) {
endRound();
return;
}
drawPhase = 'initial';
cardsDrawnInPhase = [];
cardsDrawnThisTurn = 0;
// Draw initial 3 cards
for (var i = 0; i < 3; i++) {
if (mainDeck.length > 0) {
drawCard();
}
}
}
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.level !== 'Advanced') return false;
// Check if target is a basic terrain card
if (!basicTerrain || basicTerrain.level !== '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 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;
}
// For advanced creatures, terrain must be advanced
if (creature.level === 'Advanced') {
if (terrain.level !== 'Advanced') return false;
}
// Basic creatures can be placed on any terrain type (basic or advanced)
// Check creature stacking rules
if (terrainCard.creatureStack.length > 0) {
var topCreatureInStack = terrainCard.creatureStack[terrainCard.creatureStack.length - 1];
// Basic creature stacking rules
if (creature.level === 'Basic') {
// Basic herbivore restrictions
if (creature.dietType === 'herbivore') {
if (topCreatureInStack.creatureData.level === 'Basic' && topCreatureInStack.creatureData.dietType === 'herbivore') {
return false; // Basic herbivores cannot be placed on stacks with other basic herbivores at top
}
if (topCreatureInStack.creatureData.level === 'Basic' && topCreatureInStack.creatureData.dietType === 'carnivore') {
return false; // Basic herbivores cannot be placed on stacks with basic carnivores at top
}
}
// Basic carnivore restrictions
if (creature.dietType === 'carnivore') {
if (topCreatureInStack.creatureData.level === 'Basic' && topCreatureInStack.creatureData.dietType === 'carnivore') {
return false; // Basic carnivores cannot be placed on stacks with other basic carnivores at top
}
}
}
// Advanced creature stacking rules
else if (creature.level === 'Advanced') {
// Advanced herbivores can be placed on stacks with basic herbivores at top
if (creature.dietType === 'herbivore') {
var validTarget = topCreatureInStack.creatureData && topCreatureInStack.creatureData.level === 'Basic' && topCreatureInStack.creatureData.dietType === 'herbivore';
if (!validTarget) return false;
}
// Advanced carnivores can be placed on stacks with basic carnivores OR advanced herbivores at top
else if (creature.dietType === 'carnivore') {
var validTarget = topCreatureInStack.creatureData && topCreatureInStack.creatureData.level === 'Basic' && topCreatureInStack.creatureData.dietType === 'carnivore' || topCreatureInStack.creatureData && topCreatureInStack.creatureData.level === 'Advanced' && topCreatureInStack.creatureData.dietType === 'herbivore';
if (!validTarget) return false;
}
}
} else {
// No creatures in stack - advanced creatures need something to stack on
if (creature.level === 'Advanced') {
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 at specific z-index (above basic terrain but below creatures)
var basicTerrainIndex = game.getChildIndex(basicTerrainCard);
game.addChildAt(advancedTerrainCard, basicTerrainIndex + 1);
// Update creature positions if any exist and ensure they stay on top
for (var i = 0; i < advancedTerrainCard.creatureStack.length; i++) {
var creature = advancedTerrainCard.creatureStack[i];
// Store current position to prevent unwanted movement
var currentX = creature.x;
var currentY = creature.y;
// Remove and re-add creature to ensure it's on top
game.removeChild(creature);
game.addChild(creature);
// Keep creature at its current position - no animation needed
creature.x = currentX;
creature.y = currentY;
}
// Update hand positions
updateHandPositions();
// Clear selection
selectedCard = null;
draggedCard = null;
// Reset draw phase after successful placement
if (advancedTerrainCard.mustPlay) {
drawPhase = 'complete';
}
// Reset turn
cardsDrawnThisTurn = 0;
cardsDrawnText.setText("Cards Drawn: " + cardsDrawnThisTurn + "/" + maxCardsPerTurn);
LK.getSound('cardPlace').play();
return true;
}
function placeCreatureOnStack(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);
}
// Push existing creatures down in the stack (move them south)
var stackOffset = 20;
for (var i = 0; i < terrainCard.creatureStack.length; i++) {
var existingCreature = terrainCard.creatureStack[i];
tween(existingCreature, {
y: existingCreature.y + stackOffset
}, {
duration: 200
});
}
// Add new creature to top of stack
terrainCard.creatureStack.push(creatureCard);
creatureCard.gridX = gridX;
creatureCard.gridY = gridY;
creatureCard.isInPlay = true;
// Position new creature at the top position (where first creature would go)
var targetX = terrainCard.x;
var colorBarHeight = 42;
var targetY = terrainCard.y - terrainCard.height * terrainCard.scaleY / 2 + colorBarHeight + 150; // Position even lower, just below the color bar with 150px offset
// Calculate scale needed to match terrain card dimensions completely
var terrainWidth = 252; // Terrain card asset width
var terrainHeight = 336; // Terrain card asset height
var creatureWidth = 160; // Creature card asset width
var creatureHeight = 220; // Creature card asset height
// Scale to match terrain dimensions exactly, but reduce Y scale by half the color bar height with moderate scaling
var targetScaleX = terrainWidth / creatureWidth * terrainCard.scaleX;
var targetScaleY = (terrainHeight - colorBarHeight / 2) / creatureHeight * terrainCard.scaleY * 0.95; // Moderate 5% reduction to sit flush with color bar
// Start with small scale and animate up to target scale like advanced terrain
creatureCard.scaleX = 0.1;
creatureCard.scaleY = 0.1;
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 draw phase after successful placement
if (creatureCard.mustPlay) {
drawPhase = 'complete';
}
// Reset turn
cardsDrawnThisTurn = 0;
cardsDrawnText.setText("Cards Drawn: " + cardsDrawnThisTurn + "/" + maxCardsPerTurn);
LK.getSound('cardPlace').play();
return true;
}
function applyCreatureEffect(creatureCard) {
var creature = creatureCard.creatureData;
// Stack 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 and draw phase
cardsDrawnThisTurn = 0;
drawPhase = 'complete';
cardsDrawnInPhase = [];
// 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 () {
if (drawPhase === 'complete' || drawPhase === undefined) {
startDrawPhase();
} else if (drawPhase === 'initial' && cardsDrawnInPhase.length < 3) {
// Continue drawing in initial phase
drawCard();
} else if (drawPhase === 'forced') {
// Continue drawing in forced phase
drawCard();
}
};
// Game move handler
game.move = function (x, y, obj) {
if (draggedCard) {
draggedCard.x = x;
draggedCard.y = y;
// Ensure dragged card is always on top
game.removeChild(draggedCard);
game.addChild(draggedCard);
// Highlights are already shown from the card's down event
} 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();
hidePossibleMoves();
}
}
};
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 = placeCreatureOnStack(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
hidePossibleMoves();
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
@@ -9,45 +9,46 @@
var CreatureCard = Container.expand(function (creatureData) {
var self = Container.call(this);
self.creatureData = creatureData || {
type: 'basic',
+ level: 'Basic',
dietType: 'herbivore',
name: 'Basic Herbivore',
terrainRequirement: 'land',
climateRequirement: 'any'
};
// Create creature visual
var creatureAsset;
- if (self.creatureData.type === 'basic' && self.creatureData.dietType === 'herbivore') {
+ if (self.creatureData.level === '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') {
+ } else if (self.creatureData.level === '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') {
+ } else if (self.creatureData.level === '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') {
+ } else if (self.creatureData.level === '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') {
+ if (self.creatureData.level === 'Basic' && self.creatureData.dietType === 'herbivore') {
typeStripAsset = 'creatureTypeBasicHerbivore';
- } else if (self.creatureData.type === 'advanced' && self.creatureData.dietType === 'herbivore') {
+ } else if (self.creatureData.level === 'Advanced' && self.creatureData.dietType === 'herbivore') {
typeStripAsset = 'creatureTypeAdvancedHerbivore';
- } else if (self.creatureData.type === 'basic' && self.creatureData.dietType === 'carnivore') {
+ } else if (self.creatureData.level === 'Basic' && self.creatureData.dietType === 'carnivore') {
typeStripAsset = 'creatureTypeBasicCarnivore';
- } else if (self.creatureData.type === 'advanced' && self.creatureData.dietType === 'carnivore') {
+ } else if (self.creatureData.level === 'Advanced' && self.creatureData.dietType === 'carnivore') {
typeStripAsset = 'creatureTypeAdvancedCarnivore';
}
if (typeStripAsset) {
var typeStrip = self.attachAsset(typeStripAsset, {
@@ -184,8 +185,9 @@
var TerrainCard = Container.expand(function (terrainData) {
var self = Container.call(this);
self.terrainData = terrainData || {
type: 'basic',
+ level: 'Basic',
subtype: 'land',
landType: 'flat',
waterType: null,
climate: 'temperate'
@@ -222,9 +224,9 @@
});
}
}
// Add terrain type indicator strip at top
- var terrainStripAsset = self.terrainData.type === 'advanced' ? 'advancedTerrainStrip' : 'basicTerrainStrip';
+ var terrainStripAsset = self.terrainData.level === 'Advanced' ? 'advancedTerrainStrip' : 'basicTerrainStrip';
var terrainStrip = self.attachAsset(terrainStripAsset, {
anchorX: 0.5,
anchorY: 0.5
});
@@ -241,9 +243,9 @@
self.typeText.y = -147;
self.addChild(self.typeText);
// Advanced terrain cards already have the terrain type text, no need for duplicate text
// Add requirement text for advanced terrain cards
- if (self.terrainData.type === 'advanced' && self.terrainData.climateRequirement) {
+ if (self.terrainData.level === 'Advanced' && self.terrainData.climateRequirement) {
self.requirementText = new Text2("Req: " + self.terrainData.climateRequirement, {
size: 16,
fill: 0xFFFFFF
});
@@ -364,16 +366,18 @@
// Add 9 water cards: 6 sea, 3 fresh
for (var i = 0; i < 6; i++) {
basicTerrainPool.push({
type: 'basic',
+ level: 'Basic',
subtype: 'water',
waterType: 'sea',
climate: null // Will be assigned during setup
});
}
for (var i = 0; i < 3; i++) {
basicTerrainPool.push({
type: 'basic',
+ level: 'Basic',
subtype: 'water',
waterType: 'fresh',
climate: null // Will be assigned during setup
});
@@ -381,24 +385,27 @@
// Add 14 land cards: 4 mountain, 5 hills, 5 flat
for (var i = 0; i < 4; i++) {
basicTerrainPool.push({
type: 'basic',
+ level: 'Basic',
subtype: 'land',
landType: 'mountain',
climate: null // Will be assigned during setup
});
}
for (var i = 0; i < 5; i++) {
basicTerrainPool.push({
type: 'basic',
+ level: 'Basic',
subtype: 'land',
landType: 'hills',
climate: null // Will be assigned during setup
});
}
for (var i = 0; i < 5; i++) {
basicTerrainPool.push({
type: 'basic',
+ level: 'Basic',
subtype: 'land',
landType: 'flat',
climate: null // Will be assigned during setup
});
@@ -499,8 +506,9 @@
// 2x Fresh Water (no climate requirement)
for (var i = 0; i < 2; i++) {
mainDeck.push({
type: 'advanced',
+ level: 'Advanced',
cardType: 'terrain',
subtype: 'water',
waterType: 'fresh',
name: 'Advanced Fresh Water ' + (i + 1),
@@ -511,8 +519,9 @@
var seaClimateReqs = ['cold', 'hot', 'temperate', 'temperate/hot', 'any'];
for (var i = 0; i < 5; i++) {
mainDeck.push({
type: 'advanced',
+ level: 'Advanced',
cardType: 'terrain',
subtype: 'water',
waterType: 'sea',
name: 'Advanced Sea Water ' + (i + 1),
@@ -523,8 +532,9 @@
var mountainClimateReqs = ['any', 'temperate/cold', 'temperate/hot'];
for (var i = 0; i < 3; i++) {
mainDeck.push({
type: 'advanced',
+ level: 'Advanced',
cardType: 'terrain',
subtype: 'land',
landType: 'mountain',
name: 'Advanced Mountain ' + (i + 1),
@@ -535,8 +545,9 @@
var hillsClimateReqs = ['hot', 'cold', 'temperate', 'temperate/hot', 'temperate/cold'];
for (var i = 0; i < 5; i++) {
mainDeck.push({
type: 'advanced',
+ level: 'Advanced',
cardType: 'terrain',
subtype: 'land',
landType: 'hills',
name: 'Advanced Hills ' + (i + 1),
@@ -547,8 +558,9 @@
var flatClimateReqs = ['cold', 'temperate', 'hot', 'temperate/hot', 'temperate/cold'];
for (var i = 0; i < 5; i++) {
mainDeck.push({
type: 'advanced',
+ level: 'Advanced',
cardType: 'terrain',
subtype: 'land',
landType: 'flat',
name: 'Advanced Flat Land ' + (i + 1),
@@ -560,8 +572,9 @@
for (var i = 0; i < 32; i++) {
var climateReq = herbivoreClimateReqs[i % herbivoreClimateReqs.length];
mainDeck.push({
type: 'basic',
+ level: 'Basic',
cardType: 'creature',
dietType: 'herbivore',
name: 'Basic Herbivore ' + (i + 1),
terrainRequirement: 'land',
@@ -573,8 +586,9 @@
for (var i = 0; i < 12; i++) {
var climateReq = advHerbClimateReqs[i % advHerbClimateReqs.length];
mainDeck.push({
type: 'advanced',
+ level: 'Advanced',
cardType: 'creature',
dietType: 'herbivore',
name: 'Advanced Herbivore ' + (i + 1),
terrainRequirement: 'land',
@@ -586,8 +600,9 @@
for (var i = 0; i < 10; i++) {
var climateReq = carnivoreClimateReqs[i % carnivoreClimateReqs.length];
mainDeck.push({
type: 'basic',
+ level: 'Basic',
cardType: 'creature',
dietType: 'carnivore',
name: 'Basic Carnivore ' + (i + 1),
terrainRequirement: 'any',
@@ -599,8 +614,9 @@
for (var i = 0; i < 8; i++) {
var climateReq = advCarnClimateReqs[i % advCarnClimateReqs.length];
mainDeck.push({
type: 'advanced',
+ level: 'Advanced',
cardType: 'creature',
dietType: 'carnivore',
name: 'Advanced Carnivore ' + (i + 1),
terrainRequirement: 'any',
@@ -628,9 +644,9 @@
if (card.creatureData) {
// Creature card information
var creature = card.creatureData;
if (creature) {
- infoString = creature.name + " | Type: " + creature.type + " " + creature.dietType;
+ infoString = creature.name + " | Level: " + creature.level + " " + creature.dietType;
if (creature && creature.terrainRequirement && creature.terrainRequirement !== 'any') {
infoString += " | Terrain: " + creature.terrainRequirement;
}
if (creature && creature.climateRequirement && creature.climateRequirement !== 'any') {
@@ -640,10 +656,10 @@
} 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";
+ infoString = terrain.name || terrain.level + " " + (terrain.landType || terrain.waterType);
+ infoString += " | Level: " + terrain.level + " terrain";
if (terrain.climateRequirement && terrain.climateRequirement !== 'any') {
infoString += " | Climate Required: " + terrain.climateRequirement;
}
}
@@ -842,11 +858,11 @@
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;
+ if (!advancedTerrain || advancedTerrain.level !== 'Advanced') return false;
// Check if target is a basic terrain card
- if (!basicTerrain || basicTerrain.type !== 'basic') return false;
+ if (!basicTerrain || basicTerrain.level !== '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') {
@@ -903,49 +919,49 @@
}
if (!climateMatches) return false;
}
// For advanced creatures, terrain must be advanced
- if (creature.type === 'advanced') {
- if (terrain.type !== 'advanced') return false;
+ if (creature.level === 'Advanced') {
+ if (terrain.level !== 'Advanced') return false;
}
// Basic creatures can be placed on any terrain type (basic or advanced)
// Check creature stacking rules
if (terrainCard.creatureStack.length > 0) {
var topCreatureInStack = terrainCard.creatureStack[terrainCard.creatureStack.length - 1];
// Basic creature stacking rules
- if (creature.type === 'basic') {
+ if (creature.level === 'Basic') {
// Basic herbivore restrictions
if (creature.dietType === 'herbivore') {
- if (topCreatureInStack.creatureData.type === 'basic' && topCreatureInStack.creatureData.dietType === 'herbivore') {
+ if (topCreatureInStack.creatureData.level === 'Basic' && topCreatureInStack.creatureData.dietType === 'herbivore') {
return false; // Basic herbivores cannot be placed on stacks with other basic herbivores at top
}
- if (topCreatureInStack.creatureData.type === 'basic' && topCreatureInStack.creatureData.dietType === 'carnivore') {
+ if (topCreatureInStack.creatureData.level === 'Basic' && topCreatureInStack.creatureData.dietType === 'carnivore') {
return false; // Basic herbivores cannot be placed on stacks with basic carnivores at top
}
}
// Basic carnivore restrictions
if (creature.dietType === 'carnivore') {
- if (topCreatureInStack.creatureData.type === 'basic' && topCreatureInStack.creatureData.dietType === 'carnivore') {
+ if (topCreatureInStack.creatureData.level === 'Basic' && topCreatureInStack.creatureData.dietType === 'carnivore') {
return false; // Basic carnivores cannot be placed on stacks with other basic carnivores at top
}
}
}
// Advanced creature stacking rules
- else if (creature.type === 'advanced') {
+ else if (creature.level === 'Advanced') {
// Advanced herbivores can be placed on stacks with basic herbivores at top
if (creature.dietType === 'herbivore') {
- var validTarget = topCreatureInStack.creatureData && topCreatureInStack.creatureData.type === 'basic' && topCreatureInStack.creatureData.dietType === 'herbivore';
+ var validTarget = topCreatureInStack.creatureData && topCreatureInStack.creatureData.level === 'Basic' && topCreatureInStack.creatureData.dietType === 'herbivore';
if (!validTarget) return false;
}
// Advanced carnivores can be placed on stacks with basic carnivores OR advanced herbivores at top
else if (creature.dietType === 'carnivore') {
- var validTarget = topCreatureInStack.creatureData && topCreatureInStack.creatureData.type === 'basic' && topCreatureInStack.creatureData.dietType === 'carnivore' || topCreatureInStack.creatureData && topCreatureInStack.creatureData.type === 'advanced' && topCreatureInStack.creatureData.dietType === 'herbivore';
+ var validTarget = topCreatureInStack.creatureData && topCreatureInStack.creatureData.level === 'Basic' && topCreatureInStack.creatureData.dietType === 'carnivore' || topCreatureInStack.creatureData && topCreatureInStack.creatureData.level === 'Advanced' && topCreatureInStack.creatureData.dietType === 'herbivore';
if (!validTarget) return false;
}
}
} else {
// No creatures in stack - advanced creatures need something to stack on
- if (creature.type === 'advanced') {
+ if (creature.level === 'Advanced') {
return false;
}
}
return true;