Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/binaries/data/mods/public/simulation/ai/petra/headquarters.js
Show First 20 Lines • Show All 1,098 Lines • ▼ Show 20 Lines | m.HQ.prototype.findStrategicCCLocation = function(gameState, template) | ||||
} | } | ||||
return [x, z]; | return [x, z]; | ||||
}; | }; | ||||
/** | /** | ||||
* Returns the best position to build a new market: if the allies already have a market, build it as far as possible | * Returns the best position to build a new market: if the allies already have a market, build it as far as possible | ||||
* from it, although not in our border to be able to defend it easily. If no allied market, our second market will | * from it, although not in our border to be able to defend it easily. If no allied market, our second market will | ||||
* follow the same logic | * follow the same logic. | ||||
* TODO check that it is on same accessIndex | * To do so, we suppose that the gain/distance is an increasing function of distance and look for the max distance | ||||
* for performance reasons. | |||||
*/ | */ | ||||
m.HQ.prototype.findMarketLocation = function(gameState, template) | m.HQ.prototype.findMarketLocation = function(gameState, template) | ||||
{ | { | ||||
let markets = gameState.updatingCollection("diplo-ExclusiveAllyMarkets", API3.Filters.byClass("Market"), gameState.getExclusiveAllyEntities()).toEntityArray(); | let markets = gameState.updatingCollection("diplo-ExclusiveAllyMarkets", API3.Filters.byClass("Market"), gameState.getExclusiveAllyEntities()).toEntityArray(); | ||||
if (!markets.length) | if (!markets.length) | ||||
markets = gameState.updatingCollection("OwnMarkets", API3.Filters.byClass("Market"), gameState.getOwnStructures()).toEntityArray(); | markets = gameState.updatingCollection("OwnMarkets", API3.Filters.byClass("Market"), gameState.getOwnStructures()).toEntityArray(); | ||||
if (!markets.length) // this is the first market. For the time being, place it arbitrarily by the ConstructionPlan | if (!markets.length) // this is the first market. For the time being, place it arbitrarily by the ConstructionPlan | ||||
return [-1, -1, -1, 0]; | return [-1, -1, -1, 0]; | ||||
// obstruction map | // obstruction map | ||||
let obstructions = m.createObstructionMap(gameState, 0, template); | let obstructions = m.createObstructionMap(gameState, 0, template); | ||||
let halfSize = 0; | let halfSize = 0; | ||||
if (template.get("Footprint/Square")) | if (template.get("Footprint/Square")) | ||||
halfSize = Math.max(+template.get("Footprint/Square/@depth"), +template.get("Footprint/Square/@width")) / 2; | halfSize = Math.max(+template.get("Footprint/Square/@depth"), +template.get("Footprint/Square/@width")) / 2; | ||||
else if (template.get("Footprint/Circle")) | else if (template.get("Footprint/Circle")) | ||||
halfSize = +template.get("Footprint/Circle/@radius"); | halfSize = +template.get("Footprint/Circle/@radius"); | ||||
let bestIdx; | let bestIdx; | ||||
let bestJdx; | let bestJdx; | ||||
let bestVal; | let bestVal; | ||||
let bestDistSq; | |||||
let bestGainMult; | |||||
let radius = Math.ceil(template.obstructionRadius().max / obstructions.cellSize); | let radius = Math.ceil(template.obstructionRadius().max / obstructions.cellSize); | ||||
let isNavalMarket = template.hasClass("NavalMarket"); | let isNavalMarket = template.hasClass("NavalMarket"); | ||||
let width = this.territoryMap.width; | let width = this.territoryMap.width; | ||||
let cellSize = this.territoryMap.cellSize; | let cellSize = this.territoryMap.cellSize; | ||||
let traderTemplatesGains = gameState.getTraderTemplatesGains(); | let traderTemplatesGains = gameState.getTraderTemplatesGains(); | ||||
Show All 9 Lines | for (let j = 0; j < this.territoryMap.length; ++j) | ||||
if (i < 0) | if (i < 0) | ||||
continue; | continue; | ||||
let index = gameState.ai.accessibility.landPassMap[i]; | let index = gameState.ai.accessibility.landPassMap[i]; | ||||
if (!this.landRegions[index]) | if (!this.landRegions[index]) | ||||
continue; | continue; | ||||
let pos = [cellSize * (j%width+0.5), cellSize * (Math.floor(j/width)+0.5)]; | let pos = [cellSize * (j%width+0.5), cellSize * (Math.floor(j/width)+0.5)]; | ||||
// checking distances to other markets | // checking distances to other markets | ||||
let maxVal = 0; | let maxVal = 0; | ||||
let maxDistSq; | |||||
let maxGainMult; | |||||
let gainMultiplier; | let gainMultiplier; | ||||
for (let market of markets) | for (let market of markets) | ||||
{ | { | ||||
if (isNavalMarket && market.hasClass("NavalMarket")) | if (isNavalMarket && market.hasClass("NavalMarket")) | ||||
{ | { | ||||
if (m.getSeaAccess(gameState, market) !== gameState.ai.accessibility.getAccessValue(pos, true)) | if (m.getSeaAccess(gameState, market) !== gameState.ai.accessibility.getAccessValue(pos, true)) | ||||
continue; | continue; | ||||
gainMultiplier = traderTemplatesGains.navalGainMultiplier; | gainMultiplier = traderTemplatesGains.navalGainMultiplier; | ||||
} | } | ||||
else if (m.getLandAccess(gameState, market) === index && | else if (m.getLandAccess(gameState, market) === index && | ||||
!m.isLineInsideEnemyTerritory(gameState, market.position(), pos)) | !m.isLineInsideEnemyTerritory(gameState, market.position(), pos)) | ||||
gainMultiplier = traderTemplatesGains.landGainMultiplier; | gainMultiplier = traderTemplatesGains.landGainMultiplier; | ||||
else | else | ||||
continue; | continue; | ||||
if (!gainMultiplier) | if (!gainMultiplier) | ||||
continue; | continue; | ||||
let val = API3.SquareVectorDistance(market.position(), pos) * gainMultiplier; | let distSq = API3.SquareVectorDistance(market.position(), pos); | ||||
if (val > maxVal) | if (gainMultiplier * distSq > maxVal) | ||||
maxVal = val; | { | ||||
maxVal = gainMultiplier * distSq; | |||||
maxDistSq = distSq; | |||||
maxGainMult = gainMultiplier; | |||||
} | |||||
} | } | ||||
if (maxVal === 0) | if (maxVal === 0) | ||||
continue; | continue; | ||||
if (bestVal !== undefined && maxVal < bestVal) | if (bestVal !== undefined && maxVal < bestVal) | ||||
continue; | continue; | ||||
if (this.isDangerousLocation(gameState, pos, halfSize)) | if (this.isDangerousLocation(gameState, pos, halfSize)) | ||||
continue; | continue; | ||||
bestVal = maxVal; | bestVal = maxVal; | ||||
bestDistSq = maxDistSq; | |||||
bestGainMult = maxGainMult; | |||||
bestIdx = i; | bestIdx = i; | ||||
bestJdx = j; | bestJdx = j; | ||||
} | } | ||||
if (this.Config.debug > 1) | if (this.Config.debug > 1) | ||||
API3.warn("We found a market position with bestVal = " + bestVal); | API3.warn("We found a market position with bestVal = " + bestVal); | ||||
if (bestVal === undefined) // no constraints. For the time being, place it arbitrarily by the ConstructionPlan | if (bestVal === undefined) // no constraints. For the time being, place it arbitrarily by the ConstructionPlan | ||||
return [-1, -1, -1, 0]; | return [-1, -1, -1, 0]; | ||||
let expectedGain = Math.round(bestVal / 10000); | let expectedGain = Math.round(bestGainMult * NormalizedTradeGain(bestDistSq)); | ||||
if (this.Config.debug > 1) | if (this.Config.debug > 1) | ||||
API3.warn("this would give a trading gain of " + expectedGain); | API3.warn("this would give a trading gain of " + expectedGain); | ||||
// do not keep it if gain is too small, except if this is our first BarterMarket | // do not keep it if gain is too small, except if this is our first BarterMarket | ||||
if (expectedGain < this.tradeManager.minimalGain || | if (expectedGain < this.tradeManager.minimalGain || | ||||
expectedGain < 8 && (!template.hasClass("BarterMarket") || gameState.getOwnEntitiesByClass("BarterMarket", true).hasEntities())) | expectedGain < 8 && (!template.hasClass("BarterMarket") || gameState.getOwnEntitiesByClass("BarterMarket", true).hasEntities())) | ||||
return false; | return false; | ||||
let x = (bestIdx % obstructions.width + 0.5) * obstructions.cellSize; | let x = (bestIdx % obstructions.width + 0.5) * obstructions.cellSize; | ||||
▲ Show 20 Lines • Show All 1,355 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator