snakesimulator.go 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. package snakesimulator
  2. import (
  3. context "context"
  4. fmt "fmt"
  5. math "math"
  6. "math/rand"
  7. "net"
  8. "time"
  9. "gonum.org/v1/gonum/mat"
  10. genetic "../genetic"
  11. grpc "google.golang.org/grpc"
  12. )
  13. type SnakeSimulator struct {
  14. field *Field
  15. snake *Snake
  16. stats *Stats
  17. speed uint32
  18. fieldUpdateQueue chan bool
  19. snakeUpdateQueue chan bool
  20. statsUpdateQueue chan bool
  21. speedQueue chan uint32
  22. }
  23. func NewSnakeSimulator() (s *SnakeSimulator) {
  24. s = &SnakeSimulator{
  25. field: &Field{
  26. Food: &Point{},
  27. Width: 40,
  28. Height: 40,
  29. },
  30. snake: &Snake{
  31. Points: []*Point{
  32. &Point{X: 20, Y: 20},
  33. &Point{X: 21, Y: 20},
  34. &Point{X: 22, Y: 20},
  35. },
  36. },
  37. stats: &Stats{},
  38. fieldUpdateQueue: make(chan bool, 2),
  39. snakeUpdateQueue: make(chan bool, 2),
  40. statsUpdateQueue: make(chan bool, 2),
  41. speedQueue: make(chan uint32, 1),
  42. speed: 10,
  43. }
  44. return
  45. }
  46. func (s *SnakeSimulator) Verify(population *genetic.Population) (results []*genetic.IndividalResult) {
  47. s.stats.Generation++
  48. s.statsUpdateQueue <- true
  49. s.field.GenerateNextFood()
  50. results = make([]*genetic.IndividalResult, len(population.Networks))
  51. for index, inidividual := range population.Networks {
  52. s.stats.Individual = uint32(index)
  53. s.statsUpdateQueue <- true
  54. s.snake = &Snake{
  55. Points: []*Point{
  56. &Point{X: 19, Y: 20},
  57. &Point{X: 20, Y: 20},
  58. &Point{X: 21, Y: 20},
  59. },
  60. }
  61. // rand.Seed(time.Now().UnixNano())
  62. // switch rand.Uint32() % 4 {
  63. // case 1:
  64. // s.snake = &Snake{
  65. // Points: []*Point{
  66. // &Point{X: 20, Y: 20},
  67. // &Point{X: 21, Y: 20},
  68. // &Point{X: 22, Y: 20},
  69. // },
  70. // }
  71. // case 2:
  72. // s.snake = &Snake{
  73. // Points: []*Point{
  74. // &Point{X: 22, Y: 20},
  75. // &Point{X: 21, Y: 20},
  76. // &Point{X: 20, Y: 20},
  77. // },
  78. // }
  79. // case 3:
  80. // s.snake = &Snake{
  81. // Points: []*Point{
  82. // &Point{X: 20, Y: 20},
  83. // &Point{X: 20, Y: 21},
  84. // &Point{X: 20, Y: 22},
  85. // },
  86. // }
  87. // default:
  88. // s.snake = &Snake{
  89. // Points: []*Point{
  90. // &Point{X: 20, Y: 22},
  91. // &Point{X: 20, Y: 21},
  92. // &Point{X: 20, Y: 20},
  93. // },
  94. // }
  95. // }
  96. i := 0
  97. s.stats.Move = 0
  98. for i < 300 {
  99. if s.speed > 0 {
  100. s.statsUpdateQueue <- true
  101. }
  102. //Read speed from client
  103. select {
  104. case newSpeed := <-s.speedQueue:
  105. fmt.Printf("Apply new speed: %v\n", newSpeed)
  106. if newSpeed < 10 {
  107. if newSpeed > 0 {
  108. s.speed = newSpeed
  109. } else {
  110. s.speed = 0
  111. }
  112. }
  113. default:
  114. }
  115. i++
  116. if s.speed > 0 {
  117. s.snakeUpdateQueue <- true
  118. }
  119. direction, _ := inidividual.Predict(mat.NewDense(inidividual.Sizes[0], 1, s.GetHeadState()))
  120. newHead := s.snake.NewHead(Direction(direction + 1))
  121. if selfCollisionIndex := s.snake.SelfCollision(newHead); selfCollisionIndex > 0 {
  122. if selfCollisionIndex == 1 {
  123. // switch Direction(direction + 1) {
  124. // case Direction_Up:
  125. // newHead = s.snake.NewHead(Direction_Down)
  126. // case Direction_Down:
  127. // newHead = s.snake.NewHead(Direction_Up)
  128. // case Direction_Left:
  129. // newHead = s.snake.NewHead(Direction_Right)
  130. // default:
  131. // newHead = s.snake.NewHead(Direction_Left)
  132. // }
  133. continue
  134. } else {
  135. fmt.Printf("Game over self collision\n")
  136. break
  137. }
  138. }
  139. if newHead.X == s.field.Food.X && newHead.Y == s.field.Food.Y {
  140. s.snake.Feed(newHead)
  141. s.field.GenerateNextFood()
  142. if s.speed > 0 {
  143. s.fieldUpdateQueue <- true
  144. }
  145. } else if newHead.X >= s.field.Width || newHead.Y >= s.field.Height {
  146. // fmt.Printf("Game over\n")
  147. // time.Sleep(1000 * time.Millisecond)
  148. break
  149. } else {
  150. s.snake.Move(newHead)
  151. }
  152. if s.speed > 0 {
  153. time.Sleep(100 / time.Duration(s.speed) * time.Millisecond)
  154. }
  155. s.stats.Move++
  156. }
  157. results[index] = &genetic.IndividalResult{
  158. // Result: float64(len(s.snake.Points)-2) * float64(s.stats.Move),
  159. Result: float64(s.stats.Move),
  160. Index: index,
  161. }
  162. }
  163. return
  164. }
  165. func (s *SnakeSimulator) GetHeadState() []float64 {
  166. headX := float64(s.snake.Points[0].X)
  167. headY := float64(s.snake.Points[0].Y)
  168. // tailX := float64(s.snake.Points[len(s.snake.Points)-1].X)
  169. // tailY := float64(s.snake.Points[len(s.snake.Points)-1].Y)
  170. // prevX := float64(s.snake.Points[1].X)
  171. // prevY := float64(s.snake.Points[1].Y)
  172. foodX := float64(s.field.Food.X)
  173. foodY := float64(s.field.Food.Y)
  174. width := float64(s.field.Width)
  175. height := float64(s.field.Height)
  176. diag := float64(width) * math.Sqrt2
  177. // tBack := float64(0.0)
  178. // bBack := float64(0.0)
  179. // lBack := float64(0.0)
  180. // rBack := float64(0.0)
  181. // if prevX == headX {
  182. // if prevY > headY {
  183. // bBack = 1.0
  184. // } else {
  185. // tBack = 1.0
  186. // }
  187. // }
  188. // if prevY == headY {
  189. // if prevX > headX {
  190. // lBack = 1.0
  191. // } else {
  192. // rBack = 1.0
  193. // }
  194. // }
  195. lWall := headX
  196. rWall := (width - headX)
  197. tWall := headY
  198. bWall := (height - headY)
  199. lFood := float64(width)
  200. rFood := float64(width)
  201. tFood := float64(height)
  202. bFood := float64(height)
  203. // tlFood := float64(diag)
  204. // trFood := float64(diag)
  205. // blFood := float64(diag)
  206. // brFood := float64(diag)
  207. tlWall := float64(0)
  208. trWall := float64(0)
  209. blWall := float64(0)
  210. brWall := float64(0)
  211. if headX == foodX {
  212. tFood = headY - foodY
  213. if tFood < 0 {
  214. tFood = height
  215. }
  216. bFood = foodY - headY
  217. if bFood < 0 {
  218. bFood = height
  219. }
  220. }
  221. if headY == foodY {
  222. rFood = foodX - headX
  223. if rFood < 0 {
  224. rFood = width
  225. }
  226. lFood = headX - foodX
  227. if lFood < 0 {
  228. lFood = width
  229. }
  230. }
  231. // if math.Abs(foodY-headY) == math.Abs(foodX-headX) {
  232. // if foodX > headX {
  233. // if foodY > headY {
  234. // trFood = math.Abs(foodX-headX) * math.Sqrt2
  235. // } else {
  236. // brFood = math.Abs(foodX-headX) * math.Sqrt2
  237. // }
  238. // } else {
  239. // if foodY > headY {
  240. // tlFood = math.Abs(foodX-headX) * math.Sqrt2
  241. // } else {
  242. // blFood = math.Abs(foodX-headX) * math.Sqrt2
  243. // }
  244. // }
  245. // }
  246. if lWall > tWall {
  247. tlWall = float64(tWall) * math.Sqrt2
  248. } else {
  249. tlWall = float64(lWall) * math.Sqrt2
  250. }
  251. if rWall > tWall {
  252. trWall = float64(tWall) * math.Sqrt2
  253. } else {
  254. trWall = float64(rWall) * math.Sqrt2
  255. }
  256. if lWall > bWall {
  257. blWall = float64(bWall) * math.Sqrt2
  258. } else {
  259. blWall = float64(lWall) * math.Sqrt2
  260. }
  261. if rWall > bWall {
  262. blWall = float64(bWall) * math.Sqrt2
  263. } else {
  264. brWall = float64(rWall) * math.Sqrt2
  265. }
  266. if lWall > tWall {
  267. tlWall = float64(tWall) * math.Sqrt2
  268. } else {
  269. tlWall = float64(lWall) * math.Sqrt2
  270. }
  271. if rWall > tWall {
  272. trWall = float64(tWall) * math.Sqrt2
  273. } else {
  274. trWall = float64(rWall) * math.Sqrt2
  275. }
  276. if lWall > bWall {
  277. blWall = float64(bWall) * math.Sqrt2
  278. } else {
  279. blWall = float64(lWall) * math.Sqrt2
  280. }
  281. if rWall > bWall {
  282. blWall = float64(bWall) * math.Sqrt2
  283. } else {
  284. brWall = float64(rWall) * math.Sqrt2
  285. }
  286. // tTail := (headY - tailY)
  287. // if tTail < 0 {
  288. // tTail = height
  289. // }
  290. // bTail := (tailY - headY)
  291. // if bTail < 0 {
  292. // bTail = height
  293. // }
  294. // lTail := (headX - tailX)
  295. // if lTail < 0 {
  296. // tTail = width
  297. // }
  298. // rTail := (tailX - headX)
  299. // if lTail < 0 {
  300. // tTail = width
  301. // }
  302. // tlTail := float64(diag)
  303. // trTail := float64(diag)
  304. // blTail := float64(diag)
  305. // brTail := float64(diag)
  306. // if math.Abs(headY-tailY) == math.Abs(headX-tailX) {
  307. // if tailY > headY {
  308. // if tailX > headX {
  309. // trTail = math.Abs(tailX-headX) * math.Sqrt2
  310. // } else {
  311. // tlTail = math.Abs(tailX-headX) * math.Sqrt2
  312. // }
  313. // } else {
  314. // if tailX > headX {
  315. // brTail = math.Abs(tailX-headX) * math.Sqrt2
  316. // } else {
  317. // blTail = math.Abs(tailX-headX) * math.Sqrt2
  318. // }
  319. // }
  320. // }
  321. return []float64{
  322. lWall / width,
  323. rWall / width,
  324. tWall / height,
  325. bWall / height,
  326. // (1.0 - lFood/width),
  327. // (1.0 - rFood/width),
  328. // (1.0 - tFood/height),
  329. // (1.0 - bFood/height),
  330. tlWall / diag,
  331. trWall / diag,
  332. blWall / diag,
  333. brWall / diag,
  334. // (1.0 - tlFood/diag),
  335. // (1.0 - trFood/diag),
  336. // (1.0 - blFood/diag),
  337. // (1.0 - brFood/diag),
  338. // tTail / height,
  339. // bTail / height,
  340. // lTail / width,
  341. // rTail / width,
  342. // tlTail / diag,
  343. // trTail / diag,
  344. // blTail / diag,
  345. // brTail / diag,
  346. }
  347. }
  348. func (s *SnakeSimulator) StartServer() {
  349. go func() {
  350. grpcServer := grpc.NewServer()
  351. RegisterSnakeSimulatorServer(grpcServer, s)
  352. lis, err := net.Listen("tcp", "localhost:65002")
  353. if err != nil {
  354. fmt.Printf("Failed to listen: %v\n", err)
  355. }
  356. fmt.Printf("Listen SnakeSimulator localhost:65002\n")
  357. if err := grpcServer.Serve(lis); err != nil {
  358. fmt.Printf("Failed to serve: %v\n", err)
  359. }
  360. }()
  361. }
  362. func (s *SnakeSimulator) Run() {
  363. s.field.GenerateNextFood()
  364. for true {
  365. direction := rand.Int31()%4 + 1
  366. newHead := s.snake.NewHead(Direction(direction))
  367. if newHead.X == s.field.Food.X && newHead.Y == s.field.Food.Y {
  368. s.snake.Feed(newHead)
  369. s.field.GenerateNextFood()
  370. s.fieldUpdateQueue <- true
  371. } else if newHead.X > s.field.Width || newHead.Y > s.field.Height {
  372. fmt.Printf("Game over\n")
  373. break
  374. } else if selfCollisionIndex := s.snake.SelfCollision(newHead); selfCollisionIndex > 0 {
  375. if selfCollisionIndex == 1 {
  376. fmt.Printf("Step backward, skip\n")
  377. continue
  378. }
  379. fmt.Printf("Game over self collision\n")
  380. break
  381. } else {
  382. s.snake.Move(newHead)
  383. }
  384. s.snakeUpdateQueue <- true
  385. time.Sleep(50 * time.Millisecond)
  386. }
  387. }
  388. func (s *SnakeSimulator) Field(_ *None, srv SnakeSimulator_FieldServer) error {
  389. ctx := srv.Context()
  390. for {
  391. select {
  392. case <-ctx.Done():
  393. return ctx.Err()
  394. default:
  395. }
  396. srv.Send(s.field)
  397. <-s.fieldUpdateQueue
  398. }
  399. }
  400. func (s *SnakeSimulator) Snake(_ *None, srv SnakeSimulator_SnakeServer) error {
  401. ctx := srv.Context()
  402. for {
  403. select {
  404. case <-ctx.Done():
  405. return ctx.Err()
  406. default:
  407. }
  408. srv.Send(s.snake)
  409. <-s.snakeUpdateQueue
  410. }
  411. }
  412. func (s *SnakeSimulator) Stats(_ *None, srv SnakeSimulator_StatsServer) error {
  413. ctx := srv.Context()
  414. for {
  415. select {
  416. case <-ctx.Done():
  417. return ctx.Err()
  418. default:
  419. }
  420. srv.Send(s.stats)
  421. <-s.statsUpdateQueue
  422. }
  423. }
  424. func (s *SnakeSimulator) SetSpeed(ctx context.Context, speed *Speed) (*None, error) {
  425. s.speedQueue <- speed.Speed
  426. return &None{}, nil
  427. }