Refactor experiments into separate applications

This commit is contained in:
Sarah Jamie Lewis 2019-09-24 23:38:15 -07:00
parent af28fc7ec0
commit fe96374bee
19 changed files with 565 additions and 518 deletions

View File

@ -1,35 +0,0 @@
package actors
import (
"git.openprivacy.ca/sarah/microworlds/core"
)
type Ant struct {
SniffDistance int
Carrying bool
DropSize float32
}
func (a *Ant) Setup(env *core.Environment, t *core.Turtle) {
//t.SetXY(150,150)
}
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")
}
t.Step(env)
} else if a.Carrying == true {
a.DropSize -= 0.6
t.Drop(env, a.DropSize, "food")
t.Wiggle()
t.Step(env)
}
}

View File

@ -1,35 +0,0 @@
package actors
import (
"git.openprivacy.ca/sarah/microworlds/core"
)
type Flocking struct {
SniffDistance int
}
func (sm *Flocking) Setup(env *core.Environment, t *core.Turtle) {
// Do nothing
}
func (sm *Flocking) Run(env *core.Environment, t *core.Turtle) {
if t.Near(env, 1,1, "avoid") {
t.TurnAround()
t.Step(env)
} else if t.Near(env, 2,1, "avoid") {
t.TurnAround()
t.Step(env)
} else {
t.FollowGradient(env, 4, 1, "trail")
t.FollowGradient(env, 3, 1,"trail")
t.FollowGradient(env, 2,1, "trail")
t.FollowGradient(env, 1, 3, "trail")
t.Wiggle()
t.Step(env)
}
t.Drop(env, 1, "trail")
t.Drop(env, 2, "avoid")
}

View File

@ -1,67 +0,0 @@
package actors
import (
"git.openprivacy.ca/sarah/microworlds/core"
"math/rand"
"strconv"
)
type Isolate struct {
color int
Probability float32
sureness float32
Byztantine bool
}
func (sm *Isolate) Setup(env *core.Environment, t *core.Turtle) {
num := rand.Intn(100)
if num >= int(sm.Probability*100.0) {
sm.color = 2
} else {
sm.color = 1
}
sm.sureness = 2
}
func (sm *Isolate) Run(env *core.Environment, t *core.Turtle) {
if sm.Byztantine {
t.Wiggle()
t.FollowGradient(env, 10,0, "2",)
t.Drop(env, 1, "2")
t.Step(env)
} else {
t.Wiggle()
am1 := t.Amount(env, 1, "1")
am2 := t.Amount(env, 1, "2")
if am1 > sm.sureness || am2 > sm.sureness {
if am1 > am2 {
if sm.color == 2 {
sm.sureness--
} else {
sm.sureness++
}
if sm.sureness == 0 {
sm.color = 1
}
} else if am2 > am1 {
if sm.color == 1 {
sm.sureness--
} else {
sm.sureness++
}
if sm.sureness == 0 {
sm.color = 2
}
}
}
if sm.sureness > 1 {
t.Drop(env, 1, strconv.Itoa(sm.color))
}
t.Step(env)
}
}

View File

@ -1,23 +0,0 @@
package actors
import (
"git.openprivacy.ca/sarah/microworlds/core"
)
type MazeGeneration struct {
SniffDistance int
}
func (sm *MazeGeneration) Setup(env *core.Environment, t *core.Turtle) {
// Do nothing
}
func (sm *MazeGeneration) Run(env *core.Environment, t *core.Turtle) {
t.Wiggle()
t.FollowGradient(env, sm.SniffDistance, 0, "trail")
t.TurnAround() // Run away from the strongest trail
t.Step(env)
t.Drop(env, 1, "trail")
}

View File

