/* run a match of numHands hands of the supplied game cards are dealt using rng, error conditions like timeouts are controlled and stored in errorInfo actions are read/sent to seat p on seatFD[ p ] if quiet is not zero, only print out errors, warnings, and final value if logFile is not NULL, print out a single line for each completed match with the final state and all player values. The values are printed in player, not seat order. if transactionFile is not NULL, a transaction log of actions made is written to the file, and if there is any input left to read on the stream when gameLoop is called, it will be processed to initialise the state returns >=0 if the match finished correctly, -1 on error */ static int gameLoop( const Game *game, char *seatName[ MAX_PLAYERS ], const uint32_t numHands, const int quiet, const int fixedSeats, rng_state_t *rng, ErrorInfo *errorInfo, const int seatFD[ MAX_PLAYERS ], ReadBuf *readBuf[ MAX_PLAYERS ], FILE *logFile, FILE *transactionFile ) { uint32_t handId; uint8_t seat, p, player0Seat, currentP, currentSeat; struct timeval t, sendTime, recvTime; Action action; MatchState state; double value[ MAX_PLAYERS ], totalValue[ MAX_PLAYERS ]; /* check version string for each player */ for( seat = 0; seat < game->numPlayers; ++seat ) { if( checkVersion( seat, readBuf[ seat ] ) < 0 ) { /* error messages already handled in function */ return -1; } } gettimeofday( &sendTime, NULL ); if( !quiet ) { fprintf( stderr, "STARTED at %zu.%06zu\n", sendTime.tv_sec, sendTime.tv_usec ); } /* start at the first hand */ handId = 0; if( checkErrorNewHand( game, errorInfo ) < 0 ) { fprintf( stderr, "ERROR: unexpected game\n" ); return -1; } initState( game, handId, &state.state ); dealCards( game, rng, &state.state ); for( seat = 0; seat < game->numPlayers; ++seat ) { totalValue[ seat ] = 0.0; } /* seat 0 is player 0 in first game */ player0Seat = 0; /* process the transaction file */ if( transactionFile != NULL ) { if( processTransactionFile( game, fixedSeats, &handId, &player0Seat, rng, errorInfo, totalValue, &state, transactionFile ) < 0 ) { /* error messages already handled in function */ return -1; } } if( handId >= numHands ) { goto finishedGameLoop; } /* play all the (remaining) hands */ while( 1 ) { /* play the hand */ while( !stateFinished( &state.state ) ) { /* find the current player */ currentP = currentPlayer( game, &state.state ); /* send state to each player */ for( seat = 0; seat < game->numPlayers; ++seat ) { state.viewingPlayer = seatToPlayer( game, player0Seat, seat ); if( sendPlayerMessage( game, &state, quiet, seat, seatFD[ seat ], &t ) < 0 ) { /* error messages already handled in function */ return -1; } /* remember the seat and send time if player is acting */ if( state.viewingPlayer == currentP ) { sendTime = t; } } /* get action from current player */ state.viewingPlayer = currentP; currentSeat = playerToSeat( game, player0Seat, currentP ); if( readPlayerResponse( game, &state, quiet, currentSeat, &sendTime, errorInfo, readBuf[ currentSeat ], &action, &recvTime ) < 0 ) { /* error messages already handled in function */ return -1; } /* log the transaction */ if( transactionFile != NULL ) { if( logTransaction( game, &state.state, &action, &sendTime, &recvTime, transactionFile ) < 0 ) { /* error messages already handled in function */ return -1; } } /* do the action */ doAction( game, &action, &state.state ); } /* get values */ for( p = 0; p < game->numPlayers; ++p ) { value[ p ] = valueOfState( game, &state.state, p ); totalValue[ playerToSeat( game, player0Seat, p ) ] += value[ p ]; } /* add the game to the log */ if( logFile != NULL ) { if( addToLogFile( game, &state.state, value, player0Seat, seatName, logFile ) < 0 ) { /* error messages already handled in function */ return -1; } } /* send final state to each player */ for( seat = 0; seat < game->numPlayers; ++seat ) { state.viewingPlayer = seatToPlayer( game, player0Seat, seat ); if( sendPlayerMessage( game, &state, quiet, seat, seatFD[ seat ], &t ) < 0 ) { /* error messages already handled in function */ return -1; } } if ( !quiet ) { if ( handId % 100 == 0) { for( seat = 0; seat < game->numPlayers; ++seat ) { fprintf(stderr, "Seconds cumulatively spent in match for seat %i: " "%i\n", seat, (int)(errorInfo->usedMatchMicros[ seat ] / 1000000)); } } } /* start a new hand */ if( setUpNewHand( game, fixedSeats, &handId, &player0Seat, rng, errorInfo, &state.state ) < 0 ) { /* error messages already handled in function */ return -1; } if( handId >= numHands ) { break; } } finishedGameLoop: /* print out the final values */ if( !quiet ) { gettimeofday( &t, NULL ); fprintf( stderr, "FINISHED at %zu.%06zu\n", sendTime.tv_sec, sendTime.tv_usec ); } if( printFinalMessage( game, seatName, totalValue, logFile ) < 0 ) { /* error messages already handled in function */ return -1; } return 0; }
int main(void) { // variable declaration int fd; pid_t pidRED, pidGRN, pidBLU, pidRead; // Create the named pipe mknod(PIPE_NAME, S_IFIFO | 0666, 0); // Opens the named pipe for both reading and writing fd = open(PIPE_NAME, O_RDWR | O_NDELAY ); // Child process that writes 'RED' to the pipe pidRED = fork(); if (pidRED == 0) { printf("Pid %d (red) started\n", getpid()); writeColours(fd, "RED"); // Write to the pipe exit(1); // ends the child process } // Child process that writes 'GRN' to the pipe pidGRN = fork(); if (pidGRN == 0) { printf("Pid %d (green) started\n", getpid()); writeColours(fd, "GRN"); // Writes to the pipe exit(1); // ends the child process } // Child process that writes 'BLU' to the pipe pidBLU = fork(); if (pidBLU == 0) { printf("Pid %d (blue) started\n", getpid()); writeColours(fd, "BLU"); // Writes to the pipe exit(1); // ends the child process } // Child process that reads the data from the pipe // and tallies up the totals pidRead = fork(); if (pidRead == 0) { // Variables to keep track of totals written by each process int nbrOfRed = 0, nbrOfGreen = 0, nbrOfBlue = 0; // Variable to hold the data read in from the pipe char data[4]; // Calculate the system time 5 seconds from now time_t endTime = time(0) + 5; // Runs loop for 5 seconds while(time(0) < endTime) { // Reads in the data from the pipe read(fd, &data, 4); // Determines which process wrote to the pipe // Increments the variable that's tallying the total if (!strcmp(data, "RED")) { nbrOfRed++; } else if (!strcmp(data, "GRN")) { nbrOfGreen++; } else if (!strcmp(data, "BLU")) { nbrOfBlue++; } // Determine how many seconds the process has left to run double oldDiff = difftime(endTime, time(0)); double newDiff; // The difference in how many seconds the process has left // Will change every 1 second // This is used as a measure to know when to print // Out the progress of the race while( newDiff != oldDiff && oldDiff != 0) { printProgress(nbrOfRed, nbrOfGreen, nbrOfBlue); newDiff = difftime(endTime, time(0)); break; } } // Close the pipe close(fd); // Print the final messages for each process printf("\n"); // line break printFinalMessage("red", nbrOfRed); printFinalMessage("green", nbrOfGreen); printFinalMessage("blue", nbrOfBlue); } return 0; }