#!/bin/perl -w

# Title: Prisoner's Dilemma Program
# Author: Wayne Snyder
# Date: 03/31/08

# Usage: pd.pl <file> 
# Infile format: 8 columns:     1 = Tricked;    2 = Helped
#    name
#    First move
#    Move if opponent tricked last time
#    Move if opponent helped last time
#    Move if opponent helped both of last two times
#    Move if opponent helped, then tricked
#    Move if opponent tricked, then helped
#    Move if opponent tricked both of last two times
#    score (added by this program, not in input file
     
$debug = 0; 

if($#ARGV < 0) { die "Error: Input file name needed on command line.\n"; }
open(INFILE, $ARGV[0]) || die "Error: Can not open $ARGV[0].\n";

$numrounds = 10;     # note, must be at least 2
$numgens = 100; 

# read input file

for( $i = 0; <INFILE>; $i++) {
   chomp; 

   for($j = 0; m/([a-zA-Z0-9]+)(.*)/; $j++) {
      $M[$i][$j] = $1; 
      $_ = $2; 
   }
   $M[$i][8] = 0;               # score      	
}


$numrows = $i; 


sub printround{
   # print each generation

   print "++++++++++++++++++++++++++++++++++\n"; 
 
   for($j = 0; $j<$numrows; $j++) {
      print $M[$j][8], "\t";
      for($k=0; $k<8; $k++) {
         print $M[$j][$k], "  ";
      }
      print "\n";  	
   }
   print "++++++++++++++++++++++++++++++++++\n"; 

}

&sort(); 

# exit(1); 



$T = 1;   $H = 2;

$payoff[1][1] = -10; 
$payoff[1][2] = 500; 
$payoff[2][1] = -100;
$payoff[2][2] = 300; 

$scoreA = $scoreB = $thisA = $thisB = $lastA = $lastB = $last2A = $last2B = 0;

for( $i = 0; $i < $numgens; $i++) {
   for($A = 0; $A < $numrows-1; $A++) {
      for($B = $A+1; $B < $numrows; $B++) {
	    if($debug == 1) {
               print "Game: ", $M[$A][0],"(",$A, ")", " vs. ", $M[$B][0],"(", $B, ")", "\n";

      print $M[$A][8], "\t";
      for($k=0; $k<8; $k++) {
         print $M[$A][$k], "  ";
      }
      print "\n";  	
      print $M[$B][8], "\t";
      for($k=0; $k<8; $k++) {
         print $M[$B][$k], "  ";
      }
      print "\n";  	
	   }
         
            # round 1
            $thisA = $M[$A][1];
            $thisB = $M[$B][1];
	    if($debug == 1) {
	    print "A's move: ", $thisA, "\n";
	    print "B's move: ", $thisB, "\n";
	}
            $scoreA = $payoff[$thisA][$thisB];
            $scoreB = $payoff[$thisB][$thisA];
            $M[$A][8] += $scoreA;
            $M[$B][8] += $scoreB;
            $lastA = $thisA;
            $lastB = $thisB;

	    if($debug == 1) {
              print "Round 0:\n"; 
	      &printround(); 
            }

            # round 2
            if($lastB eq $T) {
               $thisA = $M[$A][2];
            }
            else {
               $thisA = $M[$A][3];
            }
            if($lastA eq $T) {
               $thisB = $M[$B][2];
            }
            else {
               $thisB = $M[$B][3];
	    }
	 	    if($debug == 1) {
   print "A's move: ", $thisA, "\n";
	    print "B's move: ", $thisB, "\n";
}
            $scoreA = $payoff[$thisA][$thisB];
            $scoreB = $payoff[$thisB][$thisA];
            $M[$A][8] += $scoreA;
            $M[$B][8] += $scoreB;
            $last2A = $lastA;
            $last2B = $lastB; 
            $lastA = $thisA;
            $lastB = $thisB;


	    if($debug == 1) {
              print "Round 1:\n"; 
	      &printround(); 
            }

            # round 3 ... $numrounds
            for($r = 2; $r < $numrounds; $r++) {
               if($lastB eq $H && $last2B eq $H) {
                  $thisA = $M[$A][4];
               }
               elsif($lastB eq $T && $last2B eq $H) {
                  $thisA = $M[$A][5];
               }
               elsif($lastB eq $H && $last2B eq $T) {
                  $thisA = $M[$A][6];
               }
               elsif($lastB eq $T && $last2B eq $T) {
                  $thisA = $M[$A][7];
               }
               if($lastA eq $H && $last2A eq $H) {
                  $thisB = $M[$B][4];
               }
               elsif($lastA eq $T && $last2A eq $H) {
                  $thisB = $M[$B][5];
               }
               elsif($lastA eq $H && $last2A eq $T) {
                  $thisB = $M[$B][6];
               }
               elsif($lastA eq $T && $last2A eq $T) {
                  $thisB = $M[$B][7];
               }
		    if($debug == 1) {
    print "A's move: ", $thisA, "\n";
	    print "B's move: ", $thisB, "\n";
}
               $scoreA = $payoff[$thisA][$thisB];
               $scoreB = $payoff[$thisB][$thisA];
               $M[$A][8] += $scoreA;
               $M[$B][8] += $scoreB;
               $last2A = $lastA;
               $last2B = $lastB; 
               $lastA = $thisA;
               $lastB = $thisB;

	       if($debug == 1) {
                 print "Round ", $r, ":\n"; 
	         &printround(); 
               }

	    }
      }
   }



   # sort the list

   &sort(); 

   # print each generation

   print "==================================\n";
   print "Generation ", $i+1, "\n";
   print "==================================\n";
 
   for($j = 0; $j<$numrows; $j++) {
      print $M[$j][8], "\t";
      for($k=0; $k<8; $k++) {
         print $M[$j][$k], "  ";
      }
      print "\n";  	
   }
   print "==================================\n";

}


# just bubble sort for now....
sub sort {
    for($x = 0; $x < $numrows - 1; $x++) {
	for($y = $numrows - 2; $y >= $x; $y--) {
            if($M[$y][8] < $M[$y+1][8]) {
                for($z=0;$z<9; $z++) {
#		    print "exchanging ", $y, " and ", $y+1, "\n"; 
                    $temp = $M[$y][$z];
                    $M[$y][$z] = $M[$y+1][$z];
                    $M[$y+1][$z] = $temp; 
		}
	    }
	}
    }
}

