+ bool keyhelp; /* TRUE if keystroke help is up */
+ int i, j, count;
+ int lastcol; /* last location visited */
+ int lastrow;
+ int ny = 0, nx = 0;
+ int review = 0; /* review history */
+ int test_size;
+ int rw = 0, col = 0; /* current row and column */
+
+ do {
+ SQUARES squares;
+ HISTORY history[(YLIMIT * XLIMIT) + 1];
+ int count_moves = 0; /* count of moves so far */
+
+ /* clear screen and draw board */
+ werase(boardwin);
+ werase(helpwin);
+ werase(msgwin);
+ drawBoard();
+ help1();
+ wnoutrefresh(stdscr);
+ wnoutrefresh(helpwin);
+ wnoutrefresh(msgwin);
+ wnoutrefresh(boardwin);
+ doupdate();
+
+ for (i = 0; i < ylimit; i++) {
+ for (j = 0; j < xlimit; j++) {
+ unmarkcell(i, j);
+ }
+ }
+ memset(squares, 0, sizeof(squares));
+ memset(history, 0, sizeof(history));
+ history[0].y = history[0].x = -1;
+ history[1].y = history[1].x = -1;
+ lastrow = lastcol = -2;
+ count_moves = 1;
+ count_tries = 1;
+ keyhelp = FALSE;
+ show_help(&keyhelp);
+
+ for (;;) {
+ if (rw != lastrow || col != lastcol) {
+ if (lastrow >= 0 && lastcol >= 0) {
+ cellmove(lastrow, lastcol);
+ if (squares[lastrow][lastcol])
+ waddch(boardwin, trail);
+ else
+ waddch(boardwin, oldch);
+ }
+
+ cellmove(rw, col);
+ oldch = winch(boardwin);
+
+ lastrow = rw;
+ lastcol = col;
+ }
+ cellmove(rw, col);
+ waddch(boardwin, plus);
+ cellmove(rw, col);
+
+ wrefresh(msgwin);
+
+ switch (wgetch(boardwin)) {
+ case 'k':
+ case '8':
+ case KEY_UP:
+ ny = rw + ylimit - 1;
+ nx = col;
+ break;
+ case 'j':
+ case '2':
+ case KEY_DOWN:
+ ny = rw + 1;
+ nx = col;
+ break;
+ case 'h':
+ case '4':
+ case KEY_LEFT:
+ ny = rw;
+ nx = col + xlimit - 1;
+ break;
+ case 'l':
+ case '6':
+ case KEY_RIGHT:
+ ny = rw;
+ nx = col + 1;
+ break;
+ case 'y':
+ case '7':
+ case KEY_A1:
+ ny = rw + ylimit - 1;
+ nx = col + xlimit - 1;
+ break;
+ case 'b':
+ case '1':
+ case KEY_C1:
+ ny = rw + 1;
+ nx = col + xlimit - 1;
+ break;
+ case 'u':
+ case '9':
+ case KEY_A3:
+ ny = rw + ylimit - 1;
+ nx = col + 1;
+ break;
+ case 'n':
+ case '3':
+ case KEY_C3:
+ ny = rw + 1;
+ nx = col + 1;
+ break;
+
+#ifdef KEY_MOUSE
+ case KEY_MOUSE:
+#ifdef NCURSES_MOUSE_VERSION
+ {
+ MEVENT myevent;
+
+ getmouse(&myevent);
+ if (myevent.y >= CY(0) && myevent.y <= CY(ylimit)
+ && myevent.x >= CX(0) && myevent.x <= CX(xlimit)) {
+ nx = CXINV(myevent.x);
+ ny = CYINV(myevent.y);
+ ungetch('\n');
+ break;
+ } else {
+ beep();
+ continue;
+ }
+ }
+#endif /* NCURSES_MOUSE_VERSION */
+#ifdef PDCURSES
+ {
+ int test_y, test_x;
+ request_mouse_pos();
+ test_y = MOUSE_Y_POS + 0;
+ test_x = MOUSE_X_POS + 1;
+ if (test_y >= CY(0) && test_y <= CY(ylimit)
+ && test_x >= CX(0) && test_x <= CX(xlimit)) {
+ ny = CYINV(test_y);
+ nx = CXINV(test_x);
+ wmove(helpwin, 0, 0);
+ wrefresh(helpwin);
+ ungetch('\n');
+ }
+ break;
+ }
+#endif /* PDCURSES */
+#endif /* KEY_MOUSE */
+
+ case KEY_B2:
+ case '\n':
+ case ' ':
+ review = 0;
+ if (evaluate_move(squares, history, count_moves, rw, col)) {
+ drawMove(squares,
+ count_moves,
+ trail,
+ history[count_moves - 1].y,
+ history[count_moves - 1].x,
+ rw, col);
+ history[count_moves].y = (short) rw;
+ history[count_moves].x = (short) col;
+ count_moves++;
+ count_tries++;
+
+ if (boardIsFilled(squares, rw, col)) {
+ if (completed(squares) < 0) {
+ waddstr(msgwin, "\nYou won.");
+ } else {
+ waddstr(msgwin,
+ "\nNo further moves are possible.");
+ }
+ }
+ } else {
+ beep();
+ }
+ break;
+
+ case KEY_UNDO:
+ case KEY_BACKSPACE:
+ case '\b':
+ review = 0;
+ if (count_moves <= 0) {
+ no_previous_move();
+ } else if (count_moves <= 1) {
+ ny = history[count_moves].y;
+ nx = history[count_moves].x;
+ if (nx < 0 || ny < 0) {
+ ny = (lastrow >= 0) ? lastrow : 0;
+ nx = (lastcol >= 0) ? lastcol : 0;
+ }
+ count_moves = 0;
+ squares[ny][nx] = FALSE;
+ oldch = minus;
+ drawMove(squares, count_moves, ' ', ny, nx, -1, -1);
+ count_moves = 1;
+ count_tries = 1;
+ no_previous_move();
+ } else {
+ int oldy = history[count_moves - 1].y;
+ int oldx = history[count_moves - 1].x;
+
+ if (!squares[rw][col]) {
+ cellmove(rw, col);
+ waddch(boardwin, ' ');
+ }
+
+ squares[oldy][oldx] = FALSE;
+ --count_moves;
+ ny = history[count_moves - 1].y;
+ nx = history[count_moves - 1].x;
+ if (nx < 0 || ny < 0) {
+ ny = oldy;
+ nx = oldx;
+ }
+ drawMove(squares, count_moves, ' ', oldy, oldx, ny, nx);
+
+ /* avoid problems if we just changed the current cell */
+ cellmove(lastrow, lastcol);
+ oldch = winch(boardwin);
+ }
+ break;
+
+ case 'a':
+ nx = col;
+ ny = rw;
+ if (find_next_move(squares, history, count_moves, &ny, &nx))
+ count_next_moves(squares, count_moves, ny, nx);
+ else
+ beep();
+ break;
+
+ case 'F':
+ review = reviewHistory(history, count_moves, review - 1,
+ &ny, &nx);
+ break;
+
+ case 'B':
+ review = reviewHistory(history, count_moves, review + 1,
+ &ny, &nx);
+ break;
+
+ case 'R':
+ if (ylimit <= 6) {
+ wprintw(msgwin, "\nworking...");
+ wrefresh(msgwin);
+ test_test = 0;
+ test_size = useBacktracking(squares, history, count_moves);
+ wprintw(msgwin, "\nOk %d:%d (%d tests)",
+ test_size, maxmoves, test_test);
+ review = 0;
+ while (count_moves <= test_size) {
+ markcell(trail,
+ ny = history[count_moves].y,
+ nx = history[count_moves].x);
+ count_moves++;
+ }
+ } else {
+ wprintw(msgwin, "\nBoard is too large.");
+ }
+ wrefresh(msgwin);
+ break;
+
+#if HAVE_CURSCR
+ case KEY_REDO:
+ case '\f':
+ case 'r':
+ clearok(curscr, TRUE);
+ wnoutrefresh(stdscr);
+ wnoutrefresh(boardwin);
+ wnoutrefresh(msgwin);
+ wnoutrefresh(helpwin);
+ doupdate();
+ break;
+#endif
+
+ case 'q':
+ case 'x':
+ goto dropout;
+
+ case HELP_KEY_1:
+ show_help(&keyhelp);
+ break;
+
+ default:
+ beep();
+ break;
+ }
+
+ col = nx % xlimit;
+ rw = ny % ylimit;
+ }
+
+ dropout:
+ if ((count = completed(squares)) < 0)
+ wprintw(msgwin, "\nYou won. Care to try again? ");
+ else
+ wprintw(msgwin, "\n%d squares filled. Try again? ", count);
+ wclrtoeol(msgwin);
+ } while
+ (tolower(wgetch(msgwin)) == 'y');