Загрузка данных
import time
import keyboard
import chess
from analysis import ChessAnalyzer
import crop
class ChessLogic:
def __init__(self):
self.analyzer = ChessAnalyzer()
# Шахматный движок правил
self.board = chess.Board()
self.last_crop_matrix = None
self.is_analyzed = False
def start_initial_analysis(self):
"""Единоразовый запуск по 'S'"""
print("\n[!] Нажата 'S'. Запуск анализа доски...")
board_matrix = self.analyzer.analyze_initial_board()
if board_matrix:
# 1. Загружаем полученный FEN в python-chess
fen_str = self.matrix_to_fen(board_matrix)
try:
self.board = chess.Board(fen_str)
except ValueError:
# Если FEN несовершенен, создаем стандартную доску
print("[!] Предупреждение: FEN распознан с ошибкой, загружаем стандартную расстановку.")
self.board = chess.Board()
# 2. Фиксируем начальный снимок от crop.py
crop_matrix, _ = crop.find_chessboard_strictly_1to1()
self.last_crop_matrix = crop_matrix
self.is_analyzed = True
print("[✓] Первичный анализ завершен!")
self.print_board()
print(f"Текущий FEN: {self.board.fen()}\n")
else:
print("[!] Ошибка: не удалось проанализировать доску.")
def matrix_to_fen(self, board_matrix):
"""Превращает матрицу 8x8 от analysis.py в FEN-строку"""
fen_rows = []
for row in board_matrix:
empty_count = 0
row_fen = ""
for cell in row:
if cell == "":
empty_count += 1
else:
if empty_count > 0:
row_fen += str(empty_count)
empty_count = 0
row_fen += cell
if empty_count > 0:
row_fen += str(empty_count)
fen_rows.append(row_fen)
position_fen = "/".join(fen_rows)
# По умолчанию начинаем с хода белых 'w'
return f"{position_fen} w KQkq - 0 1"
def print_board(self):
"""Вывод доски в консоль"""
print("\n" + str(self.board) + "\n")
def track_board_changes(self):
"""Сравнивает изменения от crop.py с ЛЕГАЛЬНЫМИ ходами по правилам шахмат"""
if not self.is_analyzed or self.last_crop_matrix is None:
return
new_crop_matrix, _ = crop.find_chessboard_strictly_1to1()
if new_crop_matrix is None:
return
from_cells = [] # True -> False (освободившиеся клетки)
to_cells = [] # False -> True (новые занятые клетки)
for r in range(8):
for c in range(8):
old_val = self.last_crop_matrix[r][c]
new_val = new_crop_matrix[r][c]
if old_val and not new_val:
from_cells.append((r, c))
elif not old_val and new_val:
to_cells.append((r, c))
# Если изменений не обнаружено — выходим
if not from_cells and not to_cells:
return
# Переводим индексы (row, col) в шахматные квадраты python-chess (0..63)
# В python-chess: a1 = 0, h1 = 7, a8 = 56, h8 = 63
cleared_squares = [chess.square(c, 7 - r) for (r, c) in from_cells]
filled_squares = [chess.square(c, 7 - r) for (r, c) in to_cells]
# Ищем легальный ход, который лучше всего совпадает с изменениями на доске
matched_move = None
for move in self.board.legal_moves:
# 1. Обычный ход или взятие (откуда фигура ушла -> куда пришла)
if move.from_square in cleared_squares:
# Если клетка назначения изменила статус (или это взятие на той же клетке)
if move.to_square in filled_squares or self.board.is_capture(move):
matched_move = move
break
# Если нашли легальный ход — делаем его!
if matched_move:
san_move = self.board.san(matched_move) # Например, "Nxd4" или "e4"
self.board.push(matched_move)
print(f"[⚡ ХОД ПО ПРАВИЛАМ]: {san_move}")
self.last_crop_matrix = new_crop_matrix
self.print_board()
print(f"Новый FEN: {self.board.fen()}\n")
def run(self):
print("=========================================")
print(" Шахматный бот (с проверкой правил).")
print(" Нажмите 'S' для первоначального анализа.")
print("=========================================")
keyboard.add_hotkey('s', self.start_initial_analysis)
try:
while True:
if self.is_analyzed:
self.track_board_changes()
time.sleep(0.15)
except KeyboardInterrupt:
print("\nПрограмма завершена.")
if __name__ == '__main__':
logic = ChessLogic()
logic.run()