Example #1
0
class TestGame(unittest.TestCase):
    def test_call(self):
        game = games().example()
        self.assertIsInstance(game, axelrod.Game)

    @given(game=games())
    @settings(max_examples=5, max_iterations=20)
    def test_decorator(self, game):
        self.assertIsInstance(game, axelrod.Game)
        r, p, s, t = game.RPST()
        self.assertTrue((2 * r) > (t + s) and (t > r > p > s))

    @given(game=games(prisoners_dilemma=False))
    @settings(max_examples=5, max_iterations=20)
    def test_decorator_unconstrained(self, game):
        self.assertIsInstance(game, axelrod.Game)
Example #2
0
class TestGame(unittest.TestCase):
    def test_default_scores(self):
        expected_scores = {
            (C, D): (0, 5),
            (D, C): (5, 0),
            (D, D): (1, 1),
            (C, C): (3, 3),
        }
        self.assertEqual(axl.Game().scores, expected_scores)

    def test_default_RPST(self):
        expected_values = (3, 1, 0, 5)
        self.assertEqual(axl.Game().RPST(), expected_values)

    def test_default_score(self):
        game = axl.Game()
        self.assertEqual(game.score((C, C)), (3, 3))
        self.assertEqual(game.score((D, D)), (1, 1))
        self.assertEqual(game.score((C, D)), (0, 5))
        self.assertEqual(game.score((D, C)), (5, 0))

    def test_default_equality(self):
        self.assertEqual(axl.Game(), axl.Game())

    def test_not_default_equality(self):
        self.assertEqual(axl.Game(1, 2, 3, 4), axl.Game(1, 2, 3, 4))
        self.assertNotEqual(axl.Game(1, 2, 3, 4), axl.Game(1, 2, 3, 5))
        self.assertNotEqual(axl.Game(1, 2, 3, 4), axl.Game())

    def test_wrong_class_equality(self):
        self.assertNotEqual(axl.Game(), "wrong class")

    @given(r=integers(), p=integers(), s=integers(), t=integers())
    @settings(max_examples=5)
    def test_random_init(self, r, p, s, t):
        """Test init with random scores using the hypothesis library."""
        expected_scores = {
            (C, D): (s, t),
            (D, C): (t, s),
            (D, D): (p, p),
            (C, C): (r, r),
        }
        game = axl.Game(r, s, t, p)
        self.assertEqual(game.scores, expected_scores)

    @given(r=integers(), p=integers(), s=integers(), t=integers())
    @settings(max_examples=5)
    def test_random_RPST(self, r, p, s, t):
        """Test RPST method with random scores using the hypothesis library."""
        game = axl.Game(r, s, t, p)
        self.assertEqual(game.RPST(), (r, p, s, t))

    @given(r=integers(), p=integers(), s=integers(), t=integers())
    @settings(max_examples=5)
    def test_random_score(self, r, p, s, t):
        """Test score method with random scores using the hypothesis library."""
        game = axl.Game(r, s, t, p)
        self.assertEqual(game.score((C, C)), (r, r))
        self.assertEqual(game.score((D, D)), (p, p))
        self.assertEqual(game.score((C, D)), (s, t))
        self.assertEqual(game.score((D, C)), (t, s))

    @given(game=games())
    @settings(max_examples=5)
    def test_random_repr(self, game):
        """Test repr with random scores using the hypothesis library."""
        expected_repr = "Axelrod game: (R,P,S,T) = {}".format(game.RPST())
        self.assertEqual(expected_repr, game.__repr__())
        self.assertEqual(expected_repr, str(game))
