From fc9e8603b5cd6b26d8ce05d86780c7db4fc376eb Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Sun, 29 Sep 2019 15:32:54 -0700 Subject: [PATCH] Separate out Evapouration and Diffusion --- core/environment.go | 49 +++++++++++++++++++++++---- core/turtle.go | 17 ++++++++++ experiments/experiment.go | 8 +++-- experiments/predatorprey/main.go | 1 + experiments/slimemold/main.go | 5 ++- experiments/turtles-and-frogs/main.go | 15 +++++--- graphics/graphics.go | 10 ++---- 7 files changed, 84 insertions(+), 21 deletions(-) diff --git a/core/environment.go b/core/environment.go index 55294df..4e76c6c 100644 --- a/core/environment.go +++ b/core/environment.go @@ -15,6 +15,16 @@ func (e *Environment) Height() int { return e.height } +func (e * Environment) GetPheromones() []string { + keys := make([]string,len(e.state)) + i:=0 + for k,_ := range e.state { + keys[i] = k + i++ + } + return keys +} + func (e *Environment) InitPheromone(name string) { state := make([][]float32, e.width) for x := range state { @@ -102,23 +112,50 @@ func (e *Environment) normXY(x int, y int) (int, int) { return x, y } -func (e *Environment) Evaporate(rate float32, pheromone string) { - //log.Debugf("Evap") - _, exists := e.state[pheromone] - if !exists { - e.InitPheromone(pheromone) +func (e *Environment) Evaporate(rate float32, pheromone string) { + for x := 0; x < e.width; x++ { + for y := 0; y < e.height; y++ { + e.state[pheromone][x][y] = e.state[pheromone][x][y] * rate + } + } +} + +func (e *Environment) EvaporateAndDiffuse(rate float32, pheromone string) { + pheromoneprev := pheromone + "prev" + + e.state[pheromoneprev] = make([][]float32, e.width) + for x := range e.state[pheromoneprev] { + e.state[pheromoneprev][x] = make([]float32, e.height) + for y := 0; y < e.height; y++ { + e.state[pheromoneprev][x][y] = e.state[pheromone][x][y] * rate + } } + pheromoneMap := e.state[pheromoneprev] + for x := 0; x < e.width; x++ { + for y := 0; y < e.height; y++ { + amount := e.state[pheromoneprev][x][y] + + totalAmount := amount + e.sniffNormalized(x-1, y-1, pheromoneMap) + e.sniffNormalized(x, y-1, pheromoneMap) + e.sniffNormalized(x+1, y-1, pheromoneMap) + e.sniffNormalized(x-1, y, pheromoneMap) + e.sniffNormalized(x+1, y, pheromoneMap) + totalAmount += e.sniffNormalized(x-1, y+1, pheromoneMap) + e.sniffNormalized(x, y+1, pheromoneMap) + e.sniffNormalized(x+1, y+1, pheromoneMap) + + e.state[pheromone][x][y] = totalAmount / 9 + } + } +} + +func (e *Environment) Diffuse(pheromone string) { pheromoneprev := pheromone + "prev" e.state[pheromoneprev] = make([][]float32, e.width) for x := range e.state[pheromoneprev] { e.state[pheromoneprev][x] = make([]float32, e.height) } + for x := 0; x < e.width; x++ { for y := 0; y < e.height; y++ { - e.state[pheromoneprev][x][y] = e.state[pheromone][x][y] * rate + e.state[pheromoneprev][x][y] = e.state[pheromone][x][y] } } diff --git a/core/turtle.go b/core/turtle.go index 62bce86..10b8f04 100644 --- a/core/turtle.go +++ b/core/turtle.go @@ -108,6 +108,23 @@ func (t *Turtle) Drop(env *Environment, amount float32, pheromone string) { env.Mark(pheromone, t.xpos, t.ypos, amount) } +func (t *Turtle) AmountAll(env *Environment, distance int, pheromone string) float32 { + total := float32(0) + for i:=0;i<8;i++ { + dx0 := headings[i][0] * distance + dy0 := headings[i][1] * distance + + x0 := (t.xpos + dx0) + y0 := (t.ypos + dy0) + + + + total += env.SniffNormalized(x0, y0, pheromone) + } + + return total +} + func (t *Turtle) Amount(env *Environment, distance int, pheromone string) float32 { h0 := t.heading - 1 if h0 < 0 { diff --git a/experiments/experiment.go b/experiments/experiment.go index 2bf70e0..41f07b6 100644 --- a/experiments/experiment.go +++ b/experiments/experiment.go @@ -25,6 +25,7 @@ type Experiment struct { turtles []*core.Turtle graphics *graphics.Graphics initializedTurtles int + pheromones []string OnStep func(*core.Environment, []*core.Turtle, int) } @@ -46,8 +47,10 @@ func (e *Experiment) InitializeExperiment() { panic(err) } - e.OnStep = func(environment *core.Environment, turtles []*core.Turtle, i int) { - + e.OnStep = func(env *core.Environment, turtles []*core.Turtle, i int) { + for _, name := range e.pheromones { + env.EvaporateAndDiffuse(0.95, name) + } } e.env = core.NewEnvironment(*width, *height) @@ -62,6 +65,7 @@ func (e *Experiment) GetNumTurtles() int { func (e *Experiment) InitPheromone(name string, col color.Color) { e.env.InitPheromone(name) r, g, b, a := col.RGBA() + e.pheromones = append(e.pheromones, name) e.graphics.ColorPheromone(name, [4]uint8{uint8(r), uint8(g), uint8(b), uint8(a)}) } diff --git a/experiments/predatorprey/main.go b/experiments/predatorprey/main.go index b4d500a..702f3c4 100644 --- a/experiments/predatorprey/main.go +++ b/experiments/predatorprey/main.go @@ -115,6 +115,7 @@ func main() { alive := 0 predalive := 0 + env.EvaporateAndDiffuse(0.95, "scent") // Grow Grass x := rand.Intn(env.Width()) y := rand.Intn(env.Height()) diff --git a/experiments/slimemold/main.go b/experiments/slimemold/main.go index e16ac26..85d914b 100644 --- a/experiments/slimemold/main.go +++ b/experiments/slimemold/main.go @@ -14,7 +14,7 @@ type SlimeMold struct { } func (sm *SlimeMold) Setup(env *core.Environment, t *core.Turtle) { - // Do nothing + t.SetColor(color.RGBA{100,255,10,0}) } func (sm *SlimeMold) Run(env *core.Environment, t *core.Turtle) { @@ -33,5 +33,8 @@ func main() { return sm }) experiment.InitPheromone("trail", color.RGBA{0x80, 0xFF, 0x00, 0x00}) + experiment.OnStep = func(environment *core.Environment, turtles []*core.Turtle, i int) { + environment.EvaporateAndDiffuse(0.99, "trail") + } experiment.Run() } diff --git a/experiments/turtles-and-frogs/main.go b/experiments/turtles-and-frogs/main.go index ad7b1cb..66192ad 100644 --- a/experiments/turtles-and-frogs/main.go +++ b/experiments/turtles-and-frogs/main.go @@ -22,9 +22,10 @@ func (sm *Frog) Setup(env *core.Environment, t *core.Turtle) { } func (sm *Frog) Run(env *core.Environment, t *core.Turtle) { + t.FollowGradient(env,1,1,"frog-scent") t.Wiggle() - amountTurtle := t.Amount(env, 1, "turtle-scent") - amountFrog := t.Amount(env, 1, "frog-scent") + amountTurtle := t.AmountAll(env, 1, "turtle-scent") + amountFrog := t.AmountAll(env, 1, "frog-scent") if amountFrog > 1 && amountFrog > (amountTurtle+amountFrog)*float32(*frogPreference) { // Do Nothing } else { @@ -45,9 +46,10 @@ func (sm *Turtle) Setup(env *core.Environment, t *core.Turtle) { } func (sm *Turtle) Run(env *core.Environment, t *core.Turtle) { + t.FollowGradient(env,1,1,"turtle-scent") t.Wiggle() - amountTurtle := t.Amount(env, 1, "turtle-scent") - amountFrog := t.Amount(env, 1, "frog-scent") + amountTurtle := t.AmountAll(env, 1, "turtle-scent") + amountFrog := t.AmountAll(env, 1, "frog-scent") if amountTurtle > 1 && amountTurtle > (amountTurtle+amountFrog)*float32(*turtlePreference) { // Do Nothing } else { @@ -74,5 +76,10 @@ func main() { experiment.InitPheromone("turtle-scent", color.RGBA{0xFF, 0x00, 0x00, 0x00}) experiment.InitPheromone("frog-scent", color.RGBA{0x00, 0xFF, 0xFF, 0x00}) + experiment.OnStep = func(env *core.Environment, turtles []*core.Turtle, i int) { + env.Evaporate(.99, "turtle-scent") + env.Evaporate(.99, "frog-scent") + } + experiment.Run() } diff --git a/graphics/graphics.go b/graphics/graphics.go index ca3f462..a5793a0 100644 --- a/graphics/graphics.go +++ b/graphics/graphics.go @@ -6,7 +6,6 @@ import ( "github.com/veandco/go-sdl2/sdl" "math" "os" - "strconv" // "strconv" ) @@ -98,14 +97,9 @@ func (g *Graphics) Render(env *core.Environment, turtles []*core.Turtle) { t.Run(env) } - // TODO: Move this into an environment specification - for name := range g.colorMap { - env.Evaporate(0.95, name) - } - g.renderer.Present() g.window.UpdateSurface() - surface, _ := g.window.GetSurface() - surface.SaveBMP("./images/" + strconv.Itoa(g.t) + ".bmp") +// surface, _ := g.window.GetSurface() +// surface.SaveBMP("./images/" + strconv.Itoa(g.t) + ".bmp") g.t++ }