bool draw_krkr( const board_t *board) { int rrook, brook; int rking, bking; if(board->piece[PIECE_TO_INDEX(RedRook)] != PieceNone) rrook = board->piece[PIECE_TO_INDEX(RedRook)]; if(board->piece[PIECE_TO_INDEX(RedRook) + 1] != PieceNone) rrook = board->piece[PIECE_TO_INDEX(RedRook) + 1]; if(board->piece[PIECE_TO_INDEX(BlackRook)] != PieceNone) brook = board->piece[PIECE_TO_INDEX(RedRook)]; if(board->piece[PIECE_TO_INDEX(BlackRook) + 1] != PieceNone) brook = board->piece[PIECE_TO_INDEX(RedRook) + 1]; rking = KING_POS(board, Red); bking = KING_POS(board, Black); if(EQUAL_FILE(rrook, rking) && EQUAL_RANK(brook, bking)) return true; if(SQUARE_FILE(rking) != 0x7 && SQUARE_FILE(bking) != 0x7) { if(SQUARE_RANK(rking) < 0xa && SQUARE_RANK(bking) > 0x5) return true; } return false; }
bool is_pinned(const board_t * board, int square, int colour) { int from, to; int inc; int sq, piece; ASSERT(board!=NULL); ASSERT(SQUARE_IS_OK(square)); ASSERT(COLOUR_IS_OK(colour)); from = square; to = KING_POS(board,colour); inc = DELTA_INC_LINE(to-from); if (inc == IncNone) return false; // not a line sq = from; do sq += inc; while (board->square[sq] == Empty); if (sq != to) return false; // blocker sq = from; do sq -= inc; while ((piece=board->square[sq]) == Empty); return COLOUR_IS(piece,COLOUR_OPP(colour)) && SLIDER_ATTACK(piece,inc); }
static void note_quiet_moves(list_t * list, const board_t * board, bool in_pv, int ThreadId) { int size; int i, move; int move_piece; ASSERT(list_is_ok(list)); ASSERT(board!=NULL); size = LIST_SIZE(list); if (size >= 2) { for (i = 0; i < size; i++) { move = LIST_MOVE(list,i); list->value[i] = quiet_move_value(move,board,ThreadId); if (TryQuietKingAttacks && in_pv) { move_piece = MOVE_PIECE(move,board); if (!(PIECE_IS_PAWN(move_piece) || PIECE_IS_KING(move_piece))) { if (narrow_piece_attack_king(board,move_piece,MOVE_TO(move),KING_POS(board,COLOUR_OPP(board->turn)))) { if (see_move(move,board) >= 0) { // if (1 == NumberThreadsInternal) print_board(board); list->value[i] += 16; } } } } } } }
bool pseudo_is_legal(int move, board_t * board) { int me, opp; int from, to; int piece; bool legal; int king; undo_t undo[1]; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); // init me = board->turn; opp = COLOUR_OPP(me); from = MOVE_FROM(move); to = MOVE_TO(move); piece = board->square[from]; ASSERT(COLOUR_IS(piece,me)); // slow test for en-passant captures if (MOVE_IS_EN_PASSANT(move)) { move_do(board,move,undo); legal = !IS_IN_CHECK(board,me); move_undo(board,move,undo); return legal; } // king moves (including castle) if (PIECE_IS_KING(piece)) { legal = !is_attacked(board,to,opp); if (DEBUG) { ASSERT(board->square[from]==piece); board->square[from] = Empty; ASSERT(legal==!is_attacked(board,to,opp)); board->square[from] = piece; } return legal; } // pins if (is_pinned(board,from,me)) { king = KING_POS(board,me); return DELTA_INC_LINE(king-to) == DELTA_INC_LINE(king-from); // does not discover the line } return true; }
static void find_pins(int list[], const board_t * board) { int me, opp; int king; const sq_t * ptr; int from; int piece; int delta; int inc; int sq; int capture; int pin; ASSERT(list!=NULL); ASSERT(board!=NULL); // init me = board->turn; opp = COLOUR_OPP(me); king = KING_POS(board,opp); for (ptr = &board->piece[me][1]; (from=*ptr) != SquareNone; ptr++) { // HACK: no king piece = board->square[from]; delta = king - from; ASSERT(delta_is_ok(delta)); if (PSEUDO_ATTACK(piece,delta)) { ASSERT(PIECE_IS_SLIDER(piece)); inc = DELTA_INC_LINE(delta); ASSERT(inc!=IncNone); ASSERT(SLIDER_ATTACK(piece,inc)); sq = from; do sq += inc; while ((capture=board->square[sq]) == Empty); ASSERT(sq!=king); if (COLOUR_IS(capture,me)) { pin = sq; do sq += inc; while (board->square[sq] == Empty); if (sq == king) *list++ = pin; } } } *list = SquareNone; }
static bool simple_stalemate(const board_t * board) { int me, opp; int king; int opp_flag; int from, to; int capture; const inc_t * inc_ptr; int inc; ASSERT(board!=NULL); ASSERT(board_is_legal(board)); ASSERT(!board_is_check(board)); // lone king? me = board->turn; if (board->piece_size[me] != 1 || board->pawn_size[me] != 0) return false; // no // king in a corner? king = KING_POS(board,me); if (king != A1 && king != H1 && king != A8 && king != H8) return false; // no // init opp = COLOUR_OPP(me); opp_flag = COLOUR_FLAG(opp); // king can move? from = king; for (inc_ptr = KingInc; (inc=*inc_ptr) != IncNone; inc_ptr++) { to = from + inc; capture = board->square[to]; if (capture == Empty || FLAG_IS(capture,opp_flag)) { if (!is_attacked(board,to,opp)) return false; // legal king move } } // no legal move ASSERT(board_is_stalemate((board_t*)board)); return true; }
bool move_is_check(int move, board_t * board) { undo_t undo[1]; bool check; int me, opp, king; int from, to, piece; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); // slow test for complex moves if (MOVE_IS_SPECIAL(move)) { move_do(board,move,undo); check = IS_IN_CHECK(board,board->turn); move_undo(board,move,undo); return check; } // init me = board->turn; opp = COLOUR_OPP(me); king = KING_POS(board,opp); from = MOVE_FROM(move); to = MOVE_TO(move); piece = board->square[from]; ASSERT(COLOUR_IS(piece,me)); // direct check if (PIECE_ATTACK(board,piece,to,king)) return true; // indirect check if (is_pinned(board,from,opp) && DELTA_INC_LINE(king-to) != DELTA_INC_LINE(king-from)) { return true; } return false; }
static bool gen_evasions(list_t * list, const board_t * board, const attack_t * attack, bool legal, bool stop) { int me, opp; int opp_flag; int king; const inc_t * inc_ptr; int inc; int to; int piece; ASSERT(list!=NULL); ASSERT(board!=NULL); ASSERT(attack!=NULL); ASSERT(legal==true||legal==false); ASSERT(stop==true||stop==false); ASSERT(board_is_check(board)); ASSERT(ATTACK_IN_CHECK(attack)); // init LIST_CLEAR(list); me = board->turn; opp = COLOUR_OPP(me); opp_flag = COLOUR_FLAG(opp); king = KING_POS(board,me); for (inc_ptr = KingInc; (inc=*inc_ptr) != IncNone; inc_ptr++) { if (inc != -attack->di[0] && inc != -attack->di[1]) { // avoid escaping along a check line to = king + inc; piece = board->square[to]; if (piece == Empty || FLAG_IS(piece,opp_flag)) { if (!legal || !is_attacked(board,to,opp)) { if (stop) return true; LIST_ADD(list,MOVE_MAKE(king,to)); } } } } if (attack->dn >= 2) return false; // double check, we are done // single check ASSERT(attack->dn==1); // capture the checking piece if (add_pawn_captures(list,board,attack->ds[0],legal,stop) && stop) return true; if (add_piece_moves(list,board,attack->ds[0],legal,stop) && stop) return true; // interpose a piece inc = attack->di[0]; if (inc != IncNone) { // line for (to = king+inc; to != attack->ds[0]; to += inc) { ASSERT(SQUARE_IS_OK(to)); ASSERT(board->square[to]==Empty); if (add_pawn_moves(list,board,to,legal,stop) && stop) return true; if (add_piece_moves(list,board,to,legal,stop) && stop) return true; } } return false; }
static void add_quiet_checks(list_t * list, const board_t * board) { int me, opp; int king; const sq_t * ptr, * ptr_2; int from, to, sq; int piece; const inc_t * inc_ptr; int inc; int pawn; int rank; int pin[8+1]; ASSERT(list!=NULL); ASSERT(board!=NULL); // init me = board->turn; opp = COLOUR_OPP(me); king = KING_POS(board,opp); find_pins(pin,board); // indirect checks for (ptr = pin; (from=*ptr) != SquareNone; ptr++) { piece = board->square[from]; ASSERT(is_pinned(board,from,opp)); if (PIECE_IS_PAWN(piece)) { inc = PAWN_MOVE_INC(me); rank = PAWN_RANK(from,me); if (rank != Rank7) { // promotes are generated with captures to = from + inc; if (board->square[to] == Empty) { if (DELTA_INC_LINE(to-king) != DELTA_INC_LINE(from-king)) { ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE(from,to)); if (rank == Rank2) { to = from + (2*inc); if (board->square[to] == Empty) { ASSERT(DELTA_INC_LINE(to-king)!=DELTA_INC_LINE(from-king)); ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE(from,to)); } } } } } } else if (PIECE_IS_SLIDER(piece)) { for (inc_ptr = PIECE_INC(piece); (inc=*inc_ptr) != IncNone; inc_ptr++) { for (to = from+inc; board->square[to] == Empty; to += inc) { ASSERT(DELTA_INC_LINE(to-king)!=DELTA_INC_LINE(from-king)); LIST_ADD(list,MOVE_MAKE(from,to)); } } } else { for (inc_ptr = PIECE_INC(piece); (inc=*inc_ptr) != IncNone; inc_ptr++) { to = from + inc; if (board->square[to] == Empty) { if (DELTA_INC_LINE(to-king) != DELTA_INC_LINE(from-king)) { LIST_ADD(list,MOVE_MAKE(from,to)); } } } } } // piece direct checks for (ptr = &board->piece[me][1]; (from=*ptr) != SquareNone; ptr++) { // HACK: no king for (ptr_2 = pin; (sq=*ptr_2) != SquareNone; ptr_2++) { if (sq == from) goto next_piece; } ASSERT(!is_pinned(board,from,opp)); piece = board->square[from]; inc_ptr = PIECE_INC(piece); if (PIECE_IS_SLIDER(piece)) { for (; (inc=*inc_ptr) != IncNone; inc_ptr++) { for (to = from+inc; board->square[to] == Empty; to += inc) { if (PIECE_ATTACK(board,piece,to,king)) { LIST_ADD(list,MOVE_MAKE(from,to)); } } } } else { for (; (inc=*inc_ptr) != IncNone; inc_ptr++) { to = from + inc; if (board->square[to] == Empty) { if (PSEUDO_ATTACK(piece,king-to)) { LIST_ADD(list,MOVE_MAKE(from,to)); } } } } next_piece: ; } // pawn direct checks inc = PAWN_MOVE_INC(me); pawn = PAWN_MAKE(me); to = king - (inc-1); ASSERT(PSEUDO_ATTACK(pawn,king-to)); from = to - inc; if (board->square[from] == pawn) { if (board->square[to] == Empty) { ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE(from,to)); } } else { from = to - (2*inc); if (board->square[from] == pawn) { if (PAWN_RANK(from,me) == Rank2 && board->square[to] == Empty && board->square[from+inc] == Empty) { ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE(from,to)); } } } to = king - (inc+1); ASSERT(PSEUDO_ATTACK(pawn,king-to)); from = to - inc; if (board->square[from] == pawn) { if (board->square[to] == Empty) { ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE(from,to)); } } else { from = to - (2*inc); if (board->square[from] == pawn) { if (PAWN_RANK(from,me) == Rank2 && board->square[to] == Empty && board->square[from+inc] == Empty) { ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE(from,to)); } } } }
bool capture_is_good(int move, const board_t * board, bool in_pv) { #else static bool capture_is_good(int move, const board_t * board, bool in_pv) { #endif int piece, capture; int see_value; // WHM 11/22/08 ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(move_is_tactical(move,board)); // special cases if (MOVE_IS_EN_PASSANT(move)) return true; if (move_is_under_promote(move)) return false; // REMOVE ME? Keep, looks good to me. WHM; // if (MOVE_IS_PROMOTE(move)) return true; // WHM; promote-to-queen, measures a little weaker // too many garbage lines going nuts. // captures and queen promotes capture = board->square[MOVE_TO(move)]; piece = board->square[MOVE_FROM(move)]; if (capture != Empty) { // capture ASSERT(move_is_capture(move,board)); if (MOVE_IS_PROMOTE(move)) return true; // capture a piece on Rank8 and promote to queen if (VALUE_PIECE(capture) >= VALUE_PIECE(piece)) return true; } // return see_move(move,board) >= 0; WHM 11/22/08 // WHM 11/22/08 START see_value = see_move(move,board); if (see_value >= 0) return true; if (TryNodePVQueenPromotes) { if (in_pv && MOVE_IS_PROMOTE(move)) { ASSERT(!move_is_under_promote(move)); return true; // WHM: } } if (TryKingAttackSacs || TryKingBoxSacs || TryPasserSacs) { if (in_pv && see_value > -ValueBishop && capture != Empty) { ASSERT(COLOUR_IS(capture,COLOUR_OPP(board->turn))); // king attack sacs. if (TryKingAttackSacs) { if (narrow_piece_attack_king(board, piece, MOVE_TO(move), KING_POS(board,COLOUR_OPP(board->turn)))) { return true; } } // sacrifice attacks around the narrow/close king box can be examined more fully. Rybka lessons. if (TryKingBoxSacs) { if (DISTANCE(MOVE_TO(move),KING_POS(board,COLOUR_OPP(board->turn))) <= 1) { return true; } } // passer sacrifices... if (TryPasserSacs) { if (PIECE_IS_PAWN(capture) && PAWN_RANK(MOVE_TO(move),COLOUR_OPP(board->turn)) >= Rank6) { return true; } } } } // WHM 11/22/08 END return false; }
bool recog_draw(const board_t * board, int ThreadId) { material_info_t mat_info[1]; ASSERT(board!=NULL); // material if (board->piece_nb > 4) return false; material_get_info(mat_info,board,ThreadId); if ((mat_info->flags & DrawNodeFlag) == 0) return false; // recognisers if (false) { } else if (mat_info->recog == MAT_KK) { // KK return true; } else if (mat_info->recog == MAT_KBK) { // KBK (white) return true; } else if (mat_info->recog == MAT_KKB) { // KBK (black) return true; } else if (mat_info->recog == MAT_KNK) { // KNK (white) return true; } else if (mat_info->recog == MAT_KKN) { // KNK (black) return true; } else if (mat_info->recog == MAT_KPK) { // KPK (white) int me, opp; int wp, wk, bk; me = White; opp = COLOUR_OPP(me); wp = board->pawn[me][0]; wk = KING_POS(board,me); bk = KING_POS(board,opp); if (SQUARE_FILE(wp) >= FileE) { wp = SQUARE_FILE_MIRROR(wp); wk = SQUARE_FILE_MIRROR(wk); bk = SQUARE_FILE_MIRROR(bk); } if (kpk_draw(wp,wk,bk,board->turn)) { return true; } } else if (mat_info->recog == MAT_KKP) { // KPK (black) int me, opp; int wp, wk, bk; me = Black; opp = COLOUR_OPP(me); wp = SQUARE_RANK_MIRROR(board->pawn[me][0]); wk = SQUARE_RANK_MIRROR(KING_POS(board,me)); bk = SQUARE_RANK_MIRROR(KING_POS(board,opp)); if (SQUARE_FILE(wp) >= FileE) { wp = SQUARE_FILE_MIRROR(wp); wk = SQUARE_FILE_MIRROR(wk); bk = SQUARE_FILE_MIRROR(bk); } if (kpk_draw(wp,wk,bk,COLOUR_OPP(board->turn))) { return true; } } else if (mat_info->recog == MAT_KBKB) { // KBKB int wb, bb; wb = board->piece[White][1]; bb = board->piece[Black][1]; if (SQUARE_COLOUR(wb) == SQUARE_COLOUR(bb)) { // bishops on same colour return true; } } else if (mat_info->recog == MAT_KBPK) { // KBPK (white) int me, opp; int wp, wb, bk; me = White; opp = COLOUR_OPP(me); wp = board->pawn[me][0]; wb = board->piece[me][1]; bk = KING_POS(board,opp); if (SQUARE_FILE(wp) >= FileE) { wp = SQUARE_FILE_MIRROR(wp); wb = SQUARE_FILE_MIRROR(wb); bk = SQUARE_FILE_MIRROR(bk); } if (kbpk_draw(wp,wb,bk)) return true; } else if (mat_info->recog == MAT_KKBP) { // KBPK (black) int me, opp; int wp, wb, bk; me = Black; opp = COLOUR_OPP(me); wp = SQUARE_RANK_MIRROR(board->pawn[me][0]); wb = SQUARE_RANK_MIRROR(board->piece[me][1]); bk = SQUARE_RANK_MIRROR(KING_POS(board,opp)); if (SQUARE_FILE(wp) >= FileE) { wp = SQUARE_FILE_MIRROR(wp); wb = SQUARE_FILE_MIRROR(wb); bk = SQUARE_FILE_MIRROR(bk); } if (kbpk_draw(wp,wb,bk)) return true; } else { ASSERT(false); } return false; }
void attack_set(attack_t * attack, const board_t * board) { int me, opp; const sq_t * ptr; int from, to; int inc; int pawn; int delta, piece; int sq; ASSERT(attack!=NULL); ASSERT(board!=NULL); // init attack->dn = 0; me = board->turn; opp = COLOUR_OPP(me); to = KING_POS(board,me); // pawn attacks inc = PAWN_MOVE_INC(opp); pawn = PAWN_MAKE(opp); from = to - (inc-1); if (board->square[from] == pawn) { attack->ds[attack->dn] = from; attack->di[attack->dn] = IncNone; attack->dn++; } from = to - (inc+1); if (board->square[from] == pawn) { attack->ds[attack->dn] = from; attack->di[attack->dn] = IncNone; attack->dn++; } // piece attacks for (ptr = &board->piece[opp][1]; (from=*ptr) != SquareNone; ptr++) { // HACK: no king piece = board->square[from]; delta = to - from; ASSERT(delta_is_ok(delta)); if (PSEUDO_ATTACK(piece,delta)) { inc = IncNone; if (PIECE_IS_SLIDER(piece)) { // check for blockers inc = DELTA_INC_LINE(delta); ASSERT(inc!=IncNone); sq = from; do sq += inc; while (board->square[sq] == Empty); if (sq != to) continue; // blocker => next attacker } attack->ds[attack->dn] = from; attack->di[attack->dn] = -inc; // HACK attack->dn++; } } attack->ds[attack->dn] = SquareNone; attack->di[attack->dn] = IncNone; // debug ASSERT(attack_is_ok(attack)); }
bool egbb_probe(const board_t * board, int * value) { int i; int sq; int piece; int colour, me; const sq_t * ptr; int counter; int white_king, black_king; int piece_list[4], square_list[4]; ASSERT(board!=NULL); ASSERT(value!=NULL); ASSERT(board_is_ok(board)); ASSERT(!board_is_check(board)); // init if (Egbb->init == 0) return false; if (Egbb->load == 0) return false; ASSERT(board->piece_nb<=Egbb->piece_nb); // init for (i = 0; i < 4; i++) { piece_list[i] = 0; square_list[i] = 0; } Egbb->read_nb++; // king white_king = SQUARE_TO_64(KING_POS(board,White)); black_king = SQUARE_TO_64(KING_POS(board,Black)); counter = 0; for (colour = 0; colour < ColourNb; colour++) { me = colour; // pieces for (ptr = &board->piece[me][1]; (sq=*ptr) != SquareNone; ptr++) { // HACK: no king piece = board->square[sq]; // index ASSERT(counter>=0&&counter<4); piece_list[counter] = TbPiece[PIECE_TO_12(piece)]; square_list[counter] = SQUARE_TO_64(sq); counter++; } // pawns for (ptr = &board->pawn[me][0]; (sq=*ptr) != SquareNone; ptr++) { piece = board->square[sq]; // index ASSERT(counter>=0&&counter<4); piece_list[counter] = TbPiece[PIECE_TO_12(piece)]; square_list[counter] = SQUARE_TO_64(sq); counter++; } } // probe *value = probe_egbb_ptr(board->turn,white_king,black_king,piece_list[0],square_list[0],piece_list[1],square_list[1],piece_list[2],square_list[2]); // score if (*value != ValueError) { Egbb->read_hit++; ASSERT(!value_is_mate(*value)); return true; } return false; }