JS Bin on jsbin.com
var map = ["#####",
"# #",
"# o #",
"# #",
"#####"];
function BouncingCritter() {
this.direction = randomElement(directionNames);
//console.log(this.direction);
}
BouncingCritter.prototype.act = function(view) {
//console.log("reche dans la dir = " + this.direction);
if (view.look(this.direction) != " "){
//console.log(" cherche");
this.direction = view.find(" ") || "s";
//console.log("dir trouve espace = " + this.direction);
}
return {type: "move", direction: this.direction};
};
function Wall() {};
class Vector {
constructor (x, y){
this.x = x;
this.y = y;
}
plus (other) { return new Vector(this.x + other.x, this.y + other.y);}
}
class Grid {
constructor (W, H){
this.width = W;
this.height = H;
this.space = Array.from(new Array(this.height*this.width));
}
getS (vector) {return this.space[vector.x + this.width * vector.y];}
getSpace () {return this.space;}
setS (vector, value){this.space[vector.x + this.width * vector.y] = value;}
map (f) {
//console.log(this.space.map(f));
return this.space.map(f);}
isInside (vector) {return vector.x >= 0 && vector.x < this.width &&
vector.y >= 0 && vector.y < this.height;}
forEach(f) {
//console.log("foreach cool");
this.space.forEach((elt,i) => {
if (elt != null){
//console.log(i%this.width+ " " +Math.floor(i/this.width));
f(elt, new Vector(i%this.width,Math.floor(i/this.width)));
}
});
}
}
function elementFromChar(legend, ch) {
if (ch == " ")
return null;
//console.log(legend);
var element = new legend[ch]();
element.originChar = ch;
return element;
}
function charFromElement(element) {
if (element == null)
return " ";
else
return element.originChar;
}
class World {
constructor (map,legend){
this.grid = new Grid(map[0].length, map.length);
this.legend = legend;
}
setS (){
map.forEach( (line,y) => {
line.split("").forEach( (char,x) => {
//console.log(x + " " + " " + y + " " +char + " " +elementFromChar(this.legend,char));
this.grid.setS(new Vector(x,y),elementFromChar(this.legend,char));
});
});
}
toString () {
return (
this.grid.getSpace().map( (elt) => charFromElement(elt))
.reduce((p,n,i) => (i%this.grid.width===0) ? (p+"\n"+n) : (p+n))
);
}
}
World.prototype.turn = function() {
//console.log("turn");
var acted = [];
this.grid.forEach( (critter, vector) => {
if (critter.act && acted.indexOf(critter) == -1) {
acted.push(critter);
this.letAct(critter, vector);
}
});
};
World.prototype.letAct = function(critter, vector) {
//console.log(critter);
//console.log(vector);
var action = critter.act(new View(this, vector));
if (action && action.type == "move") {
var dest = this.checkDestination(action, vector);
if (dest && this.grid.getS(dest) == null) {
this.grid.setS(vector, null);
this.grid.setS(dest, critter);
}
}
};
World.prototype.checkDestination = function(action, vector) {
if (directions.hasOwnProperty(action.direction)) {
var dest = vector.plus(directions[action.direction]);
if (this.grid.isInside(dest))
return dest;
}
};
var directions = {
"n": new Vector( 0, -1),
"ne": new Vector( 1, -1),
"e": new Vector( 1, 0),
"se": new Vector( 1, 1),
"s": new Vector( 0, 1),
"sw": new Vector(-1, 1),
"w": new Vector(-1, 0),
"nw": new Vector(-1, -1)
};
function randomElement(array) {
return array[Math.floor(Math.random() * array.length)];
}
var directionNames = "n ne e se s sw w nw".split(" ");
//console.log(directionNames);
function View(world, vector) {
//console.log(vector);
this.world = world;
this.vector = vector;
}
View.prototype.look = function(dir) {
var target = this.vector.plus(directions[dir]);
//console.log(target);
if (this.world.grid.isInside(target))
return charFromElement(this.world.grid.getS(target));
else
return "#";
};
View.prototype.findAll = function(ch) {
var found = [];
for (var dir in directions){
if (this.look(dir) == ch){
//console.log('ch' + ch);
found.push(dir);
}
}
return found;
};
View.prototype.find = function(ch) {
//console.log("ds find ch= " + ch);
var found = this.findAll(ch);
//console.log("ds find" + found);
if (found.length == 0) return null;
return randomElement(found);
};
var world = new World(map,
{"#" : Wall,
"o" : BouncingCritter});
world.setS();
for (var i = 0; i < 10; i++) {
world.turn();
console.log(world.toString());
}