UNPKG

agentscript

Version:

AgentScript Model in Model/View architecture

123 lines (104 loc) 3.55 kB
import World from '/src/World.js' import Model from '/src/Model.js' import tileDataSet from '/models/data/tile101x101.js' class DropletsModel extends Model { speed = 0.5 // stepType choices: // 'minNeighbor', // 'patchAspect', // 'dataSetAspectNearest', // 'dataSetAspectBilinear', stepType = 'minNeighbor' moves = 0 // how many moves in a step // Installed datasets: elevation dzdx dzdy slope aspect // ====================== constructor(worldOptions = World.defaultOptions(50)) { super(worldOptions) } installDataSets(elevation) { const slopeAndAspect = elevation.slopeAndAspect() const { dzdx, dzdy, slope, aspect } = slopeAndAspect Object.assign(this, { elevation, dzdx, dzdy, slope, aspect }) this.patches.importDataSet(elevation, 'elevation', true) this.patches.importDataSet(aspect, 'aspect', true) } setup() { this.elevation = tileDataSet this.installDataSets(this.elevation) // handled by step(): // this.turtles.setDefault('atEdge', 'die') this.turtles.ask(t => (t.done = false)) this.localMins = [] this.patches.ask(p => { p.isLocalMin = p.neighbors.minOneOf('elevation').elevation > p.elevation if (p.isLocalMin) this.localMins.push(p) p.sprout(1, this.turtles) }) } faceDownhill(t) { if (this.stepType === 'minNeighbor') { // Face the best neighbor if better than me const n = t.patch.neighbors.minOneOf('elevation') if (t.patch.elevation > n.elevation) t.face(n) } else if (this.stepType === 'patchAspect') { t.theta = t.patch.aspect } else if (this.stepType.includes('dataSet')) { // Move in direction of aspect DataSet: const { minXcor, maxYcor, numX, numY } = this.world // bilinear many more minima const nearest = this.stepType === 'dataSetAspectNearest' t.theta = this.aspect.coordSample( t.x, t.y, minXcor, maxYcor, numX, numY, nearest ) } else { throw Error('bad stepType: ' + this.stepType) } } handleLocalMin(t) { if (t.patch.isLocalMin) { // center t in patch, and mark as done t.setxy(t.patch.x, t.patch.y) t.done = true } } patchOK(t, p) { return p.elevation < t.patch.elevation } step() { if (this.done) return this.moves = 0 this.turtles.ask(t => { if (t.done) return this.faceDownhill(t) const pAhead = t.patchAtHeadingAndDistance(t.heading, this.speed) if (!pAhead) { t.die() } else if (pAhead === t.patch || this.patchOK(t, pAhead)) { t.forward(this.speed) this.handleLocalMin(t) this.moves++ } else { t.done = true } }) this.done = this.moves === 0 if (this.done) console.log('No moves, stopping at step', this.ticks) } // Useful informational function: (not used by model but can be used by "app") turtlesOnLocalMins() { return this.localMins.reduce((acc, p) => acc + p.turtlesHere.length, 0) } } export default DropletsModel