- // A KPK bitbase index is an integer in [0, IndexMax] range
- //
- // Information is mapped in this way
- //
- // bit 0: side to move (WHITE or BLACK)
- // bit 1- 6: black king square (from SQ_A1 to SQ_H8)
- // bit 7-12: white king square (from SQ_A1 to SQ_H8)
- // bit 13-14: white pawn file (from FILE_A to FILE_D)
- // bit 15-17: white pawn rank - 1 (from RANK_2 - 1 to RANK_7 - 1)
-
- int compute_index(Square wksq, Square bksq, Square wpsq, Color stm) {
-
- assert(square_file(wpsq) <= FILE_D);
-
- int p = int(square_file(wpsq)) + 4 * int(square_rank(wpsq) - 1);
- int r = int(stm) + 2 * int(bksq) + 128 * int(wksq) + 8192 * p;
-
- assert(r >= 0 && r < IndexMax);
-
- return r;
- }
-
- void KPKPosition::from_index(int index) {
-
- int s = (index / 8192) % 24;
-
- sideToMove = Color(index % 2);
- blackKingSquare = Square((index / 2) % 64);
- whiteKingSquare = Square((index / 128) % 64);
- pawnSquare = make_square(File(s % 4), Rank(s / 4 + 1));
- }
-
- bool KPKPosition::is_legal() const {
-
- if ( whiteKingSquare == pawnSquare
- || whiteKingSquare == blackKingSquare
- || blackKingSquare == pawnSquare)
- return false;
-
- if (sideToMove == WHITE)
- {
- if ( bit_is_set(wk_attacks(), blackKingSquare)
- || bit_is_set(pawn_attacks(), blackKingSquare))
- return false;
- }
- else if (bit_is_set(bk_attacks(), whiteKingSquare))
- return false;
-
- return true;
- }
-
- bool KPKPosition::is_immediate_draw() const {
-
- if (sideToMove == BLACK)
- {
- Bitboard wka = wk_attacks();
- Bitboard bka = bk_attacks();
-
- // Case 1: Stalemate
- if ((bka & ~(wka | pawn_attacks())) == EmptyBoardBB)
- return true;
-
- // Case 2: King can capture pawn
- if (bit_is_set(bka, pawnSquare) && !bit_is_set(wka, pawnSquare))
- return true;
- }
+ KPKPosition::KPKPosition(unsigned idx) {
+
+ ksq[WHITE] = Square((idx >> 0) & 0x3F);
+ ksq[BLACK] = Square((idx >> 6) & 0x3F);
+ stm = Color ((idx >> 12) & 0x01);
+ psq = make_square(File((idx >> 13) & 0x3), Rank(RANK_7 - ((idx >> 15) & 0x7)));
+
+ // Invalid if two pieces are on the same square or if a king can be captured
+ if ( distance(ksq[WHITE], ksq[BLACK]) <= 1
+ || ksq[WHITE] == psq
+ || ksq[BLACK] == psq
+ || (stm == WHITE && (pawn_attacks_bb(WHITE, psq) & ksq[BLACK])))
+ result = INVALID;
+
+ // Win if the pawn can be promoted without getting captured
+ else if ( stm == WHITE
+ && rank_of(psq) == RANK_7
+ && ksq[WHITE] != psq + NORTH
+ && ( distance(ksq[BLACK], psq + NORTH) > 1
+ || (distance(ksq[WHITE], psq + NORTH) == 1)))
+ result = WIN;
+
+ // Draw if it is stalemate or the black king can capture the pawn
+ else if ( stm == BLACK
+ && ( !(attacks_bb<KING>(ksq[BLACK]) & ~(attacks_bb<KING>(ksq[WHITE]) | pawn_attacks_bb(WHITE, psq)))
+ || (attacks_bb<KING>(ksq[BLACK]) & ~attacks_bb<KING>(ksq[WHITE]) & psq)))
+ result = DRAW;
+
+ // Position will be classified later