Exemplo n.º 1
0
    def test_get_biggest_non_trump(self):

        game_state = GameState(1)
        game_state.trumps = Card.SUIT_HEARTS
        game_state.lead_card = Card(Card.SUIT_HEARTS, 10)

        card = self.player.get_biggest_non_trump(Card.SUIT_HEARTS,
                                                 game_state.lead_card,
                                                 self.player.hand)

        self.assertEqual(card.value, Card.KING)
        self.assertEqual(card._suit, Card.SUIT_SPADES)

        game_state = GameState(1)
        game_state.trumps = Card.SUIT_SPADES
        game_state.lead_card = Card(Card.SUIT_HEARTS, 10)
        card = self.player.get_biggest_non_trump(Card.SUIT_SPADES,
                                                 game_state.lead_card,
                                                 self.player.hand)
        self.assertEqual(card.value, Card.ACE)
        self.assertEqual(card._suit, Card.SUIT_HEARTS)

        result = self.player.get_biggest_non_trump(Card.SUIT_SPADES,
                                                   game_state.lead_card, [])
        self.assertIsNone(result)
Exemplo n.º 2
0
    def setUp(self) -> None:
        self.map0 = '../game_states/game0_repr.json'
        self.game_state = GameState(self.map0)
        self.ih = InputHandler(self.game_state)

        self.map1 = '../game_states/game1_cake.json'
        self.game_state1 = GameState(self.map1)
        self.ih1 = InputHandler(self.game_state1)
Exemplo n.º 3
0
    def setUp(self) -> None:
        self.map0 = '../game_states/game0_repr.json'
        self.game_state = GameState(self.map0)
        self.ih = InputHandler(self.game_state)

        self.map_two_helmets = '../game_states/game_two_helmets.json'
        self.game_two_helmets = GameState(self.map_two_helmets)
        self.ih_two_helmets = InputHandler(self.game_two_helmets)
Exemplo n.º 4
0
    def __init__(self, AIs, debug = False):
        self.gs = GameState()
        self.turn = random.randint(0, 3)

        self.pgs = []
        for i in range(4):
            self.pgs.append(GameState(self.gs.cards, i))

        self.AIs = AIs
        self.debug = debug
        self.is_game_over = False
        self.score = [0]*4
Exemplo n.º 5
0
	def turn(self, board, state):
		moves = board.getAllMoves(state)
		if not moves:
			return

                # variables for finding the best move for this turn
		board_orig = copy.deepcopy(board.board)
		value_best = -99
		end_best = 0
		start_best = 0
		updateGUI = 0

		# search for the next best move
		random.shuffle(moves)
		for move in moves:
                        board.board = copy.deepcopy(board_orig)
                        
                        end = move.pop()
                        start = move.pop()
                        last_cell = board.board[start.row][start.column]
                        return_code = board.move(start, end, state)
                        self.jumpAgain(board, state, return_code, updateGUI)

                        # now play the other player's move
                        if (state.get_state() == 2):
                                state_other = GameState(GameState.WhitesTurn)
                                self.turn_other(board, state_other)
                        elif (state.get_state() == 1):
                                state_other = GameState(GameState.BlacksTurn)
                                self.turn_other(board, state_other)
                        else:
                                print "Invalid player state"
                        
                        value = board.getValue(state)
                        print value
                        if value > value_best:
                                value_best = value
                                end_best = end
                                start_best = start

                # we found it so actually make the move
                updateGUI = 1
                board.board = copy.deepcopy(board_orig)
                print "CHOOSE THIS MOVE"
                print value_best
                last_cell = board.board[start_best.row][start_best.column]
                return_code = board.move(start, end, state)
		self.checkers.move(start, end, last_cell, return_code)
		self.jumpAgain(board, state, return_code, updateGUI)

		board.printBoard()
		print "AI turn complete"