@ -1,20 +0,0 @@
package actors
import (
"git.openprivacy.ca/sarah/microworlds/core"
)
type SlimeMold struct {
SniffDistance int
}
func (sm *SlimeMold) Setup(env *core.Environment, t *core.Turtle) {
// Do nothing
}
func (sm *SlimeMold) Run(env *core.Environment, t *core.Turtle) {
t.Wiggle()
t.FollowGradient(env, sm.SniffDistance, 2, "trail")
t.Step(env)
t.Drop(env, 1, "trail")
}

View File

@ -1,41 +0,0 @@
package actors
import (
"git.openprivacy.ca/sarah/microworlds/core"
"math/rand"
"strconv"
)
type Slush struct {
color int
Probability float32
}
func (sm *Slush) Setup(env *core.Environment, t *core.Turtle) {
num := rand.Intn(100)
if num >= int(sm.Probability*100.0) {
sm.color = 2
} else {
sm.color = 1
}
}
func (sm *Slush) Run(env *core.Environment, t *core.Turtle) {
t.Wiggle()
am1 := t.Amount(env,1,"1")
am2 := t.Amount(env,1,"2")
t.Drop(env, 1, strconv.Itoa(sm.color))
if am1 > 3 || am2 > 3 {
if am1 > am2 {
sm.color = 1
} else if am2 > am1 {
sm.color = 2
}
}
t.Step(env)
}

View File

@ -1,65 +0,0 @@
package actors
import (
"git.openprivacy.ca/sarah/microworlds/core"
"math/rand"
"strconv"
)
type Snowball struct {
color int
Probability float32
sureness float32
Byztantine bool
}
func (sm *Snowball) Setup(env *core.Environment, t *core.Turtle) {
num := rand.Intn(100)
if num >= int(sm.Probability*100.0) {
sm.color = 2
} else {
sm.color = 1
}
sm.sureness = 2
}
func (sm *Snowball) Run(env *core.Environment, t *core.Turtle) {
if sm.Byztantine {
t.Wiggle()
t.Drop(env, 1, "2")
} else {
t.Wiggle()
am1 := t.Amount(env, 1, "1")
am2 := t.Amount(env, 1, "2")
if am1 > sm.sureness || am2 > sm.sureness {
if am1 > am2 {
if sm.color == 2 {
sm.sureness--
} else {
sm.sureness++
}
if sm.sureness == 0 {
sm.color = 1
}
} else if am2 > am1 {
if sm.color == 1 {
sm.sureness--
} else {
sm.sureness++
}
if sm.sureness == 0 {
sm.color = 2
}
}
}
if sm.sureness > 1 {
t.Drop(env, 1, strconv.Itoa(sm.color))
}
t.Step(env)
}
}

View File

@ -1,38 +0,0 @@
package actors
import (
"git.openprivacy.ca/sarah/microworlds/core"
)
type WoodChips struct {
SniffDistance int
Carrying bool
}
func (a *WoodChips) Setup(env *core.Environment, t *core.Turtle) {
//t.SetXY(150,150)
}
func (a *WoodChips) Run(env *core.Environment, t *core.Turtle) {
if a.Carrying {
if env.HasValue(t.Pos()) {
for {
t.Wiggle()
t.Step(env)
if !env.HasValue(t.Pos()) {
env.PutValue(t.Pos())
a.Carrying = false
break
}
}
}
} else {
if env.HasValue(t.Pos()) {
env.TakeValue(t.Pos())
a.Carrying = true
t.TurnAround()
}
}
t.Wiggle()
t.Step(env)
}

View File

