def test_next_state_from_action_creates_deep_copy(self):
     tiles_by_player = [
             [{0}, {1, 2}, {1, 5}, {6}, {5, 6}, {4, 6}], 
             [{5}, {2, 5}, {0, 5}, {1, 3}, {2, 4}, {2}, {3, 5}], 
             [{4}, {3}, {4, 5}, {0, 1}, {0, 6}, {1, 6}, {0, 2}], 
             [{3, 4}, {0, 3}, {2, 6}, {1, 4}, {0, 4}, {3, 6}, {1}]
             ]
     state = DominoState( 1,{
         'tiles_by_player':copy.deepcopy(tiles_by_player),
         'suits_at_ends':{2,3}
     })
     next_state = state.next_state_from_action(DominoAction(1, {2,5},2))
     next_state._tiles_by_player[0].remove({0})
     self.assertEqual(tiles_by_player, state._tiles_by_player)
     self.assertIn({0}, state._tiles_by_player[0])
     self.assertNotIn({0}, next_state._tiles_by_player[0])
     self.assertIn({2,5}, state._tiles_by_player[1])
     self.assertNotIn({2,5}, next_state._tiles_by_player[1])
 def test_next_state_from_action(self):
     state = DominoState( 1,{
         'tiles_by_player':[
             [{0}, {1, 2}, {1, 5}, {6}, {5, 6}, {4, 6}], 
             [{5}, {2, 5}, {0, 5}, {1, 3}, {2, 4}, {2}, {3, 5}], 
             [{4}, {3}, {4, 5}, {0, 1}, {0, 6}, {1, 6}, {0, 2}], 
             [{3, 4}, {0, 3}, {2, 6}, {1, 4}, {0, 4}, {3, 6}, {1}]
             ],
         'suits_at_ends':{2,3}
     })
     next_state = state.next_state_from_action(DominoAction(1, {2,5}, 2))
     self.assertEqual(next_state._current_player, 2)
     self.assertEqual(next_state._suits_at_ends, {5,3})
     self.assertEqual(next_state._tiles_by_player, [
             [{0}, {1, 2}, {1, 5}, {6}, {5, 6}, {4, 6}], 
             [{5},{0, 5}, {1, 3}, {2, 4}, {2}, {3, 5}], 
             [{4}, {3}, {4, 5}, {0, 1}, {0, 6}, {1, 6}, {0, 2}], 
             [{3, 4}, {0, 3}, {2, 6}, {1, 4}, {0, 4}, {3, 6}, {1}]
     ])
class GameOfDomino(TwoPlayersGame):
    def __init__(self, players):
        self.players = players
        self.nplayer = 1  # player 1 starts
        self._state = DominoState()

    def possible_moves(self):
        return self._state.get_possible_actions()

    def make_move(self, move):
        # self.pile -= int(move) # remove bones.
        self._state = self._state.next_state_from_action(move)

    def win(self):
        #  return self.pile<=0 # opponent took the last bone ?
        winner = self._state.calc_reward()
        team_1 = self._state.team_1
        team_2 = self._state.team_2

        if winner == 0:
            return False

        if winner == team_1 and self.nplayer == 1:
            return True

        if winner == team_2 and self.nplayer == 2:
            return True

        return False

    def is_over(self):
        # return self.win() # Game stops when someone wins.
        return self._state.is_terminal()

    def show(self):
        # print ("%d bones left in the pile" % self.pile)
        print(self._state)

    def scoring(self):
        return 100 if self.win() else 0  # For the AI