Changeset View
Changeset View
Standalone View
Standalone View
binaries/data/mods/public/simulation/ai/petra/startingStrategy.js
var PETRA = function(m) | (function(m) | ||||
{ | { | ||||
/** | /** | ||||
* determines the strategy to adopt when starting a new game, depending on the initial conditions | * determines the strategy to adopt when starting a new game, depending on the initial conditions | ||||
*/ | */ | ||||
m.HQ.prototype.gameAnalysis = function(gameState) | m.HQ.prototype.gameAnalysis = function(gameState) | ||||
{ | { | ||||
// Analysis of the terrain and the different access regions | // Analysis of the terrain and the different access regions | ||||
▲ Show 20 Lines • Show All 167 Lines • ▼ Show 20 Lines | m.HQ.prototype.regionAnalysis = function(gameState) | ||||
} | } | ||||
let passabilityMap = gameState.getPassabilityMap(); | let passabilityMap = gameState.getPassabilityMap(); | ||||
let totalSize = passabilityMap.width * passabilityMap.width; | let totalSize = passabilityMap.width * passabilityMap.width; | ||||
let minLandSize = Math.floor(0.1*totalSize); | let minLandSize = Math.floor(0.1*totalSize); | ||||
let minWaterSize = Math.floor(0.2*totalSize); | let minWaterSize = Math.floor(0.2*totalSize); | ||||
let cellArea = passabilityMap.cellSize * passabilityMap.cellSize; | let cellArea = passabilityMap.cellSize * passabilityMap.cellSize; | ||||
for (let i = 0; i < accessibility.regionSize.length; ++i) | for (let i = 0; i < accessibility.regionSize.length; ++i) | ||||
{ | |||||
if (landIndex && i == landIndex) | if (landIndex && i == landIndex) | ||||
this.landRegions[i] = true; | this.landRegions[i] = true; | ||||
else if (accessibility.regionType[i] === "land" && cellArea*accessibility.regionSize[i] > 320) | else if (accessibility.regionType[i] === "land" && cellArea*accessibility.regionSize[i] > 320) | ||||
{ | |||||
if (landIndex) | if (landIndex) | ||||
{ | { | ||||
let sea = this.getSeaBetweenIndices(gameState, landIndex, i); | let sea = this.getSeaBetweenIndices(gameState, landIndex, i); | ||||
if (sea && (accessibility.regionSize[i] > minLandSize || accessibility.regionSize[sea] > minWaterSize)) | if (sea && (accessibility.regionSize[i] > minLandSize || accessibility.regionSize[sea] > minWaterSize)) | ||||
{ | { | ||||
this.navalMap = true; | this.navalMap = true; | ||||
this.landRegions[i] = true; | this.landRegions[i] = true; | ||||
this.navalRegions[sea] = true; | this.navalRegions[sea] = true; | ||||
} | } | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
let traject = accessibility.getTrajectToIndex(seaIndex, i); | let traject = accessibility.getTrajectToIndex(seaIndex, i); | ||||
if (traject && traject.length === 2) | if (traject && traject.length === 2) | ||||
{ | { | ||||
this.navalMap = true; | this.navalMap = true; | ||||
this.landRegions[i] = true; | this.landRegions[i] = true; | ||||
this.navalRegions[seaIndex] = true; | this.navalRegions[seaIndex] = true; | ||||
} | } | ||||
} | } | ||||
} | |||||
else if (accessibility.regionType[i] === "water" && accessibility.regionSize[i] > minWaterSize) | else if (accessibility.regionType[i] === "water" && accessibility.regionSize[i] > minWaterSize) | ||||
{ | { | ||||
this.navalMap = true; | this.navalMap = true; | ||||
this.navalRegions[i] = true; | this.navalRegions[i] = true; | ||||
} | } | ||||
else if (accessibility.regionType[i] === "water" && cellArea*accessibility.regionSize[i] > 3600) | else if (accessibility.regionType[i] === "water" && cellArea*accessibility.regionSize[i] > 3600) | ||||
this.navalRegions[i] = true; | this.navalRegions[i] = true; | ||||
} | |||||
if (this.Config.debug < 3) | if (this.Config.debug < 3) | ||||
return true; | return true; | ||||
for (let region in this.landRegions) | for (let region in this.landRegions) | ||||
API3.warn(" >>> zone " + region + " taille " + cellArea*gameState.ai.accessibility.regionSize[region]); | API3.warn(" >>> zone " + region + " taille " + cellArea*gameState.ai.accessibility.regionSize[region]); | ||||
API3.warn(" navalMap " + this.navalMap); | API3.warn(" navalMap " + this.navalMap); | ||||
API3.warn(" landRegions " + uneval(this.landRegions)); | API3.warn(" landRegions " + uneval(this.landRegions)); | ||||
API3.warn(" navalRegions " + uneval(this.navalRegions)); | API3.warn(" navalRegions " + uneval(this.navalRegions)); | ||||
▲ Show 20 Lines • Show All 211 Lines • ▼ Show 20 Lines | m.HQ.prototype.configFirstBase = function(gameState) | ||||
if (this.baseManagers.length < 2) | if (this.baseManagers.length < 2) | ||||
return; | return; | ||||
this.firstBaseConfig = true; | this.firstBaseConfig = true; | ||||
let startingSize = 0; | let startingSize = 0; | ||||
let startingLand = []; | let startingLand = []; | ||||
for (let region in this.landRegions) | for (let region in this.landRegions) | ||||
{ | |||||
for (let base of this.baseManagers) | for (let base of this.baseManagers) | ||||
{ | { | ||||
if (!base.anchor || base.accessIndex != +region) | if (!base.anchor || base.accessIndex != +region) | ||||
continue; | continue; | ||||
startingSize += gameState.ai.accessibility.regionSize[region]; | startingSize += gameState.ai.accessibility.regionSize[region]; | ||||
startingLand.push(base.accessIndex); | startingLand.push(base.accessIndex); | ||||
break; | break; | ||||
} | } | ||||
} | |||||
let cell = gameState.getPassabilityMap().cellSize; | let cell = gameState.getPassabilityMap().cellSize; | ||||
startingSize = startingSize * cell * cell; | startingSize = startingSize * cell * cell; | ||||
if (this.Config.debug > 1) | if (this.Config.debug > 1) | ||||
API3.warn("starting size " + startingSize + "(cut at 24000 for fish pushing)"); | API3.warn("starting size " + startingSize + "(cut at 24000 for fish pushing)"); | ||||
if (startingSize < 25000) | if (startingSize < 25000) | ||||
{ | { | ||||
this.saveSpace = true; | this.saveSpace = true; | ||||
this.Config.Economy.popForDock = Math.min(this.Config.Economy.popForDock, 16); | this.Config.Economy.popForDock = Math.min(this.Config.Economy.popForDock, 16); | ||||
let num = Math.max(this.Config.Economy.targetNumFishers, 2); | let num = Math.max(this.Config.Economy.targetNumFishers, 2); | ||||
for (let land of startingLand) | for (let land of startingLand) | ||||
{ | |||||
for (let sea of gameState.ai.accessibility.regionLinks[land]) | for (let sea of gameState.ai.accessibility.regionLinks[land]) | ||||
if (gameState.ai.HQ.navalRegions[sea]) | if (gameState.ai.HQ.navalRegions[sea]) | ||||
this.navalManager.updateFishingBoats(sea, num); | this.navalManager.updateFishingBoats(sea, num); | ||||
} | |||||
this.maxFields = 1; | this.maxFields = 1; | ||||
this.needCorral = true; | this.needCorral = true; | ||||
} | } | ||||
else if (startingSize < 60000) | else if (startingSize < 60000) | ||||
this.maxFields = 2; | this.maxFields = 2; | ||||
else | else | ||||
this.maxFields = false; | this.maxFields = false; | ||||
// - count the available wood resource, and react accordingly | // - count the available wood resource, and react accordingly | ||||
let startingFood = gameState.getResources().food; | let startingFood = gameState.getResources().food; | ||||
let check = {}; | let check = {}; | ||||
for (let proxim of ["nearby", "medium", "faraway"]) | for (let proxim of ["nearby", "medium", "faraway"]) | ||||
{ | |||||
for (let base of this.baseManagers) | for (let base of this.baseManagers) | ||||
{ | |||||
for (let supply of base.dropsiteSupplies.food[proxim]) | for (let supply of base.dropsiteSupplies.food[proxim]) | ||||
{ | { | ||||
if (check[supply.id]) // avoid double counting as same resource can appear several time | if (check[supply.id]) // avoid double counting as same resource can appear several time | ||||
continue; | continue; | ||||
check[supply.id] = true; | check[supply.id] = true; | ||||
startingFood += supply.ent.resourceSupplyAmount(); | startingFood += supply.ent.resourceSupplyAmount(); | ||||
} | } | ||||
} | |||||
} | |||||
if (startingFood < 800) | if (startingFood < 800) | ||||
{ | |||||
if (startingSize < 25000) | if (startingSize < 25000) | ||||
{ | { | ||||
this.needFish = true; | this.needFish = true; | ||||
this.Config.Economy.popForDock = 1; | this.Config.Economy.popForDock = 1; | ||||
} | } | ||||
else | else | ||||
this.needFarm = true; | this.needFarm = true; | ||||
} | |||||
// - count the available wood resource, and allow rushes only if enough (we should otherwise favor expansion) | // - count the available wood resource, and allow rushes only if enough (we should otherwise favor expansion) | ||||
let startingWood = gameState.getResources().wood; | let startingWood = gameState.getResources().wood; | ||||
check = {}; | check = {}; | ||||
for (let proxim of ["nearby", "medium", "faraway"]) | for (let proxim of ["nearby", "medium", "faraway"]) | ||||
{ | |||||
for (let base of this.baseManagers) | for (let base of this.baseManagers) | ||||
{ | |||||
for (let supply of base.dropsiteSupplies.wood[proxim]) | for (let supply of base.dropsiteSupplies.wood[proxim]) | ||||
{ | { | ||||
if (check[supply.id]) // avoid double counting as same resource can appear several time | if (check[supply.id]) // avoid double counting as same resource can appear several time | ||||
continue; | continue; | ||||
check[supply.id] = true; | check[supply.id] = true; | ||||
startingWood += supply.ent.resourceSupplyAmount(); | startingWood += supply.ent.resourceSupplyAmount(); | ||||
} | } | ||||
} | |||||
} | |||||
if (this.Config.debug > 1) | if (this.Config.debug > 1) | ||||
API3.warn("startingWood: " + startingWood + " (cut at 8500 for no rush and 6000 for saveResources)"); | API3.warn("startingWood: " + startingWood + " (cut at 8500 for no rush and 6000 for saveResources)"); | ||||
if (startingWood < 6000) | if (startingWood < 6000) | ||||
{ | { | ||||
this.saveResources = true; | this.saveResources = true; | ||||
this.Config.Economy.popPhase2 = Math.floor(0.75 * this.Config.Economy.popPhase2); // Switch to town phase sooner to be able to expand | this.Config.Economy.popPhase2 = Math.floor(0.75 * this.Config.Economy.popPhase2); // Switch to town phase sooner to be able to expand | ||||
if (startingWood < 2000 && this.needFarm) | if (startingWood < 2000 && this.needFarm) | ||||
{ | { | ||||
this.needCorral = true; | this.needCorral = true; | ||||
this.needFarm = false; | this.needFarm = false; | ||||
} | } | ||||
} | } | ||||
if (startingWood > 8500 && this.canBuildUnits) | if (startingWood > 8500 && this.canBuildUnits) | ||||
{ | { | ||||
let allowed = Math.ceil((startingWood - 8500) / 3000); | let allowed = Math.ceil((startingWood - 8500) / 3000); | ||||
// Not useful to prepare rushing if too long ceasefire | // Not useful to prepare rushing if too long ceasefire | ||||
if (gameState.isCeasefireActive()) | if (gameState.isCeasefireActive()) | ||||
{ | |||||
if (gameState.ceasefireTimeRemaining > 900) | if (gameState.ceasefireTimeRemaining > 900) | ||||
allowed = 0; | allowed = 0; | ||||
else if (gameState.ceasefireTimeRemaining > 600 && allowed > 1) | else if (gameState.ceasefireTimeRemaining > 600 && allowed > 1) | ||||
allowed = 1; | allowed = 1; | ||||
} | |||||
this.attackManager.setRushes(allowed); | this.attackManager.setRushes(allowed); | ||||
} | } | ||||
// immediatly build a wood dropsite if possible. | // immediatly build a wood dropsite if possible. | ||||
let template = gameState.applyCiv("structures/{civ}_storehouse"); | let template = gameState.applyCiv("structures/{civ}_storehouse"); | ||||
if (!gameState.getOwnEntitiesByClass("Storehouse", true).hasEntities() && this.canBuild(gameState, template)) | if (!gameState.getOwnEntitiesByClass("Storehouse", true).hasEntities() && this.canBuild(gameState, template)) | ||||
{ | { | ||||
let newDP = this.baseManagers[1].findBestDropsiteLocation(gameState, "wood"); | let newDP = this.baseManagers[1].findBestDropsiteLocation(gameState, "wood"); | ||||
Show All 15 Lines | m.HQ.prototype.configFirstBase = function(gameState) | ||||
if (this.needCorral) | if (this.needCorral) | ||||
{ | { | ||||
template = gameState.applyCiv("structures/{civ}_corral"); | template = gameState.applyCiv("structures/{civ}_corral"); | ||||
if (!gameState.getOwnEntitiesByClass("Corral", true).hasEntities() && this.canBuild(gameState, template)) | if (!gameState.getOwnEntitiesByClass("Corral", true).hasEntities() && this.canBuild(gameState, template)) | ||||
gameState.ai.queues.corral.addPlan(new m.ConstructionPlan(gameState, template, { "base": this.baseManagers[1].ID })); | gameState.ai.queues.corral.addPlan(new m.ConstructionPlan(gameState, template, { "base": this.baseManagers[1].ID })); | ||||
} | } | ||||
}; | }; | ||||
return m; | }(PETRA)); | ||||
}(PETRA); |
Wildfire Games · Phabricator