0% found this document useful (0 votes)
13 views8 pages

Codechest

The document contains a Python implementation of a chess game using a Q-Network AI for decision-making. It includes classes for the Q-Network, a replay buffer for storing experiences, and functions for handling player moves, AI moves, and drawing the chessboard. The main function initializes the game, manages the game loop, and integrates the AI's decision-making process with player interactions.

Uploaded by

hotrongphuoc2006
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
13 views8 pages

Codechest

The document contains a Python implementation of a chess game using a Q-Network AI for decision-making. It includes classes for the Q-Network, a replay buffer for storing experiences, and functions for handling player moves, AI moves, and drawing the chessboard. The main function initializes the game, manages the game loop, and integrates the AI's decision-making process with player interactions.

Uploaded by

hotrongphuoc2006
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 8

import chess

import pygame
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
import sys
import random
from collections import deque

# === Mạng Q-Network ===


class ChessQNet(nn.Module):
def __init__(self):
super(ChessQNet, self).__init__()
self.fc1 = nn.Linear(773, 128)
self.fc2 = nn.Linear(128, 64)
self.fc3 = nn.Linear(64, 1) # Giá trị Q của mỗi hành động

def forward(self, x):


x = torch.relu(self.fc1(x))
x = torch.relu(self.fc2(x))
x = self.fc3(x)
return x

# === Biểu diễn trạng thái bàn cờ ===


def board_to_tensor(board):
tensor = np.zeros(773)
piece_map = board.piece_map()
for square, piece in piece_map.items():
piece_idx = piece.piece_type - 1 + (6 if piece.color == chess.BLACK else 0)
tensor[square * 12 + piece_idx] = 1
tensor[-9:] = [
board.turn,
board.has_kingside_castling_rights(chess.WHITE),
board.has_queenside_castling_rights(chess.WHITE),
board.has_kingside_castling_rights(chess.BLACK),
board.has_queenside_castling_rights(chess.BLACK),
board.is_check(),
board.is_checkmate(),
board.is_stalemate(),
board.is_insufficient_material(),
]
return torch.tensor(tensor, dtype=torch.float32)

# === Vẽ bàn cờ và quân cờ ===


