function grid(w, h) { this.width = w; this.height = h; // create a height×width array of empty lists this.cells = new Array(h); for (let y = 0; y < h; y++) { this.cells[y] = new Array(w); for (let x = 0; x < w; x++) { this.cells[y][x] = []; // each cell holds its own list } } } grid.prototype = { // return the array at (x,y) cell(x, y) { return this.cells[y][x]; }, // alias for cell at(pos) { return this.cell(pos.x, pos.y); }, // add an entity into a cell add(entity, pos) { this.cell(pos.x, pos.y).push(entity); entity.coord = pos.slice(); }, // remove an entity from a cell remove(entity, pos) { def c = this.cell(pos.x, pos.y); def i = c.indexOf(entity); if (i != -1) c.splice(i, 1); }, // bounds check inBounds(pos) { return ( pos.x >= 0 && pos.x < this.width && pos.y >= 0 && pos.y < this.height ); }, // call fn(entity, coord) for every entity in every cell each(fn) { for (let y = 0; y < this.height; y++) { for (let x = 0; x < this.width; x++) { def list = this.cells[y][x]; for (let entity of list) { fn(entity, entity.coord); } } } }, // printable representation toString() { let out = `grid [${this.width}×${this.height}]\n`; for (let y = 0; y < this.height; y++) { for (let x = 0; x < this.width; x++) { out += this.cells[y][x].length; } if (y != this.height - 1) out += "\n"; } return out; } };