forked from 0ad/0ad
historic_bruno
0e0ed94926
Includes default library "rmgen" w/ API based on rmgen tool. Modifies rmgen scripts Cantabrian Highlands, Neareastern Badlands, and Latium. Old map support dropped from MapReader. Fixes a few bugs in existing game setup and initialization scripts. This was SVN commit r9096.
142 lines
2.7 KiB
JavaScript
142 lines
2.7 KiB
JavaScript
//////////////////////////////////////////////////////////////////////
|
|
// RangeOp
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
function RangeOp(size)
|
|
{
|
|
// Get smallest power of 2 which is greater than or equal to size
|
|
this.nn = 1;
|
|
while (this.nn < size) {
|
|
this.nn *= 2;
|
|
}
|
|
|
|
this.vals = new Int16Array(2*this.nn); // int16
|
|
}
|
|
|
|
RangeOp.prototype.set = function(pos, amt)
|
|
{
|
|
this.add(pos, amt - this.vals[this.nn + pos]);
|
|
};
|
|
|
|
RangeOp.prototype.add = function(pos, amt)
|
|
{
|
|
for(var s = this.nn; s >= 1; s /= 2)
|
|
{
|
|
this.vals[s + pos] += amt;
|
|
pos = Math.floor(pos/2);
|
|
}
|
|
};
|
|
|
|
RangeOp.prototype.get = function(start, end)
|
|
{
|
|
var ret = 0;
|
|
var i;
|
|
var nn = this.nn;
|
|
|
|
// Count from start to end by powers of 2
|
|
for (i = 1; start+i <= end; i *= 2)
|
|
{
|
|
if (start & i)
|
|
{ // For each bit in start
|
|
ret += this.vals[nn/i + Math.floor(start/i)];
|
|
start += i;
|
|
}
|
|
}
|
|
|
|
//
|
|
while(i >= 1)
|
|
{
|
|
if(start+i <= end)
|
|
{
|
|
ret += this.vals[nn/i + Math.floor(start/i)];
|
|
start += i;
|
|
}
|
|
i /= 2;
|
|
}
|
|
|
|
return ret;
|
|
};
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// TileClass
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
function TileClass(size)
|
|
{
|
|
this.size = size;
|
|
this.inclusionCount = new Array(size);
|
|
this.rangeCount = new Array(size);
|
|
|
|
for (var i=0; i < size; ++i)
|
|
{
|
|
this.inclusionCount[i] = new Int16Array(size); //int16
|
|
this.rangeCount[i] = new RangeOp(size);
|
|
}
|
|
}
|
|
|
|
TileClass.prototype.add = function(x, y)
|
|
{
|
|
if (!this.inclusionCount[x][y])
|
|
{
|
|
this.rangeCount[y].add(x, 1);
|
|
}
|
|
|
|
this.inclusionCount[x][y]++;
|
|
};
|
|
|
|
TileClass.prototype.remove = function(x, y)
|
|
{
|
|
this.inclusionCount[x][y]--;
|
|
if(!this.inclusionCount[x][y])
|
|
{
|
|
this.rangeCount[y].add(x, -1);
|
|
}
|
|
};
|
|
|
|
TileClass.prototype.countInRadius = function(cx, cy, radius, returnMembers)
|
|
{
|
|
var members = 0;
|
|
var nonMembers = 0;
|
|
var size = this.size;
|
|
|
|
var ymax = cy+radius;
|
|
|
|
for (var y = cy-radius; y <= ymax; y++)
|
|
{
|
|
var iy = Math.floor(y);
|
|
if(iy >= 0 && iy < size)
|
|
{
|
|
var dy = y - cy;
|
|
var dx = Math.sqrt(radius*radius - dy*dy);
|
|
|
|
var lowerX = Math.floor(cx - dx);
|
|
var upperX = Math.floor(cx + dx);
|
|
|
|
var minX = (lowerX > 0 ? lowerX : 0);
|
|
var maxX = (upperX < size ? upperX+1 : size);
|
|
|
|
var total = maxX - minX;
|
|
var mem = this.rangeCount[iy].get(minX, maxX);
|
|
|
|
members += mem;
|
|
nonMembers += total - mem;
|
|
}
|
|
}
|
|
|
|
if (returnMembers)
|
|
return members;
|
|
else
|
|
return nonMembers;
|
|
};
|
|
|
|
TileClass.prototype.countMembersInRadius = function(cx, cy, radius)
|
|
{
|
|
return this.countInRadius(cx, cy, radius, true);
|
|
};
|
|
|
|
TileClass.prototype.countNonMembersInRadius = function(cx, cy, radius)
|
|
{
|
|
return this.countInRadius(cx, cy, radius, false);
|
|
};
|