pepper2.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. #include <getopt.h>
  2. #include <curses.h>
  3. #include <unistd.h>
  4. #include <stdlib.h>
  5. #include <malloc_np.h>
  6. #include <string.h>
  7. #include <time.h>
  8. /* cc pepper2.c -lncurses -o p2 -O2 */
  9. typedef struct {
  10. size_t len;
  11. char *items[10];
  12. } truc_array;
  13. enum dirs {
  14. R, /* right */
  15. L, /* left */
  16. U, /* up */
  17. D /* down */
  18. };
  19. static size_t delay = 500;
  20. /* result window */
  21. static WINDOW * winR;
  22. /* sprite */
  23. static void worm(WINDOW *win, int x, int y, char c0, char repl)
  24. {
  25. static int ax, ay;
  26. static char ac = '*';
  27. wattron(win, A_REVERSE | A_BOLD);
  28. mvwprintw(win, y + 1, x + 1, "%c", c0);
  29. wattroff(win, A_REVERSE | A_BOLD);
  30. if (ac != '*')
  31. mvwprintw(win, ay + 1, ax + 1, "%c", ac);
  32. wrefresh(win);
  33. ax = x;
  34. ay = y;
  35. ac = repl;
  36. usleep(delay * 1000);
  37. }
  38. /* path lookup */
  39. static __attribute((malloc)) __attribute__((nonnull)) char *get_it(truc_array const *src)
  40. {
  41. char *r = mallocx(src->len, MALLOCX_ZERO);
  42. size_t n = 0;
  43. enum dirs dir = R;
  44. int x = 0, y = 0;
  45. char c0 = '<';
  46. WINDOW * win = newwin(14, 18, 1, 40);
  47. curs_set(0);
  48. box(win, 0, 0);
  49. while (src->len && (n < src->len)) {
  50. char c;
  51. while((c = src->items[y][x]) != ' ') {
  52. /* store */
  53. if (c != '*') {
  54. r[n++] = c;
  55. worm(win, x, y, c0, c);
  56. mvwprintw(winR, 1, 1, "%s", r);
  57. wrefresh(winR);
  58. } else
  59. worm(win, x, y, c0, '.');
  60. if (n == src->len) {
  61. break;
  62. }
  63. /* test next one */
  64. int tx = x;
  65. int ty = y;
  66. switch (dir) {
  67. case R:
  68. tx++;
  69. break;
  70. case L:
  71. tx--;
  72. break;
  73. case U:
  74. ty--;
  75. break;
  76. case D:
  77. ty++;
  78. break;
  79. default:
  80. fprintf(stderr, "Bug!\n");
  81. break;
  82. }
  83. /* ouch */
  84. if (tx > 14 || tx < 0 || ty <0 || ty > 9)
  85. break;
  86. if ((c = src->items[ty][tx]) == ' ')
  87. break;
  88. /* valid next */
  89. x = tx;
  90. y = ty;
  91. }
  92. switch (dir) {
  93. char c_up, c_down, c_left, c_right;
  94. case R:
  95. case L:
  96. /* cover up and down */
  97. c_up = ' ';
  98. c_down = ' ';
  99. if (y > 1)
  100. c_up = src->items[y - 1][x];
  101. if (y < 9)
  102. c_down = src->items[y + 1][x];
  103. if (c_up != ' ') {
  104. y = y - 1;
  105. dir = U;
  106. c0 = '^';
  107. }
  108. else if (c_down != ' ') {
  109. y = y + 1;
  110. dir = D;
  111. c0 = ';';
  112. }
  113. else
  114. goto end;
  115. break;
  116. case U:
  117. case D:
  118. /* cover left and right */
  119. c_left = ' ';
  120. c_right = ' ';
  121. if (x > 1)
  122. c_left = src->items[y][x - 1];
  123. if (y < 14)
  124. c_right = src->items[y][x + 1];
  125. if (c_left != ' ') {
  126. x = x - 1;
  127. dir = L;
  128. c0 = '>';
  129. }
  130. else if (c_right != ' ') {
  131. x = x + 1;
  132. dir = R;
  133. c0 = '<';
  134. } else
  135. goto end;
  136. break;
  137. }
  138. }
  139. end:
  140. worm(win, x , y , ' ', ' ');
  141. delwin(win);
  142. return r;
  143. }
  144. /* puzzle display */
  145. static void print_it(truc_array src)
  146. {
  147. WINDOW * win = newwin(14, 18, 1, 1);
  148. box(win, 0, 0);
  149. for (size_t j= 0; j < 10; ++j) {
  150. mvwprintw(win, j + 1, 1, "%s", src.items[j]);
  151. }
  152. wrefresh(win);
  153. delwin(win);
  154. }
  155. int main(int argc, char *argv[])
  156. {
  157. truc_array a= {60, };
  158. char *r = NULL;
  159. static struct option longopts[] = {
  160. { "delay", required_argument, NULL, 'd' },
  161. { NULL, 0, NULL, 0 }
  162. };
  163. int ch;
  164. while ((ch = getopt_long(argc, argv, "d:", longopts, NULL)) != -1) {
  165. switch (ch) {
  166. case 'd':
  167. delay = strtoul(optarg, NULL, 10);
  168. break;
  169. case 0:
  170. /* long option */
  171. break;
  172. default:
  173. break;
  174. }
  175. }
  176. /* 012345789ABCDEF */
  177. a.items[0] = "*01** $";
  178. a.items[1] = "edcBA ";
  179. a.items[2] = "* * X ";
  180. a.items[3] = "* ! * ";
  181. a.items[4] = "****F** ";
  182. a.items[5] = " * *H* ";
  183. a.items[6] = " *G** * ";
  184. a.items[7] = " X I ";
  185. a.items[8] = " X **J**** ";
  186. a.items[9] = "X Z $";
  187. initscr();
  188. nonl();
  189. noecho();
  190. winR = newwin(3, 65, 20, 1);
  191. box(winR, 0, 0);
  192. wrefresh(winR);
  193. print_it(a);
  194. r = get_it(&a);
  195. dallocx(r, 0);
  196. delwin(winR);
  197. endwin();
  198. }