aher

Chainmail post melee morale probabilities for 6 LF vs 6 LF

Mar 5th, 2013
155
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 3.20 KB | None | 0 0
  1. #!/usr/bin/perl
  2. # Chainmail post melee morale probabilities for 6 LF vs 6 LF
  3.  
  4. sub nFactorial { # Factorial n!
  5.     my $n=shift;
  6.     my $product = 1;
  7.     while($n>0) {
  8.         $product *= $n--;
  9.     }
  10.     $product;
  11. }
  12.  
  13. sub nCr { # Combinations of n out of r
  14.     my ($n,$r) = @_;
  15.     int nFactorial($n) / int nFactorial($r) * int nFactorial($n-$r);
  16. }
  17.  
  18. # Probability of 6 LF scoring n kills against 6 LF, n in 0..6
  19. sub prob {
  20.     my ($n) = @_;
  21.     nCr(6,$n) * (1/6)**$n * (5/6)**(6-$n);
  22. }
  23.  
  24. foreach $lA (1..6) {
  25.   foreach $lB (1..6) {
  26.     foreach $m (1..6) { # Morale die
  27.       # Step 1: Compute fewer casualties
  28.       $dA = 6 - $lA; # A's casualties
  29.       $dB = 6 - $lB; # B's casualties
  30.       $p = (prob($dA) * prob($dB))/6; # Probability of this outcome
  31.       if( $dA < $dB ) {
  32.         $r1A = $m * ($dB - $dA);
  33.         $r1B = 0;
  34.       } elsif( $dB < $dA ) {
  35.         $r1B = $m * ($dA - $dB);
  36.         $r1A = 0;
  37.       } else { # $dA == $dB
  38.         $r1A = 0;
  39.         $r1B = 0;
  40.       }
  41.       # Step 2: Compute greater survivors
  42.       if( $lA > $lB ) {
  43.         $r2A = $lA - $lB;
  44.         $r2B = 0;
  45.       } elsif( $lB > $lA ) {
  46.         $r2B = $lB - $lA;
  47.         $r2A = 0;
  48.       } else { # $lA == $lB
  49.         $r2A = 0;
  50.         $r2B = 0;
  51.       }
  52.       # Step 3: Surviving figures
  53.       $r3A = 4*$lA;
  54.       $r3B = 4*$lB;
  55.       # Step 4: Morale scores
  56.       $sA = $r1A + $r2A + $r3A;
  57.       $sB = $r1B + $r2B + $r3B;
  58.       # Difference
  59.       $d = abs($sA - $sB);
  60.       # Double difference because no. figures per side < 20
  61.       $d *= 2;
  62.       $prob{$d} += $p;
  63.     }
  64.   }
  65. }
  66.  
  67. foreach $d (sort {$a <=> $b} (keys %prob)) {
  68.   #print $d, " ", $prob{$d}, "\n";
  69.   if( $d >= 0 && $d <= 19 ) {
  70.     $meleecontinues += $prob{$d};
  71.   } elsif($d >= 20 && $d <= 39) {
  72.     $backhalfgoodorder += $prob{$d};
  73.   } elsif($d >= 40 && $d <= 59) {
  74.     $backonegoodorder += $prob{$d};
  75.   } elsif($d >= 60 && $d <= 79) {
  76.     $retreatonemove += $prob{$d};
  77.   } elsif($d >= 80 && $d <= 99) {
  78.     $routoneandhalfmove += $prob{$d};
  79.   } else { # $d >= 100
  80.     $surrender += $prob{$d};
  81.   }
  82.   $total += $prob{$d};
  83. }
  84.  
  85. # 13 special cases where we do not need to check post melee morale
  86. # Probability A wipes out B
  87. for $dA (0..5) { $p0Bs += prob($dA) * prob(6); }
  88. # Probability B wipes out A
  89. for $dB (0..5) { $p0As += prob($dB) * prob(6); }
  90. # Probability A & B wipe out each other
  91. $p0 = prob(6) * prob(6);
  92. # Add these special cases to the total probability mass
  93. $total += $p0 + $p0As + $p0Bs;
  94.  
  95. print "Outcome:                           Probability\n";
  96. print "=======================================================\n";
  97. print "A and B wipe out each other:       ", $p0, "\n";
  98. print "A wipes out B:                     ", $p0Bs, "\n";
  99. print "B wipes out A:                     ", $p0As, "\n";
  100. print "Melee continues            (0-19): ", $meleecontinues, "\n";
  101. print "Back 1/2 move, good order (20-39): ", $backhalfgoodorder, "\n";
  102. print "Back 1 move, good order   (40-59): ", $backonegoodorder, "\n";
  103. print "Retreat 1 move            (60-79): ", $retreatonemove, "\n";
  104. print "Rout 1 1/2 move           (80-99): ", $routoneandhalfmove, "\n";
  105. print "Surrender                  (100+): ", $surrender, "\n";
  106. print "Total:                             ", $total, "\n";
Advertisement
Add Comment
Please, Sign In to add comment