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; }
static bool is_passed(const board_t * board, int to) { int t2; int me, opp; int file, rank; me = board->turn; opp = COLOUR_OPP(me); file = SQUARE_FILE(to); rank = PAWN_RANK(to,me); t2 = board->pawn_file[me][file] | BitRev[board->pawn_file[opp][file]]; // passed pawns if ((t2 & BitGT[rank]) == 0) { if (((BitRev[board->pawn_file[opp][file-1]] | BitRev[board->pawn_file[opp][file+1]]) & BitGT[rank]) == 0) { return true; } } return false; }
static bool kbpk_draw (int wp, int wb, int bk) { ASSERT(SQUARE_IS_OK(wp)); ASSERT(SQUARE_IS_OK(wb)); ASSERT(SQUARE_IS_OK(bk)); if (SQUARE_FILE(wp) == FileA && DISTANCE(bk,A8) <= 1 && SQUARE_COLOUR(wb) != SQUARE_COLOUR(A8)) { return true; } return false; }
void move_do_null(board_t * board, undo_t * undo) { int sq; ASSERT(board!=NULL); ASSERT(undo!=NULL); ASSERT(board_is_legal(board)); ASSERT(!board_is_check(board)); // initialise undo undo->turn = board->turn; undo->ep_square = board->ep_square; undo->ply_nb = board->ply_nb; undo->cap_sq = board->cap_sq; undo->moving_piece = board->moving_piece; undo->key = board->key; // update key stack ASSERT(board->sp<StackSize); board->stack[board->sp++] = board->key; // update turn board->turn = COLOUR_OPP(board->turn); board->key ^= RANDOM_64(RandomTurn); // update en-passant square sq = board->ep_square; if (sq != SquareNone) { board->key ^= RANDOM_64(RandomEnPassant+SQUARE_FILE(sq)-FileA); board->ep_square = SquareNone; } // update move number board->ply_nb = 0; // HACK: null move is considered as a conversion // update last square board->cap_sq = SquareNone; board->moving_piece = PieceNone256; // debug ASSERT(board_is_ok(board)); }
U64 hash_ep_key(S32 square) { ASSERT(SQUARE_IS_OK(square)); return RANDOM_64(RandomEnPassant + SQUARE_FILE(square) - FileA); }
bool move_is_pseudo( int move, board_t *board ) { int me, opp; int from, to; int piece, capture; ASSERT(move_is_ok(move)); ASSERT(board != NULL); // init me = board->turn; opp = COLOUR_OPP(board->turn); // from from = MOVE_FROM(move); ASSERT(SQUARE_IS_OK(from)); piece = board->square[from]; if(INDEX_TO_COLOUR(piece) != me) return false; // to to = MOVE_TO(move); ASSERT(SQUARE_IS_OK(to)); capture = board->square[to]; if( INDEX_TO_COLOUR(capture) == me ) return false; // move switch(INDEX_TO_PIECE(piece)) { case RedKing: if(KING_IN_CITY(to) && KLegalDt[to - from + 256]) return true; if(EQUAL_FILE(from, to) && INDEX_TO_PIECE(capture) == BlackKing) { int row=SQUARE_RANK(from) - 3; int col=SQUARE_FILE(from) - 3; if(FileCapMin[row][board->file[col]] + col == to) return true; } return false; case BlackKing: if(KING_IN_CITY(to) && KLegalDt[to - from + 256]) return true; if(EQUAL_FILE(from, to) && INDEX_TO_PIECE(capture) ==RedKing) { int row=SQUARE_RANK(from) - 3; int col=SQUARE_FILE(from) - 3; if(FileCapMax[row][board->file[col]] + col == to) return true; } return false; case RedAdvisor: case BlackAdvisor: if(ADVISOR_IN_CITY(to) && ALegalDt[to - from + 256]) return true; return false; case RedBishop: case BlackBishop: if(BISHOP_IN_CITY(to) && BLegalDt[to - from + 256] && board->square[(to + from) >> 1] == PieceNone)// return true; return false; case RedKnight: case BlackKnight: if(NLegalDt[to - from + 256] && board->square[from + NLegalDt[to - from + 256]] == PieceNone)// return true; return false; case RedRook: case BlackRook: if(capture) { if(EQUAL_FILE(from, to)) { int row=SQUARE_RANK(from) - 3; int col=SQUARE_FILE(from) - 3; if(FileCapMax[row][board->file[col]] + col == to || FileCapMin[row][board->file[col]] + col == to) return true; } else if(EQUAL_RANK(from, to)) { int row=SQUARE_RANK(from) - 3; int col=SQUARE_FILE(from) - 3; if(RankCapMax[col][board->rank[row]] + (row << 4) == to || RankCapMin[col][board->rank[row]] + (row << 4) == to) return true; } } else { int row=SQUARE_RANK(from) - 3; int col=SQUARE_FILE(from) - 3; int to_row = SQUARE_RANK(to) - 3; int to_col = SQUARE_FILE(to) - 3; int rowbit = board->rank[row]; int colbit = board->file[col]; if(EQUAL_FILE(from, to)) { //if(FileNonCapMin[row][board->file[col]] + col <= to && to <= FileNonCapMax[row][board->file[col]] + col) if(PinNb[row][to_row][colbit] == 0) return true; } else if(EQUAL_RANK(from, to)) { //if(RankNonCapMin[col][board->rank[row]] + (row << 4) <= to && to <= RankNonCapMax[col][board->rank[row]] + (row << 4)) if(PinNb[col][to_col][rowbit] == 0) return true; } } return false; case RedCannon: case BlackCannon: if(capture) { if(EQUAL_RANK(from, to)) { int row=SQUARE_RANK(from) - 3; int col=SQUARE_FILE(from) - 3; if(CannonRankCapMax[col][board->rank[row]] + (row << 4) == to || CannonRankCapMin[col][board->rank[row]] + (row << 4) == to) return true; } else if(EQUAL_FILE(from, to)) { int row=SQUARE_RANK(from) - 3; int col=SQUARE_FILE(from) - 3; if(CannonFileCapMax[row][board->file[col]] + col == to || CannonFileCapMin[row][board->file[col]] + col == to) return true; } } else { int row=SQUARE_RANK(from) - 3; int col=SQUARE_FILE(from) - 3; int to_row = SQUARE_RANK(to) - 3; int to_col = SQUARE_FILE(to) - 3; int rowbit = board->rank[row]; int colbit = board->file[col]; if(EQUAL_RANK(from, to)) { //if(RankNonCapMin[col][board->rank[row]] + (row << 4) <= to && to <= RankNonCapMax[col][board->rank[row]] + (row << 4)) if(PinNb[col][to_col][rowbit] == 0) return true; } else if(EQUAL_FILE(from, to)) { //if(FileNonCapMin[row][board->file[col]] + col <= to&& to <= FileNonCapMax[row][board->file[col]] + col) if(PinNb[row][to_row][colbit] == 0) return true; } } return false; case BlackPawn: if((from + 16) == to) return true; if(SQUARE_COLOUR(from) == Red) { if((from - 1) == to || (from + 1) == to) return true; } return false; case RedPawn: if((from - 16) == to) return true; if(SQUARE_COLOUR(from) == Black) { if((from - 1) == to || (from + 1) == to) return true; } default: return false; } return false; }
void board_init_list(board_t * board) { int sq_64, sq, piece; int colour, pos; int i, size; int square; int order; int file; ASSERT(board!=NULL); // init for (sq = 0; sq < SquareNb; sq++) { board->pos[sq] = -1; } board->piece_nb = 0; for (piece = 0; piece < 12; piece++) board->number[piece] = 0; // piece lists for (colour = 0; colour < ColourNb; colour++) { // piece list pos = 0; for (sq_64 = 0; sq_64 < 64; sq_64++) { sq = SQUARE_FROM_64(sq_64); piece = board->square[sq]; if (piece != Empty && !piece_is_ok(piece)) my_fatal("board_init_list(): illegal position\n"); if (COLOUR_IS(piece,colour) && !PIECE_IS_PAWN(piece)) { if (pos >= 16) my_fatal("board_init_list(): illegal position\n"); ASSERT(pos>=0&&pos<16); board->pos[sq] = pos; board->piece[colour][pos] = sq; pos++; board->piece_nb++; board->number[PIECE_TO_12(piece)]++; } } if (board->number[COLOUR_IS_WHITE(colour)?WhiteKing12:BlackKing12] != 1) my_fatal("board_init_list(): illegal position\n"); ASSERT(pos>=1&&pos<=16); board->piece[colour][pos] = SquareNone; board->piece_size[colour] = pos; // MV sort size = board->piece_size[colour]; for (i = 1; i < size; i++) { square = board->piece[colour][i]; piece = board->square[square]; order = PIECE_ORDER(piece); for (pos = i; pos > 0 && order > PIECE_ORDER(board->square[(sq=board->piece[colour][pos-1])]); pos--) { ASSERT(pos>0&&pos<size); board->piece[colour][pos] = sq; ASSERT(board->pos[sq]==pos-1); board->pos[sq] = pos; } ASSERT(pos>=0&&pos<size); board->piece[colour][pos] = square; ASSERT(board->pos[square]==i); board->pos[square] = pos; } // debug if (DEBUG) { for (i = 0; i < board->piece_size[colour]; i++) { sq = board->piece[colour][i]; ASSERT(board->pos[sq]==i); if (i == 0) { // king ASSERT(PIECE_IS_KING(board->square[sq])); } else { ASSERT(!PIECE_IS_KING(board->square[sq])); ASSERT(PIECE_ORDER(board->square[board->piece[colour][i]])<=PIECE_ORDER(board->square[board->piece[colour][i-1]])); } } } // pawn list for (file = 0; file < FileNb; file++) { board->pawn_file[colour][file] = 0; } pos = 0; for (sq_64 = 0; sq_64 < 64; sq_64++) { sq = SQUARE_FROM_64(sq_64); piece = board->square[sq]; if (COLOUR_IS(piece,colour) && PIECE_IS_PAWN(piece)) { if (pos >= 8 || SQUARE_IS_PROMOTE(sq)) my_fatal("board_init_list(): illegal position\n"); ASSERT(pos>=0&&pos<8); board->pos[sq] = pos; board->pawn[colour][pos] = sq; pos++; board->piece_nb++; board->number[PIECE_TO_12(piece)]++; board->pawn_file[colour][SQUARE_FILE(sq)] |= BIT(PAWN_RANK(sq,colour)); } } ASSERT(pos>=0&&pos<=8); board->pawn[colour][pos] = SquareNone; board->pawn_size[colour] = pos; if (board->piece_size[colour] + board->pawn_size[colour] > 16) my_fatal("board_init_list(): illegal position\n"); } // last square board->cap_sq = SquareNone; // PST board->opening = board_opening(board); board->endgame = board_endgame(board); // hash key for (i = 0; i < board->ply_nb; i++) board->stack[i] = 0; // HACK board->sp = board->ply_nb; board->key = hash_key(board); board->pawn_key = hash_pawn_key(board); board->material_key = hash_material_key(board); // legality if (!board_is_legal(board)) my_fatal("board_init_list(): illegal position\n"); // debug ASSERT(board_is_ok(board)); }
void move_do(board_t * board, int move, undo_t * undo) { int me, opp; int from, to; int piece, pos, capture; int old_flags, new_flags; int delta; int sq; int pawn, rook; ASSERT(board!=NULL); ASSERT(move_is_ok(move)); ASSERT(undo!=NULL); ASSERT(board_is_legal(board)); // initialise undo undo->capture = false; undo->turn = board->turn; undo->flags = board->flags; undo->ep_square = board->ep_square; undo->ply_nb = board->ply_nb; undo->cap_sq = board->cap_sq; undo->opening = board->opening; undo->endgame = board->endgame; undo->key = board->key; undo->pawn_key = board->pawn_key; undo->material_key = board->material_key; // 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)); // update key stack ASSERT(board->sp<StackSize); board->stack[board->sp++] = board->key; // update turn board->turn = opp; board->key ^= RANDOM_64(RandomTurn); // update castling rights old_flags = board->flags; new_flags = old_flags & CastleMask[from] & CastleMask[to]; board->flags = new_flags; board->key ^= Castle64[new_flags^old_flags]; // HACK // update en-passant square if ((sq=board->ep_square) != SquareNone) { board->key ^= RANDOM_64(RandomEnPassant+SQUARE_FILE(sq)-FileA); board->ep_square = SquareNone; } if (PIECE_IS_PAWN(piece)) { delta = to - from; if (delta == +32 || delta == -32) { pawn = PAWN_MAKE(opp); if (board->square[to-1] == pawn || board->square[to+1] == pawn) { board->ep_square = (from + to) / 2; board->key ^= RANDOM_64(RandomEnPassant+SQUARE_FILE(to)-FileA); } } } // update move number (captures are handled later) board->ply_nb++; if (PIECE_IS_PAWN(piece)) board->ply_nb = 0; // conversion // update last square board->cap_sq = SquareNone; // remove the captured piece sq = to; if (MOVE_IS_EN_PASSANT(move)) sq = SQUARE_EP_DUAL(sq); if ((capture=board->square[sq]) != Empty) { ASSERT(COLOUR_IS(capture,opp)); ASSERT(!PIECE_IS_KING(capture)); undo->capture = true; undo->capture_square = sq; undo->capture_piece = capture; undo->capture_pos = board->pos[sq]; square_clear(board,sq,capture,true); board->ply_nb = 0; // conversion board->cap_sq = to; } // move the piece if (MOVE_IS_PROMOTE(move)) { // promote undo->pawn_pos = board->pos[from]; square_clear(board,from,piece,true); piece = move_promote(move); // insert the promote piece in MV order for (pos = board->piece_size[me]; pos > 0 && piece > board->square[board->piece[me][pos-1]]; pos--) // HACK ; square_set(board,to,piece,pos,true); board->cap_sq = to; } else { // normal move square_move(board,from,to,piece,true); } // move the rook in case of castling if (MOVE_IS_CASTLE(move)) { rook = Rook64 | COLOUR_FLAG(me); // HACK if (to == G1) { square_move(board,H1,F1,rook,true); } else if (to == C1) { square_move(board,A1,D1,rook,true); } else if (to == G8) { square_move(board,H8,F8,rook,true); } else if (to == C8) { square_move(board,A8,D8,rook,true); } else { ASSERT(false); } } // debug ASSERT(board_is_ok(board)); }
static void square_move(board_t * board, int from, int to, int piece, bool update) { int colour; int pos; int from_64, to_64; int piece_12; int piece_index; uint64 hash_xor; ASSERT(board!=NULL); ASSERT(SQUARE_IS_OK(from)); ASSERT(SQUARE_IS_OK(to)); ASSERT(piece_is_ok(piece)); ASSERT(update==true||update==false); // init colour = PIECE_COLOUR(piece); pos = board->pos[from]; ASSERT(pos>=0); // from ASSERT(board->square[from]==piece); board->square[from] = Empty; ASSERT(board->pos[from]==pos); board->pos[from] = -1; // not needed // to ASSERT(board->square[to]==Empty); board->square[to] = piece; ASSERT(board->pos[to]==-1); board->pos[to] = pos; // piece list if (!PIECE_IS_PAWN(piece)) { ASSERT(board->piece[colour][pos]==from); board->piece[colour][pos] = to; } else { ASSERT(board->pawn[colour][pos]==from); board->pawn[colour][pos] = to; // pawn "bitboard" board->pawn_file[colour][SQUARE_FILE(from)] ^= BIT(PAWN_RANK(from,colour)); board->pawn_file[colour][SQUARE_FILE(to)] ^= BIT(PAWN_RANK(to,colour)); } // update if (update) { // init from_64 = SQUARE_TO_64(from); to_64 = SQUARE_TO_64(to); piece_12 = PIECE_TO_12(piece); // PST board->opening += PST(piece_12,to_64,Opening) - PST(piece_12,from_64,Opening); board->endgame += PST(piece_12,to_64,Endgame) - PST(piece_12,from_64,Endgame); // hash key piece_index = RandomPiece + (piece_12^1) * 64; // HACK: ^1 for PolyGlot book hash_xor = RANDOM_64(piece_index+to_64) ^ RANDOM_64(piece_index+from_64); board->key ^= hash_xor; if (PIECE_IS_PAWN(piece)) board->pawn_key ^= hash_xor; } }
static void square_set(board_t * board, int square, int piece, int pos, bool update) { int piece_12, colour; int sq; int i, size; int sq_64; uint64 hash_xor; ASSERT(board!=NULL); ASSERT(SQUARE_IS_OK(square)); ASSERT(piece_is_ok(piece)); ASSERT(pos>=0); ASSERT(update==true||update==false); // init piece_12 = PIECE_TO_12(piece); colour = PIECE_COLOUR(piece); // square ASSERT(board->square[square]==Empty); board->square[square] = piece; // piece list if (!PIECE_IS_PAWN(piece)) { // init size = board->piece_size[colour]; ASSERT(size>=0); // size size++; board->piece[colour][size] = SquareNone; board->piece_size[colour] = size; // stable swap ASSERT(pos>=0&&pos<size); for (i = size-1; i > pos; i--) { sq = board->piece[colour][i-1]; board->piece[colour][i] = sq; ASSERT(board->pos[sq]==i-1); board->pos[sq] = i; } board->piece[colour][pos] = square; ASSERT(board->pos[square]==-1); board->pos[square] = pos; } else { // init size = board->pawn_size[colour]; ASSERT(size>=0); // size size++; board->pawn[colour][size] = SquareNone; board->pawn_size[colour] = size; // stable swap ASSERT(pos>=0&&pos<size); for (i = size-1; i > pos; i--) { sq = board->pawn[colour][i-1]; board->pawn[colour][i] = sq; ASSERT(board->pos[sq]==i-1); board->pos[sq] = i; } board->pawn[colour][pos] = square; ASSERT(board->pos[square]==-1); board->pos[square] = pos; // pawn "bitboard" board->pawn_file[colour][SQUARE_FILE(square)] ^= BIT(PAWN_RANK(square,colour)); } // material ASSERT(board->piece_nb<32); board->piece_nb++;; ASSERT(board->number[piece_12]<9); board->number[piece_12]++; // update if (update) { // init sq_64 = SQUARE_TO_64(square); // PST board->opening += PST(piece_12,sq_64,Opening); board->endgame += PST(piece_12,sq_64,Endgame); // hash key hash_xor = RANDOM_64(RandomPiece+(piece_12^1)*64+sq_64); // HACK: ^1 for PolyGlot book board->key ^= hash_xor; if (PIECE_IS_PAWN(piece)) board->pawn_key ^= hash_xor; // material key board->material_key ^= RANDOM_64(piece_12*16+(board->number[piece_12]-1)); } }
static void pawn_comp_info(pawn_info_t * info, const board_t * board) { int colour; int file, rank; int me, opp; const sq_t * ptr; int sq; bool backward, candidate, doubled, isolated, open, passed; int t1, t2; int n; int bits; int opening[ColourNb], endgame[ColourNb]; int flags[ColourNb]; int file_bits[ColourNb]; int passed_bits[ColourNb]; int single_file[ColourNb]; ASSERT(info!=NULL); ASSERT(board!=NULL); // pawn_file[] #if DEBUG for (colour = 0; colour < ColourNb; colour++) { int pawn_file[FileNb]; me = colour; for (file = 0; file < FileNb; file++) { pawn_file[file] = 0; } for (ptr = &board->pawn[me][0]; (sq=*ptr) != SquareNone; ptr++) { file = SQUARE_FILE(sq); rank = PAWN_RANK(sq,me); ASSERT(file>=FileA&&file<=FileH); ASSERT(rank>=Rank2&&rank<=Rank7); pawn_file[file] |= BIT(rank); } for (file = 0; file < FileNb; file++) { if (board->pawn_file[colour][file] != pawn_file[file]) my_fatal("board->pawn_file[][]\n"); } } #endif // init for (colour = 0; colour < ColourNb; colour++) { opening[colour] = 0; endgame[colour] = 0; flags[colour] = 0; file_bits[colour] = 0; passed_bits[colour] = 0; single_file[colour] = SquareNone; } // features and scoring for (colour = 0; colour < ColourNb; colour++) { me = colour; opp = COLOUR_OPP(me); for (ptr = &board->pawn[me][0]; (sq=*ptr) != SquareNone; ptr++) { // init file = SQUARE_FILE(sq); rank = PAWN_RANK(sq,me); ASSERT(file>=FileA&&file<=FileH); ASSERT(rank>=Rank2&&rank<=Rank7); // flags file_bits[me] |= BIT(file); if (rank == Rank2) flags[me] |= BackRankFlag; // features backward = false; candidate = false; doubled = false; isolated = false; open = false; passed = false; t1 = board->pawn_file[me][file-1] | board->pawn_file[me][file+1]; t2 = board->pawn_file[me][file] | BitRev[board->pawn_file[opp][file]]; // doubled if ((board->pawn_file[me][file] & BitLT[rank]) != 0) { doubled = true; } // isolated and backward if (t1 == 0) { isolated = true; } else if ((t1 & BitLE[rank]) == 0) { backward = true; // really backward? if ((t1 & BitRank1[rank]) != 0) { ASSERT(rank+2<=Rank8); if (((t2 & BitRank1[rank]) | ((BitRev[board->pawn_file[opp][file-1]] | BitRev[board->pawn_file[opp][file+1]]) & BitRank2[rank])) == 0) { backward = false; } } else if (rank == Rank2 && ((t1 & BitEQ[rank+2]) != 0)) { ASSERT(rank+3<=Rank8); if (((t2 & BitRank2[rank]) | ((BitRev[board->pawn_file[opp][file-1]] | BitRev[board->pawn_file[opp][file+1]]) & BitRank3[rank])) == 0) { backward = false; } } } // open, candidate and passed if ((t2 & BitGT[rank]) == 0) { open = true; if (((BitRev[board->pawn_file[opp][file-1]] | BitRev[board->pawn_file[opp][file+1]]) & BitGT[rank]) == 0) { passed = true; passed_bits[me] |= BIT(file); } else { // candidate? n = 0; n += BIT_COUNT(board->pawn_file[me][file-1]&BitLE[rank]); n += BIT_COUNT(board->pawn_file[me][file+1]&BitLE[rank]); n -= BIT_COUNT(BitRev[board->pawn_file[opp][file-1]]&BitGT[rank]); n -= BIT_COUNT(BitRev[board->pawn_file[opp][file+1]]&BitGT[rank]); if (n >= 0) { // safe? n = 0; n += BIT_COUNT(board->pawn_file[me][file-1]&BitEQ[rank-1]); n += BIT_COUNT(board->pawn_file[me][file+1]&BitEQ[rank-1]); n -= BIT_COUNT(BitRev[board->pawn_file[opp][file-1]]&BitEQ[rank+1]); n -= BIT_COUNT(BitRev[board->pawn_file[opp][file+1]]&BitEQ[rank+1]); if (n >= 0) candidate = true; } } } // outposts if (me == White) { if (SQUARE_IS_OK(sq+15)) { if (WEAK_SQUARE_BLACK(sq+15)) opening[White] += OutpostMatrix[White][SQUARE_TO_64(sq+15)]; else opening[White] += (OutpostMatrix[White][SQUARE_TO_64(sq+15)]+1)/2; } if (SQUARE_IS_OK(sq+17)) { if (WEAK_SQUARE_BLACK(sq+17)) opening[White] += OutpostMatrix[White][SQUARE_TO_64(sq+17)]; else opening[White] += (OutpostMatrix[White][SQUARE_TO_64(sq+17)]+1)/2; } } else { if (SQUARE_IS_OK(sq-15)) { if (WEAK_SQUARE_WHITE(sq-15)) opening[Black] += OutpostMatrix[Black][SQUARE_TO_64(sq-15)]; else opening[Black] += (OutpostMatrix[Black][SQUARE_TO_64(sq-15)]+1)/2; } if (SQUARE_IS_OK(sq-17)) { if (WEAK_SQUARE_WHITE(sq-17)) opening[Black] += OutpostMatrix[Black][SQUARE_TO_64(sq-17)]; else opening[Black] += (OutpostMatrix[Black][SQUARE_TO_64(sq-17)]+1)/2; } } // score if (doubled) { opening[me] -= DoubledOpening; endgame[me] -= DoubledEndgame; } if (isolated) { if (open) { opening[me] -= IsolatedOpeningOpen; endgame[me] -= IsolatedEndgame; } else { opening[me] -= IsolatedOpening; endgame[me] -= IsolatedEndgame; } } if (backward) { if (open) { opening[me] -= BackwardOpeningOpen; endgame[me] -= BackwardEndgame; } else { opening[me] -= BackwardOpening; endgame[me] -= BackwardEndgame; } } if (candidate) { opening[me] += quad(CandidateOpeningMin,CandidateOpeningMax,rank); endgame[me] += quad(CandidateEndgameMin,CandidateEndgameMax,rank); } // this was moved to the dynamic evaluation /* if (passed) { opening[me] += quad(PassedOpeningMin,PassedOpeningMax,rank); endgame[me] += quad(PassedEndgameMin,PassedEndgameMax,rank); } */ } } // store info info->opening = ((opening[White] - opening[Black]) * PawnStructureWeight) / 256; info->endgame = ((endgame[White] - endgame[Black]) * PawnStructureWeight) / 256; for (colour = 0; colour < ColourNb; colour++) { me = colour; opp = COLOUR_OPP(me); // draw flags bits = file_bits[me]; if (bits != 0 && (bits & (bits-1)) == 0) { // one set bit file = BIT_FIRST(bits); rank = BIT_FIRST(board->pawn_file[me][file]); ASSERT(rank>=Rank2); if (((BitRev[board->pawn_file[opp][file-1]] | BitRev[board->pawn_file[opp][file+1]]) & BitGT[rank]) == 0) { rank = BIT_LAST(board->pawn_file[me][file]); single_file[me] = SQUARE_MAKE(file,rank); } } info->flags[colour] = flags[colour]; info->passed_bits[colour] = passed_bits[colour]; info->single_file[colour] = single_file[colour]; } }
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; }
static bool kpk_draw(int wp, int wk, int bk, int turn) { int wp_file, wp_rank; int wk_file; int bk_file, bk_rank; ASSERT(SQUARE_IS_OK(wp)); ASSERT(SQUARE_IS_OK(wk)); ASSERT(SQUARE_IS_OK(bk)); ASSERT(COLOUR_IS_OK(turn)); ASSERT(SQUARE_FILE(wp)<=FileD); wp_file = SQUARE_FILE(wp); wp_rank = SQUARE_RANK(wp); wk_file = SQUARE_FILE(wk); bk_file = SQUARE_FILE(bk); bk_rank = SQUARE_RANK(bk); if (false) { } else if (bk == wp+16) { if (wp_rank <= Rank6) { return true; } else { ASSERT(wp_rank==Rank7); if (COLOUR_IS_WHITE(turn)) { if (wk == wp-15 || wk == wp-17) return true; } else { if (wk != wp-15 && wk != wp-17) return true; } } } else if (bk == wp+32) { if (wp_rank <= Rank5) { return true; } else { ASSERT(wp_rank==Rank6); if (COLOUR_IS_WHITE(turn)) { if (wk != wp-1 && wk != wp+1) return true; } else { return true; } } } else if (wk == wp-1 || wk == wp+1) { if (bk == wk+32 && COLOUR_IS_WHITE(turn)) { // opposition return true; } } else if (wk == wp+15 || wk == wp+16 || wk == wp+17) { if (wp_rank <= Rank4) { if (bk == wk+32 && COLOUR_IS_WHITE(turn)) { // opposition return true; } } } // rook pawn if (wp_file == FileA) { if (DISTANCE(bk,A8) <= 1) return true; if (wk_file == FileA) { if (wp_rank == Rank2) wp_rank++; // HACK if (bk_file == FileC && bk_rank > wp_rank) return true; } } return false; }
static void square_clear(board_t * board, int square, int piece, bool update) { int pos, piece_12, colour; int sq; int i, size; int sq_64; uint64 hash_xor; ASSERT(board!=NULL); ASSERT(SQUARE_IS_OK(square)); ASSERT(piece_is_ok(piece)); ASSERT(update==true||update==false); // init pos = board->pos[square]; ASSERT(pos>=0); piece_12 = PIECE_TO_12(piece); colour = PIECE_COLOUR(piece); // square ASSERT(board->square[square]==piece); board->square[square] = Empty; // piece list if (!PIECE_IS_PAWN(piece)) { // init size = board->piece_size[colour]; ASSERT(size>=1); // stable swap ASSERT(pos>=0&&pos<size); ASSERT(board->pos[square]==pos); board->pos[square] = -1; for (i = pos; i < size-1; i++) { sq = board->piece[colour][i+1]; board->piece[colour][i] = sq; ASSERT(board->pos[sq]==i+1); board->pos[sq] = i; } // size size--; board->piece[colour][size] = SquareNone; board->piece_size[colour] = size; } else { // init size = board->pawn_size[colour]; ASSERT(size>=1); // stable swap ASSERT(pos>=0&&pos<size); ASSERT(board->pos[square]==pos); board->pos[square] = -1; for (i = pos; i < size-1; i++) { sq = board->pawn[colour][i+1]; board->pawn[colour][i] = sq; ASSERT(board->pos[sq]==i+1); board->pos[sq] = i; } // size size--; board->pawn[colour][size] = SquareNone; board->pawn_size[colour] = size; // pawn "bitboard" board->pawn_file[colour][SQUARE_FILE(square)] ^= BIT(PAWN_RANK(square,colour)); } // material ASSERT(board->piece_nb>0); board->piece_nb--; ASSERT(board->number[piece_12]>0); board->number[piece_12]--; board->piece_material[colour] -= VALUE_PIECE(piece); // Thomas // update if (update) { // init sq_64 = SQUARE_TO_64(square); // PST board->opening -= PST(piece_12,sq_64,Opening); board->endgame -= PST(piece_12,sq_64,Endgame); // hash key hash_xor = RANDOM_64(RandomPiece+(piece_12^1)*64+sq_64); // HACK: ^1 for PolyGlot book board->key ^= hash_xor; if (PIECE_IS_PAWN(piece)) board->pawn_key ^= hash_xor; // material key board->material_key ^= RANDOM_64(piece_12*16+board->number[piece_12]); } }