diff --git a/core/environment.go b/core/environment.go index 6fa632f..e3124b1 100644 --- a/core/environment.go +++ b/core/environment.go @@ -5,6 +5,7 @@ type Environment struct { state map[string][][]float32 value [][]bool col [][]*Turtle + Step int } func (e *Environment) Width() int { diff --git a/core/turtle.go b/core/turtle.go index 5bb0226..e53c298 100644 --- a/core/turtle.go +++ b/core/turtle.go @@ -28,6 +28,10 @@ func (t *Turtle) GetActor() Actor { return t.actor } +func (t *Turtle) Heading() int { + return t.heading +} + func NewTurtle(env *Environment, actor Actor) *Turtle { for i := 0; i < 5; i++ { diff --git a/experiments/experiment.go b/experiments/experiment.go index 9a90212..2ee5036 100644 --- a/experiments/experiment.go +++ b/experiments/experiment.go @@ -97,6 +97,8 @@ func (e *Experiment) Run() { go func() { step := 0 for running { + e.env.Step = step + e.graphics.Render(e.env, e.turtles) e.OnStep(e.env, e.turtles, step) diff --git a/experiments/fractal/fractal.go b/experiments/fractal/fractal.go new file mode 100644 index 0000000..6c871a1 --- /dev/null +++ b/experiments/fractal/fractal.go @@ -0,0 +1,64 @@ +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") +var defensiveDecentralization = flag.Bool("defensiveDecentralization", false, "if true, slime molds will break up if the concentration is too great") + + +type SlimeMold struct { + SniffDistance int + Age int + Stuck bool +} + +func (sm *SlimeMold) Setup(env *core.Environment, t *core.Turtle) { + t.SetColor(color.RGBA{100, 255, 10, 0}) +} + +func (sm *SlimeMold) Run(env *core.Environment, t *core.Turtle) { + frac := (float64(sm.Age)/float64(env.Step+1)) + col := uint8(256 * frac) + if env.Step < 100 { + t.SetColor(color.RGBA{col,0,col/2, col}) + } else { + t.SetColor(color.RGBA{col,0,col, col}) + } + if sm.Stuck == false { + sm.Age++ + //t.Wiggle() + //t.Wiggle() + t.Wiggle() + t.Step(env) + c := t.Check(env) + + if c != nil { + s := c.GetActor().(*SlimeMold) + if s.Stuck == true { + sm.Stuck = true + } + } + } +} + +func main() { + experiment := new(experiments.Experiment) + experiment.InitializeExperiment() + n:=0 + experiment.InitTurtles(func() core.Actor { + n++ + sm := new(SlimeMold) + if n == 1 { + sm.Stuck = true + } + return sm + }) + experiment.InitPheromone("trail", color.RGBA{0x80, 0xFF, 0x00, 0x00}) + + experiment.Run() +} diff --git a/experiments/slimemold/main.go b/experiments/slimemold/main.go index a21273a..2ae5b9d 100644 --- a/experiments/slimemold/main.go +++ b/experiments/slimemold/main.go @@ -8,6 +8,8 @@ import ( ) var sniffDistance = flag.Int("sniffDistance", 3, "the distance a turtle can detect pheromone levels from") +var defensiveDecentralization = flag.Bool("defensiveDecentralization", false, "if true, slime molds will break up if the concentration is too great") + type SlimeMold struct { SniffDistance int @@ -19,7 +21,14 @@ func (sm *SlimeMold) Setup(env *core.Environment, t *core.Turtle) { func (sm *SlimeMold) Run(env *core.Environment, t *core.Turtle) { t.Wiggle() - t.FollowGradient(env, sm.SniffDistance, 2, "trail") + if *defensiveDecentralization == false { + t.FollowGradient(env, sm.SniffDistance, 2, "trail") + } else if t.Amount(env,sm.SniffDistance,"trail") < 5.2 { + t.FollowGradient(env, sm.SniffDistance, 2, "trail") + } else { + //t.FollowGradient(env, sm.SniffDistance, 2, "trail") + //t.TurnAround() + } t.Step(env) t.Drop(env, 1, "trail") } @@ -33,8 +42,6 @@ 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.95, "trail") - } + experiment.Run() } diff --git a/experiments/slimemold/pathfinding/main.go b/experiments/slimemold/pathfinding/main.go new file mode 100644 index 0000000..230df81 --- /dev/null +++ b/experiments/slimemold/pathfinding/main.go @@ -0,0 +1,49 @@ +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") +var defensiveDecentralization = flag.Bool("defensiveDecentralization", false, "if true, slime molds will break up if the concentration is too great") + + +type SlimeMold struct { + SniffDistance int +} + +func (sm *SlimeMold) Setup(env *core.Environment, t *core.Turtle) { + t.SetColor(color.RGBA{100, 255, 10, 0}) +} + +func (sm *SlimeMold) Run(env *core.Environment, t *core.Turtle) { + t.Wiggle() + if *defensiveDecentralization == false { + t.FollowGradient(env, sm.SniffDistance, 2, "trail") + } else if t.Amount(env,sm.SniffDistance,"trail") < 5.2 { + t.FollowGradient(env, sm.SniffDistance, 2, "trail") + } else { + //t.FollowGradient(env, sm.SniffDistance, 2, "trail") + //t.TurnAround() + } + t.Step(env) + t.Drop(env, 1, "trail") +} + +func main() { + experiment := new(experiments.Experiment) + experiment.InitializeExperiment() + experiment.InitTurtles(func() core.Actor { + sm := new(SlimeMold) + sm.SniffDistance = *sniffDistance + 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.95, "trail") + } + experiment.Run() +} diff --git a/experiments/swarm/main.go b/experiments/swarm/main.go index b12f0fe..7a29399 100644 --- a/experiments/swarm/main.go +++ b/experiments/swarm/main.go @@ -7,60 +7,127 @@ import ( "image/color" ) -var sniffDistance = flag.Int("sniffDistance", 3, "the distance an ant can detect pheromone levels from") +var sniffDistance = flag.Int("sniffDistance", 30, "the distance an ant can detect pheromone levels from") var dropSize = flag.Float64("dropSize", 1.0, "the amount of pheromone an ants drops") +type Wall struct { +} + +func (a *Wall) Setup(env *core.Environment, t *core.Turtle) { + t.SetColor(color.RGBA{0xff, 0, 0, 0xff}) +} +func (a *Wall) Run(env *core.Environment, t *core.Turtle) { + +} + type Ant struct { SniffDistance int Carrying bool DropSize float64 + Num int + Heading int +} + +var W = 1 + +var maze = [][]int{ + {W, W, W, W, W, W, W, W, W, W, W, W, W, W, W}, + {W, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, W}, + {W, 0, W, W, W, W, W, 0, W, 0, W, 0, W, 0, W}, + {W, 0, W, 0, 0, 0, 0, 0, W, 0, W, 0, W, 0, W}, + {W, 0, W, 0, W, W, W, W, W, 0, W, 0, W, 0, W}, + {W, 0, W, 0, W, 0, 0, 0, 0, 0, W, 0, W, 0, W}, + {W, 0, W, 0, W, 0, W, W, W, 0, W, 0, W, 0, W}, + {W, 0, 0, 0, W, 0, 0, 0, W, 0, W, W, W, 0, W}, + {W, 0, W, 0, W, W, 0, W, W, 0, W, 0, W, 0, W}, + {W, 0, W, 0, W, 0, 0, W, 0, 0, W, 0, W, 0, W}, + {W, 0, W, 0, W, W, 0, W, 0, W, W, 0, 0, 0, W}, + {W, 2, W, 0, W, 0, 0, W, 0, 0, 0, 0, W, 0, W}, + {W, 2, W, 0, W, 0, W, W, W, W, W, 0, W, 0, W}, + {W, 2, W, 0, W, 0, 0, W, 0, 0, 0, 0, W, 2, W}, + {W, W, W, W, W, W, W, W, W, W, W, W, W, W, W}, } func (a *Ant) Setup(env *core.Environment, t *core.Turtle) { + //t.SetColor(color.RGBA{0x67,0xf5,0x10,0xff}) + + //t.SetXY(40+(a.Num %70),50+(a.Num/50)) } func (a *Ant) Run(env *core.Environment, t *core.Turtle) { - if a.Carrying == false { - if env.HasValue(t.Pos()) { - env.TakeValue(t.Pos()) - a.Carrying = true - a.DropSize = 100 - t.TurnAround() - } else { - t.Wiggle() - t.FollowGradient(env, a.SniffDistance, 5, "food") + a.Heading = t.Heading() + if env.HasValue(t.Pos()) || a.Carrying { + t.Drop(env, 255, "slime") + a.Carrying = true + } else { + n := t.Check(env) + if n != nil { + ant,ok := n.GetActor().(*Ant) + if ok { + if ant.Carrying { + a.DropSize += 10 + t.SetHeading(a.Heading) + } else if ant.DropSize > 20{ + t.SetHeading(a.Heading) + a.DropSize += 5 + } else if ant.DropSize > 1 { + t.Wiggle() + a.DropSize += 5 + } + } } - t.Step(env) - } else if a.Carrying == true { - a.DropSize -= 0.6 - t.Drop(env, float32(a.DropSize), "food") + + + } + + if a.DropSize < 10 { + t.SetColor(color.RGBA{0, 0xf5, 0x10, 0x1f}) + t.FollowGradient(env, a.SniffDistance, 20, "slime") t.Wiggle() t.Step(env) } + + if a.DropSize > 1 { + a.DropSize-- + t.SetColor(color.RGBA{0xff,0xf5,0, 0x1f}) + t.Drop(env, float32(a.DropSize), "slime") + } } func main() { experiment := new(experiments.Experiment) experiment.InitializeExperiment() + t := new(core.Turtle) + t.SetColor(color.RGBA{255, 0, 0, 255}) experiment.InitEnvironment(func(environment *core.Environment) { // Create 2 food piles - for x := 100; x < 110; x++ { - for y := 100; y < 110; y++ { - environment.PutValue(x, y) - } - } - for x := 200; x < 210; x++ { - for y := 200; y < 210; y++ { - environment.PutValue(x, y) + + for x := 0; x < 300; x++ { + for y := 0; y < 300; y++ { + if maze[y/20][x/20] == 1 { + //if ((x %20 < 10) && (y% 20<10)) || x < 30 || y < 30 || y > 270 || x > 270 || (x <100 && y>200) || ((x>150 && x < 300) && (y > 150 && y<175)) || ((x>150 && x < 180) && (y > 100 && y<175)){ + environment.Occupy(t, x, y) + } else if maze[y/20][x/20] == 2 { + environment.PutValue(x, y) + } + /// } } } }) + + i := 0 experiment.InitTurtles(func() core.Actor { sm := new(Ant) sm.SniffDistance = *sniffDistance - sm.DropSize = *dropSize + sm.DropSize = 0 + sm.Num = i + i++ return sm }) - experiment.InitPheromone("food", color.RGBA{0x81, 0x81, 0x12, 0x00}) + + experiment.InitPheromone("slime", color.RGBA{0xff, 0xfF, 0x00, 0xff}) + experiment.OnStep = func(environment *core.Environment, turtles []*core.Turtle, i int) { + environment.EvaporateAndDiffuse(0.5, "slime") + } experiment.Run() } diff --git a/go.mod b/go.mod index aa37a28..761a439 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module git.openprivacy.ca/sarah/microworlds -require github.com/veandco/go-sdl2 v0.3.0 +go 1.13 + +require github.com/veandco/go-sdl2 v0.3.3 diff --git a/go.sum b/go.sum index ba294e4..2369cc0 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,6 @@ github.com/veandco/go-sdl2 v0.3.0 h1:IWYkHMp8V3v37NsKjszln8FFnX2+ab0538J371t+rss= github.com/veandco/go-sdl2 v0.3.0/go.mod h1:FB+kTpX9YTE+urhYiClnRzpOXbiWgaU3+5F2AB78DPg= +github.com/veandco/go-sdl2 v0.3.1 h1:WMQ72+BeCj2o/zOO/wsB4MMpqHr1Y67m6QNFxp053ug= +github.com/veandco/go-sdl2 v0.3.1/go.mod h1:FB+kTpX9YTE+urhYiClnRzpOXbiWgaU3+5F2AB78DPg= +github.com/veandco/go-sdl2 v0.3.3 h1:4/TirgB2MQ7oww3pM3Yfgf1YbChMlAQAmiCPe5koK0I= +github.com/veandco/go-sdl2 v0.3.3/go.mod h1:FB+kTpX9YTE+urhYiClnRzpOXbiWgaU3+5F2AB78DPg= diff --git a/graphics/graphics.go b/graphics/graphics.go index 0bec68b..ccbef58 100644 --- a/graphics/graphics.go +++ b/graphics/graphics.go @@ -83,6 +83,11 @@ func (g *Graphics) Render(env *core.Environment, turtles []*core.Turtle) { g.renderer.SetDrawColor(255, 255, 255, uint8(255)) g.DrawTileColor(int32(x), int32(y)) } + + g.renderer.SetDrawColor(255, 0, 0, uint8(255)) + if env.Get(x,y) != nil { + g.DrawTileColor(int32(x), int32(y)) + } } }