microworlds/experiments/experiment.go

130 lines
2.9 KiB
Go
Raw Normal View History

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
2019-09-28 21:56:23 +00:00
OnStep func(*core.Environment, []*core.Turtle, 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)
}
2019-09-29 21:16:09 +00:00
e.OnStep = func(environment *core.Environment, turtles []*core.Turtle, i int) {
}
e.env = core.NewEnvironment(*width, *height)
2019-09-28 21:56:23 +00:00
e.turtles = make([]*core.Turtle, 0)
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) {
2019-09-28 21:56:23 +00:00
numSuccess := 0
for i := e.initializedTurtles; i < e.initializedTurtles+num; i++ {
2019-09-28 21:56:23 +00:00
t := core.NewTurtle(e.env, f())
if t != nil {
e.turtles = append(e.turtles, t)
numSuccess++
}
}
2019-09-28 21:56:23 +00:00
e.initializedTurtles += numSuccess
}
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() {
2019-09-28 21:56:23 +00:00
step := 0
for running {
e.graphics.Render(e.env, e.turtles)
2019-09-29 21:16:09 +00:00
2019-09-28 21:56:23 +00:00
e.OnStep(e.env, e.turtles, step)
newTurtles := make([]*core.Turtle, 0)
deleted := 0
for _, t := range e.turtles {
if t.GetAttribute("status") != "dead" {
newTurtles = append(newTurtles, t)
} else {
e.env.Leave(t.Pos()) // Dead turtles occupy no space
deleted++
}
}
e.turtles = newTurtles
step++
}
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()
}