struct board board;
WINDOW *gamewin[WINDOW_MAX], *goalwin[WINDOW_MAX];
+ WINDOW *timer;
int cursor;
} state;
w = MIN(scr_w-split, 3+6*goalsz);
h = MIN(scr_h-GAME_YPOS, 2+3*goalsz);
realloc_area(&state->goalwin[WINDOW_AREA], h, w, GAME_YPOS, split);
+
+ /* Status area */
+ w = MAX(0, scr_w-split-1);
+ realloc_area(&state->timer, 1, w, GAME_YPOS+h, split+1);
}
static void app_initialize(int argc, char **argv)
}
game_reset(&state.board);
- state.cursor = 5*state.board.y + state.board.x;
+ state.cursor = -1;
initscr();
start_color();
cbreak();
keypad(stdscr, TRUE);
if (enable_mouse) {
+ /*
+ * While we only care about a subset of these events, for
+ * some reason with ncurses failing to enable all of them
+ * causes timeout to stop working when disabled buttons are
+ * pressed (or released).
+ *
+ * It is not known if other curses have this problem; at least
+ * pdcurses does not, but the extra events should be harmless
+ * in any case.
+ */
+#if HAVE_CURSES_MOUSE_SUPPORT
+ unsigned long mask = BUTTON1_PRESSED | BUTTON1_RELEASED
+ | BUTTON2_PRESSED | BUTTON2_RELEASED
+ | BUTTON3_PRESSED | BUTTON3_RELEASED
+#ifdef BUTTON4_PRESSED
+ | BUTTON4_PRESSED | BUTTON4_RELEASED
+#endif
+#ifdef BUTTON5_PRESSED
+ | BUTTON5_PRESSED | BUTTON5_RELEASED
+#endif
+ ;
#if HAVE_CURSES_MOUSE_SET
- mouse_set(BUTTON1_PRESSED);
+ mouse_set(mask);
#elif HAVE_CURSES_MOUSEMASK
- mousemask(BUTTON1_PRESSED, NULL);
+ mousemask(mask, NULL);
#endif
#if HAVE_CURSES_MOUSEINTERVAL
mouseinterval(0);
#endif
+#endif /* HAVE_CURSES_MOUSE_SUPPORT */
}
noecho();
if ((mask = game_do_move(&state->board, x, y)) != 0) {
curs_redraw_game(state, mask);
- refresh();
+ doupdate();
}
return mask;
}
+static void do_reset_cursor(struct app_state *state)
+{
+ state->cursor = 5*state->board.y + state->board.x;
+}
+
+static void update_timer(struct app_state *state, uint_fast32_t ms)
+{
+ unsigned sec, min;
+
+ sec = ms / 1000; ms %= 1000;
+ min = sec / 60; sec %= 60;
+ mvwprintw(state->timer, 0, 0, "Time: %u:%.2u.%.3u",
+ min, sec, (unsigned)ms);
+ wclrtoeol(state->timer);
+ wrefresh(state->timer);
+}
+
+static void do_new_game(struct app_state *state)
+{
+ game_reset(&state->board);
+
+ do_reset_cursor(state);
+ curs_redraw_game(state, -1);
+ curs_redraw_goal(state, -1);
+ update_timer(state, 0);
+ doupdate();
+
+ timeout(33);
+ game_begin(&state->board);
+}
+
#if HAVE_CURSES_MOUSE_SUPPORT
static void do_mouse(struct app_state *state)
{
y = MOUSE_Y_POS;
bstate = 0;
- if (BUTTON_CHANGED(1)) {
- switch (BUTTON_STATUS(1)) {
- case BUTTON_RELEASED: bstate |= BUTTON1_RELEASED;
- case BUTTON_PRESSED: bstate |= BUTTON1_PRESSED;
- }
- }
+
+#define set_bstate_helper(button) do { if (BUTTON_CHANGED(button)) \
+ switch (BUTTON_STATUS(button)) { \
+ case BUTTON_RELEASED: bstate |= BUTTON ## button ## _RELEASED; break; \
+ case BUTTON_PRESSED: bstate |= BUTTON ## button ## _PRESSED; break; \
+ } \
+} while (0);
+
+ set_bstate_helper(1);
+ set_bstate_helper(3);
#endif
if (bstate == BUTTON1_PRESSED) {
uint_fast32_t cursor_mask, move_mask;
move_mask = do_move(state, x/w, y/h);
if ((cursor_mask & move_mask) == 0) {
curs_redraw_game(state, cursor_mask);
- refresh();
+ doupdate();
}
}
}
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;
+ /* Cursor was hidden; reset it */
+ do_reset_cursor(state);
}
switch (c) {
setlocale(LC_ALL, "");
app_initialize(argc, argv);
- curs_redraw_game(&state, -1);
- curs_redraw_goal(&state, -1);
- refresh();
+ do_new_game(&state);
while (1) {
int c = getch();
#endif
default:
do_keystroke(&state, c);
+ case ERR:;
}
+
+ update_timer(&state, game_elapsed(&state.board));
}
}