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.
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 kind 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