# include # include # include int main ( int argc, char *argv[] ); int duel_result ( double a_accuracy, double b_accuracy ); double random_double ( ); void timestamp ( ); /******************************************************************************/ int main ( int argc, char *argv[] ) /******************************************************************************/ /* Purpose: DUEL_SIMULATION simulates a duel. Discussion: Player 1 fires at player 2, and hits with a probability of P(1). If Player 2 misses, then Player 2 fires at Player 1, hitting with a probability of P(2). The duel continues with alternating shots until only one player survives. The simulation is intended to estimate the probabilities that a player will survive, and the number of turns required. The exact probability that player 1 will survive is P(1) / ( P(1) + P(2) - P(1) * P(2) ) Player 2's chance is P(2) * ( 1 - P(1) ) / ( P(1) + P(2) - P(1) * P(2) ) Licensing: This code is distributed under the MIT license. Modified: 04 September 2012 Author: John Burkardt Reference: Paul Nahin, Duelling Idiots and Other Probability Puzzlers, Princeton University Press, 2000, ISBN13: 978-0691009797, LC: QA273.N29. Martin Shubik, "Does the Fittest Necessarily Survive?", in Readings in Game Theory and Political Behavior, edited by Martin Shubik, Doubleday, 1954, LC: H61.S53. Parameters: Input, double A_ACCURACY, B_ACCURACY, the probabilities that players A and B will hit their opponent in a single shot. Input, int DUEL_NUM, the number of duels to run. Output, double A_PROB, B_PROB, the estimated probablities that players A and B will survive. Output, double TURN_AVERAGE, the average number of turns required to complete the duel. */ { double a_accuracy; double a_prob; int a_wins; double b_accuracy; double b_prob; int b_wins; int duel; int duel_num; int seed; int winner; timestamp ( ); printf ( "\n" ); printf ( "DUEL_SIMULATION:\n" ); printf ( " C version\n" ); if ( 1 < argc ) { duel_num = atoi ( argv[1] ); } else { printf ( "Enter number of duels to run: " ); scanf ( "%d", &duel_num ); } if ( 2 < argc ) { a_accuracy = atof ( argv[2] ); } else { printf ( "Enter player A's accuracy between 0.0 and 1.0: " ); scanf ( "%lf", &a_accuracy ); } if ( 3 < argc ) { b_accuracy = atof ( argv[3] ); } else { printf ( "Enter player B's accuracy between 0.0 and 1.0: " ); scanf ( "%lf", &b_accuracy ); } /* Initialize the random number generator. */ seed = time ( 0 ); srand ( seed ); /* Simulate the duels, and count the wins. */ a_wins = 0; b_wins = 0; for ( duel = 1; duel <= duel_num; duel++ ) { winner = duel_result ( a_accuracy, b_accuracy ); if ( winner == 1 ) { a_wins = a_wins + 1; } else { b_wins = b_wins + 1; } } /* Report the results. */ a_prob = ( double ) a_wins / ( double ) duel_num; b_prob = ( double ) b_wins / ( double ) duel_num; printf ( "\n" ); printf ( " Player A wins with probability %g\n", a_prob ); printf ( " Player B wins with probability %g\n", b_prob ); /* Terminate. */ printf ( "\n" ); printf ( "DUEL_SIMULATION:\n" ); printf ( " Normal end of execution\n" ); timestamp ( ); return 0; } /******************************************************************************/ int duel_result ( double a_accuracy, double b_accuracy ) /******************************************************************************/ /* Purpose: DUEL_RESULT returns the outcome of a single duel. Licensing: This code is distributed under the MIT license. Modified: 17 September 2012 Author: John Burkardt Reference: Martin Shubik, “Does the Fittest Necessarily Survive?”, in Readings in Game Theory and Political Behavior, edited by Martin Shubik, Doubleday, 1954, LC: H61.S53. Parameters: Input, double A_ACCURACY, B_ACCURACY, the probabilities that player A and B will hit their opponent in a single shot. Output, int DUEL_RESULT, the survivor of the duel. */ { double r; int winner; while ( 1 ) { r = random_double ( ); if ( r <= a_accuracy ) { winner = 1; break; } r = random_double ( ); if ( r <= b_accuracy ) { winner = 2; break; } } return winner; } /******************************************************************************/ double random_double ( ) /******************************************************************************/ /* Purpose: RANDOM_DOUBLE returns a random number between 0 and 1. Licensing: This code is distributed under the MIT license. Modified: 08 November 2009 Author: John Burkardt Parameters: Output, double RANDOM_DOUBLE, the random value. */ { double r; r = ( double ) rand ( ) / ( double ) RAND_MAX; return r; } /******************************************************************************/ void timestamp ( ) /******************************************************************************/ /* Purpose: TIMESTAMP prints the current YMDHMS date as a time stamp. Example: 17 June 2014 09:45:54 AM Licensing: This code is distributed under the MIT license. Modified: 17 June 2014 Author: John Burkardt Parameters: None */ { # define TIME_SIZE 40 static char time_buffer[TIME_SIZE]; const struct tm *tm; time_t now; now = time ( NULL ); tm = localtime ( &now ); strftime ( time_buffer, TIME_SIZE, "%d %B %Y %I:%M:%S %p", tm ); printf ( "%s\n", time_buffer ); return; # undef TIME_SIZE }