Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 68 additions & 19 deletions model/scripts/engine/Actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,25 +65,7 @@ Actions.if_neighbor = {
// First, get num of actual neighbors that are STATE
var count = Grid.countNeighbors(agent, config.stateID);

// Did condition pass?
var pass;
switch(config.sign){
case "<":
pass = (count<config.num);
break;
case "<=":
pass = (count<=config.num);
break;
case ">":
pass = (count>config.num);
break
case ">=":
pass = (count>=config.num);
break;
case "=":
pass = (count==config.num);
break;
}
var pass = compare(config.sign, config.num, count);

// If so, perform the following actions.
if(pass){
Expand Down Expand Up @@ -118,6 +100,73 @@ Actions.if_neighbor = {

};

// IF_NEAR: If we're near a thing, do a thing!
Actions.if_near = {

name: "If near to a certain number of...",

props: {
countSign: ">=",
num: 3,
distance: 3,
stateID: 0,
actions: []
},

step: function(agent,config){

var pass = Grid.nearby(agent, config.stateID, config.num, config.countSign, config.distance);

if(pass) {
PerformActions(agent, config.actions);
}

},

ui: function(config){

return EditorHelper()
.label("If ")
.selector([
{ name:"fewer than (<)", value:"<" },
{ name:"at least (>=)", value:">=" },
],config,"countSign")
.label(" ")
.number(config, "num", {
integer:true,
min:0, max:8,
step:1
})
.stateSelector(config, "stateID")
.label(" are within")
.number(config, "distance", {
integer: true,
min:1, max:8,
step: 1
})
.actionsUI(config.actions)
.dom;
}

};

function compare(sign, constraint, value) {
switch(sign){
case "<":
return value<constraint;
case "<=":
return value<=constraint;
case ">":
return value>constraint;
case ">=":
return value>=constraint;
case "=":
return value==constraint;
}
}



// IF_RANDOM: With a X% chance, do a thing
Actions.if_random = {

Expand Down
70 changes: 61 additions & 9 deletions model/scripts/engine/Grid.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,15 +227,7 @@ Grid.getNeighbors = function(agent){
}

// Then, filter out ones that can't work
coords = coords.filter(function(coord){
var x = coord[0];
var y = coord[1];
if(x<0) return false;
if(x>=Grid.array[0].length) return false;
if(y<0) return false;
if(y>=Grid.array.length) return false;
return true;
});
coords = coords.filter(validCoordinate);

// Then, get all neighbors at those coords
var neighbors = [];
Expand All @@ -250,6 +242,27 @@ Grid.getNeighbors = function(agent){

};

function validCoordinate(coord) {
var x = coord[0];
var y = coord[1];
return legalX(x) && legalY(y);
}

function legalX(x) {
return x>=0 && x < gridWidth();
}
function legalY(y) {
return y>=0 && y < gridHeight();
}

function gridWidth() {
return Grid.array[0].length;
}

function gridHeight() {
return Grid.array.length;
}

// Get ALL agents (just collapses to a single array)
Grid.getAllAgents = function(){

Expand All @@ -276,6 +289,45 @@ Grid.countNeighbors = function(agent,stateID){
return count;
};

// Count items nearby of a certain state
Grid.nearby = function(agent,stateID, target, moreOrLess, within){

var isAtLeast = moreOrLess === ">=";

// no neighbours, so can't be at least, and definitely less than
if(within < 1) {
return !isAtLeast;
}

// calculate the maximum valid neighbourhood considering
// grid constraints
var coords = {
x: Math.max(0, agent.x - within),
mx: Math.min(agent.x + within, gridWidth()),
y: Math.max(0, agent.y - within),
my: Math.min(agent.y + within, gridHeight()),
};

var count = 0;

for(var y = coords.y, maxY = coords.my; y < maxY; y++) {
for(var x = coords.x, maxX = coords.mx; x < maxX; x++) {
if(Grid.array[y][x].stateID==stateID) {
count += 1;
// if we're at target for at least, we've done enough to know we've passed
// if at target for less than, we know we've failed
if(count >= target) {
return isAtLeast;
}
}
}
}

// if we're here we haven't found the target count. that is
// a fail for more than, a pass for less than
return !isAtLeast;
};

// Reset world, update the view, and resize to fit
Grid.reinitialize = function(){
Grid.initialize();
Expand Down