Exemplo n.º 6
0
    def turn(self, board, state):
        moves = board.getAllMoves(state)
        if not moves:
            return

        # variables for finding the best move for this turn
        board_orig = copy.deepcopy(board.board)
        value_best = -99
        start_best = 0
        updateGUI = 0

        # search for the next best move
        random.shuffle(moves)
        for move in moves:
            board.board = copy.deepcopy(board_orig)

            end = move.pop()
            start = move.pop()
            return_code = board.move(start, end, state)
            self.jumpAgain(board, state, return_code, updateGUI)

            # now play the other player's move
            if (state.get_state() == 2):
                state_other = GameState(GameState.WhitesTurn)
                self.turn_other(board, state_other)
            elif (state.get_state() == 1):
                state_other = GameState(GameState.BlacksTurn)
                self.turn_other(board, state_other)
            else:
                print "Invalid player state"

            value = board.getValue(state)
            print "The value for this board is: ", value
            if value > value_best:
                value_best = value
                start_best = start

        # we found it so actually make the move
        updateGUI = 1
        board.board = copy.deepcopy(board_orig)
        print "Choose the move with this value: ", value_best
        last_cell = board.board[start_best.row][start_best.column]
        return_code = board.move(start, end, state)
        self.checkers.move(start, end, last_cell, return_code)
        # I'd like to refresh the board here
        #self.view.show_board()
        self.jumpAgain(board, state, return_code, updateGUI)

        board.printBoard()
        time.sleep(0.75)
        print "AI turn complete"
Exemplo n.º 7
0
    def __init__(self, player1, player2):
        pygame.init()
        pygame.font.init()
        self.player1 = player1
        self.player2 = player2
        self.neutralPlayer = Player('neutral', 10000000000000, 3, 'Neutrals')

        self.factory1 = UnitFactory(player1, self)
        self.factory2 = UnitFactory(player2, self)
        self.factoryNeutral = UnitFactory(self.neutralPlayer, self)

        self.player1.factory = self.factory1
        self.player2.factory = self.factory2
        self.neutralPlayer.factory = self.factoryNeutral

        self.board = Board(self)

        bw, bh = self.board.real_size_with_offsets()

        self.cpanel = CPanel(self, bw, self.board.top_offset, 400, self.board.real_size_with_offsets()[1])
        self.screen = pygame.display.set_mode((bw + self.cpanel.width, bh))
        self.clock = pygame.time.Clock()

        self.gamestate = GameState(player1, self)

        self.rules = Rules(self)

        self.render_mode = 'normal'

        self.board.generate_neutrals(Rules.NEUTRAL_GENERATING_STRATEGY())
Exemplo n.º 8
0
 def test_returns_whitespace_if_no_characters_left_to_backspace(self):
     helper = GameState("hi")
     helper.process_backspace()
     helper.process_backspace()
     helper.process_backspace()
     process_result = helper.process_backspace()
     self.assertTrue(process_result)
Exemplo n.º 9
0
 def __init__(self, window):
     self.window = window
     self.menu_state = MenuState(self.window)
     self.game_state = GameState(self.window)
     self.score_state = ScoreState(self.window)
     self.current_state = self.menu_state
     self.running = True
Exemplo n.º 10
0
 def automate(self):
     self.root = self.dump()
     for play in self.root.playable(0, self.hands):
         self.root.children[play[0]] = GameState(self.hands, state=copy.deepcopy(self.root.ats), dom_tup=play[0], direction=play[1])
     for key in self.root.children.keys():
         self.recur(self.root.children[key], 1, 27)
     pass
Exemplo n.º 11
0
 def recur(self, parent_state, player, depth):
     if depth < 1:
         return
     if len(parent_state.playable(player, self.hands)) == 0:  # we can add 5 points to the game state by adding score=5 here
         parent_state.children['knock'] = GameState(self.hands,
             state=copy.copy(parent_state.ats),
             turn=(parent_state.ats['TURN'] + 1) % 4,
             score=5 if self.settings.nickel_for_knocking else 0
         )
         self.recur(parent_state.children['knock'], (player + 1) % 4, depth - 1)
     else:
         for play in parent_state.playable(player, self.hands):
             parent_state.children[play] = GameState(self.hands, state=copy.copy(parent_state.ats),
                                                     dom_tup=play[0], direction=play[1])
             self.recur(parent_state.children[play], (player + 1) % 4, depth - 1)
     pass
Exemplo n.º 12
0
 def test_wrong_format(self):
     expected_message = "Failed to parse JSON file: " \
                        "Expecting value: line 1 column 1 (char 0)"
     game_config = "game_wrong_emptyfile.txt"
     with self.assertRaises(GameStateFileException) as e:
         GameState(join(self.parent_path, game_config))
     self.assertEqual(expected_message, str(e.exception))
