Compare commits

...

3 Commits

Author SHA1 Message Date
Kacper Kostka (aider)
22adaeb700 feat: Modify planner to place random buildings in random locations 2025-04-02 22:39:45 +02:00
Kacper Kostka (aider)
18ac996f65 feat: Add Planner citizen type with automated city expansion 2025-04-02 22:33:18 +02:00
Kacper Kostka (aider)
3e4622fa0e feat: Add wolf packs spawning at map corners 2025-04-02 13:50:38 +02:00
5 changed files with 156 additions and 4 deletions

88
ai.js
View File

@ -263,6 +263,9 @@ function assignNewTask(cit) {
case "Soldier":
soldierTasks(cit);
break;
case "Planner":
plannerTasks(cit);
break;
default:
cit.task = null;
cit.target = null;
@ -385,9 +388,94 @@ function soldierTasks(cit) {
builderTasks(cit);
}
function plannerTasks(cit) {
// Randomly place buildings with no planning
if(Math.random() < 0.05) {
cit.task = "planBuilding";
cit.target = null;
return;
}
// Just wander around when not placing buildings
cit.task = null;
cit.target = null;
}
/**********************************************************************
* NEW TASK HANDLERS
**********************************************************************/
function planBuildingTask(cit) {
// Choose a completely random building type
const buildingTypes = ["House", "Road", "Market", "Hospital", "School"];
const buildingType = buildingTypes[Math.floor(Math.random() * buildingTypes.length)];
// Set cost based on building type
let buildingCost = 0;
switch (buildingType) {
case "House": buildingCost = COST_HOUSE; break;
case "Road": buildingCost = COST_ROAD; break;
case "Market": buildingCost = COST_MARKET; break;
case "Hospital": buildingCost = COST_HOSPITAL; break;
case "School": buildingCost = COST_SCHOOL; break;
}
// Check if we can afford it
if (money < buildingCost) {
cit.task = null;
return;
}
// Choose a completely random location
let randomX, randomY;
let attempts = 0;
// Just try random locations until we find one that's not water
do {
randomX = randInt(-1500, 1500);
randomY = randInt(-1500, 1500);
attempts++;
if (attempts > 20) {
// Give up after too many attempts
cit.task = null;
return;
}
} while (!isValidPlacement(randomX, randomY));
// Place the building at the random location
addMoney(-buildingCost, `Planner: ${buildingType}`);
let newBuilding;
switch (buildingType) {
case "House":
newBuilding = createHouseSite(randomX, randomY);
break;
case "Road":
// Just make a random road segment
newBuilding = createRoadSite(
randomX,
randomY,
randomX + randInt(-100, 100),
randomY + randInt(-100, 100)
);
break;
case "Market":
newBuilding = createMarketSite(randomX, randomY);
break;
case "Hospital":
newBuilding = createHospitalSite(randomX, randomY);
break;
case "School":
newBuilding = createSchoolSite(randomX, randomY);
break;
}
buildings.push(newBuilding);
logAction(`${cit.name} [Planner] randomly placed a ${buildingType} at (${Math.floor(randomX)}, ${Math.floor(randomY)})`);
cit.task = null;
}
function huntWolfTask(cit) {
let wolf = cit.target;
if(!wolf || wolf.dead) {

View File

@ -96,6 +96,11 @@ function setupBuyButtons() {
logAction("Click on map to place a new Soldier citizen.");
});
document.getElementById('buyPlannerBtn').addEventListener('click', () => {
purchaseMode = "Planner";
logAction("Click on map to place a new Planner citizen.");
});
document.getElementById('buyMarketBtn').addEventListener('click', () => {
purchaseMode = "Market";
logAction("Click on map to place a Market site.");
@ -395,6 +400,17 @@ function setupCanvasClick() {
}
break;
case "Planner":
if(money >= COST_PLANNER) {
addMoney(-COST_PLANNER, "Buy Planner");
let c = createCitizen(randomName(), worldX, worldY, "Planner");
citizens.push(c);
logAction(`Purchased new Planner @(${Math.floor(worldX)},${Math.floor(worldY)})`);
} else {
logAction("Not enough money to buy Planner!");
}
break;
case "Spawner":
if(money >= COST_SPAWNER) {
addMoney(-COST_SPAWNER, "Buy Spawner");

54
game.js
View File

@ -36,6 +36,7 @@ const COST_SCHOOL = 450;
const COST_SPAWNER = 500;
const COST_TREE = 50;
const COST_SOLDIER = 250;
const COST_PLANNER = 1000;
// Terrain costs
const COST_WATER = 20;
@ -90,19 +91,51 @@ const SCHOOL_WOOD_REQUIRED = 65;
const SCHOOL_BUILD_RATE = 0.12;
// Professions
const PROFESSIONS = ["Farmer", "Builder", "Merchant", "Doctor", "Teacher", "Soldier"];
const PROFESSIONS = ["Farmer", "Builder", "Merchant", "Doctor", "Teacher", "Soldier", "Planner"];
// Animals
const STARTING_RABBITS = 10;
const STARTING_WOLVES = 3;
const STARTING_WOLVES = 5;
const RABBIT_HUNGER_INCREMENT = 0.003;
const RABBIT_REPRO_COOLDOWN = 3000;
const RABBIT_REPRO_CHANCE = 0.0005;
const RABBIT_REPRO_COOLDOWN = 5000;
const RABBIT_REPRO_CHANCE = 0.0002;
const WOLF_SPEED = 0.7; // Faster than rabbits
/**********************************************************************
* INIT WORLD
**********************************************************************/
// Function to spawn wolves at the corners of the map
function spawnWolvesAtCorners() {
const corners = [
{ x: -1800, y: -1800 },
{ x: -1800, y: 1800 },
{ x: 1800, y: -1800 },
{ x: 1800, y: 1800 }
];
corners.forEach(corner => {
// Try to find valid placement near the corner
let x, y;
let attempts = 0;
do {
x = corner.x + randInt(-100, 100);
y = corner.y + randInt(-100, 100);
attempts++;
// Give up after too many attempts
if (attempts > 20) break;
} while (!isValidPlacement(x, y));
// If we found a valid spot, spawn 3 wolves there
if (attempts <= 20) {
for (let i = 0; i < 3; i++) {
const wolf = createAnimal("Wolf", x + randInt(-50, 50), y + randInt(-50, 50));
animals.push(wolf);
}
logAction(`A pack of wolves has appeared near (${Math.floor(x)}, ${Math.floor(y)})!`);
}
});
}
function initWorld() {
// Normal trees - only on land
for(let i=0; i<15; i++) {
@ -152,6 +185,19 @@ function initWorld() {
} while (!isValidPlacement(x, y));
animals.push(createAnimal("Wolf", x, y));
}
// Spawn wolves at the corners of the map
spawnWolvesAtCorners();
// Spawn additional wolves in random locations
for(let i=0; i<5; i++) {
let x, y;
do {
x = randInt(-1500,1500);
y = randInt(-1500,1500);
} while (!isValidPlacement(x, y));
animals.push(createAnimal("Wolf", x, y));
}
requestAnimationFrame(update);
}

View File

@ -194,6 +194,7 @@
<button class="menu-button" id="buyDoctorBtn">Buy Doctor ($200)</button>
<button class="menu-button" id="buyTeacherBtn">Buy Teacher ($180)</button>
<button class="menu-button" id="buySoldierBtn">Buy Soldier ($250)</button>
<button class="menu-button" id="buyPlannerBtn">Buy Planner ($1000)</button>
</div>
<div class="menu-category">

View File

@ -372,6 +372,7 @@ function drawCitizen(c) {
case "Doctor": icon = "💉"; break;
case "Teacher": icon = "📚"; break;
case "Soldier": icon = "⚔️"; break;
case "Planner": icon = "🏗️"; break;
}
ctx.fillStyle = "#000";