program main !*****************************************************************************80 ! !! 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: ! ! 17 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, real ( kind = rk ) A_ACCURACY, B_ACCURACY, the probabilities that ! players A and B will hit their opponent in a single shot. ! ! Input, integer DUEL_NUM, the number of duels to run. ! ! Output, real ( kind = rk ) A_PROB, B_PROB, the estimated probablities that ! players A and B will survive. ! ! Output, real ( kind = rk ) TURN_AVERAGE, the average number of turns ! required to complete the duel. ! implicit none integer, parameter :: rk = kind ( 1.0D+00 ) real ( kind = rk ) a_accuracy real ( kind = rk ) a_prob integer a_wins real ( kind = rk ) b_accuracy real ( kind = rk ) b_prob integer b_wins integer duel integer duel_num integer winner call timestamp ( ) write ( *, '(a)' ) '' write ( *, '(a)' ) 'DUEL_SIMULATION:' write ( *, '(a)' ) ' FORTRAN90 version' write ( *, '(a)' ) 'Enter number of duels to run:' read ( *, * ) duel_num write ( *, '(a)' ) 'Enter player A''s accuracy between 0.0 and 1.0:' read ( *, * ) a_accuracy write ( *, '(a)' ) 'Enter player B''s accuracy between 0.0 and 1.0:' read ( *, * ) b_accuracy a_wins = 0 b_wins = 0 do duel = 1, duel_num call duel_result ( a_accuracy, b_accuracy, winner ) if ( winner == 1 ) then a_wins = a_wins + 1 else b_wins = b_wins + 1 end if end do a_prob = real ( a_wins, kind = rk ) / real ( duel_num, kind = rk ) b_prob = real ( b_wins, kind = rk ) / real ( duel_num, kind = rk ) write ( *, '(a)' ) '' write ( *, '(a,g14.6)' ) ' Player A wins with probability ', a_prob write ( *, '(a,g14.6)' ) ' Player B wins with probability ', b_prob ! ! Terminate. ! write ( *, '(a)' ) '' write ( *, '(a)' ) 'duel_simulation()gg:' write ( *, '(a)' ) ' Normal end of execution.' write ( *, '(a)' ) '' call timestamp ( ) stop end subroutine duel_result ( a_accuracy, b_accuracy, winner ) !*****************************************************************************80 ! !! DUEL_RESULT returns the outcome of a single duel. ! ! Licensing: ! ! This code is distributed under the MIT license. ! ! Modified: ! ! 04 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, real ( kind = rk ) A_ACCURACY, B_ACCURACY, the probabilities that ! player A and B will hit their opponent in a single shot. ! ! Output, integer WINNER, the survivor of the duel. ! implicit none integer, parameter :: rk = kind ( 1.0D+00 ) real ( kind = rk ) a_accuracy real ( kind = rk ) b_accuracy real ( kind = rk ) r integer winner do call random_number ( harvest = r ) if ( r <= a_accuracy ) then winner = 1 exit end if call random_number ( harvest = r ) if ( r <= b_accuracy ) then winner = 2 exit end if end do return end subroutine timestamp ( ) !*****************************************************************************80 ! !! TIMESTAMP prints the current YMDHMS date as a time stamp. ! ! Example: ! ! 31 May 2001 9:45:54.872 AM ! ! Licensing: ! ! This code is distributed under the MIT license. ! ! Modified: ! ! 18 May 2013 ! ! Author: ! ! John Burkardt ! implicit none character ( len = 8 ) ampm integer d integer h integer m integer mm character ( len = 9 ), parameter, dimension(12) :: month = (/ & 'January ', 'February ', 'March ', 'April ', & 'May ', 'June ', 'July ', 'August ', & 'September', 'October ', 'November ', 'December ' /) integer n integer s integer values(8) integer y call date_and_time ( values = values ) y = values(1) m = values(2) d = values(3) h = values(5) n = values(6) s = values(7) mm = values(8) if ( h < 12 ) then ampm = 'AM' else if ( h == 12 ) then if ( n == 0 .and. s == 0 ) then ampm = 'Noon' else ampm = 'PM' end if else h = h - 12 if ( h < 12 ) then ampm = 'PM' else if ( h == 12 ) then if ( n == 0 .and. s == 0 ) then ampm = 'Midnight' else ampm = 'AM' end if end if end if write ( *, '(i2,1x,a,1x,i4,2x,i2,a1,i2.2,a1,i2.2,a1,i3.3,1x,a)' ) & d, trim ( month(m) ), y, h, ':', n, ':', s, '.', mm, trim ( ampm ) return end