0ad/binaries/data/mods/public/simulation/ai/aegis/map-module.js
wraitii 9d02495a96 Fix a few bugs.
Improve the AI gamestate to make better use of entity collections,
should be very slightly faster, and it's cleaner.
Remove enemy watchers that were no longer used.

This was SVN commit r14574.
2014-01-12 01:07:07 +00:00

149 lines
5.3 KiB
JavaScript

var AEGIS = function(m)
{
// other map functions
m.TERRITORY_PLAYER_MASK = 0x3F;
m.createObstructionMap = function(gameState, accessIndex, template){
var passabilityMap = gameState.getMap();
var territoryMap = gameState.ai.territoryMap;
// default values
var placementType = "land";
var buildOwn = true;
var buildAlly = true;
var buildNeutral = true;
var buildEnemy = false;
// If there is a template then replace the defaults
if (template){
placementType = template.buildPlacementType();
buildOwn = template.hasBuildTerritory("own");
buildAlly = template.hasBuildTerritory("ally");
buildNeutral = template.hasBuildTerritory("neutral");
buildEnemy = template.hasBuildTerritory("enemy");
}
var obstructionMask = gameState.getPassabilityClassMask("foundationObstruction") | gameState.getPassabilityClassMask("building-land");
if (placementType == "shore")
{
// TODO: this won't change much, should be cached, it's slow.
var obstructionTiles = new Uint8Array(passabilityMap.data.length);
var okay = false;
for (var x = 0; x < passabilityMap.width; ++x)
{
for (var y = 0; y < passabilityMap.height; ++y)
{
var i = x + y*passabilityMap.width;
var tilePlayer = (territoryMap.data[i] & m.TERRITORY_PLAYER_MASK);
if (gameState.ai.myIndex !== gameState.ai.accessibility.landPassMap[i])
{
obstructionTiles[i] = 0;
continue;
}
if (gameState.isPlayerEnemy(tilePlayer) && tilePlayer !== 0)
{
obstructionTiles[i] = 0;
continue;
}
if ((passabilityMap.data[i] & (gameState.getPassabilityClassMask("building-shore") | gameState.getPassabilityClassMask("default"))))
{
obstructionTiles[i] = 0;
continue;
}
okay = false;
var positions = [[0,1], [1,1], [1,0], [1,-1], [0,-1], [-1,-1], [-1,0], [-1,1]];
var available = 0;
for each (var stuff in positions)
{
var index = x + stuff[0] + (y+stuff[1])*passabilityMap.width;
var index2 = x + stuff[0]*2 + (y+stuff[1]*2)*passabilityMap.width;
var index3 = x + stuff[0]*3 + (y+stuff[1]*3)*passabilityMap.width;
var index4 = x + stuff[0]*4 + (y+stuff[1]*4)*passabilityMap.width;
if ((passabilityMap.data[index] & gameState.getPassabilityClassMask("default")) && gameState.ai.accessibility.getRegionSizei(index,true) > 500)
if ((passabilityMap.data[index2] & gameState.getPassabilityClassMask("default")) && gameState.ai.accessibility.getRegionSizei(index2,true) > 500)
if ((passabilityMap.data[index3] & gameState.getPassabilityClassMask("default")) && gameState.ai.accessibility.getRegionSizei(index3,true) > 500)
if ((passabilityMap.data[index4] & gameState.getPassabilityClassMask("default")) && gameState.ai.accessibility.getRegionSizei(index4,true) > 500) {
if (available < 2)
available++;
else
okay = true;
}
}
// checking for accessibility: if a neighbor is inaccessible, this is too. If it's not on the same "accessible map" as us, we crash-i~u.
var radius = 3;
for (var xx = -radius;xx <= radius; xx++)
for (var yy = -radius;yy <= radius; yy++)
{
var id = x + xx + (y+yy)*passabilityMap.width;
if (id > 0 && id < passabilityMap.data.length)
if (gameState.ai.terrainAnalyzer.map[id] === 0 || gameState.ai.terrainAnalyzer.map[id] == 30 || gameState.ai.terrainAnalyzer.map[id] == 40)
okay = false;
}
obstructionTiles[i] = okay ? 255 : 0;
}
}
} else {
var playerID = PlayerID;
var obstructionTiles = new Uint8Array(passabilityMap.data.length);
for (var i = 0; i < passabilityMap.data.length; ++i)
{
var tilePlayer = (territoryMap.data[i] & m.TERRITORY_PLAYER_MASK);
var invalidTerritory = (
(!buildOwn && tilePlayer == playerID) ||
(!buildAlly && gameState.isPlayerAlly(tilePlayer) && tilePlayer != playerID) ||
(!buildNeutral && tilePlayer == 0) ||
(!buildEnemy && gameState.isPlayerEnemy(tilePlayer) && tilePlayer != 0)
);
if (accessIndex)
var tileAccessible = (accessIndex === gameState.ai.accessibility.landPassMap[i]);
else
var tileAccessible = true;
if (placementType === "shore")
tileAccessible = true;
obstructionTiles[i] = (!tileAccessible || invalidTerritory || (passabilityMap.data[i] & obstructionMask)) ? 0 : 255;
}
}
var map = new API3.Map(gameState.sharedScript, obstructionTiles);
map.setMaxVal(255);
if (template && template.buildDistance()){
var minDist = template.buildDistance().MinDistance;
var category = template.buildDistance().FromCategory;
if (minDist !== undefined && category !== undefined){
gameState.getOwnStructures().forEach(function(ent) {
if (ent.buildCategory() === category && ent.position()){
var pos = ent.position();
var x = Math.round(pos[0] / gameState.cellSize);
var z = Math.round(pos[1] / gameState.cellSize);
map.addInfluence(x, z, minDist/gameState.cellSize, -255, 'constant');
}
});
}
}
return map;
};
m.createTerritoryMap = function(gameState) {
var map = gameState.ai.territoryMap;
var ret = new API3.Map(gameState.sharedScript, map.data);
ret.getOwner = function(p) {
return this.point(p) & m.TERRITORY_PLAYER_MASK;
}
ret.getOwnerIndex = function(p) {
return this.map[p] & m.TERRITORY_PLAYER_MASK;
}
return ret;
};
return m;
}(AEGIS);