@ -5,10 +5,10 @@ import (
)
type Turtle struct {
xpos, ypos int
heading int
actor Actor
width,height int
xpos, ypos int
heading int
actor Actor
width, height int
}
type NilActor struct {
@ -58,7 +58,7 @@ func (t *Turtle) SetXY(x, y int) {
if y < 0 {
y = (t.height - 1)
} else if y >=t.height {
} else if y >= t.height {
y = y % (t.height)
}
@ -111,7 +111,7 @@ func (t *Turtle) Amount(env *Environment, distance int, pheromone string) float3
as0 := env.SniffNormalized(x0, y0, pheromone)
as := env.SniffNormalized(x, y, pheromone)
as1 := env.SniffNormalized(x1, y1, pheromone)
return as0+as+as1
return as0 + as + as1
}
func (t *Turtle) Near(env *Environment, distance int, threshold float32, pheromone string) bool {
@ -152,7 +152,7 @@ func (t *Turtle) Near(env *Environment, distance int, threshold float32, pheromo
as1 = 0
}
if as0 == 0 && as == 0 && as1 == 0 {
if as0 == 0 && as == 0 && as1 == 0 {
return false
} else {
return true

102
experiments/experiment.go Normal file
View File

@ -0,0 +1,102 @@
package experiments
import (
"flag"
"git.openprivacy.ca/sarah/microworlds/core"
"git.openprivacy.ca/sarah/microworlds/graphics"
"github.com/veandco/go-sdl2/sdl"
"image/color"
"log"
"math/rand"
"os"
"runtime/pprof"
"sync"
"time"
)
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
var width = flag.Int("width", 300, "width of environment")
var height = flag.Int("height", 300, "height of environment")
var pxsize = flag.Int("pxsize", 1, "pixels per tile edge")
var numTurtles = flag.Int("numTurtles", 5000, "number of turtles")
type Experiment struct {
env *core.Environment
turtles []*core.Turtle
graphics *graphics.Graphics
initializedTurtles int
}
func (e *Experiment) InitializeExperiment() {
// We don't need real randomness
rand.Seed(time.Now().Unix())
flag.Parse()
if *cpuprofile != "" {
f, err := os.Create(*cpuprofile)
if err != nil {
log.Fatal(err)
}
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
}
if err := sdl.Init(sdl.INIT_EVERYTHING); err != nil {
panic(err)
}
e.env = core.NewEnvironment(*width, *height)
e.turtles = make([]*core.Turtle, *numTurtles)
e.graphics = graphics.NewGraphics(int32(*width), int32(*height), int32(*pxsize))
}
func (e *Experiment) GetNumTurtles() int {
return (*numTurtles)
}
func (e *Experiment) InitPheromone(name string, col color.Color) {
e.env.InitPheromone(name)
r, g, b, a := col.RGBA()
e.graphics.ColorPheromone(name, [4]uint8{uint8(r), uint8(g), uint8(b), uint8(a)})
}
func (e *Experiment) InitEnvironment(f func(environment *core.Environment)) {
f(e.env)
}
func (e *Experiment) InitNTurtles(f func() core.Actor, num int) {
for i := e.initializedTurtles; i < e.initializedTurtles+num; i++ {
e.turtles[i] = core.NewTurtle(e.env, f())
}
e.initializedTurtles += num
}
func (e *Experiment) InitTurtles(f func() core.Actor) {
e.InitNTurtles(f, (*numTurtles))
}
func (e *Experiment) Run() {
wait := sync.WaitGroup{}
running := true
wait.Add(1)
go func() {
for running {
e.graphics.Render(e.env, e.turtles)
}
wait.Done()
}()
wait.Add(1)
for running {
for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
switch event.(type) {
case *sdl.QuitEvent:
running = false
break
}
}
}
wait.Done()
wait.Wait()
}

View File

@ -0,0 +1,91 @@
package main
import (
"flag"
"git.openprivacy.ca/sarah/microworlds/core"
"git.openprivacy.ca/sarah/microworlds/experiments"
"image/color"
"math/rand"
"strconv"
)
var prob = flag.Float64("distribution", .51, "drives the probability of color assignment of turtles in consensus models, closer to .5 results in more even assignment, closer to 0 or 1 biases in favor of a color.")
var byzantineTurtles = flag.Int("byzantineTurtles", 50, "in consensus simlulations, the number of turtles who will always vote 2")
type Isolate struct {
color int
Probability float64
sureness float32
Byztantine bool
}
func (sm *Isolate) Setup(env *core.Environment, t *core.Turtle) {
num := rand.Intn(100)
if num >= int(sm.Probability*100.0) {
sm.color = 2
} else {
sm.color = 1
}
sm.sureness = 2
}
func (sm *Isolate) Run(env *core.Environment, t *core.Turtle) {
if sm.Byztantine {
t.Wiggle()
t.FollowGradient(env, 10, 0, "2")
t.Drop(env, 1, "2")
t.Step(env)
} else {
t.Wiggle()
am1 := t.Amount(env, 1, "1")
am2 := t.Amount(env, 1, "2")
if am1 > sm.sureness || am2 > sm.sureness {
if am1 > am2 {
if sm.color == 2 {
sm.sureness--
} else {
sm.sureness++
}
if sm.sureness == 0 {
sm.color = 1
}
} else if am2 > am1 {
if sm.color == 1 {
sm.sureness--
} else {
sm.sureness++
}
if sm.sureness == 0 {
sm.color = 2
}
}
}
if sm.sureness > 1 {
t.Drop(env, 1, strconv.Itoa(sm.color))
}
t.Step(env)
}
}
func main() {
experiment := new(experiments.Experiment)
experiment.InitializeExperiment()
honestTurtles := experiment.GetNumTurtles() - (*byzantineTurtles)
experiment.InitNTurtles(func() core.Actor {
sm := new(Isolate)
sm.Probability = *prob
return sm
}, honestTurtles)
experiment.InitNTurtles(func() core.Actor {
sm := new(Isolate)
sm.Probability = *prob
sm.Byztantine = true
return sm
}, (*byzantineTurtles))
experiment.InitPheromone("1", color.RGBA{0x00, 0xFF, 0x00, 0x00})
experiment.InitPheromone("2", color.RGBA{0xFF, 0x00, 0xFF, 0x00})
experiment.Run()
}

38
experiments/maze/main.go Normal file
View File

@ -0,0 +1,38 @@
package main
import (
"flag"
"git.openprivacy.ca/sarah/microworlds/core"
"git.openprivacy.ca/sarah/microworlds/experiments"
"image/color"
)
var sniffDistance = flag.Int("sniffDistance", 5, "the distance a turtle can detect pheromone levels from")
type MazeGeneration struct {
SniffDistance int
}
func (sm *MazeGeneration) Setup(env *core.Environment, t *core.Turtle) {
// Do nothing
}
func (sm *MazeGeneration) Run(env *core.Environment, t *core.Turtle) {
t.Wiggle()
t.FollowGradient(env, sm.SniffDistance, 0, "trail")
t.TurnAround() // Run away from the strongest trail
t.Step(env)
t.Drop(env, 1, "trail")
}
func main() {
experiment := new(experiments.Experiment)
experiment.InitializeExperiment()
experiment.InitTurtles(func() core.Actor {
sm := new(MazeGeneration)
sm.SniffDistance = *sniffDistance
return sm
})
experiment.InitPheromone("trail", color.RGBA{0x81, 0x00, 0x81, 0x00})
experiment.Run()
}

View File

@ -0,0 +1,37 @@
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 SlimeMold struct {
SniffDistance int
}
func (sm *SlimeMold) Setup(env *core.Environment, t *core.Turtle) {
// Do nothing
}
func (sm *SlimeMold) Run(env *core.Environment, t *core.Turtle) {
t.Wiggle()
t.FollowGradient(env, sm.SniffDistance, 2, "trail")
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.Run()
}

58
experiments/slush/main.go Normal file
View File

@ -0,0 +1,58 @@
package main
import (
"flag"
"git.openprivacy.ca/sarah/microworlds/core"
"git.openprivacy.ca/sarah/microworlds/experiments"
"image/color"
"math/rand"
"strconv"
)
var prob = flag.Float64("distribution", .51, "drives the probability of color assignment of turtles in consensus models, closer to .5 results in more even assignment, closer to 0 or 1 biases in favor of a color.")
type Slush struct {
color int
Probability float64
}
func NewSlushTurtle() core.Actor {
turtle := new(Slush)
turtle.Probability = *prob
return turtle
}
func (sm *Slush) Setup(env *core.Environment, t *core.Turtle) {
num := rand.Intn(100)
if num >= int(sm.Probability*100.0) {
sm.color = 2
} else {
sm.color = 1
}
}
func (sm *Slush) Run(env *core.Environment, t *core.Turtle) {
t.Wiggle()
am1 := t.Amount(env, 1, "1")
am2 := t.Amount(env, 1, "2")
t.Drop(env, 1, strconv.Itoa(sm.color))
if am1 > 3 || am2 > 3 {
if am1 > am2 {
sm.color = 1
} else if am2 > am1 {
sm.color = 2
}
}
t.Step(env)
}
func main() {
experiment := new(experiments.Experiment)
experiment.InitializeExperiment()
experiment.InitTurtles(NewSlushTurtle)
experiment.InitPheromone("1", color.RGBA{0x80, 0xFF, 0x00, 0x00})
experiment.InitPheromone("2", color.RGBA{0xFF, 0x00, 0xFF, 0x00})
experiment.Run()
}

View File

@ -0,0 +1,89 @@
package main
import (
"flag"
"git.openprivacy.ca/sarah/microworlds/core"
"git.openprivacy.ca/sarah/microworlds/experiments"
"image/color"
"math/rand"
"strconv"
)
var prob = flag.Float64("distribution", .51, "drives the probability of color assignment of turtles in consensus models, closer to .5 results in more even assignment, closer to 0 or 1 biases in favor of a color.")
var byzantineTurtles = flag.Int("byzantineTurtles", 50, "in consensus simlulations, the number of turtles who will always vote 2")
type Snowball struct {
color int
Probability float64
sureness float32
Byztantine bool
}
func (sm *Snowball) Setup(env *core.Environment, t *core.Turtle) {
num := rand.Intn(100)
if num >= int(sm.Probability*100.0) {
sm.color = 2
} else {
sm.color = 1
}
sm.sureness = 2
}
func (sm *Snowball) Run(env *core.Environment, t *core.Turtle) {
if sm.Byztantine {
t.Wiggle()
t.Drop(env, 1, "2")
} else {
t.Wiggle()
am1 := t.Amount(env, 1, "1")
am2 := t.Amount(env, 1, "2")
if am1 > sm.sureness || am2 > sm.sureness {
if am1 > am2 {
if sm.color == 2 {
sm.sureness--
} else {
sm.sureness++
}
if sm.sureness == 0 {
sm.color = 1
}
} else if am2 > am1 {
if sm.color == 1 {
sm.sureness--
} else {
sm.sureness++
}
if sm.sureness == 0 {
sm.color = 2
}
}
}
if sm.sureness > 1 {
t.Drop(env, 1, strconv.Itoa(sm.color))
}
t.Step(env)
}
}
func main() {
experiment := new(experiments.Experiment)
experiment.InitializeExperiment()
honestTurtles := experiment.GetNumTurtles() - (*byzantineTurtles)
experiment.InitNTurtles(func() core.Actor {
sm := new(Snowball)
sm.Probability = *prob
return sm
}, honestTurtles)
experiment.InitNTurtles(func() core.Actor {
sm := new(Snowball)
sm.Probability = *prob
sm.Byztantine = true
return sm
}, (*byzantineTurtles))
experiment.InitPheromone("1", color.RGBA{0x00, 0xFF, 0x00, 0x00})
experiment.InitPheromone("2", color.RGBA{0xFF, 0x00, 0xFF, 0x00})
experiment.Run()
}

66
experiments/swarm/main.go Normal file
View File

@ -0,0 +1,66 @@
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 an ant can detect pheromone levels from")
var dropSize = flag.Float64("dropSize", 1.0, "the amount of pheromone an ants drops")
type Ant struct {
SniffDistance int
Carrying bool
DropSize float64
}
func (a *Ant) Setup(env *core.Environment, t *core.Turtle) {
}
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")
}
t.Step(env)
} else if a.Carrying == true {
a.DropSize -= 0.6
t.Drop(env, float32(a.DropSize), "food")
t.Wiggle()
t.Step(env)
}
}
func main() {
experiment := new(experiments.Experiment)
experiment.InitializeExperiment()
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)
}
}
})
experiment.InitTurtles(func() core.Actor {
sm := new(Ant)
sm.SniffDistance = *sniffDistance
sm.DropSize = *dropSize
return sm
})
experiment.InitPheromone("food", color.RGBA{0x81, 0x81, 0x12, 0x00})
experiment.Run()
}

