fork download
  1. // SnakeAI.cpp : This file contains the 'main' function. Program execution begins and ends there.
  2. //
  3.  
  4. #include <iostream>
  5.  
  6. int main()
  7. {
  8. std::cout << "Hello World!\n";
  9. }
  10.  
  11. // Run program: Ctrl + F5 or Debug > Start Without Debugging menu
  12. // Debug program: F5 or Debug > Start Debugging menu
  13.  
  14. // Tips for Getting Started:
  15. // 1. Use the Solution Explorer window to add/manage files
  16. // 2. Use the Team Explorer window to connect to source control
  17. // 3. Use the Output window to see build output and other messages
  18. // 4. Use the Error List window to view errors
  19. // 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project
  20. // 6. In the future, to open this project again, go to File > Open > Project and select the .sln file
  21. #define ARENA_SIZE 13 * 13
  22. #define ARENA_HEIGHT 13
  23. #define ARENA_WIDTH 13
  24.  
  25. int tourToNumber[ARENA_SIZE];
  26.  
  27. /* Take an x,y coordinate, and turn it into an index in the tour */
  28. int getPathNumber(int x, int y) {
  29. return tourToNumber[x + ARENA_WIDTH * y];
  30. }
  31.  
  32. int path_distance(int a, int b) {
  33. if (a < b)
  34. return b - a - 1;
  35. return b - a - 1 + ARENA_SIZE;
  36. }
  37.  
  38. struct Maze {
  39. struct Node {
  40. bool visited : 1;
  41. bool canGoRight : 1;
  42. bool canGoDown : 1;
  43. };
  44. Node nodes[ARENA_SIZE / 4];
  45. void markVisited(int x, int y) {
  46. nodes[x + y * ARENA_WIDTH / 2].visited = true;
  47. }
  48. void markCanGoRight(int x, int y) {
  49. nodes[x + y * ARENA_WIDTH / 2].canGoRight = true;
  50. }
  51. void markCanGoDown(int x, int y) {
  52. nodes[x + y * ARENA_WIDTH / 2].canGoDown = true;
  53. }
  54. bool canGoRight(int x, int y) {
  55. return nodes[x + y * ARENA_WIDTH / 2].canGoRight;;
  56. }
  57. bool canGoDown(int x, int y) {
  58. return nodes[x + y * ARENA_WIDTH / 2].canGoDown;
  59. }
  60. bool canGoLeft(int x, int y) {
  61. if (x == 0) return false;
  62. return nodes[(x - 1) + y * ARENA_WIDTH / 2].canGoRight;
  63. }
  64.  
  65. bool canGoUp(int x, int y) {
  66. if (y == 0) return false;
  67. return nodes[x + (y - 1) * ARENA_WIDTH / 2].canGoDown;
  68. }
  69.  
  70. bool isVisited(int x, int y) {
  71. return nodes[x + y * ARENA_WIDTH / 2].visited;
  72. }
  73.  
  74. void generate() {
  75. memset(nodes, 0, sizeof(nodes));
  76. generate_r(-1, -1, 0, 0);
  77. generateTourNumber();
  78. #ifdef LOG_TO_FILE
  79. writeMazeToFile();
  80. writeTourToFile();
  81. #endif
  82. }
  83.  
  84. void generate_r(int fromx, int fromy, int x, int y) {
  85. if (x < 0 || y < 0 || x >= ARENA_WIDTH / 2 || y >= ARENA_HEIGHT / 2)
  86. return;
  87. if (isVisited(x, y))
  88. return;
  89. markVisited(x, y);
  90.  
  91. if (fromx != -1) {
  92. if (fromx < x)
  93. markCanGoRight(fromx, fromy);
  94. else if (fromx > x)
  95. markCanGoRight(x, y);
  96. else if (fromy < y)
  97. markCanGoDown(fromx, fromy);
  98. else if (fromy > y)
  99. markCanGoDown(x, y);
  100.  
  101. //Remove wall between fromx and fromy
  102. }
  103.  
  104. /* We want to visit the four connected nodes randomly,
  105.   * so we just visit two randomly (maybe already visited)
  106.   * then just visit them all non-randomly. It's okay to
  107.   * visit the same node twice */
  108. for (int i = 0; i < 2; i++) {
  109. int r = rand() % 4;
  110. switch (r) {
  111. case 0: generate_r(x, y, x - 1, y); break;
  112. case 1: generate_r(x, y, x + 1, y); break;
  113. case 2: generate_r(x, y, x, y - 1); break;
  114. case 3: generate_r(x, y, x, y + 1); break;
  115. }
  116. }
  117. generate_r(x, y, x - 1, y);
  118. generate_r(x, y, x + 1, y);
  119. generate_r(x, y, x, y + 1);
  120. generate_r(x, y, x, y - 1);
  121. }
  122.  
  123. SnakeDirection findNextDir(int x, int y, SnakeDirection dir) {
  124. if (dir == Right) {
  125. if (canGoUp(x, y))
  126. return Up;
  127. if (canGoRight(x, y))
  128. return Right;
  129. if (canGoDown(x, y))
  130. return Down;
  131. return Left;
  132. }
  133. else if (dir == Down) {
  134. if (canGoRight(x, y))
  135. return Right;
  136. if (canGoDown(x, y))
  137. return Down;
  138. if (canGoLeft(x, y))
  139. return Left;
  140. return Up;
  141. }
  142. else if (dir == Left) {
  143. if (canGoDown(x, y))
  144. return Down;
  145. if (canGoLeft(x, y))
  146. return Left;
  147. if (canGoUp(x, y))
  148. return Up;
  149. return Right;
  150. }
  151. else if (dir == Up) {
  152. if (canGoLeft(x, y))
  153. return Left;
  154. if (canGoUp(x, y))
  155. return Up;
  156. if (canGoRight(x, y))
  157. return Right;
  158. return Down;
  159. }
  160. return (SnakeDirection)-1; //Unreachable
  161. }
  162. void setTourNumber(int x, int y, int number) {
  163. if (getPathNumber(x, y) != 0)
  164. return; /* Back to the starting node */
  165. tourToNumber[x + ARENA_WIDTH * y] = number;
  166. }
  167.  
  168. void generateTourNumber() {
  169. const int start_x = 0;
  170. const int start_y = 0;
  171. int x = start_x;
  172. int y = start_y;
  173. const SnakeDirection start_dir = canGoDown(x, y) ? Up : Left;
  174. SnakeDirection dir = start_dir;
  175. int number = 0;
  176. do {
  177. SnakeDirection nextDir = findNextDir(x, y, dir);
  178. switch (dir) {
  179. case Right:
  180. setTourNumber(x * 2, y * 2, number++);
  181. if (nextDir == dir || nextDir == Down || nextDir == Left)
  182. setTourNumber(x * 2 + 1, y * 2, number++);
  183. if (nextDir == Down || nextDir == Left)
  184. setTourNumber(x * 2 + 1, y * 2 + 1, number++);
  185. if (nextDir == Left)
  186. setTourNumber(x * 2, y * 2 + 1, number++);
  187. break;
  188. case Down:
  189. setTourNumber(x * 2 + 1, y * 2, number++);
  190. if (nextDir == dir || nextDir == Left || nextDir == Up)
  191. setTourNumber(x * 2 + 1, y * 2 + 1, number++);
  192. if (nextDir == Left || nextDir == Up)
  193. setTourNumber(x * 2, y * 2 + 1, number++);
  194. if (nextDir == Up)
  195. setTourNumber(x * 2, y * 2, number++);
  196. break;
  197. case Left:
  198. setTourNumber(x * 2 + 1, y * 2 + 1, number++);
  199. if (nextDir == dir || nextDir == Up || nextDir == Right)
  200. setTourNumber(x * 2, y * 2 + 1, number++);
  201. if (nextDir == Up || nextDir == Right)
  202. setTourNumber(x * 2, y * 2, number++);
  203. if (nextDir == Right)
  204. setTourNumber(x * 2 + 1, y * 2, number++);
  205. break;
  206. case Up:
  207. setTourNumber(x * 2, y * 2 + 1, number++);
  208. if (nextDir == dir || nextDir == Right || nextDir == Down)
  209. setTourNumber(x * 2, y * 2, number++);
  210. if (nextDir == Right || nextDir == Down)
  211. setTourNumber(x * 2 + 1, y * 2, number++);
  212. if (nextDir == Down)
  213. setTourNumber(x * 2 + 1, y * 2 + 1, number++);
  214. break;
  215. }
  216. dir = nextDir;
  217.  
  218. switch (nextDir) {
  219. case Right: ++x; break;
  220. case Left: --x; break;
  221. case Down: ++y; break;
  222. case Up: --y; break;
  223. }
  224.  
  225. } while (number != ARENA_SIZE); //Loop until we return to the start
  226. }
  227. #ifdef LOG_TO_FILE
  228. void writeTourToFile() {
  229. FILE* f = fopen("maps.txt", "w+");
  230. for (int y = 0; y < ARENA_HEIGHT; ++y) {
  231. for (int x = 0; x < ARENA_WIDTH; ++x)
  232. fprintf(f, "%4d", getPathNumber(x, y));
  233. fprintf(f, "\n");
  234. }
  235. fclose(f);
  236. }
  237. void writeMazeToFile() {
  238. FILE* f = fopen("maze.txt", "w+");
  239. for (int y = 0; y < ARENA_HEIGHT / 2; ++y) {
  240. fprintf(f, "#");
  241. for (int x = 0; x < ARENA_WIDTH / 2; ++x)
  242. if (canGoRight(x, y) && canGoDown(x, y))
  243. fprintf(f, "+");
  244. else if (canGoRight(x, y))
  245. fprintf(f, "-");
  246. else if (canGoDown(x, y))
  247. fprintf(f, "|");
  248. else
  249. fprintf(f, " ");
  250. fprintf(f, "#\n");
  251. }
  252. fclose(f);
  253. }
  254. #endif
  255. };
  256.  
  257. void aiInit() {
  258. Maze maze;
  259. maze.generate();
  260. }
  261.  
  262. enum SnakeDirection
  263. {
  264. Right, Left, Up, Down
  265. };
  266.  
  267. SnakeDirection aiGetNewSnakeDirection(int x, int y) {
  268. const int pathNumber = getPathNumber(x, y);
  269. const int distanceToFood = path_distance(pathNumber, getPathNumber(food.x, food.y));
  270. const int distanceToTail = path_distance(pathNumber, getPathNumber(snake.tail_x, snake.tail_y));
  271. int cuttingAmountAvailable = distanceToTail - snake.growth_length - 3 /* Allow a small buffer */;
  272. const int numEmptySquaresOnBoard = ARENA_SIZE - snake.drawn_length - snake.growth_length - food.value;
  273. // If we don't have much space (i.e. snake is 75% of board) then don't take any shortcuts */
  274. if (numEmptySquaresOnBoard < ARENA_SIZE / 2)
  275. cuttingAmountAvailable = 0;
  276. else if (distanceToFood < distanceToTail) { /* We will eat the food on the way to the tail, so take that into account */
  277. cuttingAmountAvailable -= food.value;
  278. /* Once we ate that food, we might end up with another food suddenly appearing in front of us */
  279. if ((distanceToTail - distanceToFood) * 4 > numEmptySquaresOnBoard) /* 25% chance of another number appearing */
  280. cuttingAmountAvailable -= 10;
  281. }
  282. int cuttingAmountDesired = distanceToFood;
  283. if (cuttingAmountDesired < cuttingAmountAvailable)
  284. cuttingAmountAvailable = cuttingAmountDesired;
  285. if (cuttingAmountAvailable < 0)
  286. cuttingAmountAvailable = 0;
  287. // cuttingAmountAvailable is now the maximum amount that we can cut by
  288.  
  289. bool canGoRight = !check_for_collision(x + 1, y);
  290. bool canGoLeft = !check_for_collision(x - 1, y);
  291. bool canGoDown = !check_for_collision(x, y + 1);
  292. bool canGoUp = !check_for_collision(x, y - 1);
  293.  
  294. SnakeDirection bestDir;
  295. int bestDist = -1;
  296. if (canGoRight) {
  297. int dist = path_distance(pathNumber, getPathNumber(x + 1, y));
  298. if (dist <= cuttingAmountAvailable && dist > bestDist) {
  299. bestDir = Right;
  300. bestDist = dist;
  301. }
  302. }
  303. if (canGoLeft) {
  304. int dist = path_distance(pathNumber, getPathNumber(x - 1, y));
  305. if (dist <= cuttingAmountAvailable && dist > bestDist) {
  306. bestDir = Left;
  307. bestDist = dist;
  308. }
  309. }
  310. if (canGoDown) {
  311. int dist = path_distance(pathNumber, getPathNumber(x, y + 1));
  312. if (dist <= cuttingAmountAvailable && dist > bestDist) {
  313. bestDir = Down;
  314. bestDist = dist;
  315. }
  316. }
  317. if (canGoUp) {
  318. int dist = path_distance(pathNumber, getPathNumber(x, y - 1));
  319. if (dist <= cuttingAmountAvailable && dist > bestDist) {
  320. bestDir = Up;
  321. bestDist = dist;
  322. }
  323. }
  324. if (bestDist >= 0)
  325. return bestDir;
  326.  
  327. if (canGoUp)
  328. return Up;
  329. if (canGoLeft)
  330. return Left;
  331. if (canGoDown)
  332. return Down;
  333. if (canGoRight)
  334. return Right;
  335. return Right;
  336. }
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
prog.cpp:123:5: error: ‘SnakeDirection’ does not name a type
     SnakeDirection findNextDir(int x, int y, SnakeDirection dir) {
     ^~~~~~~~~~~~~~
prog.cpp: In member function ‘void Maze::generate()’:
prog.cpp:75:9: error: ‘memset’ was not declared in this scope
         memset(nodes, 0, sizeof(nodes));
         ^~~~~~
prog.cpp:75:9: note: ‘memset’ is defined in header ‘<cstring>’; did you forget to ‘#include <cstring>’?
prog.cpp:5:1:
+#include <cstring>
 
prog.cpp:75:9:
         memset(nodes, 0, sizeof(nodes));
         ^~~~~~
prog.cpp: In member function ‘void Maze::generateTourNumber()’:
prog.cpp:173:15: error: ‘SnakeDirection’ does not name a type
         const SnakeDirection start_dir = canGoDown(x, y) ? Up : Left;
               ^~~~~~~~~~~~~~
prog.cpp:174:9: error: ‘SnakeDirection’ was not declared in this scope
         SnakeDirection dir = start_dir;
         ^~~~~~~~~~~~~~
prog.cpp:177:27: error: expected ‘;’ before ‘nextDir’
             SnakeDirection nextDir = findNextDir(x, y, dir);
                           ^~~~~~~~
                           ;
prog.cpp:178:21: error: ‘dir’ was not declared in this scope
             switch (dir) {
                     ^~~
prog.cpp:178:21: note: suggested alternative: ‘div’
             switch (dir) {
                     ^~~
                     div
prog.cpp:179:18: error: ‘Right’ was not declared in this scope
             case Right:
                  ^~~~~
prog.cpp:181:21: error: ‘nextDir’ was not declared in this scope
                 if (nextDir == dir || nextDir == Down || nextDir == Left)
                     ^~~~~~~
prog.cpp:181:50: error: ‘Down’ was not declared in this scope
                 if (nextDir == dir || nextDir == Down || nextDir == Left)
                                                  ^~~~
prog.cpp:181:69: error: ‘Left’ was not declared in this scope
                 if (nextDir == dir || nextDir == Down || nextDir == Left)
                                                                     ^~~~
prog.cpp:183:21: error: ‘nextDir’ was not declared in this scope
                 if (nextDir == Down || nextDir == Left)
                     ^~~~~~~
prog.cpp:183:32: error: ‘Down’ was not declared in this scope
                 if (nextDir == Down || nextDir == Left)
                                ^~~~
prog.cpp:183:51: error: ‘Left’ was not declared in this scope
                 if (nextDir == Down || nextDir == Left)
                                                   ^~~~
prog.cpp:185:21: error: ‘nextDir’ was not declared in this scope
                 if (nextDir == Left)
                     ^~~~~~~
prog.cpp:185:32: error: ‘Left’ was not declared in this scope
                 if (nextDir == Left)
                                ^~~~
prog.cpp:188:18: error: ‘Down’ was not declared in this scope
             case Down:
                  ^~~~
prog.cpp:190:21: error: ‘nextDir’ was not declared in this scope
                 if (nextDir == dir || nextDir == Left || nextDir == Up)
                     ^~~~~~~
prog.cpp:190:50: error: ‘Left’ was not declared in this scope
                 if (nextDir == dir || nextDir == Left || nextDir == Up)
                                                  ^~~~
prog.cpp:190:69: error: ‘Up’ was not declared in this scope
                 if (nextDir == dir || nextDir == Left || nextDir == Up)
                                                                     ^~
prog.cpp:192:21: error: ‘nextDir’ was not declared in this scope
                 if (nextDir == Left || nextDir == Up)
                     ^~~~~~~
prog.cpp:192:32: error: ‘Left’ was not declared in this scope
                 if (nextDir == Left || nextDir == Up)
                                ^~~~
prog.cpp:192:51: error: ‘Up’ was not declared in this scope
                 if (nextDir == Left || nextDir == Up)
                                                   ^~
prog.cpp:194:21: error: ‘nextDir’ was not declared in this scope
                 if (nextDir == Up)
                     ^~~~~~~
prog.cpp:194:32: error: ‘Up’ was not declared in this scope
                 if (nextDir == Up)
                                ^~
prog.cpp:197:18: error: ‘Left’ was not declared in this scope
             case Left:
                  ^~~~
prog.cpp:199:21: error: ‘nextDir’ was not declared in this scope
                 if (nextDir == dir || nextDir == Up || nextDir == Right)
                     ^~~~~~~
prog.cpp:199:50: error: ‘Up’ was not declared in this scope
                 if (nextDir == dir || nextDir == Up || nextDir == Right)
                                                  ^~
prog.cpp:201:21: error: ‘nextDir’ was not declared in this scope
                 if (nextDir == Up || nextDir == Right)
                     ^~~~~~~
prog.cpp:201:32: error: ‘Up’ was not declared in this scope
                 if (nextDir == Up || nextDir == Right)
                                ^~
prog.cpp:203:21: error: ‘nextDir’ was not declared in this scope
                 if (nextDir == Right)
                     ^~~~~~~
prog.cpp:206:18: error: ‘Up’ was not declared in this scope
             case Up:
                  ^~
prog.cpp:208:21: error: ‘nextDir’ was not declared in this scope
                 if (nextDir == dir || nextDir == Right || nextDir == Down)
                     ^~~~~~~
prog.cpp:210:21: error: ‘nextDir’ was not declared in this scope
                 if (nextDir == Right || nextDir == Down)
                     ^~~~~~~
prog.cpp:212:21: error: ‘nextDir’ was not declared in this scope
                 if (nextDir == Down)
                     ^~~~~~~
prog.cpp:216:13: error: ‘dir’ was not declared in this scope
             dir = nextDir;
             ^~~
prog.cpp:216:13: note: suggested alternative: ‘div’
             dir = nextDir;
             ^~~
             div
prog.cpp:216:19: error: ‘nextDir’ was not declared in this scope
             dir = nextDir;
                   ^~~~~~~
prog.cpp:219:18: error: ‘Right’ was not declared in this scope
             case Right: ++x; break;
                  ^~~~~
prog.cpp:220:18: error: ‘Left’ was not declared in this scope
             case Left: --x; break;
                  ^~~~
prog.cpp:221:18: error: ‘Down’ was not declared in this scope
             case Down: ++y; break;
                  ^~~~
prog.cpp:222:18: error: ‘Up’ was not declared in this scope
             case Up: --y; break;
                  ^~
prog.cpp: In function ‘SnakeDirection aiGetNewSnakeDirection(int, int)’:
prog.cpp:269:72: error: ‘food’ was not declared in this scope
     const int distanceToFood = path_distance(pathNumber, getPathNumber(food.x, food.y));
                                                                        ^~~~
prog.cpp:269:72: note: suggested alternative: ‘feof’
     const int distanceToFood = path_distance(pathNumber, getPathNumber(food.x, food.y));
                                                                        ^~~~
                                                                        feof
prog.cpp:270:72: error: ‘snake’ was not declared in this scope
     const int distanceToTail = path_distance(pathNumber, getPathNumber(snake.tail_x, snake.tail_y));
                                                                        ^~~~~
prog.cpp:289:24: error: ‘check_for_collision’ was not declared in this scope
     bool canGoRight = !check_for_collision(x + 1, y);
                        ^~~~~~~~~~~~~~~~~~~
stdout
Standard output is empty