예제 #1
0
파일: run.py 프로젝트: zbendef/connect_four
def start_game(game_type):
    game = Game()
    ai = AI()
    
    while (game.game_finished is False):
        
        #clear board so output is not too messy
        os.system('cls' if os.name == "nt" else 'clear')
        
        #print the current board state for the players
        print_board_state(game.board)
        
        #if the game has an AI player get AI to move if it's their turn
        if (game_type == AI_PLAYS_BLUE or game_type == AI_PLAYS_RED):
            
            #if it's the AI's turn call the AI to make a move, else player is prompted for a move
            if (game.current_player_turn == RED_PLAYER and game_type == AI_PLAYS_RED):
                game.player_move(ai.get_move(game))
            elif (game.current_player_turn == BLUE_PLAYER and game_type == AI_PLAYS_BLUE):
                game.player_move(ai.get_move(game))
            else:
                game.player_move(get_user_column_input())
        
        #get player move if no AI player or it's still player turn
        else:
            game.player_move(get_user_column_input())
            
        #if the game is finished print the board state and let the player know who has won
        if (game.game_finished):
            os.system('cls' if os.name == "nt" else 'clear')
            print_board_state(game.board)
            print
            print str(game.winner) + " has won the game!"
예제 #2
0
class Game:
    def __init__(self):
        self.browser = Browser()
        self.app = QApplication(sys.argv)
        self.timer = QTimer()
        self.timer.timeout.connect(self.updateEvent)

        self.ai = AI()
        self.last_score = 1

    def run(self, delay):
        self.timer.start(delay)
        self.browser.run()
        return self.app.exec_()

    def updateEvent(self):
        self.timer.stop()

        (score, board) = self.browser.extractData()

        if self.last_score > score:
            self.ai.restart_game()
        self.last_score = score

        self.browser.sendMove(self.ai.get_move(score, board))

        self.timer.start()  # restart the event loop
예제 #3
0
class Game:
    def __init__(self):
        self.browser = Browser()
        self.app = QApplication(sys.argv)
        self.timer = QTimer()
        self.timer.timeout.connect(self.updateEvent)

        self.ai = AI()
        self.last_score = 1

    def run(self, delay):
        self.timer.start(delay)
        self.browser.run()
        return self.app.exec_()

    def updateEvent(self):
        self.timer.stop()

        (score, board) = self.browser.extractData()

        if self.last_score > score:
            self.ai.restart_game()
        self.last_score = score

        self.browser.sendMove(self.ai.get_move(score, board))

        self.timer.start() # restart the event loop
예제 #4
0
def test_get_move():
    # get_move() should return the move with the maximum value
    test_ai = AI('B')
    test_board = Board([Piece('9WN'), Piece('17BN'), Piece('21BN')], 'B')
    assert test_ai.get_move(test_board) in [{
        "position_from": "17",
        "position_to": "13"
    }, {
        "position_from": "21",
        "position_to": "18"
    }]
예제 #5
0
def run_game():
    """
    runs the game :D
    """
    game_board = Board()

    player1 = Human("1")
    player2 = AI("2")
    print(player1, "vs", player2)
    # players_turn = 1

    while not game_board.has_winner:
        col = player1.get_move(game_board)
        game_board.add_piece(col, player1.piece)
        col = player2.get_move(game_board)
        game_board.add_piece(col, player2.piece)
        game_board.print_board()
def brain_turn():
    if pp.terminateAI:
        return

    global myAI
    if myAI.turnChecked:
        opp_move = myAI.get_opponent_move(board)
        myAI.set(opp_move, 2)
    else:
        myAI = AI(board)
        if myAI.white_or_black():
            myAI.searchDeep = config.searchDeep_black
        else:
            myAI.searchDeep = config.searchDeep_white
        myAI.searchDeep_ = myAI.searchDeep
        myAI.turnChecked = True

    if myAI.turnChecked and len(myAI.theBoard.allSteps) <= 4:
        myAI.searchDeep = myAI.searchDeep_ - 2
    else:
        myAI.searchDeep = myAI.searchDeep_

    myAI.theBoard.startTime = time.clock()

    if_only = False
    if not myAI.if_found_vcx:
        # 如果之前已经找到,之后就不需要再搜了
        move, if_only = myAI.get_move()

    if not if_only:
        move_vcx = myAI.get_move_vcx()
        if move_vcx:
            myAI.if_found_vcx = True
            # print('HHHHHHH')
            move = move_vcx

    myAI.set(move, 1)
    x, y = move
    pp.do_mymove(x, y)
