-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpieces.py
180 lines (165 loc) · 6.46 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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
from movesClass import Direction, Move, Take, changeAmts
from piece import Piece
from pos import BoardPos
import config
from globals import globals
diagonal = [
Move([Direction.up, Direction.left]),
Move([Direction.left, Direction.down]),
Move([Direction.down, Direction.right]),
Move([Direction.right, Direction.up]),
]
horizontal = [
Move([Direction.up]),
Move([Direction.down]),
Move([Direction.left]),
Move([Direction.right]),
]
class Rook(Piece):
imgName = "rook"
def __init__(self, boardPos, color):
super().__init__(boardPos, color)
self.setMoves(horizontal)
self.notMoved = True
class Bishop(Piece):
imgName = "bishop"
def __init__(self, boardPos, color):
super().__init__(boardPos, color)
self.setMoves(diagonal)
def cond(piece, toMoveTo):
return piece.imgName == "pawn" and piece.state == globals.PawnStates.OriginalPos
def canEnPassant(toTake, piece):
return piece.imgName == "pawn" and toTake.imgName == "pawn" and toTake.state == globals.PawnStates.CanEnPassant
class Pawn(Piece):
imgName = "pawn"
def __init__(self, boardPos, color):
super().__init__(boardPos, color)
self.state = globals.PawnStates.OriginalPos
direction = Direction.up
if color == config.Color.black:
direction = Direction.down
self.setMoves(
[
Move([direction], amt=1),
Move([direction], amt=2, cond=cond)
],
[
Take([direction, Direction.left], amt=1),
Take([direction, Direction.right], amt=1),
Take([direction, Direction.left], amt=1, pieceOffset=direction * -1, cond=canEnPassant),
Take([direction, Direction.right], amt=1, pieceOffset=direction * -1, cond=canEnPassant),
]
)
globals.board.pawns.append(self)
def canPromote(self, boardPos):
end = 0
if self.color == config.Color.black:
end = 7
return boardPos.y == end
def promote(self, toMoveTo):
globals.board.newPromotionPrompt(self, toMoveTo) # okay that newSquare variable is just disgraceful
class Queen(Piece):
imgName = "queen"
def __init__(self, boardPos, color):
super().__init__(boardPos, color)
self.setMoves(diagonal + horizontal)
def canCastleRight(piece, toMoveTo):
if isinstance(piece, King) and piece.wouldSelfBeChecked(piece, toMoveTo):
return False
if isinstance(piece, King) and piece.isChecked():
return False
rightRook = globals.board.getSquare(BoardPos(config.BOARD_LENGTH-1, piece.boardPos.y)).piece # closer rook
if type(rightRook) == Rook and piece.notMoved and rightRook.notMoved:
for i in range(piece.boardPos.x+1, config.BOARD_LENGTH-1):
pieceInPath = globals.board.getSquare(BoardPos(i, piece.boardPos.y)).piece
if pieceInPath:
return False
return True
return False
def canCastleLeft(piece, toMoveTo):
if isinstance(piece, King) and piece.wouldSelfBeChecked(piece, toMoveTo):
return False
if isinstance(piece, King) and piece.isChecked():
return False
leftRook = globals.board.getSquare(BoardPos(0, piece.boardPos.y)).piece # farther rook
if type(leftRook) == Rook and piece.notMoved and leftRook.notMoved:
for i in range(1, piece.boardPos.x):
pieceInPath = globals.board.getSquare(BoardPos(i, piece.boardPos.y)).piece
if pieceInPath:
return False
return True
return False
def afterCastleRight(piece):
rook = globals.board.getSquare(BoardPos(7, piece.boardPos.y)).piece
rook.snap(BoardPos(5, piece.boardPos.y))
def afterCastleLeft(piece):
rook = globals.board.getSquare(BoardPos(0, piece.boardPos.y)).piece
rook.snap(BoardPos(3, piece.boardPos.y))
class Attacker: # container class
def __init__(self, attacker, route):
self.attacker = attacker
self.route = route # as in the path of attack
class King(Piece):
imgName = "king"
def __init__(self, boardPos, color):
super().__init__(boardPos, color)
self.setMoves(
[
*changeAmts(diagonal, 1),
*changeAmts(horizontal, 1),
Move([Direction.right * 2], cond=canCastleRight, after=afterCastleRight, amt=1),
Move([Direction.left * 2], cond=canCastleLeft, after=afterCastleLeft, amt=1),
],
[
*changeAmts(diagonal, 1, Take),
*changeAmts(horizontal, 1, Take),
]
)
self.notMoved = True
globals.board.kings[color] = self
def isChecked(self):
for pieceType in globals.attackAngles[self.color]:
takes = globals.attackAngles[self.color][pieceType]
for take in takes:
square = take.calc(self, False)
if square and square.piece and type(square.piece) == pieceType:
return True
return False
def wouldSelfBeChecked(self, origPiece, newSquare):
returnVal = False
origSquare = origPiece.square
newSquarePiece = newSquare.piece
origPiece.moveto(newSquare.boardPos)
if self.isChecked():
returnVal = True
origPiece.moveto(origSquare.boardPos)
newSquare.piece = newSquarePiece
return returnVal
def anyMoveAvailable(self):
for piece in globals.board.pieces[self.color]:
moves, takes = piece.getMoves()
if len([*moves, *takes]) > 0:
return False
return True
def isStalemated(self):
if self.isChecked():
return False
return self.anyMoveAvailable()
def isCheckmated(self):
if not self.isChecked():
return False
return self.anyMoveAvailable()
class Knight(Piece):
imgName = "knight"
def __init__(self, boardPos, color):
super().__init__(boardPos, color)
self.setMoves([
Move([Direction.up * 2, Direction.left], amt=1),
Move([Direction.up * 2, Direction.right], amt=1),
Move([Direction.down * 2, Direction.left], amt=1),
Move([Direction.down * 2, Direction.right], amt=1),
Move([Direction.left * 2, Direction.up], amt=1),
Move([Direction.left * 2, Direction.down], amt=1),
Move([Direction.right * 2, Direction.up], amt=1),
Move([Direction.right * 2, Direction.down], amt=1),
])