# knight's tour (coin toss)
# max 3a		--> mit coin-toss 
import pyxel
import random

class App:
    def __init__(self, board_size):
        self.board_size = board_size
        self.cell_size = 32
        self.width = self.board_size * self.cell_size
        self.height = self.board_size * self.cell_size
        pyxel.init(self.width, self.height)
        pyxel.title("Knight's Tour")
        pyxel.mouse(True)
        self.reset_board()
        self.start_x = 0
        self.start_y = 0
        # Variablen für Geschwindigkeitssteuerung
        self.auto_mode = True
        self.last_move_time = 0
        #self.move_delay = 10  # Verzögerung in Frames (je höher, desto langsamer)
        self.move_delay = 4  # Verzögerung in Frames (je höher, desto langsamer)
        self.initialize_tour()
        pyxel.run(self.update, self.draw)

    def reset_board(self):
        self.board = [[0 for _ in range(self.board_size)] for _ in range(self.board_size)]
        self.tour = []
        self.current_x = 0
        self.current_y = 0
        self.move_count = 0
        self.completed = False

    def initialize_tour(self):
        self.reset_board()
        self.current_x = self.start_x
        self.current_y = self.start_y
        self.board[self.current_y][self.current_x] = 1
        self.tour.append((self.current_x, self.current_y))
        self.move_count = 1
        self.completed = False
    
    def solve_tour(self):
        if self.completed or not self.auto_mode:
            return
        dx = [-2, -1, 1, 2, -2, -1, 1, 2]
        dy = [1, 2, 2, 1, -1, -2, -2, -1]
        kx = self.current_x
        ky = self.current_y
        pq = []
        for i in range(8):
            nx = kx + dx[i]
            ny = ky + dy[i]
            if 0 <= nx < self.board_size and 0 <= ny < self.board_size:
                if self.board[ny][nx] == 0:
                    ctr = 0
                    for j in range(8):
                        ex = nx + dx[j]
                        ey = ny + dy[j]
                        if 0 <= ex < self.board_size and 0 <= ey < self.board_size:
                            if self.board[ey][ex] == 0:
                                ctr += 1
                    pq.append((ctr, i))
        if not pq:
            self.completed = True
            return
        
        # Find the minimum value in pq
        min_val = min(x[0] for x in pq)

        # Collect all moves with the minimum value
        best_moves = [move for val, move in pq if val == min_val]

        # Choose a random move from the best moves
        if best_moves:
            m = random.choice(best_moves)
            self.current_x += dx[m]
            self.current_y += dy[m]
            self.move_count += 1
            self.board[self.current_y][self.current_x] = self.move_count
            self.tour.append((self.current_x, self.current_y))
            if self.move_count == self.board_size * self.board_size:
                self.completed = True  
    
    def update(self):
        # Schrittweise Animation
        if self.auto_mode and not self.completed and pyxel.frame_count - self.last_move_time > self.move_delay:
            self.solve_tour()
            self.last_move_time = pyxel.frame_count
        # Mausklick-Logik
        if pyxel.btnp(pyxel.MOUSE_BUTTON_LEFT):
            mouse_x = pyxel.mouse_x // self.cell_size
            mouse_y = pyxel.mouse_y // self.cell_size
            if 0 <= mouse_x < self.board_size and 0 <= mouse_y < self.board_size:
                if self.completed:
                    self.start_x = mouse_x
                    self.start_y = mouse_y
                    self.initialize_tour()
                else:
                    self.auto_mode = not self.auto_mode  # Pause/Play umschalten

    def draw(self):
        pyxel.cls(0)
        # Zeichne Schachbrett
        for y in range(self.board_size):
            for x in range(self.board_size):
                col = 13 if (x + y) % 2 == 0 else 2
                pyxel.rect(x * self.cell_size, y * self.cell_size, self.cell_size, self.cell_size, col)
        # Zeichne Linien für die Tour
        for i in range(len(self.tour) - 1):
            x1, y1 = self.tour[i]
            x2, y2 = self.tour[i + 1]
            pyxel.line(
                x1 * self.cell_size + self.cell_size // 2,
                y1 * self.cell_size + self.cell_size // 2,
                x2 * self.cell_size + self.cell_size // 2,
                y2 * self.cell_size + self.cell_size // 2,
                8,
            )
        # Zeichne Zugnummern
        for x in range(self.board_size):
            for y in range(self.board_size):
                if self.board[y][x] > 0:
                    text_color = 0 if (x + y) % 2 == 0 else 7
                    # hg für zug-nr
                    pyxel.circ(
                        x * self.cell_size + self.cell_size // 2,
                        y * self.cell_size + self.cell_size // 2,
                        #self.cell_size // 3,
                        self.cell_size // 5,	# kleiner
                        12, #8, #4, #9, 		# hmm?
                    )
                    text = str(self.board[y][x])
                    text_x = x * self.cell_size + self.cell_size // 2 - len(text) * 2
                    text_y = y * self.cell_size + self.cell_size // 2 - 3
                    pyxel.text(text_x, text_y, text, text_color)
        # Statusanzeige
        if self.auto_mode and not self.completed:
            pyxel.text(10, 2, "Running... Click to pause.", 0)
        elif not self.auto_mode and not self.completed:
            pyxel.text(10, 10, "Paused. Click to resume.", 0)
        elif self.completed:
            pyxel.text(64, 2, "Tour Complete! Click to restart.", 0)

#App(board_size=8)
App(board_size=8)