diff --git a/src/exch.c b/src/exch.c index d426608..9535ff5 100644 --- a/src/exch.c +++ b/src/exch.c @@ -211,9 +211,6 @@ void exchange_stock (void) break; default: - if (abort_game) - return; - beep(); } } @@ -259,9 +256,6 @@ void visit_bank (void) char *buf; - if (abort_game) - return; - buf = malloc(BUFSIZE); if (buf == NULL) { err_exit_nomem(); @@ -334,9 +328,6 @@ void visit_bank (void) break; default: - if (abort_game) - return; - beep(); } } @@ -491,9 +482,6 @@ void trade_shares (int num, bool *bid_used) char *buf; - if (abort_game) - return; - assert(num >= 0 && num < MAX_COMPANIES); assert(company[num].on_map); @@ -593,9 +581,6 @@ void trade_shares (int num, bool *bid_used) break; default: - if (abort_game) - return; - beep(); } } diff --git a/src/game.c b/src/game.c index 18a6837..3e13573 100644 --- a/src/game.c +++ b/src/game.c @@ -126,9 +126,6 @@ void init_game (void) while (number_players == 0) { int choice = ask_number_players(); - if (abort_game) - return; - if (choice == ERR) { abort_game = true; return; @@ -136,9 +133,6 @@ void init_game (void) } else if (choice == 0) { choice = ask_game_number(); - if (abort_game) - return; - if (choice != ERR) { game_num = choice; @@ -168,9 +162,6 @@ void init_game (void) ask_player_names(); - if (abort_game) - return; - deltxwin(); // "Number of players" window txrefresh(); @@ -230,6 +221,7 @@ void init_game (void) } quit_selected = false; + abort_game = false; } @@ -285,9 +277,6 @@ static int ask_number_players (void) break; default: - if (abort_game) - return ERR; - beep(); } } @@ -344,9 +333,6 @@ int ask_game_number (void) break; default: - if (abort_game) - return ERR; - beep(); } } @@ -362,9 +348,6 @@ int ask_game_number (void) void ask_player_names (void) { - if (abort_game) - return; - if (number_players == 1) { // Ask for the player's name @@ -379,9 +362,6 @@ void ask_player_names (void) while (true) { int ret = gettxstr(curwin, &player[0].name, NULL, false, 2, x, w, attr_input_field); - if (abort_game) - return; - if (ret == OK && strlen(player[0].name) != 0) { break; } else { @@ -391,7 +371,7 @@ void ask_player_names (void) newtxwin(5, 44, 6, WCENTER, true, attr_normal_window); mvwaddstr(curwin, 2, 2, "Do you need any instructions?"); - if (answer_yesno(curwin, attr_keycode) == true) { + if (answer_yesno(curwin, attr_keycode)) { show_help(); } @@ -452,9 +432,6 @@ void ask_player_names (void) break; case ERR: - if (abort_game) - return; - beep(); break; @@ -491,7 +468,7 @@ void ask_player_names (void) newtxwin(5, 50, 6, WCENTER, true, attr_normal_window); mvwaddstr(curwin, 2, 2, "Does any player need instructions?"); - if (answer_yesno(curwin, attr_keycode) == true) { + if (answer_yesno(curwin, attr_keycode)) { show_help(); } } @@ -510,8 +487,10 @@ void end_game (void) char *buf; - if (abort_game) + if (abort_game) { + // init_game() was cancelled by user return; + } buf = malloc(BUFSIZE); if (buf == NULL) { @@ -531,9 +510,6 @@ void end_game (void) show_status(i); } - if (abort_game) - return; - if (number_players == 1) { l_strfmon(buf, BUFSIZE, "%1n", total_value(0)); @@ -595,9 +571,6 @@ void show_map (bool closewin) int n, x, y; - if (abort_game) - return; - newtxwin(MAX_Y + 4, WIN_COLS, 1, WCENTER, true, attr_map_window); // Draw various borders @@ -697,9 +670,6 @@ void show_status (int num) int i, line; - if (abort_game) - return; - assert(num >= 0 && num < number_players); newtxwin(MAX_COMPANIES + 15, WIN_COLS, 1, WCENTER, true, diff --git a/src/globals.c b/src/globals.c index af8e74e..3deab67 100644 --- a/src/globals.c +++ b/src/globals.c @@ -84,13 +84,12 @@ bool game_loaded = false; // True if game was loaded from disk int game_num = 0; // Game number (1-9) bool quit_selected = false; // Is a player trying to quit the game? +bool abort_game = false; // Abort game without declaring winner? bool option_no_color = false; // True if --no-color was specified bool option_dont_encrypt = false; // True if --dont-encrypt was specified int option_max_turn = 0; // Max. turns if --max-turn was specified -volatile sig_atomic_t abort_game = false; // Abort game as quickly as possible? - /***********************************************************************/ // End of file diff --git a/src/globals.h b/src/globals.h index 135a717..db19be3 100644 --- a/src/globals.h +++ b/src/globals.h @@ -33,7 +33,6 @@ #include -#include /************************************************************************ @@ -196,12 +195,11 @@ extern bool game_loaded; // True if game was loaded from disk extern int game_num; // Game number (1-9) extern bool quit_selected; // Is a player trying to quit the game? +extern bool abort_game; // Abort game without declaring winner? extern bool option_no_color; // True if --no-color was specified extern bool option_dont_encrypt; // True if --dont-encrypt was specified extern int option_max_turn; // Max. turns if --max-turn was specified -extern volatile sig_atomic_t abort_game; // Abort game as quickly as possible? - #endif /* included_GLOBALS_H */ diff --git a/src/help.c b/src/help.c index 938848c..4f9a520 100644 --- a/src/help.c +++ b/src/help.c @@ -162,9 +162,6 @@ void show_help (void) bool done = false; - if (abort_game) - return; - // Count how many pages appear in the help text for (numpages = 0; help_text[numpages] != NULL; numpages++) ; @@ -359,9 +356,6 @@ void show_help (void) break; default: - if (abort_game) - return; - curpage++; done = (curpage == numpages); } diff --git a/src/intf.c b/src/intf.c index a486ab5..461587c 100644 --- a/src/intf.c +++ b/src/intf.c @@ -112,8 +112,9 @@ static void init_title (void); Parameters: sig - Signal number Returns: (nothing) - This function handles termination signals (like SIGINT and SIGTERM) by - setting the global variable abort_game to true. + This function handles termination signals (like SIGINT, SIGTERM and + SIGQUIT) by clearing the screen, uninstalling itself and reraising the + signal. */ static void sigterm_handler (int sig); @@ -163,6 +164,9 @@ void init_screen (void) if (sigaction(SIGTERM, &sa, NULL) == -1) { errno_exit("sigaction(SIGTERM)"); } + if (sigaction(SIGQUIT, &sa, NULL) == -1) { + errno_exit("sigaction(SIGQUIT)"); + } // Initialise the screen initscr(); @@ -312,13 +316,26 @@ void init_title (void) void sigterm_handler (int sig) { - /* Note that sigterm_handler() simply sets a volatile variable - instead of directly terminating, as functions like endwin() and - end_screen() are NOT reentrant. A side-effect of doing this, - however, is that the main program needs to have abort_game checks - scattered all over it. */ + struct sigaction sa; - abort_game = true; + + /* The following Curses functions are NOT async-signal-safe (ie, are + not reentrant) as they may well call malloc() or free(). However, + it does allow us to terminate with the correct signal without + having convoluted code in the main program. */ + + curs_set(CURS_ON); + clear(); + refresh(); + endwin(); + + // Reraise the same signal, using the system-default handler + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = SIG_DFL; + + sigaction(sig, &sa, NULL); + raise(sig); } @@ -705,10 +722,8 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, key = wgetch(win); if (key == ERR) { - if (abort_game) { - ret = ERR; - done = true; - } + // Do nothing on ERR + ; } else if ((key == KEY_DEFAULTVAL1 || key == KEY_DEFAULTVAL2) && defaultval != NULL && len == 0) { // Initialise buffer with the default value @@ -1512,7 +1527,7 @@ int gettxlong (WINDOW *win, long int *restrict result, long int min, /***********************************************************************/ // answer_yesno: Wait for a Yes/No answer -int answer_yesno (WINDOW *win, chtype attr_keys) +bool answer_yesno (WINDOW *win, chtype attr_keys) { int key; bool done; @@ -1539,8 +1554,6 @@ int answer_yesno (WINDOW *win, chtype attr_keys) if (key == 'Y' || key == 'N') { done = true; - } else if (abort_game) { - return ERR; } else { beep(); } diff --git a/src/intf.h b/src/intf.h index 2887925..6301c2a 100644 --- a/src/intf.h +++ b/src/intf.h @@ -534,17 +534,16 @@ extern int gettxlong (WINDOW *win, long int *restrict result, long int min, Function: answer_yesno - Wait for a Yes/No answer Parameters: win - Window to use (should be curwin) attr_keys - Window rendition to use for key choices - Returns: int - 1 if Yes was selected, 0 if No, ERR if error + Returns: bool - True if Yes was selected, false if No This function prompts the user by printing " [Y/N] " using appropriate character renditions ("Y" and "N" in attr_keys, the rest in the current rendition), then waits for the user to press either "Y" (for Yes) or - "N" (for No) on the keyboard, then prints the answer using A_BOLD. If - "Y" was selected, 1 is returned, if "N", 0 is returned. ERR is - returned if abort_game becomes true. Note that the cursor becomes - invisible after calling this function. + "N" (for No) on the keyboard, then prints the answer using A_BOLD. + True is returned if "Y" was selected, false if "N". Note that the + cursor becomes invisible after calling this function. */ -extern int answer_yesno (WINDOW *win, chtype attr_keys); +extern bool answer_yesno (WINDOW *win, chtype attr_keys); /* diff --git a/src/move.c b/src/move.c index 8d41845..3db159b 100644 --- a/src/move.c +++ b/src/move.c @@ -159,9 +159,6 @@ void select_moves (void) bool unique; - if (abort_game) - return; - // How many empty spaces are there in the galaxy map? count = 0; for (x = 0; x < MAX_X; x++) { @@ -321,9 +318,6 @@ selection_t get_move (void) break; default: - if (abort_game) - return SEL_QUIT; - beep(); } } @@ -341,13 +335,10 @@ selection_t get_move (void) // Ask the player to confirm their choice mvwaddstr(curwin, 2, 22, "Are you sure?"); - if (answer_yesno(curwin, attr_keycode) != true) { + if (! answer_yesno(curwin, attr_keycode)) { selection = SEL_NONE; } - if (abort_game) - return SEL_QUIT; - // Save the game if required if (selection == SEL_SAVE) { bool saved = false; @@ -406,9 +397,6 @@ selection_t get_move (void) break; default: - if (abort_game) - return SEL_QUIT; - beep(); } } @@ -456,13 +444,12 @@ selection_t get_move (void) void process_move (selection_t selection) { - if (abort_game) - return; - if (selection == SEL_QUIT) { // The players want to end the game quit_selected = true; + } + if (quit_selected || abort_game) { deltxwin(); // "Select move" window deltxwin(); // Galaxy map window txrefresh(); @@ -508,9 +495,6 @@ void process_move (selection_t selection) assign_vals(x, y, left, right, up, down); } - if (abort_game) - return; - if (IS_MAP_COMPANY(left) && IS_MAP_COMPANY(up) && left != up) { galaxy_map[x][y] = left; @@ -518,9 +502,6 @@ void process_move (selection_t selection) assign_vals(x, y, left, right, up, down); } - if (abort_game) - return; - if (IS_MAP_COMPANY(left) && IS_MAP_COMPANY(down) && left != down) { galaxy_map[x][y] = left; @@ -528,9 +509,6 @@ void process_move (selection_t selection) assign_vals(x, y, left, right, up, down); } - if (abort_game) - return; - if (IS_MAP_COMPANY(right) && IS_MAP_COMPANY(up) && right != up) { galaxy_map[x][y] = right; @@ -538,9 +516,6 @@ void process_move (selection_t selection) assign_vals(x, y, left, right, up, down); } - if (abort_game) - return; - if (IS_MAP_COMPANY(right) && IS_MAP_COMPANY(down) && right != down) { galaxy_map[x][y] = right; @@ -548,9 +523,6 @@ void process_move (selection_t selection) assign_vals(x, y, left, right, up, down); } - if (abort_game) - return; - if (IS_MAP_COMPANY(up) && IS_MAP_COMPANY(down) && up != down) { galaxy_map[x][y] = up; @@ -559,9 +531,6 @@ void process_move (selection_t selection) } } - if (abort_game) - return; - // See if an existing company can be expanded nearby = (IS_MAP_COMPANY(left) ? left : (IS_MAP_COMPANY(right) ? right : @@ -627,9 +596,6 @@ void next_player (void) bool all_out; - if (abort_game) - return; - all_out = true; for (i = 0; i < number_players; i++) { if (player[i].in_game) { @@ -670,9 +636,6 @@ void bankrupt_player (bool forced) int i; - if (abort_game) - return; - /* It would be nice if we had functions that would do word-wrapping for us automatically! */ @@ -827,9 +790,6 @@ void merge_companies (map_val_t a, map_val_t b) char *buf; - if (abort_game) - return; - buf = malloc(BUFSIZE); if (buf == NULL) { err_exit_nomem(); @@ -992,9 +952,6 @@ void adjust_values (void) int which; - if (abort_game) - return; - // Declare a company bankrupt! if (randf() > (1.0 - COMPANY_BANKRUPTCY)) { which = randi(MAX_COMPANIES); @@ -1128,9 +1085,6 @@ void adjust_values (void) interest_rate /= randf() + INTEREST_RATE_DIVIDER; } - if (abort_game) - return; - // Calculate current player's debt player[current_player].debt *= interest_rate + 1.0; diff --git a/src/trader.c b/src/trader.c index 8ccc6e8..b47dda6 100644 --- a/src/trader.c +++ b/src/trader.c @@ -180,7 +180,7 @@ int main (int argc, char *argv[]) // Finish up... end_program(); - return abort_game ? EXIT_FAILURE : EXIT_SUCCESS; + return EXIT_SUCCESS; }