Example #3
0
class TestMatch(unittest.TestCase):
    @given(turns=integers(min_value=1, max_value=200), game=games())
    @example(turns=5, game=axelrod.DefaultGame)
    def test_init(self, turns, game):
        p1, p2 = axelrod.Cooperator(), axelrod.Cooperator()
        match = axelrod.Match((p1, p2), turns, game=game)
        self.assertEqual(match.result, [])
        self.assertEqual(match.players, [p1, p2])
        self.assertEqual(match.turns, turns)
        self.assertEqual(match.prob_end, 0)
        self.assertEqual(match.noise, 0)
        self.assertEqual(match.game.RPST(), game.RPST())

        self.assertEqual(match.players[0].match_attributes["length"], turns)
        self.assertEqual(match._cache, {})

    @given(prob_end=floats(min_value=0, max_value=1), game=games())
    def test_init_with_prob_end(self, prob_end, game):
        p1, p2 = axelrod.Cooperator(), axelrod.Cooperator()
        match = axelrod.Match((p1, p2), prob_end=prob_end, game=game)
        self.assertEqual(match.result, [])
        self.assertEqual(match.players, [p1, p2])
        self.assertEqual(match.turns, float("inf"))
        self.assertEqual(match.prob_end, prob_end)
        self.assertEqual(match.noise, 0)
        self.assertEqual(match.game.RPST(), game.RPST())

        self.assertEqual(match.players[0].match_attributes["length"],
                         float("inf"))
        self.assertEqual(match._cache, {})

    @given(
        prob_end=floats(min_value=0, max_value=1),
        turns=integers(min_value=1, max_value=200),
        game=games(),
    )
    def test_init_with_prob_end_and_turns(self, turns, prob_end, game):
        p1, p2 = axelrod.Cooperator(), axelrod.Cooperator()
        match = axelrod.Match((p1, p2),
                              turns=turns,
                              prob_end=prob_end,
                              game=game)
        self.assertEqual(match.result, [])
        self.assertEqual(match.players, [p1, p2])
        self.assertEqual(match.turns, turns)
        self.assertEqual(match.prob_end, prob_end)
        self.assertEqual(match.noise, 0)
        self.assertEqual(match.game.RPST(), game.RPST())

        self.assertEqual(match.players[0].match_attributes["length"],
                         float("inf"))
        self.assertEqual(match._cache, {})

    def test_default_init(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Cooperator()
        match = axelrod.Match((p1, p2))
        self.assertEqual(match.result, [])
        self.assertEqual(match.players, [p1, p2])
        self.assertEqual(match.turns, axelrod.DEFAULT_TURNS)
        self.assertEqual(match.prob_end, 0)
        self.assertEqual(match.noise, 0)
        self.assertEqual(match.game.RPST(), (3, 1, 0, 5))

        self.assertEqual(match.players[0].match_attributes["length"],
                         axelrod.DEFAULT_TURNS)
        self.assertEqual(match._cache, {})

    def test_example_prob_end(self):
        """
        Test that matches have diff length and also that cache has recorded the
        outcomes
        """
        p1, p2 = axelrod.Cooperator(), axelrod.Cooperator()
        match = axelrod.Match((p1, p2), prob_end=.5)
        expected_lengths = [3, 1, 5]
        for seed, expected_length in zip(range(3), expected_lengths):
            axelrod.seed(seed)
            self.assertEqual(match.players[0].match_attributes["length"],
                             float("inf"))
            self.assertEqual(len(match.play()), expected_length)
            self.assertEqual(match.noise, 0)
            self.assertEqual(match.game.RPST(), (3, 1, 0, 5))
        self.assertEqual(len(match._cache), 3)

        for expected_length in expected_lengths:
            self.assertEqual(match._cache[(p1, p2, expected_length)],
                             [(C, C)] * expected_length)

    @given(turns=integers(min_value=1, max_value=200), game=games())
    @example(turns=5, game=axelrod.DefaultGame)
    def test_non_default_attributes(self, turns, game):
        p1, p2 = axelrod.Cooperator(), axelrod.Cooperator()
        match_attributes = {"length": 500, "game": game, "noise": 0.5}
        match = axelrod.Match((p1, p2),
                              turns,
                              game=game,
                              match_attributes=match_attributes)
        self.assertEqual(match.players[0].match_attributes["length"], 500)
        self.assertEqual(match.players[0].match_attributes["noise"], 0.5)

    @given(turns=integers(min_value=1, max_value=200))
    @example(turns=5)
    def test_len(self, turns):
        p1, p2 = axelrod.Cooperator(), axelrod.Cooperator()
        match = axelrod.Match((p1, p2), turns)
        self.assertEqual(len(match), turns)

    def test_len_error(self):
        """
        Length is not defined if it is infinite.
        """
        p1, p2 = axelrod.Cooperator(), axelrod.Cooperator()
        match = axelrod.Match((p1, p2), prob_end=.5)
        with self.assertRaises(TypeError):
            len(match)

    @given(p=floats(min_value=0, max_value=1))
    def test_stochastic(self, p):

        assume(0 < p < 1)

        p1, p2 = axelrod.Cooperator(), axelrod.Cooperator()
        match = axelrod.Match((p1, p2), 5)
        self.assertFalse(match._stochastic)

        match = axelrod.Match((p1, p2), 5, noise=p)
        self.assertTrue(match._stochastic)

        p1 = axelrod.Random()
        match = axelrod.Match((p1, p2), 5)
        self.assertTrue(match._stochastic)

    @given(p=floats(min_value=0, max_value=1))
    def test_cache_update_required(self, p):

        assume(0 < p < 1)

        p1, p2 = axelrod.Cooperator(), axelrod.Cooperator()
        match = axelrod.Match((p1, p2), 5, noise=p)
        self.assertFalse(match._cache_update_required)

        cache = DeterministicCache()
        cache.mutable = False
        match = axelrod.Match((p1, p2), 5, deterministic_cache=cache)
        self.assertFalse(match._cache_update_required)

        match = axelrod.Match((p1, p2), 5)
        self.assertTrue(match._cache_update_required)

        p1 = axelrod.Random()
        match = axelrod.Match((p1, p2), 5)
        self.assertFalse(match._cache_update_required)

    def test_play(self):
        cache = DeterministicCache()
        players = (axelrod.Cooperator(), axelrod.Defector())
        match = axelrod.Match(players, 3, deterministic_cache=cache)
        expected_result = [(C, D), (C, D), (C, D)]
        self.assertEqual(match.play(), expected_result)
        self.assertEqual(cache[(axelrod.Cooperator(), axelrod.Defector(), 3)],
                         expected_result)

        # a deliberately incorrect result so we can tell it came from the cache
        expected_result = [(C, C), (D, D), (D, C)]
        cache[(axelrod.Cooperator(), axelrod.Defector(), 3)] = expected_result
        match = axelrod.Match(players, 3, deterministic_cache=cache)
        self.assertEqual(match.play(), expected_result)

    def test_scores(self):
        player1 = axelrod.TitForTat()
        player2 = axelrod.Defector()
        match = axelrod.Match((player1, player2), 3)
        self.assertEqual(match.scores(), [])
        match.play()
        self.assertEqual(match.scores(), [(0, 5), (1, 1), (1, 1)])

    def test_final_score(self):
        player1 = axelrod.TitForTat()
        player2 = axelrod.Defector()

        match = axelrod.Match((player1, player2), 3)
        self.assertEqual(match.final_score(), None)
        match.play()
        self.assertEqual(match.final_score(), (2, 7))

        match = axelrod.Match((player2, player1), 3)
        self.assertEqual(match.final_score(), None)
        match.play()
        self.assertEqual(match.final_score(), (7, 2))

    def test_final_score_per_turn(self):
        turns = 3
        player1 = axelrod.TitForTat()
        player2 = axelrod.Defector()

        match = axelrod.Match((player1, player2), turns)
        self.assertEqual(match.final_score_per_turn(), None)
        match.play()
        self.assertEqual(match.final_score_per_turn(), (2 / turns, 7 / turns))

        match = axelrod.Match((player2, player1), turns)
        self.assertEqual(match.final_score_per_turn(), None)
        match.play()
        self.assertEqual(match.final_score_per_turn(), (7 / turns, 2 / turns))

    def test_winner(self):
        player1 = axelrod.TitForTat()
        player2 = axelrod.Defector()

        match = axelrod.Match((player1, player2), 3)
        self.assertEqual(match.winner(), None)
        match.play()
        self.assertEqual(match.winner(), player2)

        match = axelrod.Match((player2, player1), 3)
        self.assertEqual(match.winner(), None)
        match.play()
        self.assertEqual(match.winner(), player2)

        player1 = axelrod.Defector()
        match = axelrod.Match((player1, player2), 3)
        self.assertEqual(match.winner(), None)
        match.play()
        self.assertEqual(match.winner(), False)

    def test_cooperation(self):
        turns = 3
        player1 = axelrod.Cooperator()
        player2 = axelrod.Alternator()

        match = axelrod.Match((player1, player2), turns)
        self.assertEqual(match.cooperation(), None)
        match.play()
        self.assertEqual(match.cooperation(), (3, 2))

        player1 = axelrod.Alternator()
        player2 = axelrod.Defector()

        match = axelrod.Match((player1, player2), turns)
        self.assertEqual(match.cooperation(), None)
        match.play()
        self.assertEqual(match.cooperation(), (2, 0))

    def test_normalised_cooperation(self):
        turns = 3
        player1 = axelrod.Cooperator()
        player2 = axelrod.Alternator()

        match = axelrod.Match((player1, player2), turns)
        self.assertEqual(match.normalised_cooperation(), None)
        match.play()
        self.assertEqual(match.normalised_cooperation(),
                         (3 / turns, 2 / turns))

        player1 = axelrod.Alternator()
        player2 = axelrod.Defector()

        match = axelrod.Match((player1, player2), turns)
        self.assertEqual(match.normalised_cooperation(), None)
        match.play()
        self.assertEqual(match.normalised_cooperation(),
                         (2 / turns, 0 / turns))

    def test_state_distribution(self):
        turns = 3
        player1 = axelrod.Cooperator()
        player2 = axelrod.Alternator()

        match = axelrod.Match((player1, player2), turns)
        self.assertEqual(match.state_distribution(), None)

        match.play()
        expected = Counter({(C, C): 2, (C, D): 1})
        self.assertEqual(match.state_distribution(), expected)

        player1 = axelrod.Alternator()
        player2 = axelrod.Defector()

        match = axelrod.Match((player1, player2), turns)
        self.assertEqual(match.state_distribution(), None)

        match.play()
        expected = Counter({(C, D): 2, (D, D): 1})
        self.assertEqual(match.state_distribution(), expected)

    def test_normalised_state_distribution(self):
        turns = 3
        player1 = axelrod.Cooperator()
        player2 = axelrod.Alternator()

        match = axelrod.Match((player1, player2), turns)
        self.assertEqual(match.normalised_state_distribution(), None)

        match.play()
        expected = Counter({(C, C): 2 / turns, (C, D): 1 / turns})
        self.assertEqual(match.normalised_state_distribution(), expected)

        player1 = axelrod.Alternator()
        player2 = axelrod.Defector()

        match = axelrod.Match((player1, player2), turns)
        self.assertEqual(match.normalised_state_distribution(), None)

        match.play()
        expected = Counter({(C, D): 2 / turns, (D, D): 1 / turns})
        self.assertEqual(match.normalised_state_distribution(), expected)

    def test_sparklines(self):
        players = (axelrod.Cooperator(), axelrod.Alternator())
        match = axelrod.Match(players, 4)
        match.play()
        expected_sparklines = "████\n█ █ "
        self.assertEqual(match.sparklines(), expected_sparklines)
        expected_sparklines = "XXXX\nXYXY"
        self.assertEqual(match.sparklines("X", "Y"), expected_sparklines)
Example #4
0
 def test_call(self):
     game = games().example()
     self.assertIsInstance(game, axelrod.Game)
Example #5
0
 def test_call(self):
     game = games().example()
     self.assertIsInstance(game, axelrod.Game)
Example #6
0
class TestMatch(unittest.TestCase):
    @given(turns=integers(min_value=1, max_value=200), game=games())
    @example(turns=5, game=axelrod.DefaultGame)
    def test_init(self, turns, game):
        p1, p2 = axelrod.Cooperator(), axelrod.Cooperator()
        match = axelrod.Match((p1, p2), turns, game=game)
        self.assertEqual(match.result, [])
        self.assertEqual(match.players, [p1, p2])
        self.assertEqual(match.players[0].match_attributes['length'], turns)
        self.assertEqual(match._cache_key,
                         (axelrod.Cooperator, axelrod.Cooperator, turns))
        self.assertEqual(match.turns, turns)
        self.assertEqual(match._cache, {})
        self.assertEqual(match.noise, 0)
        self.assertEqual(match.game.RPST(), game.RPST())

    @given(turns=integers(min_value=1, max_value=200), game=games())
    @example(turns=5, game=axelrod.DefaultGame)
    def test_non_default_attributes(self, turns, game):
        p1, p2 = axelrod.Cooperator(), axelrod.Cooperator()
        match_attributes = {'length': 500, 'game': game, 'noise': 0.5}
        match = axelrod.Match((p1, p2),
                              turns,
                              game=game,
                              match_attributes=match_attributes)
        self.assertEqual(match.players[0].match_attributes['length'], 500)
        self.assertEqual(match.players[0].match_attributes['noise'], 0.5)

    @given(turns=integers(min_value=1, max_value=200))
    @example(turns=5)
    def test_len(self, turns):
        p1, p2 = axelrod.Cooperator(), axelrod.Cooperator()
        match = axelrod.Match((p1, p2), turns)
        self.assertEqual(len(match), turns)

    @given(p=floats(min_value=0, max_value=1), rm=random_module())
    def test_stochastic(self, p, rm):

        assume(0 < p < 1)

        p1, p2 = axelrod.Cooperator(), axelrod.Cooperator()
        match = axelrod.Match((p1, p2), 5)
        self.assertFalse(match._stochastic)

        match = axelrod.Match((p1, p2), 5, noise=p)
        self.assertTrue(match._stochastic)

        p1 = axelrod.Random()
        match = axelrod.Match((p1, p2), 5)
        self.assertTrue(match._stochastic)

    @given(p=floats(min_value=0, max_value=1), rm=random_module())
    def test_cache_update_required(self, p, rm):

        assume(0 < p < 1)

        p1, p2 = axelrod.Cooperator(), axelrod.Cooperator()
        match = axelrod.Match((p1, p2), 5, noise=p)
        self.assertFalse(match._cache_update_required)

        cache = DeterministicCache()
        cache.mutable = False
        match = axelrod.Match((p1, p2), 5, deterministic_cache=cache)
        self.assertFalse(match._cache_update_required)

        match = axelrod.Match((p1, p2), 5)
        self.assertTrue(match._cache_update_required)

        p1 = axelrod.Random()
        match = axelrod.Match((p1, p2), 5)
        self.assertFalse(match._cache_update_required)

    def test_play(self):
        cache = DeterministicCache()
        players = (axelrod.Cooperator(), axelrod.Defector())
        match = axelrod.Match(players, 3, deterministic_cache=cache)
        expected_result = [(C, D), (C, D), (C, D)]
        self.assertEqual(match.play(), expected_result)
        self.assertEqual(cache[(axelrod.Cooperator, axelrod.Defector, 3)],
                         expected_result)

        # a deliberately incorrect result so we can tell it came from the cache
        expected_result = [(C, C), (D, D), (D, C)]
        cache[(axelrod.Cooperator, axelrod.Defector, 3)] = expected_result
        match = axelrod.Match(players, 3, deterministic_cache=cache)
        self.assertEqual(match.play(), expected_result)

    def test_scores(self):
        player1 = axelrod.TitForTat()
        player2 = axelrod.Defector()
        match = axelrod.Match((player1, player2), 3)
        self.assertEqual(match.scores(), [])
        match.play()
        self.assertEqual(match.scores(), [(0, 5), (1, 1), (1, 1)])

    def test_final_score(self):
        player1 = axelrod.TitForTat()
        player2 = axelrod.Defector()

        match = axelrod.Match((player1, player2), 3)
        self.assertEqual(match.final_score(), None)
        match.play()
        self.assertEqual(match.final_score(), (2, 7))

        match = axelrod.Match((player2, player1), 3)
        self.assertEqual(match.final_score(), None)
        match.play()
        self.assertEqual(match.final_score(), (7, 2))

    def test_final_score_per_turn(self):
        turns = 3
        player1 = axelrod.TitForTat()
        player2 = axelrod.Defector()

        match = axelrod.Match((player1, player2), turns)
        self.assertEqual(match.final_score_per_turn(), None)
        match.play()
        self.assertEqual(match.final_score_per_turn(),
                         (2 / float(turns), 7 / float(turns)))

        match = axelrod.Match((player2, player1), turns)
        self.assertEqual(match.final_score_per_turn(), None)
        match.play()
        self.assertEqual(match.final_score_per_turn(),
                         (7 / float(turns), 2 / float(turns)))

    def test_winner(self):
        player1 = axelrod.TitForTat()
        player2 = axelrod.Defector()

        match = axelrod.Match((player1, player2), 3)
        self.assertEqual(match.winner(), None)
        match.play()
        self.assertEqual(match.winner(), player2)

        match = axelrod.Match((player2, player1), 3)
        self.assertEqual(match.winner(), None)
        match.play()
        self.assertEqual(match.winner(), player2)

        player1 = axelrod.Defector()
        match = axelrod.Match((player1, player2), 3)
        self.assertEqual(match.winner(), None)
        match.play()
        self.assertEqual(match.winner(), False)

    def test_cooperation(self):
        turns = 3
        player1 = axelrod.Cooperator()
        player2 = axelrod.Alternator()

        match = axelrod.Match((player1, player2), turns)
        self.assertEqual(match.cooperation(), None)
        match.play()
        self.assertEqual(match.cooperation(), (3, 2))

        player1 = axelrod.Alternator()
        player2 = axelrod.Defector()

        match = axelrod.Match((player1, player2), turns)
        self.assertEqual(match.cooperation(), None)
        match.play()
        self.assertEqual(match.cooperation(), (2, 0))

    def test_normalised_cooperation(self):
        turns = 3
        player1 = axelrod.Cooperator()
        player2 = axelrod.Alternator()

        match = axelrod.Match((player1, player2), turns)
        self.assertEqual(match.normalised_cooperation(), None)
        match.play()
        self.assertEqual(match.normalised_cooperation(),
                         (3 / float(turns), 2 / float(turns)))

        player1 = axelrod.Alternator()
        player2 = axelrod.Defector()

        match = axelrod.Match((player1, player2), turns)
        self.assertEqual(match.normalised_cooperation(), None)
        match.play()
        self.assertEqual(match.normalised_cooperation(),
                         (2 / float(turns), 0 / float(turns)))

    def test_sparklines(self):
        players = (axelrod.Cooperator(), axelrod.Alternator())
        match = axelrod.Match(players, 4)
        match.play()
        expected_sparklines = u'████\n█ █ '
        self.assertEqual(match.sparklines(), expected_sparklines)
        expected_sparklines = u'XXXX\nXYXY'
        self.assertEqual(match.sparklines('X', 'Y'), expected_sparklines)
Example #7
0
class TestMatch(unittest.TestCase):
    @given(turns=integers(min_value=1, max_value=200), game=games())
    @example(turns=5, game=axl.DefaultGame)
    def test_init(self, turns, game):
        p1, p2 = axl.Cooperator(), axl.Cooperator()
        match = axl.Match((p1, p2), turns, game=game)
        self.assertEqual(match.result, [])
        self.assertEqual(match.players, [p1, p2])
        self.assertEqual(match.turns, turns)
        self.assertEqual(match.prob_end, 0)
        self.assertEqual(match.noise, 0)
        self.assertEqual(match.game.RPST(), game.RPST())

        self.assertEqual(match.players[0].match_attributes["length"], turns)
        self.assertEqual(match._cache, {})

    @given(prob_end=floats(min_value=0, max_value=1), game=games())
    def test_init_with_prob_end(self, prob_end, game):
        p1, p2 = axl.Cooperator(), axl.Cooperator()
        match = axl.Match((p1, p2), prob_end=prob_end, game=game)
        self.assertEqual(match.result, [])
        self.assertEqual(match.players, [p1, p2])
        self.assertEqual(match.turns, float("inf"))
        self.assertEqual(match.prob_end, prob_end)
        self.assertEqual(match.noise, 0)
        self.assertEqual(match.game.RPST(), game.RPST())

        self.assertEqual(match.players[0].match_attributes["length"],
                         float("inf"))
        self.assertEqual(match._cache, {})

    @given(
        prob_end=floats(min_value=0, max_value=1),
        turns=integers(min_value=1, max_value=200),
        game=games(),
    )
    def test_init_with_prob_end_and_turns(self, turns, prob_end, game):
        p1, p2 = axl.Cooperator(), axl.Cooperator()
        match = axl.Match((p1, p2), turns=turns, prob_end=prob_end, game=game)
        self.assertEqual(match.result, [])
        self.assertEqual(match.players, [p1, p2])
        self.assertEqual(match.turns, turns)
        self.assertEqual(match.prob_end, prob_end)
        self.assertEqual(match.noise, 0)
        self.assertEqual(match.game.RPST(), game.RPST())

        self.assertEqual(match.players[0].match_attributes["length"],
                         float("inf"))
        self.assertEqual(match._cache, {})

    def test_default_init(self):
        p1, p2 = axl.Cooperator(), axl.Cooperator()
        match = axl.Match((p1, p2))
        self.assertEqual(match.result, [])
        self.assertEqual(match.players, [p1, p2])
        self.assertEqual(match.turns, axl.DEFAULT_TURNS)
        self.assertEqual(match.prob_end, 0)
        self.assertEqual(match.noise, 0)
        self.assertEqual(match.game.RPST(), (3, 1, 0, 5))

        self.assertEqual(match.players[0].match_attributes["length"],
                         axl.DEFAULT_TURNS)
        self.assertEqual(match._cache, {})

    def test_example_prob_end(self):
        """
        Test that matches have diff length and also that cache has recorded the
        outcomes
        """
        p1, p2 = axl.Cooperator(), axl.Cooperator()
        expected_lengths = [2, 1, 1]
        for seed, expected_length in zip(range(3), expected_lengths):
            match = axl.Match((p1, p2), prob_end=0.5, seed=seed)
            self.assertEqual(match.players[0].match_attributes["length"],
                             float("inf"))
            self.assertEqual(len(match.play()), expected_length)
            self.assertEqual(match.noise, 0)
            self.assertEqual(match.game.RPST(), (3, 1, 0, 5))
        self.assertEqual(len(match._cache), 1)
        self.assertEqual(match._cache[(p1, p2)], [(C, C)])

    @given(turns=integers(min_value=1, max_value=200), game=games())
    @example(turns=5, game=axl.DefaultGame)
    def test_non_default_attributes(self, turns, game):
        p1, p2 = axl.Cooperator(), axl.Cooperator()
        match_attributes = {"length": 500, "game": game, "noise": 0.5}
        match = axl.Match((p1, p2),
                          turns,
                          game=game,
                          match_attributes=match_attributes)
        self.assertEqual(match.players[0].match_attributes["length"], 500)
        self.assertEqual(match.players[0].match_attributes["noise"], 0.5)

    @given(turns=integers(min_value=1, max_value=200))
    @example(turns=5)
    def test_len(self, turns):
        p1, p2 = axl.Cooperator(), axl.Cooperator()
        match = axl.Match((p1, p2), turns)
        self.assertEqual(len(match), turns)

    def test_len_error(self):
        """
        Length is not defined if it is infinite.
        """
        p1, p2 = axl.Cooperator(), axl.Cooperator()
        match = axl.Match((p1, p2), prob_end=0.5)
        with self.assertRaises(TypeError):
            len(match)

    @given(p=floats(min_value=1e-10, max_value=1 - 1e-10))
    def test_stochastic(self, p):
        p1, p2 = axl.Cooperator(), axl.Cooperator()
        match = axl.Match((p1, p2), 5)
        self.assertFalse(match._stochastic)

        match = axl.Match((p1, p2), 5, noise=p)
        self.assertTrue(match._stochastic)

        p1 = axl.Random()
        match = axl.Match((p1, p2), 5)
        self.assertTrue(match._stochastic)

    @given(p=floats(min_value=1e-10, max_value=1 - 1e-10))
    def test_cache_update_required(self, p):
        p1, p2 = axl.Cooperator(), axl.Cooperator()
        match = axl.Match((p1, p2), 5, noise=p)
        self.assertFalse(match._cache_update_required)

        cache = DeterministicCache()
        cache.mutable = False
        match = axl.Match((p1, p2), 5, deterministic_cache=cache)
        self.assertFalse(match._cache_update_required)

        match = axl.Match((p1, p2), 5)
        self.assertTrue(match._cache_update_required)

        p1 = axl.Random()
        match = axl.Match((p1, p2), 5)
        self.assertFalse(match._cache_update_required)

    def test_play(self):
        cache = DeterministicCache()
        players = (axl.Cooperator(), axl.Defector())
        match = axl.Match(players, 3, deterministic_cache=cache)
        expected_result = [(C, D), (C, D), (C, D)]
        self.assertEqual(match.play(), expected_result)
        self.assertEqual(cache[(axl.Cooperator(), axl.Defector())],
                         expected_result)

        # a deliberately incorrect result so we can tell it came from the cache
        expected_result = [(C, C), (D, D), (D, C), (C, C), (C, D)]
        cache[(axl.Cooperator(), axl.Defector())] = expected_result
        match = axl.Match(players, 3, deterministic_cache=cache)
        self.assertEqual(match.play(), expected_result[:3])

    def test_cache_grows(self):
        """
        We want to make sure that if we try to use the cache for more turns than
        what is stored, then it will instead regenerate the result and overwrite
        the cache.
        """
        cache = DeterministicCache()
        players = (axl.Cooperator(), axl.Defector())
        match = axl.Match(players, 3, deterministic_cache=cache)
        expected_result_5_turn = [(C, D), (C, D), (C, D), (C, D), (C, D)]
        expected_result_3_turn = [(C, D), (C, D), (C, D)]
        self.assertEqual(match.play(), expected_result_3_turn)
        match.turns = 5
        self.assertEqual(match.play(), expected_result_5_turn)
        # The cache should now hold the 5-turn result..
        self.assertEqual(cache[(axl.Cooperator(), axl.Defector())],
                         expected_result_5_turn)

    def test_cache_doesnt_shrink(self):
        """
        We want to make sure that when we access the cache looking for fewer
        turns than what is stored, then it will not overwrite the cache with the
        shorter result.
        """
        cache = DeterministicCache()
        players = (axl.Cooperator(), axl.Defector())
        match = axl.Match(players, 5, deterministic_cache=cache)
        expected_result_5_turn = [(C, D), (C, D), (C, D), (C, D), (C, D)]
        expected_result_3_turn = [(C, D), (C, D), (C, D)]
        self.assertEqual(match.play(), expected_result_5_turn)
        match.turns = 3
        self.assertEqual(match.play(), expected_result_3_turn)
        # The cache should still hold the 5.
        self.assertEqual(cache[(axl.Cooperator(), axl.Defector())],
                         expected_result_5_turn)

    def test_scores(self):
        player1 = axl.TitForTat()
        player2 = axl.Defector()
        match = axl.Match((player1, player2), 3)
        self.assertEqual(match.scores(), [])
        match.play()
        self.assertEqual(match.scores(), [(0, 5), (1, 1), (1, 1)])

    def test_final_score(self):
        player1 = axl.TitForTat()
        player2 = axl.Defector()

        match = axl.Match((player1, player2), 3)
        self.assertEqual(match.final_score(), None)
        match.play()
        self.assertEqual(match.final_score(), (2, 7))

        match = axl.Match((player2, player1), 3)
        self.assertEqual(match.final_score(), None)
        match.play()
        self.assertEqual(match.final_score(), (7, 2))

    def test_final_score_per_turn(self):
        turns = 3
        player1 = axl.TitForTat()
        player2 = axl.Defector()

        match = axl.Match((player1, player2), turns)
        self.assertEqual(match.final_score_per_turn(), None)
        match.play()
        self.assertEqual(match.final_score_per_turn(), (2 / turns, 7 / turns))

        match = axl.Match((player2, player1), turns)
        self.assertEqual(match.final_score_per_turn(), None)
        match.play()
        self.assertEqual(match.final_score_per_turn(), (7 / turns, 2 / turns))

    def test_winner(self):
        player1 = axl.TitForTat()
        player2 = axl.Defector()

        match = axl.Match((player1, player2), 3)
        self.assertEqual(match.winner(), None)
        match.play()
        self.assertEqual(match.winner(), player2)

        match = axl.Match((player2, player1), 3)
        self.assertEqual(match.winner(), None)
        match.play()
        self.assertEqual(match.winner(), player2)

        player1 = axl.Defector()
        match = axl.Match((player1, player2), 3)
        self.assertEqual(match.winner(), None)
        match.play()
        self.assertEqual(match.winner(), False)

    def test_cooperation(self):
        turns = 3
        player1 = axl.Cooperator()
        player2 = axl.Alternator()

        match = axl.Match((player1, player2), turns)
        self.assertEqual(match.cooperation(), None)
        match.play()
        self.assertEqual(match.cooperation(), (3, 2))

        player1 = axl.Alternator()
        player2 = axl.Defector()

        match = axl.Match((player1, player2), turns)
        self.assertEqual(match.cooperation(), None)
        match.play()
        self.assertEqual(match.cooperation(), (2, 0))

    def test_normalised_cooperation(self):
        turns = 3
        player1 = axl.Cooperator()
        player2 = axl.Alternator()

        match = axl.Match((player1, player2), turns)
        self.assertEqual(match.normalised_cooperation(), None)
        match.play()
        self.assertEqual(match.normalised_cooperation(),
                         (3 / turns, 2 / turns))

        player1 = axl.Alternator()
        player2 = axl.Defector()

        match = axl.Match((player1, player2), turns)
        self.assertEqual(match.normalised_cooperation(), None)
        match.play()
        self.assertEqual(match.normalised_cooperation(),
                         (2 / turns, 0 / turns))

    def test_state_distribution(self):
        turns = 3
        player1 = axl.Cooperator()
        player2 = axl.Alternator()

        match = axl.Match((player1, player2), turns)
        self.assertEqual(match.state_distribution(), None)

        match.play()
        expected = Counter({(C, C): 2, (C, D): 1})
        self.assertEqual(match.state_distribution(), expected)

        player1 = axl.Alternator()
        player2 = axl.Defector()

        match = axl.Match((player1, player2), turns)
        self.assertEqual(match.state_distribution(), None)

        match.play()
        expected = Counter({(C, D): 2, (D, D): 1})
        self.assertEqual(match.state_distribution(), expected)

    def test_normalised_state_distribution(self):
        turns = 3
        player1 = axl.Cooperator()
        player2 = axl.Alternator()

        match = axl.Match((player1, player2), turns)
        self.assertEqual(match.normalised_state_distribution(), None)

        match.play()
        expected = Counter({(C, C): 2 / turns, (C, D): 1 / turns})
        self.assertEqual(match.normalised_state_distribution(), expected)

        player1 = axl.Alternator()
        player2 = axl.Defector()

        match = axl.Match((player1, player2), turns)
        self.assertEqual(match.normalised_state_distribution(), None)

        match.play()
        expected = Counter({(C, D): 2 / turns, (D, D): 1 / turns})
        self.assertEqual(match.normalised_state_distribution(), expected)

    def test_sparklines(self):
        players = (axl.Cooperator(), axl.Alternator())
        match = axl.Match(players, 4)
        match.play()
        expected_sparklines = "████\n█ █ "
        self.assertEqual(match.sparklines(), expected_sparklines)
        expected_sparklines = "XXXX\nXYXY"
        self.assertEqual(match.sparklines("X", "Y"), expected_sparklines)