UNPKG

agentscript

Version:

AgentScript Model in Model/View architecture

111 lines (103 loc) 3.42 kB
import World from 'https://code.agentscript.org/src/World.js' import Model from 'https://code.agentscript.org/src/Model.js' import * as util from 'https://code.agentscript.org/src/utils.js' export default class AntsModel extends Model { population = 200 speed = 1.0 maxPheromone = 35 diffusionRate = 0.3 evaporationRate = 0.01 wiggleAngle = 30 // degrees foodX = world => world.minX + 6 foodY = () => 0 nestX = world => world.maxX - 6 nestY = () => 0 foodSeekers = 0 nestSeekers = 0 // ====================== constructor(worldOptions = World.defaultOptions(40)) { super(worldOptions) } setup() { this.turtles.setDefault('atEdge', 'bounce') this.setupPatches() this.setupTurtles() } setupPatches() { this.patches.ask(p => { p.isNest = p.isFood = false p.nestPheromone = p.foodPheromone = 0 }) this.patches .patchRectXY(this.nestX(this.world), this.nestY(this.world), 3, 3) .ask(p => { p.isNest = true }) this.patches .patchRectXY(this.foodX(this.world), this.foodY(this.world), 3, 3) .ask(p => { p.isFood = true }) } setupTurtles() { this.turtles.create(this.population, t => { t.setxy(this.nestX(this.world), this.nestY(this.world)) this.resetTurtle(t, false) // sets t.pheromone to max }) } resetTurtle(t, withFood) { t.carryingFood = withFood t.pheromone = this.maxPheromone } step() { this.updateTurtles() this.updatePatches() } updateTurtles() { this.foodSeekers = 0 this.nestSeekers = 0 this.turtles.ask(t => { if (t.id >= this.ticks) return // slowly release ants this.wiggleUphill(t) this.dropPheromone(t) if (t.carryingFood) { this.nestSeekers++ } else { this.foodSeekers++ } }) } wiggleUphill(t) { const p = t.patch if (p.isOnEdge()) { // t.rotate(Math.PI) t.rotate(180) } else { // Note: neighbors is an AgentArray who's inCone uses radians. // const nAhead = p.neighbors.inCone(p, 2, Math.PI, t.theta) const nAhead = p.neighbors.inCone(p, 2, 180, t.heading) const pheromone = t.carryingFood ? 'nestPheromone' : 'foodPheromone' const [n, max] = nAhead.maxValOf(pheromone) if (max > 0.001 / this.maxPheromone) t.face(n) } t.rotate(util.randomCentered(this.wiggleAngle)) t.forward(this.speed) } dropPheromone(t) { const p = t.patch if ((!t.carryingFood && p.isFood) || (t.carryingFood && p.isNest)) { this.resetTurtle(t, !t.carryingFood) } const pheromone = t.carryingFood ? 'foodPheromone' : 'nestPheromone' p[pheromone] += 0.1 * t.pheromone t.pheromone *= 0.9 } updatePatches() { this.patches.diffuse('nestPheromone', this.diffusionRate) this.patches.diffuse('foodPheromone', this.diffusionRate) this.patches.ask(p => { p.foodPheromone *= 1 - this.evaporationRate p.nestPheromone *= 1 - this.evaporationRate }) } }