예제 #7
0
class AbstractBoard(object):
    '''A class that keeps track of the board logic; piece positions, legal
    moves etc.'''
    def __init__(self, shape=None):
        self.ai = None

        self.man_coords = set()
        self.ball_coords = (0, 0)
        self.shape = (15, 19)
        self.legal_moves = {}

        # Speculative attributes will hold data about the move the
        # player is currently making, without disrupting the full
        # logical state.
        self.speculative_ball_coords = (0, 0)
        self.speculative_man_coords = set()
        self.speculative_legal_moves = {}
        self.speculative_step_removals = []
        self.speculative_steps = []

        self.message = ''

        self.current_player = 'top'

        if 'shape' is not None:
            self.shape = shape

    def initialise_ai(self):
        if not self.ai:
            self.ai = AI(self)

    def check_for_win(self):
        '''Checks if either player has won.'''
        ball_coords = self.ball_coords
        if ball_coords[1] <= 1:
            return 'bottom'
        elif ball_coords[1] >= self.shape[1] - 2:
            return 'top'
        else:
            return 'none'

    def speculative_move_ball_to(self, coords):
        '''Tries to move the ball to the given coordinates. Returns
        appropriate instructions for how the board should change in
        response.'''
        coords = tuple(coords)
        speculative_legal_moves = self.speculative_legal_moves

        if coords in self.speculative_legal_moves:
            possible_paths = self.speculative_legal_moves[coords]
            if len(possible_paths) > 1:
                short_paths = list(
                    filter(lambda j: len(j) == 1, possible_paths))
                if not short_paths:
                    return {'conflicting_paths': (coords, possible_paths)}
                steps = short_paths[0]
            else:
                steps = possible_paths[0]

            self.speculative_ball_coords = coords
            newly_removed_coords = removed_coords_from_steps(coords, steps)
            remove_coords_lists_from_set(newly_removed_coords,
                                         self.speculative_man_coords)
            self.speculative_step_removals.extend(newly_removed_coords)
            self.speculative_legal_moves = get_legal_moves(
                self.speculative_ball_coords, self.speculative_man_coords,
                self.shape)
            self.speculative_steps.extend(list(map(tuple, steps)))
            return {
                'speculative_marker':
                get_speculative_move_identifiers(coords,
                                                 self.speculative_steps)
            }

        if coords in self.speculative_steps:
            i = index = self.speculative_steps.index(coords)
            added_stones = self.speculative_step_removals[index:]
            self.speculative_ball_coords = coords
            self.speculative_steps = self.speculative_steps[:index]
            self.speculative_step_removals = self.speculative_step_removals[:i]
            add_coords_lists_to_set(added_stones, self.speculative_man_coords)
            self.speculative_legal_moves = get_legal_moves(
                self.speculative_ball_coords, self.speculative_man_coords,
                self.shape)
            return {
                'speculative_marker':
                get_speculative_move_identifiers(coords,
                                                 self.speculative_steps)
            }

        return None

    def speculative_play_man_at(self, coords):
        '''Speculatively plays a man at the given coordinates.'''
        coords = tuple(coords)
        self.speculative_man_coords.add(coords)
        self.speculative_legal_moves = get_legal_moves(
            self.speculative_ball_coords, self.speculative_man_coords,
            self.shape)

    def confirm_speculation(self):
        '''Sets the current speculation state to the real board state. Returns
        a list of permanent instructions.'''
        if (not self.speculative_step_removals
                and self.speculative_man_coords - self.man_coords == set()):
            return None
        new_men = self.speculative_man_coords - self.man_coords
        self.ball_coords = self.speculative_ball_coords
        self.man_coords = self.speculative_man_coords
        self.legal_moves = self.speculative_legal_moves
        if new_men:
            instructions = {'add': list(new_men)}
        else:
            removals = []
            for coords in self.speculative_step_removals:
                removals.extend(coords)
            instructions = {
                'move_ball_to':
                self.ball_coords,
                'move_ball_via':
                get_speculative_move_identifiers(tuple(self.ball_coords),
                                                 self.speculative_steps),
                'remove':
                removals,
                'clear_transient':
                None
            }
        self.reset_speculation()
        return instructions

    def reset_speculation(self):
        self.speculative_ball_coords = self.ball_coords
        self.speculative_man_coords = self.man_coords.copy()
        self.speculative_legal_moves = self.legal_moves
        self.speculative_step_removals = []
        self.speculative_steps = []

    def reset(self, *args):
        self.man_coords = set()
        self.ball_coords = (0, 0)
        self.legal_moves = []
        self.reset_speculation()

    def add_man(self, coords):
        coords = tuple(coords)
        if coords in self.man_coords:
            return None
        self.man_coords.add(coords)
        return {'add': [coords]}

    def remove_man(self, coords):
        coords = tuple(coords)
        if coords not in self.man_coords:
            return None
        self.man_coords.remove(coords)
        return {'remove': [coords]}

    def toggle_man(self, coords):
        coords = tuple(coords)
        if coords in self.man_coords:
            instructions = self.remove_man(coords)
        else:
            instructions = self.add_man(coords)
        self.update_legal_moves()
        return instructions

    def play_man_at(self, coords):
        '''Method for attempting to play a man piece. Adds the man, and
        updates internal move state if necessary.
        '''
        instructions = self.add_man(coords)
        if instructions:
            self.update_legal_moves()
            self.reset_speculation()
        return instructions

    def do_ai_move(self):
        if not self.ai:
            self.initialise_ai()

        self.reset_speculation()

        move_type, coords = self.ai.get_move()
        print('ai wants to move at', coords, move_type)
        if move_type == 'move':
            self.speculative_move_ball_to(coords)
        elif move_type == 'play':
            self.speculative_play_man_at(coords)
