-
Notifications
You must be signed in to change notification settings - Fork 2
/
pieces.py
151 lines (123 loc) · 4.73 KB
/
pieces.py
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
"""
Code illustration: 4.07
NO CHANGES FROM PREVIOUS ITERATION
Tkinter GUI Application Development Hotshot
"""
import sys
SHORT_NAME = {
'R': 'Rook',
'N': 'Knight',
'B': 'Bishop',
'Q': 'Queen',
'K': 'King',
'P': 'Pawn'
}
def create_piece(piece, color='white'):
''' Takes a piece name or shortname and returns the corresponding piece instance '''
if piece in (None, ' '): return
if len(piece) == 1:
if piece.isupper():
color = 'white'
else:
color = 'black'
piece = SHORT_NAME[piece.upper()]
module = sys.modules[__name__]
return module.__dict__[piece](color)
class Piece(object):
def __init__(self, color):
if color == 'black':
self.shortname = self.shortname.lower()
elif color == 'white':
self.shortname = self.shortname.upper()
self.color = color
def place(self, board):
''' Keep a reference to the board '''
self.board = board
def moves_available(self, pos, orthogonal, diagonal, distance):
board = self.board
allowed_moves = []
orth = ((-1, 0), (0, -1), (0, 1), (1, 0))
diag = ((-1, -1), (-1, 1), (1, -1), (1, 1))
piece = self
beginningpos = board.num_notation(pos.upper())
if orthogonal and diagonal:
directions = diag + orth
elif diagonal:
directions = diag
elif orthogonal:
directions = orth
for x, y in directions:
collision = False
for step in range(1, distance + 1):
if collision: break
dest = beginningpos[0] + step * x, beginningpos[1] + step * y
if self.board.alpha_notation(dest) not in board.occupied(
'white') + board.occupied('black'):
allowed_moves.append(dest)
elif self.board.alpha_notation(dest) in board.occupied(
piece.color):
collision = True
else:
allowed_moves.append(dest)
collision = True
allowed_moves = filter(board.is_on_board, allowed_moves)
return map(board.alpha_notation, allowed_moves)
class King(Piece):
shortname = 'k'
def moves_available(self, pos):
return super(King, self).moves_available(pos.upper(), True, True, 1)
class Queen(Piece):
shortname = 'q'
def moves_available(self, pos):
return super(Queen, self).moves_available(pos.upper(), True, True, 8)
class Rook(Piece):
shortname = 'r'
def moves_available(self, pos):
return super(Rook, self).moves_available(pos.upper(), True, False, 8)
class Bishop(Piece):
shortname = 'b'
def moves_available(self, pos):
return super(Bishop, self).moves_available(pos.upper(), False, True, 8)
class Knight(Piece):
shortname = 'n'
def moves_available(self, pos):
board = self.board
allowed_moves = []
beginningpos = board.num_notation(pos.upper())
piece = board.get(pos.upper())
deltas = (
(-2, -1), (-2, 1), (-1, -2), (-1, 2), (1, -2), (1, 2), (2, -1), (2, 1))
for x, y in deltas:
dest = beginningpos[0] + x, beginningpos[1] + y
if (board.alpha_notation(dest) not in board.occupied(piece.color)):
allowed_moves.append(dest)
allowed_moves = filter(board.is_on_board, allowed_moves)
return map(board.alpha_notation, allowed_moves)
class Pawn(Piece):
shortname = 'p'
def moves_available(self, pos):
board = self.board
piece = self
if self.color == 'white':
startpos, direction, enemy = 1, 1, 'black'
else:
startpos, direction, enemy = 6, -1, 'white'
allowed_moves = []
# Moving
prohibited = board.occupied('white') + board.occupied('black')
beginningpos = board.num_notation(pos.upper())
forward = beginningpos[0] + direction, beginningpos[1]
if board.alpha_notation(forward) not in prohibited:
allowed_moves.append(forward)
if beginningpos[0] == startpos:
# If pawn is in starting position allow double moves
double_forward = (forward[0] + direction, forward[1])
if board.alpha_notation(double_forward) not in prohibited:
allowed_moves.append(double_forward)
# Attacking
for a in range(-1, 2, 2):
attack = beginningpos[0] + direction, beginningpos[1] + a
if board.alpha_notation(attack) in board.occupied(enemy):
allowed_moves.append(attack)
allowed_moves = filter(board.is_on_board, allowed_moves)
return map(board.alpha_notation, allowed_moves)