Exemplo n.º 13
0
def play_game():
    mat_init = add_two(
        add_two([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]))
    # mat_init = [[8, 4, 2, 8], [2, 16, 8, 4], [256, 32, 4, 2], [4, 2, 4, 2]]    # Death matrix for debugging
    # mat_init = [[2,4,32,2],[4,16,512,4],[4,8,128,16],[4,16,8,2]]               # Death matrix for debugging

    state = GameState(mat_init)  # Initialize 2048 grid
    loop_count = 0
    game_over = False  # True if add_two can't add anywhere after moving

    while state.game_state(
    ) == 'not over' and game_over == False:  # Run if the game is not over
        loop_count += 1

        print("Move count: " + str(loop_count))
        print("Points    : " + str(state.point_count))
        print(str(state))

        move = UCT(root_state=state,
                   n_search_path=50,
                   n_search_depth=5,
                   exploration_const=100,
                   verbose=True)

        print("Best Move: " + str(move) + "\n")
        game_over = state.do_move(move)

    print("======================= Game Over =======================")
    print(str(state))
    print(state.game_state())
Exemplo n.º 14
0
def game_main_loop():


    initGameState = GameState()

    # 2 - Initialize the game
    pygame.init()
    width, height = 640, 480
    screen = pygame.display.set_mode((width, height))

    # 3 - Load images
    # player = pygame.image.load("resources/images/dude.png")

    # 4 - keep looping through
    while 1:
        # 5 - clear the screen before drawing it again
        screen.fill(0)
        # 6 - draw the screen elements
        # screen.blit(player, (100, 100))
        # 7 - update the screen
        pygame.display.flip()
        # 8 - loop through the events
        for event in pygame.event.get():
            # check if the event is the X button
            if event.type == pygame.QUIT:
                # if it is quit the game
                pygame.quit()
                exit(0)
Exemplo n.º 15
0
 def test_game0_repr(self):
     game_config = "game0_repr.json"
     try:
         GameState(join(self.parent_path, game_config))
     except GameStateFileException:
         self.assertTrue(False)
     self.assertTrue(True)
Exemplo n.º 16
0
    def __init__(self, saves_path: str, base_path: str, game_xml_path: str,
                 desired_win_size_pixels: Optional[Point],
                 tile_size_pixels: int) -> None:
        # Determine effective window size in both tiles and pixels
        # Initialize the pygame displays
        if desired_win_size_pixels is None:
            screen = pygame.display.set_mode(
                (0, 0), pygame.FULLSCREEN | pygame.NOFRAME
                | pygame.SRCALPHA)  # | pygame.DOUBLEBUF | pygame.HWSURFACE)
            self.win_size_pixels = Point(screen.get_size())
            win_size_tiles = (self.win_size_pixels / tile_size_pixels).floor()
        else:
            win_size_tiles = (desired_win_size_pixels /
                              tile_size_pixels).floor()
            self.win_size_pixels = win_size_tiles * tile_size_pixels
            pygame.display.set_mode(
                self.win_size_pixels.getAsIntTuple(),
                pygame.SRCALPHA)  # | pygame.DOUBLEBUF | pygame.HWSURFACE)

        self.title_image, self.title_music = \
            GameInfo.static_init(base_path, game_xml_path, win_size_tiles, tile_size_pixels)

        self.title_screen('Loading...')

        self.game_state = GameState(saves_path, base_path, game_xml_path,
                                    win_size_tiles, tile_size_pixels)
        self.gde = GameDialogEvaluator(self.game_state.game_info,
                                       self.game_state)
        self.gde.update_default_dialog_font_color()
Exemplo n.º 17
0
 def play(self, game_state, possible_moves):
     if self.is_ai_player:
         best_score = -1000000
         best_move = None
         for move in possible_moves:
             next_state = GameState()
             fogged_move = Move(
                 game_state.generate_fog_of_war_state(),
                 [move.from_row_col[0], move.from_row_col[1]],
                 [move.to_row_col[0], move.to_row_col[1]])
             next_state.set_from_move(fogged_move)
             move_score = h(next_state, self.heuristic_weights)
             if move_score > best_score:
                 best_score = move_score
                 best_move = move
         return best_move
     else:
         game_state.generate_fog_of_war_state().print_board()
         print("Select a move: ")
         for i in range(len(possible_moves)):
             print(
                 str(i) + ': ' + GameState.row_col_to_chess_position_str(
                     possible_moves[i].from_row_col[0],
                     possible_moves[i].from_row_col[1]) + ' -> ' +
                 GameState.row_col_to_chess_position_str(
                     possible_moves[i].to_row_col[0],
                     possible_moves[i].to_row_col[1]))
         move_index = int(input())
         return possible_moves[move_index]
