Skip to content

Commit 36ac9a4

Browse files
authored
Merge pull request #1141 from gaffney2010/master
Implemented strategy Cave (k49r from Axelrod's Second)
2 parents 06b2862 + 219b83b commit 36ac9a4

File tree

6 files changed

+108
-5
lines changed

6 files changed

+108
-5
lines changed

axelrod/strategies/_strategies.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
UnnamedStrategy, SteinAndRapoport, TidemanAndChieruzzi)
1010
from .axelrod_second import (
1111
Champion, Eatherley, Tester, Gladstein, Tranquilizer, MoreGrofman,
12-
Kluepfel, Borufsen)
12+
Kluepfel, Borufsen, Cave)
1313
from .backstabber import BackStabber, DoubleCrosser
1414
from .better_and_better import BetterAndBetter
1515
from .bush_mosteller import BushMosteller
@@ -113,6 +113,7 @@
113113
BushMosteller,
114114
Calculator,
115115
CautiousQLearner,
116+
Cave,
116117
Champion,
117118
CollectiveStrategy,
118119
ContriteTitForTat,

axelrod/strategies/axelrod_second.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,3 +718,56 @@ def strategy(self, opponent: Player) -> Action:
718718

719719
# Tit-for-tat
720720
return self.try_return(opponent.history[-1])
721+
722+
class Cave(Player):
723+
"""
724+
Strategy submitted to Axelrod's second tournament by Rob Cave (K49R), and
725+
came in fourth in that tournament.
726+
727+
First look for overly-defective or apparently random opponents, and defect
728+
if found. That is any opponent meeting one of:
729+
730+
- turn > 39 and percent defects > 0.39
731+
- turn > 29 and percent defects > 0.65
732+
- turn > 19 and percent defects > 0.79
733+
734+
Otherwise, respond to cooperation with cooperation. And respond to defcts
735+
with either a defect (if opponent has defected at least 18 times) or with
736+
a random (50/50) choice. [Cooperate on first.]
737+
738+
Names:
739+
740+
- Cave: [Axelrod1980b]_
741+
"""
742+
743+
name = "Cave"
744+
classifier = {
745+
'memory_depth': float('inf'),
746+
'stochastic': True,
747+
'makes_use_of': set(),
748+
'long_run_time': False,
749+
'inspects_source': False,
750+
'manipulates_source': False,
751+
'manipulates_state': False
752+
}
753+
754+
def strategy(self, opponent: Player) -> Action:
755+
turn = len(self.history) + 1
756+
if turn == 1: return C
757+
758+
did_d = np.vectorize(lambda action: float(action == D))
759+
number_defects = np.sum(did_d(opponent.history))
760+
perc_defects = number_defects / turn # Size of numerator is smaller than denomator -- How it was in the Fortran.
761+
762+
# If overly defect or appears random
763+
if turn > 39 and perc_defects > 0.39: return D
764+
if turn > 29 and perc_defects > 0.65: return D
765+
if turn > 19 and perc_defects > 0.79: return D
766+
767+
if opponent.history[-1] == D:
768+
if number_defects > 17:
769+
return D
770+
else:
771+
return random_choice(0.5)
772+
else:
773+
return C