#        legal_moves[current_pos] =

    def update_legal_moves(self):
        moves = get_legal_moves(self.ball_coords, self.man_coords, self.shape)
        self.legal_moves = moves
        return self.legal_moves

    def as_ascii(self, speculative=False, *args):
        '''Returns an ascii representation of the board.'''
        string_elements = []
        if not speculative:
            ball_coords = self.ball_coords
            man_coords = self.man_coords
            legal_moves = self.legal_moves
        else:
            ball_coords = self.speculative_ball_coords
            man_coords = self.speculative_man_coords
            legal_moves = self.speculative_legal_moves
        for y in range(self.shape[1])[::-1]:
            for x in range(self.shape[0]):
                coords = (x, y)
                if (coords[0] == ball_coords[0]
                        and coords[1] == ball_coords[1]):
                    string_elements.append('O')
                elif coords in man_coords:
                    string_elements.append('X')
                elif coords in legal_moves:
                    string_elements.append('@')
                elif coords[1] <= 1 or coords[1] >= self.shape[1] - 2:
                    string_elements.append(',')
                else:
                    string_elements.append(',')
            string_elements.append('\n')
        return ''.join(string_elements)

    def serialise(self):
        '''Serialises the board position (all stones, including speculative
        moves) as json.

        '''

        return json.dumps({
            'shape':
            self.shape,
            'ball_coords':
            self.ball_coords,
            'man_coords':
            list(self.man_coords),
            'current_player':
            self.current_player,
            'legal_moves':
            list(self.legal_moves.items()),
            'speculative_ball_coords':
            self.speculative_ball_coords,
            'speculative_man_coords':
            list(self.speculative_man_coords),
            'speculative_legal_moves':
            list(self.speculative_legal_moves.items()),
            'speculative_step_removals':
            self.speculative_step_removals,
            'speculative_steps':
            self.speculative_steps,
            'message':
            '',
            'other':
            '',
        })

    def save_state(self, filen):
        '''Saves the state of self in the given file.'''
        with open(filen, 'w') as fileh:
            fileh.write(self.serialise())

    def load_dict(self, d):
        '''Sets the properties of self according to the dictionary.'''
        if ('shape' not in d or 'ball_coords' not in d or 'man_coords' not in d
                or 'current_player' not in d):
            raise Exception('Not enough information to load.')

        print('loading from', d)
        self.shape = tuple(d['shape'])
        self.ball_coords = tuple(d['ball_coords'])
        print('ball coords set to', self.ball_coords)
        self.man_coords = set([tuple(coords) for coords in d['man_coords']])
        self.current_player = d['current_player']
        self.legal_moves = get_legal_moves(self.ball_coords, self.man_coords,
                                           self.shape)

        # Speculative saving not implemented yet.
        self.reset_speculation()

        if 'message' in d:
            self.message = d['message']

    def load_file(self, filen):
        '''Loads json data from filen and sets the properties of self
        appropriately.'''
        with open(filen, 'r') as fileh:
            data = json.load(fileh)
        self.load_dict(data)
