Added castling logic, fixed en passant and promotion
parent
c0f2df0b59
commit
4aa67bd830
67
chess.py
67
chess.py
|
@ -119,6 +119,11 @@ class Game:
|
|||
self.moves = []
|
||||
self.stack = []
|
||||
self.turn = "white"
|
||||
self.can_castle = {"white" : {"queen" : True,
|
||||
"king" : True},
|
||||
"black" : {"queen" : True,
|
||||
"king" : True}
|
||||
}
|
||||
|
||||
def __repr__(self):
|
||||
# Unicode board representation
|
||||
|
@ -148,6 +153,11 @@ class Game:
|
|||
self.board[sq].color = "white"
|
||||
for sq in cross(files, "78"):
|
||||
self.board[sq].color = "black"
|
||||
# Castling markers
|
||||
self.board["a1"].side = "queen"
|
||||
self.board["a8"].side = "queen"
|
||||
self.board["h1"].side = "king"
|
||||
self.board["h8"].side = "king"
|
||||
|
||||
def is_empty(self, sq):
|
||||
return self.board[sq] == None
|
||||
|
@ -155,23 +165,66 @@ class Game:
|
|||
def occupying(self, piece):
|
||||
return [sq for sq in squares if self.board[sq] == piece]
|
||||
|
||||
def castle(self, side):
|
||||
color = self.turn
|
||||
rank = home_ranks[self.turn]
|
||||
|
||||
if side not in ("queen", "king"):
|
||||
return False
|
||||
if not self.can_castle[color][side]:
|
||||
return False
|
||||
|
||||
if side == "queen":
|
||||
check_if_empty = cross("bcd", rank)
|
||||
check_if_attacked = cross("cde", rank)
|
||||
rook_move = "a"+rank, "d"+rank
|
||||
king_move = "e"+rank, "c"+rank
|
||||
elif side == "king":
|
||||
check_if_empty = cross("fg", rank)
|
||||
check_if_attacked = check_if_empty
|
||||
rook_move = "h"+rank, "f"+rank
|
||||
king_move = "e"+rank, "g"+rank
|
||||
are_empty = all(map(self.is_empty, check_if_empty))
|
||||
not_attacked = not any(self.is_attacked(color, sq)
|
||||
for sq in check_if_attacked)
|
||||
|
||||
if not (are_empty and not_attacked):
|
||||
return False
|
||||
|
||||
self.board[king_move[1]] = self.board[king_move[0]]
|
||||
self.board[rook_move[1]] = self.board[rook_move[0]]
|
||||
self.board[king_move[0]] = Piece()
|
||||
self.board[rook_move[0]] = Piece()
|
||||
self.can_castle[color]["queen"] = False
|
||||
self.can_castle[color]["king"] = False
|
||||
|
||||
def move(self, source, target, promotion=None):
|
||||
if not self.is_legal(source, target, promotion):
|
||||
return False
|
||||
board = self.board
|
||||
moved = board[source]
|
||||
eaten = board[target]
|
||||
|
||||
if promotion == None:
|
||||
promotion = moved
|
||||
else:
|
||||
promotion = Piece(self.turn, promotion)
|
||||
|
||||
if moved.piece == "pawn" and target in moves(source, bishop_dirs):
|
||||
if moved.piece == "pawn" and target in moves(source, bishop_dirs) and eaten==None:
|
||||
# En passant
|
||||
a, b = move(target, up), move(target, down)
|
||||
board[a] = Piece()
|
||||
board[b] = Piece()
|
||||
|
||||
# Castling
|
||||
if moved.piece == "rook":
|
||||
self.can_castle[self.turn][moved.side] = False
|
||||
if eaten.piece == "rook":
|
||||
self.can_castle[eaten.color][eaten.side] = False
|
||||
if moved.piece == "king":
|
||||
self.can_castle[self.turn]["queen"] = False
|
||||
self.can_castle[self.turn]["king"] = False
|
||||
|
||||
self.moves.append((source, target))
|
||||
self.stack.append(eaten)
|
||||
|
||||
|
@ -189,7 +242,7 @@ class Game:
|
|||
return False
|
||||
if promotion == None and pawn_on_last_rank:
|
||||
return False
|
||||
if promotion == "pawn":
|
||||
if promotion in ("king", "pawn"):
|
||||
return False
|
||||
return color == self.turn and target in self.possible_moves(source)
|
||||
|
||||
|
@ -289,14 +342,16 @@ def test():
|
|||
game = Game()
|
||||
assert len(squares) == 8**2
|
||||
assert sum(map(len, init_positions.values())) == 8*4
|
||||
moves = [("a2", "a4"), ("b8", "c6"), ("a4", "a5"), ("b7", "b5"), ("a5", "b6"),
|
||||
("c6", "e5"), ("b6", "b7"), ("h7", "h5"), ("b7", "b8", "pawn")]
|
||||
moves = [('d2', 'd4'), ('d7', 'd5'), ('d1', 'd3'), ('h7', 'h5'),
|
||||
('c1', 'h6'), ('g7', 'h6'), ('b1', 'c3'), ('d8', 'd6'),
|
||||
('h2', 'h4'), ('d6', 'f4'), ('e2', 'e3'), ('f4', 'g4'), ('e1', 'd1')]
|
||||
for m in moves:
|
||||
game.move(*m)
|
||||
print (game.can_castle)
|
||||
print (game)
|
||||
|
||||
game.board["c3"] = Piece("black", "king")
|
||||
|
||||
game.castle("queen")
|
||||
print(game)
|
||||
print (game.attacks("c3"))
|
||||
print(game.possible_moves("c3"))
|
||||
print(game.is_attacked("black", "d8"))
|
||||
|
|
Loading…
Reference in New Issue