Search code examples
pythonpython-chess

python chess board.attackers how to use


I'm playing around with some python chess code, its for fun.
However i have difficulty in using the board.attackers function.
I'm not sure what it accepts
This code below makes use of the chess lib described here:
http://python-chess.readthedocs.io/en/latest/core.html

in the docs example code exists where they put in chess.F3 though i need some conversion from move to chess.xx i guess ?.

def staticAnalysis(board, move, my_color):
  score = random.random()
  board.push(move)
 
  for (piece, value) in [(chess.PAWN, 1), 
                       (chess.BISHOP, 4), 
                       (chess.KING, 0), 
                       (chess.QUEEN, 10), 
                       (chess.KNIGHT, 5),
                       (chess.ROOK, 3)]:
    score += len(board.pieces(piece, my_color)) * value
    score -= len(board.pieces(piece, not my_color)) * value
     
  score += 100 if board.is_checkmate() else 0
  score += 10 if board.is_capture(move)  else 0

  # to get proposed destination of the move, removes piece, thus Ph1 becomes h1
  square =  str(move)[-2:]  

  # but its not accepted ?.. what can be used to do achieve this ?.
  myAttackers = board.attackers(not my_color,  square)
  score +=len(attackers)*-2

return score

Solution

  • There are built-in methods that take care of converting between a square's str name and int value already:

    >>> chess.square_name(21)
    'f3'
    >>> chess.parse_square('f3')
    21
    

    However, your solution using ord() is technically more efficient as it runs in O(1) whereas chess.parse_square calls SQUARES.index(...) and runs in O(n). But no need to reinvent the wheel here.


    For more context, chess.Square is simply an alias for a Python int. Here is the actual source code where it's defined:

    Square = int
    SQUARES = [
        A1, B1, C1, D1, E1, F1, G1, H1,
        A2, B2, C2, D2, E2, F2, G2, H2,
        A3, B3, C3, D3, E3, F3, G3, H3,
        A4, B4, C4, D4, E4, F4, G4, H4,
        A5, B5, C5, D5, E5, F5, G5, H5,
        A6, B6, C6, D6, E6, F6, G6, H6,
        A7, B7, C7, D7, E7, F7, G7, H7,
        A8, B8, C8, D8, E8, F8, G8, H8,
    ] = range(64)
    

    This is shorthand for chess.A1=0, chess.B1=1, ... , chess.H8=63.

    In your code, you are providing attackers() with a string (because you define square = str(move)[-2:] ), not a chess.Square (an int), which is causing your error.

    You can replace the line where you define square with this, so its type is actually chess.Square (here I know the type of move is chess.Move since you use board.push(move) earlier):

    square = move.to_square  # a ``chess.Square``
    

    On a side note, I noticed your piece values look a bit off. Maybe you wanted them like this:

    [(chess.PAWN, 1),
    (chess.BISHOP, 3),
    (chess.KING, 0),
    (chess.QUEEN, 9),
    (chess.KNIGHT, 3),
    (chess.ROOK, 5)]