예제 #8
0
파일: game.py 프로젝트: cprimera/projects
class Game:
    def __init__(self):
        # get user input for board size and number of ships, if input is invalid it gets re-asked
        while True:
            try:
                size = raw_input("Please enter a size for the board [10]: ")
                if size == "":
                    size = 10
                else:
                    size = int(size)
                    if size < 1:
                        raise ValueError
                break
            except ValueError:
                continue
        while True:
            try:
                ships2 = raw_input("Please enter the amount of size 2 ships [1]: ")
                if ships2 == "":
                    ships2 = 1
                else:
                    ships2 = int(ships2)
                    if ships2 < 0:
                        raise ValueError
                    # preliminary check for whether the ships will fit on the board
                    # if the total area of ships is greater than the area of the board
                    # than there is no chance of the ships fitting and a new value is asked for
                    # this check is done for all ships and does not take into account previously
                    # added ships
                    if ships2 > size * size / 2:
                        print "The ships will not fit on the board"
                        raise ValueError
                break
            except ValueError:
                continue
        while True:
            try:
                ships3 = raw_input("Please enter the amount of size 3 ships [2]: ")
                if ships3 == "":
                    ships3 = 2
                else:
                    ships3 = int(ships3)
                    if ships3 < 0:
                        raise ValueError
                    if ships3 > size * size / 3:
                        print "The ships will not fit on the board"
                        raise ValueError
                break
            except ValueError:
                continue
        while True:
            try:
                ships4 = raw_input("Please enter the amount of size 4 ships [1]: ")
                if ships4 == "":
                    ships4 = 1
                else:
                    ships4 = int(ships4)
                    if ships4 < 0:
                        raise ValueError
                    if ships4 > size * size / 4:
                        print "The ships will not fit on the board"
                        raise ValueError
                break
            except ValueError:
                continue
        while True:
            try:
                ships5 = raw_input("Please enter the amount of size 5 ships [1]: ")
                if ships5 == "":
                    ships5 = 1
                else:
                    ships5 = int(ships5)
                    if ships5 < 0:
                        raise ValueError
                    if ships5 > size * size / 5:
                        print "The ships will not fit on the board"
                        raise ValueError
                break
            except ValueError:
                continue
        # get user input for type of game
        if enhancements:
            while True:
                try:
                    game_type = raw_input("Please enter game type:\n\t0:Human vs. Human\n\t1:Human vs. Computer\n\t2:Computer vs. Computer\n[1]:\n")
                    if game_type == "":
                        game_type = 1
                    else:
                        game_type = int(game_type)
                        if game_type < 0 or game_type > 2:
                            raise ValueError
                    break
                except ValueError:
                    continue
        else:
            while True:
                try:
                    game_type = raw_input("Please enter game type:\n\t0:Human vs. Human\n\t1:Human vs. Computer\n[1]:\n")
                    if game_type == "":
                        game_type = 1
                    else:
                        game_type = int(game_type)
                        if game_type < 0 or game_type > 1:
                            raise ValueError
                    break
                except ValueError:
                    continue
        # create the players, their boards and ships, also ask for AI difficulty if enhancements are enabled
        # and a user is AI
        if game_type == 0:
            self._player1 = User(Board(size, ships2, ships3, ships4, ships5), 0)
            self._player2 = User(Board(size, ships2, ships3, ships4, ships5), 1)
        elif game_type == 1:
            difficulty = 0
            if enhancements:
                while True:
                    try:
                        difficulty = raw_input("Please enter a computer difficulty:\n\t0:Easy\n\t1:Hard\n[0]:\n")
                        if difficulty == "":
                            difficulty = 0
                        else:
                            difficulty = int(difficulty)
                            if difficulty < 0 or difficulty > 1:
                                raise ValueError
                        break
                    except ValueError:
                        continue
            self._player1 = User(Board(size, ships2, ships3, ships4, ships5), 0)
            self._player2 = AI(Board(size, ships2, ships3, ships4, ships5), difficulty)
        elif game_type == 2:
            difficulty = 0
            if enhancements:
                while True:
                    try:
                        difficulty = raw_input("Please enter a computer difficulty:\n\t0:Easy\n\t1:Hard\n[0]:\n")
                        if difficulty == "":
                            difficulty = 0
                        else:
                            difficulty = int(difficulty)
                            if difficulty < 0 or difficulty > 1:
                                raise ValueError
                        break
                    except ValueError:
                        continue
            self._player1 = AI(Board(size, ships2, ships3, ships4, ships5), difficulty)
            difficulty = 0
            if enhancements:
                while True:
                    try:
                        difficulty = raw_input("Please enter a computer difficulty:\n\t0:Easy\n\t1:Hard\n[0]:\n")
                        if difficulty == "":
                            difficulty = 0
                        else:
                            difficulty = int(difficulty)
                            if difficulty < 0 or difficulty > 1:
                                raise ValueError
                        break
                    except ValueError:
                        continue
            self._player2 = AI(Board(size, ships2, ships3, ships4, ships5), difficulty)
        else:
            print "Game type was incorrent"
            
        # if enhancements are enabled initialize and setup variables for the GUI display
        if enhancements:
            pygame.init()
            self._screen1 = pygame.display.set_mode(((size * 22) + 1,(size * 11) + 50))
            self._screen1.fill((0,0,0))
            self._font = pygame.font.Font(None, 30)
            self._ship_font = pygame.font.Font(None, 20)
        
    def start(self):
        # continue playing the game as long as someone has not lost
        turn_count = 0
        draw_ships = False
        while(not self._player1.is_defeated() and not self._player2.is_defeated()):
            # if enhancements are enabled generate the images to display for the GUI and display them
            if enhancements:
                for event in pygame.event.get(pygame.QUIT):
                    pygame.quit()
                    sys.exit()
                self._screen1.fill((0,0,0))
                image, imagerect = self._player1.get_board().draw_board(draw_ships)
                imagerect.top += 50
                image1, imagerect1 = self._player2.get_board().draw_board(draw_ships)
                imagerect1.top += 50
                imagerect1.left = imagerect.width + 1
                self._screen1.blit(image, imagerect)
                self._screen1.blit(image1, imagerect1)
                # create the 'scoreboard' for the GUI with the player name highlighted for
                # whoever's turn it currently is
                if turn_count % 2 == 0:
                    self._font.set_bold(True)
                else:
                    self._font.set_bold(False)
                font_image = self._font.render("Player 1", False, (255,255,255))
                self._screen1.blit(font_image, pygame.Rect(0,0,self._font.size("Player 1")[0], self._font.size("Player 1")[1]))
                ship_image = self._ship_font.render("ships left = " + str(self._player1.get_ships_left()), False, (255,255,255))
                self._screen1.blit(ship_image, pygame.Rect(0,30,self._ship_font.size("ships left = " + str(self._player1.get_ships_left()))[0], self._ship_font.size("ships left = " + str(self._player1.get_ships_left()))[1]))
                if turn_count % 2 != 0:
                    self._font.set_bold(True)
                else:
                    self._font.set_bold(False)
                font_image = self._font.render("Player 2", False, (255,255,255))
                self._screen1.blit(font_image, pygame.Rect(self._screen1.get_width() - self._font.size("Player 2")[0],0,self._font.size("Player 2")[0], self._font.size("Player 2")[1]))
                ship_image = self._ship_font.render("ships left = " + str(self._player2.get_ships_left()), False, (255,255,255))
                self._screen1.blit(ship_image, pygame.Rect(self._screen1.get_width() - self._ship_font.size("ships left = " + str(self._player2.get_ships_left()))[0],30,self._ship_font.size("ships left = " + str(self._player2.get_ships_left()))[0], self._ship_font.size("ships left = " + str(self._player2.get_ships_left()))[1]))
                pygame.display.update()
            # get player 1 or player 2 move and check for hit and update board
            if turn_count % 2 == 0:
                if not enhancements:
                    print self._player1.get_board()
                value = self._player2.is_hit(Point(0, self._player1.get_move()))
                if value:
                    self._player1.set_prev_was_hit(True)
                elif self._player1.get_prev_was_hit() and not value:
                    self._player1.next_direction()
            else:
                if not enhancements:
                    print self._player2.get_board()
                value = self._player1.is_hit(Point(0, self._player2.get_move()))
                if value:
                    self._player2.set_prev_was_hit(True)
                elif self._player2.get_prev_was_hit() and not value:
                    self._player2.next_direction()
            # change players turn
            turn_count += 1
        # if enhancements are enabled display the final display after a player has won
        if enhancements:
            self._screen1.fill((0,0,0))
            self._font.set_bold(False)
            font_image = self._font.render("Player 1", False, (255,255,255))
            self._screen1.blit(font_image, pygame.Rect(0,0,self._font.size("Player 1")[0], self._font.size("Player 1")[1]))
            font_image = self._font.render("Player 2", False, (255,255,255))
            self._screen1.blit(font_image, pygame.Rect(self._screen1.get_width() - self._font.size("Player 2")[0],0,self._font.size("Player 2")[0], self._font.size("Player 2")[1]))
        # display who was the winner of the game
        if self._player1.is_defeated():
            if not enhancements:
                print "Player 2 Wins."
                print self._player1.get_board()
            else:
                end_image = self._ship_font.render("Player 2 Wins.", False, (255,255,255))
                self._screen1.blit(end_image, pygame.Rect(0,30, self._ship_font.size("Player 2 Wins.")[0], self._ship_font.size("Player 2 Wins.")[1]))
        elif self._player2.is_defeated():
            if not enhancements:
                print "Player 1 Wins."
                print self._player2.get_board()
            else:
                end_image = self._ship_font.render("Player 1 Wins.", False, (255,255,255))
                self._screen1.blit(end_image, pygame.Rect(0,30, self._ship_font.size("Player 1 Wins.")[0], self._ship_font.size("Player 1 Wins.")[1]))
        # if enhancements are enabled display the actual boards of the players after one has won
        if enhancements:
            image, imagerect = self._player1.get_board().draw_board(draw_ships)
            imagerect.top += 50
            image1, imagerect1 = self._player2.get_board().draw_board(draw_ships)
            imagerect1.top += 50
            imagerect1.left = imagerect.width + 1
            self._screen1.blit(image, imagerect)
            self._screen1.blit(image1, imagerect1)        
            pygame.display.update()
            # wait for a mouse click to allow the users to see the outcome of the game
            while len(pygame.event.get(pygame.MOUSEBUTTONUP)) == 0:
                continue