Exemplo n.º 18
0
    def __init__(self, numHumans, numComps):
        self.players = []
        cardIds = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
        r.shuffle(cardIds)
        self.startingDeck = [
           Gaurd(cardIds[0]), Gaurd(cardIds[1]), Gaurd(cardIds[2]), Gaurd(cardIds[3]), Gaurd(cardIds[4]),
           Priest(cardIds[5]), Priest(cardIds[6]),
           Baron(cardIds[7]), Baron(cardIds[8]),
           Handmaid(cardIds[9]), Handmaid(cardIds[10]),
           Prince(cardIds[11]), Prince(cardIds[12]),
           King(cardIds[13]),
           Countess(cardIds[14]),
           Princess(cardIds[15])]

        # self.startingDeck = [Gaurd(0), Priest(1), Handmaid(2), Princess(3)]

        deck = self.startingDeck.copy()
        r.shuffle(deck)
        self.state = GameState(numHumans + numComps, deck)
        
        if numHumans + numComps > 4 or numHumans + numComps < 2: 
            util.raiseException("must have 2 to 4 players")

        for i in range(numHumans):
            self.players.append(Player.createPlayer("human", i, self.state))

        for i in range(numComps):
            self.players.append(Player.createPlayer("computer", i + numHumans, self.state))

        self.state.setPlayers(self.players)
Exemplo n.º 19
0
def managerMaker(jsonStuff):
    names = jsonStuff[0]
    floor = jsonStuff[1]
    natural = jsonStuff[2]
    ptList = jsonStuff[3]
    actorMoveLL = moves_parser(jsonStuff[4])
    levelMade = floorMaker(floor)
    testState = GameState([levelMade])
    manager = GameManager(testState)
    users = []
    index = 0
    for name in names:
        newUser = LocalPlayer(name, "player", index)
        newUser.set_moves(actorMoveLL[index])
        manager.register_player_user(newUser)
        testState.move_player_via_id(index, translate_to_xy(ptList[index]))
        newUser.set_moves(actorMoveLL[index])
        users.append(newUser)
        index = index + 1
    while index < len(ptList):
        adverse = Adversary(3, index, name_list[index],
                            monster_types[index - 2], 3)
        manager.add_adversary(adverse)
        testState.move_character(adverse, translate_to_xy(ptList[index]))
        index = index + 1
    return (manager, natural, users)
Exemplo n.º 20
0
    def test_get_smallest_winning_card(self):
        game_state = GameState(1)
        game_state.lead_card = Card(Card.SUIT_HEARTS, 10)
        game_state.trick_cards = [game_state.lead_card]
        game_state.trumps = Card.SUIT_HEARTS

        lead_card_suit = game_state.lead_card.get_suit(game_state.trumps)

        smallest_winning = self.player.smallest_winning_card(
            Card.SUIT_HEARTS, game_state.trick_cards,
            game_state.get_valid_plays(self.player.hand))

        self.assertIsNotNone(smallest_winning)
        self.assertEqual(Card.SUIT_HEARTS,
                         smallest_winning.get_suit(game_state.trumps))
        self.assertEqual(
            Card.ACE + Card.TRUMP_BONUS,
            smallest_winning.get_total_value(game_state.trumps,
                                             lead_card_suit))

        game_state.lead_card = Card(Card.SUIT_HEARTS, Card.JACK)
        game_state.trick_cards = [game_state.lead_card]

        smallest_winning = self.player.smallest_winning_card(
            Card.SUIT_HEARTS, game_state.trick_cards,
            game_state.get_valid_plays(self.player.hand))
        self.assertIsNone(smallest_winning)
