- bool KPKPosition::is_legal() const {
- if(whiteKingSquare == pawnSquare || whiteKingSquare == blackKingSquare ||
- pawnSquare == blackKingSquare)
- return false;
- if(sideToMove == WHITE) {
- if(bit_is_set(this->wk_attacks(), blackKingSquare))
- return false;
- if(bit_is_set(this->pawn_attacks(), blackKingSquare))
- return false;
- }
- else {
- if(bit_is_set(this->bk_attacks(), whiteKingSquare))
- return false;
- }
- return true;
- }
-
-
- bool KPKPosition::is_immediate_draw() const {
- if(sideToMove == BLACK) {
- Bitboard wka = this->wk_attacks();
- Bitboard bka = this->bk_attacks();
-
- // Case 1: Stalemate
- if((bka & ~(wka | this->pawn_attacks())) == EmptyBoardBB)
- return true;
-
- // Case 2: King can capture pawn
- if(bit_is_set(bka, pawnSquare) && !bit_is_set(wka, pawnSquare))
- return true;
- }
- else {
- // Case 1: Stalemate
- if(whiteKingSquare == SQ_A8 && pawnSquare == SQ_A7 &&
- (blackKingSquare == SQ_C7 || blackKingSquare == SQ_C8))
- return true;
- }
-
- return false;
- }
-
-
- bool KPKPosition::is_immediate_win() const {
- // The position is an immediate win if it is white to move and the white
- // pawn can be promoted without getting captured:
- return
- sideToMove == WHITE &&
- square_rank(pawnSquare) == RANK_7 &&
- (square_distance(blackKingSquare, pawnSquare+DELTA_N) > 1 ||
- bit_is_set(this->wk_attacks(), pawnSquare+DELTA_N));
- }
-
-
- Bitboard KPKPosition::wk_attacks() const {
- return StepAttackBB[WK][whiteKingSquare];
- }
-
-
- Bitboard KPKPosition::bk_attacks() const {
- return StepAttackBB[BK][blackKingSquare];
- }
-
-
- Bitboard KPKPosition::pawn_attacks() const {
- return StepAttackBB[WP][pawnSquare];
- }
-
-
- void initialize() {
- KPKPosition p;
- for(int i = 0; i < IndexMax; i++) {
- p.from_index(i);
- if(!p.is_legal())
- Bitbase[i] = RESULT_INVALID;
- else if(p.is_immediate_draw())
- Bitbase[i] = RESULT_DRAW;
- else if(p.is_immediate_win())
- Bitbase[i] = RESULT_WIN;
- else {
- Bitbase[i] = RESULT_UNKNOWN;
- UnknownCount++;
- }
- }
- }
-
-
- bool next_iteration() {
- KPKPosition p;
- int previousUnknownCount = UnknownCount;
-
- for(int i = 0; i < IndexMax; i++)
- if(Bitbase[i] == RESULT_UNKNOWN) {
- p.from_index(i);
-
- Bitbase[i] = (p.sideToMove == WHITE)? classify_wtm(p) : classify_btm(p);
-
- if(Bitbase[i] == RESULT_WIN || Bitbase[i] == RESULT_LOSS ||
- Bitbase[i] == RESULT_DRAW)
- UnknownCount--;
- }
-
- return UnknownCount != previousUnknownCount;
- }
-
-
- Result classify_wtm(const KPKPosition &p) {
-
- // If one move leads to a position classified as RESULT_LOSS, the result
- // of the current position is RESULT_WIN. If all moves lead to positions
- // classified as RESULT_DRAW, the current position is classified as
- // RESULT_DRAW. Otherwise, the current position is classified as
- // RESULT_UNKNOWN.
-
- bool unknownFound = false;
- Bitboard b;
- Square s;
-
- // King moves
- b = p.wk_attacks();
- while(b) {
- s = pop_1st_bit(&b);
- switch(Bitbase[compute_index(s, p.blackKingSquare, p.pawnSquare,
- BLACK)]) {
- case RESULT_LOSS:
- return RESULT_WIN;
-
- case RESULT_UNKNOWN:
- unknownFound = true;
- break;
-
- case RESULT_DRAW: case RESULT_INVALID:
- break;