Small fix + fmt

This commit is contained in:
Sarah Jamie Lewis 2019-08-02 22:14:56 -07:00
parent f888eea668
commit 56f0e4f487
9 changed files with 126 additions and 155 deletions

View File

@ -4,18 +4,17 @@ import (
"git.openprivacy.ca/sarah/microworlds/core" "git.openprivacy.ca/sarah/microworlds/core"
) )
type Ant struct { type Ant struct {
SniffDistance int SniffDistance int
Carrying bool Carrying bool
DropSize float32 DropSize float32
} }
func (a * Ant) Setup(env *core.Environment, t *core.Turtle) { func (a *Ant) Setup(env *core.Environment, t *core.Turtle) {
//t.SetXY(150,150) //t.SetXY(150,150)
} }
func (a*Ant) Run(env *core.Environment, t *core.Turtle) { func (a *Ant) Run(env *core.Environment, t *core.Turtle) {
if a.Carrying == false { if a.Carrying == false {
if env.HasValue(t.Pos()) { if env.HasValue(t.Pos()) {
env.TakeValue(t.Pos()) env.TakeValue(t.Pos())
@ -27,11 +26,10 @@ func (a*Ant) Run(env *core.Environment, t *core.Turtle) {
t.FollowGradient(env, a.SniffDistance, 5) t.FollowGradient(env, a.SniffDistance, 5)
} }
t.Step(env) t.Step(env)
} else if a.Carrying == true { } else if a.Carrying == true {
a.DropSize -= 0.6 a.DropSize -= 0.6
t.Drop(env, a.DropSize) t.Drop(env, a.DropSize)
t.Wiggle() t.Wiggle()
t.Step(env) t.Step(env)
} }
} }

View File

@ -8,11 +8,11 @@ type SlimeMold struct {
SniffDistance int SniffDistance int
} }
func(sm * SlimeMold) Setup(env *core.Environment, t *core.Turtle) { func (sm *SlimeMold) Setup(env *core.Environment, t *core.Turtle) {
// Do nothing // Do nothing
} }
func (sm * SlimeMold) Run(env *core.Environment, t *core.Turtle) { func (sm *SlimeMold) Run(env *core.Environment, t *core.Turtle) {
t.Wiggle() t.Wiggle()
t.FollowGradient(env, sm.SniffDistance, 2) t.FollowGradient(env, sm.SniffDistance, 2)
t.Step(env) t.Step(env)

View File

@ -6,20 +6,20 @@ import (
type WoodChips struct { type WoodChips struct {
SniffDistance int SniffDistance int
Carrying bool Carrying bool
} }
func (a * WoodChips) Setup(env *core.Environment, t *core.Turtle) { func (a *WoodChips) Setup(env *core.Environment, t *core.Turtle) {
//t.SetXY(150,150) //t.SetXY(150,150)
} }
func (a*WoodChips) Run(env *core.Environment, t *core.Turtle) { func (a *WoodChips) Run(env *core.Environment, t *core.Turtle) {
if a.Carrying { if a.Carrying {
if env.HasValue(t.Pos()) { if env.HasValue(t.Pos()) {
for { for {
t.Wiggle() t.Wiggle()
t.Step(env) t.Step(env)
if !env.HasValue(t.Pos()){ if !env.HasValue(t.Pos()) {
env.PutValue(t.Pos()) env.PutValue(t.Pos())
a.Carrying = false a.Carrying = false
break break
@ -35,4 +35,4 @@ func (a*WoodChips) Run(env *core.Environment, t *core.Turtle) {
} }
t.Wiggle() t.Wiggle()
t.Step(env) t.Step(env)
} }

View File

@ -1,18 +1,17 @@
package core package core
type Environment struct { type Environment struct {
width,height int width, height int
state [][]float32 state [][]float32
pstate [][]float32 pstate [][]float32
value [][]bool value [][]bool
col [][]bool col [][]bool
} }
func (e *Environment) Width() int { func (e *Environment) Width() int {
return e.width return e.width
} }
func (e *Environment) Height() int { func (e *Environment) Height() int {
return e.height return e.height
} }
@ -37,95 +36,88 @@ func NewEnvironment(width int, height int) *Environment {
return env return env
} }
func (e *Environment) Mark(x,y int,amount float32) { func (e *Environment) Mark(x, y int, amount float32) {
e.state[x][y] = e.state[x][y] + amount e.state[x][y] = e.state[x][y] + amount
if e.state[x][y] > 255 { if e.state[x][y] > 255 {
e.state[x][y] = 255 e.state[x][y] = 255
} }
//log.Debugf("Marking: %d %d %f", x, y, e.state[x][y])
} }
func (e Environment) Occupy(x, y int) {
func (e Environment) Occupy(x,y int) {
e.col[x][y] = true e.col[x][y] = true
} }
func (e Environment) Check(x,y int) bool { func (e Environment) Check(x, y int) bool {
return e.col[x][y] return e.col[x][y]
} }
func (e Environment) Leave(x,y int) { func (e Environment) Leave(x, y int) {
e.col[x][y] = false e.col[x][y] = false
} }
func (e Environment) HasValue(x, y int) bool {
func (e Environment) HasValue(x,y int) bool {
return e.value[x][y] return e.value[x][y]
} }
func (e Environment) PutValue(x,y int) { func (e Environment) PutValue(x, y int) {
e.value[x][y] = true e.value[x][y] = true
} }
func (e Environment) TakeValue(x,y int) { func (e Environment) TakeValue(x, y int) {
e.value[x][y] = false e.value[x][y] = false
} }
func (e Environment) Sniff(x,y int) float32 { func (e Environment) Sniff(x, y int) float32 {
return e.state[x][y] return e.state[x][y]
} }
func (e *Environment) normXY(x int, y int) (int, int) {
func (e *Environment) normXY(x int, y int) (int,int) {
if x < 0 { if x < 0 {
x = (e.width - 1) x = (e.width - 1)
} else if x >= e.width { } else if x >= e.width {
x = x % (e.width ) x = x % (e.width)
} }
if y< 0 { if y < 0 {
y = (e.height - 1) y = (e.height - 1)
} else if y >= e.height { } else if y >= e.height {
y = y % (e.height) y = y % (e.height)
} }
return x,y return x, y
} }
func (e *Environment) Evaporate(rate float32) { func (e *Environment) Evaporate(rate float32) {
//log.Debugf("Evap") //log.Debugf("Evap")
e.pstate = make([][]float32, e.width) e.pstate = make([][]float32, e.width)
for x := range e.pstate { for x := range e.pstate {
e.pstate[x] = make([]float32, e.height) e.pstate[x] = make([]float32, e.height)
} }
for x:=0;x<e.width;x++ { for x := 0; x < e.width; x++ {
for y := 0; y < e.height; y++ { for y := 0; y < e.height; y++ {
e.pstate[x][y] = e.state[x][y] * rate e.pstate[x][y] = e.state[x][y] * rate
} }
} }
for x := 0; x < e.width; x++ {
for x:=0;x<e.width;x++ { for y := 0; y < e.height; y++ {
for y:=0;y<e.height;y++ {
amount := e.pstate[x][y] amount := e.pstate[x][y]
totalAmount := amount + e.NormalizeSniff(x-1,y-1) + e.NormalizeSniff(x,y-1) + e.NormalizeSniff(x+1,y-1) + e.NormalizeSniff(x-1,y) + e.NormalizeSniff(x+1,y) totalAmount := amount + e.NormalizeSniff(x-1, y-1) + e.NormalizeSniff(x, y-1) + e.NormalizeSniff(x+1, y-1) + e.NormalizeSniff(x-1, y) + e.NormalizeSniff(x+1, y)
totalAmount += e.NormalizeSniff(x-1,y+1) + e.NormalizeSniff(x,y+1) +e.NormalizeSniff(x+1,y+1) totalAmount += e.NormalizeSniff(x-1, y+1) + e.NormalizeSniff(x, y+1) + e.NormalizeSniff(x+1, y+1)
e.state[x][y] = totalAmount/9 e.state[x][y] = totalAmount / 9
} }
} }
} }
func (e *Environment) SniffNormalized(x int, y int) float32 { func (e *Environment) SniffNormalized(x int, y int) float32 {
x,y = e.normXY(x,y) x, y = e.normXY(x, y)
return e.state[x][y] return e.state[x][y]
} }
func (e *Environment) NormalizeSniff(x int, y int) float32 { func (e *Environment) NormalizeSniff(x int, y int) float32 {
x,y = e.normXY(x,y) x, y = e.normXY(x, y)
return e.pstate[x][y] return e.pstate[x][y]
} }

View File

@ -5,20 +5,20 @@ import (
) )
func TestEnvironment_Mark(t *testing.T) { func TestEnvironment_Mark(t *testing.T) {
env := NewEnvironment(3,3) env := NewEnvironment(3, 3)
env.Mark(1,1,9) env.Mark(1, 1, 9)
env.Evaporate(0.9) env.Evaporate(0.9)
for x:=0;x<3;x++ { for x := 0; x < 3; x++ {
for y:=0;y<3;y++ { for y := 0; y < 3; y++ {
t.Logf("mark(%d,%d) = %f", x,y,env.Sniff(x,y)) t.Logf("mark(%d,%d) = %f", x, y, env.Sniff(x, y))
} }
} }
t.Logf("\n") t.Logf("\n")
env.Evaporate(0.9) env.Evaporate(0.9)
for x:=0;x<3;x++ { for x := 0; x < 3; x++ {
for y:=0;y<3;y++ { for y := 0; y < 3; y++ {
t.Logf("mark(%d,%d) = %f", x,y,env.Sniff(x,y)) t.Logf("mark(%d,%d) = %f", x, y, env.Sniff(x, y))
} }
} }
} }

View File

@ -6,13 +6,11 @@ import (
type Turtle struct { type Turtle struct {
xpos, ypos int xpos, ypos int
heading int heading int
actor Actor actor Actor
} }
type NilActor struct { type NilActor struct {
} }
func (NilActor) Setup(*Environment, *Turtle) { func (NilActor) Setup(*Environment, *Turtle) {
@ -28,7 +26,7 @@ func NewTurtle(env *Environment, actor Actor) *Turtle {
turtle.ypos = rand.Intn(env.height) turtle.ypos = rand.Intn(env.height)
turtle.actor = actor turtle.actor = actor
if env.Check(turtle.xpos, turtle.ypos) == false { if env.Check(turtle.xpos, turtle.ypos) == false {
actor.Setup(env,turtle) actor.Setup(env, turtle)
env.Occupy(turtle.xpos, turtle.ypos) env.Occupy(turtle.xpos, turtle.ypos)
turtle.setRandomHeading() turtle.setRandomHeading()
return turtle return turtle
@ -37,24 +35,23 @@ func NewTurtle(env *Environment, actor Actor) *Turtle {
} }
func (t *Turtle) Pos() (int,int) { func (t *Turtle) Pos() (int, int) {
return t.xpos,t.ypos return t.xpos, t.ypos
} }
var headings = [][]int{{-1,-1},{0,-1},{1,-1},{1,0},{1,1},{0,1},{-1,1},{-1,0}} var headings = [][]int{{-1, -1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}}
func (t *Turtle) setRandomHeading() { func (t *Turtle) setRandomHeading() {
t.heading = rand.Intn(8) t.heading = rand.Intn(8)
} }
func (t *Turtle) SetXY(x,y int) { func (t *Turtle) SetXY(x, y int) {
t.xpos = x t.xpos = x
t.ypos = y t.ypos = y
} }
func (t *Turtle) Wiggle() { func (t *Turtle) Wiggle() {
wiggle := rand.Intn(3) - 1 wiggle := rand.Intn(3) - 1
h := (t.heading + wiggle) % 8 h := (t.heading + wiggle) % 8
if h < 0 { if h < 0 {
h = 7 h = 7
@ -62,19 +59,17 @@ func (t *Turtle) Wiggle() {
t.heading = h t.heading = h
} }
func (t *Turtle) TurnAround() {
func (t*Turtle) TurnAround() {
t.heading = (t.heading + 4) % 8 t.heading = (t.heading + 4) % 8
} }
func (t *Turtle) Drop(env *Environment, amount float32) {
func (t*Turtle) Drop(env *Environment, amount float32) { env.Mark(t.xpos, t.ypos, amount)
env.Mark(t.xpos,t.ypos, amount)
} }
func (t *Turtle) FollowGradient(env *Environment, distance int, threshold float32 ) { func (t *Turtle) FollowGradient(env *Environment, distance int, threshold float32) {
h0 := t.heading-1 h0 := t.heading - 1
if h0 < 0 { if h0 < 0 {
h0 = 7 h0 = 7
} }
@ -82,71 +77,69 @@ func (t *Turtle) FollowGradient(env *Environment, distance int, threshold float3
dx0 := headings[h0][0] * distance dx0 := headings[h0][0] * distance
dy0 := headings[h0][1] * distance dy0 := headings[h0][1] * distance
x0 := (t.xpos + dx0) x0 := (t.xpos + dx0)
y0 := (t.ypos + dy0) y0 := (t.ypos + dy0)
dx := headings[t.heading][0] * distance dx := headings[t.heading][0] * distance
dy := headings[t.heading][1] * distance dy := headings[t.heading][1] * distance
x := (t.xpos + dx) x := (t.xpos + dx)
y := (t.ypos + dy) y := (t.ypos + dy)
h1 := (t.heading + 1) % 8
h1 := (t.heading+1) % 8
dx1 := headings[h1][0] * distance dx1 := headings[h1][0] * distance
dy1 := headings[h1][1] * distance dy1 := headings[h1][1] * distance
x1 := (t.xpos + dx1) x1 := (t.xpos + dx1)
y1 := (t.ypos + dy1) y1 := (t.ypos + dy1)
as0 := env.SniffNormalized(x0,y0) as0 := env.SniffNormalized(x0, y0)
if as0 < threshold { if as0 < threshold {
as0 = 0 as0 = 0
} }
as := env.SniffNormalized(x,y) as := env.SniffNormalized(x, y)
if as < threshold { if as < threshold {
as = 0 as = 0
} }
as1 := env.SniffNormalized(x1,y1) as1 := env.SniffNormalized(x1, y1)
if as1 < threshold { if as1 < threshold {
as1 = 0 as1 = 0
} }
if as0 > as && as0 > as1{ if as0 > as && as0 > as1 {
t.heading = h0 t.heading = h0
} else if as1 > as && as1 > as0 { } else if as1 > as && as1 > as0 {
t.heading = h1 t.heading = h1
} }
} }
func (t* Turtle) Step(env *Environment) bool { func (t *Turtle) Step(env *Environment) bool {
dx := headings[t.heading][0] dx := headings[t.heading][0]
dy := headings[t.heading][1] dy := headings[t.heading][1]
ox := t.xpos ox := t.xpos
oy := t.ypos oy := t.ypos
env.Leave(ox,oy) env.Leave(ox, oy)
t.xpos = (t.xpos + dx) % (env.width -1) t.xpos = (t.xpos + dx) % (env.width)
if t.xpos < 0 { if t.xpos < 0 {
t.xpos = env.width-1 t.xpos = env.width - 1
} }
t.ypos = (t.ypos + dy) % (env.height -1) t.ypos = (t.ypos + dy) % (env.height)
if t.ypos < 0 { if t.ypos < 0 {
t.ypos = env.height-1 t.ypos = env.height - 1
} }
success := true success := true
if env.Check(t.xpos,t.ypos) == true { if env.Check(t.xpos, t.ypos) == true {
t.xpos = ox t.xpos = ox
t.ypos = oy t.ypos = oy
success = false success = false
} }
env.Occupy(t.xpos,t.ypos) env.Occupy(t.xpos, t.ypos)
return success return success
} }
// Run the turtle program // Run the turtle program
func (t * Turtle) Run(env * Environment) { func (t *Turtle) Run(env *Environment) {
//log.Debugf("Pos: %v %v", t.xpos, t.ypos)
t.actor.Run(env, t) t.actor.Run(env, t)
} }

View File

@ -5,12 +5,12 @@ import (
) )
func TestTurtle_Wiggle(t *testing.T) { func TestTurtle_Wiggle(t *testing.T) {
turtle := NewTurtle(NewEnvironment(3,3,), new(NilActor)) turtle := NewTurtle(NewEnvironment(3, 3), new(NilActor))
counts := []int{0,0,0,0,0,0,0,0} counts := []int{0, 0, 0, 0, 0, 0, 0, 0}
for i:=0;i<1000;i++ { for i := 0; i < 1000; i++ {
turtle.Wiggle() turtle.Wiggle()
//t.Logf("Heading %v", turtle.heading) //t.Logf("Heading %v", turtle.heading)
counts[turtle.heading]++ counts[turtle.heading]++
} }
t.Logf("Heading %v", counts) t.Logf("Heading %v", counts)
} }

View File

@ -10,16 +10,16 @@ import (
) )
type Graphics struct { type Graphics struct {
window *sdl.Window window *sdl.Window
renderer *sdl.Renderer renderer *sdl.Renderer
width, height int32 width, height int32
t int t int
} }
func NewGraphics(width, height int32) *Graphics { func NewGraphics(width, height int32) *Graphics {
graphics := new(Graphics) graphics := new(Graphics)
graphics.width = width graphics.width = width
graphics.height= height graphics.height = height
window, err := sdl.CreateWindow("Microworlds", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, window, err := sdl.CreateWindow("Microworlds", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED,
width, height, sdl.WINDOW_SHOWN) width, height, sdl.WINDOW_SHOWN)
if err != nil { if err != nil {
@ -27,7 +27,7 @@ func NewGraphics(width, height int32) *Graphics {
} }
graphics.window = window graphics.window = window
surface,_ := window.GetSurface() surface, _ := window.GetSurface()
renderer, err := sdl.CreateSoftwareRenderer(surface) renderer, err := sdl.CreateSoftwareRenderer(surface)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Failed to create renderer: %s\n", err) fmt.Fprintf(os.Stderr, "Failed to create renderer: %s\n", err)
@ -37,44 +37,41 @@ func NewGraphics(width, height int32) *Graphics {
return graphics return graphics
} }
func (g* Graphics) Render(env *core.Environment, turtles []*core.Turtle) { func (g *Graphics) Render(env *core.Environment, turtles []*core.Turtle) {
g.renderer.SetDrawColor(0x00,0x00,0x00,0x00) g.renderer.SetDrawColor(0x00, 0x00, 0x00, 0x00)
g.renderer.FillRect(&sdl.Rect{0,0,600,600}) g.renderer.FillRect(&sdl.Rect{0, 0, 600, 600})
for x := 0; x < int(g.width); x++ {
for y := 0; y < int(g.height); y++ {
for x:=0;x<int(g.width);x++ { amount := math.Min(float64(env.Sniff(x, y)), 255)
for y:=0;y<int(g.height);y++ {
amount := math.Min(float64(env.Sniff(x,y)), 255)
if amount > 0 { if amount > 0 {
col := uint8(amount*0x81) col := uint8(amount * 0x81)
if col > 0x81 { if col > 0x81 {
col = 0x81 col = 0x81
} }
g.renderer.SetDrawColor(col,0,col, uint8(255) ) g.renderer.SetDrawColor(col, 0, col, uint8(255))
g.renderer.DrawPoint(int32(x), int32(y)) g.renderer.DrawPoint(int32(x), int32(y))
} }
if env.HasValue(x,y) { if env.HasValue(x, y) {
g.renderer.SetDrawColor(255,255,255, uint8(255) ) g.renderer.SetDrawColor(255, 255, 255, uint8(255))
g.renderer.DrawPoint(int32(x), int32(y)) g.renderer.DrawPoint(int32(x), int32(y))
} }
} }
} }
g.renderer.SetDrawColor(0xF3, 0x81, 0, 0x00)
g.renderer.SetDrawColor(0xF3,0x81,0,0x00) for _, t := range turtles {
for _,t := range turtles { x, y := t.Pos()
x,y := t.Pos() g.renderer.DrawPoint(int32(x), int32(y))
g.renderer.DrawPoint(int32(x),int32(y))
t.Run(env) t.Run(env)
} }
env.Evaporate(0.95) env.Evaporate(0.95)
g.renderer.Present() g.renderer.Present()
g.window.UpdateSurface() g.window.UpdateSurface()
surface,_ := g.window.GetSurface() surface, _ := g.window.GetSurface()
surface.SaveBMP("./images/"+ strconv.Itoa(g.t)+".bmp") surface.SaveBMP("./images/" + strconv.Itoa(g.t) + ".bmp")
g.t++; g.t++
} }

51
main.go
View File

@ -14,7 +14,6 @@ import (
"time" "time"
) )
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file") var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
var model = flag.String("model", "slime", "slimemold|swarm|woodchips") var model = flag.String("model", "slime", "slimemold|swarm|woodchips")
@ -23,8 +22,6 @@ var width = flag.Int("width", 300, "width of environment")
var height = flag.Int("height", 300, "height of environment") var height = flag.Int("height", 300, "height of environment")
var numTurtles = flag.Int("numTurtles", 5000, "number of turtles") var numTurtles = flag.Int("numTurtles", 5000, "number of turtles")
func main() { func main() {
// We don't need real randomness // We don't need real randomness
@ -45,54 +42,50 @@ func main() {
} }
defer sdl.Quit() defer sdl.Quit()
env := core.NewEnvironment(*width, *height)
env := core.NewEnvironment(*width,*height) turtles := make([]*core.Turtle, *numTurtles)
turtles := make([]*core.Turtle,*numTurtles)
switch *model { switch *model {
case "swarm": case "swarm":
// Create 2 food blocks // Create 2 food blocks
for x:= 100;x<110;x++ { for x := 100; x < 110; x++ {
for y:= 100;y<110;y++ { for y := 100; y < 110; y++ {
env.PutValue(x,y) env.PutValue(x, y)
} }
} }
for x:= 200;x<210;x++ { for x := 200; x < 210; x++ {
for y:= 200;y<210;y++ { for y := 200; y < 210; y++ {
env.PutValue(x,y) env.PutValue(x, y)
} }
} }
for i:=0;i<*numTurtles;i++ { for i := 0; i < *numTurtles; i++ {
turtles[i] = core.NewTurtle(env, &actors.Ant{SniffDistance:3, Carrying:false}) turtles[i] = core.NewTurtle(env, &actors.Ant{SniffDistance: 3, Carrying: false})
} }
case "woodchips": case "woodchips":
for x := 0;x<*numTurtles;x++ { for x := 0; x < *numTurtles; x++ {
env.PutValue(rand.Intn(*width), rand.Intn(*height)) env.PutValue(rand.Intn(*width), rand.Intn(*height))
} }
for x:= 200;x<210;x++ { for x := 200; x < 210; x++ {
for y:= 200;y<210;y++ { for y := 200; y < 210; y++ {
env.PutValue(x,y) env.PutValue(x, y)
} }
} }
for i:=0;i<*numTurtles;i++ { for i := 0; i < *numTurtles; i++ {
turtles[i] = core.NewTurtle(env, &actors.WoodChips{SniffDistance:20, Carrying:false}) turtles[i] = core.NewTurtle(env, &actors.WoodChips{SniffDistance: 20, Carrying: false})
} }
case "slimemold": case "slimemold":
for i:=0;i<*numTurtles;i++ { for i := 0; i < *numTurtles; i++ {
turtles[i] = core.NewTurtle(env, &actors.SlimeMold{SniffDistance:20}) turtles[i] = core.NewTurtle(env, &actors.SlimeMold{SniffDistance: 20})
} }
default: default:
for i:=0;i<*numTurtles;i++ { for i := 0; i < *numTurtles; i++ {
turtles[i] = core.NewTurtle(env, &actors.SlimeMold{SniffDistance:20}) turtles[i] = core.NewTurtle(env, &actors.SlimeMold{SniffDistance: 20})
} }
} }
g := graphics.NewGraphics(int32(*width), int32(*height))
g := graphics.NewGraphics(int32(*width),int32(*height))
running := true running := true
wait := sync.WaitGroup{} wait := sync.WaitGroup{}
@ -105,7 +98,6 @@ func main() {
wait.Done() wait.Done()
}() }()
wait.Add(1) wait.Add(1)
for running { for running {
for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() { for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
@ -119,4 +111,3 @@ func main() {
wait.Done() wait.Done()
wait.Wait() wait.Wait()
} }