Dynamics of Learning and Iterated Games Project

Successful evolutionary strategies [1]

  1. Be nice
  2. Be provocable
  3. Do not be envious
  4. Be clear

[1] Robert Axelrod. The evolution of cooperation. Book Title: The evolution of cooperation. London: Penguin, 1990. isbn: 978-0-14-012495-8.

Noise affects evolutionary strategies

  • TFT: is too provokable
  • Win-stay, shift-lose: can re-establish trust
  • TF2T: Harder to lose trust

Creating our own strategies for noisy environments

  • Based on Adaptive Pavlov
  • Cooperation strategy is TF2T
  • Exploits weakness of certain strategies

Preliminary strategy classification

def strategy(self, opponent: Player) -> Action:
        # Cooperates in the first 2 rounds, not punishing a suspicious agent
        if len(self.history) < 2:
            return C
        # Play TFT for another 4 rounds
        if len(self.history) < 6:
            return D if opponent.history[-1] == D else C
        # First classification round
        if len(self.history) == 6:
            # Default guess
            self.opponent_class = "Random"
            # Ignore the first defection made by a possible STFT
            # Use at least 4 due to possible noise
            if opponent.history[-5:].count(C) >= 4:
                self.opponent_class = "Cooperative"
            if opponent.history[-6:].count(D) >= 4:
                self.opponent_class = "ALLD"

Secondary strategy classification

        if self.opponent_class == "Cooperative":
            # Defect on round 7 and 8 to determine later on if it's
            # possible to exploit the opponents strategy.
            if len(self.history) < 8:
                return D
            # Cooperate for the next 3 round
            if len(self.history) < 11:
                return C
            # Analyse last 5 rounds
            if len(self.history) == 11:
                # Default guess
                self.opponent_class = "TFT"
                if opponent.history[-5:] == [D] * 2 + [C] * 3:
                    self.opponent_class = "self"
                if opponent.history[-5:] == [C] + [D] * 4:
                    self.opponent_class = "Grudger"
                if opponent.history[-5:] == [C, D, D, D, C]:
                    self.opponent_class = "2TFT"
                if opponent.history[-5:] == [C] * 5:
                    self.opponent_class = "AllC"
                if opponent.history[-5:] == [C, D, D, C, C]:
                    self.opponent_class = "TFT"
                if opponent.history[-5:] == [C, C, D, C, C]:
                    self.opponent_class = "TF2T"

Move selection depending on opponent

        # Play according to classification
        if self.opponent_class in ["Random", "ALLD", "Grudger", "AllC"]:
            return D
        if self.opponent_class in ["2TFT", "TFT", "self"]:
            # Play Tits for 2 Tats as our cooperative strategy (noise forgiving)
            return D if opponent.history[-2:] == [D, D] else C
        if self.opponent_class == "TF2T":
            # Ensure we don't commit two defection in a row by mistake:
            if self.history[-2:] == [D] * 2:
                return C
            return D if self.history[-1] == C else C

Tournament results

Medium tournament STD

Medium tournament Noisy

Complete tournament results, (STD)

Ranked 136

(0-indexed ranking)

Complete tournament results, (noisy)

Ranked 21

(0-indexed ranking)

deck

By girgias

deck

  • 169