View File

@ -0,0 +1,67 @@
package main
import (
"flag"
"git.openprivacy.ca/sarah/microworlds/core"
"git.openprivacy.ca/sarah/microworlds/experiments"
"image/color"
"math/rand"
)
var sniffDistance = flag.Int("sniffDistance", 3, "the distance a turtle can detect pheromone levels from")
var numWoodChips = flag.Int("numWoodChips", 5000, "the number of woodchips in the model")
type WoodChips struct {
SniffDistance int
Carrying bool
}
func (a *WoodChips) Setup(env *core.Environment, t *core.Turtle) {
}
func (a *WoodChips) Run(env *core.Environment, t *core.Turtle) {
if a.Carrying {
if env.HasValue(t.Pos()) {
for {
t.Wiggle()
t.Step(env)
if !env.HasValue(t.Pos()) {
env.PutValue(t.Pos())
a.Carrying = false
break
}
}
}
} else {
if env.HasValue(t.Pos()) {
env.TakeValue(t.Pos())
a.Carrying = true
t.TurnAround()
}
}
t.Wiggle()
t.Step(env)
}
func main() {
experiment := new(experiments.Experiment)
experiment.InitializeExperiment()
experiment.InitEnvironment(func(environment *core.Environment) {
for x := 0; x < *numWoodChips; x++ {
environment.PutValue(rand.Intn(environment.Width()), rand.Intn(environment.Height()))
}
for x := 200; x < 210; x++ {
for y := 200; y < 210; y++ {
environment.PutValue(x, y)
}
}
})
experiment.InitTurtles(func() core.Actor {
sm := new(WoodChips)
sm.SniffDistance = *sniffDistance
return sm
})
experiment.InitPheromone("trail", color.RGBA{0x80, 0xFF, 0x00, 0x00})
experiment.Run()
}

