bool piece_attack(const board_t * board, int piece, int from, int to) { int delta; int inc, sq; ASSERT(board_is_ok(board)); ASSERT(piece_is_ok(piece)); ASSERT(square_is_ok(from)); ASSERT(square_is_ok(to)); delta = to - from; ASSERT(delta_is_ok(delta)); if ((piece & DELTA_MASK(delta)) == 0) return false; // no pseudo-attack if (!piece_is_slider(piece)) return true; inc = DELTA_INC(delta); ASSERT(inc_is_ok(inc)); for (sq = from+inc; sq != to; sq += inc) { ASSERT(square_is_ok(sq)); if (board->square[sq] != Empty) return false; // blocker } return true; }
bool is_pinned(const board_t * board, int from, int to, int colour) { int king; int inc; int sq, piece; ASSERT(board!=NULL); ASSERT(square_is_ok(from)); ASSERT(square_is_ok(to)); ASSERT(colour_is_ok(colour)); king = king_pos(board,colour); inc = DELTA_INC(king-from); if (inc == IncNone) return false; // not a line sq = from; do sq += inc; while (board->square[sq] == Empty); if (sq != king) return false; // blocker sq = from; do sq -= inc; while ((piece=board->square[sq]) == Empty); return square_is_ok(sq) && (piece & DELTA_MASK(king-sq)) != 0 && piece_colour(piece) == colour_opp(colour) && DELTA_INC(king-to) != inc; }
static void square_clear(board_t * board, int square, int piece) { int pos, piece_12, colour; int sq, size; ASSERT(board!=NULL); ASSERT(square_is_ok(square)); ASSERT(piece_is_ok(piece)); // init pos = board->pos[square]; ASSERT(pos>=0); colour = piece_colour(piece); piece_12 = piece_to_12(piece); // square ASSERT(board->square[square]==piece); board->square[square] = Empty; ASSERT(board->pos[square]==pos); board->pos[square] = -1; // not needed // piece list ASSERT(board->variant==Horde?board->list_size[colour]>=1:board->list_size[colour]>=2); size = --board->list_size[colour]; ASSERT(pos<=size); if (pos != size) { sq = board->list[colour][size]; ASSERT(square_is_ok(sq)); ASSERT(sq!=square); ASSERT(board->pos[sq]==size); board->pos[sq] = pos; ASSERT(board->list[colour][pos]==square); board->list[colour][pos] = sq; } board->list[colour][size] = SquareNone; // material ASSERT(board->number[piece_12]>=1); board->number[piece_12]--; // hash key board->key ^= random_64(RandomPiece+piece_12*64+square_to_64(square)); }
static void square_set(board_t * board, int square, int piece, int pos) { int piece_12, colour; int sq, size; ASSERT(board!=NULL); ASSERT(square_is_ok(square)); ASSERT(piece_is_ok(piece)); ASSERT(pos>=0); // init colour = piece_colour(piece); piece_12 = piece_to_12(piece); // square ASSERT(board->square[square]==Empty); board->square[square] = piece; ASSERT(board->pos[square]==-1); board->pos[square] = pos; // piece list size = board->list_size[colour]++; ASSERT(board->list[colour][size]==SquareNone); ASSERT(pos<=size); if (pos != size) { sq = board->list[colour][pos]; ASSERT(square_is_ok(sq)); ASSERT(sq!=square); ASSERT(board->pos[sq]==pos); board->pos[sq] = size; ASSERT(board->list[colour][size]==SquareNone); board->list[colour][size] = sq; } board->list[colour][pos] = square; // material ASSERT(board->number[piece_12]<=8); board->number[piece_12]++; // hash key board->key ^= random_64(RandomPiece+piece_12*64+square_to_64(square)); }
int History::move_ordering_score(Piece p, Square to) const { assert(piece_is_ok(p)); assert(square_is_ok(to)); return history[p][to]; }
static void square_move(board_t * board, int from, int to, int piece) { int colour, pos; int piece_index; ASSERT(board!=NULL); ASSERT(square_is_ok(from)); ASSERT(square_is_ok(to)); ASSERT(piece_is_ok(piece)); // 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 ASSERT(board->list[colour][pos]==from); board->list[colour][pos] = to; // hash key piece_index = RandomPiece + piece_to_12(piece) * 64; board->key ^= random_64(piece_index+square_to_64(from)) ^ random_64(piece_index+square_to_64(to)); }
void History::failure(Piece p, Square to, Depth d) { assert(piece_is_ok(p)); assert(square_is_ok(to)); history[p][to] -= int(d) * int(d); // Prevent history underflow if (history[p][to] <= -HistoryMax) for (int i = 0; i < 16; i++) for (int j = 0; j < 64; j++) history[i][j] /= 2; }
void History::success(Piece p, Square to, Depth d) { assert(piece_is_ok(p)); assert(square_is_ok(to)); history[p][to] += int(d) * int(d); // Prevent history overflow if (history[p][to] >= HistoryMax) for (int i = 0; i < 16; i++) for (int j = 0; j < 64; j++) history[i][j] /= 2; }
bool is_attacked(const board_t * board, int to, int colour) { const uint8 * ptr; int from, piece; ASSERT(board_is_ok(board)); ASSERT(square_is_ok(to)); ASSERT(colour_is_ok(colour)); for (ptr = board->list[colour]; (from=*ptr) != SquareNone; ptr++) { piece = board->square[from]; ASSERT(colour_equal(piece,colour)); if (piece_attack(board,piece,from,to)) return true; } return false; }
void init_direction_table() { SquareDelta deltas[8] = { DELTA_E, DELTA_W, DELTA_N, DELTA_S, DELTA_NE, DELTA_SW, DELTA_NW, DELTA_SE }; for(Square s1 = SQ_A1; s1 <= SQ_H8; s1++) for(Square s2 = SQ_A1; s2 <= SQ_H8; s2++) { DirectionTable[s1][s2] = uint8_t(DIR_NONE); SignedDirectionTable[s1][s2] = uint8_t(SIGNED_DIR_NONE); if(s1 == s2) continue; for(SignedDirection d = SIGNED_DIR_E; d <= SIGNED_DIR_SE; d++) { SquareDelta delta = deltas[d]; Square s3, s4; for(s4 = s1 + delta, s3 = s1; square_distance(s4, s3) == 1 && s4 != s2 && square_is_ok(s4); s3 = s4, s4 += delta); if(s4 == s2 && square_distance(s4, s3) == 1) { SignedDirectionTable[s1][s2] = uint8_t(d); DirectionTable[s1][s2] = uint8_t(d/2); break; } } } }
bool board_is_ok(const board_t * board) { int sq, piece; int colour, pos; int king, rook; if (board == NULL) return false; // optional heavy DEBUG mode if (!UseSlowDebug) return true; // squares for (sq = 0; sq < SquareNb; sq++) { piece = board->square[sq]; if (square_is_ok(sq)) { pos = board->pos[sq]; if (piece == Empty) { if (pos != -1) return false; } else { if (pos < 0) return false; if (board->list[piece_colour(piece)][pos] != sq) return false; } } else { if (piece != Knight64) return false; } } // white piece list colour = White; pos = 0; if (board->list_size[colour] <= 0 || board->list_size[colour] > 16) return false; sq = board->list[colour][pos]; if (sq == SquareNone) return false; if (board->pos[sq] != pos) return false; piece = board->square[sq]; if (!colour_equal(piece,colour) || !piece_is_king(piece)) return false; for (pos++; pos < board->list_size[colour]; pos++) { sq = board->list[colour][pos]; if (sq == SquareNone) return false; if (board->pos[sq] != pos) return false; if (!colour_equal(board->square[sq],colour)) return false; } sq = board->list[colour][pos]; if (sq != SquareNone) return false; // black piece list colour = Black; pos = 0; if (board->list_size[colour] <= 0 || board->list_size[colour] > 16) return false; sq = board->list[colour][pos]; if (sq == SquareNone) return false; if (board->pos[sq] != pos) return false; piece = board->square[sq]; if (!colour_equal(piece,colour) || !piece_is_king(piece)) return false; for (pos++; pos < board->list_size[colour]; pos++) { sq = board->list[colour][pos]; if (sq == SquareNone) return false; if (board->pos[sq] != pos) return false; if (!colour_equal(board->square[sq],colour)) return false; } sq = board->list[colour][pos]; if (sq != SquareNone) return false; // TODO: material if (board->number[WhiteKing12] != 1) return false; if (board->number[BlackKing12] != 1) return false; if (!colour_is_ok(board->turn)) return false; // castling status if (board->castle[White][SideH] != SquareNone) { king = board->list[White][0]; if (king < A1 || king > H1) return false; if (board->square[king] != WhiteKing256) return false; rook = board->castle[White][SideH]; if (rook < A1 || rook > H1) return false; if (board->square[rook] != WhiteRook256) return false; if (rook <= king) return false; } if (board->castle[White][SideA] != SquareNone) { king = board->list[White][0]; if (king < A1 || king > H1) return false; if (board->square[king] != WhiteKing256) return false; rook = board->castle[White][SideA]; if (rook < A1 || rook > H1) return false; if (board->square[rook] != WhiteRook256) return false; if (rook >= king) return false; } if (board->castle[Black][SideH] != SquareNone) { king = board->list[Black][0]; if (king < A8 || king > H8) return false; if (board->square[king] != BlackKing256) return false; rook = board->castle[Black][SideH]; if (rook < A8 || rook > H8) return false; if (board->square[rook] != BlackRook256) return false; if (rook <= king) return false; } if (board->castle[Black][SideA] != SquareNone) { king = board->list[Black][0]; if (king < A8 || king > H8) return false; if (board->square[king] != BlackKing256) return false; rook = board->castle[Black][SideA]; if (rook < A8 || rook > H8) return false; if (board->square[rook] != BlackRook256) return false; if (rook >= king) return false; } return true; }