def main(): screen = p.display.set_mode((WIDTH, HEIGHT)) clock = p.time.Clock() screen.fill(p.Color(WHITE)) gs = GameState() # gs is the game state validMoves = gs.getValidMoves() moveMade = False loadImages() # we are only loading the images once in pygame running = True sqSelected = () # keeps track of the last user mouse clicks playerClicks = [] # keeps track of the last player clicks while running: for e in p.event.get(): if e.type == p.QUIT: running = False # mouse key handlers elif e.type == p.MOUSEBUTTONDOWN: location = p.mouse.get_pos() # location of x and y col = location[0] // SQ_SIZE row = location[1] // SQ_SIZE if sqSelected == (row, col): sqSelected = () playerClicks = [] # if the player clicks on a chess piece else: sqSelected = (row, col) playerClicks.append( sqSelected ) # this appends both the 1st and the 2nd clicks if len(playerClicks) == 2: # if the user made 2 mouse clicks move = Move(playerClicks[0], playerClicks[1], gs.board) print( str(move.getChessNotation()) + ' id: ' + str(move.moveID)) for i in range(len(validMoves)): if move == validMoves[i]: gs.makeMove(validMoves[i]) moveMade = True sqSelected = () playerClicks = [] # resets user clicks if not moveMade: playerClicks = [sqSelected] # keyboard handlers elif e.type == p.KEYDOWN: if e.key == p.K_z: # the undo key gs.undoMove() moveMade = True if moveMade: validMoves = gs.getValidMoves() moveMade = False drawGameState(screen, gs) clock.tick(MAX_FPS) p.display.flip()
def minimax(board: GameState, alpha: float, beta: float, maximizer: bool, curDepth: int, max_depth: int) -> Tuple[float, Move]: """ returns an integer score and move which is the best current player can get """ if board.is_game_over(): if board.staleMate: return 0, None if board.checkMate: return (-inf if maximizer else +inf), None if curDepth == max_depth: return evaluate(board, not (board.whiteToMove ^ maximizer)), None # sending inf so that the branch is ignored by parent if final_move is not None and time() - stime > timeout: return +inf if maximizer else -inf, None moves = list(board.getValidMoves()) # moves.sort(key=move_score, reverse=True) assert moves != [] best_move = None if maximizer: best_score = -inf def is_better_score(curr, currbest): return curr >= currbest def update_AB(score): nonlocal alpha alpha = max(alpha, score) else: best_score = +inf def is_better_score(curr, currbest): return curr <= currbest def update_AB(score): nonlocal beta beta = min(beta, score) for move in moves: board.makeMove(move, by_AI=True) global moves_cnt moves_cnt += 1 curr_score, _ = minimax(board, alpha, beta, not maximizer, curDepth + 1, max_depth) board.undoMove() if is_better_score(curr_score, best_score): best_score = curr_score best_move = move update_AB(best_score) if alpha >= beta: break return best_score, best_move
def minimax(board: GameState, moves: List[Move], alpha: float, beta: float, maximizer: bool, curDepth: int, max_depth: int, moves_line: List[Move]) -> Tuple[float, Move, List[Move]]: """ returns an integer score and move which is the best current player can get """ if board.is_game_over(): moves_line.append(None) if board.staleMate: return 0, None, moves_line if board.checkMate: return (-inf if maximizer else +inf), None, moves_line if curDepth == max_depth: return evaluate(board, not(board.whiteToMove ^ maximizer)), None, moves_line # sending inf so that the branch is ignored by parent if final_move is not None and time() - stime > timeout: moves_line.append(None) return +inf if maximizer else -inf, None, moves_line # moves = list(board.getValidMoves()) assert moves != [] best_move = None best_line = [] best_score = -inf if maximizer else +inf for move in moves: board.makeMove(move, by_AI=True) moves_line.append(move) global moves_cnt moves_cnt += 1 curr_score, _, curr_line = minimax( board, board.getValidMoves(), alpha, beta, not maximizer, curDepth+1, max_depth, moves_line[:]) board.undoMove() moves_line.pop() if maximizer: if curr_score >= best_score: best_score, best_move, best_line = curr_score, move, curr_line alpha = max(alpha, best_score) else: if curr_score <= best_score: best_score, best_move, best_line = curr_score, move, curr_line beta = min(beta, best_score) if alpha >= beta: break return best_score, best_move, best_line