def draw_board(screen, board, square_size):
colors = [pygame.Color(240, 217, 181), pygame.Color(181, 136, 99)]
font = pygame.font.Font("DejaVuSans.ttf", square_size // 2)
unicode_pieces = {
'P': '♙', 'N': '♘', 'B': '♗', 'R': '♖', 'Q': '♕', 'K': '♔',
'p': '♟', 'n': '♞', 'b': '♝', 'r': '♜', 'q': '♛', 'k': '♚'
}

for row in range(8):


for col in range(8):
color = colors[(row + col) % 2]
pygame.draw.rect(screen, color, pygame.Rect(col * square_size, row * square_size,
square_size, square_size))

pieces = board.piece_map()
for square, piece in pieces.items():
row, col = divmod(square, 8)
piece_text = unicode_pieces[piece.symbol()]
text_surface = font.render(piece_text, True, pygame.Color('black' if piece.color ==
chess.WHITE else 'white'))
text_rect = text_surface.get_rect(center=((col + 0.5) * square_size, (row + 0.5) *
square_size))
screen.blit(text_surface, text_rect)

# === Popup phong tốt ===


def promote_pawn_popup():
options = ["Queen", "Rook", "Bishop", "Knight"]
print("Phong tốt: Hãy chọn quân cờ:")
for i, option in enumerate(options, 1):
print(f"{i}. {option}")

while True:
try:
choice = int(input("Lựa chọn (1-4): "))
if 1 <= choice <= 4:
return [chess.QUEEN, chess.ROOK, chess.BISHOP, chess.KNIGHT][choice - 1]
except ValueError:
pass
print("Lựa chọn không hợp lệ. Vui lòng thử lại.")
# === Replay Buffer ===
class ReplayBuffer:
def __init__(self, capacity):
self.buffer = deque(maxlen=capacity)

def push(self, state, action, reward, next_state, done):


self.buffer.append((state, action, reward, next_state, done))

def sample(self, batch_size):


batch = random.sample(self.buffer, batch_size)
states, actions, rewards, next_states, dones = zip(*batch)
return states, actions, rewards, next_states, dones

def __len__(self):
return len(self.buffer)

# === Xử lý nước đi người chơi ===


def handle_player_move(board, from_square, to_square):
piece = board.piece_at(from_square)
if piece and piece.piece_type == chess.PAWN and chess.square_rank(to_square) in [0, 7]:
promotion = promote_pawn_popup()
move = chess.Move(from_square, to_square, promotion=promotion)
else:
move = chess.Move(from_square, to_square)

if move in board.legal_moves:
board.push(move)
print(f"Player moved: {move}")
else:
print("Nước đi không hợp lệ.")

# === AI chọn nước đi ===


def select_ai_move(board, model, epsilon=0.1):
legal_moves = list(board.legal_moves)
if not legal_moves:
return None

if random.random() < epsilon:


return random.choice(legal_moves)
else:
state = board_to_tensor(board).unsqueeze(0)
q_values = []
for move in legal_moves:
board.push(move)
next_state = board_to_tensor(board).unsqueeze(0)
q_value = model(next_state).item()
q_values.append(q_value)
board.pop()

best_move_idx = np.argmax(q_values)
return legal_moves[best_move_idx]

# === Huấn luyện Q-Network ===


def train_q_network(model, optimizer, replay_buffer, batch_size, gamma=0.99):
if len(replay_buffer) < batch_size:
return
states, actions, rewards, next_states, dones = replay_buffer.sample(batch_size)
states = torch.stack(states)
next_states = torch.stack(next_states)
rewards = torch.tensor(rewards, dtype=torch.float32).unsqueeze(1)
dones = torch.tensor(dones, dtype=torch.float32).unsqueeze(1)

q_values = model(states)

with torch.no_grad():
next_q_values = model(next_states)
max_next_q_values = next_q_values.max(1, keepdim=True)[0]

targets = rewards + gamma * max_next_q_values * (1 - dones)

loss = nn.MSELoss()(q_values, targets)

optimizer.zero_grad()
loss.backward()
optimizer.step()

# === Main ===


def main():
pygame.init()
square_size = 80
screen = pygame.display.set_mode((square_size * 8, square_size * 8))
pygame.display.set_caption("Cờ vua với Q-Network AI")
clock = pygame.time.Clock()
board = chess.Board()
model = ChessQNet()
optimizer = optim.Adam(model.parameters(), lr=0.001)
replay_buffer = ReplayBuffer(capacity=10000)
batch_size = 32

ai_plays_white = random.choice([True, False])


print(f"AI sẽ chơi {'trắng' if ai_plays_white else 'đen'}")

running = True
selected_square = None

while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN and board.turn != ai_plays_white:
pos = pygame.mouse.get_pos()
col, row = pos[0] // square_size, pos[1] // square_size
square = row * 8 + col
if selected_square is None:
selected_square = square
else:
handle_player_move(board, selected_square, square)
selected_square = None

if board.turn == ai_plays_white and not board.is_game_over():


state = board_to_tensor(board)
ai_move = select_ai_move(board, model)
if ai_move:
board.push(ai_move)
print(f"AI moved: {ai_move}")
reward = 1 if board.is_checkmate() else 0
next_state = board_to_tensor(board)
replay_buffer.push(state, ai_move, reward, next_state, board.is_game_over())

train_q_network(model, optimizer, replay_buffer, batch_size)

screen.fill(pygame.Color('white'))
draw_board(screen, board, square_size)
pygame.display.flip()
clock.tick(30)

pygame.quit()
sys.exit()

if __name__ == "__main__":
main()

You might also like