예제 #9
0
class GameGrid(Frame):
    def __init__(self):
        Frame.__init__(self)

        self.grid()
        self.master.title('2048')
        self.grid_cells = []

        self.init_grid()
        self.init_matrix()
        self.update_grid_cells()
        self.AI = AI()

        self.run_game()
        self.mainloop()

    def run_game(self):

        while True:
            self.board.move(self.AI.get_move(self.board))
            self.update_grid_cells()
            self.add_random_tile()
            self.update_grid_cells()

            if len(self.board.get_available_moves()) == 0:
                self.game_over_display()
                break

            self.update()

    def game_over_display(self):
        for i in range(4):
            for j in range(4):
                self.grid_cells[i][j].configure(text="",
                                                bg=BACKGROUND_COLOR_CELL_EMPTY)

        self.grid_cells[1][1].configure(text="TOP",
                                        bg=BACKGROUND_COLOR_CELL_EMPTY)
        self.grid_cells[1][2].configure(text="4 TILES:",
                                        bg=BACKGROUND_COLOR_CELL_EMPTY)
        top_4 = list(
            map(int, reversed(sorted(list(self.board.grid.flatten())))))
        self.grid_cells[2][0].configure(text=str(top_4[0]),
                                        bg=BACKGROUND_COLOR_DICT[2048],
                                        fg=CELL_COLOR_DICT[2048])
        self.grid_cells[2][1].configure(text=str(top_4[1]),
                                        bg=BACKGROUND_COLOR_DICT[2048],
                                        fg=CELL_COLOR_DICT[2048])
        self.grid_cells[2][2].configure(text=str(top_4[2]),
                                        bg=BACKGROUND_COLOR_DICT[2048],
                                        fg=CELL_COLOR_DICT[2048])
        self.grid_cells[2][3].configure(text=str(top_4[3]),
                                        bg=BACKGROUND_COLOR_DICT[2048],
                                        fg=CELL_COLOR_DICT[2048])
        self.update()

    def init_grid(self):
        background = Frame(self,
                           bg=BACKGROUND_COLOR_GAME,
                           width=SIZE,
                           height=SIZE)
        background.grid()

        for i in range(GRID_LEN):
            grid_row = []

            for j in range(GRID_LEN):

                cell = Frame(background,
                             bg=BACKGROUND_COLOR_CELL_EMPTY,
                             width=SIZE / GRID_LEN,
                             height=SIZE / GRID_LEN)
                cell.grid(row=i,
                          column=j,
                          padx=GRID_PADDING,
                          pady=GRID_PADDING)
                # font = Font(size=FONT_SIZE, family=FONT_FAMILY, weight=FONT_WEIGHT)
                t = Label(master=cell,
                          text="",
                          bg=BACKGROUND_COLOR_CELL_EMPTY,
                          justify=CENTER,
                          font=FONT,
                          width=4,
                          height=2)
                t.grid()
                grid_row.append(t)

            self.grid_cells.append(grid_row)

    def gen(self):
        return randint(0, GRID_LEN - 1)

    def init_matrix(self):
        self.board = GameBoard()
        self.add_random_tile()
        self.add_random_tile()

    def update_grid_cells(self):
        for i in range(GRID_LEN):
            for j in range(GRID_LEN):
                new_number = int(self.board.grid[i][j])
                if new_number == 0:
                    self.grid_cells[i][j].configure(
                        text="", bg=BACKGROUND_COLOR_CELL_EMPTY)
                else:
                    n = new_number
                    if new_number > 2048:
                        c = 2048
                    else:
                        c = new_number

                    self.grid_cells[i][j].configure(
                        text=str(n),
                        bg=BACKGROUND_COLOR_DICT[c],
                        fg=CELL_COLOR_DICT[c])
        self.update_idletasks()

    def add_random_tile(self):
        if randint(0, 99) < 100 * 0.9:
            value = 2
        else:
            value = 4

        cells = self.board.get_available_cells()
        pos = cells[randint(0, len(cells) - 1)] if cells else None

        if pos is None:
            return None
        else:
            self.board.insert_tile(pos, value)
            return pos
