@@ -384,18 +384,27 @@ def strategy(self, opponent: Player) -> Action:
384384 return move
385385
386386
387- class Gradual (Player ):
387+ class OriginalGradual (Player ):
388388 """
389389 A player that punishes defections with a growing number of defections
390- but after punishing enters a calming state and cooperates no matter what
391- the opponent does for two rounds.
390+ but after punishing for `punishment_limit` number of times enters a calming
391+ state and cooperates no matter what the opponent does for two rounds.
392+
393+ The `punishment_limit` is incremented whenever the opponent defects and the
394+ strategy is not in either calming or punishing state.
395+
396+ Note that `Gradual` appears in [CRISTAL-SMAC2018]_ however that version of
397+ `Gradual` does not give the results reported in [Beaufils1997]_ which is the
398+ paper that first introduced the strategy. For a longer discussion of this
399+ see: https://github.com/Axelrod-Python/Axelrod/issues/1294. This is why this
400+ strategy has been renamed to `OriginalGradual`.
392401
393402 Names:
394403
395404 - Gradual: [Beaufils1997]_
396405 """
397406
398- name = "Gradual"
407+ name = "Original Gradual"
399408 classifier = {
400409 "memory_depth" : float ("inf" ),
401410 "stochastic" : False ,
@@ -439,6 +448,67 @@ def strategy(self, opponent: Player) -> Action:
439448 return C
440449
441450
451+ class Gradual (Player ):
452+ """
453+ Similar to OriginalGradual, this is a player that punishes defections with a
454+ growing number of defections but after punishing for `punishment_limit`
455+ number of times enters a calming state and cooperates no matter what the
456+ opponent does for two rounds.
457+
458+ This version of Gradual is an update of `OriginalGradual` and the difference
459+ is that the `punishment_limit` is incremented whenever the opponent defects
460+ (regardless of the state of the player).
461+
462+ Note that this version of `Gradual` appears in [CRISTAL-SMAC2018]_ however
463+ this version of
464+ `Gradual` does not give the results reported in [Beaufils1997]_ which is the
465+ paper that first introduced the strategy. For a longer discussion of this
466+ see: https://github.com/Axelrod-Python/Axelrod/issues/1294.
467+
468+ This version is based on https://github.com/cristal-smac/ipd/blob/master/src/strategies.py#L224
469+
470+ Names:
471+
472+ - Gradual: [CRISTAL-SMAC2018]_
473+ """
474+
475+ name = "Gradual"
476+ classifier = {
477+ "memory_depth" : float ("inf" ),
478+ "stochastic" : False ,
479+ "makes_use_of" : set (),
480+ "long_run_time" : False ,
481+ "inspects_source" : False ,
482+ "manipulates_source" : False ,
483+ "manipulates_state" : False ,
484+ }
485+
486+ def __init__ (self ) -> None :
487+
488+ super ().__init__ ()
489+ self .calm_count = 0
490+ self .punish_count = 0
491+
492+ def strategy (self , opponent : Player ) -> Action :
493+
494+ if len (self .history ) == 0 :
495+ return C
496+
497+ if self .punish_count > 0 :
498+ self .punish_count -= 1
499+ return D
500+
501+ if self .calm_count > 0 :
502+ self .calm_count -= 1
503+ return C
504+
505+ if opponent .history [- 1 ] == D :
506+ self .punish_count = opponent .defections - 1
507+ self .calm_count = 2
508+ return D
509+ return C
510+
511+
442512@TrackHistoryTransformer (name_prefix = None )
443513class ContriteTitForTat (Player ):
444514 """
0 commit comments