From 96ad92e5dd3591cc607ec0d9f1bb95ce485d9225 Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Fri, 25 Oct 2019 16:54:23 -0700 Subject: [PATCH] Playing with flocking models --- core/turtle.go | 89 +++++++++++++++++++++++++++++++++++- experiments/flocking/main.go | 64 +++++++++++++++++++++++++- 2 files changed, 151 insertions(+), 2 deletions(-) diff --git a/core/turtle.go b/core/turtle.go index b811ec9..5bb0226 100644 --- a/core/turtle.go +++ b/core/turtle.go @@ -2,6 +2,7 @@ package core import ( "image/color" + "math" "math/rand" ) @@ -38,9 +39,9 @@ func NewTurtle(env *Environment, actor Actor) *Turtle { turtle.actor = actor turtle.atts = make(map[string]string) if env.Check(turtle.xpos, turtle.ypos) == false { + turtle.setRandomHeading() actor.Setup(env, turtle) env.Occupy(turtle, turtle.xpos, turtle.ypos) - turtle.setRandomHeading() return turtle } } @@ -100,6 +101,11 @@ func (t *Turtle) SetAttribute(name, val string) { t.atts[name] = val } +func (t *Turtle) SetHeading(heading int) { + t.heading =heading +} + + func (t *Turtle) TurnAround() { t.heading = (t.heading + 4) % 8 } @@ -246,6 +252,87 @@ func (t *Turtle) FollowGradient(env *Environment, distance int, threshold float3 } } + +func (t *Turtle) AvoidAverageGradient(env *Environment, distance int, threshold float32, pheromone string) { + + h0 := t.heading - 1 + if h0 < 0 { + h0 = 7 + } + + dx0 := headings[h0][0] * distance + dy0 := headings[h0][1] * distance + + x0 := (t.xpos + dx0) + y0 := (t.ypos + dy0) + + dx := headings[t.heading][0] * distance + dy := headings[t.heading][1] * distance + + x := (t.xpos + dx) + y := (t.ypos + dy) + + h1 := (t.heading + 1) % 8 + dx1 := headings[h1][0] * distance + dy1 := headings[h1][1] * distance + + x1 := (t.xpos + dx1) + y1 := (t.ypos + dy1) + + as0 := env.SniffNormalized(x0, y0, pheromone) + as := env.SniffNormalized(x, y, pheromone) + as1 := env.SniffNormalized(x1, y1, pheromone) + + avg := float64((1 * as0) + (2*as) + (3 *as1) / (as0+as+as1)) + + heading := math.Round(avg) + if heading < 1 && as0 > threshold{ + t.heading = h1 + } else if heading > 2 && as1 > threshold { + t.heading = h0 + } +} + +func (t *Turtle) FollowAverageGradient(env *Environment, distance int, threshold float32, pheromone string) { + + h0 := t.heading - 1 + if h0 < 0 { + h0 = 7 + } + + dx0 := headings[h0][0] * distance + dy0 := headings[h0][1] * distance + + x0 := (t.xpos + dx0) + y0 := (t.ypos + dy0) + + dx := headings[t.heading][0] * distance + dy := headings[t.heading][1] * distance + + x := (t.xpos + dx) + y := (t.ypos + dy) + + h1 := (t.heading + 1) % 8 + dx1 := headings[h1][0] * distance + dy1 := headings[h1][1] * distance + + x1 := (t.xpos + dx1) + y1 := (t.ypos + dy1) + + as0 := env.SniffNormalized(x0, y0, pheromone) + as := env.SniffNormalized(x, y, pheromone) + as1 := env.SniffNormalized(x1, y1, pheromone) + + avg := float64((1 * as0) + (2*as) + (3 *as1) / (as0+as+as1)) + + heading := math.Round(avg) + if heading < 1 && as0 > threshold{ + t.heading = h0 + } else if heading > 2 && as1 > threshold { + t.heading = h1 + } +} + func (t *Turtle) Check(env *Environment) *Turtle { dx := headings[t.heading][0] dy := headings[t.heading][1] diff --git a/experiments/flocking/main.go b/experiments/flocking/main.go index 271cfa4..9919b1d 100644 --- a/experiments/flocking/main.go +++ b/experiments/flocking/main.go @@ -1 +1,63 @@ -package flocking +package main + +import ( +"flag" +"git.openprivacy.ca/sarah/microworlds/core" +"git.openprivacy.ca/sarah/microworlds/experiments" +"image/color" +) + +var sniffDistance = flag.Int("sniffDistance", 3, "the distance a turtle can detect pheromone levels from") + +type Bird struct { + +} + +func (sm *Bird) Setup(env *core.Environment, t *core.Turtle) { + t.SetColor(color.RGBA{100, 255, 10, 0}) + //t.SetHeading(5) +} + +func (sm *Bird) Run(env *core.Environment, t *core.Turtle) { + //t.Wiggle() + if t.AmountAll(env,1,"bird") > 1 { + //t.Wiggle() + t.AvoidAverageGradient(env, 1, 2.5, "bird") + //t.Wiggle() + t.Step(env) + t.Drop(env, 2, "bird") + } else if t.AmountAll(env,1,"bird") > 2 { + t.AvoidAverageGradient(env, 1, 1, "bird") + t.Wiggle() + t.Step(env) + t.Drop(env, 1, "bird") + } else { + // t.TurnAround() + // t.Wiggle() + // t.Wiggle() + // t.Wiggle() + t.FollowAverageGradient(env, 5, 1, "bird") + t.FollowAverageGradient(env, 4, 2, "bird") + t.FollowAverageGradient(env, 3, 3, "bird") + //t.FollowAverageGradient(env, 2, 4, "bird") + + t.Step(env) + t.Drop(env, 1, "bird") + } +} + +func main() { + experiment := new(experiments.Experiment) + experiment.InitializeExperiment() + experiment.InitTurtles(func() core.Actor { + sm := new(Bird) + + return sm + }) + experiment.InitPheromone("bird", color.RGBA{0x80, 0xaa, 0x00, 0x00}) + experiment.OnStep = func(environment *core.Environment, turtles []*core.Turtle, i int) { + environment.EvaporateAndDiffuse(0.99, "bird") + } + experiment.Run() +} +