-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPiece.java
266 lines (232 loc) · 6.23 KB
/
Piece.java
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
package boardgame.pieces;
import java.lang.*;
import java.util.*;
import boardgame.data.*;
import boardgame.data.Configuration.ConfigElement;
import boardgame.play.*;
/**
*
* @author Muneeb Ahmed
*
*/
public abstract class Piece {
protected Color color;
protected PieceName pName;
protected Square square;
protected char symbol;
protected String name;
protected int value;
protected int moveCount;
protected Board board; //We need to have a reference to the board for getValidMoves() to work
//other fields
public Piece() {
color = Color.WHITE;
square = null;
symbol = ' ';
value = 0;
name = "unknown";
moveCount = 0;
board = null;
pName = PieceName.KING;
}
public Piece(Square square) {
this();
this.square = square;
}
public Piece(Color c) {
this();
color = c;
}
public Piece(Color c, Square s) {
this();
color = c;
square = s;
s.setPiece(this); //Only ok in constructor, otherwise square always sets piece
}
//create a piece for a given board given a ConfigElement and Board
public Piece(ConfigElement element, Board b) {
this(element.getColor(), b.getSquares().get(element.getSquare()));
this.moveCount = element.getMoveCount();
this.board = b;
}
public Piece(Piece p) {
color = p.color;
square = p.square;
moveCount = p.value;
board = p.board;
}
//setters and getters
public void setSquare(Square s) {
square = s;
}
public Square getSquare() {
return square;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
public char getSymbol() {
return symbol;
}
public void setSymbol(char symbol) {
this.symbol = symbol;
}
public PieceName getPieceName() {
return pName;
}
public String getName() {
return name;
}
public void setName(PieceName name) {
this.pName = name;
this.name = name.toString();
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public int getMoveCount() {
return moveCount;
}
public void setMoveCount(int moveCount) {
this.moveCount = moveCount;
}
public Board getBoard() {
return board;
}
public void setBoard(Board board) {
this.board = board;
}
public boolean getSpecialFlags() {
return false;
}
/*
* Rooks, Kings, and pawns will override
* SpecialFlags is used for generating configurations
* Rooks, Kings, and pawns have boolean flags that other pieces don't
*/
public void setSpecialFlags(boolean flag) {
return; //don't do anything except if special piece
}
public String getEnPassant() {
return null;
}
public void setEnPassant(String s) {
return;
}
public void incrementMoveCount() {
moveCount++;
setSpecialFlags(false); //calls overridden child method (tested in debug)
}
/**
* Returns ArrayList of all squares piece is attacking, regardless
* of whether or not it can actually move there
*
* @return ArrayList of squares in range
*/
public abstract ArrayList<Square> getAttacking();
/**
* Creates ArrayList of squares that can be moved to
* <p>
* Checks of piece can actually move there<br>
* Does NOT check if King will be left in check
*
* @return ArrayList of squares that can be moved to
*/
public abstract ArrayList<Square> getValidMoves();
/**
* Helper function for getValidMoves()
*
* @param file of the destination square
* @param rank of the destination square
* @param moves ArrayList of squares to add a move to
* @return true if move added, false if not
*/
protected boolean validMovesHelper(char file, int rank, ArrayList<Square> moves) {
Square s = board.getSquares().get(file + Integer.toString(rank));
if (!s.hasPiece()) {
moves.add(s);
return true;
}
else if (s.getPiece().color != color) {
moves.add(s);
}
return false;
}
/**
* Creates ArrayList of Squares that can legally be moved to
* <p>
* Checks if King will be in check after each valid moves
*
* @return ArrayList of Squares that legally can be moved to
*/
public ArrayList<Square> getLegalMoves(){
ArrayList<Square> validMoves = getValidMoves();
ArrayList<Square> legalMoves = new ArrayList<Square>();
Configuration currentState = board.getCurrentState();
Board testBoard = new Board();
for (Square dest : validMoves) {
testBoard.loadConfiguration(currentState);
Command validMoveCommand = new Command(this, this.square, dest);
validMoveCommand = testBoard.formatCommand(validMoveCommand);
testBoard.Move(validMoveCommand);
if (!testBoard.KingInCheck(this.color)) {
legalMoves.add(dest);
}
}
return legalMoves;
}
/*
* Used by the computer to get legal moves, with checkmating moves a priority
*
* Returns legal moves <br>
* If a legal move results in checkmate, then only that move is returned
* More efficient than just calling getLegalMoves and checking each situation for checkmate
*
* @return ArrayList of squares that can legally be moved to
*
*/
public boolean getGoodLegalMoves(ArrayList<Square> legalMoves){
ArrayList<Square> validMoves = getValidMoves();
legalMoves.clear();
Configuration currentState = board.getCurrentState();
Board testBoard = new Board();
Color opponent = (color == Color.WHITE)? Color.BLACK : Color.WHITE;
ArrayList<Square> opponentMoves = new ArrayList<Square>();
boolean flag = false;
for (Square dest : validMoves) {
testBoard.loadConfiguration(currentState);
Command validMoveCommand = new Command(this, this.square, dest);
validMoveCommand = testBoard.formatCommand(validMoveCommand);
testBoard.Move(validMoveCommand); Evaluator.count++;
if (!testBoard.KingInCheck(this.color)) {
legalMoves.add(dest);
if (testBoard.KingInCheck(opponent)) {
testBoard.setCurrentState(new Configuration(testBoard)); //null pointer exception
opponentMoves.clear(); //fixes AI overlooking mate in 1
for (Piece p : testBoard.getPieces()) {
if (p.getColor() == opponent) {
opponentMoves.addAll(p.getLegalMoves());
}
if (opponentMoves.size() != 0) { break; }
}
if (opponentMoves.size() == 0) {
legalMoves.clear();
legalMoves.add(dest);
flag = true;
break;
}
}
}
}
return flag;
}
public String toString() {
return color.toString() + ' ' + pName.toString();
}
}