struct board board;
WINDOW *gamewin[WINDOW_MAX], *goalwin[WINDOW_MAX];
+ int cursor;
} state;
static void print_version(void)
printf("Report bugs to <%s>.\n", PACKAGE_BUGREPORT);
}
-static void draw_tile(WINDOW **win, unsigned colour,
+static void draw_tile(WINDOW **win, unsigned colour, unsigned selected,
unsigned x, unsigned y, unsigned start_column)
{
WINDOW *border = win[WINDOW_TILEBORDER], *fill = win[WINDOW_TILEFILL];
- int attr, ch;
- int w, h;
+ int w, h, attr, ch, bc = selected ? '#' : 0;
assert(colour < TILE_MAX);
attr = COLOR_PAIR(colour);
case TILE_YELLOW: ch = '~'; attr |= A_BOLD; break;
case TILE_BLUE: ch = 'o'; attr |= A_BOLD; break;
case TILE_WHITE: ch = '.'; attr |= A_BOLD; break;
+
+ case TILE_EMPTY: attr = A_BOLD|COLOR_PAIR(TILE_MAX);
}
getmaxyx(border, h, w);
return;
if (colour != TILE_EMPTY) {
- wattrset(border, attr);
- box(border, 0, 0);
-
mvderwin(fill, 1, 1);
wbkgdset(fill, A_REVERSE|attr|ch);
werase(fill);
werase(border);
}
+ if (bc || colour) {
+ wattrset(border, attr);
+ wborder(border, bc, bc, bc, bc, bc, bc, bc, bc);
+ }
+
wnoutrefresh(border);
}
static int
redraw_tile(WINDOW **win, unsigned x, unsigned y, unsigned start_column,
- uint_fast32_t bit0, uint_fast32_t bit1, uint_fast32_t bit2)
+ uint_fast32_t bit0, uint_fast32_t bit1, uint_fast32_t bit2,
+ unsigned selected)
{
uint_fast32_t pos = board_position(x, y);
unsigned char tile = 0;
if (bit2 & pos) tile |= 4;
assert(tile < TILE_MAX);
- draw_tile(win, tile, x, y, start_column);
+ draw_tile(win, tile, selected, x, y, start_column);
return tile;
}
for (i = 0; i < 25; i++) {
if (mask & 1) {
redraw_tile(state->gamewin, i%5, i/5,
- 4, gp[0], gp[1], gp[2]);
+ 4, gp[0], gp[1], gp[2],
+ i == state->cursor);
}
mask >>= 1;
}
for (i = 0; i < 9; i++) {
if (mask & 1) {
redraw_tile(state->goalwin, i%3, i/3,
- x+2, gp[0], gp[1], gp[2]);
+ x+2, gp[0], gp[1], gp[2], 0);
}
mask >>= 1;
}
}
game_reset(&state.board);
+ state.cursor = 5*state.board.y + state.board.x;
initscr();
start_color();
init_pair(TILE_GREEN, COLOR_GREEN, COLOR_BLACK);
init_pair(TILE_BLUE, COLOR_BLUE, COLOR_BLACK);
init_pair(TILE_WHITE, COLOR_WHITE, COLOR_BLACK);
+ init_pair(TILE_MAX, COLOR_BLACK, COLOR_BLACK);
setup_mainwin(&state);
refresh();
}
-static void do_move(struct app_state *state, int x, int y)
+static uint_fast32_t do_move(struct app_state *state, int x, int y)
{
uint_fast32_t mask;
curs_redraw_game(state, mask);
refresh();
}
+
+ return mask;
}
#if HAVE_CURSES_MOUSE_SUPPORT
}
#endif
if (bstate == BUTTON1_PRESSED) {
+ uint_fast32_t cursor_mask, move_mask;
int w, h;
/* Determine size of the game area */
if (x < 4 || (x -= 4)/5 >= w) return;
if (y < 2 || (y -= 2)/5 >= h) return;
- do_move(state, x/w, y/h);
+ /* Turn off the keyboard cursor when using the mouse */
+ cursor_mask = state->cursor < 0 ? -1 : 1ul << state->cursor;
+ state->cursor = -1;
+
+ move_mask = do_move(state, x/w, y/h);
+ if ((cursor_mask & move_mask) == 0) {
+ curs_redraw_game(state, cursor_mask);
+ refresh();
+ }
}
}
#endif
+static void do_move_cursor(struct app_state *state, int c)
+{
+ uint_fast32_t mask = 1ul << state->cursor;
+
+ if (state->cursor < 0) {
+ /* Reset keyboard cursor to the empty position */
+ state->cursor = 5*state->board.y + state->board.x;
+ }
+
+ switch (c) {
+ case KEY_UP:
+ if ((state->cursor -= 5) < 0)
+ state->cursor += 25;
+ break;
+ case KEY_DOWN:
+ if ((state->cursor += 5) >= 25)
+ state->cursor -= 25;
+ break;
+ case KEY_LEFT:
+ if ((state->cursor -= 1) % 5 == 4 || state->cursor < 0)
+ state->cursor += 5;
+ break;
+ case KEY_RIGHT:
+ if ((state->cursor += 1) % 5 == 0)
+ state->cursor -= 5;
+ break;
+ }
+
+ curs_redraw_game(state, mask | 1ul << state->cursor);
+ refresh();
+}
+
+static void do_keystroke(struct app_state *state, int c)
+{
+ switch (c) {
+ case KEY_DOWN: case KEY_UP: case KEY_LEFT: case KEY_RIGHT:
+ do_move_cursor(state, c);
+ break;
+ case ' ':
+ if (state->cursor >= 0)
+ do_move(state, state->cursor%5, state->cursor/5);
+ break;
+ }
+}
+
int main(int argc, char **argv)
{
setlocale(LC_ALL, "");
do_mouse(&state);
break;
#endif
+ default:
+ do_keystroke(&state, c);
}
}
}