#include #include #include #include #include #include #include /* cc pepper2.c -lncurses -o p2 -O2 */ typedef struct { size_t len; char *items[10]; } truc_array; enum dirs { R, /* right */ L, /* left */ U, /* up */ D /* down */ }; static size_t delay = 150; /* result window */ static WINDOW * winR; /* sprite */ static void worm(WINDOW *win, int x, int y, char c0, char repl) { static int ax, ay; static char ac = '*'; wattron(win, A_REVERSE); mvwaddch(win, y + 1, x + 1, c0); wattroff(win, A_REVERSE); if (ac != '*') { int colnum = 4; if (ac != '.') colnum = 1; wattron(win, COLOR_PAIR(colnum)); mvwaddch(win, ay, ax, ac); wattroff(win, COLOR_PAIR(colnum)); } wrefresh(win); ax = x + 1; ay = y + 1; ac = repl; usleep(delay * 1000); } /* path lookup */ static __attribute((malloc)) __attribute__((nonnull)) char *get_it(truc_array const *src) { char *r = mallocx(src->len, MALLOCX_ZERO); size_t n = 0; enum dirs dir = R; int x = 0, y = 0; char c0 = '<'; WINDOW * win = newwin(12, 17, 1, 49); curs_set(0); box(win, 0, 0); while (src->len && (n < src->len)) { char c; while((c = src->items[y][x]) != ' ') { /* store */ if (c != '*') { worm(win, x, y, c0, c); if (n > 0) mvwaddch(winR, 1, n , r[n - 1]); r[n++] = c; wattron (winR, COLOR_PAIR(2)); mvwaddch(winR, 1, n, c); wattroff(winR, COLOR_PAIR(2)); wrefresh(winR); } else worm(win, x, y, c0, '.'); if (n == src->len) { break; } /* test next one */ int tx = x; int ty = y; switch (dir) { case R: tx++; break; case L: tx--; break; case U: ty--; break; case D: ty++; break; default: fprintf(stderr, "Bug!\n"); break; } /* ouch */ if (tx > 14 || tx < 0 || ty <0 || ty > 9) break; if ((c = src->items[ty][tx]) == ' ') { wattron(win,COLOR_PAIR(3)); mvwaddch(win, ty + 1, tx + 1, c); wattroff(win, COLOR_PAIR(3)); break; } /* valid next */ x = tx; y = ty; } switch (dir) { char c_up, c_down, c_left, c_right; case R: case L: /* cover up and down */ c_up = ' '; c_down = ' '; if (y > 1) c_up = src->items[y - 1][x]; if (y < 9) c_down = src->items[y + 1][x]; if (c_up != ' ') { y = y - 1; dir = U; c0 = '^'; } else if (c_down != ' ') { y = y + 1; dir = D; c0 = ';'; } else goto end; break; case U: case D: /* cover left and right */ c_left = ' '; c_right = ' '; if (x > 1) c_left = src->items[y][x - 1]; if (y < 14) c_right = src->items[y][x + 1]; if (c_left != ' ') { x = x - 1; dir = L; c0 = '>'; } else if (c_right != ' ') { x = x + 1; dir = R; c0 = '<'; } else goto end; break; } } end: worm(win, x , y , ' ', ' '); if (n > 1) { mvwaddch(winR, 1, n, r[n -1]); wrefresh(winR); } delwin(win); return r; } /* puzzle display */ static void print_it(truc_array src) { WINDOW * win = newwin(12, 17, 1, 1); box(win, 0, 0); for (size_t j= 0; j < 10; ++j) { mvwprintw(win, j + 1, 1, "%s", src.items[j]); } wrefresh(win); delwin(win); } int main(int argc, char *argv[]) { truc_array a= {60, }; char *r = NULL; static struct option longopts[] = { { "delay", required_argument, NULL, 'd' }, { NULL, 0, NULL, 0 } }; int ch; while ((ch = getopt_long(argc, argv, "d:", longopts, NULL)) != -1) { switch (ch) { case 'd': delay = strtoul(optarg, NULL, 10); break; case 0: /* long option */ break; default: break; } } /* 012345789ABCDEF */ a.items[0] = "*01** $"; a.items[1] = "edcBA "; a.items[2] = "* * X "; a.items[3] = "* ! * "; a.items[4] = "****F** "; a.items[5] = " * *H* "; a.items[6] = " *G** * "; a.items[7] = " X I "; a.items[8] = " X **J**** "; a.items[9] = "X Z $"; initscr(); nonl(); noecho(); winR = newwin(3, 65, 13, 1); box(winR, 0, 0); wrefresh(winR); start_color(); init_pair(1, COLOR_RED, COLOR_GREEN); init_pair(2, COLOR_BLACK, COLOR_MAGENTA); init_pair(3, COLOR_BLUE, COLOR_BLUE); init_pair(4, COLOR_YELLOW, COLOR_GREEN); print_it(a); r = get_it(&a); dallocx(r, 0); delwin(winR); endwin(); }