maze.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. Source: http://rosettacode.org/wiki/Maze_generation#C
  3. License: http://www.gnu.org/licenses/fdl.html
  4. another option could be "recursive division"
  5. http://weblog.jamisbuck.org/2011/1/12/maze-generation-recursive-division-algorithm
  6. roguelike:
  7. http://www.roguebasin.com/index.php?title=Roguelike_Dev_FAQ
  8. http://www.roguebasin.com/index.php?title=How_to_Write_a_Roguelike_in_15_Steps
  9. http://www.roguebasin.com/index.php?title=Finding_graphical_tiles
  10. http://opengameart.org/content/2d-rpg-tiles
  11. http://opengameart.org/content/tileset-1bit-color
  12. http://opengameart.org/content/tileset-1bit-color-extention
  13. http://dwarffortresswiki.org/index.php/Tileset_repository
  14. http://game-icons.net/ << could be nice
  15. https://www.reddit.com/r/gamedev/comments/444zbl/roguelike_tilesets/
  16. http://cc.retinaleclipse.com/minirogue-c64-all.png (https://forums.tigsource.com/index.php?topic=14166.0)
  17. http://quale-art.blogspot.de/p/scroll-o-sprites.html oder http://imgur.com/a/uHx4k
  18. fonts:
  19. http://de.fonts2u.com/pixelcharas.schriftart
  20. http://fontstruct.com/fontstructions/show/475298/monstapix (http://de.fonts2u.com/monstapix-regular.schriftart)
  21. */
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <locale.h>
  26. #define DOUBLE_SPACE 0
  27. #if DOUBLE_SPACE
  28. # define SPC " "
  29. #else
  30. # define SPC " "
  31. #endif
  32. wchar_t glyph[] = L""SPC"│││─┘┐┤─└┌├─┴┬┼"SPC"┆┆┆┄╯╮ ┄╰╭ ┄";
  33. typedef unsigned char byte;
  34. enum { N = 1, S = 2, W = 4, E = 8, V = 16 };
  35. byte **cell;
  36. int w, h, avail;
  37. #define each(i, x, y) for (i = x; i <= y; i++)
  38. int irand(int n)
  39. {
  40. int r, rmax = n * (RAND_MAX / n);
  41. while ((r = rand()) >= rmax);
  42. return r / (RAND_MAX/n);
  43. }
  44. void show()
  45. {
  46. int i, j, c;
  47. each(i, 0, 2 * h) {
  48. each(j, 0, 2 * w) {
  49. c = cell[i][j];
  50. if (c > V) printf("\033[31m");
  51. printf("%lc", glyph[c]);
  52. if (c > V) printf("\033[m");
  53. }
  54. putchar('\n');
  55. }
  56. }
  57. inline int max(int a, int b) { return a >= b ? a : b; }
  58. inline int min(int a, int b) { return b >= a ? a : b; }
  59. static int dirs[4][2] = {{-2, 0}, {0, 2}, {2, 0}, {0, -2}};
  60. void walk(int x, int y)
  61. {
  62. int i, t, x1, y1, d[4] = { 0, 1, 2, 3 };
  63. cell[y][x] |= V;
  64. avail--;
  65. for (x1 = 3; x1; x1--)
  66. if (x1 != (y1 = irand(x1 + 1)))
  67. i = d[x1], d[x1] = d[y1], d[y1] = i;
  68. for (i = 0; avail && i < 4; i++) {
  69. x1 = x + dirs[ d[i] ][0], y1 = y + dirs[ d[i] ][1];
  70. if (cell[y1][x1] & V) continue;
  71. /* break walls */
  72. if (x1 == x) {
  73. t = (y + y1) / 2;
  74. cell[t][x+1] &= ~W, cell[t][x] &= ~(E|W), cell[t][x-1] &= ~E;
  75. } else if (y1 == y) {
  76. t = (x + x1)/2;
  77. cell[y-1][t] &= ~S, cell[y][t] &= ~(N|S), cell[y+1][t] &= ~N;
  78. }
  79. walk(x1, y1);
  80. }
  81. }
  82. int solve(int x, int y, int tox, int toy)
  83. {
  84. int i, t, x1, y1;
  85. cell[y][x] |= V;
  86. if (x == tox && y == toy) return 1;
  87. each(i, 0, 3) {
  88. x1 = x + dirs[i][0], y1 = y + dirs[i][1];
  89. if (cell[y1][x1]) continue;
  90. /* mark path */
  91. if (x1 == x) {
  92. t = (y + y1)/2;
  93. if (cell[t][x] || !solve(x1, y1, tox, toy)) continue;
  94. cell[t-1][x] |= S, cell[t][x] |= V|N|S, cell[t+1][x] |= N;
  95. } else if (y1 == y) {
  96. t = (x + x1)/2;
  97. if (cell[y][t] || !solve(x1, y1, tox, toy)) continue;
  98. cell[y][t-1] |= E, cell[y][t] |= V|E|W, cell[y][t+1] |= W;
  99. }
  100. return 1;
  101. }
  102. /* backtrack */
  103. cell[y][x] &= ~V;
  104. return 0;
  105. }
  106. void make_maze()
  107. {
  108. int i, j;
  109. int h2 = 2 * h + 2, w2 = 2 * w + 2;
  110. byte **p;
  111. p = calloc(sizeof(byte*) * (h2 + 2) + w2 * h2 + 1, 1);
  112. p[1] = (byte*)(p + h2 + 2) + 1;
  113. each(i, 2, h2) p[i] = p[i-1] + w2;
  114. p[0] = p[h2];
  115. cell = &p[1];
  116. each(i, -1, 2 * h + 1) cell[i][-1] = cell[i][w2 - 1] = V;
  117. each(j, 0, 2 * w) cell[-1][j] = cell[h2 - 1][j] = V;
  118. each(i, 0, h) each(j, 0, 2 * w) cell[2*i][j] |= E|W;
  119. each(i, 0, 2 * h) each(j, 0, w) cell[i][2*j] |= N|S;
  120. each(j, 0, 2 * w) cell[0][j] &= ~N, cell[2*h][j] &= ~S;
  121. each(i, 0, 2 * h) cell[i][0] &= ~W, cell[i][2*w] &= ~E;
  122. avail = w * h;
  123. walk(irand(2) * 2 + 1, irand(h) * 2 + 1);
  124. /* reset visited marker (it's also used by path finder) */
  125. each(i, 0, 2 * h) each(j, 0, 2 * w) cell[i][j] &= ~V;
  126. solve(1, 1, 2 * w - 1, 2 * h - 1);
  127. show();
  128. }
  129. int main(int c, char **v)
  130. {
  131. setlocale(LC_ALL, "");
  132. if (c < 2 || (w = atoi(v[1])) <= 0) w = 16;
  133. if (c < 3 || (h = atoi(v[2])) <= 0) h = 8;
  134. make_maze();
  135. return 0;
  136. }