Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3 New Strategies From the PRISON (http://www.lifl.fr/IPD/ipd.frame.html) #715

Merged
merged 10 commits into from
Sep 20, 2016
6 changes: 5 additions & 1 deletion axelrod/strategies/_strategies.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@
GoByMajority5,
HardGoByMajority, HardGoByMajority10, HardGoByMajority20, HardGoByMajority40,
HardGoByMajority5)
from .gradualkiller import GradualKiller
from .grudger import (Grudger, ForgetfulGrudger, OppositeGrudger, Aggravater,
SoftGrudger)
SoftGrudger, GrudgerAlternator, EasyGo)
from .grumpy import Grumpy
from .handshake import Handshake
from .hunter import (
Expand Down Expand Up @@ -96,6 +97,7 @@
DefectorHunter,
Desperate,
DoubleCrosser,
EasyGo,
Eatherley,
EventualCycleHunter,
Feld,
Expand All @@ -120,8 +122,10 @@
GoByMajority5,
Golden,
Gradual,
GradualKiller,
Grofman,
Grudger,
GrudgerAlternator,
Grumpy,
Handshake,
HardGoByMajority,
Expand Down
35 changes: 35 additions & 0 deletions axelrod/strategies/gradualkiller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from axelrod import Actions, Player, init_args
from axelrod.strategy_transformers import InitialTransformer

C, D = Actions.C, Actions.D

@InitialTransformer((D, D, D, D, D, C, C), name_prefix=None)
class GradualKiller(Player):
"""
It begins by defecting in the first five moves, then cooperates two times.
It then defects all the time if the opponent has defected in move 6 and 7,
else cooperates all the time.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a sentence here saying that this is designed to stop Gradual from winning? (And possibly why?)

Initially designed to stop Gradual from defeating TitForTat in a 3 Player
tournament.

Names

- Gradual Killer: [PRISON1998]_
"""

# These are various properties for the strategy
name = 'Gradual Killer'
classifier = {
'memory_depth': float('Inf'),
'stochastic': False,
'makes_use_of': set(),
'long_run_time': False,
'inspects_source': False,
'manipulates_source': False,
'manipulates_state': False
}

def strategy(self, opponent):
if opponent.history[5:7] == [D, D]:
return D
return C
60 changes: 60 additions & 0 deletions axelrod/strategies/grudger.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,63 @@ def reset(self):
Player.reset(self)
self.grudged = False
self.grudge_memory = 0



class GrudgerAlternator(Player):
"""
A player starts by cooperating until the first opponents defection,
then alternates D-C.

Names:

- c_then_per_dc: [PRISON1998]_
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also add GrudgerAlternator to this list?

- Grudger Alternator: Original name by Geraint Palmer
"""

name = 'GrudgerAlternator'
classifier = {
'memory_depth': float('inf'), # Long memory
'stochastic': False,
'makes_use_of': set(),
'long_run_time': False,
'inspects_source': False,
'manipulates_source': False,
'manipulates_state': False
}

def strategy(self, opponent):
"""Begins by playing C, then plays Alternator for the remaining rounds if the opponent ever plays D."""
if opponent.defections:
if self.history[-1] == Actions.C:
return Actions.D
return Actions.C



class EasyGo(Player):
"""
A player starts by defecting however will cooperate if at any point the opponent has defected.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the opponent

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignore this.


Names:

- Easy Go [PRISON1998]_
"""

name = 'EasyGo'
classifier = {
'memory_depth': float('inf'), # Long memory
'stochastic': False,
'makes_use_of': set(),
'long_run_time': False,
'inspects_source': False,
'manipulates_source': False,
'manipulates_state': False
}

@staticmethod
def strategy(opponent):
"""Begins by playing D, then plays C for the remaining rounds if the opponent ever plays D."""
if opponent.defections:
return C
return D
104 changes: 104 additions & 0 deletions axelrod/tests/unit/test_gradualkiller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
"""Test for the gradual killer strategy."""

import axelrod
from .test_player import TestHeadsUp, TestPlayer

from hypothesis import given
from hypothesis.strategies import integers
from axelrod.tests.property import strategy_lists

import random

C, D = axelrod.Actions.C, axelrod.Actions.D


class TestGradualKiller(TestPlayer):

name = "Gradual Killer"
player = axelrod.GradualKiller
expected_classifier = {
'memory_depth': float('Inf'),
'stochastic': False,
'makes_use_of': set(),
'inspects_source': False,
'manipulates_source': False,
'manipulates_state': False
}

def test_strategy(self):
"""Starts by Defecting."""
self.first_play_test(D)

def test_effect_of_strategy(self):
"""Fist seven moves."""
self.markov_test([D, D, D, D])
self.responses_test([], [], [D, D, D, D, D, C, C])

def test_effect_of_strategy_with_history_CC(self):
"""Continues with C if opponent played CC on 6 and 7."""
P1 = axelrod.GradualKiller()
P2 = axelrod.Player()
P1.history = [D, D, D, D, D, C, C]
P2.history = [C, C, C, C, C, C, C]
self.assertEqual(P1.strategy(P2), 'C')
P1.history = [D, D, D, D, D, C, C, C]
P2.history = [C, C, C, C, C, C, C, C]
self.assertEqual(P1.strategy(P2), 'C')
P1.history = [D, D, D, D, D, C, C, C, C]
P2.history = [C, C, C, C, C, C, C, C, C]
self.assertEqual(P1.strategy(P2), 'C')
P1.history = [D, D, D, D, D, C, C, C, C, C]
P2.history = [C, C, C, C, C, C, C, C, C, C]
self.assertEqual(P1.strategy(P2), 'C')

def test_effect_of_strategy_with_history_CD(self):
"""Continues with C if opponent played CD on 6 and 7."""
P1 = axelrod.GradualKiller()
P2 = axelrod.Player()
P1.history = [D, D, D, D, D, C, C]
P2.history = [C, C, C, C, C, C, D]
self.assertEqual(P1.strategy(P2), 'C')
P1.history = [D, D, D, D, D, C, C, C]
P2.history = [C, C, C, C, C, C, D, D]
self.assertEqual(P1.strategy(P2), 'C')
P1.history = [D, D, D, D, D, C, C, C, C]
P2.history = [C, C, C, C, C, C, D, D, C]
self.assertEqual(P1.strategy(P2), 'C')
P1.history = [D, D, D, D, D, C, C, C, C, C]
P2.history = [C, C, C, C, C, C, D, D, C, C]
self.assertEqual(P1.strategy(P2), 'C')

def test_effect_of_strategy_with_history_DC(self):
"""Continues with C if opponent played DC on 6 and 7."""
P1 = axelrod.GradualKiller()
P2 = axelrod.Player()
P1.history = [D, D, D, D, D, C, C]
P2.history = [C, C, C, C, C, D, C]
self.assertEqual(P1.strategy(P2), 'C')
P1.history = [D, D, D, D, D, C, C, C]
P2.history = [C, C, C, C, C, D, C, C]
self.assertEqual(P1.strategy(P2), 'C')
P1.history = [D, D, D, D, D, C, C, C, C]
P2.history = [C, C, C, C, C, D, C, C, D]
self.assertEqual(P1.strategy(P2), 'C')
P1.history = [D, D, D, D, D, C, C, C, C, C]
P2.history = [C, C, C, C, C, D, C, C, D, C]
self.assertEqual(P1.strategy(P2), 'C')

def test_effect_of_strategy_with_history_CC(self):
"""Continues with D if opponent played DD on 6 and 7."""
P1 = axelrod.GradualKiller()
P2 = axelrod.Player()
P1.history = [D, D, D, D, D, C, C]
P2.history = [C, C, C, C, C, D, D]
self.assertEqual(P1.strategy(P2), 'D')
P1.history = [D, D, D, D, D, C, C, D]
P2.history = [C, C, C, C, C, D, D, C]
self.assertEqual(P1.strategy(P2), 'D')
P1.history = [D, D, D, D, D, C, C, D, D]
P2.history = [C, C, C, C, C, D, D, C, C]
self.assertEqual(P1.strategy(P2), 'D')
P1.history = [D, D, D, D, D, C, C, D, D, D]
P2.history = [C, C, C, C, C, D, D, C, C, D]
self.assertEqual(P1.strategy(P2), 'D')

82 changes: 82 additions & 0 deletions axelrod/tests/unit/test_grudger.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Tests for grudger strategies."""

import axelrod
from random import randint

from .test_player import TestPlayer

Expand Down Expand Up @@ -173,3 +174,84 @@ def test_reset(self):
p.reset()
self.assertFalse(p.grudged)
self.assertEqual(p.grudge_memory, 0)



class TestGrudgerAlternator(TestPlayer):

name = "GrudgerAlternator"
player = axelrod.GrudgerAlternator
expected_classifier = {
'memory_depth': float('inf'), # Long memory
'stochastic': False,
'makes_use_of': set(),
'long_run_time': False,
'inspects_source': False,
'manipulates_source': False,
'manipulates_state': False
}

def test_initial_strategy(self):
"""
Starts by cooperating
"""
self.first_play_test(C)

def test_strategy(self):
"""
If opponent defects at any point then the player will alternate D-C.
"""
self.responses_test([C, C, C, C, C], [C, C, C, C, C], [C])
self.responses_test([C, C, C, C, C, C], [C, C, C, C, C, D], [D])
self.responses_test([C, C, C, C, C, C, D], [C, C, C, C, C, D, D], [C])
self.responses_test([C, C, C, C, C, C, D, C], [C, C, C, C, C, D, D, C], [D])
self.responses_test([C, C, C, C, C, C, D, C, D], [C, C, C, C, C, D, D, C, C], [C])

def test_starategy_random_number_rounds(self):
"""
Runs test_strategy for a random number of rounds
"""
# Hasn't defected yet
for _ in range(20):
i = randint(1, 30)
j = randint(1, 30)
opp_hist = [C] * i
my_hist = [C] * i
self.responses_test(my_hist, opp_hist, [C]*j)

# Defected at least once
for _ in range(20):
i = randint(1, 30)
j = randint(1, 30)
opp_hist = [C for r in range(i)] + [D]
my_hist = [C] * (i + 1)
expected_response = [D if r % 2 == 0 else C for r in range(j)]
self.responses_test(my_hist, opp_hist, expected_response)


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you get rid of the extra lines? Should be 2.

class TestEasyGo(TestPlayer):

name = "EasyGo"
player = axelrod.EasyGo
expected_classifier = {
'memory_depth': float('inf'), # Long memory
'stochastic': False,
'makes_use_of': set(),
'long_run_time': False,
'inspects_source': False,
'manipulates_source': False,
'manipulates_state': False
}

def test_initial_strategy(self):
"""
Starts by cooperating
"""
self.first_play_test(D)

def test_strategy(self):
"""
If opponent defects at any point then the player will cooperate forever
"""
self.responses_test([C, D, D, D], [C, C, C, C], [D])
self.responses_test([C, C, D, D, D], [C, D, C, C, C], [C])
1 change: 1 addition & 0 deletions axelrod/tests/unit/test_resultset.py
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,7 @@ def test_interactions_equality(self):

@given(tournament=tournaments(max_size=5,
max_turns=5,
max_noise=0,
max_repetitions=3))
@settings(max_examples=50, timeout=0)
def test_equality_with_round_robin(self, tournament):
Expand Down
3 changes: 3 additions & 0 deletions docs/reference/all_strategies.rst
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,6 @@ Here are the docstrings of all the strategies in the library.
.. automodule:: axelrod.strategies.titfortat
:members:
:undoc-members:
.. automodule:: axelrod.strategies.gradualkiller
:members:
:undoc-members:
1 change: 1 addition & 0 deletions docs/reference/bibliography.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ documentation.
.. [Stewart2012] Stewart, a. J., & Plotkin, J. B. (2012). Extortion and cooperation in the Prisoner’s Dilemma. Proceedings of the National Academy of Sciences, 109(26), 10134–10135. http://doi.org/10.1073/pnas.1208087109
.. [Szabó1992] Szabó, G., & Fáth, G. (2007). Evolutionary games on graphs. Physics Reports, 446(4-6), 97–216. http://doi.org/10.1016/j.physrep.2007.04.004
.. [Tzafestas2000] Tzafestas, E. (2000). Toward adaptive cooperative behavior. From Animals to Animals: Proceedings of the 6th International Conference on the Simulation of Adaptive Behavior {(SAB-2000)}, 2, 334–340.
.. [PRISON1998] LIFL (1998) PRISON. Available at: http://www.lifl.fr/IPD/ipd.frame.html (Accessed: 19 September 2016).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there no academic reference?