00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef USE_PCH
00025 #include "sys.h"
00026 #include <sstream>
00027 #include <cassert>
00028 #endif
00029
00030 #include "ChessPosition.h"
00031 #include "Direction.h"
00032 #include "ChessNotation.h"
00033 #include "debug.h"
00034
00035 namespace cwchess {
00036
00037 #ifndef DOXYGEN
00038 std::string EnPassant::FEN4(void) const
00039 {
00040 if (!exists())
00041 return "-";
00042 std::ostringstream fen;
00043 Index passed(this->index());
00044 fen << (char)('a' + passed.col()) << (passed.row() + 1);
00045 return fen.str();
00046 }
00047 #endif
00048
00049 void ChessPosition::clear_en_passant(void)
00050 {
00051 Index index = M_en_passant.pawn_index();
00052 if (index > ih1 && piece_at(index - 1) == pawn)
00053 M_pieces[index - 1].reset_can_take_king_side();
00054 if (index < ia8 && piece_at(index + 1) == pawn)
00055 M_pieces[index + 1].reset_can_take_queen_side();
00056 M_en_passant.clear();
00057 }
00058
00059 void ChessPosition::clear(void)
00060 {
00061 for (Index index = index_begin; index != index_end; ++index)
00062 M_pieces[index].set_type(nothing);
00063 M_en_passant.clear();
00064 M_castle_flags.clear();
00065 M_half_move_clock = 0;
00066 M_full_move_number = 1;
00067 for (int i = 0; i < 16; ++i)
00068 {
00069 CodeData data = { i };
00070 M_bitboards[data].reset();
00071 }
00072 M_attackers[black].reset();
00073 M_attackers[white].reset();
00074 M_pinning[black].reset();
00075 M_pinning[white].reset();
00076 M_defended[black].reset();
00077 M_defended[white].reset();
00078 M_king_battery_attack_count[black] = 0;
00079 M_king_battery_attack_count[white] = 0;
00080 M_double_check = false;
00081 }
00082
00083 void ChessPosition::initial_position(void)
00084 {
00085 clear();
00086
00087 M_to_move = white;
00088
00089 for (Index index = ia2; index <= ih2; ++index)
00090 place(white_pawn, index);
00091
00092 for (Index index = ia7; index <= ih7; ++index)
00093 place(black_pawn, index);
00094
00095 Color color = white;
00096 Index index = index_pre_begin;
00097 for (int ci = 0; ci < 2; ++ci)
00098 {
00099 place(Code(color, rook), ++index);
00100 place(Code(color, knight), ++index);
00101 place(Code(color, bishop), ++index);
00102 place(Code(color, queen), ++index);
00103 place(Code(color, king), ++index);
00104 place(Code(color, bishop), ++index);
00105 place(Code(color, knight), ++index);
00106 place(Code(color, rook), ++index);
00107 color = black;
00108 index += 48;
00109 }
00110 }
00111
00112 bool ChessPosition::increment_counters(bool pawn_advance_or_capture)
00113 {
00114 if (pawn_advance_or_capture)
00115 M_half_move_clock = 0;
00116 else
00117 ++M_half_move_clock;
00118 if (M_to_move == white)
00119 ++M_full_move_number;
00120 return M_half_move_clock == 100;
00121 }
00122
00123 bool ChessPosition::skip_move(void)
00124 {
00125 reset_en_passant();
00126 M_to_move.toggle();
00127 M_double_check = M_castle_flags.in_check(M_to_move) ? double_check(M_to_move) : false;
00128 return increment_counters(false);
00129 }
00130
00131 void ChessPosition::to_move(Color const& color)
00132 {
00133 M_to_move = color;
00134 M_double_check = M_castle_flags.in_check(M_to_move) ? double_check(M_to_move) : false;
00135 }
00136
00137 void ChessPosition::swap_colors(void)
00138 {
00139 ChessPosition new_chess_position;
00140 new_chess_position.clear();
00141 new_chess_position.M_to_move = M_to_move.opposite();
00142
00143 Index en_passant_index = index_end;
00144 if (M_en_passant.exists())
00145 {
00146 Index index = M_en_passant.pawn_index();
00147 Piece& piece(M_pieces[index]);
00148 en_passant_index = Index(index.col(), 7 - index.row());
00149 new_chess_position.place(Code(piece.color().opposite(), pawn), en_passant_index);
00150 new_chess_position.set_en_passant(Index(index.col(), 7 - M_en_passant.index().row()));
00151 }
00152
00153 PieceIterator const end;
00154 for (PieceIterator iter(this, M_bitboards[black] | M_bitboards[white]); iter != end; ++iter)
00155 {
00156 Index index(iter.index().col(), 7 - iter.index().row());
00157 if (index == en_passant_index)
00158 continue;
00159 new_chess_position.place(Code(iter->color().opposite(), iter->type()), index);
00160 }
00161 new_chess_position.M_full_move_number = 1;
00162 * this = new_chess_position;
00163 }
00164
00165
00166
00167
00168 void ChessPosition::update_removed(uint8_t col, uint8_t row, Color const& color)
00169 {
00170
00171
00172 bool ok;
00173 Code other_pawn;
00174 if (color == white)
00175 {
00176 ++row;
00177 ok = row <= 6;
00178 other_pawn = black_pawn;
00179 }
00180 else
00181 {
00182 --row;
00183 ok = (int8_t)row >= 1;
00184 other_pawn = white_pawn;
00185 }
00186 if (ok)
00187 {
00188 if (col > 0)
00189 {
00190 Index index(col - 1, row);
00191 if (M_pieces[index] == other_pawn)
00192 M_pieces[index].reset_can_take_king_side();
00193 }
00194 if (col < 7)
00195 {
00196 Index index(col + 1, row);
00197 if (M_pieces[index] == other_pawn)
00198 M_pieces[index].reset_can_take_queen_side();
00199 }
00200 }
00201 }
00202
00203
00204
00205
00206 void ChessPosition::update_placed(uint8_t col, uint8_t row, Color const& color)
00207 {
00208
00209
00210 bool ok;
00211 Code other_pawn;
00212 if (color == white)
00213 {
00214 ++row;
00215 ok = row <= 6;
00216 other_pawn = black_pawn;
00217 }
00218 else
00219 {
00220 --row;
00221 ok = (int8_t)row >= 1;
00222 other_pawn = white_pawn;
00223 }
00224 if (ok)
00225 {
00226 if (col > 0)
00227 {
00228 Index index(col - 1, row);
00229 if (M_pieces[index] == other_pawn)
00230 M_pieces[index].set_can_take_king_side();
00231 }
00232 if (col < 7)
00233 {
00234 Index index(col + 1, row);
00235 if (M_pieces[index] == other_pawn)
00236 M_pieces[index].set_can_take_queen_side();
00237 }
00238 }
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 void ChessPosition::update_pinning(Code const& code, Index const& index, mask_t mask, Direction const& direction, BitBoard const& relevant_pieces)
00250 {
00251 bool king_side_is_msb = (relevant_pieces() < mask);
00252
00253 PieceIterator piece_iter = king_side_is_msb ? PieceIterator(this, relevant_pieces, 0) : PieceIterator(this, relevant_pieces);
00254 PieceIterator end = king_side_is_msb ? PieceIterator(0) : PieceIterator();
00255 Code first_piece_code;
00256 Index first_piece_index;
00257 bool found_first_piece = false;
00258 bool taking_en_passant_not_allowed = false;
00259 while (piece_iter != end)
00260 {
00261 if (found_first_piece)
00262 {
00263 Code second_piece_code = piece_iter->code();
00264 if (!second_piece_code.has_opposite_color_of(code))
00265 break;
00266 else
00267 {
00268 if (second_piece_code.moves_along(direction))
00269 {
00270 if (taking_en_passant_not_allowed)
00271 M_en_passant.pinned_set();
00272 else
00273 M_pinning[code.color()] |= squares_from_to(piece_iter.index(), index);
00274 break;
00275 }
00276 else if (M_en_passant.exists() && M_en_passant.pawn_index() == piece_iter.index() && first_piece_code.is_a(pawn)&&
00277 direction.is_horizontal() && M_en_passant.pawn_index() - direction == first_piece_index&&
00278 first_piece_code.has_opposite_color_of(second_piece_code))
00279 taking_en_passant_not_allowed = true;
00280 else
00281 break;
00282 }
00283 }
00284 else
00285 {
00286 first_piece_code = piece_iter->code();
00287 first_piece_index = piece_iter.index();
00288 if (first_piece_code.has_opposite_color_of(code))
00289 {
00290 if (!M_en_passant.exists() || M_en_passant.pawn_index() != first_piece_index || !direction.is_horizontal())
00291 break;
00292 else
00293 {
00294
00295 taking_en_passant_not_allowed = true;
00296 }
00297 }
00298 else if (taking_en_passant_not_allowed&&
00299 (!first_piece_code.is_a(pawn) || first_piece_index - direction != M_en_passant.pawn_index()))
00300 break;
00301 else
00302 found_first_piece = true;
00303 }
00304 if (king_side_is_msb)
00305 {
00306 if (piece_iter.index() == ia1)
00307 break;
00308 --piece_iter;
00309 }
00310 else
00311 ++piece_iter;
00312 }
00313 }
00314
00315
00316 bool ChessPosition::place(Code const& code, Index const& index)
00317 {
00318 DoutEntering(dc::place, "ChessPosition::place(" << code << ", " << index << ")");
00319
00320
00321 if (code.is_a(pawn))
00322 {
00323 int row = index.row();
00324 if (row == 0 || row == 7)
00325 return false;
00326 }
00327
00328 if (code.is_a(king) && M_bitboards[code].test())
00329 return false;
00330
00331 Code const old_code = M_pieces[index].code();
00332
00333
00334
00335
00336
00337 if (old_code == code)
00338 return true;
00339
00340 mask_t const mask(index2mask(index));
00341 int index_row = index.row();
00342
00343 if (!old_code.is_nothing())
00344 {
00345
00346 M_bitboards[old_code.color()].reset(mask);
00347 M_bitboards[old_code].reset(mask);
00348
00349
00350 M_castle_flags.update_removed(old_code, index);
00351
00352
00353 if (code.is_nothing() || code.color() != old_code.color())
00354 update_removed(index.col(), index_row, old_code.color());
00355
00356
00357 if (
00358 #if DEBUG_ENPASSANT_EXISTS
00359 M_en_passant.exists() &&
00360
00361 #endif
00362 M_en_passant.pawn_index() == index)
00363 clear_en_passant();
00364
00365
00366 if (code.is_nothing())
00367 {
00368 if (index_row > 1 && M_pieces[index - 8] == white_pawn)
00369 {
00370 M_pieces[index - 8].set_is_not_blocked();
00371 if (index_row == 2 && M_pieces[index + 8] == nothing)
00372 M_pieces[index - 8].set_can_move_two_squares();
00373 }
00374 else if (index_row == 3 && M_pieces[index - 16] == white_pawn)
00375 M_pieces[index - 16].set_can_move_two_squares_if_not_blocked();
00376 if (index_row < 6 && M_pieces[index + 8] == black_pawn)
00377 {
00378 M_pieces[index + 8].set_is_not_blocked();
00379 if (index_row == 5 && M_pieces[index - 8] == nothing)
00380 M_pieces[index + 8].set_can_move_two_squares();
00381 }
00382 else if (index_row == 4 && M_pieces[index + 16] == black_pawn)
00383 M_pieces[index + 16].set_can_move_two_squares_if_not_blocked();
00384 }
00385
00386
00387 if (old_code.is_a(king))
00388 {
00389 M_attackers[old_code].reset();
00390 M_pinning[old_code].reset();
00391 M_en_passant.pinned_reset();
00392 M_king_battery_attack_count[old_code.color().opposite()] = 0;
00393 }
00394
00395
00396 bool battery = false;
00397 M_defended[old_code.color()].sub(defendables(old_code, index, battery));
00398 if (battery)
00399 --M_king_battery_attack_count[old_code.color()];
00400 update_blocked_defendables(old_code, index, true);
00401 }
00402
00403 if (!code.is_nothing())
00404 {
00405
00406 M_bitboards[code.color()].set(mask);
00407 M_bitboards[code].set(mask);
00408
00409
00410 M_castle_flags.update_placed(code, index);
00411
00412
00413 if (M_en_passant.exists() && (index == M_en_passant.index() || index == M_en_passant.from_index()))
00414 clear_en_passant();
00415
00416
00417 if (old_code.is_nothing() || code.color() != old_code.color())
00418 update_placed(index.col(), index_row, code.color());
00419
00420
00421 if (old_code.is_nothing())
00422 {
00423 if (index_row > 1 && M_pieces[index - 8] == white_pawn)
00424 M_pieces[index - 8].reset_is_not_blocked();
00425 else if (index_row == 3 && M_pieces[index - 16] == white_pawn)
00426 M_pieces[index - 16].reset_can_move_two_squares();
00427 if (index_row < 6 && M_pieces[index + 8] == black_pawn)
00428 M_pieces[index + 8].reset_is_not_blocked();
00429 else if (index_row == 4 && M_pieces[index + 16] == black_pawn)
00430 M_pieces[index + 16].reset_can_move_two_squares();
00431 }
00432
00433
00434 if (code.is_a(king))
00435 {
00436
00437 Color color(code.color());
00438 color.toggle();
00439 Code bishop_code(color, bishop);
00440 Code rook_code(color, rook);
00441 Code queen_code(color, queen);
00442
00443 BitBoard rook_attackers(candidates_table[candidates_table_offset(rook) + index()]);
00444 rook_attackers& = M_bitboards[rook_code] | M_bitboards[queen_code];
00445
00446 BitBoard bishop_attackers(candidates_table[candidates_table_offset(bishop) + index()]);
00447 bishop_attackers& = M_bitboards[bishop_code] | M_bitboards[queen_code];
00448
00449 BitBoard attackers(CW_MASK_T_CONST(0));
00450 for (PieceIterator piece_iter(this, rook_attackers); piece_iter != piece_end(); ++piece_iter)
00451 attackers |= squares_from_to(piece_iter.index(), index);
00452 for (PieceIterator piece_iter(this, bishop_attackers); piece_iter != piece_end(); ++piece_iter)
00453 attackers |= squares_from_to(piece_iter.index(), index);
00454 M_attackers[code] = attackers;
00455 BitBoard const all_pieces(M_bitboards[white] | M_bitboards[black]);
00456 BitBoard possible_pinning_directions(candidates_table[candidates_table_offset(king) + index()]);
00457 possible_pinning_directions& = attackers;
00458 for (PieceIterator direction_iter(this, possible_pinning_directions); direction_iter != piece_end(); ++direction_iter)
00459 {
00460 Direction direction(direction_from_to(index, direction_iter.index()));
00461 BitBoard relevant_pieces(all_pieces);
00462 relevant_pieces& = direction.from(index);
00463 update_pinning(code, index, mask, direction, relevant_pieces);
00464 }
00465 }
00466
00467
00468 bool battery = false;
00469 M_defended[code.color()].add(defendables(code, index, battery));
00470 if (battery)
00471 ++M_king_battery_attack_count[code.color()];
00472 update_blocked_defendables(code, index, false);
00473 }
00474
00475 Flags flags(fl_none);
00476
00477 if (code.is_a(pawn))
00478 {
00479
00480
00481
00482
00483
00484
00485
00486 BitBoardData forward1 = { mask };
00487 BitBoardData forward2 = { mask };
00488 BitBoard other_pieces, all_pieces;
00489 uint8_t initial_row;
00490 if (code.color() == white)
00491 {
00492 other_pieces = M_bitboards[black];
00493 forward1.M_bitmask <<= 8;
00494 forward2.M_bitmask <<= 16;
00495 all_pieces = other_pieces | M_bitboards[white];
00496 initial_row = 1;
00497 }
00498 else
00499 {
00500 other_pieces = M_bitboards[white];
00501 forward1.M_bitmask >>= 8;
00502 forward2.M_bitmask >>= 16;
00503 all_pieces = other_pieces | M_bitboards[black];
00504 initial_row = 6;
00505 }
00506 BitBoardData kingside(forward1), queenside(forward1);
00507 kingside.M_bitmask <<= 1;
00508 queenside.M_bitmask >>= 1;
00509 kingside.M_bitmask& = ~file_a.M_bitmask;
00510 queenside.M_bitmask& = ~file_h.M_bitmask;
00511 if (!(all_pieces & forward1))
00512 {
00513 flags |= fl_pawn_is_not_blocked;
00514 if (!(all_pieces & forward2) && initial_row == index_row)
00515 flags |= fl_pawn_can_move_two_squares;
00516 }
00517 if (M_en_passant.exists() && M_en_passant.from_index().row() != initial_row)
00518 other_pieces |= M_en_passant.index();
00519 if ((other_pieces & queenside))
00520 flags |= fl_pawn_can_take_queen_side;
00521 if ((other_pieces & kingside))
00522 flags |= fl_pawn_can_take_king_side;
00523 }
00524
00525
00526 M_pieces[index] = Piece(code, flags);
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673 int color_count = 0;
00674
00675 for (Color color = black; color_count < 2; ++color_count, color = white)
00676 {
00677 Code const king_code(color, king);
00678 Index const king_index(mask2index(M_bitboards[king_code]()));
00679 if (king_index == index_end)
00680 continue;
00681 BitBoard const line(squares_from_to(index, king_index));
00682 if (!line.test())
00683 continue;
00684
00685
00686 Direction const direction(direction_from_to(king_index, index));
00687 bool const attacker = (code.color() != color) && direction.matches(code.type());
00688
00689 bool need_reset = false;
00690 bool need_update = false;
00691
00692 bool const corresponding_bit_in_M_attackers_is_set = M_attackers[color]() & mask;
00693 if (attacker)
00694 {
00695
00696 if (!corresponding_bit_in_M_attackers_is_set)
00697 {
00698
00699 M_attackers[color] |= line;
00700 }
00701 need_reset = need_update = true;
00702 }
00703 else if (corresponding_bit_in_M_attackers_is_set)
00704 {
00705
00706 if (code.is_nothing())
00707 {
00708
00709 if (direction.matches(old_code.type()))
00710 {
00711
00712 TypeData mover;
00713 mover.M_bits = direction.flags & type_mask;
00714 Code queen_code(color.opposite(), queen);
00715 Code mover_code(color.opposite(), mover);
00716 BitBoard mover_attackers(M_bitboards[mover_code] | M_bitboards[queen_code]);
00717 BitBoard line(direction.from(king_index));
00718 mover_attackers& = line;
00719 BitBoard attackers(CW_MASK_T_CONST(0));
00720 for (PieceIterator piece_iter(this, mover_attackers); piece_iter != piece_end(); ++piece_iter)
00721 attackers |= squares_from_to(piece_iter.index(), king_index);
00722 M_attackers[color].reset(line);
00723 M_attackers[color].set(attackers);
00724
00725
00726
00727
00728 need_reset = need_update = M_pinning[color].test(mask) || !(M_pinning[color] & line).test();
00729 }
00730 else
00731 {
00732
00733 need_reset = true;
00734
00735 need_update = !(M_pinning[color]() & mask);
00736 }
00737 }
00738 else if ((M_pinning[color]() & mask))
00739 {
00740
00741 need_reset = true;
00742 need_update = !old_code.is_nothing();
00743 }
00744 else
00745 {
00746
00747 BitBoard line(direction.from(king_index));
00748 need_reset = need_update =
00749 (code.color() == color || (M_en_passant.exists() && direction.is_horizontal())) && !M_pinning[color].test(line);
00750 }
00751 }
00752 if (need_reset)
00753 {
00754 BitBoard line(direction.from(king_index));
00755 M_pinning[color].reset(line);
00756 if (need_update)
00757 {
00758 if (__builtin_expect(M_en_passant.exists(), false))
00759 {
00760 Index pawn_index(M_en_passant.pawn_index());
00761 if (M_pieces[pawn_index].color() != color && line.test(pawn_index))
00762 M_en_passant.pinned_reset();
00763 }
00764 update_pinning(king_code, king_index, M_bitboards[king_code](), direction, (M_bitboards[black] | M_bitboards[white]) & line);
00765 }
00766 }
00767 }
00768
00769
00770 bool in_check = check();
00771 M_castle_flags.set_check(M_to_move, in_check);
00772 M_castle_flags.set_check(M_to_move.opposite(), check(M_to_move.opposite()));
00773 M_double_check = in_check ? double_check(M_to_move) : false;
00774
00775
00776 return true;
00777 }
00778
00779 bool ChessPosition::load_FEN(std::string const& FEN)
00780 {
00781 DoutEntering(dc::notice, "ChessPosition::load_FEN(\"" << FEN << "\")");
00782
00783
00784 clear();
00785 std::string::const_iterator iter = FEN.begin();
00786 char c;
00787
00788 while (*iter == ' ')
00789 ++iter;
00790 if (iter == FEN.end())
00791 return false;
00792
00793 Color color;
00794 int col = 0, row = 7;
00795 while ((c =* iter++) != ' ')
00796 {
00797 color = white;
00798 switch (c)
00799 {
00800 case '/':
00801 if (col != 8 || row <= 0)
00802 return false;
00803 col = 0;
00804 --row;
00805 break;
00806 case '1':
00807 case '2':
00808 case '3':
00809 case '4':
00810 case '5':
00811 case '6':
00812 case '7':
00813 case '8':
00814 col += (int)(c - '0');
00815 break;
00816 case 'p':
00817 case 'r':
00818 case 'n':
00819 case 'b':
00820 case 'q':
00821 case 'k':
00822 color = black;
00823 case 'P':
00824 case 'R':
00825 case 'N':
00826 case 'B':
00827 case 'Q':
00828 case 'K':
00829 {
00830 c = std::toupper(c);
00831 Type type;
00832 if (c == 'P')
00833 type = pawn;
00834 else if (c == 'R')
00835 type = rook;
00836 else if (c == 'N')
00837 type = knight;
00838 else if (c == 'B')
00839 type = bishop;
00840 else if (c == 'Q')
00841 type = queen;
00842 else
00843 type = king;
00844 place(Code(color, type), Index(col, row));
00845 ++col;
00846 break;
00847 }
00848 default:
00849 return false;
00850 }
00851 if (iter == FEN.end())
00852 return false;
00853 }
00854 if (col != 8)
00855 return false;
00856 if (iter == FEN.end())
00857 return false;
00858
00859 while (*iter == ' ')
00860 if (++iter == FEN.end())
00861 return false;
00862
00863 c =* iter++;
00864 if (c != 'w' && c != 'b')
00865 return false;
00866 M_to_move = (c == 'w') ? white : black;
00867 bool in_check = check();
00868 M_double_check = in_check ? double_check(M_to_move) : false;
00869 if (iter == FEN.end() ||* iter != ' ')
00870 return false;
00871
00872 while (*iter == ' ')
00873 if (++iter == FEN.end())
00874 return false;
00875
00876 uint8_t white_castle_flags = white_rook_queen_side_moved | white_king_moved | white_rook_king_side_moved;
00877 uint8_t black_castle_flags = black_rook_queen_side_moved | black_king_moved | black_rook_king_side_moved;
00878 while ((c =* iter++) != ' ')
00879 {
00880 if (c == '-')
00881 break;
00882 switch (c)
00883 {
00884 case 'K':
00885 white_castle_flags& = ~(white_king_moved | white_rook_king_side_moved);
00886 break;
00887 case 'Q':
00888 white_castle_flags& = ~(white_king_moved | white_rook_queen_side_moved);
00889 break;
00890 case 'k':
00891 black_castle_flags& = ~(black_king_moved | black_rook_king_side_moved);
00892 break;
00893 case 'q':
00894 black_castle_flags& = ~(black_king_moved | black_rook_queen_side_moved);
00895 break;
00896 default:
00897 return false;
00898 }
00899 if (iter == FEN.end())
00900 return false;
00901 }
00902 M_castle_flags = white_castle_flags | black_castle_flags;
00903 M_castle_flags.set_check(M_to_move, in_check);
00904 if (iter == FEN.end())
00905 return false;
00906
00907 while (*iter == ' ')
00908 if (++iter == FEN.end())
00909 return false;
00910
00911 if ((c =* iter++) != '-')
00912 {
00913 if (c < 'a' || c > 'h' || iter == FEN.end())
00914 return false;
00915 int col = c - 'a';
00916 c =* iter++;
00917 if (c < '1' || c > '8' || iter == FEN.end())
00918 return false;
00919 int row = c - '1';
00920 Code other_pawn;
00921 if (M_to_move == white)
00922 {
00923 other_pawn = white_pawn;
00924 if (row != 5 || M_pieces[Index(col, row - 1)] != black_pawn || M_pieces[Index(col, row)] != nothing)
00925 return false;
00926 }
00927 else
00928 {
00929 other_pawn = black_pawn;
00930 if (row != 2 || M_pieces[Index(col, row + 1)] != white_pawn || M_pieces[Index(col, row)] != nothing)
00931 return false;
00932 }
00933 set_en_passant(Index(col, row));
00934 }
00935 if (iter == FEN.end() ||* iter != ' ')
00936 return false;
00937
00938 while (*iter == ' ')
00939 if (++iter == FEN.end())
00940 return false;
00941
00942 M_half_move_clock = 0;
00943 while ((c =* iter++) != ' ')
00944 {
00945 if (!std::isdigit(c))
00946 return false;
00947 M_half_move_clock = 10 * M_half_move_clock + c - '0';
00948 if (iter == FEN.end())
00949 return false;
00950 }
00951
00952 while (*iter == ' ')
00953 if (++iter == FEN.end())
00954 return false;
00955
00956 M_full_move_number = 0;
00957 while (iter != FEN.end() &&* iter != ' ')
00958 {
00959 if (!std::isdigit(*iter))
00960 return false;
00961 M_full_move_number = 10 * M_full_move_number +* iter++ - '0';
00962 }
00963 if (M_full_move_number == 0)
00964 return false;
00965
00966 return true;
00967 }
00968
00969 std::string ChessPosition::FEN(void) const
00970 {
00971 std::ostringstream fen;
00972 for (int row = 7; row >= 0; --row)
00973 {
00974 int empty_count = 0;
00975 for (int col = 0; col <= 7; ++col)
00976 {
00977 Code code = M_pieces[Index(col, row)].code();
00978 if (code.is_nothing())
00979 ++empty_count;
00980 else if (empty_count > 0)
00981 {
00982 fen << (char)('0' + empty_count);
00983 empty_count = 0;
00984 }
00985 switch (code())
00986 {
00987 case (black_bits|pawn_bits):
00988 fen << 'p';
00989 break;
00990 case (black_bits|rook_bits):
00991 fen << 'r';
00992 break;
00993 case (black_bits|knight_bits):
00994 fen << 'n';
00995 break;
00996 case (black_bits|bishop_bits):
00997 fen << 'b';
00998 break;
00999 case (black_bits|queen_bits):
01000 fen << 'q';
01001 break;
01002 case (black_bits|king_bits):
01003 fen << 'k';
01004 break;
01005 case (white_bits|pawn_bits):
01006 fen << 'P';
01007 break;
01008 case (white_bits|rook_bits):
01009 fen << 'R';
01010 break;
01011 case (white_bits|knight_bits):
01012 fen << 'N';
01013 break;
01014 case (white_bits|bishop_bits):
01015 fen << 'B';
01016 break;
01017 case (white_bits|queen_bits):
01018 fen << 'Q';
01019 break;
01020 case (white_bits|king_bits):
01021 fen << 'K';
01022 break;
01023 }
01024 }
01025 if (empty_count > 0)
01026 fen << (char)('0' + empty_count);
01027 if (row != 0)
01028 fen << '/';
01029 }
01030 if (M_to_move == white)
01031 fen << " w ";
01032 else
01033 fen << " b ";
01034 unsigned int flags = 0;
01035 if (M_castle_flags.can_castle_short(white))
01036 flags |= 1;
01037 if (M_castle_flags.can_castle_long(white))
01038 flags |= 2;
01039 if (M_castle_flags.can_castle_short(black))
01040 flags |= 4;
01041 if (M_castle_flags.can_castle_long(black))
01042 flags |= 8;
01043 if (flags == 0)
01044 fen << '-';
01045 else
01046 {
01047 for (unsigned int mask = 1; mask <= 8; mask <<= 1)
01048 {
01049 if ((flags & mask))
01050 {
01051 switch (mask)
01052 {
01053 case 1:
01054 fen << 'K';
01055 break;
01056 case 2:
01057 fen << 'Q';
01058 break;
01059 case 4:
01060 fen << 'k';
01061 break;
01062 case 8:
01063 fen << 'q';
01064 break;
01065 }
01066 }
01067 }
01068 }
01069 fen << ' ' << M_en_passant.FEN4() << ' ' << (int)M_half_move_clock << ' ' << (int)M_full_move_number;
01070 return fen.str();
01071 }
01072
01073 bool ChessPosition::set_en_passant(Index const& index)
01074 {
01075 int offset;
01076 Code code;
01077 if (index.row() == 2)
01078 {
01079 code = black_pawn;
01080 offset = 8;
01081 to_move(black);
01082 }
01083 else
01084 {
01085 code = white_pawn;
01086 offset = -8;
01087 to_move(white);
01088 }
01089 M_en_passant = EnPassant(index);
01090 Index index_of_only_neighboring_pawn = index_end;
01091 bool possible = false;
01092 if (index.col() > 0 && M_pieces[index + offset - 1] == code)
01093 {
01094 possible = true;
01095 index_of_only_neighboring_pawn = index + offset - 1;
01096 M_pieces[index_of_only_neighboring_pawn].set_can_take_king_side();
01097 }
01098 if (index.col() < 7 && M_pieces[index + offset + 1] == code)
01099 {
01100 possible = true;
01101 Index right_pawn_index = index + offset + 1;
01102 M_pieces[right_pawn_index].set_can_take_queen_side();
01103 if (index_of_only_neighboring_pawn != index_end)
01104 index_of_only_neighboring_pawn = index_end;
01105 else
01106 index_of_only_neighboring_pawn = right_pawn_index;
01107 }
01108 if (index_of_only_neighboring_pawn != index_end)
01109 {
01110 mask_t mask = index2mask(index_of_only_neighboring_pawn);
01111 if (M_attackers[M_to_move].test(mask))
01112 {
01113 Code king_code(M_to_move, king);
01114 mask = M_bitboards[king_code]();
01115 Index king_index(mask2index(mask));
01116 Direction direction(direction_from_to(king_index, index_of_only_neighboring_pawn));
01117 if (direction.is_horizontal())
01118 {
01119 BitBoard line(direction.from(king_index));
01120 M_pinning[M_to_move].reset(line);
01121 update_pinning(king_code, king_index, mask, direction, (M_bitboards[black] | M_bitboards[white]) & line);
01122 M_en_passant.pinned_set();
01123 }
01124 }
01125 }
01126 return possible;
01127 }
01128
01129 enum up_and_right {
01130 right = 1,
01131 up_left = 7,
01132 up = 8,
01133 up_right = 9,
01134 };
01135
01136 enum down_and_left {
01137 left = 1,
01138 down_right = 7,
01139 down = 8,
01140 down_left = 9
01141 };
01142
01143 template <typename T>
01144 inline void move(mask_t& m, T);
01145
01146 template <>
01147 inline void move<up_and_right>(mask_t& m, up_and_right offset)
01148 {
01149 m <<= offset;
01150 }
01151
01152 template <>
01153 inline void move<down_and_left>(mask_t& m, down_and_left offset)
01154 {
01155 m >>= offset;
01156 }
01157
01158 BitBoard ChessPosition::all_pieces_minus_bishop_movers(Color const& color, Index const& index) const
01159 {
01160 BitBoard result(M_bitboards[white] | M_bitboards[black]);
01161 if (color.is_white())
01162 {
01163 result.reset(M_bitboards[white_queen]);
01164 result.reset(M_bitboards[white_bishop]);
01165
01166 BitBoard north_west_pawn(M_bitboards[white_pawn]);
01167 north_west_pawn& = Direction(north_west).from(index);
01168 if (north_west_pawn.test())
01169 {
01170 Index res(index_pre_begin);
01171 res.next_bit_in(north_west_pawn());
01172 result.reset(res);
01173 if (res.col() != 0)
01174 {
01175 res += north_west.offset;
01176 result.set(res);
01177 }
01178 }
01179 BitBoard north_east_pawn(M_bitboards[white_pawn]);
01180 north_east_pawn& = Direction(north_east).from(index);
01181 if (north_east_pawn.test())
01182 {
01183 Index res(index_pre_begin);
01184 res.next_bit_in(north_east_pawn());
01185 result.reset(res);
01186 if (res.col() != 7)
01187 {
01188 res += north_east.offset;
01189 result.set(res);
01190 }
01191 }
01192 }
01193 else
01194 {
01195 result.reset(M_bitboards[black_queen]);
01196 result.reset(M_bitboards[black_bishop]);
01197
01198 BitBoard south_west_pawn(M_bitboards[black_pawn]);
01199 south_west_pawn& = Direction(south_west).from(index);
01200 if (south_west_pawn.test())
01201 {
01202 Index res(index_end);
01203 res.prev_bit_in(south_west_pawn());
01204 result.reset(res);
01205 if (res.col() != 0)
01206 {
01207 res += south_west.offset;
01208 result.set(res);
01209 }
01210 }
01211 BitBoard south_east_pawn(M_bitboards[black_pawn]);
01212 south_east_pawn& = Direction(south_east).from(index);
01213 if (south_east_pawn.test())
01214 {
01215 Index res(index_end);
01216 res.prev_bit_in(south_east_pawn());
01217 result.reset(res);
01218 if (res.col() != 7)
01219 {
01220 res += south_east.offset;
01221 result.set(res);
01222 }
01223 }
01224 }
01225 return result;
01226 }
01227
01228 BitBoard ChessPosition::defendables(Code const& code, Index const& index, bool& battery) const
01229 {
01230 Color color = code.color();
01231 mask_t pos = index2mask(index);
01232 switch(code.type()())
01233 {
01234 case nothing_bits:
01235 {
01236 BitBoard result;
01237 result.reset();
01238 return result;
01239 }
01240 case pawn_bits:
01241 {
01242 int col = index.col();
01243 BitBoard result((color == white) ? (pos << 7) | (pos << 9) : (pos >> 9) | (pos >> 7));
01244 if (__builtin_expect(col == 0, false))
01245 result.reset(file_h);
01246 else if (__builtin_expect(col == 7, false))
01247 result.reset(file_a);
01248 return result;
01249 }
01250 case knight_bits:
01251 {
01252 BitBoard result(candidates_table[candidates_table_offset(knight) + index()]);
01253 return result;
01254 }
01255 case king_bits:
01256 {
01257 BitBoard result(candidates_table[candidates_table_offset(king) + index()]);
01258 return result;
01259 }
01260 case rook_bits:
01261 {
01262 BitBoard all_pieces_minus_rook_movers(M_bitboards[white] | M_bitboards[black]);
01263 Code queen_code(color, queen);
01264 Code rook_code(color, rook);
01265 BitBoard other_attackers(M_bitboards[queen_code] | M_bitboards[rook_code]);
01266 all_pieces_minus_rook_movers.reset(other_attackers);
01267
01268
01269 mask_t block = all_pieces_minus_rook_movers();
01270 mask_t probe = pos;
01271 mask_t reachables = 0;
01272 do
01273 {
01274 move(probe, up);
01275 reachables |= probe;
01276 }
01277 while((block & probe) != probe);
01278
01279
01280 probe = pos;
01281 do
01282 {
01283 move(probe, down);
01284 reachables |= probe;
01285 }
01286 while((block & probe) != probe);
01287
01288
01289 BitBoard result(reachables);
01290
01291
01292 block |= file_h.M_bitmask;
01293 probe = pos;
01294 do
01295 {
01296 move(probe, left);
01297 reachables |= probe;
01298 }
01299 while((block & probe) != probe);
01300 reachables& = ~file_h.M_bitmask;
01301
01302
01303 result |= reachables;
01304
01305
01306 block = all_pieces_minus_rook_movers() | file_a.M_bitmask;
01307 probe = pos;
01308 do
01309 {
01310 move(probe, right);
01311 reachables |= probe;
01312 }
01313 while((block & probe) != probe);
01314 reachables& = ~file_a.M_bitmask;
01315
01316 result |= reachables;
01317
01318
01319 BitBoard opposite_king_pos(M_bitboards[Code(color.opposite(), king)]);
01320 if (__builtin_expect(
01321 result.test(opposite_king_pos) &&
01322 result.test(other_attackers),
01323 false))
01324 {
01325
01326
01327 Index king_index(mask2index(opposite_king_pos()));
01328 Direction direction(direction_from_to(king_index, index));
01329 BitBoard line(direction.from(king_index));
01330 line& = result;
01331 line& = other_attackers;
01332 battery = line.test();
01333 }
01334
01335 return result;
01336 }
01337 case bishop_bits:
01338 {
01339 BitBoard all_pieces_minus_bishop_movers(this->all_pieces_minus_bishop_movers(color, index));
01340
01341
01342 mask_t block = all_pieces_minus_bishop_movers() | file_h.M_bitmask;
01343 mask_t probe = pos;
01344 mask_t reachables = 0;
01345 do
01346 {
01347 move(probe, down_left);
01348 reachables |= probe;
01349 }
01350 while((block & probe) != probe);
01351
01352
01353 probe = pos;
01354 do
01355 {
01356 move(probe, up_left);
01357 reachables |= probe;
01358 }
01359 while((block & probe) != probe);
01360 reachables& = ~file_h.M_bitmask;
01361
01362
01363 BitBoard result(reachables);
01364
01365
01366 block = all_pieces_minus_bishop_movers() | file_a.M_bitmask;
01367 probe = pos;
01368 do
01369 {
01370 move(probe, up_right);
01371 reachables |= probe;
01372 }
01373 while((block & probe) != probe);
01374
01375
01376 probe = pos;
01377 do
01378 {
01379 move(probe, down_right);
01380 reachables |= probe;
01381 }
01382 while((block & probe) != probe);
01383 reachables& = ~file_a.M_bitmask;
01384
01385 result |= reachables;
01386
01387
01388 BitBoard opposite_king_pos(M_bitboards[Code(color.opposite(), king)]);
01389 if (__builtin_expect(result.test(opposite_king_pos), false))
01390 {
01391 Code queen_code(color, queen);
01392 Code bishop_code(color, bishop);
01393 BitBoard other_attackers(M_bitboards[queen_code] | M_bitboards[bishop_code]);
01394 if (result.test(other_attackers))
01395 {
01396
01397
01398 Index king_index(mask2index(opposite_king_pos()));
01399 Direction direction(direction_from_to(king_index, index));
01400 BitBoard line(direction.from(king_index));
01401 line& = result;
01402 line& = other_attackers;
01403 battery = line.test();
01404 }
01405 }
01406
01407 return result;
01408 }
01409 case queen_bits:
01410 {
01411 BitBoard all_pieces_minus_bishop_movers(this->all_pieces_minus_bishop_movers(color, index));
01412 BitBoard all_pieces_minus_rook_movers(M_bitboards[white] | M_bitboards[black]);
01413 Code queen_code(color, queen);
01414 Code rook_code(color, rook);
01415 BitBoard other_rook_movers(M_bitboards[queen_code] | M_bitboards[rook_code]);
01416 all_pieces_minus_rook_movers.reset(other_rook_movers);
01417
01418
01419 mask_t block = all_pieces_minus_rook_movers();
01420 mask_t probe = pos;
01421 mask_t reachables = 0;
01422 do
01423 {
01424 move(probe, up);
01425 reachables |= probe;
01426 }
01427 while((block & probe) != probe);
01428
01429
01430 probe = pos;
01431 do
01432 {
01433 move(probe, down);
01434 reachables |= probe;
01435 }
01436 while((block & probe) != probe);
01437
01438
01439 BitBoard result(reachables);
01440
01441
01442 block |= file_h.M_bitmask;
01443 probe = pos;
01444 do
01445 {
01446 move(probe, left);
01447 reachables |= probe;
01448 }
01449 while((block & probe) != probe);
01450
01451
01452 block = all_pieces_minus_bishop_movers() | file_h.M_bitmask;
01453
01454
01455 probe = pos;
01456 do
01457 {
01458 move(probe, down_left);
01459 reachables |= probe;
01460 }
01461 while((block & probe) != probe);
01462
01463
01464 probe = pos;
01465 do
01466 {
01467 move(probe, up_left);
01468 reachables |= probe;
01469 }
01470 while((block & probe) != probe);
01471 reachables& = ~file_h.M_bitmask;
01472
01473
01474 result |= reachables;
01475
01476
01477 block = all_pieces_minus_rook_movers() | file_a.M_bitmask;
01478 probe = pos;
01479 do
01480 {
01481 move(probe, right);
01482 reachables |= probe;
01483 }
01484 while((block & probe) != probe);
01485
01486
01487 block = all_pieces_minus_bishop_movers() | file_a.M_bitmask;
01488
01489
01490 probe = pos;
01491 do
01492 {
01493 move(probe, up_right);
01494 reachables |= probe;
01495 }
01496 while((block & probe) != probe);
01497
01498
01499 probe = pos;
01500 do
01501 {
01502 move(probe, down_right);
01503 reachables |= probe;
01504 }
01505 while((block & probe) != probe);
01506 reachables& = ~file_a.M_bitmask;
01507
01508 result |= reachables;
01509
01510
01511 BitBoard opposite_king_pos(M_bitboards[Code(color.opposite(), king)]);
01512 if (__builtin_expect(result.test(opposite_king_pos), false))
01513 {
01514 Code queen_code(color, queen);
01515 Code bishop_code(color, bishop);
01516 BitBoard other_attackers(other_rook_movers | M_bitboards[queen_code] | M_bitboards[bishop_code]);
01517 if (result.test(other_attackers))
01518 {
01519
01520
01521 Index king_index(mask2index(opposite_king_pos()));
01522 Direction direction(direction_from_to(king_index, index));
01523 BitBoard line(direction.from(king_index));
01524 line& = result;
01525 line& = other_attackers;
01526 battery = line.test();
01527 }
01528 }
01529
01530 return result;
01531 }
01532 }
01533 return BitBoard();
01534 }
01535
01536
01537
01538
01539 void ChessPosition::update_blocked_defendables(Code const& code, Index const& index, bool add)
01540 {
01541
01542 BitBoard const all_pieces(M_bitboards[white] | M_bitboards[black]);
01543
01544 BitBoard blocked_rookmovers(M_bitboards[black_rook] | M_bitboards[black_queen] | M_bitboards[white_rook] | M_bitboards[white_queen]);
01545
01546 BitBoard blocked_bishopmovers(M_bitboards[black_bishop] | M_bitboards[black_queen] | M_bitboards[white_bishop] | M_bitboards[white_queen]);
01547
01548
01549
01550 if (code.is_a_slider())
01551 {
01552 Color color(code.color());
01553 Code queen_code(color, queen);
01554
01555 if (code.is_a_rookmover())
01556 {
01557
01558 Code rook_code(color, rook);
01559 blocked_rookmovers.reset(M_bitboards[rook_code] | M_bitboards[queen_code]);
01560 }
01561 if (code.is_a_bishopmover())
01562 {
01563
01564 Code bishop_code(color, bishop);
01565 blocked_bishopmovers.reset(M_bitboards[bishop_code] | M_bitboards[queen_code]);
01566 }
01567 }
01568
01569
01570
01571
01572
01573
01574
01575 ArrayColor<BitBoard> result;
01576 result[black].reset();
01577 result[white].reset();
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600 BitBoard line(north.from(index));
01601
01602
01603
01604 line& = all_pieces;
01605
01606
01607
01608
01609 Index blocked_piece(index_pre_begin);
01610
01611
01612
01613
01614 blocked_piece.next_bit_in(line());
01615
01616
01617
01618
01619
01620 if (__builtin_expect(blocked_piece != index_end&&
01621 blocked_rookmovers.test(blocked_piece), false))
01622 {
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632 Color blocked_piece_color(M_pieces[blocked_piece].color());
01633 Code rook_code(blocked_piece_color, rook);
01634 Code queen_code(blocked_piece_color, queen);
01635 BitBoard rookmovers_of_same_color(M_bitboards[rook_code] | M_bitboards[queen_code]);
01636
01637
01638
01639 BitBoard all_blockers(all_pieces);
01640
01641
01642
01643
01644
01645 all_blockers.reset(rookmovers_of_same_color);
01646
01647
01648
01649 BitBoard opposite_line(south.from(index));
01650
01651
01652
01653 all_blockers& = opposite_line;
01654
01655
01656
01657
01658 Index current_blocker(index_end);
01659 current_blocker.prev_bit_in(all_blockers());
01660
01661
01662
01663
01664 BitBoard blocked_squares(opposite_line);
01665
01666
01667
01668 if (current_blocker != index_pre_begin)
01669 blocked_squares.reset(south.from(current_blocker));
01670
01671
01672 if (blocked_squares)
01673 {
01674
01675 result[blocked_piece_color] |= blocked_squares;
01676
01677
01678
01679
01680 Code king_code(blocked_piece_color.opposite(), king);
01681 bool king_attack = M_bitboards[king_code].test(blocked_squares);
01682 if (__builtin_expect(king_attack && blocked_squares.test(rookmovers_of_same_color), false))
01683 {
01684 if (add)
01685 ++M_king_battery_attack_count[blocked_piece_color];
01686 else
01687 --M_king_battery_attack_count[blocked_piece_color];
01688 }
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701 for (blocked_piece.next_bit_in(line());
01702 blocked_piece != index_end && rookmovers_of_same_color.test(blocked_piece);
01703 blocked_piece.next_bit_in(line()))
01704 {
01705 if (add)
01706 M_defended[blocked_piece_color].add(blocked_squares);
01707 else
01708 M_defended[blocked_piece_color].sub(blocked_squares);
01709 if (king_attack)
01710 {
01711 if (add)
01712 ++M_king_battery_attack_count[blocked_piece_color];
01713 else
01714 --M_king_battery_attack_count[blocked_piece_color];
01715 }
01716 }
01717 }
01718 }
01719
01720
01721 line = south.from(index);
01722 line& = all_pieces;
01723 blocked_piece = index_end;
01724 blocked_piece.prev_bit_in(line());
01725 if (__builtin_expect(blocked_piece != index_pre_begin && blocked_rookmovers.test(blocked_piece), false))
01726 {
01727
01728 Color blocked_piece_color(M_pieces[blocked_piece].color());
01729 Code rook_code(blocked_piece_color, rook);
01730 Code queen_code(blocked_piece_color, queen);
01731 BitBoard rookmovers_of_same_color(M_bitboards[rook_code] | M_bitboards[queen_code]);
01732
01733 BitBoard all_blockers(all_pieces);
01734 all_blockers.reset(rookmovers_of_same_color);
01735 BitBoard opposite_line(north.from(index));
01736 all_blockers& = opposite_line;
01737 Index current_blocker(index_pre_begin);
01738 current_blocker.next_bit_in(all_blockers());
01739 BitBoard blocked_squares(opposite_line);
01740 if (current_blocker != index_end)
01741 blocked_squares.reset(north.from(current_blocker));
01742
01743
01744 if (blocked_squares)
01745 {
01746 result[blocked_piece_color] |= blocked_squares;
01747 Code king_code(blocked_piece_color.opposite(), king);
01748 bool king_attack = M_bitboards[king_code].test(blocked_squares);
01749 if (__builtin_expect(king_attack && blocked_squares.test(rookmovers_of_same_color), false))
01750 {
01751 if (add)
01752 ++M_king_battery_attack_count[blocked_piece_color];
01753 else
01754 --M_king_battery_attack_count[blocked_piece_color];
01755 }
01756 if (blocked_piece != index_begin)
01757 {
01758 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()))
01759 {
01760 if (add)
01761 M_defended[blocked_piece_color].add(blocked_squares);
01762 else
01763 M_defended[blocked_piece_color].sub(blocked_squares);
01764 if (king_attack)
01765 {
01766 if (add)
01767 ++M_king_battery_attack_count[blocked_piece_color];
01768 else
01769 --M_king_battery_attack_count[blocked_piece_color];
01770 }
01771 if (blocked_piece == index_begin)
01772 break;
01773 }
01774 }
01775 }
01776 }
01777
01778
01779 line = east.from(index);
01780 line& = all_pieces;
01781 blocked_piece = index_pre_begin;
01782 blocked_piece.next_bit_in(line());
01783 if (__builtin_expect(blocked_piece != index_end && blocked_rookmovers.test(blocked_piece), false))
01784 {
01785
01786 Color blocked_piece_color(M_pieces[blocked_piece].color());
01787 Code rook_code(blocked_piece_color, rook);
01788 Code queen_code(blocked_piece_color, queen);
01789 BitBoard rookmovers_of_same_color(M_bitboards[rook_code] | M_bitboards[queen_code]);
01790
01791 BitBoard all_blockers(all_pieces);
01792 all_blockers.reset(rookmovers_of_same_color);
01793 BitBoard opposite_line(west.from(index));
01794 all_blockers& = opposite_line;
01795 Index current_blocker(index_end);
01796 current_blocker.prev_bit_in(all_blockers());
01797 BitBoard blocked_squares(opposite_line);
01798 if (current_blocker != index_pre_begin)
01799 blocked_squares.reset(west.from(current_blocker));
01800
01801 if (blocked_squares)
01802 {
01803 result[blocked_piece_color] |= blocked_squares;
01804 Code king_code(blocked_piece_color.opposite(), king);
01805 bool king_attack = M_bitboards[king_code].test(blocked_squares);
01806 if (__builtin_expect(king_attack && blocked_squares.test(rookmovers_of_same_color), false))
01807 {
01808 if (add)
01809 ++M_king_battery_attack_count[blocked_piece_color];
01810 else
01811 --M_king_battery_attack_count[blocked_piece_color];
01812 }
01813 for (blocked_piece.next_bit_in(line()); blocked_piece != index_end && rookmovers_of_same_color.test(blocked_piece); blocked_piece.next_bit_in(line()))
01814 {
01815 if (add)
01816 M_defended[blocked_piece_color].add(blocked_squares);
01817 else
01818 M_defended[blocked_piece_color].sub(blocked_squares);
01819 if (king_attack)
01820 {
01821 if (add)
01822 ++M_king_battery_attack_count[blocked_piece_color];
01823 else
01824 --M_king_battery_attack_count[blocked_piece_color];
01825 }
01826 }
01827 }
01828 }
01829
01830
01831 line = west.from(index);
01832 line& = all_pieces;
01833 blocked_piece = index_end;
01834 blocked_piece.prev_bit_in(line());
01835 if (__builtin_expect(blocked_piece != index_pre_begin && blocked_rookmovers.test(blocked_piece), false))
01836 {
01837
01838 Color blocked_piece_color(M_pieces[blocked_piece].color());
01839 Code rook_code(blocked_piece_color, rook);
01840 Code queen_code(blocked_piece_color, queen);
01841 BitBoard rookmovers_of_same_color(M_bitboards[rook_code] | M_bitboards[queen_code]);
01842
01843 BitBoard all_blockers(all_pieces);
01844 all_blockers.reset(rookmovers_of_same_color);
01845 BitBoard opposite_line(east.from(index));
01846 all_blockers& = opposite_line;
01847 Index current_blocker(index_pre_begin);
01848 current_blocker.next_bit_in(all_blockers());
01849 BitBoard blocked_squares(opposite_line);
01850 if (current_blocker != index_end)
01851 blocked_squares.reset(east.from(current_blocker));
01852
01853 if (blocked_squares)
01854 {
01855 result[blocked_piece_color] |= blocked_squares;
01856 Code king_code(blocked_piece_color.opposite(), king);
01857 bool king_attack = M_bitboards[king_code].test(blocked_squares);
01858 if (__builtin_expect(king_attack && blocked_squares.test(rookmovers_of_same_color), false))
01859 {
01860 if (add)
01861 ++M_king_battery_attack_count[blocked_piece_color];
01862 else
01863 --M_king_battery_attack_count[blocked_piece_color];
01864 }
01865 if (blocked_piece != index_begin)
01866 {
01867 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()))
01868 {
01869 if (add)
01870 M_defended[blocked_piece_color].add(blocked_squares);
01871 else
01872 M_defended[blocked_piece_color].sub(blocked_squares);
01873 if (king_attack)
01874 {
01875 if (add)
01876 ++M_king_battery_attack_count[blocked_piece_color];
01877 else
01878 --M_king_battery_attack_count[blocked_piece_color];
01879 }
01880 if (blocked_piece == index_begin)
01881 break;
01882 }
01883 }
01884 }
01885 }
01886
01887
01888 line = north_west.from(index);
01889 line& = all_pieces;
01890 blocked_piece = index_pre_begin;
01891 blocked_piece.next_bit_in(line());
01892 if (__builtin_expect(blocked_piece != index_end && blocked_bishopmovers.test(blocked_piece), false))
01893 {
01894
01895 Color blocked_piece_color(M_pieces[blocked_piece].color());
01896 Code bishop_code(blocked_piece_color, bishop);
01897 Code queen_code(blocked_piece_color, queen);
01898 BitBoard bishopmovers_of_same_color(M_bitboards[bishop_code] | M_bitboards[queen_code]);
01899
01900 BitBoard all_blockers(all_pieces);
01901 all_blockers.reset(bishopmovers_of_same_color);
01902 BitBoard opposite_line(south_east.from(index));
01903 all_blockers& = opposite_line;
01904 Index current_blocker(index_end);
01905 current_blocker.prev_bit_in(all_blockers());
01906 BitBoard blocked_squares(opposite_line);
01907 if (current_blocker != index_pre_begin)
01908 blocked_squares.reset(south_east.from(current_blocker));
01909
01910 if (blocked_squares)
01911 {
01912 if (__builtin_expect(code == black_pawn, false) && blocked_piece_color == black)
01913 blocked_squares.reset(index + south_east.offset);
01914 result[blocked_piece_color] |= blocked_squares;
01915 Code king_code(blocked_piece_color.opposite(), king);
01916 bool king_attack = M_bitboards[king_code].test(blocked_squares);
01917 if (__builtin_expect(king_attack && blocked_squares.test(bishopmovers_of_same_color), false))
01918 {
01919 if (add)
01920 ++M_king_battery_attack_count[blocked_piece_color];
01921 else
01922 --M_king_battery_attack_count[blocked_piece_color];
01923 }
01924 for (blocked_piece.next_bit_in(line()); blocked_piece != index_end && bishopmovers_of_same_color.test(blocked_piece); blocked_piece.next_bit_in(line()))
01925 {
01926 if (add)
01927 M_defended[blocked_piece_color].add(blocked_squares);
01928 else
01929 M_defended[blocked_piece_color].sub(blocked_squares);
01930 if (king_attack)
01931 {
01932 if (add)
01933 ++M_king_battery_attack_count[blocked_piece_color];
01934 else
01935 --M_king_battery_attack_count[blocked_piece_color];
01936 }
01937 }
01938 }
01939 }
01940
01941
01942 line = south_east.from(index);
01943 line& = all_pieces;
01944 blocked_piece = index_end;
01945 blocked_piece.prev_bit_in(line());
01946 if (__builtin_expect(blocked_piece != index_pre_begin && blocked_bishopmovers.test(blocked_piece), false))
01947 {
01948
01949 Color blocked_piece_color(M_pieces[blocked_piece].color());
01950 Code bishop_code(blocked_piece_color, bishop);
01951 Code queen_code(blocked_piece_color, queen);
01952 BitBoard bishopmovers_of_same_color(M_bitboards[bishop_code] | M_bitboards[queen_code]);
01953
01954 BitBoard all_blockers(all_pieces);
01955 all_blockers.reset(bishopmovers_of_same_color);
01956 BitBoard opposite_line(north_west.from(index));
01957 all_blockers& = opposite_line;
01958 Index current_blocker(index_pre_begin);
01959 current_blocker.next_bit_in(all_blockers());
01960 BitBoard blocked_squares(opposite_line);
01961 if (current_blocker != index_end)
01962 blocked_squares.reset(north_west.from(current_blocker));
01963
01964 if (blocked_squares)
01965 {
01966 if (__builtin_expect(code == white_pawn, false) && blocked_piece_color == white)
01967 blocked_squares.reset(index + north_west.offset);
01968 result[blocked_piece_color] |= blocked_squares;
01969 Code king_code(blocked_piece_color.opposite(), king);
01970 bool king_attack = M_bitboards[king_code].test(blocked_squares);
01971 if (__builtin_expect(king_attack && blocked_squares.test(bishopmovers_of_same_color), false))
01972 {
01973 if (add)
01974 ++M_king_battery_attack_count[blocked_piece_color];
01975 else
01976 --M_king_battery_attack_count[blocked_piece_color];
01977 }
01978 if (blocked_piece != index_begin)
01979 {
01980 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()))
01981 {
01982 if (add)
01983 M_defended[blocked_piece_color].add(blocked_squares);
01984 else
01985 M_defended[blocked_piece_color].sub(blocked_squares);
01986 if (king_attack)
01987 {
01988 if (add)
01989 ++M_king_battery_attack_count[blocked_piece_color];
01990 else
01991 --M_king_battery_attack_count[blocked_piece_color];
01992 }
01993 if (blocked_piece == index_begin)
01994 break;
01995 }
01996 }
01997 }
01998 }
01999
02000
02001 line = north_east.from(index);
02002 line& = all_pieces;
02003 blocked_piece = index_pre_begin;
02004 blocked_piece.next_bit_in(line());
02005 if (__builtin_expect(blocked_piece != index_end && blocked_bishopmovers.test(blocked_piece), false))
02006 {
02007
02008 Color blocked_piece_color(M_pieces[blocked_piece].color());
02009 Code bishop_code(blocked_piece_color, bishop);
02010 Code queen_code(blocked_piece_color, queen);
02011 BitBoard bishopmovers_of_same_color(M_bitboards[bishop_code] | M_bitboards[queen_code]);
02012
02013 BitBoard all_blockers(all_pieces);
02014 all_blockers.reset(bishopmovers_of_same_color);
02015 BitBoard opposite_line(south_west.from(index));
02016 all_blockers& = opposite_line;
02017 Index current_blocker(index_end);
02018 current_blocker.prev_bit_in(all_blockers());
02019 BitBoard blocked_squares(opposite_line);
02020 if (current_blocker != index_pre_begin)
02021 blocked_squares.reset(south_west.from(current_blocker));
02022
02023 if (blocked_squares)
02024 {
02025 if (__builtin_expect(code == black_pawn, false) && blocked_piece_color == black)
02026 blocked_squares.reset(index + south_west.offset);
02027 result[blocked_piece_color] |= blocked_squares;
02028 Code king_code(blocked_piece_color.opposite(), king);
02029 bool king_attack = M_bitboards[king_code].test(blocked_squares);
02030 if (__builtin_expect(king_attack && blocked_squares.test(bishopmovers_of_same_color), false))
02031 {
02032 if (add)
02033 ++M_king_battery_attack_count[blocked_piece_color];
02034 else
02035 --M_king_battery_attack_count[blocked_piece_color];
02036 }
02037 for (blocked_piece.next_bit_in(line()); blocked_piece != index_end && bishopmovers_of_same_color.test(blocked_piece); blocked_piece.next_bit_in(line()))
02038 {
02039 if (add)
02040 M_defended[blocked_piece_color].add(blocked_squares);
02041 else
02042 M_defended[blocked_piece_color].sub(blocked_squares);
02043 if (king_attack)
02044 {
02045 if (add)
02046 ++M_king_battery_attack_count[blocked_piece_color];
02047 else
02048 --M_king_battery_attack_count[blocked_piece_color];
02049 }
02050 }
02051 }
02052 }
02053
02054
02055 line = south_west.from(index);
02056 line& = all_pieces;
02057 blocked_piece = index_end;
02058 blocked_piece.prev_bit_in(line());
02059 if (__builtin_expect(blocked_piece != index_pre_begin && blocked_bishopmovers.test(blocked_piece), false))
02060 {
02061
02062 Color blocked_piece_color(M_pieces[blocked_piece].color());
02063 Code bishop_code(blocked_piece_color, bishop);
02064 Code queen_code(blocked_piece_color, queen);
02065 BitBoard bishopmovers_of_same_color(M_bitboards[bishop_code] | M_bitboards[queen_code]);
02066
02067 BitBoard all_blockers(all_pieces);
02068 all_blockers.reset(bishopmovers_of_same_color);
02069 BitBoard opposite_line(north_east.from(index));
02070 all_blockers& = opposite_line;
02071 Index current_blocker(index_pre_begin);
02072 current_blocker.next_bit_in(all_blockers());
02073 BitBoard blocked_squares(opposite_line);
02074 if (current_blocker != index_end)
02075 blocked_squares.reset(north_east.from(current_blocker));
02076
02077 if (blocked_squares)
02078 {
02079 if (__builtin_expect(code == white_pawn, false) && blocked_piece_color == white)
02080 blocked_squares.reset(index + north_east.offset);
02081 result[blocked_piece_color] |= blocked_squares;
02082 Code king_code(blocked_piece_color.opposite(), king);
02083 bool king_attack = M_bitboards[king_code].test(blocked_squares);
02084 if (__builtin_expect(king_attack && blocked_squares.test(bishopmovers_of_same_color), false))
02085 {
02086 if (add)
02087 ++M_king_battery_attack_count[blocked_piece_color];
02088 else
02089 --M_king_battery_attack_count[blocked_piece_color];
02090 }
02091 if (blocked_piece != index_begin)
02092 {
02093 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()))
02094 {
02095 if (add)
02096 M_defended[blocked_piece_color].add(blocked_squares);
02097 else
02098 M_defended[blocked_piece_color].sub(blocked_squares);
02099 if (king_attack)
02100 {
02101 if (add)
02102 ++M_king_battery_attack_count[blocked_piece_color];
02103 else
02104 --M_king_battery_attack_count[blocked_piece_color];
02105 }
02106 if (blocked_piece == index_begin)
02107 break;
02108 }
02109 }
02110 }
02111 }
02112
02113
02114 if (BitBoard black_result = result[black])
02115 {
02116 if (add)
02117 M_defended[black].add(black_result);
02118 else
02119 M_defended[black].sub(black_result);
02120 }
02121 if (BitBoard white_result = result[white])
02122 {
02123 if (add)
02124 M_defended[white].add(white_result);
02125 else
02126 M_defended[white].sub(white_result);
02127 }
02128 }
02129
02130 BitBoard ChessPosition::reachables(Index const& index, bool attacked_squares) const
02131 {
02132 BitBoard all_pieces(M_bitboards[white] | M_bitboards[black]);
02133 Piece piece(M_pieces[index]);
02134 Color color = piece.color();
02135 mask_t pos = index2mask(index);
02136 switch(piece.type()())
02137 {
02138 case nothing_bits:
02139 {
02140 BitBoard result;
02141 result.reset();
02142 return result;
02143 }
02144 case pawn_bits:
02145 {
02146 if (attacked_squares)
02147 {
02148 BitBoard result((color == white) ? (pos << 7) | (pos << 9) : (pos >> 9) | (pos >> 7));
02149 result.reset(M_bitboards[color]);
02150 int col = index.col();
02151 if (__builtin_expect(col == 0, false))
02152 result.reset(file_h);
02153 else if (__builtin_expect(col == 7, false))
02154 result.reset(file_a);
02155 return result;
02156 }
02157 return candidates(index);
02158 }
02159 case rook_bits:
02160 {
02161
02162 mask_t block = all_pieces();
02163 mask_t probe = pos;
02164 mask_t reachables = 0;
02165 do
02166 {
02167 move(probe, up);
02168 reachables |= probe;
02169 }
02170 while((block & probe) != probe);
02171
02172
02173 probe = pos;
02174 do
02175 {
02176 move(probe, down);
02177 reachables |= probe;
02178 }
02179 while((block & probe) != probe);
02180
02181
02182 BitBoard result(reachables);
02183
02184
02185 block |= file_h.M_bitmask;
02186 probe = pos;
02187 do
02188 {
02189 move(probe, left);
02190 reachables |= probe;
02191 }
02192 while((block & probe) != probe);
02193 reachables& = ~file_h.M_bitmask;
02194
02195
02196 result |= reachables;
02197
02198
02199 block = all_pieces() | file_a.M_bitmask;
02200 probe = pos;
02201 do
02202 {
02203 move(probe, right);
02204 reachables |= probe;
02205 }
02206 while((block & probe) != probe);
02207 reachables& = ~file_a.M_bitmask;
02208
02209 result |= reachables;
02210 result.reset(M_bitboards[color]);
02211 return result;
02212 }
02213 case knight_bits:
02214 {
02215 BitBoard result(candidates_table[candidates_table_offset(knight) + index()]);
02216 result.reset(M_bitboards[color]);
02217 return result;
02218 }
02219 case bishop_bits:
02220 {
02221
02222 mask_t block = all_pieces() | file_h.M_bitmask;
02223 mask_t probe = pos;
02224 mask_t reachables = 0;
02225 do
02226 {
02227 move(probe, down_left);
02228 reachables |= probe;
02229 }
02230 while((block & probe) != probe);
02231
02232
02233 probe = pos;
02234 do
02235 {
02236 move(probe, up_left);
02237 reachables |= probe;
02238 }
02239 while((block & probe) != probe);
02240 reachables& = ~file_h.M_bitmask;
02241
02242
02243 BitBoard result(reachables);
02244
02245
02246 block = all_pieces() | file_a.M_bitmask;
02247 probe = pos;
02248 do
02249 {
02250 move(probe, up_right);
02251 reachables |= probe;
02252 }
02253 while((block & probe) != probe);
02254
02255
02256 probe = pos;
02257 do
02258 {
02259 move(probe, down_right);
02260 reachables |= probe;
02261 }
02262 while((block & probe) != probe);
02263 reachables& = ~file_a.M_bitmask;
02264
02265 result |= reachables;
02266 result.reset(M_bitboards[color]);
02267 return result;
02268 }
02269 case queen_bits:
02270 {
02271
02272 mask_t block = all_pieces();
02273 mask_t probe = pos;
02274 mask_t reachables = 0;
02275 do
02276 {
02277 move(probe, up);
02278 reachables |= probe;
02279 }
02280 while((block & probe) != probe);
02281
02282
02283 probe = pos;
02284 do
02285 {
02286 move(probe, down);
02287 reachables |= probe;
02288 }
02289 while((block & probe) != probe);
02290
02291
02292 BitBoard result(reachables);
02293
02294
02295 block |= file_h.M_bitmask;
02296 probe = pos;
02297 do
02298 {
02299 move(probe, left);
02300 reachables |= probe;
02301 }
02302 while((block & probe) != probe);
02303
02304
02305 probe = pos;
02306 do
02307 {
02308 move(probe, down_left);
02309 reachables |= probe;
02310 }
02311 while((block & probe) != probe);
02312
02313
02314 probe = pos;
02315 do
02316 {
02317 move(probe, up_left);
02318 reachables |= probe;
02319 }
02320 while((block & probe) != probe);
02321 reachables& = ~file_h.M_bitmask;
02322
02323
02324 result |= reachables;
02325
02326
02327 block = all_pieces() | file_a.M_bitmask;
02328 probe = pos;
02329 do
02330 {
02331 move(probe, right);
02332 reachables |= probe;
02333 }
02334 while((block & probe) != probe);
02335
02336
02337 probe = pos;
02338 do
02339 {
02340 move(probe, up_right);
02341 reachables |= probe;
02342 }
02343 while((block & probe) != probe);
02344
02345
02346 probe = pos;
02347 do
02348 {
02349 move(probe, down_right);
02350 reachables |= probe;
02351 }
02352 while((block & probe) != probe);
02353 reachables& = ~file_a.M_bitmask;
02354
02355 result |= reachables;
02356 result.reset(M_bitboards[color]);
02357 return result;
02358 }
02359 case king_bits:
02360 {
02361 BitBoard result(candidates_table[candidates_table_offset(king) + index()]);
02362 result.reset(M_bitboards[color]);
02363 if (attacked_squares || !M_castle_flags.can_castle(color))
02364 return result;
02365 BitBoard long_castle_squares(0), short_castle_squares(0);
02366 bool can_castle_long = false, can_castle_short = false;
02367 if (M_castle_flags.can_castle_short(color))
02368 {
02369 short_castle_squares = BitBoard((color == white) ? f1|g1 : f8|g8);
02370 if (!(all_pieces & short_castle_squares))
02371 {
02372 can_castle_short = true;
02373 short_castle_squares.reset(f1|f8);
02374 }
02375 }
02376 if (M_castle_flags.can_castle_long(color))
02377 {
02378 long_castle_squares = BitBoard((color == white) ? b1|c1|d1 : b8|c8|d8);
02379 if (!(all_pieces & long_castle_squares))
02380 {
02381 can_castle_long = true;
02382 long_castle_squares.reset(b1|b8|d1|d8);
02383 }
02384 }
02385 if (can_castle_short || can_castle_long)
02386 {
02387
02388 BitBoard attacked_squares;
02389 attacked_squares.reset();
02390 for (PieceIterator iter = piece_begin(color.opposite()); iter != piece_end(); ++iter)
02391 attacked_squares |= reachables(iter.index(), true);
02392 if (can_castle_short && !(attacked_squares & ((color == white) ? (e1|f1|g1) : (e8|f8|g8))))
02393 result |= short_castle_squares;
02394 if (can_castle_long && !(attacked_squares & ((color == white) ? (c1|d1|e1) : (c8|d8|e8))))
02395 result |= long_castle_squares;
02396 }
02397 return result;
02398 }
02399 }
02400 return BitBoard();
02401 }
02402
02403 BitBoard ChessPosition::moves(Index const& index) const
02404 {
02405 Code code(M_pieces[index].code());
02406 Color color(code.color());
02407
02408 BitBoard reachables(this->reachables(index));
02409
02410
02411
02412 if (__builtin_expect(color == M_to_move && M_castle_flags.in_check(M_to_move), false))
02413 {
02414 bool is_king = code.is_a(king);
02415
02416 if (__builtin_expect(M_double_check && !is_king, false))
02417 return BitBoard((mask_t)0);
02418
02419
02420 BitBoard attacker_squares;
02421 attacker_squares.reset();
02422 Code king_code(color, king);
02423 BitBoard king_pos(M_bitboards[king_code]);
02424 Index king_index(mask2index(king_pos()));
02425 if (__builtin_expect(!M_double_check && !is_king, true))
02426 {
02427 if (color == black)
02428 {
02429 BitBoard queenside_pawn(king_pos() >> 9);
02430 BitBoard kingside_pawn(king_pos() >> 7);
02431 queenside_pawn.reset(file_h);
02432 kingside_pawn.reset(file_a);
02433 attacker_squares = (queenside_pawn | kingside_pawn) & M_bitboards[white_pawn];
02434 attacker_squares |= candidates_table[candidates_table_offset(knight) + king_index()] & M_bitboards[white_knight];
02435 }
02436 else
02437 {
02438 BitBoard queenside_pawn(king_pos() << 7);
02439 BitBoard kingside_pawn(king_pos() << 9);
02440 queenside_pawn.reset(file_h);
02441 kingside_pawn.reset(file_a);
02442 attacker_squares = (queenside_pawn | kingside_pawn) & M_bitboards[black_pawn];
02443 attacker_squares |= candidates_table[candidates_table_offset(knight) + king_index()] & M_bitboards[black_knight];
02444 }
02445 }
02446
02447
02448 if (!attacker_squares)
02449 {
02450 BitBoard const all_pieces(M_bitboards[white] | M_bitboards[black]);
02451 Color opposite_color(color.opposite());
02452 Code rook_code(opposite_color, rook);
02453 Code queen_code(opposite_color, queen);
02454 BitBoard rookmovers(candidates_table[candidates_table_offset(rook) + king_index()] & (M_bitboards[rook_code] | M_bitboards[queen_code]));
02455 for (PieceIterator piece_iter(this, rookmovers); piece_iter != piece_end(); ++piece_iter)
02456 {
02457 Direction const& direction(direction_from_to(king_index, piece_iter.index()));
02458 BitBoard line(squares_from_to(piece_iter.index(), king_index));
02459 if ((line & all_pieces) == BitBoard(piece_iter.index()))
02460 {
02461
02462 if (is_king)
02463 {
02464
02465 Index one_step_away_from_attacker(king_index - direction);
02466
02467 if (one_step_away_from_attacker() < 64)
02468 reachables.reset(one_step_away_from_attacker);
02469 }
02470 else
02471 attacker_squares |= line;
02472 break;
02473 }
02474 }
02475 if (M_double_check || !attacker_squares)
02476 {
02477 Code bishop_code(opposite_color, bishop);
02478 BitBoard bishopmovers(candidates_table[candidates_table_offset(bishop) + king_index()] & (M_bitboards[bishop_code] | M_bitboards[queen_code]));
02479 for (PieceIterator piece_iter(this, bishopmovers); piece_iter != piece_end(); ++piece_iter)
02480 {
02481 Direction const& direction(direction_from_to(king_index, piece_iter.index()));
02482 BitBoard line(squares_from_to(piece_iter.index(), king_index));
02483 if ((line & all_pieces) == piece_iter.index())
02484 {
02485
02486 if (is_king)
02487 {
02488 Index one_step_away_from_attacker(king_index - direction);
02489 if (one_step_away_from_attacker() < 64)
02490 reachables.reset(one_step_away_from_attacker);
02491 }
02492 else
02493 attacker_squares |= line;
02494 break;
02495 }
02496 }
02497 }
02498 }
02499 if (!is_king)
02500 {
02501
02502 reachables& = attacker_squares;
02503 }
02504 }
02505 BitBoard pinning(M_pinning[color]);
02506 if (__builtin_expect(pinning.test(index), false))
02507 {
02508
02509 if (code.is_a(pawn))
02510 reachables& = pinning;
02511 else
02512 {
02513 Index king_index(index_of_king(color));
02514 Direction direction(direction_from_to(king_index, index));
02515 BitBoard line(direction.from(king_index));
02516 reachables& = line;
02517 }
02518 }
02519 if (__builtin_expect(M_en_passant.exists() && M_en_passant.pinned() && code.is_a(pawn), false))
02520 reachables.reset(M_en_passant.index());
02521 if (__builtin_expect(code.is_a(king), false))
02522 reachables.reset(M_defended[color.opposite()].any());
02523
02524 return reachables;
02525 }
02526
02527 bool ChessPosition::legal(Move const& move) const
02528 {
02529 Index from(move.from());
02530 Index to(move.to());
02531
02532 if (to() > 63 || from() > 63)
02533 return false;
02534 BitBoard from_pos(from);
02535 BitBoard to_pos(to);
02536 Piece const& piece(M_pieces[from]);
02537
02538 if (piece.code().is_nothing() || piece.color() != M_to_move)
02539 return false;
02540 bool is_pawn_promotion = piece.code().is_a(pawn) && (to.row() == 0 || to.row() == 7);
02541
02542 if (is_pawn_promotion)
02543 {
02544 Type promotion_type(move.promotion_type());
02545 if (promotion_type != rook && promotion_type != knight && promotion_type != bishop && promotion_type != queen)
02546 return false;
02547 }
02548 else if (move.promotion_type() != nothing)
02549 return false;
02550
02551 return moves(from).test(to_pos);
02552 }
02553
02554 bool ChessPosition::execute(Move const& move)
02555 {
02556 BitBoard from_pos(move.from());
02557 BitBoard to_pos(move.to());
02558 BitBoard all_pieces(M_bitboards[black] | M_bitboards[white]);
02559 bool pawn_move = (from_pos & M_bitboards[Code(M_to_move, pawn)]);
02560 bool pawn_advance_or_capture = pawn_move | !!(to_pos & all_pieces);
02561
02562 if (__builtin_expect(M_en_passant.exists(), false))
02563 {
02564 if (pawn_move && M_en_passant.index() == move.to())
02565 {
02566
02567
02568 place(Code(), M_en_passant.pawn_index());
02569 }
02570 else
02571 {
02572
02573 clear_en_passant();
02574 }
02575 }
02576
02577 if (pawn_move)
02578 {
02579 uint8_t offset = move.to()() - move.from()();
02580 bool pawn_advanced_two_squares = !(offset & 0xf);
02581 if (pawn_advanced_two_squares)
02582 {
02583
02584
02585 IndexData passed_square = { move.to()() ^ 8 };
02586 set_en_passant(passed_square);
02587
02588 M_to_move.toggle();
02589 }
02590 }
02591
02592
02593 CastleFlags castle_flags(M_castle_flags);
02594 Piece piece(M_pieces[move.from()]);
02595 place(Code(), move.from());
02596 if (move.is_promotion())
02597 place(Code(M_to_move, move.promotion_type()), move.to());
02598 else
02599 {
02600 place(piece.code(), move.to());
02601
02602 uint8_t col_diff = move.to().col() - move.from().col();
02603 if (__builtin_expect(piece.code().is_a(king), false) && __builtin_expect(col_diff && !(col_diff & 1), false))
02604 {
02605 IndexData rook_from = { move.from()() - 4 + 7 * (2 + move.to()() - move.from()()) / 4 };
02606 IndexData rook_to = { move.from()() + (move.to()() - move.from()()) / 2 };
02607 place(Code(), rook_from);
02608 place(Code(M_to_move, rook), rook_to);
02609 }
02610 }
02611
02612
02613 M_to_move.toggle();
02614
02615
02616 bool in_check = M_castle_flags.in_check(M_to_move);
02617 M_castle_flags = castle_flags;
02618 M_castle_flags.set_check(M_to_move, in_check);
02619 M_castle_flags.piece_moved_from(piece, move.from());
02620
02621
02622 M_double_check = M_castle_flags.in_check(M_to_move) ? double_check(M_to_move) : false;
02623
02624 return increment_counters(pawn_advance_or_capture);
02625 }
02626
02627 BitBoardData ChessPosition::candidates_table[5 * 64] = {
02628
02629 { CW_MASK_T_CONST(0x0000000000020400)}, { CW_MASK_T_CONST(0x0000000000050800)}, { CW_MASK_T_CONST(0x00000000000a1100)}, { CW_MASK_T_CONST(0x0000000000142200)},
02630 { CW_MASK_T_CONST(0x0000000000284400)}, { CW_MASK_T_CONST(0x0000000000508800)}, { CW_MASK_T_CONST(0x0000000000a01000)}, { CW_MASK_T_CONST(0x0000000000402000)},
02631 { CW_MASK_T_CONST(0x0000000002040004)}, { CW_MASK_T_CONST(0x0000000005080008)}, { CW_MASK_T_CONST(0x000000000a110011)}, { CW_MASK_T_CONST(0x0000000014220022)},
02632 { CW_MASK_T_CONST(0x0000000028440044)}, { CW_MASK_T_CONST(0x0000000050880088)}, { CW_MASK_T_CONST(0x00000000a0100010)}, { CW_MASK_T_CONST(0x0000000040200020)},
02633 { CW_MASK_T_CONST(0x0000000204000402)}, { CW_MASK_T_CONST(0x0000000508000805)}, { CW_MASK_T_CONST(0x0000000a1100110a)}, { CW_MASK_T_CONST(0x0000001422002214)},
02634 { CW_MASK_T_CONST(0x0000002844004428)}, { CW_MASK_T_CONST(0x0000005088008850)}, { CW_MASK_T_CONST(0x000000a0100010a0)}, { CW_MASK_T_CONST(0x0000004020002040)},
02635 { CW_MASK_T_CONST(0x0000020400040200)}, { CW_MASK_T_CONST(0x0000050800080500)}, { CW_MASK_T_CONST(0x00000a1100110a00)}, { CW_MASK_T_CONST(0x0000142200221400)},
02636 { CW_MASK_T_CONST(0x0000284400442800)}, { CW_MASK_T_CONST(0x0000508800885000)}, { CW_MASK_T_CONST(0x0000a0100010a000)}, { CW_MASK_T_CONST(0x0000402000204000)},
02637 { CW_MASK_T_CONST(0x0002040004020000)}, { CW_MASK_T_CONST(0x0005080008050000)}, { CW_MASK_T_CONST(0x000a1100110a0000)}, { CW_MASK_T_CONST(0x0014220022140000)},
02638 { CW_MASK_T_CONST(0x0028440044280000)}, { CW_MASK_T_CONST(0x0050880088500000)}, { CW_MASK_T_CONST(0x00a0100010a00000)}, { CW_MASK_T_CONST(0x0040200020400000)},
02639 { CW_MASK_T_CONST(0x0204000402000000)}, { CW_MASK_T_CONST(0x0508000805000000)}, { CW_MASK_T_CONST(0x0a1100110a000000)}, { CW_MASK_T_CONST(0x1422002214000000)},
02640 { CW_MASK_T_CONST(0x2844004428000000)}, { CW_MASK_T_CONST(0x5088008850000000)}, { CW_MASK_T_CONST(0xa0100010a0000000)}, { CW_MASK_T_CONST(0x4020002040000000)},
02641 { CW_MASK_T_CONST(0x0400040200000000)}, { CW_MASK_T_CONST(0x0800080500000000)}, { CW_MASK_T_CONST(0x1100110a00000000)}, { CW_MASK_T_CONST(0x2200221400000000)},
02642 { CW_MASK_T_CONST(0x4400442800000000)}, { CW_MASK_T_CONST(0x8800885000000000)}, { CW_MASK_T_CONST(0x100010a000000000)}, { CW_MASK_T_CONST(0x2000204000000000)},
02643 { CW_MASK_T_CONST(0x0004020000000000)}, { CW_MASK_T_CONST(0x0008050000000000)}, { CW_MASK_T_CONST(0x00110a0000000000)}, { CW_MASK_T_CONST(0x0022140000000000)},
02644 { CW_MASK_T_CONST(0x0044280000000000)}, { CW_MASK_T_CONST(0x0088500000000000)}, { CW_MASK_T_CONST(0x0010a00000000000)}, { CW_MASK_T_CONST(0x0020400000000000)},
02645
02646 { CW_MASK_T_CONST(0x0000000000000302)}, { CW_MASK_T_CONST(0x0000000000000705)}, { CW_MASK_T_CONST(0x0000000000000e0a)}, { CW_MASK_T_CONST(0x0000000000001c14)},
02647 { CW_MASK_T_CONST(0x0000000000003828)}, { CW_MASK_T_CONST(0x0000000000007050)}, { CW_MASK_T_CONST(0x000000000000e0a0)}, { CW_MASK_T_CONST(0x000000000000c040)},
02648 { CW_MASK_T_CONST(0x0000000000030203)}, { CW_MASK_T_CONST(0x0000000000070507)}, { CW_MASK_T_CONST(0x00000000000e0a0e)}, { CW_MASK_T_CONST(0x00000000001c141c)},
02649 { CW_MASK_T_CONST(0x0000000000382838)}, { CW_MASK_T_CONST(0x0000000000705070)}, { CW_MASK_T_CONST(0x0000000000e0a0e0)}, { CW_MASK_T_CONST(0x0000000000c040c0)},
02650 { CW_MASK_T_CONST(0x0000000003020300)}, { CW_MASK_T_CONST(0x0000000007050700)}, { CW_MASK_T_CONST(0x000000000e0a0e00)}, { CW_MASK_T_CONST(0x000000001c141c00)},
02651 { CW_MASK_T_CONST(0x0000000038283800)}, { CW_MASK_T_CONST(0x0000000070507000)}, { CW_MASK_T_CONST(0x00000000e0a0e000)}, { CW_MASK_T_CONST(0x00000000c040c000)},
02652 { CW_MASK_T_CONST(0x0000000302030000)}, { CW_MASK_T_CONST(0x0000000705070000)}, { CW_MASK_T_CONST(0x0000000e0a0e0000)}, { CW_MASK_T_CONST(0x0000001c141c0000)},
02653 { CW_MASK_T_CONST(0x0000003828380000)}, { CW_MASK_T_CONST(0x0000007050700000)}, { CW_MASK_T_CONST(0x000000e0a0e00000)}, { CW_MASK_T_CONST(0x000000c040c00000)},
02654 { CW_MASK_T_CONST(0x0000030203000000)}, { CW_MASK_T_CONST(0x0000070507000000)}, { CW_MASK_T_CONST(0x00000e0a0e000000)}, { CW_MASK_T_CONST(0x00001c141c000000)},
02655 { CW_MASK_T_CONST(0x0000382838000000)}, { CW_MASK_T_CONST(0x0000705070000000)}, { CW_MASK_T_CONST(0x0000e0a0e0000000)}, { CW_MASK_T_CONST(0x0000c040c0000000)},
02656 { CW_MASK_T_CONST(0x0003020300000000)}, { CW_MASK_T_CONST(0x0007050700000000)}, { CW_MASK_T_CONST(0x000e0a0e00000000)}, { CW_MASK_T_CONST(0x001c141c00000000)},
02657 { CW_MASK_T_CONST(0x0038283800000000)}, { CW_MASK_T_CONST(0x0070507000000000)}, { CW_MASK_T_CONST(0x00e0a0e000000000)}, { CW_MASK_T_CONST(0x00c040c000000000)},
02658 { CW_MASK_T_CONST(0x0302030000000000)}, { CW_MASK_T_CONST(0x0705070000000000)}, { CW_MASK_T_CONST(0x0e0a0e0000000000)}, { CW_MASK_T_CONST(0x1c141c0000000000)},
02659 { CW_MASK_T_CONST(0x3828380000000000)}, { CW_MASK_T_CONST(0x7050700000000000)}, { CW_MASK_T_CONST(0xe0a0e00000000000)}, { CW_MASK_T_CONST(0xc040c00000000000)},
02660 { CW_MASK_T_CONST(0x0203000000000000)}, { CW_MASK_T_CONST(0x0507000000000000)}, { CW_MASK_T_CONST(0x0a0e000000000000)}, { CW_MASK_T_CONST(0x141c000000000000)},
02661 { CW_MASK_T_CONST(0x2838000000000000)}, { CW_MASK_T_CONST(0x5070000000000000)}, { CW_MASK_T_CONST(0xa0e0000000000000)}, { CW_MASK_T_CONST(0x40c0000000000000)},
02662
02663 { CW_MASK_T_CONST(0x8040201008040200)}, { CW_MASK_T_CONST(0x0080402010080500)}, { CW_MASK_T_CONST(0x0000804020110a00)}, { CW_MASK_T_CONST(0x0000008041221400)},
02664 { CW_MASK_T_CONST(0x0000000182442800)}, { CW_MASK_T_CONST(0x0000010204885000)}, { CW_MASK_T_CONST(0x000102040810a000)}, { CW_MASK_T_CONST(0x0102040810204000)},
02665 { CW_MASK_T_CONST(0x4020100804020002)}, { CW_MASK_T_CONST(0x8040201008050005)}, { CW_MASK_T_CONST(0x00804020110a000a)}, { CW_MASK_T_CONST(0x0000804122140014)},
02666 { CW_MASK_T_CONST(0x0000018244280028)}, { CW_MASK_T_CONST(0x0001020488500050)}, { CW_MASK_T_CONST(0x0102040810a000a0)}, { CW_MASK_T_CONST(0x0204081020400040)},
02667 { CW_MASK_T_CONST(0x2010080402000204)}, { CW_MASK_T_CONST(0x4020100805000508)}, { CW_MASK_T_CONST(0x804020110a000a11)}, { CW_MASK_T_CONST(0x0080412214001422)},
02668 { CW_MASK_T_CONST(0x0001824428002844)}, { CW_MASK_T_CONST(0x0102048850005088)}, { CW_MASK_T_CONST(0x02040810a000a010)}, { CW_MASK_T_CONST(0x0408102040004020)},
02669 { CW_MASK_T_CONST(0x1008040200020408)}, { CW_MASK_T_CONST(0x2010080500050810)}, { CW_MASK_T_CONST(0x4020110a000a1120)}, { CW_MASK_T_CONST(0x8041221400142241)},
02670 { CW_MASK_T_CONST(0x0182442800284482)}, { CW_MASK_T_CONST(0x0204885000508804)}, { CW_MASK_T_CONST(0x040810a000a01008)}, { CW_MASK_T_CONST(0x0810204000402010)},
02671 { CW_MASK_T_CONST(0x0804020002040810)}, { CW_MASK_T_CONST(0x1008050005081020)}, { CW_MASK_T_CONST(0x20110a000a112040)}, { CW_MASK_T_CONST(0x4122140014224180)},
02672 { CW_MASK_T_CONST(0x8244280028448201)}, { CW_MASK_T_CONST(0x0488500050880402)}, { CW_MASK_T_CONST(0x0810a000a0100804)}, { CW_MASK_T_CONST(0x1020400040201008)},
02673 { CW_MASK_T_CONST(0x0402000204081020)}, { CW_MASK_T_CONST(0x0805000508102040)}, { CW_MASK_T_CONST(0x110a000a11204080)}, { CW_MASK_T_CONST(0x2214001422418000)},
02674 { CW_MASK_T_CONST(0x4428002844820100)}, { CW_MASK_T_CONST(0x8850005088040201)}, { CW_MASK_T_CONST(0x10a000a010080402)}, { CW_MASK_T_CONST(0x2040004020100804)},
02675 { CW_MASK_T_CONST(0x0200020408102040)}, { CW_MASK_T_CONST(0x0500050810204080)}, { CW_MASK_T_CONST(0x0a000a1120408000)}, { CW_MASK_T_CONST(0x1400142241800000)},
02676 { CW_MASK_T_CONST(0x2800284482010000)}, { CW_MASK_T_CONST(0x5000508804020100)}, { CW_MASK_T_CONST(0xa000a01008040201)}, { CW_MASK_T_CONST(0x4000402010080402)},
02677 { CW_MASK_T_CONST(0x0002040810204080)}, { CW_MASK_T_CONST(0x0005081020408000)}, { CW_MASK_T_CONST(0x000a112040800000)}, { CW_MASK_T_CONST(0x0014224180000000)},
02678 { CW_MASK_T_CONST(0x0028448201000000)}, { CW_MASK_T_CONST(0x0050880402010000)}, { CW_MASK_T_CONST(0x00a0100804020100)}, { CW_MASK_T_CONST(0x0040201008040201)},
02679
02680 { CW_MASK_T_CONST(0x01010101010101fe)}, { CW_MASK_T_CONST(0x02020202020202fd)}, { CW_MASK_T_CONST(0x04040404040404fb)}, { CW_MASK_T_CONST(0x08080808080808f7)},
02681 { CW_MASK_T_CONST(0x10101010101010ef)}, { CW_MASK_T_CONST(0x20202020202020df)}, { CW_MASK_T_CONST(0x40404040404040bf)}, { CW_MASK_T_CONST(0x808080808080807f)},
02682 { CW_MASK_T_CONST(0x010101010101fe01)}, { CW_MASK_T_CONST(0x020202020202fd02)}, { CW_MASK_T_CONST(0x040404040404fb04)}, { CW_MASK_T_CONST(0x080808080808f708)},
02683 { CW_MASK_T_CONST(0x101010101010ef10)}, { CW_MASK_T_CONST(0x202020202020df20)}, { CW_MASK_T_CONST(0x404040404040bf40)}, { CW_MASK_T_CONST(0x8080808080807f80)},
02684 { CW_MASK_T_CONST(0x0101010101fe0101)}, { CW_MASK_T_CONST(0x0202020202fd0202)}, { CW_MASK_T_CONST(0x0404040404fb0404)}, { CW_MASK_T_CONST(0x0808080808f70808)},
02685 { CW_MASK_T_CONST(0x1010101010ef1010)}, { CW_MASK_T_CONST(0x2020202020df2020)}, { CW_MASK_T_CONST(0x4040404040bf4040)}, { CW_MASK_T_CONST(0x80808080807f8080)},
02686 { CW_MASK_T_CONST(0x01010101fe010101)}, { CW_MASK_T_CONST(0x02020202fd020202)}, { CW_MASK_T_CONST(0x04040404fb040404)}, { CW_MASK_T_CONST(0x08080808f7080808)},
02687 { CW_MASK_T_CONST(0x10101010ef101010)}, { CW_MASK_T_CONST(0x20202020df202020)}, { CW_MASK_T_CONST(0x40404040bf404040)}, { CW_MASK_T_CONST(0x808080807f808080)},
02688 { CW_MASK_T_CONST(0x010101fe01010101)}, { CW_MASK_T_CONST(0x020202fd02020202)}, { CW_MASK_T_CONST(0x040404fb04040404)}, { CW_MASK_T_CONST(0x080808f708080808)},
02689 { CW_MASK_T_CONST(0x101010ef10101010)}, { CW_MASK_T_CONST(0x202020df20202020)}, { CW_MASK_T_CONST(0x404040bf40404040)}, { CW_MASK_T_CONST(0x8080807f80808080)},
02690 { CW_MASK_T_CONST(0x0101fe0101010101)}, { CW_MASK_T_CONST(0x0202fd0202020202)}, { CW_MASK_T_CONST(0x0404fb0404040404)}, { CW_MASK_T_CONST(0x0808f70808080808)},
02691 { CW_MASK_T_CONST(0x1010ef1010101010)}, { CW_MASK_T_CONST(0x2020df2020202020)}, { CW_MASK_T_CONST(0x4040bf4040404040)}, { CW_MASK_T_CONST(0x80807f8080808080)},
02692 { CW_MASK_T_CONST(0x01fe010101010101)}, { CW_MASK_T_CONST(0x02fd020202020202)}, { CW_MASK_T_CONST(0x04fb040404040404)}, { CW_MASK_T_CONST(0x08f7080808080808)},
02693 { CW_MASK_T_CONST(0x10ef101010101010)}, { CW_MASK_T_CONST(0x20df202020202020)}, { CW_MASK_T_CONST(0x40bf404040404040)}, { CW_MASK_T_CONST(0x807f808080808080)},
02694 { CW_MASK_T_CONST(0xfe01010101010101)}, { CW_MASK_T_CONST(0xfd02020202020202)}, { CW_MASK_T_CONST(0xfb04040404040404)}, { CW_MASK_T_CONST(0xf708080808080808)},
02695 { CW_MASK_T_CONST(0xef10101010101010)}, { CW_MASK_T_CONST(0xdf20202020202020)}, { CW_MASK_T_CONST(0xbf40404040404040)}, { CW_MASK_T_CONST(0x7f80808080808080)},
02696
02697 { CW_MASK_T_CONST(0x81412111090503fe)}, { CW_MASK_T_CONST(0x02824222120a07fd)}, { CW_MASK_T_CONST(0x0404844424150efb)}, { CW_MASK_T_CONST(0x08080888492a1cf7)},
02698 { CW_MASK_T_CONST(0x10101011925438ef)}, { CW_MASK_T_CONST(0x2020212224a870df)}, { CW_MASK_T_CONST(0x404142444850e0bf)}, { CW_MASK_T_CONST(0x8182848890a0c07f)},
02699 { CW_MASK_T_CONST(0x412111090503fe03)}, { CW_MASK_T_CONST(0x824222120a07fd07)}, { CW_MASK_T_CONST(0x04844424150efb0e)}, { CW_MASK_T_CONST(0x080888492a1cf71c)},
02700 { CW_MASK_T_CONST(0x101011925438ef38)}, { CW_MASK_T_CONST(0x20212224a870df70)}, { CW_MASK_T_CONST(0x4142444850e0bfe0)}, { CW_MASK_T_CONST(0x82848890a0c07fc0)},
02701 { CW_MASK_T_CONST(0x2111090503fe0305)}, { CW_MASK_T_CONST(0x4222120a07fd070a)}, { CW_MASK_T_CONST(0x844424150efb0e15)}, { CW_MASK_T_CONST(0x0888492a1cf71c2a)},
02702 { CW_MASK_T_CONST(0x1011925438ef3854)}, { CW_MASK_T_CONST(0x212224a870df70a8)}, { CW_MASK_T_CONST(0x42444850e0bfe050)}, { CW_MASK_T_CONST(0x848890a0c07fc0a0)},
02703 { CW_MASK_T_CONST(0x11090503fe030509)}, { CW_MASK_T_CONST(0x22120a07fd070a12)}, { CW_MASK_T_CONST(0x4424150efb0e1524)}, { CW_MASK_T_CONST(0x88492a1cf71c2a49)},
02704 { CW_MASK_T_CONST(0x11925438ef385492)}, { CW_MASK_T_CONST(0x2224a870df70a824)}, { CW_MASK_T_CONST(0x444850e0bfe05048)}, { CW_MASK_T_CONST(0x8890a0c07fc0a090)},
02705 { CW_MASK_T_CONST(0x090503fe03050911)}, { CW_MASK_T_CONST(0x120a07fd070a1222)}, { CW_MASK_T_CONST(0x24150efb0e152444)}, { CW_MASK_T_CONST(0x492a1cf71c2a4988)},
02706 { CW_MASK_T_CONST(0x925438ef38549211)}, { CW_MASK_T_CONST(0x24a870df70a82422)}, { CW_MASK_T_CONST(0x4850e0bfe0504844)}, { CW_MASK_T_CONST(0x90a0c07fc0a09088)},
02707 { CW_MASK_T_CONST(0x0503fe0305091121)}, { CW_MASK_T_CONST(0x0a07fd070a122242)}, { CW_MASK_T_CONST(0x150efb0e15244484)}, { CW_MASK_T_CONST(0x2a1cf71c2a498808)},
02708 { CW_MASK_T_CONST(0x5438ef3854921110)}, { CW_MASK_T_CONST(0xa870df70a8242221)}, { CW_MASK_T_CONST(0x50e0bfe050484442)}, { CW_MASK_T_CONST(0xa0c07fc0a0908884)},
02709 { CW_MASK_T_CONST(0x03fe030509112141)}, { CW_MASK_T_CONST(0x07fd070a12224282)}, { CW_MASK_T_CONST(0x0efb0e1524448404)}, { CW_MASK_T_CONST(0x1cf71c2a49880808)},
02710 { CW_MASK_T_CONST(0x38ef385492111010)}, { CW_MASK_T_CONST(0x70df70a824222120)}, { CW_MASK_T_CONST(0xe0bfe05048444241)}, { CW_MASK_T_CONST(0xc07fc0a090888482)},
02711 { CW_MASK_T_CONST(0xfe03050911214181)}, { CW_MASK_T_CONST(0xfd070a1222428202)}, { CW_MASK_T_CONST(0xfb0e152444840404)}, { CW_MASK_T_CONST(0xf71c2a4988080808)},
02712 { CW_MASK_T_CONST(0xef38549211101010)}, { CW_MASK_T_CONST(0xdf70a82422212020)}, { CW_MASK_T_CONST(0xbfe0504844424140)}, { CW_MASK_T_CONST(0x7fc0a09088848281)},
02713 };
02714
02715 }