|
@@ -7,6 +7,7 @@ import (
|
|
|
"math/rand"
|
|
|
"net"
|
|
|
"sort"
|
|
|
+ "sync"
|
|
|
"time"
|
|
|
|
|
|
"gonum.org/v1/gonum/mat"
|
|
@@ -28,6 +29,9 @@ type SnakeSimulator struct {
|
|
|
snakeUpdateQueue chan bool
|
|
|
statsUpdateQueue chan bool
|
|
|
speedQueue chan uint32
|
|
|
+
|
|
|
+ snakeReadMutex sync.Mutex
|
|
|
+ fieldReadMutex sync.Mutex
|
|
|
}
|
|
|
|
|
|
// Initializes new snake population with maximum number of verification steps
|
|
@@ -86,7 +90,9 @@ func (s *SnakeSimulator) Verify(population *genetic.Population) (fitnesses []*ge
|
|
|
})
|
|
|
|
|
|
//Best snake showtime!
|
|
|
+ s.fieldReadMutex.Lock()
|
|
|
s.field.GenerateNextFood()
|
|
|
+ s.fieldReadMutex.Unlock()
|
|
|
s.fieldUpdateQueue <- true
|
|
|
prevSpeed := s.speed
|
|
|
s.speed = 5
|
|
@@ -96,12 +102,14 @@ func (s *SnakeSimulator) Verify(population *genetic.Population) (fitnesses []*ge
|
|
|
}
|
|
|
|
|
|
func (s *SnakeSimulator) runSnake(inidividual *neuralnetwork.NeuralNetwork, randomStart bool) {
|
|
|
+ s.snakeReadMutex.Lock()
|
|
|
if randomStart {
|
|
|
rand.Seed(time.Now().UnixNano())
|
|
|
s.snake = NewSnake(Direction(rand.Uint32()%4), *s.field)
|
|
|
} else {
|
|
|
s.snake = NewSnake(Direction_Left, *s.field)
|
|
|
}
|
|
|
+ s.snakeReadMutex.Unlock()
|
|
|
|
|
|
s.stats.Move = 0
|
|
|
for i := 0; i < s.maxVerificationSteps; i++ {
|
|
@@ -134,13 +142,19 @@ func (s *SnakeSimulator) runSnake(inidividual *neuralnetwork.NeuralNetwork, rand
|
|
|
break
|
|
|
} else if foodCollision(newHead, s.field.Food) {
|
|
|
i = 0
|
|
|
+ s.snakeReadMutex.Lock()
|
|
|
s.snake.Feed(newHead)
|
|
|
+ s.snakeReadMutex.Unlock()
|
|
|
+ s.fieldReadMutex.Lock()
|
|
|
s.field.GenerateNextFood()
|
|
|
+ s.fieldReadMutex.Unlock()
|
|
|
if s.speed > 0 {
|
|
|
s.fieldUpdateQueue <- true
|
|
|
}
|
|
|
} else {
|
|
|
+ s.snakeReadMutex.Lock()
|
|
|
s.snake.Move(newHead)
|
|
|
+ s.snakeReadMutex.Unlock()
|
|
|
}
|
|
|
s.stats.Move++
|
|
|
}
|
|
@@ -358,7 +372,9 @@ func (s *SnakeSimulator) Field(_ *None, srv SnakeSimulator_FieldServer) error {
|
|
|
return ctx.Err()
|
|
|
default:
|
|
|
}
|
|
|
+ s.snakeReadMutex.Lock()
|
|
|
srv.Send(s.field)
|
|
|
+ s.snakeReadMutex.Unlock()
|
|
|
<-s.fieldUpdateQueue
|
|
|
}
|
|
|
}
|
|
@@ -386,7 +402,9 @@ func (s *SnakeSimulator) Stats(_ *None, srv SnakeSimulator_StatsServer) error {
|
|
|
return ctx.Err()
|
|
|
default:
|
|
|
}
|
|
|
+ s.fieldReadMutex.Lock()
|
|
|
srv.Send(s.stats)
|
|
|
+ s.fieldReadMutex.Unlock()
|
|
|
<-s.statsUpdateQueue
|
|
|
}
|
|
|
}
|