pepper2.c 4.3 KB

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