View File

@ -7,16 +7,15 @@ import (
"math"
"os"
"strconv"
//"strconv"
)
type Graphics struct {
window *sdl.Window
renderer *sdl.Renderer
window *sdl.Window
renderer *sdl.Renderer
width, height, pxsize int32
t int
colorMap map[string][4]uint8
t int
colorMap map[string][4]uint8
}
func NewGraphics(width, height, pxsize int32) *Graphics {
@ -25,7 +24,7 @@ func NewGraphics(width, height, pxsize int32) *Graphics {
graphics.height = height
graphics.pxsize = pxsize
window, err := sdl.CreateWindow("Microworlds", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED,
width * pxsize, height * pxsize, sdl.WINDOW_SHOWN)
width*pxsize, height*pxsize, sdl.WINDOW_SHOWN)
if err != nil {
panic(err)
}
@ -65,20 +64,20 @@ func (g *Graphics) Render(env *core.Environment, turtles []*core.Turtle) {
amount := math.Min(float64(env.Sniff(name, x, y)), 255)
if amount > 2 {
amount = 2
amount = 2
}
if amount > 0 {
scaledamountRed := uint8(float64(color[0]) * (amount/2))
scaledamountGreen := uint8(float64(color[1]) * (amount/2))
scaledamountBlue := uint8(float64(color[2]) * (amount/2))
scaledamountRed := uint8(float64(color[0]) * (amount / 2))
scaledamountGreen := uint8(float64(color[1]) * (amount / 2))
scaledamountBlue := uint8(float64(color[2]) * (amount / 2))
scaledamountRedTotal += int(scaledamountRed)
scaledamountGreenTotal += int(scaledamountGreen)
scaledamountBlueTotal += int(scaledamountBlue)
}
}
g.renderer.SetDrawColor(uint8(scaledamountRedTotal/len(g.colorMap)),uint8(scaledamountGreenTotal/len(g.colorMap)),uint8(scaledamountBlueTotal/len(g.colorMap)), uint8(0xF0))
g.renderer.SetDrawColor(uint8(scaledamountRedTotal/len(g.colorMap)), uint8(scaledamountGreenTotal/len(g.colorMap)), uint8(scaledamountBlueTotal/len(g.colorMap)), uint8(0xF0))
g.DrawTileColor(int32(x), int32(y))
if env.HasValue(x, y) {

176
main.go
View File

@ -1,176 +0,0 @@
package main
import (
"flag"
"git.openprivacy.ca/sarah/microworlds/actors"
"git.openprivacy.ca/sarah/microworlds/core"
"git.openprivacy.ca/sarah/microworlds/graphics"
"github.com/veandco/go-sdl2/sdl"
"log"
"math/rand"
"os"
"runtime/pprof"
"sync"
"time"
)
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
var model = flag.String("model", "slime", "slimemold|swarm|woodchips")
var width = flag.Int("width", 300, "width of environment")
var height = flag.Int("height", 300, "height of environment")
var pxsize = flag.Int("pxsize", 1, "pixels per tile edge")
var numTurtles = flag.Int("numTurtles", 5000, "number of turtles")
var byzantineTurtles = flag.Int("byzantineTurtles", 50,"in consensus simlulations, the number of turtles who will always vote 2")
var prob = flag.Float64("distribution", .51, "drives the probability of color assignment of turtles in consensus models, closer to .5 results in more even assignment, closer to 0 or 1 biases in favor of a color.")
func main() {
// We don't need real randomness
rand.Seed(time.Now().Unix())
flag.Parse()
if *cpuprofile != "" {
f, err := os.Create(*cpuprofile)
if err != nil {
log.Fatal(err)
}
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
}
if err := sdl.Init(sdl.INIT_EVERYTHING); err != nil {
panic(err)
}
defer sdl.Quit()
env := core.NewEnvironment(*width, *height)
turtles := make([]*core.Turtle, *numTurtles)
g := graphics.NewGraphics(int32(*width), int32(*height), int32(*pxsize))
switch *model {
case "swarm":
// Create 2 food blocks
for x := 100; x < 110; x++ {
for y := 100; y < 110; y++ {
env.PutValue(x, y)
}
}
for x := 200; x < 210; x++ {
for y := 200; y < 210; y++ {
env.PutValue(x, y)
}
}
for i := 0; i < *numTurtles; i++ {
turtles[i] = core.NewTurtle(env, &actors.Ant{SniffDistance: 3, Carrying: false})
}
env.InitPheromone("food")
g.ColorPheromone("food", [4]uint8{0x81, 0x81, 0x12, 0x00})
case "woodchips":
for x := 0; x < *numTurtles; x++ {
env.PutValue(rand.Intn(*width), rand.Intn(*height))
}
for x := 200; x < 210; x++ {
for y := 200; y < 210; y++ {
env.PutValue(x, y)
}
}
for i := 0; i < *numTurtles; i++ {
turtles[i] = core.NewTurtle(env, &actors.WoodChips{SniffDistance: 20, Carrying: false})
}
case "slimemold":
for i := 0; i < *numTurtles; i++ {
turtles[i] = core.NewTurtle(env, &actors.SlimeMold{SniffDistance: 5})
}
env.InitPheromone("trail")
g.ColorPheromone("trail", [4]uint8{0x81, 0, 0x81, 0x00})
case "maze":
for i := 0; i < *numTurtles; i++ {
turtles[i] = core.NewTurtle(env, &actors.MazeGeneration{SniffDistance: 5})
}
env.InitPheromone("trail")
g.ColorPheromone("trail", [4]uint8{0x81, 0, 0x81, 0x00})
case "slush":
for i := 0; i < *numTurtles; i++ {
turtles[i] = core.NewTurtle(env, &actors.Slush{Probability:float32(*prob)})
}
env.InitPheromone("1")
env.InitPheromone("2")
g.ColorPheromone("1", [4]uint8{0x80, 0xFF, 0x00, 0x00})
g.ColorPheromone("2", [4]uint8{0xFF, 0, 0xFF, 0x00})
case "snowball":
for i := 0; i < *numTurtles; i++ {
turtles[i] = core.NewTurtle(env, &actors.Snowball{Probability:float32(*prob)})
}
env.InitPheromone("1")
env.InitPheromone("2")
g.ColorPheromone("1", [4]uint8{0x00, 0xFF, 0x80, 0x00})
g.ColorPheromone("2", [4]uint8{0xFF, 0x80, 0x00, 0x00})
case "snowball-byzantine":
honestTurtles := (*numTurtles)-(*byzantineTurtles)
for i := 0; i < honestTurtles; i++ {
turtles[i] = core.NewTurtle(env, &actors.Snowball{Probability:float32(*prob)})
}
for i := honestTurtles; i < honestTurtles+(*byzantineTurtles); i++ {
turtles[i] = core.NewTurtle(env, &actors.Snowball{Probability:float32(*prob), Byztantine:true})
}
env.InitPheromone("1")
env.InitPheromone("2")
g.ColorPheromone("1", [4]uint8{0x00, 0xFF, 0x80, 0x00})
g.ColorPheromone("2", [4]uint8{0xFF, 0x00, 0xa5, 0x00})
case "isolate":
honestTurtles := (*numTurtles)-(*byzantineTurtles)
for i := 0; i < honestTurtles; i++ {
turtles[i] = core.NewTurtle(env, &actors.Isolate{Probability:float32(*prob)})
}
for i := honestTurtles; i < honestTurtles+(*byzantineTurtles); i++ {
turtles[i] = core.NewTurtle(env, &actors.Isolate{Probability:float32(*prob), Byztantine:true})
}
env.InitPheromone("1")
env.InitPheromone("2")
g.ColorPheromone("1", [4]uint8{0x00, 0xFF, 0x80, 0x00})
g.ColorPheromone("2", [4]uint8{0xFF, 0x00, 0xa5, 0x00})
case "flocking":
for i := 0; i < *numTurtles; i++ {
turtles[i] = core.NewTurtle(env, &actors.Flocking{SniffDistance: 1})
}
env.InitPheromone("trail")
env.InitPheromone("avoid")
g.ColorPheromone("trail", [4]uint8{0x81, 0, 0x81, 0x00})
g.ColorPheromone("avoid", [4]uint8{0xd1, 0, 0xff, 0x00})
default:
for i := 0; i < *numTurtles; i++ {
turtles[i] = core.NewTurtle(env, &actors.SlimeMold{SniffDistance: 20})
}
env.InitPheromone("trail")
g.ColorPheromone("trail", [4]uint8{0x81, 0, 0x81, 0x00})
}
running := true
wait := sync.WaitGroup{}
wait.Add(1)
go func() {
for running {
g.Render(env, turtles)
}
wait.Done()
}()
wait.Add(1)
for running {
for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
switch event.(type) {
case *sdl.QuitEvent:
running = false
break
}
}
}
wait.Done()
wait.Wait()
}