Exemplo n.º 21
0
def run_game(k):
    mean_low, mean_high = (-5, 5)
    stdev_low, stdev_high = (0, 3)
    distros = []
    for _ in range(k):
        distros.append(
            Normal(random.uniform(mean_low, mean_high),
                   random.uniform(stdev_low, stdev_high)))
    bandit = DistroBandit(distros)

    game_state = GameState(bandit)

    print(
        f"This is the k-armed bandit game for k={k}.\nThe action rewards are sampled from normal distributions, which are randomly initialized for each action with each mean uniformly sampled from ({mean_low}, {mean_high}) and each standard deviation uniformly sampled from ({stdev_low}, {stdev_high})."
    )

    while True:
        selection = input(
            "Select an Action...\n\t\ttotal reward - prints accumulated reward\n\t\t0-k - do an action\n\t\tquit - quit the game\n"
        )
        if selection == "quit":
            print("Goodbye!")
            break
        elif selection.isdigit():
            if int(selection) >= game_state.bandit.k:
                print("Action out of range.")
                continue
            reward = game_state.select(int(selection))
            print(f"\tReward gained: {reward}")
        elif selection == "total reward":
            print(f"\tTotal Reward so far: {game_state.total_reward}")
        else:
            print("\tUnrecognized action, try again.")
        print("___")
Exemplo n.º 22
0
    def test_get_trump_cards(self):

        game_state = GameState(1)
        game_state.trumps = Card.SUIT_HEARTS
        game_state.lead_card = Card(Card.SUIT_HEARTS, 10)
        cards = self.player.get_trump_cards(game_state.trumps,
                                            self.player.hand)
        self.assertEqual(len(cards), 3)

        self.assertEqual(cards[0], self.player.hand[2])
        self.assertEqual(cards[1], self.player.hand[3])
        self.assertEqual(cards[2], self.player.hand[4])

        cards = self.player.get_trump_cards(game_state.trumps,
                                            self.player.hand)
        self.assertEqual(len(cards), 3)

        game_state.trumps = Card.SUIT_CLUBS
        game_state.lead_card._suit = Card.SUIT_CLUBS
        cards = self.player.get_trump_cards(game_state.trumps,
                                            self.player.hand)
        self.assertEqual(len(cards), 1)

        # Test that even through the player has a trump card, he cannot play it
        # since the lead card is hearts and he must follow suit.
        game_state.lead_card._suit = Card.SUIT_HEARTS
        cards = self.player.get_trump_cards(
            game_state.trumps, game_state.get_valid_plays(self.player.hand))
        self.assertEqual(len(cards), 0)
Exemplo n.º 23
0
    def __init__(self):
        super(MainWindow, self).__init__()

        absdir = os.path.dirname(os.path.abspath(__file__))

        # Load up the UI designed in QtCreator
        uic.loadUi(os.path.join(absdir, 'window.ui'), self)

        # Setup ROS so ally's can use it
        rospy.init_node('command_center', anonymous=True)

        # Is this a fast or slow computer? What should the plot
        # update rate be? (in ms)
        update_period = 250

        # Figure out which ally is active
        ally1_active = True
        ally2_active = True

        # Setup all the GUI and ROS elements for each Ally
        ally1 = Ally(self, ally=1, active=ally1_active, interval=update_period)
        ally2 = Ally(self, ally=2, active=ally2_active, interval=update_period)

        # Setup Game State stuff
        game_state = GameState(self)
Exemplo n.º 24
0
def main():
    # initializing and drawing background UI elements
    background = UIBox(g_const.screen_size, (0, 0, 0), (0, 0))
    arena = UIBox(g_const.arena_size, (50, 50, 50), g_const.arena_pos)
    sidebar = UIBox(g_const.sidebar_size, (50, 50, 50), g_const.sidebar_pos)
    background.draw()
    sidebar.draw()

    evt_man = EventManager()
    terrain = Terrain()
    game_state = GameState(terrain)

    start = time.time()
    evt_man.start_world_update()

    while True:
        dt = time.time() - start

        if dt >= frame_length:
            start = time.time()  # reset start tick

            events = evt_man.processEvents()  # handle events

            game_state.update(events)  # update game state

            # draw objects
            arena.draw()
            game_state.curr_shape.draw()
            terrain.draw()

            # update display
            pyg.display.update()
