-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathBoard.py
More file actions
154 lines (123 loc) · 5.85 KB
/
Board.py
File metadata and controls
154 lines (123 loc) · 5.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
from copy import deepcopy
from GUI import GUI
from Pieces.Piece import Team, Rank
from Pieces.Rook import Rook
from Pieces.Bishop import Bishop
from Pieces.Pawn import Pawn
from Pieces.Queen import Queen
from Pieces.King import King
from Pieces.Knight import Knight
BOARD_SIZE = 8
DEFAULT_BOARD = [
[Rook(Team.WHITE), Knight(Team.WHITE), Bishop(Team.WHITE), Queen(Team.WHITE), King(Team.WHITE), Bishop(Team.WHITE), Knight(Team.WHITE), Rook(Team.WHITE)],
[Pawn(Team.WHITE), Pawn(Team.WHITE), Pawn(Team.WHITE), Pawn(Team.WHITE), Pawn(Team.WHITE), Pawn(Team.WHITE), Pawn(Team.WHITE), Pawn(Team.WHITE)],
[None, None, None, None, None, None, None, None],
[None, None, None, None, None, None, None, None],
[None, None, None, None, None, None, None, None],
[None, None, None, None, None, None, None, None],
[Pawn(Team.BLACK), Pawn(Team.BLACK), Pawn(Team.BLACK), Pawn(Team.BLACK), Pawn(Team.BLACK), Pawn(Team.BLACK), Pawn(Team.BLACK), Pawn(Team.BLACK)],
[Rook(Team.BLACK), Knight(Team.BLACK), Bishop(Team.BLACK), Queen(Team.BLACK), King(Team.BLACK), Bishop(Team.BLACK), Knight(Team.BLACK), Rook(Team.BLACK)],
]
class Board:
def __init__(self, starting_board=DEFAULT_BOARD):
self.board = []
self.populate_board(starting_board)
self.gui = GUI()
def populate_board(self, starting_board):
self.board = deepcopy(starting_board)
def display(self):
"""
print("---------------------------")
for row in reversed(range(len(self.board))):
print(self.board[row])
print("---------------------------")
"""
self.gui.draw_board(self.board)
def get_board(self):
return self.board
def get_piece(self, pos):
return self.board[pos[0]][pos[1]]
# note: just adding this method for readability
def attack_position(self, current_pos, new_pos, attacking_piece):
current_row, current_col = current_pos
new_row, new_col = new_pos
self.board[current_row][current_col] = None
self.board[new_row][new_col] = attacking_piece
# tries all the legal moves on a team. if it finds one that stops check returns False
def is_checkmate(self, team):
for row in range(BOARD_SIZE):
for col in range(BOARD_SIZE):
piece = self.board[row][col]
piece_pos = (row, col)
if piece and piece.team == team:
piece_moves = piece.get_legal_moves(self.board, piece_pos)
# note: no need to check piece.move() because we already know this move is legal
for move in piece_moves:
# only changing board state to re-evaluate check. always revert board state below
self.attack_position(piece_pos, move, piece)
if not self.in_check(piece.team):
# found a spot that would get out of check
self.attack_position(move, piece_pos, piece)
return False
else:
self.attack_position(move, piece_pos, piece)
return True
def get_ranks_position(self, team, rank):
for row in range(BOARD_SIZE):
for col in range(BOARD_SIZE):
piece = self.get_piece((row, col))
if piece and piece.rank == rank and piece.team == team:
return (row, col)
# check if a team is in check
def in_check(self, team):
king_row, king_col = self.get_ranks_position(team, Rank.KING)
test_queen = Queen(team)
test_knight = Knight(team)
# get all legal moves for queen and knight from king's position
# these positions represent potential enemy positions
potential_enemies = test_queen.get_legal_moves(self.board, (king_row, king_col))
potential_enemies.extend(test_knight.get_legal_moves(self.board, (king_row, king_col)))
# print(potential_enemies)
# iterate over potential enemy positions
for position in potential_enemies:
row, col = position
# if there is a piece at potential enemy position
if self.board[row][col]:
# get legal moves for that piece
for pos in self.board[row][col].get_legal_moves(self.board, (row, col)):
# check if any legal moves are the position of the king
if self.board[pos[0]][pos[1]]:
if self.get_piece(pos).rank == Rank.KING:
# in check
return True
# if loop completes and no legal moves of potential enemies threaten king, team is not in check
return False
def move(self, current_pos, new_pos):
piece = self.get_piece(current_pos)
if not piece:
return False
team_in_check = self.in_check(piece.get_team())
if team_in_check:
print("You're in check!")
if piece.move(self.board, current_pos, new_pos):
self.attack_position(current_pos, new_pos, piece)
if self.in_check(piece.get_team()):
self.attack_position(new_pos, current_pos, piece)
print("Try again: you can't move into check!" if not team_in_check else "Try again: you're still in check!")
return False
else:
self.display()
piece.first_move = False
return True
return False
def is_game_over(self, team):
if self.in_check(team):
if self.is_checkmate(team):
winner = Team.BLACK if team == Team.WHITE else Team.WHITE
return winner
board = Board()
board.move((1, 4), (3, 4))
board.move((0, 5), (3, 2))
board.move((0, 3), (4, 7))
board.move((3, 2), (6, 5))
print(board.is_game_over(Team.BLACK))