1
0
forked from 0ad/0ad

ai common api : use maps for entitycollection lists + cleanings

This was SVN commit r16019.
This commit is contained in:
mimo 2014-12-03 20:22:13 +00:00
parent 7e0e566346
commit 0df90c5c2b
5 changed files with 369 additions and 363 deletions

View File

@ -17,7 +17,6 @@ m.GameState = function() {
m.GameState.prototype.init = function(SharedScript, state, player) {
this.sharedScript = SharedScript;
this.EntCollecNames = SharedScript._entityCollectionsName;
this.EntCollec = SharedScript._entityCollections;
this.timeElapsed = SharedScript.timeElapsed;
this.circularMap = SharedScript.circularMap;
this.templates = SharedScript._templates;
@ -33,7 +32,6 @@ m.GameState.prototype.init = function(SharedScript, state, player) {
m.GameState.prototype.update = function(SharedScript, state) {
this.sharedScript = SharedScript;
this.EntCollecNames = SharedScript._entityCollectionsName;
this.EntCollec = SharedScript._entityCollections;
this.timeElapsed = SharedScript.timeElapsed;
this.templates = SharedScript._templates;
this.techTemplates = SharedScript._techTemplates;
@ -47,67 +45,54 @@ m.GameState.prototype.update = function(SharedScript, state) {
this.turnCache = {};
};
m.GameState.prototype.updatingCollection = function(id, filter, collection, allowQuick){
// automatically add the player ID in front.
id = this.player + "-" + id;
if (!this.EntCollecNames[id]) {
m.GameState.prototype.updatingCollection = function(id, filter, collection, allowQuick)
{
let gid = this.player + "-" + id; // automatically add the player ID
return this.updatingGlobalCollection(gid, filter, collection, allowQuick);
};
m.GameState.prototype.destroyCollection = function(id)
{
let gid = this.player + "-" + id; // automatically add the player ID
return this.destroyGlobalCollection(gid);
};
m.GameState.prototype.getEC = function(id)
{
let gid = this.player + "-" + id; // automatically add the player ID
return this.getGEC(gid);
};
m.GameState.prototype.updatingGlobalCollection = function(id, filter, collection, allowQuick)
{
if (this.EntCollecNames.has(id))
return this.EntCollecNames.get(id);
if (collection !== undefined)
this.EntCollecNames[id] = collection.filter(filter);
else {
this.EntCollecNames[id] = this.entities.filter(filter);
}
if (allowQuick)
this.EntCollecNames[id].allowQuickIter();
this.EntCollecNames[id].registerUpdates();
// warn ("New Collection named " +id);
}
return this.EntCollecNames[id];
};
m.GameState.prototype.destroyCollection = function(id){
// automatically add the player ID
id = this.player + "-" + id;
if (this.EntCollecNames[id] !== undefined){
this.sharedScript.removeUpdatingEntityCollection(this.EntCollecNames[id]);
delete this.EntCollecNames[id];
}
};
m.GameState.prototype.getEC = function(id){
// automatically add the player ID
id = this.player + "-" + id;
if (this.EntCollecNames[id] !== undefined)
return this.EntCollecNames[id];
return undefined;
};
m.GameState.prototype.updatingGlobalCollection = function(id, filter, collection, allowQuick) {
if (!this.EntCollecNames[id]){
if (collection !== undefined)
this.EntCollecNames[id] = collection.filter(filter);
var newCollection = collection.filter(filter);
else
this.EntCollecNames[id] = this.entities.filter(filter);
var newCollection = this.entities.filter(filter);
if (allowQuick)
this.EntCollecNames[id].allowQuickIter();
this.EntCollecNames[id].registerUpdates();
//warn ("New Global Collection named " +id);
}
return this.EntCollecNames[id];
newCollection.allowQuickIter();
newCollection.registerUpdates();
this.EntCollecNames.set(id, newCollection);
return newCollection;
};
m.GameState.prototype.destroyGlobalCollection = function(id)
{
if (this.EntCollecNames[id] !== undefined){
this.sharedScript.removeUpdatingEntityCollection(this.EntCollecNames[id]);
delete this.EntCollecNames[id];
}
if (!this.EntCollecNames.has(id))
return;
this.sharedScript.removeUpdatingEntityCollection(this.EntCollecNames.get(id));
this.EntCollecNames.delete(id);
};
m.GameState.prototype.getGEC = function(id)
{
if (this.EntCollecNames[id] !== undefined)
return this.EntCollecNames[id];
if (!this.EntCollecNames.has(id))
return undefined;
return this.EntCollecNames.get(id);
};
m.GameState.prototype.getTimeElapsed = function()

View File

@ -6,7 +6,8 @@ var API3 = function(m)
*/
// The function needs to be named too because of the copyConstructor functionality
m.Map = function Map(sharedScript, originalMap, actualCopy){
m.Map = function Map(sharedScript, originalMap, actualCopy)
{
// get the map to find out the correct dimensions
var gameMap = sharedScript.passabilityMap;
this.width = gameMap.width;
@ -15,34 +16,40 @@ m.Map = function Map(sharedScript, originalMap, actualCopy){
this.maxVal = 255;
if (originalMap && actualCopy){
if (originalMap && actualCopy)
{
this.map = new Uint8Array(this.length);
for (var i = 0; i < originalMap.length; ++i)
for (let i = 0; i < originalMap.length; ++i)
this.map[i] = originalMap[i];
} else if (originalMap) {
}
else if (originalMap)
this.map = originalMap;
} else {
else
this.map = new Uint8Array(this.length);
}
this.cellSize = 4;
}
m.Map.prototype.setMaxVal = function(val){
this.cellSize = 4;
};
m.Map.prototype.setMaxVal = function(val)
{
this.maxVal = val;
};
m.Map.prototype.gamePosToMapPos = function(p){
m.Map.prototype.gamePosToMapPos = function(p)
{
return [Math.floor(p[0]/this.cellSize), Math.floor(p[1]/this.cellSize)];
};
m.Map.prototype.point = function(p){
m.Map.prototype.point = function(p)
{
var q = this.gamePosToMapPos(p);
q[0] = q[0] >= this.width ? this.width : (q[0] < 0 ? 0 : q[0]);
q[1] = q[1] >= this.width ? this.width : (q[1] < 0 ? 0 : q[1]);
return this.map[q[0] + this.width * q[1]];
};
m.Map.prototype.addInfluence = function(cx, cy, maxDist, strength, type) {
m.Map.prototype.addInfluence = function(cx, cy, maxDist, strength, type)
{
strength = strength ? +strength : +maxDist;
type = type ? type : 'linear';
@ -53,7 +60,8 @@ m.Map.prototype.addInfluence = function(cx, cy, maxDist, strength, type) {
var maxDist2 = maxDist * maxDist;
var str = 0.0;
switch (type){
switch (type)
{
case 'linear':
str = +strength / +maxDist;
break;
@ -68,16 +76,16 @@ m.Map.prototype.addInfluence = function(cx, cy, maxDist, strength, type) {
// code duplicating for speed
if (type === 'linear' || type === "linear")
{
for ( var y = y0; y < y1; ++y) {
for ( var x = x0; x < x1; ++x) {
var dx = x - cx;
var dy = y - cy;
var r2 = dx*dx + dy*dy;
if (r2 < maxDist2) {
var quant = 0;
var r = Math.sqrt(r2);
quant = str * (maxDist - r);
for (let y = y0; y < y1; ++y)
{
for (let x = x0; x < x1; ++x)
{
let dx = x - cx;
let dy = y - cy;
let r2 = dx*dx + dy*dy;
if (r2 < maxDist2)
{
let quant = str * (maxDist - Math.sqrt(r2));
if (this.map[x + y * this.width] + quant < 0)
this.map[x + y * this.width] = 0;
else if (this.map[x + y * this.width] + quant > this.maxVal)
@ -87,16 +95,19 @@ m.Map.prototype.addInfluence = function(cx, cy, maxDist, strength, type) {
}
}
}
} else if (type === 'quadratic' || type === "quadratic")
}
else if (type === 'quadratic' || type === "quadratic")
{
for ( var y = y0; y < y1; ++y) {
for ( var x = x0; x < x1; ++x) {
var dx = x - cx;
var dy = y - cy;
var r2 = dx*dx + dy*dy;
if (r2 < maxDist2){
var quant = str * (maxDist2 - r2);
for (let y = y0; y < y1; ++y)
{
for (let x = x0; x < x1; ++x)
{
let dx = x - cx;
let dy = y - cy;
let r2 = dx*dx + dy*dy;
if (r2 < maxDist2)
{
let quant = str * (maxDist2 - r2);
if (this.map[x + y * this.width] + quant < 0)
this.map[x + y * this.width] = 0;
else if (this.map[x + y * this.width] + quant > this.maxVal)
@ -106,14 +117,18 @@ m.Map.prototype.addInfluence = function(cx, cy, maxDist, strength, type) {
}
}
}
} else if (type === 'constant' || type === "constant")
}
else if (type === 'constant' || type === "constant")
{
for (let y = y0; y < y1; ++y)
{
for (let x = x0; x < x1; ++x)
{
let dx = x - cx;
let dy = y - cy;
let r2 = dx*dx + dy*dy;
if (r2 < maxDist2)
{
for ( var y = y0; y < y1; ++y) {
for ( var x = x0; x < x1; ++x) {
var dx = x - cx;
var dy = y - cy;
var r2 = dx*dx + dy*dy;
if (r2 < maxDist2){
if (this.map[x + y * this.width] + str < 0)
this.map[x + y * this.width] = 0;
else if (this.map[x + y * this.width] + str > this.maxVal)
@ -126,7 +141,8 @@ m.Map.prototype.addInfluence = function(cx, cy, maxDist, strength, type) {
}
};
m.Map.prototype.multiplyInfluence = function(cx, cy, maxDist, strength, type) {
m.Map.prototype.multiplyInfluence = function(cx, cy, maxDist, strength, type)
{
strength = strength ? +strength : +maxDist;
type = type ? type : 'constant';
@ -137,7 +153,8 @@ m.Map.prototype.multiplyInfluence = function(cx, cy, maxDist, strength, type) {
var maxDist2 = maxDist * maxDist;
var str = 0.0;
switch (type){
switch (type)
{
case 'linear':
str = strength / maxDist;
break;
@ -151,57 +168,17 @@ m.Map.prototype.multiplyInfluence = function(cx, cy, maxDist, strength, type) {
if (type === 'linear' || type === "linear")
{
for ( var y = y0; y < y1; ++y) {
for ( var x = x0; x < x1; ++x) {
var dx = x - cx;
var dy = y - cy;
var r2 = dx*dx + dy*dy;
if (r2 < maxDist2){
var quant = 0;
var r = Math.sqrt(r2);
quant = str * (maxDist - r);
var machin = this.map[x + y * this.width] * quant;
if (machin < 0)
this.map[x + y * this.width] = 0;
else if (machin > this.maxVal)
this.map[x + y * this.width] = this.maxVal;
else
this.map[x + y * this.width] = machin;
}
}
}
} else if (type === 'quadratic' || type === "quadratic")
for (let y = y0; y < y1; ++y)
{
for ( var y = y0; y < y1; ++y) {
for ( var x = x0; x < x1; ++x) {
var dx = x - cx;
var dy = y - cy;
var r2 = dx*dx + dy*dy;
if (r2 < maxDist2){
var quant = str * (maxDist2 - r2);
var machin = this.map[x + y * this.width] * quant;
if (machin < 0)
this.map[x + y * this.width] = 0;
else if (machin > this.maxVal)
this.map[x + y * this.width] = this.maxVal;
else
this.map[x + y * this.width] = machin;
}
}
}
} else if (type === 'constant' || type === "constant")
for (let x = x0; x < x1; ++x)
{
for ( var y = y0; y < y1; ++y) {
for ( var x = x0; x < x1; ++x) {
var dx = x - cx;
var dy = y - cy;
var r2 = dx*dx + dy*dy;
if (r2 < maxDist2){
var machin = this.map[x + y * this.width] * str;
let dx = x - cx;
let dy = y - cy;
let r2 = dx*dx + dy*dy;
if (r2 < maxDist2)
{
let quant = str * (maxDist - Math.sqrt(r2));
let machin = this.map[x + y * this.width] * quant;
if (machin < 0)
this.map[x + y * this.width] = 0;
else if (machin > this.maxVal)
@ -213,10 +190,57 @@ m.Map.prototype.multiplyInfluence = function(cx, cy, maxDist, strength, type) {
}
}
}
else if (type === 'quadratic' || type === "quadratic")
{
for (let y = y0; y < y1; ++y)
{
for (let x = x0; x < x1; ++x)
{
let dx = x - cx;
let dy = y - cy;
let r2 = dx*dx + dy*dy;
if (r2 < maxDist2)
{
let quant = str * (maxDist2 - r2);
let machin = this.map[x + y * this.width] * quant;
if (machin < 0)
this.map[x + y * this.width] = 0;
else if (machin > this.maxVal)
this.map[x + y * this.width] = this.maxVal;
else
this.map[x + y * this.width] = machin;
}
}
}
}
else if (type === 'constant' || type === "constant")
{
for (let y = y0; y < y1; ++y)
{
for (let x = x0; x < x1; ++x)
{
let dx = x - cx;
let dy = y - cy;
let r2 = dx*dx + dy*dy;
if (r2 < maxDist2)
{
let machin = this.map[x + y * this.width] * str;
if (machin < 0)
this.map[x + y * this.width] = 0;
else if (machin > this.maxVal)
this.map[x + y * this.width] = this.maxVal;
else
this.map[x + y * this.width] = machin;
}
}
}
}
};
// doesn't check for overflow.
m.Map.prototype.setInfluence = function(cx, cy, maxDist, value) {
m.Map.prototype.setInfluence = function(cx, cy, maxDist, value)
{
value = value ? value : 0;
var x0 = Math.max(0, cx - maxDist);
@ -225,19 +249,20 @@ m.Map.prototype.setInfluence = function(cx, cy, maxDist, value) {
var y1 = Math.min(this.height, cy + maxDist);
var maxDist2 = maxDist * maxDist;
for ( var y = y0; y < y1; ++y) {
for ( var x = x0; x < x1; ++x) {
var dx = x - cx;
var dy = y - cy;
var r2 = dx*dx + dy*dy;
if (r2 < maxDist2){
for (let y = y0; y < y1; ++y)
{
for (let x = x0; x < x1; ++x)
{
let dx = x - cx;
let dy = y - cy;
if (dx*dx + dy*dy < maxDist2)
this.map[x + y * this.width] = value;
}
}
}
};
m.Map.prototype.sumInfluence = function(cx, cy, radius){
m.Map.prototype.sumInfluence = function(cx, cy, radius)
{
var x0 = Math.max(0, cx - radius);
var y0 = Math.max(0, cy - radius);
var x1 = Math.min(this.width, cx + radius);
@ -246,16 +271,16 @@ m.Map.prototype.sumInfluence = function(cx, cy, radius){
var sum = 0;
for ( var y = y0; y < y1; ++y) {
for ( var x = x0; x < x1; ++x) {
var dx = x - cx;
var dy = y - cy;
var r2 = dx*dx + dy*dy;
if (r2 < radius2){
for (let y = y0; y < y1; ++y)
{
for (let x = x0; x < x1; ++x)
{
let dx = x - cx;
let dy = y - cy;
if (dx*dx + dy*dy < radius2)
sum += this.map[x + y * this.width];
}
}
}
return sum;
};
/**
@ -263,7 +288,8 @@ m.Map.prototype.sumInfluence = function(cx, cy, radius){
* neighbours' values. (If the grid is initialised with 0s and 65535s or 255s, the
* result of each cell is its Manhattan distance to the nearest 0.)
*/
m.Map.prototype.expandInfluences = function(maximum, map) {
m.Map.prototype.expandInfluences = function(maximum, map)
{
var grid = this.map;
if (map !== undefined)
grid = map;
@ -272,10 +298,12 @@ m.Map.prototype.expandInfluences = function(maximum, map) {
maximum = this.maxVal;
var w = this.width;
var h = this.height;
for ( var y = 0; y < h; ++y) {
var min = maximum;
for ( var x = 0; x < w; ++x) {
var g = grid[x + y * w];
for (let y = 0; y < h; ++y)
{
let min = maximum;
for (let x = 0; x < w; ++x)
{
let g = grid[x + y * w];
if (g > min)
grid[x + y * w] = min;
else if (g < min)
@ -285,8 +313,9 @@ m.Map.prototype.expandInfluences = function(maximum, map) {
min = maximum;
}
for ( var x = w - 2; x >= 0; --x) {
var g = grid[x + y * w];
for (let x = w - 2; x >= 0; --x)
{
let g = grid[x + y * w];
if (g > min)
grid[x + y * w] = min;
else if (g < min)
@ -297,10 +326,12 @@ m.Map.prototype.expandInfluences = function(maximum, map) {
}
}
for ( var x = 0; x < w; ++x) {
var min = maximum;
for ( var y = 0; y < h; ++y) {
var g = grid[x + y * w];
for (let x = 0; x < w; ++x)
{
let min = maximum;
for (let y = 0; y < h; ++y)
{
let g = grid[x + y * w];
if (g > min)
grid[x + y * w] = min;
else if (g < min)
@ -310,8 +341,9 @@ m.Map.prototype.expandInfluences = function(maximum, map) {
min = maximum;
}
for ( var y = h - 2; y >= 0; --y) {
var g = grid[x + y * w];
for (let y = h - 2; y >= 0; --y)
{
let g = grid[x + y * w];
if (g > min)
grid[x + y * w] = min;
else if (g < min)
@ -324,15 +356,17 @@ m.Map.prototype.expandInfluences = function(maximum, map) {
};
// Multiplies current map by the parameter map pixelwise
m.Map.prototype.multiply = function(map, onlyBetter, divider, maxMultiplier){
for (var i = 0; i < this.length; ++i){
m.Map.prototype.multiply = function(map, onlyBetter, divider, maxMultiplier)
{
for (let i = 0; i < this.length; ++i)
if (map.map[i]/divider > 1)
this.map[i] = Math.min(maxMultiplier*this.map[i], this.map[i] * (map.map[i]/divider));
}
};
// add to current map by the parameter map pixelwise
m.Map.prototype.add = function(map){
for (var i = 0; i < this.length; ++i) {
m.Map.prototype.add = function(map)
{
for (let i = 0; i < this.length; ++i)
{
if (this.map[i] + map.map[i] < 0)
this.map[i] = 0;
else if (this.map[i] + map.map[i] > this.maxVal)
@ -342,14 +376,18 @@ m.Map.prototype.add = function(map){
}
};
m.Map.prototype.findBestTile = function(radius, obstructionTiles){
m.Map.prototype.findBestTile = function(radius, obstructionTiles)
{
// Find the best non-obstructed tile
var bestIdx = 0;
var bestVal = -1;
for ( var i = 0; i < this.length; ++i) {
if (obstructionTiles.map[i] > radius) {
var v = this.map[i];
if (v > bestVal) {
for (let i = 0; i < this.length; ++i)
{
if (obstructionTiles.map[i] > radius)
{
let v = this.map[i];
if (v > bestVal)
{
bestVal = v;
bestIdx = i;
}
@ -360,13 +398,14 @@ m.Map.prototype.findBestTile = function(radius, obstructionTiles){
};
// returns the point with the lowest radius in the immediate vicinity
m.Map.prototype.findLowestNeighbor = function(x,y) {
m.Map.prototype.findLowestNeighbor = function(x,y)
{
var lowestPt = [0,0];
var lowestcoeff = 99999;
x = Math.floor(x/4);
y = Math.floor(y/4);
for (var xx = x-1; xx <= x+1; ++xx)
for (var yy = y-1; yy <= y+1; ++yy)
for (let xx = x-1; xx <= x+1; ++xx)
for (let yy = y-1; yy <= y+1; ++yy)
if (xx >= 0 && xx < this.width && yy >= 0 && yy < this.width)
if (this.map[xx+yy*this.width] <= lowestcoeff)
{
@ -376,7 +415,8 @@ m.Map.prototype.findLowestNeighbor = function(x,y) {
return lowestPt;
}
m.Map.prototype.dumpIm = function(name, threshold){
m.Map.prototype.dumpIm = function(name, threshold)
{
name = name ? name : "default.png";
threshold = threshold ? threshold : this.maxVal;
Engine.DumpImage(name, this.map, this.width, this.height, threshold);

View File

@ -1,77 +1,62 @@
var API3 = function(m)
{
m.Resources = function(amounts, population) {
if (amounts === undefined) {
amounts = {
food : 0,
wood : 0,
stone : 0,
metal : 0
};
}
for ( var tKey in this.types) {
var t = this.types[tKey];
this[t] = amounts[t] || 0;
}
m.Resources = function(amounts, population)
{
if (!amounts)
amounts = { food : 0, wood : 0, stone : 0, metal : 0 };
for (let key of this.types)
this[key] = amounts[key] || 0;
if (population > 0) {
if (population && population > 0)
this.population = parseInt(population);
} else {
else
this.population = 0;
}
}
};
m.Resources.prototype.types = [ "food", "wood", "stone", "metal" ];
m.Resources.prototype.reset = function() {
for ( var tKey in this.types) {
var t = this.types[tKey];
this[t] = 0;
}
m.Resources.prototype.reset = function()
{
for (let key of this.types)
this[key] = 0;
this.population = 0;
};
m.Resources.prototype.canAfford = function(that) {
for ( var tKey in this.types) {
var t = this.types[tKey];
if (this[t] < that[t]) {
m.Resources.prototype.canAfford = function(that)
{
for (let key of this.types)
if (this[key] < that[key])
return false;
}
}
return true;
};
m.Resources.prototype.add = function(that) {
for ( var tKey in this.types) {
var t = this.types[tKey];
this[t] += that[t];
}
m.Resources.prototype.add = function(that)
{
for (let key of this.types)
this[key] += that[key];
this.population += that.population;
};
m.Resources.prototype.subtract = function(that) {
for ( var tKey in this.types) {
var t = this.types[tKey];
this[t] -= that[t];
}
m.Resources.prototype.subtract = function(that)
{
for (let key of this.types)
this[key] -= that[key];
this.population += that.population;
};
m.Resources.prototype.multiply = function(n) {
for ( var tKey in this.types) {
var t = this.types[tKey];
this[t] *= n;
}
m.Resources.prototype.multiply = function(n)
{
for (let key of this.types)
this[key] *= n;
this.population *= n;
};
m.Resources.prototype.toInt = function() {
var sum = 0;
for ( var tKey in this.types) {
var t = this.types[tKey];
sum += this[t];
}
m.Resources.prototype.toInt = function()
{
let sum = 0;
for (let key of this.types)
sum += this[key];
sum += this.population * 50; // based on typical unit costs
return sum;
};

View File

@ -20,9 +20,9 @@ m.SharedScript = function(settings)
this._techModifications = { 0 : {}, 1 : {}, 2 : {}, 3 : {}, 4 : {}, 5 : {}, 6 : {}, 7 : {}, 8 : {} };
// array of entity collections
this._entityCollections = [];
this._entityCollections = new Map();
// each name is a reference to the actual one.
this._entityCollectionsName = {};
this._entityCollectionsName = new Map();
this._entityCollectionsByDynProp = {};
this._entityCollectionsUID = 0;
@ -237,13 +237,13 @@ m.SharedScript.prototype.ApplyEntitiesDelta = function(state)
this.entities.addEnt(this._entities[evt.entity]);
// Update all the entity collections since the create operation affects static properties as well as dynamic
for (var entCollection in this._entityCollections)
this._entityCollections[entCollection].updateEnt(this._entities[evt.entity]);
for (let entCol of this._entityCollections.values())
entCol.updateEnt(this._entities[evt.entity]);
}
for (var i in RenamingEvents)
{
var evt = RenamingEvents[i];
// Switch the metadata
// Switch the metadata: TODO entityCollections are updated only because of the owner change. Should be done properly
for (var p in this._players)
{
this._entityMetadata[this._players[p]][evt.newentity] = this._entityMetadata[this._players[p]][evt.entity];
@ -309,10 +309,8 @@ m.SharedScript.prototype.ApplyEntitiesDelta = function(state)
for (var j in this._players)
evt.metadata[this._players[j]] = this._entityMetadata[this._players[j]][evt.entity];
for each (var entCol in this._entityCollections)
{
for (let entCol of this._entityCollections.values())
entCol.removeEnt(this._entities[evt.entity]);
}
this.entities.removeEnt(this._entities[evt.entity]);
delete this._entities[evt.entity];
@ -366,49 +364,37 @@ m.SharedScript.prototype.ApplyTemplatesDelta = function(state)
m.SharedScript.prototype.registerUpdatingEntityCollection = function(entCollection, noPush)
{
if (!noPush) {
this._entityCollections.push(entCollection);
}
entCollection.setUID(this._entityCollectionsUID);
if (!noPush) {
this._entityCollections.set(this._entityCollectionsUID, entCollection);
}
for each (var prop in entCollection.dynamicProperties())
{
this._entityCollectionsByDynProp[prop] = this._entityCollectionsByDynProp[prop] || [];
this._entityCollectionsByDynProp[prop].push(entCollection);
this._entityCollectionsByDynProp[prop] = this._entityCollectionsByDynProp[prop] || new Map();
this._entityCollectionsByDynProp[prop].set(this._entityCollectionsUID, entCollection);
}
this._entityCollectionsUID++;
};
m.SharedScript.prototype.removeUpdatingEntityCollection = function(entCollection)
{
for (var i in this._entityCollections)
{
if (this._entityCollections[i].getUID() === entCollection.getUID())
{
this._entityCollections.splice(i, 1);
}
}
let uid = entCollection.getUID();
for each (var prop in entCollection.dynamicProperties())
{
for (var i in this._entityCollectionsByDynProp[prop])
{
if (this._entityCollectionsByDynProp[prop][i].getUID() === entCollection.getUID())
{
this._entityCollectionsByDynProp[prop].splice(i, 1);
}
}
}
if (this._entityCollections.has(uid))
this._entityCollections.delete(uid);
for each (let prop in entCollection.dynamicProperties())
if (this._entityCollectionsByDynProp[prop].has(uid))
this._entityCollectionsByDynProp[prop].delete(uid);
};
m.SharedScript.prototype.updateEntityCollections = function(property, ent)
{
if (this._entityCollectionsByDynProp[property] !== undefined)
{
for (var entCollectionid in this._entityCollectionsByDynProp[property])
{
this._entityCollectionsByDynProp[property][entCollectionid].updateEnt(ent);
}
}
if (this._entityCollectionsByDynProp[property] === undefined)
return;
for (let entCol of this._entityCollectionsByDynProp[property].values())
entCol.updateEnt(ent);
}
m.SharedScript.prototype.setMetadata = function(player, ent, key, value)

View File

@ -14,18 +14,17 @@ var API3 = function(m)
// The initializer creates an expanded influence map for checking.
// It's not extraordinarily slow, but it's not exactly fast either.
m.aStarPath = function(gameState, onWater, disregardEntities, targetTerritory) {
var self = this;
m.aStarPath = function(gameState, onWater, disregardEntities, targetTerritory)
{
// get the terrain analyzer map as a reference.
this.Map(gameState.ai, gameState.ai.terrainAnalyzer.map);
// get the accessibility as a reference
this.accessibility = gameState.ai.accessibility;
this.terrainAnalyzer = gameState.ai.terrainAnalyzer;
if (onWater) {
if (onWater)
this.waterPathfinder = true;
} else
else
this.waterPathfinder = false;
var pathObstruction = gameState.sharedScript.passabilityClasses["pathfinderObstruction"];
@ -34,21 +33,22 @@ m.aStarPath = function(gameState, onWater, disregardEntities, targetTerritory) {
this.widthMap = new Uint8Array(this.map.length);
for (var i = 0; i < this.map.length; ++i) {
if (this.map[i] === 0)
for (var i = 0; i < this.map.length; ++i)
{
if (this.map[i] == 0)
this.widthMap[i] = 0;
else if (!disregardEntities && (((terrMap.data[i] & 0x3F) !== gameState.ai.player && (terrMap.data[i] & 0x3F) !== 0 && (terrMap.data[i] & 0x3F) !== targetTerritory)
|| (passMap.data[i] & pathObstruction)))
else if (!disregardEntities && (((terrMap.data[i] & 0x3F) !== gameState.ai.player && (terrMap.data[i] & 0x3F) !== 0
&& (terrMap.data[i] & 0x3F) !== targetTerritory) || (passMap.data[i] & pathObstruction)))
this.widthMap[i] = 1; // we try to avoid enemy territory and pathfinder obstructions.
else if (!disregardEntities && this.map[i] === 30)
else if (!disregardEntities && this.map[i] == 30)
this.widthMap[i] = 0;
else if (!disregardEntities && this.map[i] === 40)
else if (!disregardEntities && this.map[i] == 40)
this.widthMap[i] = 0;
else if (!disregardEntities && this.map[i] === 41)
else if (!disregardEntities && this.map[i] == 41)
this.widthMap[i] = 2;
else if (!disregardEntities && this.map[i] === 42)
else if (!disregardEntities && this.map[i] == 42)
this.widthMap[i] = 1;
else if (!onWater && this.map[i] === 201)
else if (!onWater && this.map[i] == 201)
this.widthMap[i] = 1;
else
this.widthMap[i] = 255;
@ -58,7 +58,8 @@ m.aStarPath = function(gameState, onWater, disregardEntities, targetTerritory) {
m.copyPrototype(m.aStarPath, m.Map);
// marks some points of the map as impassable. This can be used to create different paths, or to avoid going through some areas.
m.aStarPath.prototype.markImpassableArea = function(cx, cy, Distance) {
m.aStarPath.prototype.markImpassableArea = function(cx, cy, Distance)
{
[cx,cy] = this.gamePosToMapPos([cx,cy]);
var x0 = Math.max(0, cx - Distance);
var y0 = Math.max(0, cy - Distance);
@ -66,16 +67,17 @@ m.aStarPath.prototype.markImpassableArea = function(cx, cy, Distance) {
var y1 = Math.min(this.height, cy + Distance);
var maxDist2 = Distance * Distance;
for ( var y = y0; y < y1; ++y) {
for ( var x = x0; x < x1; ++x) {
for ( var y = y0; y < y1; ++y)
{
for ( var x = x0; x < x1; ++x)
{
var dx = x - cx;
var dy = y - cy;
var r2 = dx*dx + dy*dy;
if (r2 < maxDist2){
if (r2 < maxDist2)
this.widthMap[x + y * this.width] = 0;
}
}
}
};
@ -92,12 +94,11 @@ m.aStarPath.prototype.getPath = function(start, end, Sampling, preferredWidth, i
var s = this.terrainAnalyzer.findClosestPassablePoint(this.gamePosToMapPos(start), !this.waterPathfinder, 500, false);
var e = this.terrainAnalyzer.findClosestPassablePoint(this.gamePosToMapPos(end), !this.waterPathfinder, 500, true);
var w = this.width;
if (!s || !e) {
if (!s || !e)
return undefined;
}
if (gamestate !== undefined)
{
this.TotorMap = new m.Map(gamestate);
@ -111,11 +112,12 @@ m.aStarPath.prototype.getPath = function(start, end, Sampling, preferredWidth, i
this.s = s[0] + w*s[1];
this.e = e[0] + w*e[1];
if (this.waterPathfinder && this.map[this.s] !== 200 && this.map[this.s] !== 201)
if (this.waterPathfinder && this.map[this.s] != 200 && this.map[this.s] != 201)
{
m.debug ("Trying a path over water, but we are on land, aborting");
return undefined;
} else if (!this.waterPathfinder && this.map[this.s] === 200)
}
else if (!this.waterPathfinder && this.map[this.s] == 200)
{
m.debug ("Trying a path over land, but we are over water, aborting");
return undefined;
@ -143,8 +145,8 @@ m.aStarPath.prototype.getPath = function(start, end, Sampling, preferredWidth, i
this.parentSquare[this.s] = this.s;
return this.continuePath(gamestate);
}
// in case it's not over yet, this can carry on the calculation of a path over multiple turn until it's over
m.aStarPath.prototype.continuePath = function(gamestate)
{
@ -171,12 +173,14 @@ m.aStarPath.prototype.continuePath = function(gamestate)
var tIndex = 0;
// on to A*
while (found === false && this.openList.length !== 0 && iteration < this.iterationLimit) {
while (found === false && this.openList.length != 0 && iteration < this.iterationLimit)
{
currentDist = infinity;
if (shortcut === true) {
if (shortcut === true)
this.currentSquare = this.openList.shift();
} else {
else
{
for (var i in this.openList)
{
var sum = this.fCostArray[this.openList[i]] + this.gCostArray[this.openList[i]];
@ -189,11 +193,10 @@ m.aStarPath.prototype.continuePath = function(gamestate)
}
this.openList.splice(tIndex,1);
}
if (!this.onWater && this.map[this.currentSquare] === 200) {
if (!this.onWater && this.map[this.currentSquare] == 200)
this.onWater = true;
} else if (this.onWater && (this.map[this.currentSquare] !== 200 && this.map[this.currentSquare] !== 201)) {
else if (this.onWater && (this.map[this.currentSquare] != 200 && this.map[this.currentSquare] != 201))
this.onWater = false;
}
shortcut = false;
this.isOpened[this.currentSquare] = false;
@ -204,8 +207,8 @@ m.aStarPath.prototype.continuePath = function(gamestate)
for (var i in positions)
{
var index = 0 + this.currentSquare +positions[i][0]*this.Sampling +w*this.Sampling*positions[i][1];
if (this.widthMap[index] >= this.minWidth || (this.onWater && this.map[index] > 0 && this.map[index] !== 200 && this.map[index] !== 201)
|| (!this.onWater && this.map[index] === 200))
if (this.widthMap[index] >= this.minWidth || (this.onWater && this.map[index] > 0 && this.map[index] != 200 && this.map[index] != 201)
|| (!this.onWater && this.map[index] == 200))
{
if(this.isOpened[index] === undefined)
{
@ -214,43 +217,46 @@ m.aStarPath.prototype.continuePath = function(gamestate)
this.fCostArray[index] = m.SquareVectorDistance([index%w, Math.floor(index/w)], target);// * cost[i];
this.gCostArray[index] = this.gCostArray[this.currentSquare] + cost[i] * this.Sampling;// - this.map[index];
if (!this.onWater && this.map[index] === 200) {
if (!this.onWater && this.map[index] == 200)
this.gCostArray[index] += 10000;
} else if (this.onWater && this.map[index] !== 200) {
else if (this.onWater && this.map[index] != 200)
this.gCostArray[index] += 10000;
}
if (this.widthMap[index] < this.preferredWidth)
this.gCostArray[index] += 200 * (this.preferredWidth-this.widthMap[index]);
if (this.map[index] === 200 || (this.map[index] === 201 && this.onWater))
if (this.map[index] == 200 || (this.map[index] == 201 && this.onWater))
this.gCostArray[index] += 1000;
if (this.openList[0] !== undefined && this.fCostArray[this.openList[0]] + this.gCostArray[this.openList[0]] > this.fCostArray[index] + this.gCostArray[index])
{
this.openList.unshift(index);
shortcut = true;
} else {
this.openList.push(index);
}
else
this.openList.push(index);
this.isOpened[index] = true;
if (m.SquareVectorDistance( [index%w, Math.floor(index/w)] , target) <= this.Sampling*this.Sampling-1) {
if (m.SquareVectorDistance( [index%w, Math.floor(index/w)] , target) <= this.Sampling*this.Sampling-1)
{
if (this.e != index)
this.parentSquare[this.e] = index;
found = true;
break;
}
} else {
var addCost = 0;
if (!this.onWater && this.map[index] === 200) {
addCost += 10000;
} else if (this.onWater && this.map[index] !== 200) {
addCost += 10000;
}
else
{
var addCost = 0;
if (!this.onWater && this.map[index] == 200)
addCost += 10000;
else if (this.onWater && this.map[index] != 200)
addCost += 10000;
if (this.widthMap[index] < this.preferredWidth)
addCost += 200 * (this.preferredWidth-this.widthMap[index]);
if (this.map[index] === 200 || (this.map[index] === 201 && this.onWater))
if (this.map[index] == 200 || (this.map[index] == 201 && this.onWater))
addCost += 1000;
// already on the Open or closed list
@ -265,14 +271,15 @@ m.aStarPath.prototype.continuePath = function(gamestate)
iteration++;
}
this.totalIteration += iteration;
if (iteration === this.iterationLimit && found === false && this.openList.length !== 0)
if (iteration == this.iterationLimit && found === false && this.openList.length != 0)
{
// we've got to assume that we stopped because we reached the upper limit of iterations
return "toBeContinued";
}
//m.debug (this.totalIteration);
var paths = [];
if (found) {
if (found)
{
this.currentSquare = e;
var lastPosx = 0;
var lastPosy = 0;
@ -280,12 +287,15 @@ m.aStarPath.prototype.continuePath = function(gamestate)
{
this.currentSquare = this.parentSquare[this.currentSquare];
if (!this.onWater && this.map[this.currentSquare] === 200) {
if (!this.onWater && this.map[this.currentSquare] == 200)
{
//m.debug ("We must cross water, going " +this.currentSquare + " from parent " + this.parentSquare[this.currentSquare]);
this.pathChangesTransport = true;
changes[this.currentSquare] = true;
this.onWater = true;
} else if (this.onWater && (this.map[this.currentSquare] !== 200 && this.map[this.currentSquare] !== 201)) {
}
else if (this.onWater && (this.map[this.currentSquare] != 200 && this.map[this.currentSquare] != 201))
{
//m.debug ("We must cross to the ground, going " +this.currentSquare + " from parent " + this.parentSquare[this.currentSquare]);
this.pathChangesTransport = true;
changes[this.currentSquare] = true;
@ -306,7 +316,9 @@ m.aStarPath.prototype.continuePath = function(gamestate)
this.TotorMap.addInfluence(this.currentSquare % w, Math.floor(this.currentSquare / w),1,50 + paths.length,'constant');
}
}
} else {
}
else
{
// we have not found a path.
// what do we do then?
}
@ -321,14 +333,12 @@ m.aStarPath.prototype.continuePath = function(gamestate)
// the return, if defined is [ [path, each waypoint being [position, mustchangeTransport] ], is there any transport change, ]
if (paths.length > 0) {
if (paths.length > 0)
return [paths, this.pathChangesTransport];
} else {
else
return undefined;
}
}
return m;
}(API3);