axelrod/tests/strategies/test_axelrod_second.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,3 +490,52 @@ def test_strategy(self):
490490
[(D, C)] + [(C, C), (C, D), (D, C)] * 8 + \
491491
[(D, C)] * 25
492492
self.versus_test(axelrod.WinShiftLoseStay(D), expected_actions=actions)
493+
494+
class TestCave(TestPlayer):
495+
name = "Cave"
496+
player = axelrod.Cave
497+
expected_classifier = {
498+
'memory_depth': float('inf'),
499+
'stochastic': True,
500+
'makes_use_of': set(),
501+
'long_run_time': False,
502+
'inspects_source': False,
503+
'manipulates_source': False,
504+
'manipulates_state': False
505+
}
506+
507+
def test_strategy(self):
508+
actions = [(C, C)] * 100
509+
self.versus_test(axelrod.Cooperator(), expected_actions=actions)
510+
511+
# It will take until turn 18 to respond decide to repond D->D
512+
actions = [(C, D)]
513+
actions += [(C, D), (D, D), (D, D), (C, D), (C, D), (C, D), (D, D),
514+
(D, D), (C, D), (C, D), (D, D), (C, D), (D, D), (C, D),
515+
(C, D), (D, D), (C, D)] # Randomly choose
516+
actions += [(D, D)] * 30 # Defect
517+
self.versus_test(axelrod.Defector(), expected_actions=actions, seed=1)
518+
519+
# Highly-defective opponent
520+
# It will take until turn 20 to respond decide to repond D to C
521+
opponent_actions = [D] * 17 + [C, C, C, C]
522+
almost_defector = axelrod.MockPlayer(actions=opponent_actions)
523+
524+
actions = [(C, D)]
525+
actions += [(C, D), (D, D), (D, D), (C, D), (C, D), (C, D), (D, D),
526+
(D, D), (C, D), (C, D), (D, D), (C, D), (D, D), (C, D),
527+
(C, D), (D, D), (C, C)] # Randomly choose
528+
actions += [(C, C)] # Coop for a minute
529+
actions += [(D, C), (D, C)]
530+
self.versus_test(almost_defector, expected_actions=actions, seed=1)
531+
532+
#Here it will take until turn 40 to detect random and defect
533+
actions = [(C, C)]
534+
actions += [(C, D), (D, C), (C, D), (D, C), (C, D), (C, C), (C, D),
535+
(C, C), (C, D), (D, C), (C, D), (D, C), (C, D), (D, C),
536+
(C, D), (C, C), (C, D), (D, C), (C, D), (D, C), (C, D),
537+
(D, C), (C, D), (C, C), (C, D), (C, C), (C, D), (C, C),
538+
(C, D), (D, C), (C, D), (D, C), (C, D), (D, C), (C, D)] #Randomly choose
539+
actions += [(D, C), (C, D), (D, C)] # 17 D have come, so tit for tat for a while
540+
actions += [(D, D), (D, C)] * 100 # Random finally detected
541+
self.versus_test(axelrod.Alternator(), expected_actions=actions, seed=2)

axelrod/tests/strategies/test_meta.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -331,11 +331,11 @@ class TestMetaMajorityLongMemory(TestMetaPlayer):
331331
}
332332

333333
def test_strategy(self):
334-
actions = [(C, C), (C, D), (C, C), (C, D), (D, C)]
334+
actions = [(C, C), (C, D), (D, C), (C, D), (D, C)]
335335
self.versus_test(opponent=axelrod.Alternator(),
336336
expected_actions=actions, seed=0)
337337

338-
actions = [(C, C), (C, D), (D, C), (C, D), (D, C)]
338+
actions = [(C, C), (C, D), (C, C), (C, D), (D, C)]
339339
self.versus_test(opponent=axelrod.Alternator(),
340340
expected_actions=actions, seed=1)
341341

docs/reference/overview_of_strategies.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ repository.
119119
"K46R_", "Graham J Eatherley", ":class:`Eatherley <axelrod.strategies.axelrod_second.Eatherley>`"
120120
"K47R_", "Richard Hufford", "Not Implemented"
121121
"K48R_", "George Hufford", "Not Implemented"
122-
"K49R_", "Rob Cave", "Not Implemented"
122+
"K49R_", "Rob Cave", ":class:`Cave <axelrod.strategies.axelrod_second.Cave>`"
123123
"K50R_", "Rik Smoody", "Not Implemented"
124124
"K51R_", "John Willaim Colbert", "Not Implemented"
125125
"K52R_", "David A Smith", "Not Implemented"

docs/tutorials/advanced/classification_of_strategies.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ strategies::
4747
... }
4848
>>> strategies = axl.filtered_strategies(filterset)
4949
>>> len(strategies)
50-
76
50+
77
5151

5252
Or, to find out how many strategies only use 1 turn worth of memory to
5353
make a decision::

0 commit comments

Comments
 (0)