## Problem 20 of Monte Carlo solutions to Fifty Challenging Problems...

(This is another part of the Fifty Problems series, a set of example applications of Monte Carlo methods. In each post, I present source code which answers a probabilistic question using simulated models of the underlying system.)

Problem 20: in a stepwise, three cornered duel between Adam, Bryan, and Costello, what should Adam's strategy be? Adam shoots first, then Bryan, then Costello, then Adam, and so on, until only one stands. The probability of Adam hitting his target is 0.3, Bryan is a perfect shot, and C is 50/50.

Note that the code below doesn't actually answer the question the same way as Mosteller. He admits a possibility our code below doesn't, which, personally, I feel is a breach of honor in such an esteemed tradition as settling arguments by the well-reasoned method of shooting at each other.

```#!/usr/bin/env ruby # I don't like the answer in the book here; # code of honor is rough. class Duel P_A = 0.3 P_B = 1.0 P_C = 0.5 def initialize() @a_live = true @b_live = true @c_live = true @a_moves = [] end attr_reader :a_moves def over?() !@a_live || !(@b_live || @c_live) end def a_live?() return @a_live end def run_round(moves) @a_moves.push(moves[0]) if rand() < P_A if moves[0] == 0 && @b_live @b_live = false else @c_live = false end end if @b_live && rand() < P_B if moves[1] == 0 || !@c_live @a_live = false else @c_live = false end end if @c_live && rand() < P_C if moves[1] == 0 && @b_live @b_live = false else @a_live = false end end end end move_space = [] 8.times { |move_mask| move_a = move_mask & 1 == 0 ? 1 : 0 move_b = move_mask & 2 == 0 ? 1 : 0 move_c = move_mask & 4 == 0 ? 1 : 0 move_space.push( [move_a, move_b, move_c] ) } a_lives = Hash.new { |h,k| h[k] = 0 } a_attempts = Hash.new { |h,k| h[k] = 0 } two_move_space = [] al1 = [0,0] aa1 = [0,0] move_space.each { |m1| a1 = m1[0] move_space.each { |m2| 100.times { d = Duel.new d.run_round(m1) d.run_round(m2) while (!d.over?) d.run_round(m2) # doesn't matter, we only have c left if we're still in the game end aa1[a1] += 1 al1[a1] += 1 if d.a_live? a_lives[ d.a_moves ] += 1 if d.a_live? a_attempts[ d.a_moves ] += 1 } } } puts a_lives.inspect puts a_attempts.inspect lives = [0,0] attempts = [0,0] a_lives.each { |k,v| first_move = k[0] att = a_attempts[k] lives[first_move] += v attempts[first_move] += att } puts lives.inspect puts attempts.inspect puts puts aa1.inspect puts al1.inspect puts [ al1[0]/aa1[0].to_f, al1[1]/aa1[1].to_f ].inspect ```

I've been coding my way through Fifty Challenging Problems in Statistics with Solutions. This post is a part of the Fifty Challenging Problems series.

This was brought to you by Josh Myer. He has other fun things at his homepage.