예제 #10
0
class GameControl:
    def __init__(self, player_color, is_computer_opponent):
        self.turn = player_color
        self.winner = None
        self.board = None
        self.board_draw = None
        self.held_piece = None
        self.ai_control = None

        if is_computer_opponent:
            self.ai_control = AI("B") if player_color == "W" else AI("W")

        self.setup()

    def get_turn(self):
        return self.turn

    def get_winner(self):
        return self.winner

    def setup(self):
        # Initial setup
        pieces = []

        for opponent_piece in range(0, 12):
            pieces.append(Piece(str(opponent_piece) + 'BN'))

        for player_piece in range(20, 32):
            pieces.append(Piece(str(player_piece) + 'WN'))

        self.board = Board(pieces, self.turn)
        self.board_draw = BoardGUI(self.board)
        pass

    def draw_screen(self, display_surface):
        self.board_draw.draw_board(display_surface)
        self.board_draw.draw_pieces(display_surface)

        if self.held_piece is not None:
            self.held_piece.draw_piece(display_surface)

    def hold_piece(self, mouse_pos):
        piece_clicked = self.board_draw.get_piece_on_mouse(mouse_pos)
        board_pieces = self.board.get_pieces()
        has_jump_restraint = False  # True if any piece can jump in one of its moves, forcing the player to jump

        if piece_clicked is None:
            return

        if piece_clicked["piece"]["color"] != self.turn:
            return

        # Determines if player has a jump restraint
        for piece in board_pieces:
            for move in piece.get_moves(self.board):
                if move["eats_piece"]:
                    if piece.get_color() == piece_clicked["piece"]["color"]:
                        has_jump_restraint = True
            else:
                continue
            break

        piece_moves = board_pieces[piece_clicked["index"]].get_moves(
            self.board)

        if has_jump_restraint:
            piece_moves = list(
                filter(lambda move: move["eats_piece"] == True, piece_moves))

        move_marks = []

        # Gets possible moving positions and tells BoardGUI to draw them
        for possible_move in piece_moves:
            row = self.board.get_row_number(int(possible_move["position"]))
            column = self.board.get_col_number(int(possible_move["position"]))
            move_marks.append((row, column))

        self.board_draw.set_move_marks(move_marks)

        self.board_draw.hide_piece(piece_clicked["index"])
        self.set_held_piece(piece_clicked["index"],
                            board_pieces[piece_clicked["index"]], mouse_pos)

    def release_piece(self):
        if self.held_piece is None:
            return

        position_released = self.held_piece.check_collision(
            self.board_draw.get_move_marks())
        moved_index = self.board_draw.show_piece()
        piece_moved = self.board.get_piece_by_index(moved_index)

        # Only moves the piece if dropped in a proper move mark
        if position_released is not None:
            self.board.move_piece(
                moved_index,
                self.board_draw.get_position_by_rect(position_released))
            self.board_draw.set_pieces(
                self.board_draw.get_piece_properties(self.board))
            self.winner = self.board.get_winner()

            # Check if player can eat another piece, granting an extra turn.
            jump_moves = list(
                filter(lambda move: move["eats_piece"] == True,
                       piece_moved.get_moves(self.board)))

            if len(jump_moves) == 0 or piece_moved.get_has_eaten() == False:
                self.turn = "B" if self.turn == "W" else "W"

        self.held_piece = None
        self.board_draw.set_move_marks([])

    def set_held_piece(self, index, piece, mouse_pos):
        # Creates a HeldPiece object to follow the mouse
        surface = self.board_draw.get_surface(piece)
        offset = get_surface_mouse_offset(
            self.board_draw.get_piece_by_index(index)["rect"], mouse_pos)
        self.held_piece = HeldPiece(surface, offset)

    def move_ai(self):
        # Gets best move from an AI instance and moves it.
        if self.turn == "W":
            return

        optimal_move = self.ai_control.get_move(self.board)
        index_moved = -1
        piece_moved = None

        for index, piece in enumerate(self.board.get_pieces()):
            if piece.get_position() == optimal_move["position_from"]:
                index_moved = index
                piece_moved = piece
                break
        else:
            raise RuntimeError(
                "AI was supposed to return a move from an existing piece but found none."
            )

        self.board.move_piece(index_moved, int(optimal_move["position_to"]))
        self.board_draw.set_pieces(
            self.board_draw.get_piece_properties(self.board))
        self.winner = self.board.get_winner()

        # Check if AI can eat another piece, granting an extra turn.
        jump_moves = list(
            filter(lambda move: move["eats_piece"] == True,
                   piece_moved.get_moves(self.board)))

        if len(jump_moves) == 0 or piece_moved.get_has_eaten() == False:
            self.turn = "B" if self.turn == "W" else "W"
