Fabrice E Iyolo

Turn coke into code


Prisoner's dilemma in Php

I have recently implemented the iterative Prisoners dilemma in PHP. This game, which will be explained in the next section, once implemented, we should also implement two strategies, tit for tats and another strategy to be chosen, then compete them against each other and analyze their performance. We’re starting by presenting the prisoner’s dilemma game, then explain our strategies, describe the technologies used and how we implemented them, then browse about the competition and explain the results.


Presentation of Prisoner’s dilemma

The prisoner’s dilemma is a canonical example of a game analyzed in game theory that shows why two individuals might not cooperate, even if it appears that it is in their best interests to do so.

You can find more about the prisoner's dilemma game here..

Strategies implemented

Two strategies compete against each other : Tit for tat versus Random strategy.

An agent using tit for tat strategy will first cooperate, then subsequently replicate an opponent’s previous action. If the opponent previously was cooperative, the agent is cooperative. If not, the agent is not.

Here is the implementation of tit for tat

class Tit_for_tat extends Prisoner_strategy implements Prisoner_strategy_interface
{
	public function decide()
	{
		if (count($this->opponent_choices) > 0)
			return end($this->opponent_choices);

		return 'c';
	}
}



An agent using Random strategy will choose to Cooperate or Defect in an equally probability of 0.5. So there are no rule, no way to anticipate or to learn its strategy. Its strategy is not based on the outcome or on the history.

Here is the implementation of randon

class Random extends Prisoner_strategy implements Prisoner_strategy_interface
{
	public function decide()
	{
		return mt_rand(1, 2) === 1 ? 'c' : 'd';
	}
}



As you might have noticed, these two strategies implements and the interface. Here are their implementations

interface Prisoner_strategy_interface
{
	public function decide();
	public function remember($round);
}

class Prisoner_strategy
{
	protected $opponent_choices = array();
	protected $opponent_scores = array();
	protected $my_choices = array();
	protected $my_scores = array();

	public function remember($round)
	{
		$this->opponent_choices[] = $round['opponent_choice'];
		$this->opponent_scores[] = $round['opponent_score'];
		$this->my_choices[] = $round['my_choice'];
		$this->my_scores[] = $round['my_score'];
	}
}


Implementations details

We implemented Prisoners dilemma with a PHP class Prisonersdilemma. This class takes the two strategies, compete them and compute he different outputs needed. We implemented each game in a different class. Each class for each game has a main method decide which decide the action for a given round according to the strategy’s properties.

The main method allow to the user to define a given number of rounds or to let the system define a random number between 100 and 10000. Once this number get, this page run the Prisoners dilemma class, which compete the two methods and each method calling its own class for picking a strategy corresponding to its properties according to the actual round (Defect for example for tits for tats in the first round). This main page get the results to the Prisoners dilemma class and display them, the summary of all the rounds, and a matrix for each round played underlining the outcome.

Here is the class prisonersdilemma

class Prisoners_dilemma
{



	// Each Strategy's % of total population
	private $strategies = array(

		// Nice Strategies
		'Tit_for_tat' => 6,
		'Random' => 8,
		
	);

	private $use_population = false;

	private $points_per_outcome = array(
		/* STRATEGIE1:STRATEGIE2 => YOUR POINTS
		C: Cooperate
		D: Defect
		*/
		'c:c' => 2,
		'c:d' => 0,
		'd:c' => 3,
		'd:d' => 1,
	);

	//Let's initiate values
	
	private $total_matches = array();
	private $total_points = array();
	private $avg_points_per_match = array();

	//Constructir
	function __construct()
	{
		$this->prepare_variables();
	}

	public function use_population()
	{
		$this->use_population = true;
	}

	public function run($matches, $rounds_per_match)
	{
		for ($i = 0; $i < $matches; $i++)
		$this->match($rounds_per_match);
  		$this->calculate_averages();
		$this->sort_data();

		$info = array();
		$info['avg_points_per_match'] = $this->avg_points_per_match;
		$info['total_matches'] = $this->total_matches;
		$info['total_points'] = $this->total_points;
		$info['matches'] = $matches;
		$info['rounds_per_match'] = $rounds_per_match;

		return $info;
	}

