1
0
Fork 0
microworlds/core/turtle.go

146 lines
2.6 KiB
Go
Raw Permalink Normal View History

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