/The-Iterated-Prisoners-Dilemma

The Prisoner's Dilemma Game

Primary LanguageC++MIT LicenseMIT

The Prisoner's Dilemma Game

Table of Contents

  1. Introduction
  2. Prerequisites and building
  3. Creating Matches
  4. Running the Tournament
  5. Adding Your Strategy
  6. Testing
  7. Contributing
  8. Acknowledgments

Introduction

Welcome to the implementation of Axelrod's Iterated Prisoner's Dilemma Tournament! This repository contains the code (in C++) for simulating and participating in the famous Axelrod's Iterated Prisoner's Dilemma (IPD) Tournament. The tournament is a classic example in game theory, where participants (strategies) compete against each other in a series of repeated prisoner's dilemma games.

Prerequisites And Building

The only prerequisites for library are CMake 3.22+ and a C++20 (and MinGW if you are going to use makefile) compiler.

Building:

$ mkdir build
$ cd build
$ cmake .. -G"MinGW Makefiles" # or use ony generator you want
$ make shakhbat_pd_lib

After a successful compilation The library should reside in ./lib directory as libshakhbat_pd_lib.a.

Use this command to copy the static library and include headers in the package folder.

$ make install

In the package folder will be libshakhbat_pd_lib.a and include folder.

You need to include include\shakhbat_pd.hpp and static link libshakhbat_pd_lib.a into your project.

Running :

$ make play

This will link (and build if not builded) the library with play.cpp, and produce play.exe which you can run

Creating Matches

You can create your own match between two strategies using the qlm::Match function.

	// first strategy
    qlm::FirstByJoss strategy_0;

    // second strategy
    qlm::TitForTat strategy_1;

    // match parameters
    const unsigned int num_rounds = 15;
    const qlm::PayOff pay_off {}; // default pay off
    const int seed = 0; // seed for  probabilistic strategies

    qlm::MatchResult match = qlm::Match(strategy_0, strategy_1, num_rounds, pay_off, seed);
    
    // print results
    match.Print();

    // save results as csv file
    match.SaveAsCSV("match_results.csv");

The output :

First by Joss: 0.9  VS  TitForTat
Match result of 15 rounds :
First by Joss: 0.9 Wins ,Score : 42
TitForTat Losses ,Score : 37
| Round | First by Joss: 0.9 | TitForTat |
| ----- | ------------------ | --------- |
| 0     | COOPERATE          | COOPERATE |
| 1     | COOPERATE          | COOPERATE |
| 2     | COOPERATE          | COOPERATE |
| 3     | COOPERATE          | COOPERATE |
| 4     | DEFECT             | COOPERATE |
| 5     | COOPERATE          | DEFECT    |
| 6     | DEFECT             | COOPERATE |
| 7     | COOPERATE          | DEFECT    |
| 8     | DEFECT             | COOPERATE |
| 9     | COOPERATE          | DEFECT    |
| 10    | DEFECT             | COOPERATE |
| 11    | COOPERATE          | DEFECT    |
| 12    | DEFECT             | COOPERATE |
| 13    | COOPERATE          | DEFECT    |
| 14    | DEFECT             | COOPERATE |
| ----- | ------------------ | --------- |

Running the Tournament

To run the Axelrod's Iterated Prisoner's Dilemma Tournament

Adding Your Strategy

To add your own strategy to compete in the tournament, follow these steps:

  • Write your strategy as a class publicly internets from Strategy and place the declaration in strategies.hpp
  • If you only need the constructor, Reset, FirstAction, and Action function to be written (most probably), then use this macro
    • DECLARE_STRATEGY(MyStrategy, n); // n is the number of flags you want std::bitset<n> flags
  • In the constructor you initialize the information of your strategy : name, info, properties.
  • The FirstAction will be called when your strategy starts first.
  • The Action is your action function and will take the opponent action as input and you access the history of actions.
  • you can use this function void UpdateHistory(const Choice my_play, const Choice opponent_play) to update history inside Action function.
  • Make CPP file with your class name MyStrategy.cpp inside source/strategies and write the implementation there.

Testing

The testing process involves a comparison between strategies playing against each other in this C++ library and the and Axelrod Python library.

The results (winner, score, actions) are generated by both libraries and compared to ensure consistency.

Prerequisites

Before running the tests, make sure you have the Axelrod library

Run Test

Compile the C++ library and run the test

$ make
$ make run_test

Add strategy to the test

Inside Axelrod.py add the strategy to the list strategy_list.

strategy_list = [axl.Cooperator(), ... , axl.YourNewStrategy()]

Inside shakhbat_pd_test.cpp push the strategy to the vector FillStrategies.

void FillStrategies()
{
    ADD_STRATEGY(qlm::Cooperator);
    .
    .
    .
    ADD_STRATEGY(qlm::YourNewStrategy);
}

The python list and CPP vector must have the same number of strategies and in the same order.

Contributing

If you would like to contribute to this project, please fork the repository, make your changes, and submit a pull request. Contributions are welcome!

Acknowledgments

Axelrod, r. (1980a). effective choice in the prisoner’s dilemma