package core import ( "math/rand" ) type Turtle struct { xpos, ypos int heading int actor Actor } func NewTurtle(env *Environment, actor Actor) *Turtle { for { turtle := new(Turtle) turtle.xpos = rand.Intn(env.width) turtle.ypos = rand.Intn(env.height) turtle.actor = actor if env.Check(turtle.xpos, turtle.ypos) == false { actor.Setup(env,turtle) env.Occupy(turtle.xpos, turtle.ypos) turtle.setRandomHeading() return turtle } } } func (t *Turtle) Pos() (int,int) { return t.xpos,t.ypos } var headings = [][]int{{-1,-1},{0,-1},{1,-1},{1,0},{1,1},{0,1},{-1,1},{-1,0}} func (t *Turtle) setRandomHeading() { t.heading = rand.Intn(7) } func (t *Turtle) SetXY(x,y int) { t.xpos = x t.ypos = y } func (t *Turtle) Wiggle() { wiggle := rand.Intn(3) - 1 h := (t.heading + wiggle) % 8 if h < 0 { h = 7 } t.heading = h } func (t*Turtle) TurnAround() { t.heading = (t.heading + 4) % 8 } func (t*Turtle) Drop(env *Environment, amount float32) { env.Mark(t.xpos,t.ypos, amount) } func (t *Turtle) FollowGradient(env *Environment, distance int, threshold float32 ) { h0 := t.heading-1 if h0 < 0 { h0 = 7 } dx0 := headings[h0][0] * distance dy0 := headings[h0][1] * distance x0 := (t.xpos + dx0) y0 := (t.ypos + dy0) dx := headings[t.heading][0] * distance dy := headings[t.heading][1] * distance x := (t.xpos + dx) y := (t.ypos + dy) h1 := (t.heading+1) % 7 dx1 := headings[h1][0] * distance dy1 := headings[h1][1] * distance x1 := (t.xpos + dx1) y1 := (t.ypos + dy1) as0 := env.SniffNormalized(x0,y0) if as0 < threshold { as0 = 0 } as := env.SniffNormalized(x,y) if as < threshold { as = 0 } as1 := env.SniffNormalized(x1,y1) if as1 < threshold { as1 = 0 } if as0 > as && as0 > as1{ t.heading = h0 } else if as1 > as && as1 > as0 { t.heading = h1 } } func (t* Turtle) Step(env *Environment) bool { dx := headings[t.heading][0] dy := headings[t.heading][1] ox := t.xpos oy := t.ypos env.Leave(ox,oy) t.xpos = (t.xpos + dx) % (env.width -1) if t.xpos < 0 { t.xpos = env.width-1 } t.ypos = (t.ypos + dy) % (env.height -1) if t.ypos < 0 { t.ypos = env.height-1 } success := true if env.Check(t.xpos,t.ypos) == true { t.xpos = ox t.ypos = oy success = false } env.Occupy(t.xpos,t.ypos) return success } // Run the turtle program func (t * Turtle) Run(env * Environment) { //log.Debugf("Pos: %v %v", t.xpos, t.ypos) t.actor.Run(env, t) }