Skip to content

Added strategies Desperate, Willing, Hopeless, Grim #686

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

Merged
merged 7 commits into from
Aug 16, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions axelrod/strategies/_strategies.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
ZDGen2, ZDGTFT2, ZDSet2, WinStayLoseShift, WinShiftLoseStay)
from .mindcontrol import MindController, MindWarper, MindBender
from .mindreader import MindReader, ProtectedMindReader, MirrorMindReader
from .mutual import Desperate, Hopeless, Willing
from .oncebitten import OnceBitten, FoolMeOnce, ForgetfulFoolMeOnce, FoolMeForever
from .prober import (Prober, Prober2, Prober3, HardProber,
NaiveProber, RemorsefulProber)
Expand Down Expand Up @@ -92,6 +93,7 @@
Davis,
Defector,
DefectorHunter,
Desperate,
DoubleCrosser,
Eatherley,
EventualCycleHunter,
Expand All @@ -115,21 +117,22 @@
GoByMajority20,
GoByMajority40,
GoByMajority5,
Golden,
Gradual,
Grofman,
Grudger,
Grumpy,
Handshake,
HardGoByMajority,
HardGoByMajority10,
HardGoByMajority20,
HardGoByMajority40,
HardGoByMajority5,
Golden,
Gradual,
Grofman,
Grudger,
Grumpy,
HardProber,
HardTitFor2Tats,
HardTitForTat,
HesitantQLearner,
Hopeless,
Inverse,
InversePunisher,
Joss,
Expand Down Expand Up @@ -184,6 +187,7 @@
TrickyDefector,
Tullock,
TwoTitsForTat,
Willing,
WinShiftLoseStay,
WinStayLoseShift,
ZDExtort2,
Expand Down
82 changes: 82 additions & 0 deletions axelrod/strategies/mutual.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
from axelrod import Actions, Player, init_args
from axelrod.random_ import random_choice

C, D = Actions.C, Actions.D


class Desperate(Player):
"""A player that only cooperates after mutual defection.

Names:

- Desperate: [Berg2015]_"""

name = "Desperate"
classifier = {
'memory_depth': 1,
'long_run_time': False,
'stochastic': True,
'makes_use_of': set(),
'inspects_source': False,
'manipulates_source': False,
'manipulates_state': False
}

def strategy(self, opponent):
if not opponent.history:
return random_choice()
if self.history[-1] == D and opponent.history[-1] == D:
return C
return D


class Hopeless(Player):
"""A player that only defects after mutual cooperation.

Names:

- Hopeless: [Berg2015]_"""

name = "Hopeless"
classifier = {
'memory_depth': 1,
'long_run_time': False,
'stochastic': True,
'makes_use_of': set(),
'inspects_source': False,
'manipulates_source': False,
'manipulates_state': False
}

def strategy(self, opponent):
if not opponent.history:
return random_choice()
if self.history[-1] == C and opponent.history[-1] == C:
return D
return C


class Willing(Player):
"""A player that only defects after mutual defection.

Names:

- Willing: [Berg2015]_"""

name = "Willing"
classifier = {
'memory_depth': 1,
'long_run_time': False,
'stochastic': True,
'makes_use_of': set(),
'inspects_source': False,
'manipulates_source': False,
'manipulates_state': False
}

def strategy(self, opponent):
if not opponent.history:
return random_choice()
if self.history[-1] == D and opponent.history[-1] == D:
return D
return C
84 changes: 84 additions & 0 deletions axelrod/tests/unit/test_mutual.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
"""Tests for strategies Desperate, Hopeless, Willing, and Grim"""
import axelrod

from axelrod.random_ import seed

from .test_player import TestPlayer

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

class TestDesperate(TestPlayer):

name = "Desperate"
player = axelrod.Desperate
expected_classifier = {
'memory_depth': 1,
'long_run_time': False,
'stochastic': True,
'makes_use_of': set(),
'inspects_source': False,
'manipulates_source': False,
'manipulates_state': False
}

def test_strategy(self):
seed(1)
self.first_play_test(C)
seed(2)
self.first_play_test(D)

def test_responses(self):
self.responses_test([C] * 4, [D] * 4, [D])
self.responses_test([D, D, C], [C, C, D], [D])
self.responses_test([D, D, D], [C, C, D], [C])


class TestHopeless(TestPlayer):

name = "Hopeless"
player = axelrod.Hopeless
expected_classifier = {
'memory_depth': 1,
'long_run_time': False,
'stochastic': True,
'makes_use_of': set(),
'inspects_source': False,
'manipulates_source': False,
'manipulates_state': False
}

def test_strategy(self):
seed(1)
self.first_play_test(C)
seed(2)
self.first_play_test(D)

def test_responses(self):
self.responses_test([C] * 4, [D] * 4, [C])
self.responses_test([D] * 5, [C] * 5, [C])
self.responses_test([C, D, C], [C, C, C], [D])

class TestWilling(TestPlayer):

name = "Willing"
player = axelrod.Willing
expected_classifier = {
'memory_depth': 1,
'long_run_time': False,
'stochastic': True,
'makes_use_of': set(),
'inspects_source': False,
'manipulates_source': False,
'manipulates_state': False
}

def test_strategy(self):
seed(1)
self.first_play_test(C)
Copy link
Member

Choose a reason for hiding this comment

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

Could we also check that D is sometimes played?

Copy link
Member

Choose a reason for hiding this comment

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

And for the other two.

Suggestion: instead of a seed could just play 20 first plays and check that both C and D are in there.

seed(2)
self.first_play_test(D)

def test_responses(self):
self.responses_test([C] * 4, [D] * 4, [C])
self.responses_test([D] * 5, [C] * 5, [C])
self.responses_test([C, C, D], [C, C, D], [D])
4 changes: 2 additions & 2 deletions docs/tutorials/advanced/classification_of_strategies.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ This allows us to, for example, quickly identify all the stochastic
strategies::

>>> len([s for s in axl.strategies if s().classifier['stochastic']])
40
43

Or indeed find out how many strategy only use 1 turn worth of memory to
make a decision::

>>> len([s for s in axl.strategies if s().classifier['memory_depth']==1])
21
24

We can also identify strategies that make use of particular properties of the
tournament. For example, here is the number of strategies that make use of the
Expand Down