예제 #11
0
class AbstractBoard(object):
    '''A class that keeps track of the board logic; piece positions, legal
    moves etc.'''

    def __init__(self, shape=None):
        self.ai = None
        
        self.man_coords = set()
        self.ball_coords = (0, 0)
        self.shape = (15, 19)
        self.legal_moves = {}

        # Speculative attributes will hold data about the move the
        # player is currently making, without disrupting the full
        # logical state.
        self.speculative_ball_coords = (0, 0)
        self.speculative_man_coords = set()
        self.speculative_legal_moves = {}
        self.speculative_step_removals = []
        self.speculative_steps = []

        self.message = ''

        self.current_player = 'top'

        if 'shape' is not None:
            self.shape = shape

    def initialise_ai(self):
        if not self.ai:
            self.ai = AI(self)

    def check_for_win(self):
        '''Checks if either player has won.'''
        ball_coords = self.ball_coords
        if ball_coords[1] <= 1:
            return 'bottom'
        elif ball_coords[1] >= self.shape[1]-2:
            return 'top'
        else:
            return 'none'

    def speculative_move_ball_to(self, coords):
        '''Tries to move the ball to the given coordinates. Returns
        appropriate instructions for how the board should change in
        response.'''
        coords = tuple(coords)
        speculative_legal_moves = self.speculative_legal_moves

        if coords in self.speculative_legal_moves:
            possible_paths = self.speculative_legal_moves[coords]
            if len(possible_paths) > 1:
                short_paths = list(filter(lambda j: len(j) == 1, possible_paths))
                if not short_paths:
                    return {'conflicting_paths': (coords, possible_paths)}
                steps = short_paths[0]
            else:
                steps = possible_paths[0]

            self.speculative_ball_coords = coords
            newly_removed_coords = removed_coords_from_steps(coords, steps)
            remove_coords_lists_from_set(newly_removed_coords,
                                         self.speculative_man_coords)
            self.speculative_step_removals.extend(newly_removed_coords)
            self.speculative_legal_moves = get_legal_moves(
                self.speculative_ball_coords, self.speculative_man_coords,
                self.shape)
            self.speculative_steps.extend(list(map(tuple, steps)))
            return {'speculative_marker': get_speculative_move_identifiers(
                coords, self.speculative_steps)}

        if coords in self.speculative_steps:
            i = index = self.speculative_steps.index(coords)
            added_stones = self.speculative_step_removals[index:]
            self.speculative_ball_coords = coords
            self.speculative_steps = self.speculative_steps[:index]
            self.speculative_step_removals = self.speculative_step_removals[:i]
            add_coords_lists_to_set(added_stones, self.speculative_man_coords)
            self.speculative_legal_moves = get_legal_moves(
                self.speculative_ball_coords,
                self.speculative_man_coords,
                self.shape)
            return {'speculative_marker': get_speculative_move_identifiers(
                coords, self.speculative_steps)}

        return None

    def speculative_play_man_at(self, coords):
        '''Speculatively plays a man at the given coordinates.'''
        coords = tuple(coords)
        self.speculative_man_coords.add(coords)
        self.speculative_legal_moves = get_legal_moves(
            self.speculative_ball_coords,
            self.speculative_man_coords,
            self.shape)

    def confirm_speculation(self):
        '''Sets the current speculation state to the real board state. Returns
        a list of permanent instructions.'''
        if (not self.speculative_step_removals and 
            self.speculative_man_coords - self.man_coords == set()):
            return None
        new_men = self.speculative_man_coords - self.man_coords
        self.ball_coords = self.speculative_ball_coords
        self.man_coords = self.speculative_man_coords
        self.legal_moves = self.speculative_legal_moves
        if new_men:
            instructions = {'add': list(new_men)}
        else:
            removals = []
            for coords in self.speculative_step_removals:
                removals.extend(coords)
            instructions = {'move_ball_to': self.ball_coords,
                            'move_ball_via': get_speculative_move_identifiers(
                                tuple(self.ball_coords),
                                self.speculative_steps),
                            'remove': removals,
                            'clear_transient': None}
        self.reset_speculation()
        return instructions

    def reset_speculation(self):
        self.speculative_ball_coords = self.ball_coords
        self.speculative_man_coords = self.man_coords.copy()
        self.speculative_legal_moves = self.legal_moves
        self.speculative_step_removals = []
        self.speculative_steps = []

    def reset(self, *args):
        self.man_coords = set()
        self.ball_coords = (0, 0)
        self.legal_moves = []
        self.reset_speculation()

    def add_man(self, coords):
        coords = tuple(coords)
        if coords in self.man_coords:
            return None
        self.man_coords.add(coords)
        return {'add': [coords]}

    def remove_man(self, coords):
        coords = tuple(coords)
        if coords not in self.man_coords:
            return None
        self.man_coords.remove(coords)
        return {'remove': [coords]}

    def toggle_man(self, coords):
        coords = tuple(coords)
        if coords in self.man_coords:
            instructions = self.remove_man(coords)
        else:
            instructions = self.add_man(coords)
        self.update_legal_moves()
        return instructions

    def play_man_at(self, coords):
        '''Method for attempting to play a man piece. Adds the man, and
        updates internal move state if necessary.
        '''
        instructions = self.add_man(coords)
        if instructions:
            self.update_legal_moves()
            self.reset_speculation()
        return instructions

    def do_ai_move(self):
        if not self.ai:
            self.initialise_ai()

        self.reset_speculation()

        move_type, coords = self.ai.get_move()
        print('ai wants to move at', coords, move_type)
        if move_type == 'move':
            self.speculative_move_ball_to(coords)
        elif move_type == 'play':
            self.speculative_play_man_at(coords)
