Fix #13: add a method to populate a terrarium non-randomly

This commit is contained in:
Riley Shaw 2014-08-25 13:49:17 -07:00
parent 02e2609ed5
commit 1988080a86
4 changed files with 87 additions and 59 deletions

View File

@ -22,35 +22,40 @@ function Terrarium(width, height, id, cellSize, insertAfter) {
} }
/** /**
* Populates a terrarium with a set distribution of creatures * Create a grid and fill it by using a function, 2-d array, or uniform type
* @param {array} creatures an array of arrays of the form [string 'creatureName', int fillPercent] * @param {*} content if function, fill grid according to fn(x, y)
* @param {[type]} grid the grid to fill * if array, fill grid cells with the corresponding creatureType
* if string, fill grid with that creatureType
* otherwise, create empty grid
* @return {grid} a grid adhering to the above rules
*/ */
Terrarium.prototype.populate = function (creatures, grid) { Terrarium.prototype.makeGrid = function (content) {
function pickCreature(accum, creature) { var grid = [], type = typeof content, creature;
var percentage = accum + creature[1]; for (var x = 0, _w = this.width; x < _w; x++) {
if (!current && percentage > rand) { grid.push([]);
current = creatureFactory.make(creature[0]); for (var y = 0, _h = this.height; y < _h; y++) {
grid[x].push(creatureFactory.make(
type === 'function' ? content(x, y) :
type === 'object' && content.length ? (content[y] || [])[x] :
type === 'string' ? content :
undefined
));
} }
return percentage; } return grid;
} };
var current, rand = 0; /**
if (!grid) grid = this.grid; * Create a grid and fill it randomly with a set creature distribution
* @param {array} distribution an array of arrays of the form [string 'creatureName', float fillPercent]
for (var x = this.width; x--;) { */
grid[x] = []; Terrarium.prototype.makeGridWithDistribution = function (distribution) {
// populate the array with creatures if provided, var current, rand = 0, grid = [];
// otherwise leave it sparse for (var x = 0, _w = this.width; x < _w; x++) {
if (creatures) { grid.push([]);
for (var y = this.height; y--;) { for (var y = 0, _h = this.height; y < _h; y++) {
current = false; grid[x].push(creatureFactory.make(_.pickRandomWeighted(distribution)));
rand = _.random(100, true);
_.reduce(creatures, pickCreature, 0);
grid[x].push(current);
}
} }
} } return grid;
}; };
/** /**
@ -62,7 +67,7 @@ Terrarium.prototype.step = function (steps) {
function copyAndRemoveInner (origCreature) { function copyAndRemoveInner (origCreature) {
if (origCreature) { if (origCreature) {
var copy = _.assign(new (origCreature.constructor)(), origCreature); var copy = _.assign(new (origCreature.constructor)(), origCreature);
return copy.isDead() ? false : copy; return copy && !copy.isDead() ? copy : false;
} else return false; } else return false;
} }
@ -120,7 +125,7 @@ Terrarium.prototype.step = function (steps) {
var winnerCreature = winner.creature; var winnerCreature = winner.creature;
// clear the original creature's square if successFn returns false // clear the original creature's square if successFn returns false
if (winnerCreature.successFn() === false) { if (!winnerCreature.successFn()) {
newGrid[winner.x][winner.y] = false; newGrid[winner.x][winner.y] = false;
} }
@ -153,8 +158,7 @@ Terrarium.prototype.step = function (steps) {
newGrid = _.map(oldGrid, copyAndRemove); newGrid = _.map(oldGrid, copyAndRemove);
// create an empty grid to hold creatures competing for the same square // create an empty grid to hold creatures competing for the same square
eigenGrid = []; eigenGrid = this.makeGrid();
this.populate(false, eigenGrid);
// Add each creature's intended destination to the eigenGrid // Add each creature's intended destination to the eigenGrid
_.each(newGrid, processCreatures); _.each(newGrid, processCreatures);

View File

@ -31,6 +31,16 @@ _.getNeighborCoords = function (x0, y0, xMax, yMax, radius) {
return coords; return coords;
}; };
_.pickRandomWeighted = function (weightedArrays) {
var sum = 0, rand = _.random(100, true);
var cur, i;
for (i = 0, _len = weightedArrays.length; i < _len; i++) {
cur = weightedArrays[i];
sum += cur[1];
if (sum > rand) return cur[0];
} return false;
};
/** /**
* CommonJS exports * CommonJS exports
* @type {Object} * @type {Object}

72
dist/terra.js vendored
View File

@ -280,35 +280,40 @@ function Terrarium(width, height, id, cellSize, insertAfter) {
} }
/** /**
* Populates a terrarium with a set distribution of creatures * Create a grid and fill it by using a function, 2-d array, or uniform type
* @param {array} creatures an array of arrays of the form [string 'creatureName', int fillPercent] * @param {*} content if function, fill grid according to fn(x, y)
* @param {[type]} grid the grid to fill * if array, fill grid cells with the corresponding creatureType
* if string, fill grid with that creatureType
* otherwise, create empty grid
* @return {grid} a grid adhering to the above rules
*/ */
Terrarium.prototype.populate = function (creatures, grid) { Terrarium.prototype.makeGrid = function (content) {
function pickCreature(accum, creature) { var grid = [], type = typeof content, creature;
var percentage = accum + creature[1]; for (var x = 0, _w = this.width; x < _w; x++) {
if (!current && percentage > rand) { grid.push([]);
current = creatureFactory.make(creature[0]); for (var y = 0, _h = this.height; y < _h; y++) {
grid[x].push(creatureFactory.make(
type === 'function' ? content(x, y) :
type === 'object' && content.length ? (content[y] || [])[x] :
type === 'string' ? content :
undefined
));
} }
return percentage; } return grid;
} };
var current, rand = 0; /**
if (!grid) grid = this.grid; * Create a grid and fill it randomly with a set creature distribution
* @param {array} distribution an array of arrays of the form [string 'creatureName', float fillPercent]
for (var x = this.width; x--;) { */
grid[x] = []; Terrarium.prototype.makeGridWithDistribution = function (distribution) {
// populate the array with creatures if provided, var current, rand = 0, grid = [];
// otherwise leave it sparse for (var x = 0, _w = this.width; x < _w; x++) {
if (creatures) { grid.push([]);
for (var y = this.height; y--;) { for (var y = 0, _h = this.height; y < _h; y++) {
current = false; grid[x].push(creatureFactory.make(_.pickRandomWeighted(distribution)));
rand = _.random(100, true);
_.reduce(creatures, pickCreature, 0);
grid[x].push(current);
}
} }
} } return grid;
}; };
/** /**
@ -320,7 +325,7 @@ Terrarium.prototype.step = function (steps) {
function copyAndRemoveInner (origCreature) { function copyAndRemoveInner (origCreature) {
if (origCreature) { if (origCreature) {
var copy = _.assign(new (origCreature.constructor)(), origCreature); var copy = _.assign(new (origCreature.constructor)(), origCreature);
return copy.isDead() ? false : copy; return copy && !copy.isDead() ? copy : false;
} else return false; } else return false;
} }
@ -378,7 +383,7 @@ Terrarium.prototype.step = function (steps) {
var winnerCreature = winner.creature; var winnerCreature = winner.creature;
// clear the original creature's square if successFn returns false // clear the original creature's square if successFn returns false
if (winnerCreature.successFn() === false) { if (!winnerCreature.successFn()) {
newGrid[winner.x][winner.y] = false; newGrid[winner.x][winner.y] = false;
} }
@ -411,8 +416,7 @@ Terrarium.prototype.step = function (steps) {
newGrid = _.map(oldGrid, copyAndRemove); newGrid = _.map(oldGrid, copyAndRemove);
// create an empty grid to hold creatures competing for the same square // create an empty grid to hold creatures competing for the same square
eigenGrid = []; eigenGrid = this.makeGrid();
this.populate(false, eigenGrid);
// Add each creature's intended destination to the eigenGrid // Add each creature's intended destination to the eigenGrid
_.each(newGrid, processCreatures); _.each(newGrid, processCreatures);
@ -498,6 +502,16 @@ _.getNeighborCoords = function (x0, y0, xMax, yMax, radius) {
return coords; return coords;
}; };
_.pickRandomWeighted = function (weightedArrays) {
var sum = 0, rand = _.random(100, true);
var cur, i;
for (i = 0, _len = weightedArrays.length; i < _len; i++) {
cur = weightedArrays[i];
sum += cur[1];
if (sum > rand) return cur[0];
} return false;
};
/** /**
* CommonJS exports * CommonJS exports
* @type {Object} * @type {Object}

2
dist/terra.min.js vendored

File diff suppressed because one or more lines are too long