0ad/binaries/data/mods/public/maps/random/rmgen/tileclass.js

142 lines
2.7 KiB
JavaScript
Raw Normal View History

//////////////////////////////////////////////////////////////////////
// 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);
};