Skip to content

Commit cb4d840

Browse files
authored
Merge pull request #724 from Huaraz2/WorseAndWorse
New Strategy From the PRISON (http://www.lifl.fr/IPD/ipd.frame.html)
2 parents d9b6147 + 3ddaa0e commit cb4d840

File tree

6 files changed

+178
-8
lines changed

6 files changed

+178
-8
lines changed

axelrod/strategies/_strategies.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
TitForTat, TitFor2Tats, TwoTitsForTat, Bully, SneakyTitForTat,
6060
SuspiciousTitForTat, AntiTitForTat, HardTitForTat, HardTitFor2Tats,
6161
OmegaTFT, Gradual, ContriteTitForTat, SlowTitForTwoTats, AdaptiveTitForTat)
62-
62+
from .worse_and_worse import (WorseAndWorse, KnowledgeableWorseAndWorse)
6363

6464
# Note: Meta* strategies are handled in .__init__.py
6565

@@ -141,6 +141,7 @@
141141
Inverse,
142142
InversePunisher,
143143
Joss,
144+
KnowledgeableWorseAndWorse,
144145
LimitedRetaliate,
145146
LimitedRetaliate2,
146147
LimitedRetaliate3,
@@ -195,12 +196,13 @@
195196
Willing,
196197
WinShiftLoseStay,
197198
WinStayLoseShift,
199+
WorseAndWorse,
198200
ZDExtort2,
199201
ZDExtort2v2,
200202
ZDExtort4,
201203
ZDGTFT2,
202204
ZDGen2,
203205
ZDSet2,
204206
e,
205-
207+
206208
]

axelrod/strategies/worse_and_worse.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
from axelrod import Actions, Player, random_choice
2+
3+
C, D = Actions.C, Actions.D
4+
5+
class WorseAndWorse (Player):
6+
"""
7+
Defects with probability of 'current turn / 1000'. Therefore
8+
it is more and more likely to defect as the round goes on.
9+
10+
Source code available at the download tab of [PRISON1998]_
11+
12+
13+
Names:
14+
- Worse and Worse: [PRISON1998]_
15+
16+
"""
17+
18+
name = 'Worse and Worse'
19+
classifier = {
20+
'memory_depth': float('inf'),
21+
'stochastic': True,
22+
'makes_use_of': set(),
23+
'long_run_time': False,
24+
'inspects_source': False,
25+
'manipulates_source': False,
26+
'manipulates_state': False
27+
}
28+
29+
def strategy(self, opponent):
30+
current_round = len(self.history) + 1
31+
probability = 1 - float(current_round) / 1000
32+
return random_choice(probability)
33+
34+
35+
class KnowledgeableWorseAndWorse (Player):
36+
"""
37+
This strategy is based on 'Worse And Worse' but will defect with probability
38+
of 'current turn / total no. of turns'.
39+
40+
Names:
41+
- Knowledgeable Worse and Worse: Original name by Adam Pohl
42+
"""
43+
44+
name = 'Knowledgeable Worse and Worse'
45+
classifier = {
46+
'memory_depth': float('inf'),
47+
'stochastic': True,
48+
'makes_use_of': set(['length']),
49+
'long_run_time': False,
50+
'inspects_source': False,
51+
'manipulates_source': False,
52+
'manipulates_state': False
53+
}
54+
55+
def strategy(self, opponent):
56+
current_round = len(self.history) + 1
57+
expected_length = self.match_attributes['length']
58+
probability = 1 - float(current_round) / expected_length
59+
return random_choice(probability)

