Spaces:
Sleeping
Sleeping
| import chess | |
| import random | |
| import time | |
| from . import evaluation | |
| def random_move(board): | |
| """ | |
| Trả về một nước đi ngẫu nhiên từ các nước đi hợp lệ. | |
| """ | |
| legal_moves = list(board.legal_moves) | |
| if not legal_moves: | |
| return None | |
| return random.choice(legal_moves) | |
| def find_best_move(board, weights_dict, depth): | |
| """ | |
| Tìm nước đi tốt nhất sử dụng Minimax với Alpha-Beta Pruning. | |
| """ | |
| legal_moves = list(board.legal_moves) | |
| if not legal_moves: | |
| return None | |
| start_time = time.time() | |
| print(f"AI đang tính toán với độ sâu {depth}...") | |
| best_move = None | |
| max_eval = -float('inf') | |
| alpha = -float('inf') | |
| beta = float('inf') | |
| nodes_evaluated = 0 | |
| # Sắp xếp các nước đi để tối ưu alpha-beta pruning | |
| # Ưu tiên các nước đi ăn quân và chiếu | |
| def move_priority(move): | |
| score = 0 | |
| # Nước đi ăn quân có ưu tiên cao | |
| if board.piece_at(move.to_square): | |
| captured_piece = board.piece_at(move.to_square) | |
| piece_values = {chess.PAWN: 10, chess.KNIGHT: 30, chess.BISHOP: 30, | |
| chess.ROOK: 50, chess.QUEEN: 90, chess.KING: 900} | |
| score += piece_values.get(captured_piece.piece_type, 0) | |
| # Kiểm tra xem có chiếu không | |
| board.push(move) | |
| if board.is_check(): | |
| score += 50 | |
| board.pop() | |
| return score | |
| sorted_moves = sorted(legal_moves, key=move_priority, reverse=True) | |
| for i, move in enumerate(sorted_moves): | |
| board.push(move) | |
| # Gọi minimax với negamax | |
| eval_score = -minimax_search(board, weights_dict, depth - 1, -beta, -alpha) | |
| nodes_evaluated += 1 | |
| board.pop() | |
| if eval_score > max_eval: | |
| max_eval = eval_score | |
| best_move = move | |
| alpha = max(alpha, eval_score) | |
| if beta <= alpha: | |
| break # Alpha-beta pruning | |
| end_time = time.time() | |
| elapsed_time = end_time - start_time | |
| print(f"AI chọn nước đi: {best_move.uci() if best_move else 'None'}") | |
| print(f"Điểm đánh giá: {max_eval:.2f}") | |
| print(f"Thời gian: {elapsed_time:.2f}s, Nodes: {nodes_evaluated}") | |
| return best_move | |
| def minimax_search(board, weights_dict, depth, alpha, beta): | |
| """ | |
| Hàm đệ quy Minimax với Alpha-Beta Pruning (Negamax implementation) | |
| """ | |
| # Điều kiện dừng: game over | |
| if board.is_game_over(): | |
| eval_score = evaluation.evaluate_board(board, weights_dict) | |
| return eval_score if board.turn == chess.WHITE else -eval_score | |
| # Khi depth = 0, sử dụng quiescence search | |
| if depth == 0: | |
| return quiescence_search(board, weights_dict, alpha, beta) | |
| max_eval = -float('inf') | |
| legal_moves = list(board.legal_moves) | |
| # Sắp xếp nước đi để tối ưu pruning | |
| def move_priority(move): | |
| score = 0 | |
| if board.piece_at(move.to_square): | |
| captured_piece = board.piece_at(move.to_square) | |
| piece_values = {chess.PAWN: 10, chess.KNIGHT: 30, chess.BISHOP: 30, | |
| chess.ROOK: 50, chess.QUEEN: 90, chess.KING: 900} | |
| score += piece_values.get(captured_piece.piece_type, 0) | |
| return score | |
| sorted_moves = sorted(legal_moves, key=move_priority, reverse=True) | |
| for move in sorted_moves: | |
| board.push(move) | |
| # Gọi đệ quy với negamax | |
| eval_score = -minimax_search(board, weights_dict, depth - 1, -beta, -alpha) | |
| board.pop() | |
| max_eval = max(max_eval, eval_score) | |
| alpha = max(alpha, eval_score) | |
| # Alpha-beta pruning | |
| if beta <= alpha: | |
| break | |
| return max_eval | |
| def quiescence_search(board, weights_dict, alpha, beta): | |
| """ | |
| Quiescence search để đánh giá tốt hơn các vị trí có capture | |
| """ | |
| # Đánh giá vị trí hiện tại | |
| stand_pat = evaluation.evaluate_board(board, weights_dict) | |
| stand_pat = stand_pat if board.turn == chess.WHITE else -stand_pat | |
| if stand_pat >= beta: | |
| return beta | |
| if alpha < stand_pat: | |
| alpha = stand_pat | |
| # Chỉ xem xét các nước đi capture | |
| capture_moves = [move for move in board.legal_moves if board.piece_at(move.to_square)] | |
| for move in capture_moves: | |
| board.push(move) | |
| score = -quiescence_search(board, weights_dict, -beta, -alpha) | |
| board.pop() | |
| if score >= beta: | |
| return beta | |
| if score > alpha: | |
| alpha = score | |
| return alpha |