-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchess.hpp
325 lines (275 loc) · 9.44 KB
/
chess.hpp
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
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
/*
Copyright (c) 2016 Walter William Karas
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#if !defined(CHESS_HPP)
#define CHESS_HPP
#include "misc.hpp"
#include "brdsize.hpp"
enum PIECECOLOR { WHITE, BLACK };
inline PIECECOLOR OtherColor(PIECECOLOR c)
{ return(c == WHITE ? BLACK : WHITE); }
enum PIECETYPE { TYPEKING, TYPEQUEEN, TYPEBISHOP, TYPEKNIGHT,
TYPEROOK, TYPEPAWN, TYPENOPIECE };
// simple completion status of a move
enum MOVEEVAL
{
// move done (not an en passant capture)
MOVEDONE,
// en passant capture move performed
MOVEENPASSANT,
// move not performed because it is illegal
ILLEGALMOVE,
// move not performed because if would allow opponent to take
// king on next move
WOULDLOSEKING
};
// full completion status of move
class MOVESTATUS
{
public:
// simple completions status
MOVEEVAL status;
// if status is WOULDLOSEKING, dangerToKing specifies the position
// of the opponent piece that would take the king on the nex move
POSITION dangerToKing;
MOVESTATUS(void) { };
// constructor if status is not WOULDLOSEKING
MOVESTATUS(MOVEEVAL s) : status(s) { };
// constructor if status is WOULDLOSEKING
MOVESTATUS(MOVEEVAL s, POSITION p) : status(s), dangerToKing(p) { };
};
// specifies a move
enum MOVETYPE { KINGSIDECASTLE, QUEENSIDECASTLE, NORMALMOVE };
class PIECEMOVE
{
public:
MOVETYPE type;
POSITION start, end;
// if moved piece is pawn which has thus arrived last rank, the
// type of the piece to promote it to. set to TYPENOPIECE if no
// promotion.
PIECETYPE promoteType;
PIECEMOVE(void) { }
PIECEMOVE
(
MOVETYPE t,
POSITION s,
POSITION e,
PIECETYPE pT = TYPENOPIECE
) : type(t), start(s), end(e), promoteType(pT) { }
// constructor for castling moves
PIECEMOVE
(
MOVETYPE t
) : type(t) { }
};
class PIECE;
// records whether the current move is an en passant capture, or
// follows a two-rank move of a pawn
enum EFFECTENPASSANT { ENPASSANTCAPTURE, AFTERDOUBLEMOVE, OTHERMOVE };
// information (other than the starting and end piece position)
// required to undo the effects of moving a piece
class MOVEUNDODATA
{
public:
// if not null, piece captured by moving piece
PIECE *capturedPiece;
// en passant effect
EFFECTENPASSANT enPassantEffect;
// if enPassantEffect not OTHERMOVE, records position of
// previously double-moved pawn
POSITION saveDoubleMoved;
};
// evalution of change in relative situation of the two players after
// one or more moves
enum SITUATIONOFKING { KINGLOST, STALEMATE, KINGOK };
class BOARDMETRIC
{
public:
SITUATIONOFKING kingSituation[2]; // indexed by PIECECOLOR
// change in relative material (total white material -
// total black material)
int materialDiff;
};
// maximum number of pieces of one color on the board
const int MAXPIECES = 16;
// maximum number of locations that a piece can reach in
// a single move
const int MAXMOVES = 28;
// list of moves which result in the greatest gain (or least loss)
// of material.
class BESTMOVES
{
public:
// number of moves in list
int nMoves;
PIECEMOVE move[MAXPIECES * MAXMOVES];
};
// internal representation of chess board
class BOARD
{
private:
// location in brd array points to piece in corresponding position
// on chess board. a null pointer means no piece in that location.
PIECE *brd[NUMROWS][NUMCOLS];
// flags if the last move was a double pawn move
BOOL wasLastMoveDoublePawn;
// if last move was double pawn move, contains the ending position
// of the pawn.
POSITION doubleMovedPawn;
// recursive function to find optimal moves in terms of
// getting opponent in checkmate or material gain.
void helpFindBestMoves
(
// number of moves to look-ahead
int lookAhead,
// color of player that is going to move
PIECECOLOR moveColor,
// metric of optimal moves
BOARDMETRIC &metric,
// if not null, filled in with list of optimal moves
BESTMOVES *bestMoves
);
public:
BOARD(void);
~BOARD(void);
PIECE *whatPiece(POSITION p) const
{ return(brd[p.row][p.col]); }
PIECE *whatPiece(int row, int col) const
{ return(brd[row][col]); }
// perform a move. move is not validated (assumed to be legal).
void doMove
(
// starting and ending position of piece to move
POSITION start,
POSITION end,
// data needed to undo move. caller must delete captured
// piece (unless move is undone)
MOVEUNDODATA &undoData
);
// undo a move done with doMove
void undoMove
(
// ending and original position of piece (transposed of order
// as passed to doMove)
POSITION end,
POSITION orig,
// undo data returned by call to doMove
MOVEUNDODATA undoData
);
// returns TRUE if the king of the given color can castle on the
// given side (as given by whichCastle). the one preventing
// condition not cheched for is if the final position of the king
// places it in check.
BOOL canCastle(MOVETYPE whichCastle, PIECECOLOR color);
// do a castle on the given side with the king of given color.
// no validation, assumed to be legal.
void castle(MOVETYPE whichCastle, PIECECOLOR color,
MOVEUNDODATA &undoData);
// undo a castle. undoData must be as returned by castle member.
void undoCastle(MOVETYPE whichCastle, PIECECOLOR color,
MOVEUNDODATA &undoData);
// checks if the piece in the given position can be promoted.
BOOL canPromote(POSITION where);
// promotes pawn in given location to piece of given type.
// assumed to be legal, no validation.
void promote(POSITION where, PIECETYPE promoteType);
// "un-promotes" a piece back to being a pawn. won't work if
// the piece was not originally a pawn.
void restorePawn(POSITION where);
// do a move with full validation, returning status
MOVESTATUS doUserMove
(
// starting and ending position of piece. the starting
// position is assumed to be valid.
POSITION start,
POSITION end
);
// complete check of whether a castle move can be done
BOOL userCanCastle(MOVETYPE whichCastle, PIECECOLOR color);
// returns TRUE if the last move was a double pawn move. if
// TRUE, the ending position of the pawn is returned as well.
BOOL lastMoveDoublePawn(POSITION &whereDoubleMovedPawn) const
{
if (wasLastMoveDoublePawn)
whereDoubleMovedPawn = doubleMovedPawn;
return(wasLastMoveDoublePawn);
}
// front end for helpFindBestMoves. simply initializes the
// material change to 0.
void findBestMoves
(
int lookAhead,
PIECECOLOR moveColor,
BOARDMETRIC &metric,
BESTMOVES *bestMoves
)
{
metric.materialDiff = 0;
helpFindBestMoves(lookAhead, moveColor, metric, bestMoves);
return;
}
};
// list of possible ending positions if a piece is moved from a fixed
// starting positions
class POSITIONLIST
{
public:
// number of ending positions
int nMoves;
POSITION end[MAXMOVES];
};
// abstract base class for piece.
class PIECE
{
private:
const PIECECOLOR color;
const PIECETYPE type;
// material value of piece.
const int value;
// number of moves piece has made.
int moveCount;
public:
PIECE(PIECECOLOR c, PIECETYPE t, int v) :
color(c), type(t), value(v), moveCount(0)
{ }
virtual ~PIECE(void) { }
PIECECOLOR whatColor(void) const { return(color); }
virtual PIECETYPE whatType(void) const { return(type); }
virtual int whatValue(void) const { return(value); }
// material value of piece where white is positive and
// black is negative
int signedValue(void) const
{ return(color == WHITE ? whatValue() : -whatValue()); }
// tell piece it was moved (once)
void moveDone(void) { moveCount++; }
// tell piece it was "unmoved"
void moveUndone(void) { moveCount--; }
// ask piece if it has been moved at least once
BOOL hasBeenMoved(void) const { return(moveCount > 0); }
// return list of legal moves for the piece
virtual void legalMoves
(
// tell piece where it is in board
POSITION start,
// give it the board, so it knows where other pieces are
const BOARD &board,
// struture to fill with ending positions of legal moves
// from the given start
POSITIONLIST &moves
) const = 0;
};
#endif