Another day, another Chess related CodeFights problem.
Pawn Race
Pawn race is a game for two people, played on an ordinary 8 × 8 chessboard. The first player has a white pawn, the second one - a black pawn. Initially the pawns are placed somewhere on the board so that the 1st and the 8th rows are not occupied. Players take turns to make a move.
White pawn moves upwards, black one moves downwards. The following moves are allowed:
- one-cell move on the same vertical in the allowed direction
- two-cell move on the same vertical in the allowed direction, if the pawn is standing on the 2nd (for the white pawn) or the 7th (for the black pawn) row. Note that even with the two-cell move a pawn can't jump over the opponent's pawn
- capture move one cell forward in the allowed direction and one cell to the left or to the right.
The purpose of the game is to reach the the 1st row (for the black pawn) or the 8th row (for the white one), or to capture the opponent's pawn.
Given the initial positions and whose turn it is, determine who will win or declare it a draw (i.e. it is impossible for any player to win). Assume that the players play optimally.
It is guaranteed that
white ≠ black
.Example
- For
white = "e2"
,black = "e7"
andtoMove = 'w'
, the output should bepawnRace(white, black, toMove) = "draw"
.- For
white = "e3"
,black = "d7"
andtoMove = 'b'
, the output should bepawnRace(white, black, toMove) = "black"
.- For
white = "a7"
,black = "h2"
andtoMove = 'w'
, the output should bepawnRace(white, black, toMove) = "white"
.
Code
def pawnRace(white, black, to_move):
winner = {'w': 'white',
'b': 'black'}
_to_piece = lambda piece: [ord(piece[0])-ord('a'), int(piece[1])]
white_file, white_rank = _to_piece(white)
black_file, black_rank = _to_piece(black)
# if on the same file and black is on a higher rank,
# they'll bump and will not be able to pass eachother
if(white_file == black_file and black_rank > white_rank):
return 'draw'
def can_capture(black_rank, black_file, white_rank, white_file):
"""return True if a piece can be captured"""
return abs(black_file - white_file) == 1 and \
abs(white_rank - black_rank) == 1 and \
white_rank < black_rank
while True:
# if piece can capture: return winner
if can_capture(black_rank, black_file, white_rank, white_file):
return winner[to_move]
# else move
if to_move == 'w':
if white_rank != 2 or \
can_capture(black_rank, black_file, white_rank + 2, white_file):
white_rank += 1
else:
white_rank += 2
if to_move == 'b':
if black_rank != 7 or \
can_capture(black_rank - 2, black_file, white_rank, white_file):
black_rank -= 1
else:
black_rank -= 2
# if piece is on promotion square: return winner
if white_rank == 8 or black_rank == 1:
return winner[to_move]
to_move = 'w' if to_move == 'b' else 'b'
Notes
This challenge is missing the en-passant move
I really tried my best this time to make it hard for all code-reviewers to critique my approach by making it readable while still keeping it simple. However as always I wonder how I did, and therefore feel the need to post it here.
Is there anything you would change or improve to my implementation?