@@ -1550,7 +1550,7 @@ def strategy(self, opponent: Player) -> Action:
1550
1550
class Black (Player ):
1551
1551
"""
1552
1552
Strategy submitted to Axelrod's second tournament by Paul E Black (K83R)
1553
- and came in fourteenth in that tournament.
1553
+ and came in fifteenth in that tournament.
1554
1554
1555
1555
The strategy Cooperates for the first five turns. Then it calculates the
1556
1556
number of opponent defects in the last five moves and Cooperates with
@@ -1597,3 +1597,116 @@ def strategy(self, opponent: Player) -> Action:
1597
1597
number_defects = np .sum (did_d (recent_history ))
1598
1598
1599
1599
return random_choice (self .prob_coop [number_defects ])
1600
+
1601
+
1602
+ class RichardHufford (Player ):
1603
+ """
1604
+ Strategy submitted to Axelrod's second tournament by Richard Hufford (K47R)
1605
+ and came in sixteenth in that tournament.
1606
+
1607
+ The strategy tracks opponent "agreements," that is whenever the opponent's
1608
+ previous move is the some as this player's move two turns ago. If the
1609
+ opponent's first move is a Defection, this is counted as a disagreement,
1610
+ and otherwise an agreement. From the agreement counts, two measures are
1611
+ calculated:
1612
+
1613
+ - `proportion_agree`: This is the number of agreements (through opponent's
1614
+ last turn) + 2 divided by the current turn number.
1615
+ - `last_four_num`: The number of agreements in the last four turns. If
1616
+ there have been fewer than four previous turns, then this is number of
1617
+ agreement + (4 - number of past turns).
1618
+
1619
+ We then use these measures to decide how to play, using these rules:
1620
+
1621
+ 1. If `proportion_agree` > 0.9 and `last_four_num` >= 4, then Cooperate.
1622
+ 2. Otherwise if `proportion_agree` >= 0.625 and `last_four_num` >= 2, then
1623
+ Tit-for-Tat.
1624
+ 3. Otherwise, Defect.
1625
+
1626
+ However, if the opponent has Cooperated the last `streak_needed` turns,
1627
+ then the strategy deviates from the usual strategy, and instead Defects.
1628
+ (We call such deviation an "aberration.") In the turn immediately after an
1629
+ aberration, the strategy doesn't override, even if there's a streak of
1630
+ Cooperations. Two turns after an aberration, the strategy: Restarts the
1631
+ Cooperation streak (never looking before this turn); Cooperates; and
1632
+ changes `streak_needed` to:
1633
+
1634
+ floor(20.0 * `num_abb_def` / `num_abb_coop`) + 1
1635
+
1636
+ Here `num_abb_def` is 2 + the number of times that the opponent Defected in
1637
+ the turn after an aberration, and `num_abb_coop` is 2 + the number of times
1638
+ that the opponent Cooperated in response to an aberration.
1639
+
1640
+ Names:
1641
+
1642
+ - RichardHufford: [Axelrod1980b]_
1643
+ """
1644
+
1645
+ name = 'RichardHufford'
1646
+ classifier = {
1647
+ 'memory_depth' : float ("inf" ),
1648
+ 'stochastic' : False ,
1649
+ 'makes_use_of' : set (),
1650
+ 'long_run_time' : False ,
1651
+ 'inspects_source' : False ,
1652
+ 'manipulates_source' : False ,
1653
+ 'manipulates_state' : False
1654
+ }
1655
+
1656
+ def __init__ (self ) -> None :
1657
+ super ().__init__ ()
1658
+ self .num_agreements = 2
1659
+ self .last_four_agreements = [1 ] * 4
1660
+ self .last_four_index = 0
1661
+
1662
+ self .streak_needed = 21
1663
+ self .current_streak = 2
1664
+ self .last_aberration = float ("inf" )
1665
+ self .num_abb_coop = 2
1666
+ self .num_abb_def = 2
1667
+
1668
+ def strategy (self , opponent : Player ) -> Action :
1669
+ turn = len (self .history ) + 1
1670
+ if turn == 1 :
1671
+ return C
1672
+
1673
+ # Check if opponent agreed with us.
1674
+ self .last_four_index = (self .last_four_index + 1 ) % 4
1675
+ me_two_moves_ago = C
1676
+ if turn > 2 :
1677
+ me_two_moves_ago = self .history [- 2 ]
1678
+ if me_two_moves_ago == opponent .history [- 1 ]:
1679
+ self .num_agreements += 1
1680
+ self .last_four_agreements [self .last_four_index ] = 1
1681
+ else :
1682
+ self .last_four_agreements [self .last_four_index ] = 0
1683
+
1684
+ # Check is last_aberration is infinite.
1685
+ # i.e Not an aberration in last two turns.
1686
+ if turn < self .last_aberration :
1687
+ if opponent .history [- 1 ] == C :
1688
+ self .current_streak += 1
1689
+ else :
1690
+ self .current_streak = 0
1691
+ if self .current_streak >= self .streak_needed :
1692
+ self .last_aberration = turn
1693
+ if self .current_streak == self .streak_needed :
1694
+ return D
1695
+ elif turn == self .last_aberration + 2 :
1696
+ self .last_aberration = float ("inf" )
1697
+ if opponent .history [- 1 ] == C :
1698
+ self .num_abb_coop += 1
1699
+ else :
1700
+ self .num_abb_def += 1
1701
+ self .streak_needed = np .floor (20.0 * self .num_abb_def / self .num_abb_coop ) + 1
1702
+ self .current_streak = 0
1703
+ return C
1704
+
1705
+ proportion_agree = self .num_agreements / turn
1706
+ last_four_num = np .sum (self .last_four_agreements )
1707
+ if proportion_agree > 0.9 and last_four_num >= 4 :
1708
+ return C
1709
+ elif proportion_agree >= 0.625 and last_four_num >= 2 :
1710
+ return opponent .history [- 1 ]
1711
+ else :
1712
+ return D
0 commit comments