max2201111

brief OK

Jul 20th, 2025
333
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 11.56 KB | Science | 0 0
  1. import time
  2. from copy import deepcopy
  3.  
  4. directions = {
  5.     'K': [(1,0), (0,1), (-1,0), (0,-1), (1,1), (-1,-1), (1,-1), (-1,1)],
  6.     'Q': [(1,0), (0,1), (-1,0), (0,-1), (1,1), (-1,-1), (1,-1), (-1,1)],
  7.     'R': [(1,0), (0,1), (-1,0), (0,-1)],
  8.     'B': [(1,1), (-1,-1), (1,-1), (-1,1)],
  9.     'N': [(2,1), (1,2), (-1,2), (-2,1), (-2,-1), (-1,-2), (1,-2), (2,-1)],
  10.     'P': [(1,1), (-1,1)],  
  11.     'p': [(1,-1), (-1,-1)],
  12.     'A': [],
  13.     'C': [],
  14.     'E': [],
  15. }
  16.  
  17. def in_bounds(x,y):
  18.     return 0 <= x < 8 and 0 <= y < 8
  19.  
  20. class Board:
  21.     def __init__(self, grid, turn):
  22.         self.grid = grid
  23.         self.turn = turn
  24.  
  25.     def copy(self):
  26.         return Board(deepcopy(self.grid), self.turn)
  27.  
  28.     def is_white(self, p):
  29.         return p.isupper()
  30.  
  31.     def is_black(self, p):
  32.         return p.islower()
  33.  
  34.     def enemy_color(self):
  35.         return 'b' if self.turn == 'w' else 'w'
  36.  
  37.     def get_king_pos(self, color):
  38.         king_char = 'K' if color == 'w' else 'k'
  39.         for y in range(8):
  40.             for x in range(8):
  41.                 if self.grid[y][x] == king_char:
  42.                     return (x,y)
  43.         return None
  44.  
  45.     def under_attack(self, x, y, color):
  46.         enemy = 'b' if color == 'w' else 'w'
  47.         enemy_pieces = []
  48.         for yy in range(8):
  49.             for xx in range(8):
  50.                 p = self.grid[yy][xx]
  51.                 if p and ((enemy == 'w' and p.isupper()) or (enemy == 'b' and p.islower())):
  52.                     enemy_pieces.append( (p, xx, yy) )
  53.         for (p, ex, ey) in enemy_pieces:
  54.             if self.attacks_square(ex, ey, x, y, p):
  55.                 return True
  56.         return False
  57.  
  58.     def attacks_square(self, sx, sy, tx, ty, piece):
  59.         c = piece.upper()
  60.         dx = tx - sx
  61.         dy = ty - sy
  62.  
  63.         def sign(n): return (n > 0) - (n < 0)
  64.  
  65.         if c == 'P':
  66.             if piece.isupper():
  67.                 return (dx, dy) in [(1, -1), (-1, -1)]
  68.             else:
  69.                 return (dx, dy) in [(1, 1), (-1, 1)]
  70.  
  71.         elif c == 'N':
  72.             return (abs(dx), abs(dy)) in [(2,1), (1,2)]
  73.  
  74.         elif c == 'K':
  75.             return max(abs(dx), abs(dy)) == 1
  76.  
  77.         elif c in ['B', 'Q', 'A', 'E']:
  78.             if abs(dx) == abs(dy) and dx != 0:
  79.                 stepx = sign(dx)
  80.                 stepy = sign(dy)
  81.                 x = sx + stepx
  82.                 y = sy + stepy
  83.                 while (x, y) != (tx, ty):
  84.                     if self.grid[y][x] is not None:
  85.                         return False
  86.                     x += stepx
  87.                     y += stepy
  88.                 return True
  89.  
  90.         if c in ['R', 'Q', 'C', 'E']:
  91.             if (dx == 0 and dy != 0) or (dy == 0 and dx != 0):
  92.                 stepx = sign(dx)
  93.                 stepy = sign(dy)
  94.                 x = sx + stepx
  95.                 y = sy + stepy
  96.                 while (x, y) != (tx, ty):
  97.                     if self.grid[y][x] is not None:
  98.                         return False
  99.                     x += stepx
  100.                     y += stepy
  101.                 return True
  102.  
  103.         if c in ['A','C','E']:
  104.             knight_jumps = [(2,1), (1,2), (-1,2), (-2,1), (-2,-1), (-1,-2), (1,-2), (2,-1)]
  105.             if (dx, dy) in knight_jumps:
  106.                 return True
  107.  
  108.         return False
  109.  
  110.     def generate_moves(self):
  111.         moves = []
  112.         for y in range(8):
  113.             for x in range(8):
  114.                 p = self.grid[y][x]
  115.                 if p is None:
  116.                     continue
  117.                 if (self.turn == 'w' and p.isupper()) or (self.turn == 'b' and p.islower()):
  118.                     moves.extend(self.piece_moves(x, y, p))
  119.         return moves
  120.  
  121.     def piece_moves(self, x, y, p):
  122.         moves = []
  123.         c = p.upper()
  124.  
  125.         def add_move_if_valid(nx, ny):
  126.             if not in_bounds(nx, ny):
  127.                 return False
  128.             target = self.grid[ny][nx]
  129.             if target is None or (self.turn == 'w' and target.islower()) or (self.turn == 'b' and target.isupper()):
  130.                 moves.append((x, y, nx, ny))
  131.                 return target is None
  132.             return False
  133.  
  134.         if c == 'P':
  135.             forward = -1 if p.isupper() else 1
  136.             start_row = 6 if p.isupper() else 1
  137.  
  138.             if in_bounds(x, y + forward) and self.grid[y + forward][x] is None:
  139.                 moves.append((x, y, x, y + forward))
  140.                 if y == start_row and self.grid[y + 2 * forward][x] is None:
  141.                     moves.append((x, y, x, y + 2 * forward))
  142.             for dx in [-1, 1]:
  143.                 nx, ny = x + dx, y + forward
  144.                 if in_bounds(nx, ny):
  145.                     target = self.grid[ny][nx]
  146.                     if target and ((p.isupper() and target.islower()) or (p.islower() and target.isupper())):
  147.                         moves.append((x, y, nx, ny))
  148.  
  149.         else:
  150.             knight_moves = [(2,1),(1,2),(-1,2),(-2,1),(-2,-1),(-1,-2),(1,-2),(2,-1)]
  151.             if c in ['N','A','C','E']:
  152.                 for dx, dy in knight_moves:
  153.                     nx, ny = x + dx, y + dy
  154.                     if in_bounds(nx, ny):
  155.                         target = self.grid[ny][nx]
  156.                         if target is None or (self.turn == 'w' and target.islower()) or (self.turn == 'b' and target.isupper()):
  157.                             moves.append((x, y, nx, ny))
  158.  
  159.             if c in ['R','Q','C','E']:
  160.                 for dx, dy in [(1,0),(0,1),(-1,0),(0,-1)]:
  161.                     nx, ny = x + dx, y + dy
  162.                     while in_bounds(nx, ny):
  163.                         target = self.grid[ny][nx]
  164.                         if target is None:
  165.                             moves.append((x, y, nx, ny))
  166.                         else:
  167.                             if (self.turn == 'w' and target.islower()) or (self.turn == 'b' and target.isupper()):
  168.                                 moves.append((x, y, nx, ny))
  169.                             break
  170.                         nx += dx
  171.                         ny += dy
  172.  
  173.             if c in ['B','Q','A','E']:
  174.                 for dx, dy in [(1,1),(1,-1),(-1,1),(-1,-1)]:
  175.                     nx, ny = x + dx, y + dy
  176.                     while in_bounds(nx, ny):
  177.                         target = self.grid[ny][nx]
  178.                         if target is None:
  179.                             moves.append((x, y, nx, ny))
  180.                         else:
  181.                             if (self.turn == 'w' and target.islower()) or (self.turn == 'b' and target.isupper()):
  182.                                 moves.append((x, y, nx, ny))
  183.                             break
  184.                         nx += dx
  185.                         ny += dy
  186.  
  187.             if c == 'K':
  188.                 for dx, dy in directions['K']:
  189.                     nx, ny = x + dx, y + dy
  190.                     if in_bounds(nx, ny):
  191.                         target = self.grid[ny][nx]
  192.                         if target is None or (self.turn == 'w' and target.islower()) or (self.turn == 'b' and target.isupper()):
  193.                             moves.append((x, y, nx, ny))
  194.  
  195.         return moves
  196.  
  197.     def move(self, x1, y1, x2, y2):
  198.         b = self.copy()
  199.         b.grid[y2][x2] = b.grid[y1][x1]
  200.         b.grid[y1][x1] = None
  201.         b.turn = 'b' if self.turn == 'w' else 'w'
  202.         return b
  203.  
  204.     def is_in_check(self, color):
  205.         king_pos = self.get_king_pos(color)
  206.         if king_pos is None:
  207.             return True
  208.         xk, yk = king_pos
  209.         return self.under_attack(xk, yk, color)
  210.  
  211.     def is_checkmate(self):
  212.         if not self.is_in_check(self.turn):
  213.             return False
  214.         for move in self.generate_moves():
  215.             new_board = self.move(*move)
  216.             if not new_board.is_in_check(self.turn):
  217.                 return False
  218.         return True
  219.  
  220.     def is_stalemate(self):
  221.         if self.is_in_check(self.turn):
  222.             return False
  223.         for move in self.generate_moves():
  224.             new_board = self.move(*move)
  225.             if not new_board.is_in_check(self.turn):
  226.                 return False
  227.         return True
  228.  
  229.     def fen(self):
  230.         rows = []
  231.         for y in range(8):
  232.             row = ''
  233.             empty = 0
  234.             for x in range(8):
  235.                 p = self.grid[y][x]
  236.                 if p is None:
  237.                     empty += 1
  238.                 else:
  239.                     if empty > 0:
  240.                         row += str(empty)
  241.                         empty = 0
  242.                     row += p
  243.             if empty > 0:
  244.                 row += str(empty)
  245.             rows.append(row)
  246.         fen_str = '/'.join(rows)
  247.         fen_str += ' ' + self.turn + ' - - 0 1'
  248.         return fen_str
  249.  
  250.     def ascii(self):
  251.         lines = []
  252.         for y in range(8):
  253.             line = ''
  254.             for x in range(8):
  255.                 p = self.grid[y][x]
  256.                 if p is None:
  257.                     line += '.'
  258.                 else:
  259.                     if p.upper() == 'K':
  260.                         line += 'K' if p.isupper() else 'k'
  261.                     else:
  262.                         line += p
  263.             lines.append(line)
  264.         return '\n'.join(lines)
  265.  
  266. def parse_fen(fen):
  267.     parts = fen.split()
  268.     board_part = parts[0]
  269.     turn = parts[1]
  270.     rows = board_part.split('/')
  271.     grid = []
  272.     for r in rows:
  273.         row = []
  274.         for ch in r:
  275.             if ch.isdigit():
  276.                 for _ in range(int(ch)):
  277.                     row.append(None)
  278.             else:
  279.                 row.append(ch)
  280.         grid.append(row)
  281.     return grid, turn
  282.  
  283. def minimax(board, depth, max_depth, printed_depths, path=[]):
  284.     if depth == 0 or board.is_checkmate() or board.is_stalemate():
  285.         # Konec větve, mat nebo pat nebo dosažení hloubky
  286.         if board.is_checkmate():
  287.             if board.turn == 'w':
  288.                 return -1, path
  289.             else:
  290.                 return 1, path
  291.         if board.is_stalemate():
  292.             return 0, path
  293.         return 0, path
  294.  
  295.     best_score = -float('inf') if board.turn == 'w' else float('inf')
  296.     best_path = None
  297.  
  298.     moves = board.generate_moves()
  299.     legal_moves = []
  300.     for m in moves:
  301.         new_board = board.move(*m)
  302.         if not new_board.is_in_check(board.turn):
  303.             legal_moves.append(m)
  304.  
  305.     if not legal_moves:
  306.         # Žádné legální tahy
  307.         if board.is_in_check(board.turn):
  308.             # Mat
  309.             return (-1 if board.turn == 'w' else 1), path
  310.         else:
  311.             # Pat
  312.             return 0, path
  313.  
  314.     for m in legal_moves:
  315.         new_board = board.move(*m)
  316.         score, p = minimax(new_board, depth-1, max_depth, printed_depths, path + [new_board])
  317.         if board.turn == 'w':
  318.             if score > best_score:
  319.                 best_score = score
  320.                 best_path = p
  321.         else:
  322.             if score < best_score:
  323.                 best_score = score
  324.                 best_path = p
  325.  
  326.     current_depth = max_depth - depth + 1
  327.     if current_depth not in printed_depths:
  328.         print(f"[{time.strftime('%H:%M:%S')}] Dokončena hloubka: {current_depth}")
  329.         printed_depths.add(current_depth)
  330.  
  331.     return best_score, best_path
  332.  
  333. # --- Hlavní program ---
  334.  
  335. fen = "8/8/4A3/8/6k1/8/8/6K1 b - - 0 1"
  336. grid, turn = parse_fen(fen)
  337. board = Board(grid, turn)
  338.  
  339. depth = 7
  340. max_depth = depth
  341. printed_depths = set()
  342.  
  343. score, path = minimax(board, depth, max_depth, printed_depths, [board])
  344.  
  345. if score == 1:
  346.     print("Bílý vyhrává (mat):\n")
  347. elif score == -1:
  348.     print("Černý vyhrává (mat):\n")
  349. else:
  350.     print("Remíza (pat nebo nedosažený mat):\n")
  351.  
  352. for b in path:
  353.     print(b.ascii())
  354.     print(b.fen())
  355.     print("-" * 20)
Advertisement
Add Comment
Please, Sign In to add comment