2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 const char *char_board
[64] = {
21 "a1", "b1", "c1", "d1", "e1", "f1", "g1", "h1",
22 "a2", "b2", "c2", "d2", "e2", "f2", "g2", "h2",
23 "a3", "b3", "c3", "d3", "e3", "f3", "g3", "h3",
24 "a4", "b4", "c4", "d4", "e4", "f4", "g4", "h4",
25 "a5", "b5", "c5", "d5", "e5", "f5", "g5", "h5",
26 "a6", "b6", "c6", "d6", "e6", "f6", "g6", "h6",
27 "a7", "b7", "c7", "d7", "e7", "f7", "g7", "h7",
28 "a8", "b8", "c8", "d8", "e8", "f8", "g8", "h8" };
30 const char char_pieces
[7] = {' ', 'P', 'N', 'B', 'R', 'Q', 'K'};
36 uint64_t isolated_mask
[8]; /* masks adjacent files */
37 uint64_t passer_mask
[2][64]; /* masks passed pawn way */
38 uint64_t pawn_moves
[2][64]; /* pawn capture moves */
39 uint64_t piece_moves
[7][64]; /* all piece moves */
40 uint64_t forward_ray
[2][64]; /* masks squares infront of a pawn */
41 uint64_t king_shield
[2][64]; /* example: for king on G1 - F2,g2,h2 */
43 int distance
[64][64]; /* distance from 2 squares */
45 /* bitboard mask for files */
46 const uint64_t file_bit
[8] = {
47 0x0101010101010101ULL
, 0x0202020202020202ULL
,
48 0x0404040404040404ULL
, 0x0808080808080808ULL
,
49 0x1010101010101010ULL
, 0x2020202020202020ULL
,
50 0x4040404040404040ULL
, 0x8080808080808080ULL
53 uint64_t complete
; /* complete bitboard for both sides */
54 int square64
[64]; /* regular board */
55 struct board_t brd
; /* board parameters */
56 struct game_history_t game_history
; /* takeback buffer */
58 uint64_t piece_boards
[2][7]; /* bitboard for each type of piece */
59 uint64_t r_pieces
[2]; /* pieces except kings */
60 uint64_t side_boards
[2]; /* pieces for each side */
62 int castled
[2]; /* WHITE or BLACK castled */
64 int material_complete
[2]; /* sum of the material */
65 int material_pawns
[2]; /* ... for pawns */
66 int material_pieces
[2]; /* for pieces except pawns */
68 /* initial values according to Larry Kaufman */
69 int piece_value
[7] = { 0, 100, 325, 325, 500, 975 };
71 int piece_count
[2][7]; /* count pieces of each type */
73 /* add piece to the board, update bitboard, zobrist and count */
75 add_piece(int square
, int piece
, int side
)
77 assert(square
>= 0 && square
<= 63);
78 assert(piece
>= PAWN
&& piece
<= KING
);
79 assert(side
== WHITE
|| side
== BLACK
);
80 assert(material_complete
[side
] == material_pieces
[side
] + \
81 material_pawns
[side
]);
83 square64
[square
] = piece
;
85 SET(piece_boards
[side
][piece
], square
); /* update bitboard */
86 brd
.hash_key
^= hash_code
[side
][piece
][square
]; /* update zobrist key */
89 brd
.kings
[side
] = square
;
92 brd
.hash_pawn_key
^= hash_code
[side
][PAWN
][square
];
93 material_pawns
[side
] += piece_value
[PAWN
];
95 material_pieces
[side
] += piece_value
[piece
];
96 material_complete
[side
] += piece_value
[piece
];
98 piece_count
[side
][piece
]++;
102 board_is_legal(struct board_t
*b
)
110 for (i
= 0; i
< 64; i
++) {
112 /* if mailbox square isn't empty but bitboard's bit isn't set */
113 if (complete
& BIT(i
))
117 switch (square64
[i
]) {
119 if (((PAWNS(WHITE
) | PAWNS(BLACK
)) & BIT(i
)) == 0)
121 if (_FILE(square64
[i
]) == 0 || _FILE(square64
[i
]) == 7)
125 if (((KNIGHTS(WHITE
) | KNIGHTS(BLACK
)) & BIT(i
)) == 0)
129 if (((BISHOPS(WHITE
) | BISHOPS(BLACK
)) & BIT(i
)) == 0)
133 if (((ROOKS(WHITE
) | ROOKS(BLACK
)) & BIT(i
)) == 0)
137 if (((QUEENS(WHITE
) | QUEENS(BLACK
)) & BIT(i
)) == 0)
141 if (b
->kings
[WHITE
] == i
)
143 else if (b
->kings
[BLACK
] == i
)
152 /* bad king count or more than 32 pieces total */
153 if (wk
!= 1 || bk
!= 1 || n_pieces
> 32)
159 /* return board position in Forsyth-Edwards notation */
161 current_fen_position(char *buf
)
163 assert(board_is_legal(&brd
));
172 for (i
= 8; i
> 0; i
--) {
173 for (j
= 0; j
< 8; j
++) {
174 p
= square64
[(i
- 1) * 8 + j
];
179 /* square is not empty, but last square is. add empty
180 square count to result */
181 snprintf(tmp
, 2, "%d", empty
);
184 if (side_boards
[WHITE
] & BIT((i
- 1) * 8 + j
))
185 sprintf(tmp
, "%c", char_pieces
[p
]);
187 sprintf(tmp
, "%c", (char)(char_pieces
[p
] + 'a' - 'A'));
193 snprintf(tmp
, 2, "%d", empty
);
201 strcat(buf
, !brd
.wtm
? " w " : " b ");
203 if (!brd
.castle_mask
)
206 if (brd
.castle_mask
& WHITE_CASTLE_KINGSIDE
)
208 if (brd
.castle_mask
& WHITE_CASTLE_QUEENSIDE
)
210 if (brd
.castle_mask
& BLACK_CASTLE_KINGSIDE
)
212 if (brd
.castle_mask
& BLACK_CASTLE_QUEENSIDE
)
221 strcat(buf
, char_board
[brd
.ep
]);
226 /* remove piece from the board, update bitboard, zobrist and count */
228 remove_piece(int square
, int piece
, int side
)
230 assert(square
>= 0 && square
<= 63);
231 assert(piece
>= PAWN
&& piece
<= KING
);
232 assert(side
== WHITE
|| side
== BLACK
);
233 assert(material_complete
[side
] == material_pieces
[side
] + \
234 material_pawns
[side
]);
236 square64
[square
] = 0;
238 CLEAR(piece_boards
[side
][piece
], square
); /* update bitboard */
239 brd
.hash_key
^= hash_code
[side
][piece
][square
]; /* update zobrist */
243 brd
.hash_pawn_key
^= hash_code
[side
][PAWN
][square
];
244 material_pawns
[side
] -= piece_value
[PAWN
];
246 material_pieces
[side
] -= piece_value
[piece
];
247 material_complete
[side
] -= piece_value
[piece
];
249 piece_count
[side
][piece
]--;
252 /* how many times this position was occured */
258 /* search for the same hash_key */
259 for (i
= 0, rep
= 0; i
< game_history
.count
- 1; i
++)
260 if (game_history
.board
[i
].hash_key
== brd
.hash_key
)
266 /* setup board using FEN notation */
268 setup_board(char *fen
)
277 if (sscanf(fen
, "%8[1-8pnbrqkPNBRQK]/%8[1-8pnbrqkPNBRQK]/" \
278 "%8[1-8pnbrqkPNBRQK]/%8[1-8pnbrqkPNBRQK]/%8[1-8pnbrqkPNBRQK]/" \
279 "%8[1-8pnbrqkPNBRQK]/%8[1-8pnbrqkPNBRQK]/%8[1-8pnbrqkPNBRQK] " \
280 "%1[bw] %[KQkq-] %[1-8a-h-]", ranks
[7], ranks
[6], ranks
[5], \
281 ranks
[4], ranks
[3], ranks
[2], ranks
[1], ranks
[0], side
, \
286 ZERO_MEM(game_history
);
287 ZERO_MEM(piece_boards
);
289 ZERO_MEM(side_boards
);
290 ZERO_MEM(material_pawns
);
291 ZERO_MEM(material_pieces
);
292 ZERO_MEM(material_complete
);
293 ZERO_MEM(piece_count
);
295 castled
[WHITE
] = castled
[BLACK
] = FALSE
;
297 for (i
= 0, j
= 0; i
< 8; i
++, j
= 0)
298 for (p
= 0; p
< strlen(ranks
[i
]); p
++) {
299 if (ranks
[i
][p
] < 'A') { /* empty squares */
300 for (m
= j
, k
= m
; k
< m
+ ranks
[i
][p
] - '0'; k
++, j
++)
301 square64
[i
* 8 + j
] = 0;
304 /* lowercase letter - BLACK, uppercase - WHITE */
305 color
= ranks
[i
][p
] > 'a'? BLACK
: WHITE
;
306 switch (ranks
[i
][p
] - ('a' - 'A') * color
) {
308 add_piece(i
* 8 + j
, BISHOP
, color
);
311 add_piece(i
* 8 + j
, KING
, color
);
314 add_piece(i
* 8 + j
, KNIGHT
, color
);
317 add_piece(i
* 8 + j
, PAWN
, color
);
320 add_piece(i
* 8 + j
, QUEEN
, color
);
323 add_piece(i
* 8 + j
, ROOK
, color
);
329 brd
.wtm
= (!strcmp(side
, "w")) ? WHITE
: BLACK
;
332 if (strncmp(ep
, "-", 1)) {
333 i
= (ep
[0] - 'a') + (ep
[1] - '1') * 8;
334 j
= i
+ (brd
.wtm
== WHITE
? 8 : -8);
335 /* polyglot compatibility hack */
336 if ((BIT(j
- 1) & PAWNS(brd
.wtm
)) || (BIT(j
+ 1) & PAWNS(brd
.wtm
)))
339 assert((brd
.ep
>= 16 && brd
.ep
<= 47) || brd
.ep
== -1);
343 if (strchr(castle
, 'K'))
344 brd
.castle_mask
|= WHITE_CASTLE_KINGSIDE
;
345 if (strchr(castle
, 'Q'))
346 brd
.castle_mask
|= WHITE_CASTLE_QUEENSIDE
;
347 if (strchr(castle
, 'k'))
348 brd
.castle_mask
|= BLACK_CASTLE_KINGSIDE
;
349 if (strchr(castle
, 'q'))
350 brd
.castle_mask
|= BLACK_CASTLE_QUEENSIDE
;
355 calc_zobrist(&brd
.hash_key
, &brd
.hash_pawn_key
);
357 assert(board_is_legal(&brd
));
358 set_engine_value(&e
.hopeless_moves
, 0);
363 /* update bitboards, normaly after making moves */
367 r_pieces
[WHITE
] = PAWNS(WHITE
) | KNIGHTS(WHITE
) | BISHOPS(WHITE
) | \
368 ROOKS(WHITE
) | QUEENS(WHITE
);
369 r_pieces
[BLACK
] = PAWNS(BLACK
) | KNIGHTS(BLACK
) | BISHOPS(BLACK
) | \
370 ROOKS(BLACK
) | QUEENS(BLACK
);
372 side_boards
[WHITE
] = r_pieces
[WHITE
] | KING(WHITE
);
373 side_boards
[BLACK
] = r_pieces
[BLACK
] | KING(BLACK
);
375 complete
= side_boards
[WHITE
] | side_boards
[BLACK
];
378 /* simple board representation for debugging */
384 for (rank
= 7; rank
>= 0; rank
--) {
385 for (file
= 0; file
< 8; file
++)
386 if (b
& (1ULL << (rank
* 8 + file
)))
395 /* simple bitboard representation for debugging */
400 char pieces
[] = {' ', 'P', 'N', 'B', 'R', 'Q', 'K'};
402 for (i
= 7; i
>= 0; i
--) {
403 printf("%d ", i
+ 1);
404 for (j
= 0; j
< 8; j
++) {
405 p
= square64
[i
* 8 + j
];
407 if (side_boards
[BLACK
] & BIT(i
* 8 + j
))
408 printf("%c ", (char)(pieces
[p
] + ('a' - 'A')));
410 printf("%c ", pieces
[p
]);
416 printf("\n a b c d e f g h\n");