	// This method pick an action for each player according to their respective strategy. 
	private function match($rounds_per_match)
	{
		$strategy1 = $this->pick_Tit_for_tat();
		$strategy2 = $this->pick_Random();

		$opponent1 = new $strategy1();
		$opponent2 = new $strategy2();

		for ($i = 0; $i < $rounds_per_match; $i++)
		{
			$decision1 = $opponent1->decide();
			$decision2 = $opponent2->decide();
			$outcomegame = $decision1.":".$decision2;
            //echo "Decisions : ". $decision1."-".$decision2;
	
			$_SESSION['arrayvalues'][$i] = $this->display_game($outcomegame);
			
			list($score1, $score2) = $this->calculate_scores($decision1, $decision2);
			//echo "Score : ". $score1."-".$score2;
			$this->total_points[$strategy1] += $score1;
			$this->total_points[$strategy2] += $score2;

			$opponent1->remember(array(
				'opponent_choice' => $decision2,
				'opponent_score' => $score2,
				'my_choice' => $decision1,
				'my_score' => $score1,
			));

			$opponent2->remember(array(
				'opponent_choice' => $decision1,
				'opponent_score' => $score1,
				'my_choice' => $decision2,
				'my_score' => $score2,
			));
		}

		return array($score1, $score2);
	}
	// This method displays the outcome of the game in a form of a matrix
private function display_game($outcome) {
		
if($outcome == 'c:c') {
$display = "<table width='100' border='0' cellspacing='0' cellpadding='6' style='border:solid 1px #000000;'><tr><td width='50%' bgcolor='#666666' style='color:#FFFFFF;border-right:solid 1px #000000;'>2&nbsp;&nbsp;2</td><td width='50%' style='border-bottom:solid 1px #000000;'>0&nbsp;&nbsp;3</td></tr><tr><td width='50%' style='border-top:solid 1px #000000;'>3&nbsp;&nbsp;0</td><td width='50%' style='border-left:solid 1px #000000;'>1&nbsp;&nbsp;1</td></tr></table>";
		}
		elseif($outcome == 'c:d') {
$display = "<table width='100' border='0' cellspacing='0' cellpadding='6' style='border:solid 1px #000000;'><tr><td width='50%' style='border-right:solid 1px #000000;' >2&nbsp;&nbsp;2</td><td width='50%' bgcolor='#666666' style='color:#FFFFFF;border-bottom:solid 1px #000000;'>0&nbsp;&nbsp;3</td></tr><tr><td width='50%'  style='border-top:solid 1px #000000;'>3&nbsp;&nbsp;0</td><td width='50%' style='border-left:solid 1px #000000;'>1&nbsp;&nbsp;1</td></tr></table>";
		}
		elseif($outcome == 'd:c') {
$display = "<table width='100' border='0' cellspacing='0' cellpadding='6' style='border:solid 1px #000000;'><tr><td width='50%' style='border-right:solid 1px #000000;' >2&nbsp;&nbsp;2</td><td width='50%' style='border-bottom:solid 1px #000000;'>0&nbsp;&nbsp;3</td></tr><tr><td width='50%' bgcolor='#666666' style='color:#FFFFFF;border-top:solid 1px #000000;'>3&nbsp;&nbsp;0</td><td width='50%' style='border-left:solid 1px #000000;'>1&nbsp;&nbsp;1</td></tr></table>";
		}
		elseif($outcome == 'd:d') {
$display = "<table width='100' border='0' cellspacing='0' cellpadding='6' style='border:solid 1px #000000;'><tr><td width='50%' style='border-right:solid 1px #000000;' >2&nbsp;&nbsp;2</td><td width='50%' style='border-bottom:solid 1px #000000;'>0&nbsp;&nbsp;3</td></tr><tr><td width='50%'  style='border-top:solid 1px #000000;'>3&nbsp;&nbsp;0</td><td width='50%' bgcolor='#666666' style='color:#FFFFFF;solid 1px #000000;'>1&nbsp;&nbsp;1</td></tr></table>";
		}	
	return $display;
	}

	// This method choose the action for tit for tat 
private function pick_Tit_for_tat()
	{
		//$strategy = $this->strategies['Tit_for_tat'];
		$this->total_matches['Tit_for_tat']++;
		return "Tit_for_tat";
	}
// this method pick the random strategy
	private function pick_Random()
	{
		//$strategy = $this->strategies['Grudger_soft'];
		$this->total_matches['Random']++;

		return "Random";
	}
// This method compute the score of each of players according to their action
	private function calculate_scores($decision1, $decision2)
	{
		$outcome = $decision1 . ':' . $decision2;

		return array(
			$this->points_per_outcome[$outcome],
			$this->points_per_outcome[strrev($outcome)],
		);
	}

	// this method computes the average of all the games played
	private function calculate_averages()
	{
		foreach ($this->total_points as $strategy => $total_points)
	$this->avg_points_per_match[$strategy] = round($total_points / $this->total_matches[$strategy], 3);
	}
// This method sort all the outcome
	private function sort_data()
	{
		arsort($this->avg_points_per_match, SORT_NUMERIC);
		arsort($this->total_matches, SORT_NUMERIC);
		arsort($this->total_points, SORT_NUMERIC);
	}
// This method initialize to null the number of points and matches played
	private function prepare_variables()
	{
		foreach ($this->strategies as $strategy => $dummy)
		{
			$this->total_points[$strategy] = 0;
			$this->total_matches[$strategy] = 0;
		}
	}
}

You can download the full project here with a html test page.

You can also try to play it online here.

 

Enjoy it!

A propos

Je suis techniquement fort, expérimenté, pratique et curieux. Je travaille depuis plus de 15 ans dans le domaine de technologies de l'information. Je suis passionné de technologie et de ses applications. J'ai des connaissances et des compétences étendues et approfondies dans les domaines de la cloud computing, des outils, de l'automatisation et de la business intelligence.

Contact