-2

In a chess position, I wish to check whether any passed pawn exists for white.

Is it possible to do so using the python-chess library? If not, how can I implement it?

def checkForPassedPawn(position: chess.Board, side_to_move: chess.Color):
    # ... check for passed pawn
    # return a boolean value

I could not find any built-in method that detects passed pawns.

Boo Who
  • 17
  • 6

1 Answers1

0

You'll have to look at the pawn positions yourself. There are many ways to do that. For instance, you could take the board's string representation as a starting point:

r n b q k b n r
p p . . . p p p
. . . . . . . .
. . p P p . . .
. . . . . P . .
. . . . . . . .
P P P P . . P P
R N B Q K B N R

This is the kond of string you get with str(position).

Then you could put each column in a separate list:

lines = str(position).replace(" ", "").splitlines()
columns = list(zip(*lines))

This gives you:

[
    ('r', 'p', '.', '.', '.', '.', 'P', 'R'),
    ('n', 'p', '.', '.', '.', '.', 'P', 'N'),
    ('b', '.', '.', 'p', '.', '.', 'P', 'B'),
    ('q', '.', '.', 'P', '.', '.', 'P', 'Q'),
    ('k', '.', '.', 'p', '.', '.', '.', 'K'),
    ('b', 'p', '.', '.', 'P', '.', '.', 'B'),
    ('n', 'p', '.', '.', '.', '.', 'P', 'N'),
    ('r', 'p', '.', '.', '.', '.', 'P', 'R')
]

It the current player is white, you then can check for the left most "P" in each tuple where it has a "p" more left to it, either in the current tuple, the previous one, or the next one.

For the black player, you would use a similar logic and it might be useful to first reverse the tuples in that case.

Here is an implementation of that idea:

import chess

def checkForPassedPawn(position: chess.Board, side_to_move: chess.Color):
    selfpawn = "pP"[side_to_move]
    otherpawn = "Pp"[side_to_move]
    lines = str(position).replace(" ", "").splitlines()
    if side_to_move == chess.BLACK:
        lines.reverse()
    # turn rows into columns and vice versa
    columns = list(zip(*lines))
    for colnum, col in enumerate(columns):
        if selfpawn in col:
            rownum = col.index(selfpawn)
            if (otherpawn not in col[:rownum]
                    and (colnum == 0 or otherpawn not in columns[colnum-1][:rownum])
                    and (colnum == 7 or otherpawn not in columns[colnum+1][:rownum])):
                return f"{'abcdefgh'[colnum]}{rownum+1}"
    
position = chess.Board()
position.push_san("e4")
position.push_san("d5")
position.push_san("f4")
position.push_san("e5")
position.push_san("exd5")
position.push_san("c5")  # Now white pawn at d5 is a passed pawn 
print(position)
passedpawn = checkForPassedPawn(position, chess.WHITE)
print("passed white pawn:", passedpawn)
position.push_san("d4")
position.push_san("e4")  # Now black pawn at e4 is a passed pawn
print(position)
passedpawn = checkForPassedPawn(position, chess.BLACK)
print("passed black pawn:", passedpawn)

Output:

r n b q k b n r
p p . . . p p p
. . . . . . . .
. . p P p . . .
. . . . . P . .
. . . . . . . .
P P P P . . P P
R N B Q K B N R
passed white pawn: d4
r n b q k b n r
p p . . . p p p
. . . . . . . .
. . p P . . . .
. . . P p P . .
. . . . . . . .
P P P . . . P P
R N B Q K B N R
passed black pawn: e4
trincot
  • 317,000
  • 35
  • 244
  • 286