- // 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(file_of(wpsq) <= FILE_D);
-
- int p = file_of(wpsq) + 4 * (rank_of(wpsq) - 1);
- int r = stm + 2 * bksq + 128 * wksq + 8192 * p;
-
- assert(r >= 0 && r < IndexMax);
-
- return r;
- }
-
- void KPKPosition::from_index(int index) {
-
- int s = index >> 13;
- sideToMove = Color(index & 1);
- blackKingSquare = Square((index >> 1) & 63);
- whiteKingSquare = Square((index >> 7) & 63);
- pawnSquare = make_square(File(s & 3), Rank((s >> 2) + 1));
+ 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
+ else
+ result = UNKNOWN;