Загрузка данных


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()