PageRenderTime 54ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/mona/src/pong/pongWorld.cpp

#
C++ | 1465 lines | 1312 code | 107 blank | 46 comment | 356 complexity | 29af15907481abc7962caf3b691ffa42 MD5 | raw file
  1. // For conditions of distribution and use, see copyright notice in pong.hpp
  2. /*
  3. * The Pong game world.
  4. *
  5. * Mona senses the ball and paddle within a cell that is visible within a grid
  6. * spanning the game area. Mona can move about the game grid and move the paddle
  7. * one grid unit up or down. A game ends with either a score by the ball or a strike
  8. * by the paddle.
  9. */
  10. #include "pong.hpp"
  11. #include "../mona/mona.hpp"
  12. #include <assert.h>
  13. #ifndef WIN32
  14. #include <unistd.h>
  15. #endif
  16. // Version (SCCS "what" format).
  17. #define PONG_WORLD_VERSION "@(#)Pong world version 1.0"
  18. const char *PongWorldVersion = PONG_WORLD_VERSION;
  19. // Usage.
  20. char *Usage[] =
  21. {
  22. (char *)"pong_world\n",
  23. (char *)" -trainingRuns <number of training runs>\n",
  24. (char *)" [-unforcedTrainingRunModulo <frequency of unforced training run = 1/modulo>]\n",
  25. (char *)" [-recordTrainingPlayback <playback file name>]\n",
  26. (char *)" [-createNuPICfromTraining <NuPIC input data file name>]*\n",
  27. (char *)" [-createLensExamplesFromTraining <Lens NN examples file name>]**\n",
  28. (char *)" [-trainingRandomSeed <generation seed>]\n",
  29. (char *)" -testingRuns <number of test runs>\n",
  30. (char *)" [-recordTestingPlayback <playback file name>]\n",
  31. (char *)" [-createNuPICfromTesting <NuPIC input data file name>]*\n",
  32. (char *)" [-createLensExamplesFromTesting <Lens NN examples file name>]**\n",
  33. (char *)" [-testingRandomSeed <generation seed>]\n",
  34. (char *)" [-gridDimensions <game grid dimensions (odd X odd)>]\n",
  35. (char *)" [-startPosition <x> <y> (starting position on game grid)]\n",
  36. (char *)" [-ballSpeed <grid cells/step>]\n",
  37. (char *)" [-load <load file name>]\n",
  38. (char *)" [-save <save file name>]\n",
  39. (char *)" [-verbose]\n",
  40. (char *)" * https://github.com/numenta/NuPIC/wiki/NuPIC-Input-Data-File-Format\n",
  41. (char *)" ** http://web.stanford.edu/group/mbc/LENSManual/Manual\n",
  42. NULL
  43. };
  44. // Runs.
  45. #define MAX_GAME_STEPS 200
  46. int TrainingRuns = -1;
  47. int UnforcedTrainingRunModulo = -1;
  48. int TrainingRandomSeed = 4517;
  49. int TestingRuns = -1;
  50. int TestingRandomSeed = 3605;
  51. // Game properties.
  52. int GridDimensions = 5;
  53. float CellSize = 1.0f / (float)GridDimensions;
  54. int StartX = GridDimensions / 2;
  55. int StartY = GridDimensions / 2;
  56. float BallSpeed = 0.0f;
  57. // Files.
  58. char *TrainingPlaybackFile = NULL;
  59. char *TrainingNuPICFile = NULL;
  60. char *TrainingLensFile = NULL;
  61. char *TestingPlaybackFile = NULL;
  62. char *TestingNuPICFile = NULL;
  63. char *TestingLensFile = NULL;
  64. FILE *NuPICfp;
  65. FILE *LensFp;
  66. vector<string> LensGame;
  67. char *LoadFile = NULL;
  68. char *SaveFile = NULL;
  69. // Pong game.
  70. Pong *pong;
  71. // Paddle position.
  72. int PaddleY;
  73. // Game state.
  74. int CurrentGame;
  75. int BallPositionX, BallPositionY;
  76. int BallNextPositionX, BallNextPositionY;
  77. int PaddlePosition;
  78. bool ShowBallNext = false;
  79. // Mona.
  80. Mona *mona;
  81. // Mona sensors.
  82. enum MONA_SENSORS
  83. {
  84. BALL_SENSOR = 0,
  85. PADDLE_SENSOR = 1,
  86. NUM_SENSORS = 2
  87. };
  88. // Ball sensor values.
  89. float BALL_ABSENT = 0.0f;
  90. float BALL_PRESENT = 0.1f;
  91. float BALL_MOVING_LEFT = 0.2f;
  92. float BALL_MOVING_RIGHT = 0.3f;
  93. float BALL_MOVING_UP = 0.4f;
  94. float BALL_MOVING_DOWN = 0.5f;
  95. float BALL_NULL = 1.0f;
  96. // Paddle sensor values.
  97. float PADDLE_ABSENT = 0.0f;
  98. float PADDLE_PRESENT = 0.5f;
  99. float PADDLE_NULL = 1.0f;
  100. // Cycle.
  101. int cycle(bool overrideResponse = false);
  102. // Mona responses.
  103. enum MONA_RESPONSES
  104. {
  105. CHECK_BALL = 0,
  106. TRACK_BALL_LEFT = 1,
  107. TRACK_BALL_RIGHT = 2,
  108. PAN_LEFT = 3,
  109. PAN_RIGHT = 4,
  110. MOVE_PADDLE_UP = 5,
  111. MOVE_PADDLE_DOWN = 6,
  112. NUM_RESPONSES = 7,
  113. NULL_RESPONSE = NUM_RESPONSES
  114. };
  115. enum OUTCOME
  116. {
  117. CONTINUE = 0,
  118. WIN = 1,
  119. LOSE = 2
  120. };
  121. // Execute response.
  122. OUTCOME execute(int response);
  123. // Step pong.
  124. OUTCOME stepPong();
  125. // Mona needs.
  126. enum MONA_NEEDS
  127. {
  128. TRACK_BALL_NEED = 0,
  129. NUM_NEEDS = 1
  130. };
  131. // Mona position.
  132. int MonaX, MonaY;
  133. // Reset game.
  134. enum RESET_TYPE
  135. {
  136. TRAINING = 0,
  137. TESTING = 1
  138. };
  139. void reset(RESET_TYPE);
  140. // Randomizers.
  141. Random *TrainingRandomizer;
  142. Random *TestingRandomizer;
  143. // Verbose mode.
  144. bool Verbose = false;
  145. void printUsage()
  146. {
  147. for (int i = 0; Usage[i] != NULL; i++)
  148. {
  149. fprintf(stderr, "%s", Usage[i]);
  150. }
  151. }
  152. int
  153. main(int argc, char *argv[])
  154. {
  155. int i, j, k, win, lose, draw;
  156. OUTCOME outcome;
  157. FILE *trainingPlaybackFp;
  158. FILE *testingPlaybackFp;
  159. #ifdef WIN32
  160. char *pongfile;
  161. #else
  162. char pongfile[128];
  163. #endif
  164. vector<float> sensors;
  165. int pongTest = 0;
  166. for (i = 1; i < argc; i++)
  167. {
  168. if (strcmp(argv[i], "-trainingRuns") == 0)
  169. {
  170. i++;
  171. if (i >= argc)
  172. {
  173. printUsage();
  174. return(1);
  175. }
  176. TrainingRuns = atoi(argv[i]);
  177. if (TrainingRuns < 0)
  178. {
  179. printUsage();
  180. return(1);
  181. }
  182. continue;
  183. }
  184. if (strcmp(argv[i], "-unforcedTrainingRunModulo") == 0)
  185. {
  186. i++;
  187. if (i >= argc)
  188. {
  189. printUsage();
  190. return(1);
  191. }
  192. UnforcedTrainingRunModulo = atoi(argv[i]);
  193. if (UnforcedTrainingRunModulo <= 0)
  194. {
  195. printUsage();
  196. return(1);
  197. }
  198. continue;
  199. }
  200. if (strcmp(argv[i], "-recordTrainingPlayback") == 0)
  201. {
  202. i++;
  203. if (i >= argc)
  204. {
  205. printUsage();
  206. return(1);
  207. }
  208. TrainingPlaybackFile = argv[i];
  209. continue;
  210. }
  211. if (strcmp(argv[i], "-createNuPICfromTraining") == 0)
  212. {
  213. i++;
  214. if (i >= argc)
  215. {
  216. printUsage();
  217. return(1);
  218. }
  219. TrainingNuPICFile = argv[i];
  220. continue;
  221. }
  222. if (strcmp(argv[i], "-createLensExamplesFromTraining") == 0)
  223. {
  224. i++;
  225. if (i >= argc)
  226. {
  227. printUsage();
  228. return(1);
  229. }
  230. TrainingLensFile = argv[i];
  231. continue;
  232. }
  233. if (strcmp(argv[i], "-trainingRandomSeed") == 0)
  234. {
  235. i++;
  236. if (i >= argc)
  237. {
  238. printUsage();
  239. return(1);
  240. }
  241. TrainingRandomSeed = atoi(argv[i]);
  242. continue;
  243. }
  244. if (strcmp(argv[i], "-testingRuns") == 0)
  245. {
  246. i++;
  247. if (i >= argc)
  248. {
  249. printUsage();
  250. return(1);
  251. }
  252. TestingRuns = atoi(argv[i]);
  253. if (TestingRuns < 0)
  254. {
  255. printUsage();
  256. return(1);
  257. }
  258. continue;
  259. }
  260. if (strcmp(argv[i], "-recordTestingPlayback") == 0)
  261. {
  262. i++;
  263. if (i >= argc)
  264. {
  265. printUsage();
  266. return(1);
  267. }
  268. TestingPlaybackFile = argv[i];
  269. continue;
  270. }
  271. if (strcmp(argv[i], "-createNuPICfromTesting") == 0)
  272. {
  273. i++;
  274. if (i >= argc)
  275. {
  276. printUsage();
  277. return(1);
  278. }
  279. TestingNuPICFile = argv[i];
  280. continue;
  281. }
  282. if (strcmp(argv[i], "-createLensExamplesFromTesting") == 0)
  283. {
  284. i++;
  285. if (i >= argc)
  286. {
  287. printUsage();
  288. return(1);
  289. }
  290. TestingLensFile = argv[i];
  291. continue;
  292. }
  293. if (strcmp(argv[i], "-testingRandomSeed") == 0)
  294. {
  295. i++;
  296. if (i >= argc)
  297. {
  298. printUsage();
  299. return(1);
  300. }
  301. TestingRandomSeed = atoi(argv[i]);
  302. continue;
  303. }
  304. if (strcmp(argv[i], "-gridDimensions") == 0)
  305. {
  306. i++;
  307. if (i >= argc)
  308. {
  309. printUsage();
  310. return(1);
  311. }
  312. GridDimensions = atoi(argv[i]);
  313. if (GridDimensions < 1)
  314. {
  315. printUsage();
  316. return(1);
  317. }
  318. if ((GridDimensions % 2) == 0)
  319. {
  320. printUsage();
  321. return(1);
  322. }
  323. CellSize = 1.0f / (float)GridDimensions;
  324. continue;
  325. }
  326. if (strcmp(argv[i], "-startPosition") == 0)
  327. {
  328. i++;
  329. if (i >= argc)
  330. {
  331. printUsage();
  332. return(1);
  333. }
  334. StartX = atoi(argv[i]);
  335. if (StartX < 0)
  336. {
  337. printUsage();
  338. return(1);
  339. }
  340. i++;
  341. if (i >= argc)
  342. {
  343. printUsage();
  344. return(1);
  345. }
  346. StartY = atoi(argv[i]);
  347. if (StartY < 0)
  348. {
  349. printUsage();
  350. return(1);
  351. }
  352. continue;
  353. }
  354. if (strcmp(argv[i], "-ballSpeed") == 0)
  355. {
  356. i++;
  357. if (i >= argc)
  358. {
  359. printUsage();
  360. return(1);
  361. }
  362. BallSpeed = (float)atof(argv[i]);
  363. if (BallSpeed <= 0.0f)
  364. {
  365. printUsage();
  366. return(1);
  367. }
  368. continue;
  369. }
  370. if (strcmp(argv[i], "-load") == 0)
  371. {
  372. i++;
  373. if (i >= argc)
  374. {
  375. printUsage();
  376. return(1);
  377. }
  378. LoadFile = argv[i];
  379. continue;
  380. }
  381. if (strcmp(argv[i], "-save") == 0)
  382. {
  383. i++;
  384. if (i >= argc)
  385. {
  386. printUsage();
  387. return(1);
  388. }
  389. SaveFile = argv[i];
  390. continue;
  391. }
  392. if (strcmp(argv[i], "-verbose") == 0)
  393. {
  394. Verbose = true;
  395. continue;
  396. }
  397. if (strcmp(argv[i], "-pongTest") == 0)
  398. {
  399. i++;
  400. if (i >= argc)
  401. {
  402. fprintf(stderr, "Invalid pongTest option\n");
  403. return(1);
  404. }
  405. pongTest = atoi(argv[i]);
  406. if ((pongTest < 0) || (pongTest > 2))
  407. {
  408. fprintf(stderr, "Invalid pongTest value\n");
  409. return(1);
  410. }
  411. continue;
  412. }
  413. printUsage();
  414. return(1);
  415. }
  416. if (TrainingRuns == -1)
  417. {
  418. printUsage();
  419. return(1);
  420. }
  421. if ((TestingRuns == -1) && (pongTest == 0))
  422. {
  423. printUsage();
  424. return(1);
  425. }
  426. if ((StartX >= GridDimensions) || (StartY >= GridDimensions))
  427. {
  428. printUsage();
  429. return(1);
  430. }
  431. if (BallSpeed == 0.0f)
  432. {
  433. BallSpeed = CellSize;
  434. }
  435. // Get random numbers.
  436. TrainingRandomizer = new Random(TrainingRandomSeed);
  437. assert(TrainingRandomizer != NULL);
  438. TestingRandomizer = new Random(TestingRandomSeed);
  439. assert(TestingRandomizer != NULL);
  440. // Create Pong game.
  441. pong = new Pong();
  442. assert(pong != NULL);
  443. pong->paddle.setLength(CellSize);
  444. // Create Mona.
  445. if (LoadFile == NULL)
  446. {
  447. mona = new Mona(NUM_SENSORS, NUM_RESPONSES, NUM_NEEDS);
  448. assert(mona != NULL);
  449. mona->setNeed(TRACK_BALL_NEED, 1.0);
  450. sensors.resize(NUM_SENSORS, 0.0f);
  451. sensors[BALL_SENSOR] = BALL_PRESENT;
  452. sensors[PADDLE_SENSOR] = PADDLE_ABSENT;
  453. mona->addGoal(TRACK_BALL_NEED, sensors, 0, 0.5);
  454. sensors[BALL_SENSOR] = BALL_PRESENT;
  455. sensors[PADDLE_SENSOR] = PADDLE_PRESENT;
  456. mona->addGoal(TRACK_BALL_NEED, sensors, 0, 0.5);
  457. }
  458. else
  459. {
  460. mona = new Mona();
  461. assert(mona != NULL);
  462. if (!mona->load(LoadFile))
  463. {
  464. fprintf(stderr, "Cannot load from file %s\n", LoadFile);
  465. return(1);
  466. }
  467. }
  468. // Training runs.
  469. if (TrainingPlaybackFile != NULL)
  470. {
  471. trainingPlaybackFp = fopen(TrainingPlaybackFile, "w");
  472. if (trainingPlaybackFp == NULL)
  473. {
  474. fprintf(stderr, "Cannot open training playback file %s\n", TrainingPlaybackFile);
  475. return(1);
  476. }
  477. else
  478. {
  479. fprintf(trainingPlaybackFp, "Dimension %d\n", GridDimensions);
  480. }
  481. }
  482. else
  483. {
  484. trainingPlaybackFp = NULL;
  485. }
  486. if (TrainingNuPICFile != NULL)
  487. {
  488. NuPICfp = fopen(TrainingNuPICFile, "w");
  489. if (NuPICfp == NULL)
  490. {
  491. fprintf(stderr, "Cannot open NuPIC file %s\n", TrainingNuPICFile);
  492. return(1);
  493. }
  494. else
  495. {
  496. fprintf(NuPICfp, "game, ball_sensor, paddle_sensor, response\n");
  497. fprintf(NuPICfp, "int, float, float, float\n");
  498. fprintf(NuPICfp, "S,,,\n");
  499. }
  500. }
  501. else
  502. {
  503. NuPICfp = NULL;
  504. }
  505. if (TrainingLensFile != NULL)
  506. {
  507. LensFp = fopen(TrainingLensFile, "w");
  508. if (LensFp == NULL)
  509. {
  510. fprintf(stderr, "Cannot open Lens file %s\n", TrainingLensFile);
  511. return(1);
  512. }
  513. }
  514. else
  515. {
  516. LensFp = NULL;
  517. }
  518. win = lose = draw = 0;
  519. for (i = 0; i < TrainingRuns; i++)
  520. {
  521. // Reset game.
  522. CurrentGame = i;
  523. reset(TRAINING);
  524. // Run game.
  525. if (Verbose || (pongTest != 0))
  526. {
  527. printf("Training game=%d\n", i);
  528. printf("Step=0\n");
  529. printf("Mona location=%d/%d\n", MonaX, MonaY);
  530. printf("Ball position=%0.2f/%0.2f, velocity=%0.2f/%0.2f, paddle = %0.2f\n",
  531. pong->ball.position.x, pong->ball.position.y,
  532. pong->ball.velocity.x, pong->ball.velocity.y, pong->paddle.position);
  533. }
  534. if ((trainingPlaybackFp != NULL) && (pongTest == 0))
  535. {
  536. fprintf(trainingPlaybackFp, "Game %d\n", i);
  537. fprintf(trainingPlaybackFp, "Step 0 %0.2f %0.2f %0.2f %0.2f %0.2f\n",
  538. pong->ball.position.x, pong->ball.position.y, pong->paddle.position,
  539. ((float)MonaX * CellSize) + (CellSize * 0.5f), ((float)MonaY * CellSize) + (CellSize * 0.5f));
  540. }
  541. if (LensFp != NULL)
  542. {
  543. LensGame.clear();
  544. }
  545. for (j = 0; j < MAX_GAME_STEPS; j++)
  546. {
  547. if (Verbose || (pongTest != 0))
  548. {
  549. printf("Step=%d\n", j + 1);
  550. }
  551. // Cycle Mona and execute response.
  552. if (pongTest == 0)
  553. {
  554. if ((UnforcedTrainingRunModulo > 0) && (i > 0) &&
  555. ((i % UnforcedTrainingRunModulo) == 0))
  556. {
  557. outcome = execute(cycle());
  558. }
  559. else
  560. {
  561. outcome = execute(cycle(true));
  562. }
  563. if (trainingPlaybackFp != NULL)
  564. {
  565. fprintf(trainingPlaybackFp, "Step %d %0.2f %0.2f %0.2f %0.2f %0.2f\n", j + 1,
  566. pong->ball.position.x, pong->ball.position.y, pong->paddle.position,
  567. ((float)MonaX * CellSize) + (CellSize * 0.5f), ((float)MonaY * CellSize) + (CellSize * 0.5f));
  568. }
  569. }
  570. else
  571. {
  572. outcome = stepPong();
  573. if (pongTest == 1)
  574. {
  575. PaddleY = (int)(pong->ball.position.y / CellSize);
  576. pong->paddle.position = ((float)PaddleY * CellSize) + (CellSize * 0.5f);
  577. }
  578. }
  579. if (Verbose || (pongTest != 0))
  580. {
  581. printf("Outcome=");
  582. switch (outcome)
  583. {
  584. case CONTINUE:
  585. printf("CONTINUE");
  586. break;
  587. case WIN:
  588. printf("WIN");
  589. break;
  590. case LOSE:
  591. printf("LOSE");
  592. break;
  593. }
  594. printf(", ball position=%0.2f/%0.2f, velocity=%0.2f/%0.2f, paddle=%0.2f\n",
  595. pong->ball.position.x, pong->ball.position.y,
  596. pong->ball.velocity.x, pong->ball.velocity.y, pong->paddle.position);
  597. }
  598. if (outcome == WIN)
  599. {
  600. cycle(true);
  601. win++;
  602. if (trainingPlaybackFp != NULL)
  603. {
  604. fprintf(trainingPlaybackFp, "Win %d\n", win);
  605. }
  606. if (Verbose || (pongTest != 0))
  607. {
  608. printf("Win\n");
  609. }
  610. if (LensFp != NULL)
  611. {
  612. fprintf(LensFp, "name: { game_%d } %d\n", i, (int)LensGame.size());
  613. for (k = 0; k < (int)LensGame.size(); k++)
  614. {
  615. fprintf(LensFp, "%s", LensGame[k].c_str());
  616. if (k == (int)LensGame.size() - 1)
  617. {
  618. fprintf(LensFp, ";");
  619. }
  620. fprintf(LensFp, "\n");
  621. }
  622. }
  623. break;
  624. }
  625. else if (outcome == LOSE)
  626. {
  627. lose++;
  628. if (trainingPlaybackFp != NULL)
  629. {
  630. fprintf(trainingPlaybackFp, "Lose %d\n", lose);
  631. }
  632. if (Verbose || (pongTest != 0))
  633. {
  634. printf("Lose\n");
  635. }
  636. break;
  637. }
  638. }
  639. if (j == MAX_GAME_STEPS)
  640. {
  641. draw++;
  642. if (trainingPlaybackFp != NULL)
  643. {
  644. fprintf(trainingPlaybackFp, "Draw %d\n", draw);
  645. }
  646. if (Verbose || (pongTest != 0))
  647. {
  648. printf("Draw\n");
  649. }
  650. }
  651. if (Verbose || (pongTest != 0))
  652. {
  653. printf("Score: win=%d, lose=%d, draw=%d\n", win, lose, draw);
  654. }
  655. }
  656. if (pongTest != 0)
  657. {
  658. return(0);
  659. }
  660. if (trainingPlaybackFp != NULL)
  661. {
  662. fclose(trainingPlaybackFp);
  663. trainingPlaybackFp = NULL;
  664. }
  665. if (NuPICfp != NULL)
  666. {
  667. fclose(NuPICfp);
  668. NuPICfp = NULL;
  669. }
  670. if (LensFp != NULL)
  671. {
  672. fclose(LensFp);
  673. LensFp = NULL;
  674. }
  675. if (SaveFile != NULL)
  676. {
  677. if (!mona->save(SaveFile))
  678. {
  679. fprintf(stderr, "Cannot save to file %s\n", SaveFile);
  680. return(1);
  681. }
  682. }
  683. // Testing runs.
  684. if (TestingPlaybackFile != NULL)
  685. {
  686. testingPlaybackFp = fopen(TestingPlaybackFile, "w");
  687. if (testingPlaybackFp == NULL)
  688. {
  689. fprintf(stderr, "Cannot open testing playback file %s\n", TestingPlaybackFile);
  690. return(1);
  691. }
  692. else
  693. {
  694. fprintf(testingPlaybackFp, "Dimension %d\n", GridDimensions);
  695. }
  696. }
  697. else
  698. {
  699. testingPlaybackFp = NULL;
  700. }
  701. if (TestingNuPICFile != NULL)
  702. {
  703. NuPICfp = fopen(TestingNuPICFile, "w");
  704. if (NuPICfp == NULL)
  705. {
  706. fprintf(stderr, "Cannot open NuPIC file %s\n", TestingNuPICFile);
  707. return(1);
  708. }
  709. else
  710. {
  711. fprintf(NuPICfp, "game, ball_sensor, paddle_sensor, response\n");
  712. fprintf(NuPICfp, "int, float, float, float\n");
  713. fprintf(NuPICfp, "S,,,\n");
  714. }
  715. }
  716. else
  717. {
  718. NuPICfp = NULL;
  719. }
  720. if (TestingLensFile != NULL)
  721. {
  722. LensFp = fopen(TestingLensFile, "w");
  723. if (LensFp == NULL)
  724. {
  725. fprintf(stderr, "Cannot open Lens file %s\n", TestingLensFile);
  726. return(1);
  727. }
  728. }
  729. else
  730. {
  731. LensFp = NULL;
  732. }
  733. win = lose = draw = 0;
  734. #ifdef WIN32
  735. pongfile = tmpnam(NULL);
  736. #else
  737. sprintf(pongfile, "/tmp/pong_%d.mona", getpid());
  738. #endif
  739. mona->save(pongfile);
  740. for (i = 0; i < TestingRuns; i++)
  741. {
  742. // Reset game.
  743. CurrentGame = i;
  744. mona->load(pongfile);
  745. reset(TESTING);
  746. // Run game.
  747. if (Verbose)
  748. {
  749. printf("Testing game=%d\n", i);
  750. printf("Step=0\n");
  751. printf("Mona location=%d/%d\n", MonaX, MonaY);
  752. printf("Ball position=%0.2f/%0.2f, velocity=%0.2f/%0.2f, paddle = %0.2f\n",
  753. pong->ball.position.x, pong->ball.position.y,
  754. pong->ball.velocity.x, pong->ball.velocity.y, pong->paddle.position);
  755. }
  756. if (testingPlaybackFp != NULL)
  757. {
  758. fprintf(testingPlaybackFp, "Game %d\n", i);
  759. fprintf(testingPlaybackFp, "Step 0 %0.2f %0.2f %0.2f %0.2f %0.2f\n",
  760. pong->ball.position.x, pong->ball.position.y, pong->paddle.position,
  761. ((float)MonaX * CellSize) + (CellSize * 0.5f), ((float)MonaY * CellSize) + (CellSize * 0.5f));
  762. }
  763. if (LensFp != NULL)
  764. {
  765. LensGame.clear();
  766. }
  767. for (j = 0; j < MAX_GAME_STEPS; j++)
  768. {
  769. if (Verbose || (pongTest != 0))
  770. {
  771. printf("Step=%d\n", j + 1);
  772. }
  773. // Cycle Mona and execute response.
  774. outcome = execute(cycle());
  775. if (testingPlaybackFp != NULL)
  776. {
  777. fprintf(testingPlaybackFp, "Step %d %0.2f %0.2f %0.2f %0.2f %0.2f\n", j + 1,
  778. pong->ball.position.x, pong->ball.position.y, pong->paddle.position,
  779. ((float)MonaX * CellSize) + (CellSize * 0.5f), ((float)MonaY * CellSize) + (CellSize * 0.5f));
  780. }
  781. if (Verbose)
  782. {
  783. printf("Outcome=");
  784. switch (outcome)
  785. {
  786. case CONTINUE:
  787. printf("CONTINUE");
  788. break;
  789. case WIN:
  790. printf("WIN");
  791. break;
  792. case LOSE:
  793. printf("LOSE");
  794. break;
  795. }
  796. printf(", ball position=%0.2f/%0.2f, velocity=%0.2f/%0.2f, paddle=%0.2f\n",
  797. pong->ball.position.x, pong->ball.position.y,
  798. pong->ball.velocity.x, pong->ball.velocity.y, pong->paddle.position);
  799. }
  800. if (outcome == WIN)
  801. {
  802. execute(cycle());
  803. win++;
  804. if (testingPlaybackFp != NULL)
  805. {
  806. fprintf(testingPlaybackFp, "Step %d %0.2f %0.2f %0.2f %0.2f %0.2f\n", j + 2,
  807. pong->ball.position.x, pong->ball.position.y, pong->paddle.position,
  808. ((float)MonaX * CellSize) + (CellSize * 0.5f), ((float)MonaY * CellSize) + (CellSize * 0.5f));
  809. fprintf(testingPlaybackFp, "Win %d\n", win);
  810. }
  811. if (Verbose)
  812. {
  813. printf("Win\n");
  814. }
  815. if (LensFp != NULL)
  816. {
  817. fprintf(LensFp, "name: { game_%d } %d\n", i, (int)LensGame.size());
  818. for (k = 0; k < (int)LensGame.size(); k++)
  819. {
  820. fprintf(LensFp, "%s", LensGame[k].c_str());
  821. if (k == (int)LensGame.size() - 1)
  822. {
  823. fprintf(LensFp, ";");
  824. }
  825. fprintf(LensFp, "\n");
  826. }
  827. }
  828. break;
  829. }
  830. else if (outcome == LOSE)
  831. {
  832. execute(cycle());
  833. lose++;
  834. if (testingPlaybackFp != NULL)
  835. {
  836. fprintf(testingPlaybackFp, "Step %d %0.2f %0.2f %0.2f %0.2f %0.2f\n", j + 2,
  837. pong->ball.position.x, pong->ball.position.y, pong->paddle.position,
  838. ((float)MonaX * CellSize) + (CellSize * 0.5f), ((float)MonaY * CellSize) + (CellSize * 0.5f));
  839. fprintf(testingPlaybackFp, "Lose %d\n", lose);
  840. }
  841. if (Verbose)
  842. {
  843. printf("Lose\n");
  844. }
  845. break;
  846. }
  847. }
  848. if (j == MAX_GAME_STEPS)
  849. {
  850. draw++;
  851. if (testingPlaybackFp != NULL)
  852. {
  853. fprintf(testingPlaybackFp, "Draw %d\n", draw);
  854. }
  855. if (Verbose)
  856. {
  857. printf("Draw\n");
  858. }
  859. }
  860. if (Verbose)
  861. {
  862. printf("Score: win=%d, lose=%d, draw=%d\n", win, lose, draw);
  863. }
  864. }
  865. #ifdef WIN32
  866. _unlink(pongfile);
  867. #else
  868. unlink(pongfile);
  869. #endif
  870. if (testingPlaybackFp != NULL)
  871. {
  872. fclose(testingPlaybackFp);
  873. testingPlaybackFp = NULL;
  874. }
  875. if (NuPICfp != NULL)
  876. {
  877. fclose(NuPICfp);
  878. NuPICfp = NULL;
  879. }
  880. if (LensFp != NULL)
  881. {
  882. fclose(LensFp);
  883. LensFp = NULL;
  884. }
  885. return(0);
  886. }
  887. // Reset game.
  888. void reset(RESET_TYPE type)
  889. {
  890. float x, y, v;
  891. Random *randomizer;
  892. x = ((float)StartX * CellSize) + (CellSize * 0.5f);
  893. y = ((float)StartY * CellSize) + (CellSize * 0.5f);
  894. pong->setBallPosition(x, y);
  895. if (type == TRAINING)
  896. {
  897. randomizer = TrainingRandomizer;
  898. }
  899. else
  900. {
  901. randomizer = TestingRandomizer;
  902. }
  903. pong->setBallVelocity((float)randomizer->RAND_INTERVAL(0.1, 1.0),
  904. (float)randomizer->RAND_INTERVAL(-1.0, 1.0));
  905. if (randomizer->RAND_BOOL())
  906. {
  907. pong->ball.velocity.x = -pong->ball.velocity.x;
  908. }
  909. if (fabs(pong->ball.velocity.y) > fabs(pong->ball.velocity.x))
  910. {
  911. v = pong->ball.velocity.x;
  912. pong->ball.velocity.x = pong->ball.velocity.y;
  913. pong->ball.velocity.y = v;
  914. }
  915. pong->setBallSpeed(BallSpeed);
  916. PaddleY = GridDimensions / 2;
  917. pong->paddle.setPosition(0.5f);
  918. ShowBallNext = false;
  919. MonaX = StartX;
  920. MonaY = StartY;
  921. mona->clearWorkingMemory();
  922. mona->inflateNeed(TRACK_BALL_NEED);
  923. }
  924. // Cycle Mona and return response.
  925. int cycle(bool overrideResponse)
  926. {
  927. int response;
  928. Pong::Ball ball;
  929. char buf[BUFSIZ];
  930. vector<float> sensors;
  931. sensors.resize(NUM_SENSORS);
  932. BallPositionX = (int)(pong->ball.position.x / CellSize);
  933. if (BallPositionX < 0)
  934. {
  935. BallPositionX = 0;
  936. }
  937. if (BallPositionX >= GridDimensions)
  938. {
  939. BallPositionX = GridDimensions - 1;
  940. }
  941. BallPositionY = (int)(pong->ball.position.y / CellSize);
  942. if (BallPositionY < 0)
  943. {
  944. BallPositionY = 0;
  945. }
  946. if (BallPositionY >= GridDimensions)
  947. {
  948. BallPositionY = GridDimensions - 1;
  949. }
  950. Vector p = pong->ball.position;
  951. Vector d = pong->ball.velocity;
  952. ball = pong->ball;
  953. pong->step();
  954. BallNextPositionX = (int)(pong->ball.position.x / CellSize);
  955. if (BallNextPositionX < 0)
  956. {
  957. BallNextPositionX = 0;
  958. }
  959. if (BallNextPositionX >= GridDimensions)
  960. {
  961. BallNextPositionX = GridDimensions - 1;
  962. }
  963. BallNextPositionY = (int)(pong->ball.position.y / CellSize);
  964. if (BallNextPositionY < 0)
  965. {
  966. BallNextPositionY = 0;
  967. }
  968. if (BallNextPositionY >= GridDimensions)
  969. {
  970. BallNextPositionY = GridDimensions - 1;
  971. }
  972. pong->ball = ball;
  973. if ((MonaX != BallPositionX) || (MonaY != BallPositionY))
  974. {
  975. sensors[BALL_SENSOR] = BALL_ABSENT;
  976. }
  977. else
  978. {
  979. if (ShowBallNext)
  980. {
  981. if (MonaY == BallNextPositionY)
  982. {
  983. if (MonaX == BallNextPositionX)
  984. {
  985. sensors[BALL_SENSOR] = BALL_PRESENT;
  986. }
  987. else if (MonaX > BallNextPositionX)
  988. {
  989. sensors[BALL_SENSOR] = BALL_MOVING_LEFT;
  990. }
  991. else
  992. {
  993. sensors[BALL_SENSOR] = BALL_MOVING_RIGHT;
  994. }
  995. }
  996. else if (MonaY > BallNextPositionY)
  997. {
  998. sensors[BALL_SENSOR] = BALL_MOVING_DOWN;
  999. }
  1000. else
  1001. {
  1002. sensors[BALL_SENSOR] = BALL_MOVING_UP;
  1003. }
  1004. }
  1005. else
  1006. {
  1007. sensors[BALL_SENSOR] = BALL_PRESENT;
  1008. }
  1009. }
  1010. sensors[PADDLE_SENSOR] = PADDLE_ABSENT;
  1011. PaddlePosition = (int)(pong->paddle.position / CellSize);
  1012. if (MonaX == GridDimensions - 1)
  1013. {
  1014. if (MonaY == PaddlePosition)
  1015. {
  1016. sensors[PADDLE_SENSOR] = PADDLE_PRESENT;
  1017. }
  1018. }
  1019. if (Verbose)
  1020. {
  1021. printf("Ball current location=%d/%d, next location=%d/%d",
  1022. BallPositionX, BallPositionY, BallNextPositionX, BallNextPositionY);
  1023. printf(", Sensor[BALL_SENSOR]=");
  1024. if (sensors[BALL_SENSOR] == BALL_ABSENT)
  1025. {
  1026. printf("BALL_ABSENT");
  1027. }
  1028. if (sensors[BALL_SENSOR] == BALL_PRESENT)
  1029. {
  1030. printf("BALL_PRESENT");
  1031. }
  1032. if (sensors[BALL_SENSOR] == BALL_MOVING_LEFT)
  1033. {
  1034. printf("BALL_MOVING_LEFT");
  1035. }
  1036. if (sensors[BALL_SENSOR] == BALL_MOVING_RIGHT)
  1037. {
  1038. printf("BALL_MOVING_RIGHT");
  1039. }
  1040. if (sensors[BALL_SENSOR] == BALL_MOVING_UP)
  1041. {
  1042. printf("BALL_MOVING_UP");
  1043. }
  1044. if (sensors[BALL_SENSOR] == BALL_MOVING_DOWN)
  1045. {
  1046. printf("BALL_MOVING_DOWN");
  1047. }
  1048. printf("\n");
  1049. printf("Paddle location=%d", PaddlePosition);
  1050. printf(", Sensor[PADDLE_SENSOR]=");
  1051. if (sensors[PADDLE_SENSOR] == PADDLE_ABSENT)
  1052. {
  1053. printf("PADDLE_ABSENT");
  1054. }
  1055. if (sensors[PADDLE_SENSOR] == PADDLE_PRESENT)
  1056. {
  1057. printf("PADDLE_PRESENT");
  1058. }
  1059. printf("\n");
  1060. printf("Mona location=%d/%d\n", MonaX, MonaY);
  1061. }
  1062. if (overrideResponse)
  1063. {
  1064. if (sensors[BALL_SENSOR] == BALL_ABSENT)
  1065. {
  1066. if (sensors[PADDLE_SENSOR] == PADDLE_PRESENT)
  1067. {
  1068. if (MonaY > BallNextPositionY)
  1069. {
  1070. mona->overrideResponse(MOVE_PADDLE_DOWN);
  1071. }
  1072. else if (MonaY < BallNextPositionY)
  1073. {
  1074. mona->overrideResponse(MOVE_PADDLE_UP);
  1075. }
  1076. else
  1077. {
  1078. mona->overrideResponse(PAN_LEFT);
  1079. }
  1080. }
  1081. else
  1082. {
  1083. if (MonaX < BallPositionX)
  1084. {
  1085. mona->overrideResponse(PAN_RIGHT);
  1086. }
  1087. else
  1088. {
  1089. mona->overrideResponse(PAN_LEFT);
  1090. }
  1091. }
  1092. }
  1093. else if (sensors[BALL_SENSOR] == BALL_PRESENT)
  1094. {
  1095. mona->overrideResponse(CHECK_BALL);
  1096. }
  1097. else if (sensors[BALL_SENSOR] == BALL_MOVING_LEFT)
  1098. {
  1099. mona->overrideResponse(TRACK_BALL_LEFT);
  1100. }
  1101. else if (sensors[BALL_SENSOR] == BALL_MOVING_RIGHT)
  1102. {
  1103. mona->overrideResponse(TRACK_BALL_RIGHT);
  1104. }
  1105. else if (sensors[BALL_SENSOR] == BALL_MOVING_UP)
  1106. {
  1107. if (sensors[PADDLE_SENSOR] == PADDLE_PRESENT)
  1108. {
  1109. mona->overrideResponse(MOVE_PADDLE_UP);
  1110. }
  1111. else
  1112. {
  1113. mona->overrideResponse(PAN_RIGHT);
  1114. }
  1115. }
  1116. else if (sensors[BALL_SENSOR] == BALL_MOVING_DOWN)
  1117. {
  1118. if (sensors[PADDLE_SENSOR] == PADDLE_PRESENT)
  1119. {
  1120. mona->overrideResponse(MOVE_PADDLE_DOWN);
  1121. }
  1122. else
  1123. {
  1124. mona->overrideResponse(PAN_RIGHT);
  1125. }
  1126. }
  1127. }
  1128. response = mona->cycle(sensors);
  1129. if (NuPICfp != NULL)
  1130. {
  1131. fprintf(NuPICfp, "%d,%0.2f,%0.2f,%0.2f\n", CurrentGame,
  1132. sensors[BALL_SENSOR], sensors[PADDLE_SENSOR], (float)response * 0.1f);
  1133. }
  1134. if (LensFp != NULL)
  1135. {
  1136. float BALL_ABSENT = 0.0f;
  1137. float BALL_PRESENT = 0.1f;
  1138. float BALL_MOVING_LEFT = 0.2f;
  1139. float BALL_MOVING_RIGHT = 0.3f;
  1140. float BALL_MOVING_UP = 0.4f;
  1141. float BALL_MOVING_DOWN = 0.5f;
  1142. float BALL_NULL = 1.0f;
  1143. // Paddle sensor values.
  1144. float PADDLE_ABSENT = 0.0f;
  1145. float PADDLE_PRESENT = 0.5f;
  1146. float PADDLE_NULL = 1.0f;
  1147. if (sensors[BALL_SENSOR] == BALL_ABSENT)
  1148. {
  1149. sprintf(buf, "I: 1 0 0 0 0 0 ");
  1150. }
  1151. else if (sensors[BALL_SENSOR] == BALL_PRESENT)
  1152. {
  1153. sprintf(buf, "I: 0 1 0 0 0 0 ");
  1154. }
  1155. else if (sensors[BALL_SENSOR] == BALL_MOVING_LEFT)
  1156. {
  1157. sprintf(buf, "I: 0 0 1 0 0 0 ");
  1158. }
  1159. else if (sensors[BALL_SENSOR] == BALL_MOVING_RIGHT)
  1160. {
  1161. sprintf(buf, "I: 0 0 0 1 0 0 ");
  1162. }
  1163. else if (sensors[BALL_SENSOR] == BALL_MOVING_UP)
  1164. {
  1165. sprintf(buf, "I: 0 0 0 0 1 0 ");
  1166. }
  1167. else
  1168. {
  1169. sprintf(buf, "I: 0 0 0 0 0 1 ");
  1170. }
  1171. if (sensors[PADDLE_SENSOR] == PADDLE_ABSENT)
  1172. {
  1173. strcat(buf, "1 0 ");
  1174. }
  1175. else
  1176. {
  1177. strcat(buf, "0 1 ");
  1178. }
  1179. switch (response)
  1180. {
  1181. case CHECK_BALL:
  1182. strcat(buf, "T: 1 0 0 0 0 0 0");
  1183. break;
  1184. case TRACK_BALL_LEFT:
  1185. strcat(buf, "T: 0 1 0 0 0 0 0");
  1186. break;
  1187. case TRACK_BALL_RIGHT:
  1188. strcat(buf, "T: 0 0 1 0 0 0 0");
  1189. break;
  1190. case PAN_LEFT:
  1191. strcat(buf, "T: 0 0 0 1 0 0 0");
  1192. break;
  1193. case PAN_RIGHT:
  1194. strcat(buf, "T: 0 0 0 0 1 0 0");
  1195. break;
  1196. case MOVE_PADDLE_UP:
  1197. strcat(buf, "T: 0 0 0 0 0 1 0");
  1198. break;
  1199. case MOVE_PADDLE_DOWN:
  1200. strcat(buf, "T: 0 0 0 0 0 0 1");
  1201. break;
  1202. }
  1203. LensGame.push_back(buf);
  1204. }
  1205. if (Verbose)
  1206. {
  1207. printf("Response=");
  1208. switch (response)
  1209. {
  1210. case CHECK_BALL:
  1211. printf("CHECK_BALL");
  1212. break;
  1213. case TRACK_BALL_LEFT:
  1214. printf("TRACK_BALL_LEFT");
  1215. break;
  1216. case TRACK_BALL_RIGHT:
  1217. printf("TRACK_BALL_RIGHT");
  1218. break;
  1219. case PAN_LEFT:
  1220. printf("PAN_LEFT");
  1221. break;
  1222. case PAN_RIGHT:
  1223. printf("PAN_RIGHT");
  1224. break;
  1225. case MOVE_PADDLE_UP:
  1226. printf("MOVE_PADDLE_UP");
  1227. break;
  1228. case MOVE_PADDLE_DOWN:
  1229. printf("MOVE_PADDLE_DOWN");
  1230. break;
  1231. }
  1232. if (overrideResponse)
  1233. {
  1234. printf("(overridden)");
  1235. }
  1236. printf("\n");
  1237. printf("Need=%f\n", mona->getNeed(TRACK_BALL_NEED));
  1238. }
  1239. mona->inflateNeed(TRACK_BALL_NEED);
  1240. return(response);
  1241. }
  1242. // Execute response.
  1243. OUTCOME execute(int response)
  1244. {
  1245. switch (response)
  1246. {
  1247. case CHECK_BALL:
  1248. if (ShowBallNext)
  1249. {
  1250. if ((BallPositionX == BallNextPositionX) &&
  1251. (BallPositionY == BallNextPositionY))
  1252. {
  1253. stepPong();
  1254. }
  1255. }
  1256. ShowBallNext = true;
  1257. break;
  1258. case TRACK_BALL_LEFT:
  1259. ShowBallNext = false;
  1260. if (MonaX > 0)
  1261. {
  1262. MonaX--;
  1263. }
  1264. return(stepPong());
  1265. case TRACK_BALL_RIGHT:
  1266. ShowBallNext = false;
  1267. if (MonaX < GridDimensions - 1)
  1268. {
  1269. MonaX++;
  1270. }
  1271. return(stepPong());
  1272. case PAN_LEFT:
  1273. if (MonaX > 0)
  1274. {
  1275. MonaX--;
  1276. while (MonaX > 0)
  1277. {
  1278. if ((MonaX == BallPositionX) && (MonaY == BallPositionY))
  1279. {
  1280. break;
  1281. }
  1282. MonaX--;
  1283. }
  1284. }
  1285. break;
  1286. case PAN_RIGHT:
  1287. if (MonaX < GridDimensions - 1)
  1288. {
  1289. MonaX++;
  1290. while (MonaX < GridDimensions - 1)
  1291. {
  1292. if ((MonaX == BallPositionX) && (MonaY == BallPositionY))
  1293. {
  1294. break;
  1295. }
  1296. MonaX++;
  1297. }
  1298. }
  1299. break;
  1300. case MOVE_PADDLE_UP:
  1301. ShowBallNext = false;
  1302. if ((MonaX == GridDimensions - 1) && (MonaY == PaddleY))
  1303. {
  1304. if (PaddleY < GridDimensions - 1)
  1305. {
  1306. PaddleY++;
  1307. pong->paddle.position = ((float)PaddleY * CellSize) + (CellSize * 0.5f);
  1308. MonaY = PaddleY;
  1309. }
  1310. }
  1311. return(stepPong());
  1312. case MOVE_PADDLE_DOWN:
  1313. ShowBallNext = false;
  1314. if ((MonaX == GridDimensions - 1) && (MonaY == PaddleY))
  1315. {
  1316. if (PaddleY > 0)
  1317. {
  1318. PaddleY--;
  1319. pong->paddle.position = ((float)PaddleY * CellSize) + (CellSize * 0.5f);
  1320. MonaY = PaddleY;
  1321. }
  1322. }
  1323. return(stepPong());
  1324. }
  1325. return(CONTINUE);
  1326. }
  1327. // Step pong.
  1328. OUTCOME stepPong()
  1329. {
  1330. switch (pong->step())
  1331. {
  1332. case Pong::CLEAR:
  1333. if ((MonaX == GridDimensions - 1) &&
  1334. (MonaX == (int)(pong->ball.position.x / CellSize)) &&
  1335. (MonaY == (int)(pong->ball.position.y / CellSize)))
  1336. {
  1337. return(WIN);
  1338. }
  1339. else
  1340. {
  1341. return(CONTINUE);
  1342. }
  1343. case Pong::SCORE:
  1344. if ((MonaX == GridDimensions - 1) &&
  1345. (MonaX == (int)(pong->ball.position.x / CellSize)) &&
  1346. (MonaY == (int)(pong->ball.position.y / CellSize)))
  1347. {
  1348. return(WIN);
  1349. }
  1350. else
  1351. {
  1352. return(LOSE);
  1353. }
  1354. case Pong::STRIKE:
  1355. return(WIN);
  1356. }
  1357. return(CONTINUE);
  1358. }