Question: Your task is to modify sig_tic_tac_toe.cc to allow 2 players to play the game from different terminals. The usage model is sig_tic_tac_toe X or sig_tic_tac_toe
Your task is to modify sig_tic_tac_toe.cc to allow 2 players to play the game from different terminals. The usage model is sig_tic_tac_toe X or sig_tic_tac_toe O, where [X|O] identifies the player. The application starts by writing its PID to a file xmove.txt (player X) or omove.txt (player O), then it tries to open the opponents file to read the opponents PID. It will be using the opponents PID to send SIGUSR1 signals to the opponents application notifying it that its now its turn. Use the following steps as guideline:
1- Include a game instance in the application.
2- Use the signal notification to set a global flag (e.g. opponent_done) to true.
3- Use the convert2string() function to convert the game state to a string to write in file
4- Use the set_game_state(char *state) to update the game state from the received message
5- player X will start, player O is going to wait turn value will depend on the player
6- If the players turn: get the player move, update the game, and write the move to the other player in xmove.txt (player X) or omove.txt (player O), close the file. Check if the game has ended, otherwise increment the turn, goto 7.
7- If not the players turn: wait for signal (e.g. sleep(1) while opponent not done), read the opponents updated game state from xmove.txt (player O) or omove.txt (player X), close the file, set the game state accordingly, display the updated game, and check if the game has ended. If the game did not end increment the game turn and goto 6
. 8- A working program will allow two players to use different terminals to play the game and communicating the game movements across applications
sig_tic_tac_toe.cc
#include
#include "tic_tac_toe.h"
void handle_signal(int signal); void handle_sigalrm(int signal); void do_sleep(int seconds);
/* Usage example * * First, compile and run this program: * $ gcc signal.c * $ ./a.out * * It will print out its pid. Use it from another terminal to send signals * $ kill -HUP
if (argc != 2) { printf ("Usage: sig_tic_tac_toe [X|O] "); return (-1); } player = argv[1][0]; if (player != 'X' && player != 'O') { printf ("Usage: player names must be either X or Y"); return (-2); } if (player == 'X') { my_filename = x_file_name; oponent_filename = o_file_name; } else { my_filename = o_file_name; oponent_filename = x_file_name; }
// Print pid, so that we can send signals from other shells my_pid = getpid(); printf("My pid is: %d ", my_pid); outFile = fopen (my_filename, "w"); fprintf (outFile, "%d", my_pid); fclose(outFile); printf ("trying to open input file: ."); do { sleep(1); inFile = fopen (oponent_filename, "r"); printf ("."); } while (inFile == NULL); fgets( buffer1, 128, inFile ); oponent_pid = atoi (buffer1); printf (" done. oponent_pid %d ", oponent_pid); fclose(inFile);
// Setup the sighub handler sa.sa_handler = &handle_signal;
// Restart the system call, if at all possible sa.sa_flags = SA_RESTART;
// Block every signal during the handler sigfillset(&sa.sa_mask);
// Intercept SIGUSR1 and SIGINT if (sigaction(SIGUSR1, &sa, NULL) == -1) { perror("Error: cannot handle SIGUSR1"); // Should not happen }
// Will always fail, SIGKILL is intended to force kill your process // if (sigaction(SIGKILL, &sa, NULL) == -1) { // perror("Cannot handle SIGKILL"); // Will always happen // printf("You can never handle SIGKILL anyway... "); // }
if (sigaction(SIGINT, &sa, NULL) == -1) { perror("Error: cannot handle SIGINT"); // Should not happen }
// for (;;) { // printf(" Sleeping for ~3 seconds "); // sleep(3); // Later to be replaced with a SIGALRM // }
remove (oponent_filename); // need to remove file for next time we run the game }
void handle_signal(int signal) { sigset_t pending;
if (signal == SIGUSR1){ printf ("received SIGUSR1 signal "); } else if (signal == SIGINT) exit(0); // CTRL C exit else return;
printf("Done handling SIGUSR1 "); }
signal.cc
#include
void handle_signal(int signal); void handle_sigalrm(int signal); void do_sleep(int seconds);
/* Usage example * * First, compile and run this program: * $ gcc signal.c * $ ./a.out * * It will print out its pid. Use it from another terminal to send signals * $ kill -HUP
// Print pid, so that we can send signals from other shells printf("My pid is: %d ", getpid());
// Setup the sighub handler sa.sa_handler = &handle_signal;
// Restart the system call, if at all possible sa.sa_flags = SA_RESTART;
// Block every signal during the handler sigfillset(&sa.sa_mask);
// Intercept SIGUSR1 and SIGINT if (sigaction(SIGUSR1, &sa, NULL) == -1) { perror("Error: cannot handle SIGUSR1"); // Should not happen }
// Will always fail, SIGKILL is intended to force kill your process if (sigaction(SIGKILL, &sa, NULL) == -1) { perror("Cannot handle SIGKILL"); // Will always happen printf("You can never handle SIGKILL anyway... "); }
if (sigaction(SIGINT, &sa, NULL) == -1) { perror("Error: cannot handle SIGINT"); // Should not happen }
for (;;) { printf(" Sleeping for ~3 seconds "); sleep(3); // Later to be replaced with a SIGALRM } }
void handle_signal(int signal) { sigset_t pending;
if (signal == SIGUSR1){ printf ("received SIGUSR1 signal "); } else if (signal == SIGINT) exit(0); // CTRL C exit else return;
printf("Done handling SIGUSR1 "); }
Step by Step Solution
There are 3 Steps involved in it
Get step-by-step solutions from verified subject matter experts