#        legal_moves[current_pos] = 

    def update_legal_moves(self):
        moves = get_legal_moves(self.ball_coords, self.man_coords,
                                self.shape)
        self.legal_moves = moves
        return self.legal_moves

    def as_ascii(self, speculative=False, *args):
        '''Returns an ascii representation of the board.'''
        string_elements = []
        if not speculative:
            ball_coords = self.ball_coords
            man_coords = self.man_coords
            legal_moves = self.legal_moves
        else:
            ball_coords = self.speculative_ball_coords
            man_coords = self.speculative_man_coords
            legal_moves = self.speculative_legal_moves
        for y in range(self.shape[1])[::-1]:
            for x in range(self.shape[0]):
                coords = (x, y)
                if (coords[0] == ball_coords[0] and
                        coords[1] == ball_coords[1]):
                    string_elements.append('O')
                elif coords in man_coords:
                    string_elements.append('X')
                elif coords in legal_moves:
                    string_elements.append('@')
                elif coords[1] <= 1 or coords[1] >= self.shape[1]-2:
                    string_elements.append(',')
                else:
                    string_elements.append(',')
            string_elements.append('\n')
        return ''.join(string_elements)

    def serialise(self):
        '''Serialises the board position (all stones, including speculative
        moves) as json.

        '''

        return json.dumps(
            {'shape': self.shape,
             'ball_coords': self.ball_coords,
             'man_coords': list(self.man_coords),
             'current_player': self.current_player,
             'legal_moves': list(self.legal_moves.items()),
             'speculative_ball_coords': self.speculative_ball_coords,
             'speculative_man_coords': list(self.speculative_man_coords),
             'speculative_legal_moves': list(
                 self.speculative_legal_moves.items()),
             'speculative_step_removals': self.speculative_step_removals,
             'speculative_steps': self.speculative_steps,
             'message': '',
             'other': '',
             })

    def save_state(self, filen):
        '''Saves the state of self in the given file.'''
        with open(filen, 'w') as fileh:
            fileh.write(self.serialise())

    def load_dict(self, d):
        '''Sets the properties of self according to the dictionary.'''
        if ('shape' not in d or
            'ball_coords' not in d or
            'man_coords' not in d or
            'current_player' not in d):
            raise Exception('Not enough information to load.')

        print('loading from', d)
        self.shape = tuple(d['shape'])
        self.ball_coords = tuple(d['ball_coords'])
        print('ball coords set to', self.ball_coords)
        self.man_coords = set([tuple(coords) for coords in d['man_coords']])
        self.current_player = d['current_player']
        self.legal_moves = get_legal_moves(
            self.ball_coords, self.man_coords, self.shape)

        # Speculative saving not implemented yet. 
        self.reset_speculation()

        if 'message' in d:
            self.message = d['message']

    def load_file(self, filen):
        '''Loads json data from filen and sets the properties of self
        appropriately.'''
        with open(filen, 'r') as fileh:
            data = json.load(fileh)
        self.load_dict(data)