axelrod/tests/unit/test_player.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
# -*- coding: utf-8 -*-
2-
import copy
32
import inspect
43
import random
54
import unittest
@@ -89,7 +88,7 @@ def test_responses(test_class, P1, P2, history_1, history_2, responses,
8988
"""
9089

9190
if random_seed:
92-
random.seed(random_seed)
91+
axelrod.seed(random_seed)
9392
# Force the histories, In case either history is impossible or if some
9493
# internal state needs to be set, actually submit to moves to the strategy
9594
# method. Still need to append history manually.
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
"""Test for the Worse and Worse strategies."""
2+
3+
import axelrod
4+
5+
from .test_player import TestPlayer
6+
7+
C, D = axelrod.Actions.C, axelrod.Actions.D
8+
9+
class TestWorseAndWorse(TestPlayer):
10+
11+
name = "Worse and Worse"
12+
player = axelrod.WorseAndWorse
13+
expected_classifier = {
14+
'memory_depth': float('inf'),
15+
'stochastic': True,
16+
'makes_use_of': set(),
17+
'long_run_time': False,
18+
'inspects_source': False,
19+
'manipulates_source': False,
20+
'manipulates_state': False
21+
}
22+
23+
def test_strategy(self):
24+
"""
25+
Test that the strategy gives expected behaviour
26+
"""
27+
28+
axelrod.seed(8)
29+
opponent = axelrod.Cooperator()
30+
player = axelrod.WorseAndWorse()
31+
match = axelrod.Match((opponent, player), turns=10)
32+
self.assertEqual(match.play(), [('C', 'C'),
33+
('C', 'C'),
34+
('C', 'C'),
35+
('C', 'C'),
36+
('C', 'C'),
37+
('C', 'C'),
38+
('C', 'D'),
39+
('C', 'C'),
40+
('C', 'C'),
41+
('C', 'C')])
42+
43+
# Test that behaviour does not depend on opponent
44+
opponent = axelrod.Defector()
45+
player = axelrod.WorseAndWorse()
46+
axelrod.seed(8)
47+
match = axelrod.Match((opponent, player), turns=10)
48+
self.assertEqual(match.play(), [('D', 'C'),
49+
('D', 'C'),
50+
('D', 'C'),
51+
('D', 'C'),
52+
('D', 'C'),
53+
('D', 'C'),
54+
('D', 'D'),
55+
('D', 'C'),
56+
('D', 'C'),
57+
('D', 'C')])
58+
59+
60+
class TestWorseAndWorseRandom(TestPlayer):
61+
62+
name = "Knowledgeable Worse and Worse"
63+
player = axelrod.KnowledgeableWorseAndWorse
64+
expected_classifier = {
65+
'memory_depth': float('inf'),
66+
'stochastic': True,
67+
'makes_use_of': set(['length']),
68+
'long_run_time': False,
69+
'inspects_source': False,
70+
'manipulates_source': False,
71+
'manipulates_state': False
72+
}
73+
74+
def test_strategy(self):
75+
"""
76+
Test that the strategy gives expected behaviour
77+
"""
78+
axelrod.seed(1)
79+
opponent = axelrod.Cooperator()
80+
player = axelrod.KnowledgeableWorseAndWorse()
81+
match = axelrod.Match((opponent, player), turns=5)
82+
self.assertEqual(match.play(), [('C', 'C'),
83+
('C', 'D'),
84+
('C', 'D'),
85+
('C', 'D'),
86+
('C', 'D')])
87+
88+
# Test that behaviour does not depend on opponent
89+
opponent = axelrod.Defector()
90+
player = axelrod.KnowledgeableWorseAndWorse()
91+
axelrod.seed(1)
92+
match = axelrod.Match((opponent, player), turns=5)
93+
self.assertEqual(match.play(), [('D', 'C'),
94+
('D', 'D'),
95+
('D', 'D'),
96+
('D', 'D'),
97+
('D', 'D')])
98+
99+
# Test that behaviour changes when does not know length.
100+
axelrod.seed(1)
101+
match = axelrod.Match((opponent, player), turns=5,
102+
match_attributes={'length': float('inf')})
103+
self.assertEqual(match.play(), [('D', 'C'),
104+
('D', 'C'),
105+
('D', 'C'),
106+
('D', 'C'),
107+
('D', 'C')])

docs/reference/all_strategies.rst

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ Here are the docstrings of all the strategies in the library.
6060
.. automodule:: axelrod.strategies.gobymajority
6161
:members:
6262
:undoc-members:
63+
.. automodule:: axelrod.strategies.gradualkiller
64+
:members:
65+
:undoc-members:
6366
.. automodule:: axelrod.strategies.grudger
6467
:members:
6568
:undoc-members:
@@ -120,6 +123,6 @@ Here are the docstrings of all the strategies in the library.
120123
.. automodule:: axelrod.strategies.titfortat
121124
:members:
122125
:undoc-members:
123-
.. automodule:: axelrod.strategies.gradualkiller
126+
.. automodule:: axelrod.strategies.worse_and_worse
124127
:members:
125-
:undoc-members:
128+
:undoc-members:

docs/tutorials/advanced/classification_of_strategies.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ strategies::
4747
... }
4848
>>> strategies = axl.filtered_strategies(filterset)
4949
>>> len(strategies)
50-
35
50+
37
5151

5252

5353
Or, to find out how many strategies only use 1 turn worth of memory to
@@ -81,7 +81,7 @@ length of each match of the tournament::
8181
... }
8282
>>> strategies = axl.filtered_strategies(filterset)
8383
>>> len(strategies)
84-
4
84+
5
8585

8686
Note that in the filterset dictionary, the value for the 'makes_use_of' key
8787
must be a list. Here is how we might identify the number of strategies that use

0 commit comments

Comments
 (0)