Skip to content

Commit d238418

Browse files
committed
Implemented strategy Cave (k49r from Axelrod's Second)
1 parent 92b9ee2 commit d238418

File tree

5 files changed

+110
-4
lines changed

5 files changed

+110
-4
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 = np.average(did_d(opponent.history))
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: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,3 +490,55 @@ 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+
random.seed(1)
513+
actions = [(C, D)]
514+
actions += [(C, D), (D, D), (D, D), (C, D), (C, D), (C, D), (D, D),
515+
(D, D), (C, D), (C, D), (D, D), (C, D), (D, D), (C, D),
516+
(C, D), (D, D), (C, D)] # Randomly choose
517+
actions += [(D, D)] * 30 # Defect
518+
self.versus_test(axelrod.Defector(), expected_actions=actions)
519+
520+
# Highly-defective opponent
521+
# It will take until turn 20 to respond decide to repond D to C
522+
opponent_actions = [D] * 16 + [C, C, C, C, C]
523+
almost_defector = axelrod.MockPlayer(actions=opponent_actions)
524+
525+
random.seed(1)
526+
actions = [(C, D)]
527+
actions += [(C, D), (D, D), (D, D), (C, D), (C, D), (C, D), (D, D),
528+
(D, D), (C, D), (C, D), (D, D), (C, D), (D, D), (C, D),
529+
(C, D), (D, C), (C, C)] # Randomly choose
530+
actions += [(C, C)] # Coop for a minute
531+
actions += [(D, C), (D, C)]
532+
self.versus_test(almost_defector, expected_actions=actions)
533+
534+
#Here it will take until turn 40 to detect random and defect
535+
random.seed(2)
536+
actions = [(C, C)]
537+
actions += [(C, D), (D, C), (C, D), (D, C), (C, D), (C, C), (C, D),
538+
(C, C), (C, D), (D, C), (C, D), (D, C), (C, D), (D, C),
539+
(C, D), (C, C), (C, D), (D, C), (C, D), (D, C), (C, D),
540+
(D, C), (C, D), (C, C), (C, D), (C, C), (C, D), (C, C),
541+
(C, D), (D, C), (C, D), (D, C), (C, D), (D, C), (C, D)] #Randomly choose
542+
actions += [(D, C), (C, D), (D, C)] # 17 D have come, so tit for tat for a while
543+
actions += [(D, D), (D, C)] * 100 # Random finally detected
544+
self.versus_test(axelrod.Alternator(), expected_actions=actions)

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/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)