lama2923
Centipat
- Katılım
- 16 Temmuz 2023
- Mesajlar
- 20
Daha fazla
- Cinsiyet
- Diğer
Biliyorum kodun okunaklığı ve anlaşılabilirliği zor. Sizden en baştan bir kod vermenizi istemiyorum, bana fikir verseniz bile yeter. 1 haftadır bu şeyle ilgileniyorum…
Sorun şu: Analyze_game fonksiyonu gerçekten çok yavaş çalışıyor. Bunu çözmek için önerileriniz nedir?
Multiprocessing denedim ama başaramadım, benim beceriksizliğim sanırım.
(yavaş çalışan kısım stocfish.get_top_moves kısmı)
Sorun şu: Analyze_game fonksiyonu gerçekten çok yavaş çalışıyor. Bunu çözmek için önerileriniz nedir?
Multiprocessing denedim ama başaramadım, benim beceriksizliğim sanırım.
(yavaş çalışan kısım stocfish.get_top_moves kısmı)
Kod:
import chess
import chess.pgn
from stockfish import Stockfish
from lama2923 import clear_screen, llinput
import datetime
import time
import os
# TerminalCHESS - Stockfish * lama2923
class ChessGame:
def init(self, stockfish_path, stockfish_depth=12):
"""
INIT
"""
self.stockfish_depth = stockfish_depth
self.language = self.select_language()
self.messages = self.define_messages()
self.GAME_MODE = int(self.select_game_mode()) # 0: AI vs AI, 1: Player vs AI, 2: Player vs Player
self.stockfish = Stockfish(path=stockfish_path)
self.stockfish.set_depth(stockfish_depth)
self.board = None
self.move_history = []
if self.GAME_MODE == 0:
self.white_elo = self.get_elo(f" ({self.get_message('white')})")
self.black_elo = self.get_elo(f" ({self.get_message('black')})")
elif self.GAME_MODE == 2:
self.white_elo = 0
self.black_elo = 0
else:
if int(self.select_color()) == 1:
self.white_elo = self.get_elo(f" ({self.get_message('white')})")
self.black_elo = 0
else:
self.white_elo = 0
self.black_elo = self.get_elo(f" ({self.get_message('black')})")
self.unicode_pieces = self.define_unicode_pieces()
self.FEN = None
self.game_end = False
self.move_INDEX = 0
self.analyz_history = {}
self.move_analysis = {}
self.stockfish_history = {}
def str(self):
return self.move_history
def repr(self):
return self.move_history, self.FEN, self.white_elo, self.black_elo, self.GAME_MODE, self.stockfish_depth
def select_language(self):
"""
Dil seçmeye yarar.
-----------------------
Used to select language.
"""
all_languages = list(self.define_messages().keys())
chars = set()
for lang in all_languages:
for c in lang:
chars.add(c)
lang_choice = llinput("Select Language: ", wend=" (" + "/".join(all_languages) + ")", choices=(all_languages, False), availablechars=r"".join(chars), forceinput=True, max_length=2, min_length=2)
return lang_choice
def select_game_mode(self):
"""
Oyun modunu seçmeye yarar.
-----------------------
Used to select game mode.
"""
game_modes = {"0": "AI vs AI", "1": "Player vs AI", "2": "Player vs Player"}
wend_text = " "
for key, value in game_modes.items():
wend_text += f" | {key}: {value}"
game_mode_choice = llinput(self.get_message("SGM"), wend=wend_text, choices=(list(game_modes.keys()), False), forceinput=True, max_length=1, min_length=1)
return game_mode_choice
def select_color(self):
"""
Oyuncunun rengini seçmeye yarar
-----------------------
Used to select player's color
"""
colors = {"0": "White", "1": "Black"}
wend_text = " "
for key, value in colors.items():
wend_text += f" | {key}: {value}"
color_choice = llinput(self.get_message("SYC"), wend=wend_text, choices=(list(colors.keys()), False), forceinput=True, max_length=1, min_length=1)
return color_choice
def define_messages(self):
return {
"en": {
"SYC": "Select Your Color: ",
"SGM": "Select Game Mode: ",
"white": "White",
"black": "Black",
"yes": "y",
"no": "n",
"enter_elo": "Enter ELO rating: ",
"fen_prompt": "Enter FEN position: ",
"use_custom_fen": "Would you like to use a custom FEN?: ",
"game_over": "Game over!",
"winner": "Checkmate! Winner: ",
"draw": "The game ended in a draw!",
"white_turn": "Turn: White",
"black_turn": "Turn: Black",
"white_captured": "Captured by White: ",
"black_captured": "Captured by Black: ",
"white_elo": "White's ELO",
"black_elo": "Black's ELO",
"fen": "FEN: ",
"pgn_saved": "Game history saved as PGN."
},
"tr": {
"SYC": "Renginizi Seçin: ",
"SGM": "Oyun Modunu Seçin: ",
"white": "Beyaz",
"black": "Siyah",
"yes": "e",
"no": "h",
"enter_elo": "ELO derecesini girin: ",
"fen_prompt": "FEN pozisyonunu girin: ",
"use_custom_fen": "Özel bir FEN kullanmak istiyor musunuz?: ",
"game_over": "Oyun bitti!",
"winner": "Şah mat! Kazanan: ",
"draw": "Oyun berabere sona erdi!",
"white_turn": "Sıra: Beyaz",
"black_turn": "Sıra: Siyah",
"white_captured": "Beyaz tarafından alınan taşlar: ",
"black_captured": "Siyah tarafından alınan taşlar: ",
"white_elo": "Beyaz'ın ELO puanı: ",
"black_elo": "Siyah'ın ELO puanı: ",
"fen": "FEN: ",
"pgn_saved": "Oyun geçmişi PGN formatında kaydedildi."
},
"es": {
"SYC": "Selecciona tu color: ",
"SGM": "Selecciona el modo de juego: ",
"white": "Blanco",
"black": "Negro",
"yes": "s",
"no": "n",
"enter_elo": "Introduce tu puntuación ELO: ",
"fen_prompt": "Introduce la posición FEN: ",
"use_custom_fen": "¿Quieres usar una FEN personalizada?: ",
"game_over": "¡Juego terminado!",
"winner": "¡Jaque mate! Ganador: ",
"draw": "¡El juego terminó en empate!",
"white_turn": "Turno: Blanco",
"black_turn": "Turno: Negro",
"white_captured": "Piezas capturadas por Blanco: ",
"black_captured": "Piezas capturadas por Negro: ",
"white_elo": "ELO de Blanco: ",
"black_elo": "ELO de Negro: ",
"fen": "FEN: ",
"pgn_saved": "Historial del juego guardado como PGN."
},
"fr": {
"SYC": "Choisissez votre couleur : ",
"SGM": "Choisissez le mode de jeu : ",
"white": "Blanc",
"black": "Noir",
"yes": "o",
"no": "n",
"enter_elo": "Entrez votre classement ELO : ",
"fen_prompt": "Entrez la position FEN : ",
"use_custom_fen": "Voulez-vous utiliser un FEN personnalisé ? : ",
"game_over": "Partie terminée !",
"winner": "Échec et mat ! Gagnant : ",
"draw": "La partie s'est terminée par un match nul !",
"white_turn": "Tour : Blanc",
"black_turn": "Tour : Noir",
"white_captured": "Pièces capturées par Blanc : ",
"black_captured": "Pièces capturées par Noir : ",
"white_elo": "ELO de Blanc ",
"black_elo": "ELO de Noir ",
"fen": "FEN ",
"pgn_saved": "Historique de la partie sauvegardé en tant que PGN."
},
"de": {
"SYC": "Wähle deine Farbe: ",
"SGM": "Wähle den Spielmodus: ",
"white": "Weiß",
"black": "Schwarz",
"yes": "j",
"no": "n",
"enter_elo": "Gib deine ELO-Bewertung ein: ",
"fen_prompt": "Gib die FEN-Position ein: ",
"use_custom_fen": "Möchten Sie eine benutzerdefinierte FEN verwenden?: ",
"game_over": "Spiel vorbei!",
"winner": "Schachmatt! Gewinner: ",
"draw": "Das Spiel endete unentschieden!",
"white_turn": "Zug: Weiß",
"black_turn": "Zug: Schwarz",
"white_captured": "Gefangene Figuren von Weiß: ",
"black_captured": "Gefangene Figuren von Schwarz: ",
"white_elo": "ELO von Weiß: ",
"black_elo": "ELO von Schwarz: ",
"fen": "FEN: ",
"pgn_saved": "Spielverlauf als PGN gespeichert."
}
}
def get_message(self, key):
"""
Kullanıcın önceden seçtiği dile göre mesaj döndürür.
-----------------------
Returns message according to the language selected by the user.
"""
return self.messages[self.language].get(key, "")
def get_elo(self, wend=""):
"""
ELO puanını alır.
-----------------------
Gets the ELO rating.
"""
def enter_check(input_str):
if int(input_str) != 0:
return True
return False
return int(llinput(self.get_message("enter_elo"), wend=wend, forceint=True, forceinput=True, min_length=1, max_length=4, custom_enter_check_func=enter_check))
def set_board(self):
"""
Tahtayı Oluşturur.
-----------------------
Creates the board.
"""
if llinput(self.get_message("use_custom_fen"), wend=f" ({self.get_message("yes")}/{self.get_message("no")})", forceinput=True, choices=([self.get_message("yes"), self.get_message("no")], False), max_length=1, min_length=1).lower() == self.get_message("yes"):
self.FEN = self.custom_fen()
self.board = chess.Board(self.FEN)
else:
self.FEN = chess.Board().fen()
self.board = chess.Board()
def custom_fen(self):
"""
Custom FEN Almaya yarar.
-----------------------
Used to get custom FEN.
"""
def check_fen(fen):
try:
chess.Board(fen)
return True
except ValueError:
return False
return llinput(self.get_message("fen_prompt"), forceinput=True, min_length=1, max_length=71, custom_enter_check_func=check_fen)
def define_unicode_pieces(self):
return {
"P": "\033[1m♟︎\033[0m", "N": "\033[1m♞\033[0m", "B": "\033[1m♝\033[0m",
"R": "\033[1m♜\033[0m", "Q": "\033[1m♛\033[0m", "K": "\033[1m♚\033[0m",
"p": "\033[1m♙\033[0m", "n": "\033[1m♘\033[0m", "b": "\033[1m♗\033[0m",
"r": "\033[1m♖\033[0m", "q": "\033[1m♕\033[0m", "k": "\033[1m♔\033[0m"
}
def print_board(self, move_index=None, reverse_board=False):
"""
Tahtayı konsola çıktılar. Ayrıca oyun oynanırken stockfish değerlendirmesi yapar.
move_index: Hangi hamlenin gösterileceğini belirler.
reverse_board: Tahtayı ters çevirir.
------------------------------------------
Prints the board to the console. Also evaluates the board while playing the game.
move_index: Determines which move will be displayed.
reverse_board: Reverses the board.
"""
self.stockfish.set_depth(self.stockfish_depth)
if self.board:
text = ""
if move_index is None:
move_index = len(self.move_history)
if move_index > len(self.move_history):
move_index = len(self.move_history)
new_board = chess.Board(self.FEN)
for i in range(move_index):
new_board.push_uci(self.move_history)
if self.stockfish_history.get(new_board.fen()) is None:
stockfish = Stockfish()
stockfish.set_fen_position(new_board.fen())
stockfish.set_depth(self.stockfish_depth)
self.stockfish_history[new_board.fen()] = stockfish.get_evaluation()
stockfish_evaluation = self.stockfish_history[new_board.fen()]
eval_display = ""
if stockfish_evaluation["type"] == "mate":
eval_display = f"# {'+' if stockfish_evaluation['value'] > 0 else '-'}{abs(stockfish_evaluation['value'])}"
else:
eval_score = stockfish_evaluation["value"]
eval_score = max(min(eval_score, 1000), -1000)
eval_display = f"{eval_score / 100:+.2f}"
initial_counts = {chess.PAWN: 8, chess.KNIGHT: 2, chess.BISHOP: 2, chess.ROOK: 2, chess.QUEEN: 1}
piece_values = {chess.PAWN: 1, chess.KNIGHT: 3, chess.BISHOP: 3, chess.ROOK: 5, chess.QUEEN: 9}
white_captured, black_captured = [], []
material_difference = 0
for piece_type, count in initial_counts.items():
white_on_board = len(new_board.pieces(piece_type, chess.WHITE))
black_on_board = len(new_board.pieces(piece_type, chess.BLACK))
white_captured_count = count - white_on_board
black_captured_count = count - black_on_board
material_difference += (white_captured_count - black_captured_count) * piece_values[piece_type]
white_captured.extend([self.unicode_pieces[chess.Piece(piece_type, chess.BLACK).symbol()]] * black_captured_count)
black_captured.extend([self.unicode_pieces[chess.Piece(piece_type, chess.WHITE).symbol()]] * white_captured_count)
white_score = abs(material_difference) if material_difference < 0 else 0
black_score = abs(material_difference) if material_difference > 0 else 0
board_lines = [
"\n a b c d e f g h",
" ┌───┬───┬───┬───┬───┬───┬───┬───┐"
]
if reverse_board:
for rank in range(8):
row = f" {rank + 1} │"
for file in range(8):
piece = new_board.piece_at(chess.square(file, rank))
row += f" {self.unicode_pieces.get(piece.symbol(), ' ')} │" if piece else " │"
board_lines.append(row)
if rank < 7:
board_lines.append(" ├───┼───┼───┼───┼───┼───┼───┼───┤")
else:
for rank in range(7, -1, -1):
row = f" {rank + 1} │"
for file in range(8):
piece = new_board.piece_at(chess.square(file, rank))
row += f" {self.unicode_pieces.get(piece.symbol(), ' ')} │" if piece else " │"
board_lines.append(row)
if rank > 0:
board_lines.append(" ├───┼───┼───┼───┼───┼───┼───┼───┤")
board_lines.append(" └───┴───┴───┴───┴───┴───┴───┴───┘\n")
move_columns = []
num_moves = len(self.move_history)
for start in range(0, num_moves, 32):
column = []
for i in range(32):
index = start + i
if index >= num_moves:
break
move_number = index // 2 + 1
if index % 2 == 0:
if index == move_index - 1:
column.append(f"{move_number:>2}. {self.move_history[index]} <--")
else:
column.append(f"{move_number:>2}. {self.move_history[index]}")
else:
if index == move_index - 1:
column[-1] += f" {self.move_history[index]} <--"
else:
column[-1] += f" {self.move_history[index]}"
move_columns.append(column)
max_rows = max(len(board_lines), max((len(col) for col in move_columns), default=0))
clear_screen()
if self.game_end:
text += f"Eval ({self.stockfish.depth}): {eval_display}\n"
evalanalyz = self.analyz_history.get(new_board.fen())
if evalanalyz is not None:
evalanalyzdisplay = ""
if evalanalyz["type"] == "mate":
evalanalyzdisplay = f"# {'+' if evalanalyz['value'] > 0 else '-'}{abs(evalanalyz['value'])}"
else:
eval_score20 = evalanalyz["value"]
eval_score20 = max(min(eval_score20, 1000), -1000)
evalanalyzdisplay = f"{eval_score20 / 100:+.2f}"
else:
evalanalyzdisplay = evalanalyz
if evalanalyzdisplay is not None:
text += f"Eval (analyz): {evalanalyzdisplay}\n"
for key, value in self.move_analysis[str("black" if new_board.turn == chess.WHITE else "white")].items():
if new_board.fen() in value:
text += f"Move Category (analyz): {key}\n"
break
else:
if self.GAME_MODE == 0:
text += f"Eval: {eval_display}\n"
for row in range(max_rows):
board_part = board_lines[row] if row < len(board_lines) else ""
if row == 0:
text += f"{board_part:<35}\n"
else:
move_row = row - 1
columns_part = " | ".join(
move_columns[col][move_row] if move_row < len(move_columns[col]) else ""
for col in range(len(move_columns))
).strip(" |")
text += f"{board_part:<35} | {columns_part}\n" if columns_part else f"{board_part}\n"
text += f"{self.get_message('white_captured')} {' '.join(white_captured)} {'+{}'.format(white_score) if white_score > 0 else ''}\n"
text += f"{self.get_message('black_captured')} {' '.join(black_captured)} {'+{}'.format(black_score) if black_score > 0 else ''}\n\n"
text += f"{self.get_message('white_turn') if new_board.turn == chess.WHITE else self.get_message('black_turn')}\n"
text += f"{self.get_message('white_elo')}: {self.white_elo} {self.get_message('black_elo')}: {self.black_elo}\n"
text += f"{self.get_message('fen')}: {new_board.fen()}\n"
print(text, flush=True)
def save_pgn(self):
"""
Oyun Rotasyonunu PGN formatında kaydeder.
-----------------------
Saves the game rotation in PGN format.
"""
if self.board and self.move_history:
game = chess.pgn.Game()
game.headers["Event"] = f"Stockfish Game (Depth {self.stockfish.depth})"
game.headers["White"] = f"Stockfish (ELO {self.white_elo})"
game.headers["Black"] = f"Stockfish (ELO {self.black_elo})"
game.headers["Result"] = self.board.result()
game.headers["Date"] = datetime.datetime.now().strftime("%Y.%m.%d")
game.headers["FEN"] = self.FEN
board_position = chess.Board(self.FEN)
node = game
for move_uci in self.move_history:
move = chess.Move.from_uci(move_uci)
if move in board_position.legal_moves:
node = node.add_variation(move)
board_position.push(move)
else:
print(f"Illegal move: {move_uci}")
with open("game_history.pgn", "w") as pgn_file:
print(game, file=pgn_file)
print(self.get_message("pgn_saved"))
def is_playable_position(self):
"""
True: oynanabilir durum
False: oynanamaz durum
-----------------------
True: playable position
False: unplayable position
"""
board = self.board.copy()
stockfish = self.stockfish
stockfish.set_fen_position(board.fen())
evaluation = stockfish.get_evaluation()
if evaluation["type"] == "cp":
value = evaluation["value"]
if (board.turn == chess.BLACK and value >= -500) or (board.turn == chess.WHITE and value <= 500):
return True # oynanabilir durum. Unplayable position.
else:
return False # Oynanamaz durum. Unplayable position.
elif evaluation["type"] == "mate":
if board.turn == chess.WHITE and evaluation["value"] < 0:
return True # Oynanabilir durum. Unplayable position.
elif board.turn == chess.BLACK and evaluation["value"] > 0:
return True # Oynanabilir durum. Unplayable position.
else:
return False # Oynanamaz durum. Unplayable position.
else:
return False # Oynanamaz durum. Unplayable position.
def is_draw(self):
"""
True: Berabere
False: Berabere değil
-----------------------
True: Draw
False: Not draw
"""
board = self.board
return any([board.is_stalemate(), board.is_insufficient_material(), board.is_seventyfive_moves(), board.is_fivefold_repetition(), board.is_variant_draw()])
def get_skill_level(self, elo_rating):
"""
ELO puanı ile orantılı bir şekilde skill_level'i belirler.
-----------------------
Determines the skill_level proportionally with the ELO rating.
"""
return max(0, min(20, int(elo_rating) // 50))
def get_depth_level(self, elo_rating):
"""
ELO puanı ile orantılı bir şekilde depth_level'i belirler.
-----------------------
Determines the depth_level proportionally with the ELO rating.
"""
return max(1, min(int(self.stockfish.depth), int(elo_rating) // 100))
def get_key(self):
"""
sadece rewiev_game fonksiyonunda çağırılır. Arrow key'leri algılar ve döndürür.
-----------------------
Called only in the rewiev_game function. Detects and returns the arrow keys.
"""
if os.name == "nt": # Windows
import msvcrt
key = msvcrt.getch()
if key in [b"\xe0", b"\x00"]: # Ok tuşları. Arrow keys.
key = msvcrt.getch()
if key == b"H":
return "UP"
elif key == b"P":
return "DOWN"
elif key == b"M":
return "RIGHT"
elif key == b"K":
return "LEFT"
else: # Linux/Unix
import termios
import tty
import sys
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(fd)
key = sys.stdin.read(1)
if key == "\x1b":
key = sys.stdin.read(2)
if key == "[A":
return "UP"
elif key == "[B":
return "DOWN"
elif key == "[C":
return "RIGHT"
elif key == "[D":
return "LEFT"
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return None
def rewiev_game(self):
"""
Oyun bittiğinde incelemeye yarar.
-----------------------
Used to review the game when the game ends.
"""
while True:
if self.game_end:
key = self.get_key()
if key == "UP":
self.move_INDEX = len(self.move_history)
elif key == "DOWN":
self.move_INDEX = 0
elif key == "LEFT":
self.move_INDEX = self.move_INDEX - 1 if self.move_INDEX > 0 else 0
elif key == "RIGHT":
if self.move_INDEX < len(self.move_history):
self.move_INDEX += 1
self.print_board(self.move_INDEX)
def analyze_game(self):
"""
Oyunu analiz eder.
-----------------------
Analyzes the game.
"""
board = chess.Board(self.FEN)
stockfish = Stockfish()
self.stockfish.set_depth(self.stockfish_depth)
stockfish.set_depth(20)
analyzed_moves = 0
move_analysis = {
"white": {
"brilliant": [],
"best": [],
"excellent": [],
"good": [],
"inaccuracy": [],
"mistake": [],
"blunder": [],
"missed_win": [],
"unknown": [],
},
"black": {
"brilliant": [],
"best": [],
"excellent": [],
"good": [],
"inaccuracy": [],
"mistake": [],
"blunder": [],
"missed_win": [],
"unknown": [],
}
}
evaluation_changes = {"white": [], "black": []}
def update_bar():
bar = "█" * int(analyzed_moves / len(self.move_history) * 50) + f" %{int(analyzed_moves / len(self.move_history) * 100)}"
print(f"Analiz: {bar} {analyzed_moves}/{len(self.move_history)}", end="\r")
if board.fen() not in self.analyz_history:
stockfish.set_fen_position(board.fen())
evaluation_before = stockfish.get_evaluation()
self.analyz_history[board.fen()] = evaluation_before
else:
evaluation_before = self.analyz_history[board.fen()]
for move in self.move_history:
player = "white" if board.turn == chess.WHITE else "black"
board.push_uci(move)
main_board_fen = board.fen()
analyzed_moves += 1
if int(self.stockfish_depth) >= int(stockfish.depth):
if board.fen() not in self.stockfish_history:
stockfish.set_fen_position(board.fen())
evaluation_after = stockfish.get_evaluation()
self.analyz_history[board.fen()] = evaluation_after
else:
evaluation_after = self.stockfish_history[board.fen()]
self.analyz_history[board.fen()] = evaluation_after
else:
if board.fen() in self.analyz_history:
evaluation_after = self.analyz_history[board.fen()]
else:
stockfish.set_fen_position(board.fen())
evaluation_after = stockfish.get_evaluation()
self.analyz_history[board.fen()] = evaluation_after
eval_diff = None
if evaluation_before["type"] == "cp" and evaluation_after["type"] == "cp":
eval_diff = evaluation_after["value"] - evaluation_before["value"]
elif evaluation_before["type"] == "mate" or evaluation_after["type"] == "mate":
if evaluation_before["type"] == "mate" and evaluation_after["type"] == "mate":
eval_diff = evaluation_after["value"] - evaluation_before["value"]
if player == "black":
if eval_diff is not None:
eval_diff = -eval_diff
board.pop()
stockfish.set_fen_position(board.fen())
stockfish.set_depth(20)
top_moves = stockfish.get_top_moves(6)
try:
top_moves = [move["Move"] for move in top_moves]
except:
top_moves = []
if top_moves:
best_move = top_moves[0]
if eval_diff is not None:
evaluation_changes[player].append({
"move": move,
"eval_diff": eval_diff
})
if eval_diff >= 200 and move == best_move:
move_analysis[player]["brilliant"].append(main_board_fen)
elif move == best_move:
move_analysis[player]["best"].append(main_board_fen)
elif len(top_moves) >= 1 and move in top_moves:
stockfish.set_fen_position(board.fen())
main_move = move
x_flag = False
for move2 in top_moves:
if move2 == main_move:
continue
board.push_uci(move2)
stockfish.set_fen_position(board.fen())
evaluation_move = stockfish.get_evaluation()
if evaluation_move["type"] == "cp":
eval_diff2 = evaluation_move["value"] - evaluation_after["value"]
else:
eval_diff2 = evaluation_move["value"]
if player == "black":
if eval_diff2 is not None:
eval_diff2 = -eval_diff2
board.pop()
if eval_diff2 >= 50 and eval_diff < 0:
if -100 <= eval_diff:
move_analysis[player]["inaccuracy"].append(main_board_fen)
elif -300 <= eval_diff < -100:
move_analysis[player]["mistake"].append(main_board_fen)
elif eval_diff < -300:
move_analysis[player]["blunder"].append(main_board_fen)
x_flag = True
break
if not x_flag:
move_analysis[player]["excellent"].append(main_board_fen)
elif 0 <= eval_diff:
move_analysis[player]["good"].append(main_board_fen)
elif -100 <= eval_diff:
move_analysis[player]["inaccuracy"].append(main_board_fen)
elif -300 <= eval_diff < -100:
move_analysis[player]["mistake"].append(main_board_fen)
elif eval_diff < -300:
move_analysis[player]["blunder"].append(main_board_fen)
else:
if evaluation_before["type"] == "mate" and evaluation_after["type"] != "mate":
move_analysis[player]["missed_win"].append(main_board_fen)
else:
move_analysis[player]["unknown"].append(main_board_fen)
board.push_uci(move)
evaluation_before = evaluation_after
update_bar()
print("\n")
def calculate_accuracy_with_eval_changes(move_analysis: dict):
accuracies = {"white": 0, "black": 0}
for player in ["white", "black"]:
accuracies[player] = 0
correct_moves = len(move_analysis[player]["brilliant"]) + len(move_analysis[player]["best"]) + len(move_analysis[player]["excellent"]) + len(move_analysis[player]["good"])
incorrect_moves = len(move_analysis[player]["inaccuracy"]) + len(move_analysis[player]["mistake"]) + len(move_analysis[player]["blunder"])
total_moves = correct_moves + incorrect_moves
if total_moves > 0:
accuracies[player] = (correct_moves / total_moves) * 100
return accuracies
accuracies = calculate_accuracy_with_eval_changes(move_analysis)
white_accuracy_percentage = max(0, min(accuracies["white"], 100))
black_accuracy_percentage = max(0, min(accuracies["black"], 100))
print("--------------")
print(f"Beyaz doğruluk: %{white_accuracy_percentage:.2f}")
print(f"Siyah doğruluk: %{black_accuracy_percentage:.2f}")
print("\n\n")
print(" White | Black")
print(" -----------|-----------")
for key in ["brilliant", "best", "excellent", "good", "inaccuracy", "mistake", "blunder", "missed_win", "unknown"]:
white_moves_len = len(move_analysis["white"][key])
black_moves_len = len(move_analysis["black"][key])
print(f"{key.capitalize() + ' ' * (10 - len(key))} {white_moves_len}{' ' * (10 - len(str(white_moves_len)))}| {black_moves_len}")
self.move_analysis = move_analysis
self.rewiev_game()
def bot_move(self):
"""
Bot'un en iyi hamlesini, Botun ELO puanına göre döndürür. Bazı durumlarda oyun berabere bitmemesi adına ve oyunun oynanabilir bir durumda olması durumunda, oyunu kaybettirmeyecek alternatif hamleler de döndürebilir.
-----------------------
Returns the best move of the bot according to the Bot's ELO rating. In some cases, it can return alternative moves that will not lose the game in order to prevent the game from ending in a draw and if the game is in a playable position.
"""
if self.stockfish:
board = self.board.copy()
stockfish = self.stockfish
elo_rating = self.white_elo if self.board.turn == chess.WHITE else self.black_elo
stockfish.set_elo_rating(elo_rating)
stockfish.set_depth(self.get_depth_level(elo_rating))
stockfish.set_skill_level(self.get_skill_level(elo_rating))
stockfish.set_fen_position(self.board.fen())
best_move = stockfish.get_best_move()
if best_move is None:
print("No legal moves.")
return None
board.push_uci(best_move)
stockfish.set_fen_position(board.fen())
if board.is_game_over() and self.is_draw():
board.pop()
stockfish.set_fen_position(board.fen())
if self.is_playable_position():
alternative_moves = [move['Move'] for move in stockfish.get_top_moves(6)]
found_move = False
for move in alternative_moves:
if move == best_move:
continue
if move:
board.push_uci(move)
stockfish.set_fen_position(board.fen())
if self.is_playable_position():
board.pop()
return move
else:
board.pop()
else:
print(f"İllegal move: {move}")
if not found_move:
return best_move
else:
return best_move
return best_move
def convert_to_uci(self, short_move):
"""
Kısaltılmış bir hamleyi (örneğin e4, Nf5) tam UCI formatına çevirir.
-----------------------
Converts a short move (e.g. e4, Nf5) to full UCI format.
"""
board = self.board.copy()
for move in board.legal_moves:
if board.san(move) == short_move:
return move.uci()
if short_move == "O-O" or short_move == "0-0":
for move in board.legal_moves:
if board.is_kingside_castling(move):
return move.uci()
if short_move == "O-O-O" or short_move == "0-0-0":
for move in board.legal_moves:
if board.is_queenside_castling(move):
return move.uci()
return short_move
def start_game(self):
"""
Ana oyun döngüsü.
-----------------------
Main game loop.
"""
self.set_board()
self.print_board()
def get_move(Move):
try:
if chess.Move.from_uci(Move) in self.board.legal_moves:
return chess.Move.from_uci(Move)
except:
try:
if Move in self.board.legal_moves:
return Move
except:
return None
return None
while not self.board.is_game_over() or self.game_end:
self.stockfish.set_depth(self.stockfish_depth)
if self.GAME_MODE == 0:
move = self.bot_move()
if move is None:
self.game_end = True
break
elif self.GAME_MODE == 1:
if self.white_elo == 0:
player_color = chess.WHITE
else:
player_color = chess.BLACK
if self.board.turn == player_color:
while True:
print("Commands: 'resign', 'takeback'\n")
move = llinput("Your move: ", forceinput=True)
move = self.convert_to_uci(move)
if move == "resign":
break
elif move == "takeback":
if len(self.move_history) > 1:
self.board.pop()
self.board.pop()
self.move_history.pop()
self.move_history.pop()
break
elif len(self.move_history) == 1:
self.board.pop()
self.move_history.pop()
break
else:
print("No moves to take back.")
continue
if get_move(move):
break
else:
move = self.bot_move()
if move is None:
self.game_end = True
break
elif self.GAME_MODE == 2:
if self.board.turn == chess.WHITE:
while True:
print("Commands: 'resign', 'takeback'\n")
move = llinput("White's move: ", forceinput=True)
move = self.convert_to_uci(move)
if move == "resign":
break
elif move == "takeback":
if len(self.move_history) > 1:
self.board.pop()
self.board.pop()
self.move_history.pop()
self.move_history.pop()
break
elif len(self.move_history) == 1:
self.board.pop()
self.move_history.pop()
break
else:
print("No moves to take back.")
continue
if get_move(move):
break
else:
while True:
print("Commands: 'resign', 'takeback'\n")
move = llinput("Black's move: ", forceinput=True)
move = self.convert_to_uci(move)
if move == "resign":
break
elif move == "takeback":
if len(self.move_history) > 1:
self.board.pop()
self.board.pop()
self.move_history.pop()
self.move_history.pop()
break
elif len(self.move_history) == 1:
self.board.pop()
self.move_history.pop()
break
else:
print("No moves to take back.")
continue
if get_move(move):
break
if move == "resign":
print(f"{('White' if self.board.turn == chess.WHITE else 'Black')} resigned.")
self.game_end = True
break
if move:
if move not in ("resign", "takeback"):
self.move_history.append(move)
self.board.push_uci(move)
if self.GAME_MODE == 0:
if self.white_elo >= self.black_elo:
self.print_board()
else:
self.print_board(reverse_board=True)
elif self.GAME_MODE == 1:
if self.white_elo == 0:
self.print_board()
else:
self.print_board(reverse_board=True)
elif self.GAME_MODE == 2:
if self.board.turn == chess.WHITE:
self.print_board()
else:
self.print_board(reverse_board=True)
else:
self.print_board()
self.game_end = True
time.sleep(1)
if self.board.is_checkmate():
print(f"{self.get_message('winner')} {('Black' if self.board.turn == chess.WHITE else 'White')}")
elif self.board.is_stalemate():
print(self.get_message("draw"))
elif self.board.is_insufficient_material():
print(self.get_message("draw"))
elif self.board.is_seventyfive_moves():
print(self.get_message("draw"))
elif self.board.is_fivefold_repetition():
print(self.get_message("draw"))
else:
print(self.get_message("game_over"))
self.save_pgn()
print("\n\n")
self.analyze_game()
if name == "main":
chess_game = ChessGame(stockfish_path="/workspaces/Tests/stockfishTest/stockfish", stockfish_depth=20) # Stockfish path'i ve depth'i değiştirebilirsiniz. You can change the Stockfish path and depth.
chess_game.start_game() # Oyunu başlatır. Starts the game.
Son düzenleme: