From c7c503498a82194c15fbdbf8647af6cc12d62120 Mon Sep 17 00:00:00 2001 From: girst Date: Thu, 26 Apr 2018 22:49:33 +0200 Subject: [PATCH] refactor main event loop probably needs more testing. I've started reusing enums; let's see how that turns out. --- mines.c | 134 ++++++++++++++++++++++++++++++-------------------------- mines.h | 14 +++--- 2 files changed, 81 insertions(+), 67 deletions(-) diff --git a/mines.c b/mines.c index 323c930..fb5ef9b 100644 --- a/mines.c +++ b/mines.c @@ -79,38 +79,64 @@ int main (int argc, char** argv) { } } + signal_setup(); + screen_setup(1); + atexit (*quit); + /* check boundaries */ if (f.m > (f.w-1) * (f.h-1)) { + move_ph (LINE_OFFSET+f.h+LINES_AFTER-1,0); f.m = (f.w-1) * (f.h-1); - fprintf (stderr, "too many mines. reduced to %d.\r\n", f.m); //TODO: doesn't show up + fprintf (stdout, "too many mines. reduced to %d.\r\n", f.m); //TODO: doesn't show up } /* end check */ - signal_setup(); - screen_setup(1); - atexit (*quit); - newgame: + switch (minesviiper()) { + case GAME_NEW: goto newgame; + case GAME_WON: g.o = GAME_WON; break; + case GAME_LOST:g.o = GAME_LOST;break; + } + + timer_setup(0); /* stop timer */ + show_minefield (SHOWMINES); + int gotaction; + do { + unsigned char mouse[3]; + gotaction = getch(mouse); + if (gotaction==CTRSEQ_MOUSE_LEFT && clicked_emoticon(mouse)) { + free_field (); + goto newgame; + } else if (gotaction == 'r') { + free_field (); + goto newgame; + } else if (gotaction == 'q') { + goto quit; + } + } while (1); + +quit: + return 0; +} + +int minesviiper(void) { f.c = alloc_array (f.h, f.w); g = (const struct game){0}; /* reset all game-specific parameters */ - - struct line_col markers[26]; - for (int i=26; i; markers[--i].l = -1); + for (int i=26; i; g.m[--i].l = -1); show_minefield (NORMAL); while (1) { int action; - unsigned char mouse[3]; - action = getch(mouse); + action = getch_wrapper(); switch (action) { case ' ': if (g.s == MODE_OPEN || f.c[g.p[0]][g.p[1]].o == OPENED) { switch (do_uncover(&(g.n))) { - case GAME_LOST: goto lose; - case GAME_WON: goto win; + case GAME_LOST: return GAME_LOST; + case GAME_WON: return GAME_WON; } } else if (g.s == MODE_FLAG) { flag_square (g.p[0], g.p[1]); @@ -122,31 +148,13 @@ newgame: show_minefield (g.c?SHOWMINES:NORMAL); break; case CTRSEQ_MOUSE_LEFT: - if (clicked_emoticon(mouse)) { - free_field (); - goto newgame; - } - if (screen2field_c (mouse[1]) < 0 || - screen2field_c (mouse[1]) >= f.w || - screen2field_l (mouse[2]) < 0 || - screen2field_l (mouse[2]) >= f.h) break; - g.p[0] = screen2field_l (mouse[2]); - g.p[1] = screen2field_c (mouse[1]); - /* fallthrough */ case 'o': switch (do_uncover(&(g.n))) { - case GAME_LOST: goto lose; - case GAME_WON: goto win; + case GAME_LOST: return GAME_LOST; + case GAME_WON: return GAME_WON; } break; case CTRSEQ_MOUSE_RIGHT: - if (screen2field_c (mouse[1]) < 0 || - screen2field_c (mouse[1]) >= f.w || - screen2field_l (mouse[2]) < 0 || - screen2field_l (mouse[2]) >= f.h) break; - g.p[0] = screen2field_l (mouse[2]); - g.p[1] = screen2field_c (mouse[1]); - /* fallthrough */ case 'i': flag_square (g.p[0], g.p[1]); break; case '?':quesm_square (g.p[0], g.p[1]); break; case CTRSEQ_CURSOR_LEFT: @@ -168,23 +176,24 @@ newgame: case 'G': move_hi (f.h-1, g.p[1] ); break; case 'z': move_hi (f.h/2, f.w/2); break; case 'm': - action = tolower(getch(mouse)); + action = tolower(getch_wrapper()); if (action < 'a' || action > 'z') break;/*out of bound*/ - markers[action-'a'].l = g.p[0]; - markers[action-'a'].c = g.p[1]; + g.m[action-'a'].l = g.p[0]; + g.m[action-'a'].c = g.p[1]; break; case'\'': /* fallthrough */ case '`': - action = tolower(getch(mouse)); + action = tolower(getch_wrapper()); if (action < 'a' || action > 'z' /* out of bound or */ - || markers[action-'a'].l == -1) break; /* unset */ - move_hi (markers[action-'a'].l, markers[action-'a'].c); + || g.m[action-'a'].l == -1) break; /* unset */ + move_hi (g.m[action-'a'].l, g.m[action-'a'].c); break; + case WRAPPER_EMOTICON: case 'r': /* start a new game */ free_field (); - goto newgame; + return GAME_NEW; case 'q': - goto quit; + return GAME_QUIT; case '\014': /* Ctrl-L -- redraw */ show_minefield (NORMAL); break; @@ -196,28 +205,6 @@ newgame: } } -win: g.o = GAME_WON; goto endgame; -lose: g.o = GAME_LOST; goto endgame; -endgame: - timer_setup(0); /* stop timer */ - show_minefield (SHOWMINES); - int gotaction; - do { - unsigned char mouse[3]; - gotaction = getch(mouse); - if (gotaction==CTRSEQ_MOUSE_LEFT && clicked_emoticon(mouse)) { - free_field (); - goto newgame; - } else if (gotaction == 'r') { - free_field (); - goto newgame; - } else if (gotaction == 'q') { - goto quit; - } - } while (1); - -quit: - return 0; } void quit (void) { @@ -612,6 +599,29 @@ compatible with the ncurses implementation of same name */ return action; } +int getch_wrapper (void) { + unsigned char mouse[3]; + int c = getch(mouse); + + if (c == CTRSEQ_MOUSE_LEFT || c == CTRSEQ_MOUSE_RIGHT) { + if (clicked_emoticon(mouse)) + return WRAPPER_EMOTICON; + + if (screen2field_c (mouse[1]) < 0 + || screen2field_c (mouse[1]) >= f.w + || screen2field_l (mouse[2]) < 0 + || screen2field_l (mouse[2]) >= f.h) + return CTRSEQ_INVALID; + + g.p[0] = screen2field_l (mouse[2]); + g.p[1] = screen2field_c (mouse[1]); + + return c; /* CTRSEQ_MOUSE_LEFT || CTRSEQ_MOUSE_RIGHT */ + } + + return c; +} + int parse_fieldspec(char* str) { /* parses the FIELDSPEC (WxHxM); returns 1 on error */ int n = sscanf (str, "%dx%dx%d", &f.w, &f.h, &f.m); diff --git a/mines.h b/mines.h index 036b073..5696c57 100644 --- a/mines.h +++ b/mines.h @@ -47,6 +47,10 @@ struct game { int o; /* mode */ int n; /* new game? */ int c; /* cheat mode? */ + struct line_col { + int l; + int c; + } m[26]; /* markers, a-z */ }; struct opt { @@ -54,16 +58,13 @@ struct opt { int mode; /* allow flags? quesm? */ }; -struct line_col { - int l; - int c; -}; - +int minesviiper(void); void fill_minefield (int, int); void move_ph (int, int); void move_hi (int, int); void to_next_boundary (int, int, char); int getch (unsigned char*); +int getch_wrapper (void); int getctrlseq (unsigned char*); int everything_opened (void); int wait_mouse_up (int, int); @@ -110,6 +111,7 @@ enum game_states { GAME_INPROGRESS, GAME_WON, GAME_LOST, + GAME_QUIT, }; enum space_modes { MODE_OPEN = 0, /* expected zero while resetting `g' */ @@ -130,6 +132,8 @@ enum event { CTRSEQ_CURSOR_DOWN = -8, CTRSEQ_CURSOR_UP = -9, CTRSEQ_CURSOR_RIGHT = -10, + /* for getch_wrapper() */ + WRAPPER_EMOTICON = -11, }; enum mine_types { NO_MINE, -- 2.39.3