Exemplo n.º 25
0
    def __init__(self, player_type: type(Player), game_id: int, game_type: GameType=GameType.PROGRESSIVE):

        self.players = [player_type(0, Teams.TEAM_A, "Player-0"),
                        player_type(1, Teams.TEAM_B, "Player-1"),
                        player_type(2, Teams.TEAM_A, "Player-2"),
                        player_type(3, Teams.TEAM_B, "Player-3")]

        self.game_type = game_type

        self.scores = [0, 0]        # Indexed using TEAM_A and TEAM_B
        self.tricks_won = [0, 0]    # Indexed using TEAM_A and TEAM_B

        self.deck = Deck()
        self.game_state = GameState(game_id)

        self.players[self.game_state.current_dealer].set_dealer()

        self.current_player_turn = (self.game_state.current_dealer + 1) % len(self.players)

        self.game_state.set_state(GameState.GAME_START)

        self.loaner_team = None
        self.loaner_player = None

        self.trick_obj = None
Exemplo n.º 26
0
def playTak():
    currentGameState = GameState()
    print(currentGameState)

    with tf.Graph().as_default():
        # make graph to apply the network
        # boards = tf.placeholder(tf.float32)
        # pieceCounts = tf.placeholder(tf.float32)
        # inferenceOp = TakNet.inference(boards, pieceCounts)

        # mimic training graph structure to load variables
        globalStep = tf.contrib.framework.get_or_create_global_step()
        # get data
        boards, pieceCounts, realScores = TakNet.inputs(False)
        # instantiate prediction graph
        scores = TakNet.inference(boards, pieceCounts)
        # calculate loss
        totalLoss, meanLoss = TakNet.loss(realScores, scores)
        # train for one batch and update parameters
        # noinspection PyUnusedLocal
        trainOp = TakNet.train(totalLoss, meanLoss, globalStep)

        with tf.Session() as session:
            # restore weights from model in Network folder
            tf.train.Saver().restore(session,
                                     tf.train.latest_checkpoint("Network"))

            tf.get_variable_scope().reuse_variables()
            boards2 = tf.placeholder(tf.float32)
            pieceCounts2 = tf.placeholder(tf.float32)
            inferenceOp = TakNet.inference(boards2, pieceCounts2)

            while True:
                try:
                    if currentGameState.turnIndicator == 1:
                        startTime = time.time()
                        move = miniMax(currentGameState, session, inferenceOp,
                                       boards2, pieceCounts2)
                        endTime = time.time()
                        print("TakticalBot: " + move)
                        print("Time: " + str(endTime - startTime))
                    else:
                        move = input("Player:      ")
                        if move == "quit":
                            break
                    currentGameState = currentGameState.applyMove(move)
                    print(currentGameState)
                    winner = currentGameState.checkVictory()
                    if winner != 2:
                        if winner == 1:
                            print("TakticalBot Won!")
                        elif winner == -1:
                            print("You Won!")
                        else:
                            print("It was a draw")
                        break
                except TakException as exception:
                    print(exception)
                    continue
Exemplo n.º 27
0
def main():
    state = input()
    gameState = GameState()
    gameState.feed(state)

    ai = ClassicalAI()
    move = ai.makeMove(GameState)
    print(move.get_json())
Exemplo n.º 28
0
 def test_not_existing(self):
     expected_message = "Failed to read file: " \
                        "[Errno 2] No such file or directory: " \
                        "'..\\\game_states\\\game_not_existing.json'"
     game_config = "game_not_existing.json"
     with self.assertRaises(GameStateFileException) as e:
         GameState(join(self.parent_path, game_config))
     self.assertEqual(expected_message, str(e.exception))
Exemplo n.º 29
0
 def setup_state(self):
     board = [[Location((col, row)) for row in xrange(0, c.BOARD_LENGTH)]
              for col in xrange(0, c.BOARD_LENGTH)]
     p1Inventory = Inventory(c.PLAYER_ONE, [], [], 0)
     p2Inventory = Inventory(c.PLAYER_TWO, [], [], 0)
     neutralInventory = Inventory(c.NEUTRAL, [], [], 0)
     return GameState(board, [p1Inventory, p2Inventory, neutralInventory],
                      c.SETUP_PHASE_1, c.PLAYER_ONE)
Exemplo n.º 30
0
 def flip(self, chosen_card):
     for card in self.cards:
         if card.back_face == chosen_card:
             if card.is_flipped:
                 return GameState('INVALID_MOVE', [card])
             else:
                 card.flip()
     return self.evaluate_board()