ChessPosition.cc
Go to the documentation of this file.
1 // cwchessboard -- A C++ chessboard tool set
2 //
3 //! @file ChessPosition.cc This file contains the implementation of class ChessPosition.
4 //
5 // Copyright (C) 2008, by
6 //
7 // Carlo Wood, Run on IRC <carlo@alinoe.com>
8 // RSA-1024 0x624ACAD5 1997-01-26 Sign & Encrypt
9 // Fingerprint16 = 32 EC A7 B6 AC DB 65 A6 F6 F6 55 DD 1C DC FF 61
10 //
11 // This program is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation, either version 2 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 
24 #ifndef USE_PCH
25 #include "sys.h"
26 #include <sstream>
27 #include <cassert>
28 #endif
29 
30 #include "ChessPosition.h"
31 #include "Direction.h"
32 #include "ChessNotation.h"
33 #include "debug.h"
34 
35 namespace cwchess {
36 
37 #ifndef DOXYGEN
38 std::string EnPassant::FEN4(void) const
39 {
40  if (!exists())
41  return "-";
42  std::ostringstream fen;
43  Index passed(this->index());
44  fen << (char)('a' + passed.col()) << (passed.row() + 1);
45  return fen.str();
46 }
47 #endif
48 
49 void ChessPosition::clear_en_passant(void)
50 {
51  Index index = M_en_passant.pawn_index();
52  if (index > ih1 && piece_at(index - 1) == pawn)
53  M_pieces[index - 1].reset_can_take_king_side();
54  if (index < ia8 && piece_at(index + 1) == pawn)
55  M_pieces[index + 1].reset_can_take_queen_side();
56  M_en_passant.clear();
57 }
58 
60 {
61  for (Index index = index_begin; index != index_end; ++index)
62  M_pieces[index].set_type(nothing);
63  M_en_passant.clear();
64  M_castle_flags.clear();
65  M_half_move_clock = 0;
66  M_full_move_number = 1;
67  for (int i = 0; i < 16; ++i)
68  {
69  CodeData data = { static_cast<uint8_t>(i) };
70  M_bitboards[data].reset();
71  }
72  M_attackers[black].reset();
73  M_attackers[white].reset();
74  M_pinning[black].reset();
75  M_pinning[white].reset();
76  M_defended[black].reset();
77  M_defended[white].reset();
78  M_king_battery_attack_count[black] = 0;
79  M_king_battery_attack_count[white] = 0;
80  M_double_check = false;
81 }
82 
84 {
85  clear();
86  // It's white's turn.
87  M_to_move = white;
88  // White pawns.
89  for (Index index = ia2; index <= ih2; ++index)
90  place(white_pawn, index);
91  // Black pawns.
92  for (Index index = ia7; index <= ih7; ++index)
93  place(black_pawn, index);
94  // The other pieces.
95  Color color = white;
96  Index index = index_pre_begin;
97  for (int ci = 0; ci < 2; ++ci)
98  {
99  place(Code(color, rook), ++index);
100  place(Code(color, knight), ++index);
101  place(Code(color, bishop), ++index);
102  place(Code(color, queen), ++index);
103  place(Code(color, king), ++index);
104  place(Code(color, bishop), ++index);
105  place(Code(color, knight), ++index);
106  place(Code(color, rook), ++index);
107  color = black;
108  index += 48; // Skip all pawns and empty squares.
109  }
110 }
111 
112 bool ChessPosition::increment_counters(bool pawn_advance_or_capture)
113 {
114  if (pawn_advance_or_capture)
115  M_half_move_clock = 0;
116  else
117  ++M_half_move_clock;
118  if (M_to_move == white)
119  ++M_full_move_number;
120  return M_half_move_clock == 100;
121 }
122 
124 {
125  reset_en_passant();
126  M_to_move.toggle();
127  M_double_check = M_castle_flags.in_check(M_to_move) ? double_check(M_to_move) : false;
128  return increment_counters(false);
129 }
130 
131 void ChessPosition::to_move(Color const& color)
132 {
133  M_to_move = color;
134  M_double_check = M_castle_flags.in_check(M_to_move) ? double_check(M_to_move) : false;
135 }
136 
138 {
139  ChessPosition new_chess_position;
140  new_chess_position.clear();
141  new_chess_position.M_to_move = M_to_move.opposite();
142  // First place the pawn that can be taken en passant, if any.
143  Index en_passant_index = index_end;
144  if (M_en_passant.exists())
145  {
146  Index index = M_en_passant.pawn_index();
147  Piece& piece(M_pieces[index]);
148  en_passant_index = Index(index.col(), 7 - index.row());
149  new_chess_position.place(Code(piece.color().opposite(), pawn), en_passant_index);
150  new_chess_position.set_en_passant(Index(index.col(), 7 - M_en_passant.index().row()));
151  }
152  // Then place all other pawns (and pieces).
153  PieceIterator const end;
154  for (PieceIterator iter(this, M_bitboards[black] | M_bitboards[white]); iter != end; ++iter)
155  {
156  Index index(iter.index().col(), 7 - iter.index().row());
157  if (index == en_passant_index)
158  continue;
159  new_chess_position.place(Code(iter->color().opposite(), iter->type()), index);
160  }
161  new_chess_position.M_full_move_number = 1; // The history of the game was changed in an unknown way: it is not allowed that black started the game.
162  * this = new_chess_position;
163 }
164 
165 // Called when a piece of color \a color has been removed from (col, row) (possibly replaced
166 // by a piece of the opposite color). This function updates the pawn flags of influenced
167 // pawns on the board.
168 void ChessPosition::update_removed(uint8_t col, uint8_t row, Color const& color)
169 {
170  // A piece was removed from (col, row).
171  // We have to update possible pawns on (col - 1, row +/- 1) and (col + 1, row +/- 1).
172  bool ok;
173  Code other_pawn;
174  if (color == white)
175  {
176  ++row;
177  ok = row <= 6; // 6, not 7, because there can't be black pawns on row 7.
178  other_pawn = black_pawn;
179  }
180  else
181  {
182  --row;
183  ok = (int8_t)row >= 1; // 1, not 0, because there can't be white pawns on row 0.
184  other_pawn = white_pawn;
185  }
186  if (ok)
187  {
188  if (col > 0)
189  {
190  Index index(col - 1, row);
191  if (M_pieces[index] == other_pawn)
192  M_pieces[index].reset_can_take_king_side();
193  }
194  if (col < 7)
195  {
196  Index index(col + 1, row);
197  if (M_pieces[index] == other_pawn)
198  M_pieces[index].reset_can_take_queen_side();
199  }
200  }
201 }
202 
203 // Called when a piece of color \a color has been placed at (col, row) (possibly replacing
204 // a piece of the opposite color). This function updates the pawn flags of influenced
205 // pawns on the board.
206 void ChessPosition::update_placed(uint8_t col, uint8_t row, Color const& color)
207 {
208  // A piece was placed at (col, row).
209  // We have to update possible pawns on (col - 1, row +/- 1) and (col + 1, row +/- 1).
210  bool ok;
211  Code other_pawn;
212  if (color == white)
213  {
214  ++row;
215  ok = row <= 6; // 6, not 7, because there can't be black pawns on row 7.
216  other_pawn = black_pawn;
217  }
218  else
219  {
220  --row;
221  ok = (int8_t)row >= 1; // 1, not 0, because there can't be white pawns on row 0.
222  other_pawn = white_pawn;
223  }
224  if (ok)
225  {
226  if (col > 0)
227  {
228  Index index(col - 1, row);
229  if (M_pieces[index] == other_pawn)
230  M_pieces[index].set_can_take_king_side();
231  }
232  if (col < 7)
233  {
234  Index index(col + 1, row);
235  if (M_pieces[index] == other_pawn)
236  M_pieces[index].set_can_take_queen_side();
237  }
238  }
239 }
240 
241 // This function recalculates M_pinning for the color of code (a black_king or white_king).
242 //
243 // @param code : The code of the king.
244 // @param index : The index of the king.
245 // @param mask : The position of the king.
246 // @param direction : The direction from the king towards the attacker.
247 // @param relevant_pieces : All pieces along that line (possibly cut off at the last attacker).
248 //
249 void ChessPosition::update_pinning(Code const& code, Index const& index, mask_t mask, Direction const& direction, BitBoard const& relevant_pieces)
250 {
251  bool king_side_is_msb = (relevant_pieces() < mask); // This means that the most significant bit is on the side of the king.
252  // Run over all pieces, starting at the side of the king.
253  PieceIterator piece_iter = king_side_is_msb ? PieceIterator(this, relevant_pieces, 0) : PieceIterator(this, relevant_pieces);
254  PieceIterator end = king_side_is_msb ? PieceIterator(0) : PieceIterator();
255  Code first_piece_code;
256  Index first_piece_index;
257  bool found_first_piece = false;
258  bool taking_en_passant_not_allowed = false;
259  while (piece_iter != end)
260  {
261  if (found_first_piece)
262  {
263  Code second_piece_code = piece_iter->code();
264  if (!second_piece_code.has_opposite_color_of(code))
265  break;
266  else
267  {
268  if (second_piece_code.moves_along(direction))
269  {
270  if (taking_en_passant_not_allowed)
271  M_en_passant.pinned_set(); // Disallow taking en passant.
272  else
273  M_pinning[code.color()] |= squares_from_to(piece_iter.index(), index);
274  break;
275  }
276  else if (M_en_passant.exists() && M_en_passant.pawn_index() == piece_iter.index() && first_piece_code.is_a(pawn)&&
277  direction.is_horizontal() && M_en_passant.pawn_index() - direction == first_piece_index&&
278  first_piece_code.has_opposite_color_of(second_piece_code))
279  taking_en_passant_not_allowed = true;
280  else
281  break;
282  }
283  }
284  else
285  {
286  first_piece_code = piece_iter->code();
287  first_piece_index = piece_iter.index();
288  if (first_piece_code.has_opposite_color_of(code))
289  {
290  if (!M_en_passant.exists() || M_en_passant.pawn_index() != first_piece_index || !direction.is_horizontal())
291  break; // Nothing is pinned (though we might be in check).
292  else
293  {
294  // This handles a very special case.
295  taking_en_passant_not_allowed = true;
296  }
297  }
298  else if (taking_en_passant_not_allowed&&
299  (!first_piece_code.is_a(pawn) || first_piece_index - direction != M_en_passant.pawn_index()))
300  break; // Also special case does not apply.
301  else
302  found_first_piece = true;
303  }
304  if (king_side_is_msb)
305  {
306  if (piece_iter.index() == ia1) // We are not allowed to call --piece_iter if we're already at square a1.
307  break;
308  --piece_iter;
309  }
310  else
311  ++piece_iter;
312  }
313 }
314 
315 // This function updates M_pieces and M_bitboards.
316 bool ChessPosition::place(Code const& code, Index const& index)
317 {
318  DoutEntering(dc::place, "ChessPosition::place(" << code << ", " << index << ")");
319 
320  // Refuse to place pawns on row 1 or 8.
321  if (code.is_a(pawn))
322  {
323  int row = index.row();
324  if (row == 0 || row == 7)
325  return false;
326  }
327  // Refuse to place two kings of the same color on the board.
328  if (code.is_a(king) && M_bitboards[code].test())
329  return false;
330 
331  Code const old_code = M_pieces[index].code(); // The current piece that is on this square, if any.
332 
333  // Do nothing if we replace a piece with the same piece.
334  // This test is actually only effective if we're replacing a pawn that can be taken
335  // en passant with a pawn of the same color; in which case this causes the en passant
336  // state to be preserved.
337  if (old_code == code)
338  return true;
339 
340  mask_t const mask(index2mask(index)); // Calculate the bitboard mask.
341  int index_row = index.row(); // Cache the row of the square involved.
342 
343  if (!old_code.is_nothing())
344  {
345  // Update administration regarding removal of a piece.
346  M_bitboards[old_code.color()].reset(mask);
347  M_bitboards[old_code].reset(mask);
348 
349  // Update castling flags.
350  M_castle_flags.update_removed(old_code, index);
351 
352  // Update can_take_king/queen_side flags.
353  if (code.is_nothing() || code.color() != old_code.color())
354  update_removed(index.col(), index_row, old_code.color());
355 
356  // Update can_take_king/queen_side flags for pawns 'taking' the en_passant pawn, if any.
357  if (
358 #if DEBUG_ENPASSANT_EXISTS
359  M_en_passant.exists() && // This check is normally not needed because if M_en_passant.M_bits == 64,
360  // then M_en_passant.pawn_index() returns 72, so the test will fail anyway.
361 #endif
362  M_en_passant.pawn_index() == index)
363  clear_en_passant(); // The pawn that could be taken en passant was removed.
364 
365  // Update is_blocked flag for pawns.
366  if (code.is_nothing())
367  {
368  if (index_row > 1 && M_pieces[index - 8] == white_pawn)
369  {
370  M_pieces[index - 8].set_is_not_blocked();
371  if (index_row == 2 && M_pieces[index + 8] == nothing)
372  M_pieces[index - 8].set_can_move_two_squares();
373  }
374  else if (index_row == 3 && M_pieces[index - 16] == white_pawn)
375  M_pieces[index - 16].set_can_move_two_squares_if_not_blocked();
376  if (index_row < 6 && M_pieces[index + 8] == black_pawn)
377  {
378  M_pieces[index + 8].set_is_not_blocked();
379  if (index_row == 5 && M_pieces[index - 8] == nothing)
380  M_pieces[index + 8].set_can_move_two_squares();
381  }
382  else if (index_row == 4 && M_pieces[index + 16] == black_pawn)
383  M_pieces[index + 16].set_can_move_two_squares_if_not_blocked();
384  }
385 
386  // Reset all pinning flags if piece being removed is a king.
387  if (old_code.is_a(king))
388  {
389  M_attackers[old_code].reset();
390  M_pinning[old_code].reset();
391  M_en_passant.pinned_reset();
392  M_king_battery_attack_count[old_code.color().opposite()] = 0;
393  }
394 
395  // Update the M_defended CountBoard.
396  bool battery = false;
397  M_defended[old_code.color()].sub(defendables(old_code, index, battery));
398  if (battery)
399  --M_king_battery_attack_count[old_code.color()];
400  update_blocked_defendables(old_code, index, true);
401  }
402 
403  if (!code.is_nothing())
404  {
405  // Update administration regarding adding of a piece.
406  M_bitboards[code.color()].set(mask);
407  M_bitboards[code].set(mask);
408 
409  // Update castling flags.
410  M_castle_flags.update_placed(code, index);
411 
412  // Clear the right of taking en passant if a piece is placed behind the en passant pawn.
413  if (M_en_passant.exists() && (index == M_en_passant.index() || index == M_en_passant.from_index()))
414  clear_en_passant();
415 
416  // Update can_take_king/queen_side flags.
417  if (old_code.is_nothing() || code.color() != old_code.color())
418  update_placed(index.col(), index_row, code.color());
419 
420  // Update is_blocked flag for pawns.
421  if (old_code.is_nothing())
422  {
423  if (index_row > 1 && M_pieces[index - 8] == white_pawn)
424  M_pieces[index - 8].reset_is_not_blocked();
425  else if (index_row == 3 && M_pieces[index - 16] == white_pawn)
426  M_pieces[index - 16].reset_can_move_two_squares();
427  if (index_row < 6 && M_pieces[index + 8] == black_pawn)
428  M_pieces[index + 8].reset_is_not_blocked();
429  else if (index_row == 4 && M_pieces[index + 16] == black_pawn)
430  M_pieces[index + 16].reset_can_move_two_squares();
431  }
432 
433  // Update pinning flags if a king is being placed on the board.
434  if (code.is_a(king))
435  {
436  // Set bishop_code, rook_code and queen_code to the code of respective pieces of the opposite color.
437  Color color(code.color());
438  color.toggle();
439  Code bishop_code(color, bishop);
440  Code rook_code(color, rook);
441  Code queen_code(color, queen);
442  // Find all rook movers on the same line as this king.
443  BitBoard rook_attackers(candidates_table[candidates_table_offset(rook) + index()]);
444  rook_attackers& = M_bitboards[rook_code] | M_bitboards[queen_code];
445  // Find all bishop movers on the same line as this king.
446  BitBoard bishop_attackers(candidates_table[candidates_table_offset(bishop) + index()]);
447  bishop_attackers& = M_bitboards[bishop_code] | M_bitboards[queen_code];
448  // Finally fill M_attackers with all squares between king and attacking pieces (inclusive).
449  BitBoard attackers(CW_MASK_T_CONST(0));
450  for (PieceIterator piece_iter(this, rook_attackers); piece_iter != piece_end(); ++piece_iter)
451  attackers |= squares_from_to(piece_iter.index(), index);
452  for (PieceIterator piece_iter(this, bishop_attackers); piece_iter != piece_end(); ++piece_iter)
453  attackers |= squares_from_to(piece_iter.index(), index);
454  M_attackers[code] = attackers;
455  BitBoard const all_pieces(M_bitboards[white] | M_bitboards[black]);
456  BitBoard possible_pinning_directions(candidates_table[candidates_table_offset(king) + index()]); // All squares around the king.
457  possible_pinning_directions& = attackers; // Only those squares in the direction of attackers.
458  for (PieceIterator direction_iter(this, possible_pinning_directions); direction_iter != piece_end(); ++direction_iter)
459  {
460  Direction direction(direction_from_to(index, direction_iter.index())); // Run over all directions in which there are attackers.
461  BitBoard relevant_pieces(all_pieces); // Only the pieces.
462  relevant_pieces& = direction.from(index); // On the line towards the attacker.
463  update_pinning(code, index, mask, direction, relevant_pieces);
464  }
465  }
466 
467  // Update the M_defended CountBoard.
468  bool battery = false;
469  M_defended[code.color()].add(defendables(code, index, battery));
470  if (battery)
471  ++M_king_battery_attack_count[code.color()];
472  update_blocked_defendables(code, index, false);
473  }
474 
475  Flags flags(fl_none);
476 
477  if (code.is_a(pawn))
478  {
479  // Initialize the pawn flags for this pawn.
480  // Calculate forward1: the square right in front of the pawn,
481  // forward2: the square two squares in front of the pawn, or 0 if that's off the board.
482  // kingside: the square that the pawn attacks towards the h-file (or 0 when the pawn is on the h-file).
483  // queenside: the square that the pawn attacks towards the a-file (or 0 when the pawn is on the a-file).
484  // other_pieces: All pieces of a different color.
485  // all_pieces: All pieces.
486  BitBoardData forward1 = { mask };
487  BitBoardData forward2 = { mask };
488  BitBoard other_pieces, all_pieces;
489  uint8_t initial_row;
490  if (code.color() == white)
491  {
492  other_pieces = M_bitboards[black];
493  forward1.M_bitmask <<= 8;
494  forward2.M_bitmask <<= 16;
495  all_pieces = other_pieces | M_bitboards[white];
496  initial_row = 1;
497  }
498  else
499  {
500  other_pieces = M_bitboards[white];
501  forward1.M_bitmask >>= 8;
502  forward2.M_bitmask >>= 16;
503  all_pieces = other_pieces | M_bitboards[black];
504  initial_row = 6;
505  }
506  BitBoardData kingside(forward1), queenside(forward1);
507  kingside.M_bitmask <<= 1;
508  queenside.M_bitmask >>= 1;
509  kingside.M_bitmask& = ~file_a.M_bitmask;
510  queenside.M_bitmask& = ~file_h.M_bitmask;
511  if (!(all_pieces & forward1))
512  {
513  flags |= fl_pawn_is_not_blocked;
514  if (!(all_pieces & forward2) && initial_row == index_row)
516  }
517  if (M_en_passant.exists() && M_en_passant.from_index().row() != initial_row)
518  other_pieces |= M_en_passant.index();
519  if ((other_pieces & queenside))
521  if ((other_pieces & kingside))
523  }
524 
525  // Replace or put the piece on the board.
526  M_pieces[index] = Piece(code, flags);
527 
528  // Update pinning flags.
529  //
530  // We have two pinning masks (for each color of the king, so four in total).
531  // The first mask (M_attackers) contains bits for every square between every attacker and the king (not including the king).
532  // The second mask (M_pinning) contains the same, but only for those attackers that actually pin a piece.
533  //
534  // For the examples, we consider only rooks as attackers, and only over a horizontal line.
535  //
536  // We have the following cases:
537  //
538  // 1) The new piece is on a line with the enemy king : we need to check more.
539  //
540  // x ? ? ? ? K
541  //
542  // 2) The new piece is not on a line with the enemy king : we do not need to update anything.
543  //
544  // x ? ? ? ? ?
545  // ? ? ? ? ? K
546  //
547  // In case 1), we have the possibilities:
548  //
549  // 1a) The new piece is an attacker (a rook or queen, in the case of a horizontal line) of the enemy king.
550  //
551  // r ? ? ? ? K
552  //
553  // 1b) The new piece is not an attacker (or empty)
554  //
555  // n ? ? ? ? K
556  //
557  // This is sufficient information to update mask 1:
558  // In the case of 1b we need to do nothing unless we're removing a piece (case 1br).
559  // In the case 1a we need set bits only if the bit under the piece is not set already.
560  //
561  // For example,
562  // __ no attackers
563  // ___/
564  // ? ? r ? ? ? ? K
565  // mask1: 0 0 1 1 1 1 1 0
566  // place: r --> mask doesn't change.
567  // place: r --> mask is extended.
568  //
569  // In case 1br, there are two cases:
570  //
571  // 1br1) We are removing an attacker.
572  // 1br2) We are not removing an attacker.
573  //
574  // In case 1br1 it is necessary to recalculate mask 1. For example,
575  //
576  // ? ? r - r - N K
577  // mask1: 0 0 1 1 1 1 1 0
578  // remove: ^
579  // mask1: 0 0 0 0 1 1 1 0
580  //
581  // At this point mask 1 is updated.
582  //
583  // In case 1br1 we only need to update mask 2 if the attacker being removed
584  // was the pinning attacker, if the corresponding bit in mask 2 is set as well,
585  // or if there wasn't any pinning along this line.
586  //
587  // For example,
588  //
589  // ? ? r - r - N K
590  // mask1: 0 0 1 1 1 1 1 0
591  // mask2: 0 0 0 0 1 1 1 0
592  // remove: ^ Not update of mask2 is needed.
593  // remove: ^
594  // mask2: 0 0 1 1 1 1 1 0
595  //
596  // or
597  //
598  // ? ? r N r - - K
599  // mask1: 0 0 1 1 1 1 1 0
600  // mask2: 0 0 0 0 0 0 0 0
601  // remove: ^
602  // mask2: 0 0 1 1 1 1 1 0
603  //
604  // In case 1br2 we need to reset mask 2, and there is only a need to recalculate
605  // it if the piece being removed wasn't actually pinned. For example,
606  //
607  // ? ? r - N - N K
608  // mask1: 0 0 1 1 1 1 1 0
609  // mask2: 0 0 0 0 0 0 0 0
610  // remove: ^
611  // mask2: 0 0 1 1 1 1 1 0
612  //
613  // or
614  //
615  // ? ? r - N - - K
616  // mask1: 0 0 1 1 1 1 1 0
617  // mask2: 0 0 1 1 1 1 1 0
618  // remove: ^
619  // mask2: 0 0 0 0 0 0 0 0 Just reset: the removed piece was pinned (we're in check now).
620  //
621  // If the piece is an attacker (==> the corresponding bit in mask 1 is set), we need
622  // to reset the bits for this direction in mask 2 and call ChessPosition::update_pinning.
623  //
624  // ? ? r - - - N K The knight is pinned.
625  // mask1: 0 0 1 1 1 1 1 0
626  // mask2: 0 0 1 1 1 1 1 0
627  // place: r
628  // mask2: 0 0 0 0 1 1 1 0 The knight is pinned by the new piece.
629  //
630  // If the piece is not an attacker and the corresponding bit in mask 1 is not set,
631  // then we are done.
632  //
633  // ? ? r - - - N K
634  // mask1: 0 0 1 1 1 1 1 0
635  // mask2: 0 0 1 1 1 1 1 0
636  // place: b
637  // mask2: 0 0 1 1 1 1 1 0 The knight is still pinnded by the old piece (r).
638  //
639  // If the piece is not an attacker and the corresponding bit in mask 1 is set,
640  // We have two possibilities: the corresponding bit in mask 2 is set, or not set:
641  //
642  // 1ba) The new piece is not an attacker and the corresponding bit in mask 1 and mask 2 are set.
643  // 1bb) The new piece is not an attacker and the corresponding bit in mask 1 is set, and in mask 2 is not set.
644  //
645  // In case 1ba, the bits for this direction in mask 2 must be reset, and if old_code
646  // is not empty, ChessPosition::update_pinning must be called.
647  //
648  // ? ? r - - - N K
649  // mask1: 0 0 1 1 1 1 1 0
650  // mask2: 0 0 1 1 1 1 1 0
651  // place: b
652  // mask2: 0 0 0 0 0 0 0 0
653  // place: b
654  // mask2: 0 0 0 0 0 0 0 0
655  // place: B
656  // mask2: 0 0 1 1 1 1 1 0
657  //
658  // In case 1bb, if any bit for this direction in mask 2 is set, or if the color
659  // of the piece that is placed is different from the king, we are done.
660  // Otherwise we need to call ChessPosition::update_pinning.
661  //
662  // ? ? r - r - N K
663  // mask1: 0 0 1 1 1 1 1 0
664  // mask2: 0 0 0 0 1 1 1 0
665  // place: b We are done.
666  //
667  // ? ? r - - - - K
668  // mask1: 0 0 1 1 1 1 1 0
669  // mask2: 0 0 0 0 0 0 0 0
670  // place: B
671  // mask2: 0 0 1 1 1 1 1 0
672  //
673  int color_count = 0;
674  // Run over all colors.
675  for (Color color = black; color_count < 2; ++color_count, color = white)
676  {
677  Code const king_code(color, king); // The king of this color.
678  Index const king_index(mask2index(M_bitboards[king_code]())); // Where that king is.
679  if (king_index == index_end)
680  continue; // If there isn't a king of that color, nothing can be pinned.
681  BitBoard const line(squares_from_to(index, king_index)); // All squares from the new piece to the that king.
682  if (!line.test()) // Are the piece and this king on one line at all?
683  continue; // case 2: If not, then this piece cannot influence pinning.
684 
685  // case 1:
686  Direction const direction(direction_from_to(king_index, index)); // The direction from king to this piece.
687  bool const attacker = (code.color() != color) && direction.matches(code.type()); // The new piece attacks the king if it is of opposite color
688  // and can move along the given direction.
689  bool need_reset = false; // Set if M_pinning might have bits set that need to be unset.
690  bool need_update = false; // Recalculate M_pinning.
691 
692  bool const corresponding_bit_in_M_attackers_is_set = M_attackers[color]() & mask;
693  if (attacker)
694  {
695  // case 1a.
696  if (!corresponding_bit_in_M_attackers_is_set)
697  {
698  // We have a new attacker that is even further away from the king.
699  M_attackers[color] |= line; // Extend M_attackers to include the new attacker.
700  }
701  need_reset = need_update = true;
702  }
703  else if (corresponding_bit_in_M_attackers_is_set)
704  {
705  // Case 1b.
706  if (code.is_nothing())
707  {
708  // Case 1br.
709  if (direction.matches(old_code.type()))
710  {
711  // An attacker was removed. Check if M_attackers needs to be changed.
712  TypeData mover;
713  mover.M_bits = direction.flags & type_mask;
714  Code queen_code(color.opposite(), queen);
715  Code mover_code(color.opposite(), mover);
716  BitBoard mover_attackers(M_bitboards[mover_code] | M_bitboards[queen_code]);
717  BitBoard line(direction.from(king_index));
718  mover_attackers& = line;
719  BitBoard attackers(CW_MASK_T_CONST(0));
720  for (PieceIterator piece_iter(this, mover_attackers); piece_iter != piece_end(); ++piece_iter)
721  attackers |= squares_from_to(piece_iter.index(), king_index);
722  M_attackers[color].reset(line);
723  M_attackers[color].set(attackers);
724 
725  // We only need an update if the corresponding bit in M_pinning is set as well
726  // (then this was the pinning attacker), or otherwise if M_pinning has no
727  // bits set at all, in which case this piece could have been blocking the pin.
728  need_reset = need_update = M_pinning[color].test(mask) || !(M_pinning[color] & line).test();
729  }
730  else
731  {
732  // A non-attacker was removed.
733  need_reset = true;
734  // If the corresponding bit in M_pinning isn't set, then this wasn't a pinned piece, so we need to update M_pinning.
735  need_update = !(M_pinning[color]() & mask);
736  }
737  }
738  else if ((M_pinning[color]() & mask)) // Is the corresponding bit in M_pinning set too?
739  {
740  // Case 1ba.
741  need_reset = true;
742  need_update = !old_code.is_nothing();
743  }
744  else
745  {
746  // Case 1bb.
747  BitBoard line(direction.from(king_index));
748  need_reset = need_update =
749  (code.color() == color || (M_en_passant.exists() && direction.is_horizontal())) && !M_pinning[color].test(line);
750  }
751  }
752  if (need_reset)
753  {
754  BitBoard line(direction.from(king_index));
755  M_pinning[color].reset(line);
756  if (need_update)
757  {
758  if (__builtin_expect(M_en_passant.exists(), false))
759  {
760  Index pawn_index(M_en_passant.pawn_index());
761  if (M_pieces[pawn_index].color() != color && line.test(pawn_index))
762  M_en_passant.pinned_reset();
763  }
764  update_pinning(king_code, king_index, M_bitboards[king_code](), direction, (M_bitboards[black] | M_bitboards[white]) & line);
765  }
766  }
767  }
768 
769  // Update caching of in_check and M_double_check.
770  bool in_check = check();
771  M_castle_flags.set_check(M_to_move, in_check);
772  M_castle_flags.set_check(M_to_move.opposite(), check(M_to_move.opposite()));
773  M_double_check = in_check ? double_check(M_to_move) : false;
774 
775  // Success.
776  return true;
777 }
778 
779 bool ChessPosition::load_FEN(std::string const& FEN)
780 {
781  DoutEntering(dc::notice, "ChessPosition::load_FEN(\"" << FEN << "\")");
782 
783  // Clear the position.
784  clear();
785  std::string::const_iterator iter = FEN.begin();
786  char c;
787  // Eat preceding spaces.
788  while (*iter == ' ')
789  ++iter;
790  if (iter == FEN.end())
791  return false;
792  // Field 1: Piece placement.
793  Color color;
794  int col = 0, row = 7;
795  while ((c =* iter++) != ' ')
796  {
797  color = white;
798  switch (c)
799  {
800  case '/':
801  if (col != 8 || row <= 0)
802  return false;
803  col = 0;
804  --row;
805  break;
806  case '1':
807  case '2':
808  case '3':
809  case '4':
810  case '5':
811  case '6':
812  case '7':
813  case '8':
814  col += (int)(c - '0');
815  break;
816  case 'p':
817  case 'r':
818  case 'n':
819  case 'b':
820  case 'q':
821  case 'k':
822  color = black;
823  case 'P':
824  case 'R':
825  case 'N':
826  case 'B':
827  case 'Q':
828  case 'K':
829  {
830  c = std::toupper(c);
831  Type type;
832  if (c == 'P')
833  type = pawn;
834  else if (c == 'R')
835  type = rook;
836  else if (c == 'N')
837  type = knight;
838  else if (c == 'B')
839  type = bishop;
840  else if (c == 'Q')
841  type = queen;
842  else // if (c == 'K')
843  type = king;
844  place(Code(color, type), Index(col, row));
845  ++col;
846  break;
847  }
848  default:
849  return false;
850  }
851  if (iter == FEN.end())
852  return false;
853  }
854  if (col != 8)
855  return false;
856  if (iter == FEN.end())
857  return false;
858  // Eat extra spaces.
859  while (*iter == ' ')
860  if (++iter == FEN.end())
861  return false;
862  // Field 2: Active color.
863  c =* iter++;
864  if (c != 'w' && c != 'b')
865  return false;
866  M_to_move = (c == 'w') ? white : black;
867  bool in_check = check();
868  M_double_check = in_check ? double_check(M_to_move) : false;
869  if (iter == FEN.end() ||* iter != ' ')
870  return false;
871  // Eat space and possibly extra spaces.
872  while (*iter == ' ')
873  if (++iter == FEN.end())
874  return false;
875  // Field 3: Castling availability.
876  uint8_t white_castle_flags = white_rook_queen_side_moved | white_king_moved | white_rook_king_side_moved;
877  uint8_t black_castle_flags = black_rook_queen_side_moved | black_king_moved | black_rook_king_side_moved;
878  while ((c =* iter++) != ' ')
879  {
880  if (c == '-')
881  break;
882  switch (c)
883  {
884  case 'K':
885  white_castle_flags& = ~(white_king_moved | white_rook_king_side_moved);
886  break;
887  case 'Q':
888  white_castle_flags& = ~(white_king_moved | white_rook_queen_side_moved);
889  break;
890  case 'k':
891  black_castle_flags& = ~(black_king_moved | black_rook_king_side_moved);
892  break;
893  case 'q':
894  black_castle_flags& = ~(black_king_moved | black_rook_queen_side_moved);
895  break;
896  default:
897  return false;
898  }
899  if (iter == FEN.end())
900  return false;
901  }
902  M_castle_flags = white_castle_flags | black_castle_flags;
903  M_castle_flags.set_check(M_to_move, in_check);
904  if (iter == FEN.end())
905  return false;
906  // Eat extra spaces.
907  while (*iter == ' ')
908  if (++iter == FEN.end())
909  return false;
910  // Field 4: En passant target square in algebraic notation.
911  if ((c =* iter++) != '-')
912  {
913  if (c < 'a' || c > 'h' || iter == FEN.end())
914  return false;
915  int col = c - 'a';
916  c =* iter++;
917  if (c < '1' || c > '8' || iter == FEN.end())
918  return false;
919  int row = c - '1';
920  Code other_pawn;
921  if (M_to_move == white)
922  {
923  other_pawn = white_pawn;
924  if (row != 5 || M_pieces[Index(col, row - 1)] != black_pawn || M_pieces[Index(col, row)] != nothing)
925  return false;
926  }
927  else
928  {
929  other_pawn = black_pawn;
930  if (row != 2 || M_pieces[Index(col, row + 1)] != white_pawn || M_pieces[Index(col, row)] != nothing)
931  return false;
932  }
933  set_en_passant(Index(col, row));
934  }
935  if (iter == FEN.end() ||* iter != ' ')
936  return false;
937  // Eat space and possibly extra spaces.
938  while (*iter == ' ')
939  if (++iter == FEN.end())
940  return false;
941  // Field 5: Halfmove clock: This is the number of halfmoves since the last pawn advance or capture.
942  M_half_move_clock = 0;
943  while ((c =* iter++) != ' ')
944  {
945  if (!std::isdigit(c))
946  return false;
947  M_half_move_clock = 10 * M_half_move_clock + c - '0';
948  if (iter == FEN.end())
949  return false;
950  }
951  // Eat extra spaces.
952  while (*iter == ' ')
953  if (++iter == FEN.end())
954  return false;
955  // Field 6: Fullmove number: The number of the full move.
956  M_full_move_number = 0;
957  while (iter != FEN.end() &&* iter != ' ')
958  {
959  if (!std::isdigit(*iter))
960  return false;
961  M_full_move_number = 10 * M_full_move_number +* iter++ - '0';
962  }
963  if (M_full_move_number == 0)
964  return false;
965  // Success.
966  return true;
967 }
968 
969 std::string ChessPosition::FEN(void) const
970 {
971  std::ostringstream fen;
972  for (int row = 7; row >= 0; --row)
973  {
974  int empty_count = 0;
975  for (int col = 0; col <= 7; ++col)
976  {
977  Code code = M_pieces[Index(col, row)].code();
978  if (code.is_nothing())
979  ++empty_count;
980  else if (empty_count > 0)
981  {
982  fen << (char)('0' + empty_count);
983  empty_count = 0;
984  }
985  switch (code())
986  {
987  case (black_bits|pawn_bits):
988  fen << 'p';
989  break;
990  case (black_bits|rook_bits):
991  fen << 'r';
992  break;
993  case (black_bits|knight_bits):
994  fen << 'n';
995  break;
996  case (black_bits|bishop_bits):
997  fen << 'b';
998  break;
999  case (black_bits|queen_bits):
1000  fen << 'q';
1001  break;
1002  case (black_bits|king_bits):
1003  fen << 'k';
1004  break;
1005  case (white_bits|pawn_bits):
1006  fen << 'P';
1007  break;
1008  case (white_bits|rook_bits):
1009  fen << 'R';
1010  break;
1011  case (white_bits|knight_bits):
1012  fen << 'N';
1013  break;
1014  case (white_bits|bishop_bits):
1015  fen << 'B';
1016  break;
1017  case (white_bits|queen_bits):
1018  fen << 'Q';
1019  break;
1020  case (white_bits|king_bits):
1021  fen << 'K';
1022  break;
1023  }
1024  }
1025  if (empty_count > 0)
1026  fen << (char)('0' + empty_count);
1027  if (row != 0)
1028  fen << '/';
1029  }
1030  if (M_to_move == white)
1031  fen << " w ";
1032  else
1033  fen << " b ";
1034  unsigned int flags = 0;
1035  if (M_castle_flags.can_castle_short(white))
1036  flags |= 1;
1037  if (M_castle_flags.can_castle_long(white))
1038  flags |= 2;
1039  if (M_castle_flags.can_castle_short(black))
1040  flags |= 4;
1041  if (M_castle_flags.can_castle_long(black))
1042  flags |= 8;
1043  if (flags == 0)
1044  fen << '-';
1045  else
1046  {
1047  for (unsigned int mask = 1; mask <= 8; mask <<= 1)
1048  {
1049  if ((flags & mask))
1050  {
1051  switch (mask)
1052  {
1053  case 1:
1054  fen << 'K';
1055  break;
1056  case 2:
1057  fen << 'Q';
1058  break;
1059  case 4:
1060  fen << 'k';
1061  break;
1062  case 8:
1063  fen << 'q';
1064  break;
1065  }
1066  }
1067  }
1068  }
1069  fen << ' ' << M_en_passant.FEN4() << ' ' << (int)M_half_move_clock << ' ' << (int)M_full_move_number;
1070  return fen.str();
1071 }
1072 
1074 {
1075  int offset;
1076  Code code;
1077  if (index.row() == 2)
1078  {
1079  code = black_pawn;
1080  offset = 8;
1081  to_move(black);
1082  }
1083  else
1084  {
1085  code = white_pawn;
1086  offset = -8;
1087  to_move(white);
1088  }
1089  M_en_passant = EnPassant(index);
1090  Index index_of_only_neighboring_pawn = index_end;
1091  bool possible = false;
1092  if (index.col() > 0 && M_pieces[index + offset - 1] == code)
1093  {
1094  possible = true;
1095  index_of_only_neighboring_pawn = index + offset - 1;
1096  M_pieces[index_of_only_neighboring_pawn].set_can_take_king_side();
1097  }
1098  if (index.col() < 7 && M_pieces[index + offset + 1] == code)
1099  {
1100  possible = true;
1101  Index right_pawn_index = index + offset + 1;
1102  M_pieces[right_pawn_index].set_can_take_queen_side();
1103  if (index_of_only_neighboring_pawn != index_end)
1104  index_of_only_neighboring_pawn = index_end;
1105  else
1106  index_of_only_neighboring_pawn = right_pawn_index;
1107  }
1108  if (index_of_only_neighboring_pawn != index_end)
1109  {
1110  mask_t mask = index2mask(index_of_only_neighboring_pawn);
1111  if (M_attackers[M_to_move].test(mask))
1112  {
1113  Code king_code(M_to_move, king);
1114  mask = M_bitboards[king_code]();
1115  Index king_index(mask2index(mask));
1116  Direction direction(direction_from_to(king_index, index_of_only_neighboring_pawn));
1117  if (direction.is_horizontal())
1118  {
1119  BitBoard line(direction.from(king_index));
1120  M_pinning[M_to_move].reset(line);
1121  update_pinning(king_code, king_index, mask, direction, (M_bitboards[black] | M_bitboards[white]) & line);
1122  M_en_passant.pinned_set();
1123  }
1124  }
1125  }
1126  return possible;
1127 }
1128 
1129 enum up_and_right {
1130  right = 1,
1131  up_left = 7,
1132  up = 8,
1133  up_right = 9,
1134 };
1135 
1136 enum down_and_left {
1137  left = 1,
1138  down_right = 7,
1139  down = 8,
1140  down_left = 9
1141 };
1142 
1143 template <typename T>
1144 inline void move(mask_t& m, T);
1145 
1146 template <>
1147 inline void move<up_and_right>(mask_t& m, up_and_right offset)
1148 {
1149  m <<= offset;
1150 }
1151 
1152 template <>
1153 inline void move<down_and_left>(mask_t& m, down_and_left offset)
1154 {
1155  m >>= offset;
1156 }
1157 
1158 BitBoard ChessPosition::all_pieces_minus_bishop_movers(Color const& color, Index const& index) const
1159 {
1160  BitBoard result(M_bitboards[white] | M_bitboards[black]); // A bitboard with bits set on every square where there is any piece.
1161  if (color.is_white())
1162  {
1163  result.reset(M_bitboards[white_queen]); // Remove the queens and bishop, because we can defend through them.
1164  result.reset(M_bitboards[white_bishop]);
1165 
1166  BitBoard north_west_pawn(M_bitboards[white_pawn]);
1167  north_west_pawn& = Direction(north_west).from(index);
1168  if (north_west_pawn.test())
1169  {
1170  Index res(index_pre_begin);
1171  res.next_bit_in(north_west_pawn());
1172  result.reset(res);
1173  if (res.col() != 0)
1174  {
1175  res += north_west.offset;
1176  result.set(res);
1177  }
1178  }
1179  BitBoard north_east_pawn(M_bitboards[white_pawn]);
1180  north_east_pawn& = Direction(north_east).from(index);
1181  if (north_east_pawn.test())
1182  {
1183  Index res(index_pre_begin);
1184  res.next_bit_in(north_east_pawn());
1185  result.reset(res);
1186  if (res.col() != 7)
1187  {
1188  res += north_east.offset;
1189  result.set(res);
1190  }
1191  }
1192  }
1193  else
1194  {
1195  result.reset(M_bitboards[black_queen]); // Remove the queens and bishop, because we can defend through them.
1196  result.reset(M_bitboards[black_bishop]);
1197 
1198  BitBoard south_west_pawn(M_bitboards[black_pawn]);
1199  south_west_pawn& = Direction(south_west).from(index);
1200  if (south_west_pawn.test())
1201  {
1202  Index res(index_end);
1203  res.prev_bit_in(south_west_pawn());
1204  result.reset(res);
1205  if (res.col() != 0)
1206  {
1207  res += south_west.offset;
1208  result.set(res);
1209  }
1210  }
1211  BitBoard south_east_pawn(M_bitboards[black_pawn]);
1212  south_east_pawn& = Direction(south_east).from(index);
1213  if (south_east_pawn.test())
1214  {
1215  Index res(index_end);
1216  res.prev_bit_in(south_east_pawn());
1217  result.reset(res);
1218  if (res.col() != 7)
1219  {
1220  res += south_east.offset;
1221  result.set(res);
1222  }
1223  }
1224  }
1225  return result;
1226 }
1227 
1228 BitBoard ChessPosition::defendables(Code const& code, Index const& index, bool& battery) const
1229 {
1230  Color color = code.color(); // The color of the piece.
1231  mask_t pos = index2mask(index); // The current position of the piece.
1232  switch(code.type()())
1233  {
1234  case nothing_bits: // This should never be called, but return an empty bitboard anyway.
1235  {
1236  BitBoard result;
1237  result.reset();
1238  return result;
1239  }
1240  case pawn_bits:
1241  {
1242  int col = index.col();
1243  BitBoard result((color == white) ? (pos << 7) | (pos << 9) : (pos >> 9) | (pos >> 7));
1244  if (__builtin_expect(col == 0, false))
1245  result.reset(file_h);
1246  else if (__builtin_expect(col == 7, false))
1247  result.reset(file_a);
1248  return result;
1249  }
1250  case knight_bits:
1251  {
1252  BitBoard result(candidates_table[candidates_table_offset(knight) + index()]);
1253  return result;
1254  }
1255  case king_bits:
1256  {
1257  BitBoard result(candidates_table[candidates_table_offset(king) + index()]);
1258  return result;
1259  }
1260  case rook_bits:
1261  {
1262  BitBoard all_pieces_minus_rook_movers(M_bitboards[white] | M_bitboards[black]);
1263  Code queen_code(color, queen);
1264  Code rook_code(color, rook);
1265  BitBoard other_attackers(M_bitboards[queen_code] | M_bitboards[rook_code]);
1266  all_pieces_minus_rook_movers.reset(other_attackers); // Remove the queens and rooks, because we can defend through them.
1267 
1268  // Find reachable squares above the rook.
1269  mask_t block = all_pieces_minus_rook_movers();
1270  mask_t probe = pos;
1271  mask_t reachables = 0;
1272  do
1273  {
1274  move(probe, up);
1275  reachables |= probe;
1276  }
1277  while((block & probe) != probe);
1278 
1279  // Find reachable squares below the rook.
1280  probe = pos;
1281  do
1282  {
1283  move(probe, down);
1284  reachables |= probe;
1285  }
1286  while((block & probe) != probe);
1287 
1288  // Result so far.
1289  BitBoard result(reachables);
1290 
1291  // Find reachable squares left of the rook.
1292  block |= file_h.M_bitmask;
1293  probe = pos;
1294  do
1295  {
1296  move(probe, left);
1297  reachables |= probe;
1298  }
1299  while((block & probe) != probe);
1300  reachables& = ~file_h.M_bitmask;
1301 
1302  // Update result.
1303  result |= reachables;
1304 
1305  // Find reachable squares right of the rook.
1306  block = all_pieces_minus_rook_movers() | file_a.M_bitmask;
1307  probe = pos;
1308  do
1309  {
1310  move(probe, right);
1311  reachables |= probe;
1312  }
1313  while((block & probe) != probe);
1314  reachables& = ~file_a.M_bitmask;
1315 
1316  result |= reachables;
1317 
1318  // Do we need to update M_king_battery_attack_count?
1319  BitBoard opposite_king_pos(M_bitboards[Code(color.opposite(), king)]); // The position of the opposite king.
1320  if (__builtin_expect(
1321  result.test(opposite_king_pos) && // Do we give check?
1322  result.test(other_attackers), // and block or look through another attacker?
1323  false))
1324  {
1325  // This other attacker could be on a different line than the one to the king.
1326  // So, check if it is really on the line with the king or not.
1327  Index king_index(mask2index(opposite_king_pos()));
1328  Direction direction(direction_from_to(king_index, index));
1329  BitBoard line(direction.from(king_index)); // All squares from checked king in the direction of the new attacker.
1330  line& = result; // ... but only until the blocker on the other side.
1331  line& = other_attackers; // ... only possible other attackers.
1332  battery = line.test(); // Battery exists if line is non-empty (note that 'result' has 'index' never set).
1333  }
1334 
1335  return result;
1336  }
1337  case bishop_bits:
1338  {
1339  BitBoard all_pieces_minus_bishop_movers(this->all_pieces_minus_bishop_movers(color, index));
1340 
1341  // Find reachable squares left below the bishop.
1342  mask_t block = all_pieces_minus_bishop_movers() | file_h.M_bitmask;
1343  mask_t probe = pos;
1344  mask_t reachables = 0;
1345  do
1346  {
1347  move(probe, down_left);
1348  reachables |= probe;
1349  }
1350  while((block & probe) != probe);
1351 
1352  // Find reachable squares left above the bishop.
1353  probe = pos;
1354  do
1355  {
1356  move(probe, up_left);
1357  reachables |= probe;
1358  }
1359  while((block & probe) != probe);
1360  reachables& = ~file_h.M_bitmask;
1361 
1362  // Result so far.
1363  BitBoard result(reachables);
1364 
1365  // Find reachable squares right above the bishop;
1366  block = all_pieces_minus_bishop_movers() | file_a.M_bitmask;
1367  probe = pos;
1368  do
1369  {
1370  move(probe, up_right);
1371  reachables |= probe;
1372  }
1373  while((block & probe) != probe);
1374 
1375  // Find reachable squares right below the bishop;
1376  probe = pos;
1377  do
1378  {
1379  move(probe, down_right);
1380  reachables |= probe;
1381  }
1382  while((block & probe) != probe);
1383  reachables& = ~file_a.M_bitmask;
1384 
1385  result |= reachables;
1386 
1387  // Do we need to update M_king_battery_attack_count?
1388  BitBoard opposite_king_pos(M_bitboards[Code(color.opposite(), king)]); // The position of the opposite king.
1389  if (__builtin_expect(result.test(opposite_king_pos), false)) // Do we give check?
1390  {
1391  Code queen_code(color, queen);
1392  Code bishop_code(color, bishop);
1393  BitBoard other_attackers(M_bitboards[queen_code] | M_bitboards[bishop_code]);
1394  if (result.test(other_attackers)) // and block or look through another attacker?
1395  {
1396  // This other attacker could be on a different line than the one to the king.
1397  // So, check if it is really on the line with the king or not.
1398  Index king_index(mask2index(opposite_king_pos()));
1399  Direction direction(direction_from_to(king_index, index));
1400  BitBoard line(direction.from(king_index)); // All squares from checked king in the direction of the new attacker.
1401  line& = result; // ... but only until the blocker on the other side.
1402  line& = other_attackers; // ... only possible other attackers.
1403  battery = line.test(); // Battery exists if line is non-empty (note that 'result' has 'index' never set).
1404  }
1405  }
1406 
1407  return result;
1408  }
1409  case queen_bits:
1410  {
1411  BitBoard all_pieces_minus_bishop_movers(this->all_pieces_minus_bishop_movers(color, index));
1412  BitBoard all_pieces_minus_rook_movers(M_bitboards[white] | M_bitboards[black]); // A bitboard with bits set on every square where there is any piece.
1413  Code queen_code(color, queen);
1414  Code rook_code(color, rook);
1415  BitBoard other_rook_movers(M_bitboards[queen_code] | M_bitboards[rook_code]);
1416  all_pieces_minus_rook_movers.reset(other_rook_movers); // Remove the queens and rooks, because we can defend through them.
1417 
1418  // Find reachable squares above the queen.
1419  mask_t block = all_pieces_minus_rook_movers();
1420  mask_t probe = pos;
1421  mask_t reachables = 0;
1422  do
1423  {
1424  move(probe, up);
1425  reachables |= probe;
1426  }
1427  while((block & probe) != probe);
1428 
1429  // Find reachable squares below the queen.
1430  probe = pos;
1431  do
1432  {
1433  move(probe, down);
1434  reachables |= probe;
1435  }
1436  while((block & probe) != probe);
1437 
1438  // Result so far.
1439  BitBoard result(reachables);
1440 
1441  // Find reachable squares left of the queen.
1442  block |= file_h.M_bitmask;
1443  probe = pos;
1444  do
1445  {
1446  move(probe, left);
1447  reachables |= probe;
1448  }
1449  while((block & probe) != probe);
1450 
1451  // And left, but diagonal.
1452  block = all_pieces_minus_bishop_movers() | file_h.M_bitmask;
1453 
1454  // Find reachable squares left below the queen.
1455  probe = pos;
1456  do
1457  {
1458  move(probe, down_left);
1459  reachables |= probe;
1460  }
1461  while((block & probe) != probe);
1462 
1463  // Find reachable squares left above the bishop.
1464  probe = pos;
1465  do
1466  {
1467  move(probe, up_left);
1468  reachables |= probe;
1469  }
1470  while((block & probe) != probe);
1471  reachables& = ~file_h.M_bitmask;
1472 
1473  // Update result.
1474  result |= reachables;
1475 
1476  // Find reachable squares right of the queen.
1477  block = all_pieces_minus_rook_movers() | file_a.M_bitmask;
1478  probe = pos;
1479  do
1480  {
1481  move(probe, right);
1482  reachables |= probe;
1483  }
1484  while((block & probe) != probe);
1485 
1486  // And right, but diagonal.
1487  block = all_pieces_minus_bishop_movers() | file_a.M_bitmask;
1488 
1489  // Find reachable squares right above the queen;
1490  probe = pos;
1491  do
1492  {
1493  move(probe, up_right);
1494  reachables |= probe;
1495  }
1496  while((block & probe) != probe);
1497 
1498  // Find reachable squares right below the queen;
1499  probe = pos;
1500  do
1501  {
1502  move(probe, down_right);
1503  reachables |= probe;
1504  }
1505  while((block & probe) != probe);
1506  reachables& = ~file_a.M_bitmask;
1507 
1508  result |= reachables;
1509 
1510  // Do we need to update M_king_battery_attack_count?
1511  BitBoard opposite_king_pos(M_bitboards[Code(color.opposite(), king)]); // The position of the opposite king.
1512  if (__builtin_expect(result.test(opposite_king_pos), false)) // Do we give check?
1513  {
1514  Code queen_code(color, queen);
1515  Code bishop_code(color, bishop);
1516  BitBoard other_attackers(other_rook_movers | M_bitboards[queen_code] | M_bitboards[bishop_code]);
1517  if (result.test(other_attackers)) // and block or look through another attacker?
1518  {
1519  // This other attacker could be on a different line than the one to the king.
1520  // So, check if it is really on the line with the king or not.
1521  Index king_index(mask2index(opposite_king_pos()));
1522  Direction direction(direction_from_to(king_index, index));
1523  BitBoard line(direction.from(king_index)); // All squares from checked king in the direction of the new attacker.
1524  line& = result; // ... but only until the blocker on the other side.
1525  line& = other_attackers; // ... only possible other attackers.
1526  battery = line.test(); // Battery exists if line is non-empty (note that 'result' has 'index' never set).
1527  }
1528  }
1529 
1530  return result;
1531  }
1532  }
1533  return BitBoard(); // Never reached.
1534 }
1535 
1536 // This function updates M_defended by adding or subtracting BitBoard's
1537 // that represent blocked squares by placing 'code' on square 'index'.
1538 // It also updates M_king_battery_attack_count.
1539 void ChessPosition::update_blocked_defendables(Code const& code, Index const& index, bool add)
1540 {
1541  // A bitboard with bits set on every square where there is any piece.
1542  BitBoard const all_pieces(M_bitboards[white] | M_bitboards[black]);
1543  // Calculate a bitboard with bits set for every rook and queen.
1544  BitBoard blocked_rookmovers(M_bitboards[black_rook] | M_bitboards[black_queen] | M_bitboards[white_rook] | M_bitboards[white_queen]);
1545  // Calculate a bitboard with bits set for every bishop and queen.
1546  BitBoard blocked_bishopmovers(M_bitboards[black_bishop] | M_bitboards[black_queen] | M_bitboards[white_bishop] | M_bitboards[white_queen]);
1547  // However, remove those pieces from these bitboards that can defend THROUGH the considered piece and are of the same color.
1548  // For example, if 'code' is a white rook-- then we remove white rooks and white queens from 'blocked_rookmovers'
1549  // because they won't be blocked by 'code'.
1550  if (code.is_a_slider())
1551  {
1552  Color color(code.color());
1553  Code queen_code(color, queen);
1554  // Queen, rook or bishop.
1555  if (code.is_a_rookmover())
1556  {
1557  // Queen or rook.
1558  Code rook_code(color, rook);
1559  blocked_rookmovers.reset(M_bitboards[rook_code] | M_bitboards[queen_code]);
1560  }
1561  if (code.is_a_bishopmover())
1562  {
1563  // Queen or bishop.
1564  Code bishop_code(color, bishop);
1565  blocked_bishopmovers.reset(M_bitboards[bishop_code] | M_bitboards[queen_code]);
1566  }
1567  }
1568 
1569  // A single piece can block eight different pieces (for all eight directions). Those pieces
1570  // do not necessarily need to be of the same color of course. In order to update the two
1571  // M_defended[] variables (squares defended by white and squares defended by black), we
1572  // need to keep distinguish between squares that need updating because a white piece
1573  // is (un)blocked, and squares that need updating because a black piece is (un)blocked.
1574 
1575  ArrayColor<BitBoard> result;
1576  result[black].reset();
1577  result[white].reset();
1578 
1579  // Find the first piece above the piece at 'index'.
1580  //
1581  // This first direction is heavily commented.
1582  // Consider the following case:
1583  //
1584  // <-- North, South -->
1585  // Q R . r . R k .
1586  // ^
1587  // index
1588  // Where code = r = black_rook, Q = white_queen, R = white_rook and k = black_king.
1589  //
1590  // This case could for example happen if the right-most white rook just took a black piece
1591  // and now black picks up his rook to take back.
1592  //
1593  // Note that blocked_rookmovers is:
1594  // Q R . r . R k .
1595  // 1 1 0 0 0 1 0 0 <-- blocked_rookmovers, all rook movers or opposite color of 'r'.
1596 
1597  // All squares north of index.
1598  // Q R . r . R k .
1599  // 1 1 1 0 0 0 0 0 <-- line
1600  BitBoard line(north.from(index));
1601  // All pieces north of index.
1602  // Q R . r . R k .
1603  // 1 1 0 0 0 0 0 0 <-- line
1604  line& = all_pieces;
1605 
1606  // Q R . r . R k .
1607  // ^
1608  // blocked_piece
1609  Index blocked_piece(index_pre_begin);
1610  // The first piece north of index, if any.
1611  // Q R . r . R k .
1612  // ^
1613  // blocked_piece
1614  blocked_piece.next_bit_in(line());
1615  // Does this piece exist, and is it blocked by the piece on index?
1616  // If another white rook or queen was placed (or picked up) instead
1617  // of the black rook (r), then 'blocked_piece' would not really be
1618  // blocked (it can see through it). In that case the 'test' would
1619  // fail.
1620  if (__builtin_expect(blocked_piece != index_end&&
1621  blocked_rookmovers.test(blocked_piece), false))
1622  {
1623  // The piece is really blocked.
1624  //
1625  // Find all rooks and queens on the board of the same color
1626  // as this blocked piece (because they look through eachother).
1627  // Q R . r . R k .
1628  // 1 1 0 0 0 1 0 0 <-- rookmovers_of_same_color
1629  // In our example this is the same as blocked_rookmovers because
1630  // the removed piece 'r' is a rook mover too, of opposite color.
1631 
1632  Color blocked_piece_color(M_pieces[blocked_piece].color());
1633  Code rook_code(blocked_piece_color, rook);
1634  Code queen_code(blocked_piece_color, queen);
1635  BitBoard rookmovers_of_same_color(M_bitboards[rook_code] | M_bitboards[queen_code]);
1636 
1637  // Find the current blocker.
1638 
1639  BitBoard all_blockers(all_pieces);
1640  // All pieces that would block 'blocked_piece'.
1641  // Q R . r . R k .
1642  // 0 0 0 ? 0 0 1 0 <-- all_blockers
1643  // The question mark reflects the fact that we don't really
1644  // know if that rook is being removed or placed at this point.
1645  all_blockers.reset(rookmovers_of_same_color);
1646  // All squares below index.
1647  // Q R . r . R k .
1648  // 0 0 0 0 1 1 1 1 <-- opposite_line
1649  BitBoard opposite_line(south.from(index));
1650  // All pieces below index that would block 'blocked_piece' if index is empty.
1651  // Q R . r . R k .
1652  // 0 0 0 0 0 0 1 0 <-- all_blockers
1653  all_blockers& = opposite_line;
1654  // The first piece south of 'blocked_piece' that would block 'blocked_piece' if index is empty.
1655  // Q R . r . R k .
1656  // ^
1657  // current_blocker
1658  Index current_blocker(index_end);
1659  current_blocker.prev_bit_in(all_blockers());
1660 
1661  // Calculate all squares that become/are hidden from 'blocked_piece' by the piece in index.
1662 
1663  // All squares south of index.
1664  BitBoard blocked_squares(opposite_line);
1665  // Minus all squares south of current blocker.
1666  // Q R . r . R k .
1667  // 0 0 0 0 1 1 1 0 <-- blocked_squares
1668  if (current_blocker != index_pre_begin)
1669  blocked_squares.reset(south.from(current_blocker));
1670 
1671  // Is there anything to update?
1672  if (blocked_squares)
1673  {
1674  // The update of M_defended is delayed. Instead, collect all results (seperated by color).
1675  result[blocked_piece_color] |= blocked_squares;
1676 
1677  // If the current_blocker is a king of opposite color of blocked_piece,
1678  // then we are dealing with an attack on the king and M_king_battery_attack_count
1679  // might need to be updated too.
1680  Code king_code(blocked_piece_color.opposite(), king);
1681  bool king_attack = M_bitboards[king_code].test(blocked_squares);
1682  if (__builtin_expect(king_attack && blocked_squares.test(rookmovers_of_same_color), false))
1683  {
1684  if (add)
1685  ++M_king_battery_attack_count[blocked_piece_color];
1686  else
1687  --M_king_battery_attack_count[blocked_piece_color];
1688  }
1689 
1690  // Call call_back_battery for each additional piece that is blocked:
1691  // that is north of 'blocked_piece' but 'looks through' the piece on index.
1692  //
1693  // At this point we have:
1694  // Q R . r . R k .
1695  // 1 1 0 0 0 0 0 0 <-- line
1696  // ^
1697  // blocked_piece
1698  //
1699  // So, it will find the 'Q' next and call call_back_battery once.
1700 
1701  for (blocked_piece.next_bit_in(line());
1702  blocked_piece != index_end && rookmovers_of_same_color.test(blocked_piece);
1703  blocked_piece.next_bit_in(line()))
1704  {
1705  if (add)
1706  M_defended[blocked_piece_color].add(blocked_squares);
1707  else
1708  M_defended[blocked_piece_color].sub(blocked_squares);
1709  if (king_attack)
1710  {
1711  if (add)
1712  ++M_king_battery_attack_count[blocked_piece_color];
1713  else
1714  --M_king_battery_attack_count[blocked_piece_color];
1715  }
1716  }
1717  }
1718  }
1719 
1720  // Find the first piece below this piece.
1721  line = south.from(index);
1722  line& = all_pieces;
1723  blocked_piece = index_end;
1724  blocked_piece.prev_bit_in(line());
1725  if (__builtin_expect(blocked_piece != index_pre_begin && blocked_rookmovers.test(blocked_piece), false))
1726  {
1727  // The piece is blocked.
1728  Color blocked_piece_color(M_pieces[blocked_piece].color());
1729  Code rook_code(blocked_piece_color, rook);
1730  Code queen_code(blocked_piece_color, queen);
1731  BitBoard rookmovers_of_same_color(M_bitboards[rook_code] | M_bitboards[queen_code]);
1732  // Find the current blocker.
1733  BitBoard all_blockers(all_pieces);
1734  all_blockers.reset(rookmovers_of_same_color);
1735  BitBoard opposite_line(north.from(index));
1736  all_blockers& = opposite_line;
1737  Index current_blocker(index_pre_begin);
1738  current_blocker.next_bit_in(all_blockers());
1739  BitBoard blocked_squares(opposite_line);
1740  if (current_blocker != index_end)
1741  blocked_squares.reset(north.from(current_blocker));
1742 
1743  // Call it multiple times if there is a battery.
1744  if (blocked_squares)
1745  {
1746  result[blocked_piece_color] |= blocked_squares;
1747  Code king_code(blocked_piece_color.opposite(), king);
1748  bool king_attack = M_bitboards[king_code].test(blocked_squares);
1749  if (__builtin_expect(king_attack && blocked_squares.test(rookmovers_of_same_color), false))
1750  {
1751  if (add)
1752  ++M_king_battery_attack_count[blocked_piece_color];
1753  else
1754  --M_king_battery_attack_count[blocked_piece_color];
1755  }
1756  if (blocked_piece != index_begin)
1757  {
1758  for (blocked_piece.prev_bit_in(line()); blocked_piece != index_pre_begin && rookmovers_of_same_color.test(blocked_piece); blocked_piece.prev_bit_in(line()))
1759  {
1760  if (add)
1761  M_defended[blocked_piece_color].add(blocked_squares);
1762  else
1763  M_defended[blocked_piece_color].sub(blocked_squares);
1764  if (king_attack)
1765  {
1766  if (add)
1767  ++M_king_battery_attack_count[blocked_piece_color];
1768  else
1769  --M_king_battery_attack_count[blocked_piece_color];
1770  }
1771  if (blocked_piece == index_begin)
1772  break;
1773  }
1774  }
1775  }
1776  }
1777 
1778  // Find the first piece right of this piece.
1779  line = east.from(index);
1780  line& = all_pieces;
1781  blocked_piece = index_pre_begin;
1782  blocked_piece.next_bit_in(line());
1783  if (__builtin_expect(blocked_piece != index_end && blocked_rookmovers.test(blocked_piece), false))
1784  {
1785  // The piece is blocked.
1786  Color blocked_piece_color(M_pieces[blocked_piece].color());
1787  Code rook_code(blocked_piece_color, rook);
1788  Code queen_code(blocked_piece_color, queen);
1789  BitBoard rookmovers_of_same_color(M_bitboards[rook_code] | M_bitboards[queen_code]);
1790  // Find the current blocker.
1791  BitBoard all_blockers(all_pieces);
1792  all_blockers.reset(rookmovers_of_same_color);
1793  BitBoard opposite_line(west.from(index));
1794  all_blockers& = opposite_line;
1795  Index current_blocker(index_end);
1796  current_blocker.prev_bit_in(all_blockers());
1797  BitBoard blocked_squares(opposite_line);
1798  if (current_blocker != index_pre_begin)
1799  blocked_squares.reset(west.from(current_blocker));
1800  // Call it multiple times if there is a battery.
1801  if (blocked_squares)
1802  {
1803  result[blocked_piece_color] |= blocked_squares;
1804  Code king_code(blocked_piece_color.opposite(), king);
1805  bool king_attack = M_bitboards[king_code].test(blocked_squares);
1806  if (__builtin_expect(king_attack && blocked_squares.test(rookmovers_of_same_color), false))
1807  {
1808  if (add)
1809  ++M_king_battery_attack_count[blocked_piece_color];
1810  else
1811  --M_king_battery_attack_count[blocked_piece_color];
1812  }
1813  for (blocked_piece.next_bit_in(line()); blocked_piece != index_end && rookmovers_of_same_color.test(blocked_piece); blocked_piece.next_bit_in(line()))
1814  {
1815  if (add)
1816  M_defended[blocked_piece_color].add(blocked_squares);
1817  else
1818  M_defended[blocked_piece_color].sub(blocked_squares);
1819  if (king_attack)
1820  {
1821  if (add)
1822  ++M_king_battery_attack_count[blocked_piece_color];
1823  else
1824  --M_king_battery_attack_count[blocked_piece_color];
1825  }
1826  }
1827  }
1828  }
1829 
1830  // Find the first piece left of this piece.
1831  line = west.from(index);
1832  line& = all_pieces;
1833  blocked_piece = index_end;
1834  blocked_piece.prev_bit_in(line());
1835  if (__builtin_expect(blocked_piece != index_pre_begin && blocked_rookmovers.test(blocked_piece), false))
1836  {
1837  // The piece is blocked.
1838  Color blocked_piece_color(M_pieces[blocked_piece].color());
1839  Code rook_code(blocked_piece_color, rook);
1840  Code queen_code(blocked_piece_color, queen);
1841  BitBoard rookmovers_of_same_color(M_bitboards[rook_code] | M_bitboards[queen_code]);
1842  // Find the current blocker.
1843  BitBoard all_blockers(all_pieces);
1844  all_blockers.reset(rookmovers_of_same_color);
1845  BitBoard opposite_line(east.from(index));
1846  all_blockers& = opposite_line;
1847  Index current_blocker(index_pre_begin);
1848  current_blocker.next_bit_in(all_blockers());
1849  BitBoard blocked_squares(opposite_line);
1850  if (current_blocker != index_end)
1851  blocked_squares.reset(east.from(current_blocker));
1852  // Call it multiple times if there is a battery.
1853  if (blocked_squares)
1854  {
1855  result[blocked_piece_color] |= blocked_squares;
1856  Code king_code(blocked_piece_color.opposite(), king);
1857  bool king_attack = M_bitboards[king_code].test(blocked_squares);
1858  if (__builtin_expect(king_attack && blocked_squares.test(rookmovers_of_same_color), false))
1859  {
1860  if (add)
1861  ++M_king_battery_attack_count[blocked_piece_color];
1862  else
1863  --M_king_battery_attack_count[blocked_piece_color];
1864  }
1865  if (blocked_piece != index_begin)
1866  {
1867  for (blocked_piece.prev_bit_in(line()); blocked_piece != index_pre_begin && rookmovers_of_same_color.test(blocked_piece); blocked_piece.prev_bit_in(line()))
1868  {
1869  if (add)
1870  M_defended[blocked_piece_color].add(blocked_squares);
1871  else
1872  M_defended[blocked_piece_color].sub(blocked_squares);
1873  if (king_attack)
1874  {
1875  if (add)
1876  ++M_king_battery_attack_count[blocked_piece_color];
1877  else
1878  --M_king_battery_attack_count[blocked_piece_color];
1879  }
1880  if (blocked_piece == index_begin)
1881  break;
1882  }
1883  }
1884  }
1885  }
1886 
1887  // Find the first piece north-west of this piece.
1888  line = north_west.from(index);
1889  line& = all_pieces;
1890  blocked_piece = index_pre_begin;
1891  blocked_piece.next_bit_in(line());
1892  if (__builtin_expect(blocked_piece != index_end && blocked_bishopmovers.test(blocked_piece), false))
1893  {
1894  // The piece is blocked.
1895  Color blocked_piece_color(M_pieces[blocked_piece].color());
1896  Code bishop_code(blocked_piece_color, bishop);
1897  Code queen_code(blocked_piece_color, queen);
1898  BitBoard bishopmovers_of_same_color(M_bitboards[bishop_code] | M_bitboards[queen_code]);
1899  // Find the current blocker.
1900  BitBoard all_blockers(all_pieces);
1901  all_blockers.reset(bishopmovers_of_same_color);
1902  BitBoard opposite_line(south_east.from(index));
1903  all_blockers& = opposite_line;
1904  Index current_blocker(index_end);
1905  current_blocker.prev_bit_in(all_blockers());
1906  BitBoard blocked_squares(opposite_line);
1907  if (current_blocker != index_pre_begin)
1908  blocked_squares.reset(south_east.from(current_blocker));
1909  // Call it multiple times if there is a battery.
1910  if (blocked_squares)
1911  {
1912  if (__builtin_expect(code == black_pawn, false) && blocked_piece_color == black)
1913  blocked_squares.reset(index + south_east.offset);
1914  result[blocked_piece_color] |= blocked_squares;
1915  Code king_code(blocked_piece_color.opposite(), king);
1916  bool king_attack = M_bitboards[king_code].test(blocked_squares);
1917  if (__builtin_expect(king_attack && blocked_squares.test(bishopmovers_of_same_color), false))
1918  {
1919  if (add)
1920  ++M_king_battery_attack_count[blocked_piece_color];
1921  else
1922  --M_king_battery_attack_count[blocked_piece_color];
1923  }
1924  for (blocked_piece.next_bit_in(line()); blocked_piece != index_end && bishopmovers_of_same_color.test(blocked_piece); blocked_piece.next_bit_in(line()))
1925  {
1926  if (add)
1927  M_defended[blocked_piece_color].add(blocked_squares);
1928  else
1929  M_defended[blocked_piece_color].sub(blocked_squares);
1930  if (king_attack)
1931  {
1932  if (add)
1933  ++M_king_battery_attack_count[blocked_piece_color];
1934  else
1935  --M_king_battery_attack_count[blocked_piece_color];
1936  }
1937  }
1938  }
1939  }
1940 
1941  // Find the first piece south-east this piece.
1942  line = south_east.from(index);
1943  line& = all_pieces;
1944  blocked_piece = index_end;
1945  blocked_piece.prev_bit_in(line());
1946  if (__builtin_expect(blocked_piece != index_pre_begin && blocked_bishopmovers.test(blocked_piece), false))
1947  {
1948  // The piece is blocked.
1949  Color blocked_piece_color(M_pieces[blocked_piece].color());
1950  Code bishop_code(blocked_piece_color, bishop);
1951  Code queen_code(blocked_piece_color, queen);
1952  BitBoard bishopmovers_of_same_color(M_bitboards[bishop_code] | M_bitboards[queen_code]);
1953  // Find the current blocker.
1954  BitBoard all_blockers(all_pieces);
1955  all_blockers.reset(bishopmovers_of_same_color);
1956  BitBoard opposite_line(north_west.from(index));
1957  all_blockers& = opposite_line;
1958  Index current_blocker(index_pre_begin);
1959  current_blocker.next_bit_in(all_blockers());
1960  BitBoard blocked_squares(opposite_line);
1961  if (current_blocker != index_end)
1962  blocked_squares.reset(north_west.from(current_blocker));
1963  // Call it multiple times if there is a battery.
1964  if (blocked_squares)
1965  {
1966  if (__builtin_expect(code == white_pawn, false) && blocked_piece_color == white)
1967  blocked_squares.reset(index + north_west.offset);
1968  result[blocked_piece_color] |= blocked_squares;
1969  Code king_code(blocked_piece_color.opposite(), king);
1970  bool king_attack = M_bitboards[king_code].test(blocked_squares);
1971  if (__builtin_expect(king_attack && blocked_squares.test(bishopmovers_of_same_color), false))
1972  {
1973  if (add)
1974  ++M_king_battery_attack_count[blocked_piece_color];
1975  else
1976  --M_king_battery_attack_count[blocked_piece_color];
1977  }
1978  if (blocked_piece != index_begin)
1979  {
1980  for (blocked_piece.prev_bit_in(line()); blocked_piece != index_pre_begin && bishopmovers_of_same_color.test(blocked_piece); blocked_piece.prev_bit_in(line()))
1981  {
1982  if (add)
1983  M_defended[blocked_piece_color].add(blocked_squares);
1984  else
1985  M_defended[blocked_piece_color].sub(blocked_squares);
1986  if (king_attack)
1987  {
1988  if (add)
1989  ++M_king_battery_attack_count[blocked_piece_color];
1990  else
1991  --M_king_battery_attack_count[blocked_piece_color];
1992  }
1993  if (blocked_piece == index_begin)
1994  break;
1995  }
1996  }
1997  }
1998  }
1999 
2000  // Find the first piece north-east of this piece.
2001  line = north_east.from(index);
2002  line& = all_pieces;
2003  blocked_piece = index_pre_begin;
2004  blocked_piece.next_bit_in(line());
2005  if (__builtin_expect(blocked_piece != index_end && blocked_bishopmovers.test(blocked_piece), false))
2006  {
2007  // The piece is blocked.
2008  Color blocked_piece_color(M_pieces[blocked_piece].color());
2009  Code bishop_code(blocked_piece_color, bishop);
2010  Code queen_code(blocked_piece_color, queen);
2011  BitBoard bishopmovers_of_same_color(M_bitboards[bishop_code] | M_bitboards[queen_code]);
2012  // Find the current blocker.
2013  BitBoard all_blockers(all_pieces);
2014  all_blockers.reset(bishopmovers_of_same_color);
2015  BitBoard opposite_line(south_west.from(index));
2016  all_blockers& = opposite_line;
2017  Index current_blocker(index_end);
2018  current_blocker.prev_bit_in(all_blockers());
2019  BitBoard blocked_squares(opposite_line);
2020  if (current_blocker != index_pre_begin)
2021  blocked_squares.reset(south_west.from(current_blocker));
2022  // Call it multiple times if there is a battery.
2023  if (blocked_squares)
2024  {
2025  if (__builtin_expect(code == black_pawn, false) && blocked_piece_color == black)
2026  blocked_squares.reset(index + south_west.offset);
2027  result[blocked_piece_color] |= blocked_squares;
2028  Code king_code(blocked_piece_color.opposite(), king);
2029  bool king_attack = M_bitboards[king_code].test(blocked_squares);
2030  if (__builtin_expect(king_attack && blocked_squares.test(bishopmovers_of_same_color), false))
2031  {
2032  if (add)
2033  ++M_king_battery_attack_count[blocked_piece_color];
2034  else
2035  --M_king_battery_attack_count[blocked_piece_color];
2036  }
2037  for (blocked_piece.next_bit_in(line()); blocked_piece != index_end && bishopmovers_of_same_color.test(blocked_piece); blocked_piece.next_bit_in(line()))
2038  {
2039  if (add)
2040  M_defended[blocked_piece_color].add(blocked_squares);
2041  else
2042  M_defended[blocked_piece_color].sub(blocked_squares);
2043  if (king_attack)
2044  {
2045  if (add)
2046  ++M_king_battery_attack_count[blocked_piece_color];
2047  else
2048  --M_king_battery_attack_count[blocked_piece_color];
2049  }
2050  }
2051  }
2052  }
2053 
2054  // Find the first piece south-west of this piece.
2055  line = south_west.from(index);
2056  line& = all_pieces;
2057  blocked_piece = index_end;
2058  blocked_piece.prev_bit_in(line());
2059  if (__builtin_expect(blocked_piece != index_pre_begin && blocked_bishopmovers.test(blocked_piece), false))
2060  {
2061  // The piece is blocked.
2062  Color blocked_piece_color(M_pieces[blocked_piece].color());
2063  Code bishop_code(blocked_piece_color, bishop);
2064  Code queen_code(blocked_piece_color, queen);
2065  BitBoard bishopmovers_of_same_color(M_bitboards[bishop_code] | M_bitboards[queen_code]);
2066  // Find the current blocker.
2067  BitBoard all_blockers(all_pieces);
2068  all_blockers.reset(bishopmovers_of_same_color);
2069  BitBoard opposite_line(north_east.from(index));
2070  all_blockers& = opposite_line;
2071  Index current_blocker(index_pre_begin);
2072  current_blocker.next_bit_in(all_blockers());
2073  BitBoard blocked_squares(opposite_line);
2074  if (current_blocker != index_end)
2075  blocked_squares.reset(north_east.from(current_blocker));
2076  // Call it multiple times if there is a battery.
2077  if (blocked_squares)
2078  {
2079  if (__builtin_expect(code == white_pawn, false) && blocked_piece_color == white)
2080  blocked_squares.reset(index + north_east.offset);
2081  result[blocked_piece_color] |= blocked_squares;
2082  Code king_code(blocked_piece_color.opposite(), king);
2083  bool king_attack = M_bitboards[king_code].test(blocked_squares);
2084  if (__builtin_expect(king_attack && blocked_squares.test(bishopmovers_of_same_color), false))
2085  {
2086  if (add)
2087  ++M_king_battery_attack_count[blocked_piece_color];
2088  else
2089  --M_king_battery_attack_count[blocked_piece_color];
2090  }
2091  if (blocked_piece != index_begin)
2092  {
2093  for (blocked_piece.prev_bit_in(line()); blocked_piece != index_pre_begin && bishopmovers_of_same_color.test(blocked_piece); blocked_piece.prev_bit_in(line()))
2094  {
2095  if (add)
2096  M_defended[blocked_piece_color].add(blocked_squares);
2097  else
2098  M_defended[blocked_piece_color].sub(blocked_squares);
2099  if (king_attack)
2100  {
2101  if (add)
2102  ++M_king_battery_attack_count[blocked_piece_color];
2103  else
2104  --M_king_battery_attack_count[blocked_piece_color];
2105  }
2106  if (blocked_piece == index_begin)
2107  break;
2108  }
2109  }
2110  }
2111  }
2112 
2113  // Update M_defended with the collected results.
2114  if (BitBoard black_result = result[black])
2115  {
2116  if (add)
2117  M_defended[black].add(black_result);
2118  else
2119  M_defended[black].sub(black_result);
2120  }
2121  if (BitBoard white_result = result[white])
2122  {
2123  if (add)
2124  M_defended[white].add(white_result);
2125  else
2126  M_defended[white].sub(white_result);
2127  }
2128 }
2129 
2130 BitBoard ChessPosition::reachables(Index const& index, bool attacked_squares) const
2131 {
2132  BitBoard all_pieces(M_bitboards[white] | M_bitboards[black]); // A bitboard with bits set on every square where there is any piece.
2133  Piece piece(M_pieces[index]); // The piece that we want to find the reachables for.
2134  Color color = piece.color(); // The color of the piece.
2135  mask_t pos = index2mask(index); // The current position of the piece.
2136  switch(piece.type()())
2137  {
2138  case nothing_bits: // This should never be called, but return an empty bitboard anyway.
2139  {
2140  BitBoard result;
2141  result.reset();
2142  return result;
2143  }
2144  case pawn_bits:
2145  {
2146  if (attacked_squares) // Show attacked squares instead of move candidates?
2147  {
2148  BitBoard result((color == white) ? (pos << 7) | (pos << 9) : (pos >> 9) | (pos >> 7));
2149  result.reset(M_bitboards[color]);
2150  int col = index.col();
2151  if (__builtin_expect(col == 0, false))
2152  result.reset(file_h);
2153  else if (__builtin_expect(col == 7, false))
2154  result.reset(file_a);
2155  return result;
2156  }
2157  return candidates(index); // The candidates are the reachables in the case of pawns.
2158  }
2159  case rook_bits:
2160  {
2161  // Find reachable squares above the rook.
2162  mask_t block = all_pieces();
2163  mask_t probe = pos;
2164  mask_t reachables = 0;
2165  do
2166  {
2167  move(probe, up);
2168  reachables |= probe;
2169  }
2170  while((block & probe) != probe);
2171 
2172  // Find reachable squares below the rook.
2173  probe = pos;
2174  do
2175  {
2176  move(probe, down);
2177  reachables |= probe;
2178  }
2179  while((block & probe) != probe);
2180 
2181  // Result so far.
2182  BitBoard result(reachables);
2183 
2184  // Find reachable squares left of the rook.
2185  block |= file_h.M_bitmask;
2186  probe = pos;
2187  do
2188  {
2189  move(probe, left);
2190  reachables |= probe;
2191  }
2192  while((block & probe) != probe);
2193  reachables& = ~file_h.M_bitmask;
2194 
2195  // Update result.
2196  result |= reachables;
2197 
2198  // Find reachable squares right of the rook.
2199  block = all_pieces() | file_a.M_bitmask;
2200  probe = pos;
2201  do
2202  {
2203  move(probe, right);
2204  reachables |= probe;
2205  }
2206  while((block & probe) != probe);
2207  reachables& = ~file_a.M_bitmask;
2208 
2209  result |= reachables;
2210  result.reset(M_bitboards[color]); // We cannot take our own pieces.
2211  return result;
2212  }
2213  case knight_bits:
2214  {
2215  BitBoard result(candidates_table[candidates_table_offset(knight) + index()]);
2216  result.reset(M_bitboards[color]);
2217  return result;
2218  }
2219  case bishop_bits:
2220  {
2221  // Find reachable squares left below the bishop.
2222  mask_t block = all_pieces() | file_h.M_bitmask;
2223  mask_t probe = pos;
2224  mask_t reachables = 0;
2225  do
2226  {
2227  move(probe, down_left);
2228  reachables |= probe;
2229  }
2230  while((block & probe) != probe);
2231 
2232  // Find reachable squares left above the bishop.
2233  probe = pos;
2234  do
2235  {
2236  move(probe, up_left);
2237  reachables |= probe;
2238  }
2239  while((block & probe) != probe);
2240  reachables& = ~file_h.M_bitmask;
2241 
2242  // Result so far.
2243  BitBoard result(reachables);
2244 
2245  // Find reachable squares right above the bishop;
2246  block = all_pieces() | file_a.M_bitmask;
2247  probe = pos;
2248  do
2249  {
2250  move(probe, up_right);
2251  reachables |= probe;
2252  }
2253  while((block & probe) != probe);
2254 
2255  // Find reachable squares right below the bishop;
2256  probe = pos;
2257  do
2258  {
2259  move(probe, down_right);
2260  reachables |= probe;
2261  }
2262  while((block & probe) != probe);
2263  reachables& = ~file_a.M_bitmask;
2264 
2265  result |= reachables;
2266  result.reset(M_bitboards[color]);
2267  return result;
2268  }
2269  case queen_bits:
2270  {
2271  // Find reachable squares above the queen.
2272  mask_t block = all_pieces();
2273  mask_t probe = pos;
2274  mask_t reachables = 0;
2275  do
2276  {
2277  move(probe, up);
2278  reachables |= probe;
2279  }
2280  while((block & probe) != probe);
2281 
2282  // Find reachable squares below the queen.
2283  probe = pos;
2284  do
2285  {
2286  move(probe, down);
2287  reachables |= probe;
2288  }
2289  while((block & probe) != probe);
2290 
2291  // Result so far.
2292  BitBoard result(reachables);
2293 
2294  // Find reachable squares left of the queen.
2295  block |= file_h.M_bitmask;
2296  probe = pos;
2297  do
2298  {
2299  move(probe, left);
2300  reachables |= probe;
2301  }
2302  while((block & probe) != probe);
2303 
2304  // Find reachable squares left below the queen.
2305  probe = pos;
2306  do
2307  {
2308  move(probe, down_left);
2309  reachables |= probe;
2310  }
2311  while((block & probe) != probe);
2312 
2313  // Find reachable squares left above the bishop.
2314  probe = pos;
2315  do
2316  {
2317  move(probe, up_left);
2318  reachables |= probe;
2319  }
2320  while((block & probe) != probe);
2321  reachables& = ~file_h.M_bitmask;
2322 
2323  // Update result.
2324  result |= reachables;
2325 
2326  // Find reachable squares right of the queen.
2327  block = all_pieces() | file_a.M_bitmask;
2328  probe = pos;
2329  do
2330  {
2331  move(probe, right);
2332  reachables |= probe;
2333  }
2334  while((block & probe) != probe);
2335 
2336  // Find reachable squares right above the queen;
2337  probe = pos;
2338  do
2339  {
2340  move(probe, up_right);
2341  reachables |= probe;
2342  }
2343  while((block & probe) != probe);
2344 
2345  // Find reachable squares right below the queen;
2346  probe = pos;
2347  do
2348  {
2349  move(probe, down_right);
2350  reachables |= probe;
2351  }
2352  while((block & probe) != probe);
2353  reachables& = ~file_a.M_bitmask;
2354 
2355  result |= reachables;
2356  result.reset(M_bitboards[color]);
2357  return result;
2358  }
2359  case king_bits:
2360  {
2361  BitBoard result(candidates_table[candidates_table_offset(king) + index()]);
2362  result.reset(M_bitboards[color]);
2363  if (attacked_squares || !M_castle_flags.can_castle(color))
2364  return result;
2365  BitBoard long_castle_squares(0), short_castle_squares(0);
2366  bool can_castle_long = false, can_castle_short = false;
2367  if (M_castle_flags.can_castle_short(color))
2368  {
2369  short_castle_squares = BitBoard((color == white) ? f1|g1 : f8|g8);
2370  if (!(all_pieces & short_castle_squares))
2371  {
2372  can_castle_short = true;
2373  short_castle_squares.reset(f1|f8);
2374  }
2375  }
2376  if (M_castle_flags.can_castle_long(color))
2377  {
2378  long_castle_squares = BitBoard((color == white) ? b1|c1|d1 : b8|c8|d8);
2379  if (!(all_pieces & long_castle_squares))
2380  {
2381  can_castle_long = true;
2382  long_castle_squares.reset(b1|b8|d1|d8);
2383  }
2384  }
2385  if (can_castle_short || can_castle_long)
2386  {
2387  // Check if the king or any of the squares involved in the castling is in check.
2388  BitBoard attacked_squares;
2389  attacked_squares.reset();
2390  for (PieceIterator iter = piece_begin(color.opposite()); iter != piece_end(); ++iter)
2391  attacked_squares |= reachables(iter.index(), true);
2392  if (can_castle_short && !(attacked_squares & ((color == white) ? (e1|f1|g1) : (e8|f8|g8))))
2393  result |= short_castle_squares;
2394  if (can_castle_long && !(attacked_squares & ((color == white) ? (c1|d1|e1) : (c8|d8|e8))))
2395  result |= long_castle_squares;
2396  }
2397  return result;
2398  }
2399  }
2400  return BitBoard(); // Never reached.
2401 }
2402 
2404 {
2405  Code code(M_pieces[index].code());
2406  Color color(code.color());
2407 
2408  BitBoard reachables(this->reachables(index));
2409 
2410  // If it is NOT this colors turn then it is not in check (that would be impossible in a legal position).
2411  // Are we in check?
2412  if (__builtin_expect(color == M_to_move && M_castle_flags.in_check(M_to_move), false))
2413  {
2414  bool is_king = code.is_a(king);
2415  // If we are in double check, then we can only move with the king.
2416  if (__builtin_expect(M_double_check && !is_king, false))
2417  return BitBoard((mask_t)0);
2418  // We can only move a non-king if we can take the piece that
2419  // gives check, or place something in front of it.
2420  BitBoard attacker_squares;
2421  attacker_squares.reset();
2422  Code king_code(color, king);
2423  BitBoard king_pos(M_bitboards[king_code]);
2424  Index king_index(mask2index(king_pos()));
2425  if (__builtin_expect(!M_double_check && !is_king, true))
2426  {
2427  if (color == black)
2428  {
2429  BitBoard queenside_pawn(king_pos() >> 9);
2430  BitBoard kingside_pawn(king_pos() >> 7);
2431  queenside_pawn.reset(file_h);
2432  kingside_pawn.reset(file_a);
2433  attacker_squares = (queenside_pawn | kingside_pawn) & M_bitboards[white_pawn];
2434  attacker_squares |= candidates_table[candidates_table_offset(knight) + king_index()] & M_bitboards[white_knight];
2435  }
2436  else
2437  {
2438  BitBoard queenside_pawn(king_pos() << 7);
2439  BitBoard kingside_pawn(king_pos() << 9);
2440  queenside_pawn.reset(file_h);
2441  kingside_pawn.reset(file_a);
2442  attacker_squares = (queenside_pawn | kingside_pawn) & M_bitboards[black_pawn];
2443  attacker_squares |= candidates_table[candidates_table_offset(knight) + king_index()] & M_bitboards[black_knight];
2444  }
2445  }
2446  // If attacker_squares were found then we're not in double check and we already found a check by a pawn or knight,
2447  // so there is no need to look for checks by sliding pieces.
2448  if (!attacker_squares)
2449  {
2450  BitBoard const all_pieces(M_bitboards[white] | M_bitboards[black]);
2451  Color opposite_color(color.opposite());
2452  Code rook_code(opposite_color, rook);
2453  Code queen_code(opposite_color, queen);
2454  BitBoard rookmovers(candidates_table[candidates_table_offset(rook) + king_index()] & (M_bitboards[rook_code] | M_bitboards[queen_code]));
2455  for (PieceIterator piece_iter(this, rookmovers); piece_iter != piece_end(); ++piece_iter)
2456  {
2457  Direction const& direction(direction_from_to(king_index, piece_iter.index()));
2458  BitBoard line(squares_from_to(piece_iter.index(), king_index));
2459  if ((line & all_pieces) == BitBoard(piece_iter.index()))
2460  {
2461  // We found the rookmover that gives check.
2462  if (is_king)
2463  {
2464  // If this wraps around from a-file to h-file or visa versa then that is not a problem: it will be far away from the king.
2465  Index one_step_away_from_attacker(king_index - direction);
2466  // However, we can't rely on reset() to work for indexes outside the board.
2467  if (one_step_away_from_attacker() < 64)
2468  reachables.reset(one_step_away_from_attacker);
2469  }
2470  else
2471  attacker_squares |= line;
2472  break;
2473  }
2474  }
2475  if (M_double_check || !attacker_squares)
2476  {
2477  Code bishop_code(opposite_color, bishop);
2478  BitBoard bishopmovers(candidates_table[candidates_table_offset(bishop) + king_index()] & (M_bitboards[bishop_code] | M_bitboards[queen_code]));
2479  for (PieceIterator piece_iter(this, bishopmovers); piece_iter != piece_end(); ++piece_iter)
2480  {
2481  Direction const& direction(direction_from_to(king_index, piece_iter.index()));
2482  BitBoard line(squares_from_to(piece_iter.index(), king_index));
2483  if ((line & all_pieces) == piece_iter.index())
2484  {
2485  // We found the bishopmover that gives check.
2486  if (is_king)
2487  {
2488  Index one_step_away_from_attacker(king_index - direction);
2489  if (one_step_away_from_attacker() < 64)
2490  reachables.reset(one_step_away_from_attacker);
2491  }
2492  else
2493  attacker_squares |= line;
2494  break;
2495  }
2496  }
2497  }
2498  }
2499  if (!is_king)
2500  {
2501  // The only possible move is taking the attacker, or placing something in front of it.
2502  reachables& = attacker_squares;
2503  }
2504  }
2505  BitBoard pinning(M_pinning[color]);
2506  if (__builtin_expect(pinning.test(index), false))
2507  {
2508  // Remove squares that would result in a check.
2509  if (code.is_a(pawn))
2510  reachables& = pinning;
2511  else
2512  {
2513  Index king_index(index_of_king(color));
2514  Direction direction(direction_from_to(king_index, index));
2515  BitBoard line(direction.from(king_index));
2516  reachables& = line;
2517  }
2518  }
2519  if (__builtin_expect(M_en_passant.exists() && M_en_passant.pinned() && code.is_a(pawn), false))
2520  reachables.reset(M_en_passant.index()); // Taking en passant is prohibitted.
2521  if (__builtin_expect(code.is_a(king), false))
2522  reachables.reset(M_defended[color.opposite()].any()); // The king can't go a square where it puts itself in check.
2523 
2524  return reachables;
2525 }
2526 
2527 bool ChessPosition::legal(Move const& move) const
2528 {
2529  Index from(move.from());
2530  Index to(move.to());
2531  // Lets play on the board.
2532  if (to() > 63 || from() > 63)
2533  return false;
2534  BitBoard from_pos(from);
2535  BitBoard to_pos(to);
2536  Piece const& piece(M_pieces[from]);
2537  // Only touch your own pieces.
2538  if (piece.code().is_nothing() || piece.color() != M_to_move)
2539  return false;
2540  bool is_pawn_promotion = piece.code().is_a(pawn) && (to.row() == 0 || to.row() == 7);
2541  // Only allow promotion of pawns.
2542  if (is_pawn_promotion)
2543  {
2544  Type promotion_type(move.promotion_type());
2545  if (promotion_type != rook && promotion_type != knight && promotion_type != bishop && promotion_type != queen)
2546  return false;
2547  }
2548  else if (move.promotion_type() != nothing)
2549  return false;
2550  // Get all legal squares to move to for this piece and test if we try to go one of them.
2551  return moves(from).test(to_pos);
2552 }
2553 
2554 bool ChessPosition::execute(Move const& move)
2555 {
2556  BitBoard from_pos(move.from());
2557  BitBoard to_pos(move.to());
2558  BitBoard all_pieces(M_bitboards[black] | M_bitboards[white]);
2559  bool pawn_move = (from_pos & M_bitboards[Code(M_to_move, pawn)]);
2560  bool pawn_advance_or_capture = pawn_move | !!(to_pos & all_pieces);
2561  // Handle en passant.
2562  if (__builtin_expect(M_en_passant.exists(), false))
2563  {
2564  if (pawn_move && M_en_passant.index() == move.to())
2565  {
2566  // A pawn was taken en passant, remove it.
2567  // This resets M_en_passant.
2568  place(Code(), M_en_passant.pawn_index());
2569  }
2570  else
2571  {
2572  // Clear the right to take en passant.
2573  clear_en_passant();
2574  }
2575  }
2576  // Set en passant flags, if applicable.
2577  if (pawn_move)
2578  {
2579  uint8_t offset = move.to()() - move.from()(); // -16, -9, -8, -7, 7, 8, 9 or 16.
2580  bool pawn_advanced_two_squares = !(offset & 0xf); // Only -16 and 16 have the last four bits clear.
2581  if (pawn_advanced_two_squares)
2582  {
2583  // Mark that we can take this pawn en passant.
2584  // Toggling the third bit finds the passed square: row 3 becomes row 2, and row 4 becomes row 5.
2585  IndexData passed_square = { static_cast<uint8_t>(move.to()() ^ 8) };
2586  set_en_passant(passed_square);
2587  // set_en_passant toggles the move, toggle it back because we'll toggle it again below.
2588  M_to_move.toggle();
2589  }
2590  }
2591 
2592  // FIXME. For now, use place() to execute the move.
2593  CastleFlags castle_flags(M_castle_flags);
2594  Piece piece(M_pieces[move.from()]);
2595  place(Code(), move.from()); // 160 ns.
2596  if (move.is_promotion())
2597  place(Code(M_to_move, move.promotion_type()), move.to());
2598  else
2599  {
2600  place(piece.code(), move.to()); // 110 ns.
2601  // Is this a castling?
2602  uint8_t col_diff = move.to().col() - move.from().col();
2603  if (__builtin_expect(piece.code().is_a(king), false) && __builtin_expect(col_diff && !(col_diff & 1), false))
2604  {
2605  IndexData rook_from = { static_cast<uint8_t>(move.from()() - 4 + 7 * (2 + move.to()() - move.from()()) / 4) };
2606  IndexData rook_to = { static_cast<uint8_t>(move.from()() + (move.to()() - move.from()()) / 2) };
2607  place(Code(), rook_from);
2608  place(Code(M_to_move, rook), rook_to);
2609  }
2610  }
2611 
2612  // Change whose turn it is.
2613  M_to_move.toggle();
2614 
2615  // FIXME. Correct M_castle_flags again.
2616  bool in_check = M_castle_flags.in_check(M_to_move);
2617  M_castle_flags = castle_flags;
2618  M_castle_flags.set_check(M_to_move, in_check);
2619  M_castle_flags.piece_moved_from(piece, move.from());
2620 
2621  // Cache whether or not we gave a double check.
2622  M_double_check = M_castle_flags.in_check(M_to_move) ? double_check(M_to_move) : false;
2623  // Increment the counters and return whether or not it's a draw by the 50 move rule.
2624  return increment_counters(pawn_advance_or_capture);
2625 }
2626 
2627 BitBoardData ChessPosition::candidates_table[5 * 64] = {
2628  // Knight
2629  { CW_MASK_T_CONST(0x0000000000020400)}, { CW_MASK_T_CONST(0x0000000000050800)}, { CW_MASK_T_CONST(0x00000000000a1100)}, { CW_MASK_T_CONST(0x0000000000142200)},
2630  { CW_MASK_T_CONST(0x0000000000284400)}, { CW_MASK_T_CONST(0x0000000000508800)}, { CW_MASK_T_CONST(0x0000000000a01000)}, { CW_MASK_T_CONST(0x0000000000402000)},
2631  { CW_MASK_T_CONST(0x0000000002040004)}, { CW_MASK_T_CONST(0x0000000005080008)}, { CW_MASK_T_CONST(0x000000000a110011)}, { CW_MASK_T_CONST(0x0000000014220022)},
2632  { CW_MASK_T_CONST(0x0000000028440044)}, { CW_MASK_T_CONST(0x0000000050880088)}, { CW_MASK_T_CONST(0x00000000a0100010)}, { CW_MASK_T_CONST(0x0000000040200020)},
2633  { CW_MASK_T_CONST(0x0000000204000402)}, { CW_MASK_T_CONST(0x0000000508000805)}, { CW_MASK_T_CONST(0x0000000a1100110a)}, { CW_MASK_T_CONST(0x0000001422002214)},
2634  { CW_MASK_T_CONST(0x0000002844004428)}, { CW_MASK_T_CONST(0x0000005088008850)}, { CW_MASK_T_CONST(0x000000a0100010a0)}, { CW_MASK_T_CONST(0x0000004020002040)},
2635  { CW_MASK_T_CONST(0x0000020400040200)}, { CW_MASK_T_CONST(0x0000050800080500)}, { CW_MASK_T_CONST(0x00000a1100110a00)}, { CW_MASK_T_CONST(0x0000142200221400)},
2636  { CW_MASK_T_CONST(0x0000284400442800)}, { CW_MASK_T_CONST(0x0000508800885000)}, { CW_MASK_T_CONST(0x0000a0100010a000)}, { CW_MASK_T_CONST(0x0000402000204000)},
2637  { CW_MASK_T_CONST(0x0002040004020000)}, { CW_MASK_T_CONST(0x0005080008050000)}, { CW_MASK_T_CONST(0x000a1100110a0000)}, { CW_MASK_T_CONST(0x0014220022140000)},
2638  { CW_MASK_T_CONST(0x0028440044280000)}, { CW_MASK_T_CONST(0x0050880088500000)}, { CW_MASK_T_CONST(0x00a0100010a00000)}, { CW_MASK_T_CONST(0x0040200020400000)},
2639  { CW_MASK_T_CONST(0x0204000402000000)}, { CW_MASK_T_CONST(0x0508000805000000)}, { CW_MASK_T_CONST(0x0a1100110a000000)}, { CW_MASK_T_CONST(0x1422002214000000)},
2640  { CW_MASK_T_CONST(0x2844004428000000)}, { CW_MASK_T_CONST(0x5088008850000000)}, { CW_MASK_T_CONST(0xa0100010a0000000)}, { CW_MASK_T_CONST(0x4020002040000000)},
2641  { CW_MASK_T_CONST(0x0400040200000000)}, { CW_MASK_T_CONST(0x0800080500000000)}, { CW_MASK_T_CONST(0x1100110a00000000)}, { CW_MASK_T_CONST(0x2200221400000000)},
2642  { CW_MASK_T_CONST(0x4400442800000000)}, { CW_MASK_T_CONST(0x8800885000000000)}, { CW_MASK_T_CONST(0x100010a000000000)}, { CW_MASK_T_CONST(0x2000204000000000)},
2643  { CW_MASK_T_CONST(0x0004020000000000)}, { CW_MASK_T_CONST(0x0008050000000000)}, { CW_MASK_T_CONST(0x00110a0000000000)}, { CW_MASK_T_CONST(0x0022140000000000)},
2644  { CW_MASK_T_CONST(0x0044280000000000)}, { CW_MASK_T_CONST(0x0088500000000000)}, { CW_MASK_T_CONST(0x0010a00000000000)}, { CW_MASK_T_CONST(0x0020400000000000)},
2645  // King
2646  { CW_MASK_T_CONST(0x0000000000000302)}, { CW_MASK_T_CONST(0x0000000000000705)}, { CW_MASK_T_CONST(0x0000000000000e0a)}, { CW_MASK_T_CONST(0x0000000000001c14)},
2647  { CW_MASK_T_CONST(0x0000000000003828)}, { CW_MASK_T_CONST(0x0000000000007050)}, { CW_MASK_T_CONST(0x000000000000e0a0)}, { CW_MASK_T_CONST(0x000000000000c040)},
2648  { CW_MASK_T_CONST(0x0000000000030203)}, { CW_MASK_T_CONST(0x0000000000070507)}, { CW_MASK_T_CONST(0x00000000000e0a0e)}, { CW_MASK_T_CONST(0x00000000001c141c)},
2649  { CW_MASK_T_CONST(0x0000000000382838)}, { CW_MASK_T_CONST(0x0000000000705070)}, { CW_MASK_T_CONST(0x0000000000e0a0e0)}, { CW_MASK_T_CONST(0x0000000000c040c0)},
2650  { CW_MASK_T_CONST(0x0000000003020300)}, { CW_MASK_T_CONST(0x0000000007050700)}, { CW_MASK_T_CONST(0x000000000e0a0e00)}, { CW_MASK_T_CONST(0x000000001c141c00)},
2651  { CW_MASK_T_CONST(0x0000000038283800)}, { CW_MASK_T_CONST(0x0000000070507000)}, { CW_MASK_T_CONST(0x00000000e0a0e000)}, { CW_MASK_T_CONST(0x00000000c040c000)},
2652  { CW_MASK_T_CONST(0x0000000302030000)}, { CW_MASK_T_CONST(0x0000000705070000)}, { CW_MASK_T_CONST(0x0000000e0a0e0000)}, { CW_MASK_T_CONST(0x0000001c141c0000)},
2653  { CW_MASK_T_CONST(0x0000003828380000)}, { CW_MASK_T_CONST(0x0000007050700000)}, { CW_MASK_T_CONST(0x000000e0a0e00000)}, { CW_MASK_T_CONST(0x000000c040c00000)},
2654  { CW_MASK_T_CONST(0x0000030203000000)}, { CW_MASK_T_CONST(0x0000070507000000)}, { CW_MASK_T_CONST(0x00000e0a0e000000)}, { CW_MASK_T_CONST(0x00001c141c000000)},
2655  { CW_MASK_T_CONST(0x0000382838000000)}, { CW_MASK_T_CONST(0x0000705070000000)}, { CW_MASK_T_CONST(0x0000e0a0e0000000)}, { CW_MASK_T_CONST(0x0000c040c0000000)},
2656  { CW_MASK_T_CONST(0x0003020300000000)}, { CW_MASK_T_CONST(0x0007050700000000)}, { CW_MASK_T_CONST(0x000e0a0e00000000)}, { CW_MASK_T_CONST(0x001c141c00000000)},
2657  { CW_MASK_T_CONST(0x0038283800000000)}, { CW_MASK_T_CONST(0x0070507000000000)}, { CW_MASK_T_CONST(0x00e0a0e000000000)}, { CW_MASK_T_CONST(0x00c040c000000000)},
2658  { CW_MASK_T_CONST(0x0302030000000000)}, { CW_MASK_T_CONST(0x0705070000000000)}, { CW_MASK_T_CONST(0x0e0a0e0000000000)}, { CW_MASK_T_CONST(0x1c141c0000000000)},
2659  { CW_MASK_T_CONST(0x3828380000000000)}, { CW_MASK_T_CONST(0x7050700000000000)}, { CW_MASK_T_CONST(0xe0a0e00000000000)}, { CW_MASK_T_CONST(0xc040c00000000000)},
2660  { CW_MASK_T_CONST(0x0203000000000000)}, { CW_MASK_T_CONST(0x0507000000000000)}, { CW_MASK_T_CONST(0x0a0e000000000000)}, { CW_MASK_T_CONST(0x141c000000000000)},
2661  { CW_MASK_T_CONST(0x2838000000000000)}, { CW_MASK_T_CONST(0x5070000000000000)}, { CW_MASK_T_CONST(0xa0e0000000000000)}, { CW_MASK_T_CONST(0x40c0000000000000)},
2662  // Bishop
2663  { CW_MASK_T_CONST(0x8040201008040200)}, { CW_MASK_T_CONST(0x0080402010080500)}, { CW_MASK_T_CONST(0x0000804020110a00)}, { CW_MASK_T_CONST(0x0000008041221400)},
2664  { CW_MASK_T_CONST(0x0000000182442800)}, { CW_MASK_T_CONST(0x0000010204885000)}, { CW_MASK_T_CONST(0x000102040810a000)}, { CW_MASK_T_CONST(0x0102040810204000)},
2665  { CW_MASK_T_CONST(0x4020100804020002)}, { CW_MASK_T_CONST(0x8040201008050005)}, { CW_MASK_T_CONST(0x00804020110a000a)}, { CW_MASK_T_CONST(0x0000804122140014)},
2666  { CW_MASK_T_CONST(0x0000018244280028)}, { CW_MASK_T_CONST(0x0001020488500050)}, { CW_MASK_T_CONST(0x0102040810a000a0)}, { CW_MASK_T_CONST(0x0204081020400040)},
2667  { CW_MASK_T_CONST(0x2010080402000204)}, { CW_MASK_T_CONST(0x4020100805000508)}, { CW_MASK_T_CONST(0x804020110a000a11)}, { CW_MASK_T_CONST(0x0080412214001422)},
2668  { CW_MASK_T_CONST(0x0001824428002844)}, { CW_MASK_T_CONST(0x0102048850005088)}, { CW_MASK_T_CONST(0x02040810a000a010)}, { CW_MASK_T_CONST(0x0408102040004020)},
2669  { CW_MASK_T_CONST(0x1008040200020408)}, { CW_MASK_T_CONST(0x2010080500050810)}, { CW_MASK_T_CONST(0x4020110a000a1120)}, { CW_MASK_T_CONST(0x8041221400142241)},
2670  { CW_MASK_T_CONST(0x0182442800284482)}, { CW_MASK_T_CONST(0x0204885000508804)}, { CW_MASK_T_CONST(0x040810a000a01008)}, { CW_MASK_T_CONST(0x0810204000402010)},
2671  { CW_MASK_T_CONST(0x0804020002040810)}, { CW_MASK_T_CONST(0x1008050005081020)}, { CW_MASK_T_CONST(0x20110a000a112040)}, { CW_MASK_T_CONST(0x4122140014224180)},
2672  { CW_MASK_T_CONST(0x8244280028448201)}, { CW_MASK_T_CONST(0x0488500050880402)}, { CW_MASK_T_CONST(0x0810a000a0100804)}, { CW_MASK_T_CONST(0x1020400040201008)},
2673  { CW_MASK_T_CONST(0x0402000204081020)}, { CW_MASK_T_CONST(0x0805000508102040)}, { CW_MASK_T_CONST(0x110a000a11204080)}, { CW_MASK_T_CONST(0x2214001422418000)},
2674  { CW_MASK_T_CONST(0x4428002844820100)}, { CW_MASK_T_CONST(0x8850005088040201)}, { CW_MASK_T_CONST(0x10a000a010080402)}, { CW_MASK_T_CONST(0x2040004020100804)},
2675  { CW_MASK_T_CONST(0x0200020408102040)}, { CW_MASK_T_CONST(0x0500050810204080)}, { CW_MASK_T_CONST(0x0a000a1120408000)}, { CW_MASK_T_CONST(0x1400142241800000)},
2676  { CW_MASK_T_CONST(0x2800284482010000)}, { CW_MASK_T_CONST(0x5000508804020100)}, { CW_MASK_T_CONST(0xa000a01008040201)}, { CW_MASK_T_CONST(0x4000402010080402)},
2677  { CW_MASK_T_CONST(0x0002040810204080)}, { CW_MASK_T_CONST(0x0005081020408000)}, { CW_MASK_T_CONST(0x000a112040800000)}, { CW_MASK_T_CONST(0x0014224180000000)},
2678  { CW_MASK_T_CONST(0x0028448201000000)}, { CW_MASK_T_CONST(0x0050880402010000)}, { CW_MASK_T_CONST(0x00a0100804020100)}, { CW_MASK_T_CONST(0x0040201008040201)},
2679  // Rook
2680  { CW_MASK_T_CONST(0x01010101010101fe)}, { CW_MASK_T_CONST(0x02020202020202fd)}, { CW_MASK_T_CONST(0x04040404040404fb)}, { CW_MASK_T_CONST(0x08080808080808f7)},
2681  { CW_MASK_T_CONST(0x10101010101010ef)}, { CW_MASK_T_CONST(0x20202020202020df)}, { CW_MASK_T_CONST(0x40404040404040bf)}, { CW_MASK_T_CONST(0x808080808080807f)},
2682  { CW_MASK_T_CONST(0x010101010101fe01)}, { CW_MASK_T_CONST(0x020202020202fd02)}, { CW_MASK_T_CONST(0x040404040404fb04)}, { CW_MASK_T_CONST(0x080808080808f708)},
2683  { CW_MASK_T_CONST(0x101010101010ef10)}, { CW_MASK_T_CONST(0x202020202020df20)}, { CW_MASK_T_CONST(0x404040404040bf40)}, { CW_MASK_T_CONST(0x8080808080807f80)},
2684  { CW_MASK_T_CONST(0x0101010101fe0101)}, { CW_MASK_T_CONST(0x0202020202fd0202)}, { CW_MASK_T_CONST(0x0404040404fb0404)}, { CW_MASK_T_CONST(0x0808080808f70808)},
2685  { CW_MASK_T_CONST(0x1010101010ef1010)}, { CW_MASK_T_CONST(0x2020202020df2020)}, { CW_MASK_T_CONST(0x4040404040bf4040)}, { CW_MASK_T_CONST(0x80808080807f8080)},
2686  { CW_MASK_T_CONST(0x01010101fe010101)}, { CW_MASK_T_CONST(0x02020202fd020202)}, { CW_MASK_T_CONST(0x04040404fb040404)}, { CW_MASK_T_CONST(0x08080808f7080808)},
2687  { CW_MASK_T_CONST(0x10101010ef101010)}, { CW_MASK_T_CONST(0x20202020df202020)}, { CW_MASK_T_CONST(0x40404040bf404040)}, { CW_MASK_T_CONST(0x808080807f808080)},
2688  { CW_MASK_T_CONST(0x010101fe01010101)}, { CW_MASK_T_CONST(0x020202fd02020202)}, { CW_MASK_T_CONST(0x040404fb04040404)}, { CW_MASK_T_CONST(0x080808f708080808)},
2689  { CW_MASK_T_CONST(0x101010ef10101010)}, { CW_MASK_T_CONST(0x202020df20202020)}, { CW_MASK_T_CONST(0x404040bf40404040)}, { CW_MASK_T_CONST(0x8080807f80808080)},
2690  { CW_MASK_T_CONST(0x0101fe0101010101)}, { CW_MASK_T_CONST(0x0202fd0202020202)}, { CW_MASK_T_CONST(0x0404fb0404040404)}, { CW_MASK_T_CONST(0x0808f70808080808)},
2691  { CW_MASK_T_CONST(0x1010ef1010101010)}, { CW_MASK_T_CONST(0x2020df2020202020)}, { CW_MASK_T_CONST(0x4040bf4040404040)}, { CW_MASK_T_CONST(0x80807f8080808080)},
2692  { CW_MASK_T_CONST(0x01fe010101010101)}, { CW_MASK_T_CONST(0x02fd020202020202)}, { CW_MASK_T_CONST(0x04fb040404040404)}, { CW_MASK_T_CONST(0x08f7080808080808)},
2693  { CW_MASK_T_CONST(0x10ef101010101010)}, { CW_MASK_T_CONST(0x20df202020202020)}, { CW_MASK_T_CONST(0x40bf404040404040)}, { CW_MASK_T_CONST(0x807f808080808080)},
2694  { CW_MASK_T_CONST(0xfe01010101010101)}, { CW_MASK_T_CONST(0xfd02020202020202)}, { CW_MASK_T_CONST(0xfb04040404040404)}, { CW_MASK_T_CONST(0xf708080808080808)},
2695  { CW_MASK_T_CONST(0xef10101010101010)}, { CW_MASK_T_CONST(0xdf20202020202020)}, { CW_MASK_T_CONST(0xbf40404040404040)}, { CW_MASK_T_CONST(0x7f80808080808080)},
2696  // Queen
2697  { CW_MASK_T_CONST(0x81412111090503fe)}, { CW_MASK_T_CONST(0x02824222120a07fd)}, { CW_MASK_T_CONST(0x0404844424150efb)}, { CW_MASK_T_CONST(0x08080888492a1cf7)},
2698  { CW_MASK_T_CONST(0x10101011925438ef)}, { CW_MASK_T_CONST(0x2020212224a870df)}, { CW_MASK_T_CONST(0x404142444850e0bf)}, { CW_MASK_T_CONST(0x8182848890a0c07f)},
2699  { CW_MASK_T_CONST(0x412111090503fe03)}, { CW_MASK_T_CONST(0x824222120a07fd07)}, { CW_MASK_T_CONST(0x04844424150efb0e)}, { CW_MASK_T_CONST(0x080888492a1cf71c)},
2700  { CW_MASK_T_CONST(0x101011925438ef38)}, { CW_MASK_T_CONST(0x20212224a870df70)}, { CW_MASK_T_CONST(0x4142444850e0bfe0)}, { CW_MASK_T_CONST(0x82848890a0c07fc0)},
2701  { CW_MASK_T_CONST(0x2111090503fe0305)}, { CW_MASK_T_CONST(0x4222120a07fd070a)}, { CW_MASK_T_CONST(0x844424150efb0e15)}, { CW_MASK_T_CONST(0x0888492a1cf71c2a)},
2702  { CW_MASK_T_CONST(0x1011925438ef3854)}, { CW_MASK_T_CONST(0x212224a870df70a8)}, { CW_MASK_T_CONST(0x42444850e0bfe050)}, { CW_MASK_T_CONST(0x848890a0c07fc0a0)},
2703  { CW_MASK_T_CONST(0x11090503fe030509)}, { CW_MASK_T_CONST(0x22120a07fd070a12)}, { CW_MASK_T_CONST(0x4424150efb0e1524)}, { CW_MASK_T_CONST(0x88492a1cf71c2a49)},
2704  { CW_MASK_T_CONST(0x11925438ef385492)}, { CW_MASK_T_CONST(0x2224a870df70a824)}, { CW_MASK_T_CONST(0x444850e0bfe05048)}, { CW_MASK_T_CONST(0x8890a0c07fc0a090)},
2705  { CW_MASK_T_CONST(0x090503fe03050911)}, { CW_MASK_T_CONST(0x120a07fd070a1222)}, { CW_MASK_T_CONST(0x24150efb0e152444)}, { CW_MASK_T_CONST(0x492a1cf71c2a4988)},
2706  { CW_MASK_T_CONST(0x925438ef38549211)}, { CW_MASK_T_CONST(0x24a870df70a82422)}, { CW_MASK_T_CONST(0x4850e0bfe0504844)}, { CW_MASK_T_CONST(0x90a0c07fc0a09088)},
2707  { CW_MASK_T_CONST(0x0503fe0305091121)}, { CW_MASK_T_CONST(0x0a07fd070a122242)}, { CW_MASK_T_CONST(0x150efb0e15244484)}, { CW_MASK_T_CONST(0x2a1cf71c2a498808)},
2708  { CW_MASK_T_CONST(0x5438ef3854921110)}, { CW_MASK_T_CONST(0xa870df70a8242221)}, { CW_MASK_T_CONST(0x50e0bfe050484442)}, { CW_MASK_T_CONST(0xa0c07fc0a0908884)},
2709  { CW_MASK_T_CONST(0x03fe030509112141)}, { CW_MASK_T_CONST(0x07fd070a12224282)}, { CW_MASK_T_CONST(0x0efb0e1524448404)}, { CW_MASK_T_CONST(0x1cf71c2a49880808)},
2710  { CW_MASK_T_CONST(0x38ef385492111010)}, { CW_MASK_T_CONST(0x70df70a824222120)}, { CW_MASK_T_CONST(0xe0bfe05048444241)}, { CW_MASK_T_CONST(0xc07fc0a090888482)},
2711  { CW_MASK_T_CONST(0xfe03050911214181)}, { CW_MASK_T_CONST(0xfd070a1222428202)}, { CW_MASK_T_CONST(0xfb0e152444840404)}, { CW_MASK_T_CONST(0xf71c2a4988080808)},
2712  { CW_MASK_T_CONST(0xef38549211101010)}, { CW_MASK_T_CONST(0xdf70a82422212020)}, { CW_MASK_T_CONST(0xbfe0504844424140)}, { CW_MASK_T_CONST(0x7fc0a09088848281)},
2713 };
2714 
2715 } // namespace cwchess
CodeData const black_pawn
A constant representing a black pawn.
Definition: Code.h:66
BitBoardData const b8
The square b8.
Definition: BitBoard.h:153
BitBoardData const d8
The square d8.
Definition: BitBoard.h:155
IndexData const index_begin
A constant representing the& #39;first&#39; index.
Definition: Index.h:184
The POD base type of class Code.
Definition: Code.h:49
BitBoardData const c8
The square c8.
Definition: BitBoard.h:154
A namespace for all chess related objects that are not related to the GUI.
Definition: Array.h:39
mask_t M_bitmask
A one-bit-per-square chessboard mask.
Definition: BitBoard.h:93
IndexData const ia7
A constant representing the index to square a7.
Definition: Index.h:149
TypeData const bishop
A constant representing a bishop.
Definition: Type.h:71
BitBoardData const file_h
The h-file.
Definition: BitBoard.h:204
bool load_FEN(std::string const& FEN)
Read a FEN code.
void prev_bit_in(uint64_t mask)
Retreat Index to the previous bit that is set.
Definition: Index.h:432
CodeData const white_queen
A constant representing a white queen.
Definition: Code.h:62
TypeData const queen
A constant representing a queen.
Definition: Type.h:75
Color opposite(void) const
Return a Color object with the opposite color of this object.
Definition: Color.h:133
BitBoardData const f1
The square f1.
Definition: BitBoard.h:101
TypeData const rook
A constant representing a rook.
Definition: Type.h:73
bool execute(Move const& move)
Execute move move.
Index mask2index(mask_t mask)
Convert a single bit mask into it&#39;s Index.
Definition: BitBoard.h:69
mask_t index2mask(Index index)
Convert Index to a mask_t.
Definition: BitBoard.h:51
ColorData const white
A constant representing the color white.
Definition: Color.h:55
FlagsData const fl_pawn_is_not_blocked
A constant representing the flag& #39;pawn is not blocked&#39;.
Definition: Flags.h:47
IndexData const ia1
A constant representing the index to square a1.
Definition: Index.h:53
IndexData const ih1
A constant representing the index to square h1.
Definition: Index.h:67
void toggle(void)
Change the color from black to white or vica versa.
Definition: Color.h:125
bool is_nothing(void) const
Returns TRUE if the code represents& #39;nothing&#39;.
Definition: Code.h:160
This file contains the declaration of class Direction.
A chess move in a particular chess position.
Definition: Move.h:44
BitBoardData const file_a
The a-file.
Definition: BitBoard.h:197
TypeData const pawn
A constant representing a pawn.
Definition: Type.h:65
TypeData const king
A constant representing a king.
Definition: Type.h:69
Flags representing the state of a piece on the chessboard.
Definition: Flags.h:85
void next_bit_in(uint64_t mask)
Advance the index to the next bit that is set in mask.
Definition: Index.h:360
CodeData const black_queen
A constant representing a black queen;.
Definition: Code.h:74
The POD base type of class BitBoard.
Definition: BitBoard.h:87
bool set_en_passant(Index const& index)
Explicity set the en passant information.
uint8_t const bishop_bits
The underlaying integral value of type& #39;bishop&#39;.
Definition: Type.h:57
void set()
Set all values to TRUE.
Definition: BitBoard.h:386
bool moves_along(Direction const& direction)
Return TRUE if this piece moves along direction.
Definition: Code.h:178
BitBoardData const e1
The square e1.
Definition: BitBoard.h:100
IndexData const ia8
A constant representing the index to square a8.
Definition: Index.h:165
The POD base type of class Index.
Definition: Index.h:45
CodeData const black_rook
A constant representing a black rook;.
Definition: Code.h:68
BitBoardData const c1
The square c1.
Definition: BitBoard.h:98
FlagsData const fl_pawn_can_take_king_side
A constant representing the flag& #39;pawn can take king side&#39;.
Definition: Flags.h:48
Type type(void) const
The type of this piece.
Definition: Piece.h:115
void clear(void)
Clear the board.
bool is_promotion(void) const
Return TRUE if this move is a pawn promotion.
Definition: Move.h:98
bool is_a_slider(void) const
Returns TRUE if the type is a bishop, rook or queen.
Definition: Code.h:151
A chess piece type.
Definition: Type.h:87
An object representing en passant information.
Definition: EnPassant.h:49
A one-boolean-per-square chessboard.
Definition: BitBoard.h:266
The index of a chess square.
Definition: Index.h:211
bool test() const
Test if any bit is set at all.
Definition: BitBoard.h:450
uint8_t M_bits
00000STT, where STT is the type. If S == 1 then the piece is a slider.
Definition: Type.h:50
IndexData const ih2
A constant representing the index to square h2.
Definition: Index.h:83
BitBoardData const e8
The square e8.
Definition: BitBoard.h:156
bool has_opposite_color_of(Code const& code)
Return TRUE if the colors are different.
Definition: Code.h:175
IndexData const ih7
A constant representing the index to square h7.
Definition: Index.h:163
int col(void) const
Returns the column.
Definition: Index.h:337
CodeData const white_rook
A constant representing a white rook.
Definition: Code.h:56
bool legal(Move const& move) const
Return true if the move is a legal move.
A class to keep track of castling rights.
Definition: CastleFlags.h:63
A particular piece on the board.
Definition: Piece.h:45
Index index(void) const
Return the index of the square that was passed.
Definition: EnPassant.h:85
uint64_t mask_t
The type of an internal BitBoard mask.
Definition: BitBoard.h:48
BitBoardData const d1
The square d1.
Definition: BitBoard.h:99
bool is_a(Type const& type) const
Returns TRUE if the type is equal.
Definition: Code.h:163
uint8_t const white_bits
The underlaying integral value of color& #39;white&#39;.
Definition: Color.h:49
uint8_t const king_bits
The underlaying integral value of type& #39;king&#39;.
Definition: Type.h:56
TypeData const knight
A constant representing a knight.
Definition: Type.h:67
Index pawn_index(void) const
Return the index of the pawn that just advanced two squares.
Definition: EnPassant.h:95
CodeData const black_bishop
A constant representing a black bishop;.
Definition: Code.h:72
bool skip_move(void)
Skip a move.
bool is_white(void) const
Return TRUE if this color is white.
Definition: Color.h:111
Index from(void) const
Return the square the piece moves from.
Definition: Move.h:101
BitBoardData const b1
The square b1.
Definition: BitBoard.h:97
BitBoardData const g8
The square g8.
Definition: BitBoard.h:158
int row(void) const
Returns the row.
Definition: Index.h:334
Color color(void) const
Return the color of the piece.
Definition: Piece.h:112
IndexData const ia2
A constant representing the index to square a2.
Definition: Index.h:69
A chess position.
Definition: ChessPosition.h:50
bool is_a_rookmover(void) const
Returns TRUE if the type is a rook or queen.
Definition: Code.h:154
BitBoard reachables(Index const& index, bool attacked_squares=false) const
Return a BitBoard with bits set for each square that a piece can reach in one move.
BitBoard from(Index const& index) const
Return a BitBoard with all squares in this direction.
Definition: Direction.h:56
A chess piece type including color.
Definition: Code.h:92
Index to(void) const
Return the square the piece moves to.
Definition: Move.h:104
uint8_t const black_bits
The underlaying integral value of color& #39;black&#39;.
Definition: Color.h:48
bool is_a_bishopmover(void) const
Returns TRUE if the type is a bishop or queen.
Definition: Code.h:157
FlagsData const fl_pawn_can_move_two_squares
A constant representing the flag& #39;pawn can move two squares&#39;.
Definition: Flags.h:49
This file contains the declaration of class ChessPosition.
std::string FEN(void) const
Return the FEN code for this position.
TypeData const nothing
A constant representing the absence of a piece.
Definition: Type.h:63
Type type(void) const
Return the Type of this Code.
Definition: Code.h:181
IndexData const index_pre_begin
A constant representing& #39;one before the start&#39;.
Definition: Index.h:182
CodeData const white_pawn
A constant representing a white pawn.
Definition: Code.h:54
BitBoardData const f8
The square f8.
Definition: BitBoard.h:157
bool exists(void) const
Return TRUE if the last move was a pawn advancing two squares.
Definition: EnPassant.h:79
CodeData const black_knight
A constant representing a black knight;.
Definition: Code.h:70
void swap_colors(void)
Swap colors.
A color (black or white).
Definition: Color.h:67
uint8_t const type_mask
A mask for the bits used for the type of a piece.
Definition: Type.h:60
BitBoard defendables(Code const& code, Index const& index, bool& battery) const
Return a BitBoard with bits set for each square that a piece defends, or would defend if an exchange ...
BitBoardData const g1
The square g1.
Definition: BitBoard.h:102
BitBoard moves(Index const& index) const
Return a BitBoard with bits set for each square the piece at index can legally go to...
IndexData const index_end
A constant representing& #39;one past the end&#39;.
Definition: Index.h:186
Non-mutable iterator over selective chess pieces in a chess position.
Definition: PieceIterator.h:42
uint8_t const knight_bits
The underlaying integral value of type& #39;knight&#39;.
Definition: Type.h:55
The POD base type of class Type.
Definition: Type.h:49
void initial_position(void)
Set up the initial position.
Color color(void) const
Return the Color of this Code.
Definition: Code.h:184
uint8_t const queen_bits
The underlaying integral value of type& #39;queen&#39;.
Definition: Type.h:59
Type promotion_type(void) const
Return the promotion type. Returns empty if this isn&#39;t a promotion.
Definition: Move.h:107
Color to_move(void) const
Return whose turn it is.
This file contains the declaration of class ChessNotation.
void reset()
Set all values to FALSE.
Definition: BitBoard.h:377
FlagsData const fl_pawn_can_take_queen_side
A constant representing the flag& #39;pawn can take queen side&#39;.
Definition: Flags.h:46
CodeData const white_bishop
A constant representing a white bishop.
Definition: Code.h:60
bool place(Code const& code, Index const& index)
Place a piece on the board.
CodeData const white_knight
A constant representing a white knight.
Definition: Code.h:58
uint8_t const nothing_bits
The underlaying integral value of type& #39;nothing&#39;.
Definition: Type.h:53
uint8_t const pawn_bits
The underlaying integral value of type& #39;pawn&#39;.
Definition: Type.h:54
Code code(void) const
The code of this piece.
Definition: Piece.h:121
uint8_t const rook_bits
The underlaying integral value of type& #39;rook&#39;.
Definition: Type.h:58
Index const & index(void) const
Return the current index.
ColorData const black
A constant representing the color black.
Definition: Color.h:53

Copyright © 2006 - 2010 Carlo Wood.  All rights reserved.