bool piece_attack_king(const board_t * board, int piece, int from, int king) { const inc_t * inc_ptr; int code; const int * delta_ptr; int delta, inc; int to; int sq; ASSERT(board!=NULL); ASSERT(piece_is_ok(piece)); ASSERT(SQUARE_IS_OK(from)); ASSERT(SQUARE_IS_OK(king)); inc_ptr = PIECE_INC(piece); code = PieceCode[piece]; ASSERT(code>=0&&code<4); if (PIECE_IS_SLIDER(piece)) { for (delta_ptr = PieceDeltaDelta[code][DeltaOffset+(king-from)]; (delta=*delta_ptr) != DeltaNone; delta_ptr++) { ASSERT(delta_is_ok(delta)); inc = DeltaIncLine[DeltaOffset+delta]; ASSERT(inc!=IncNone); to = from + delta; sq = from; do { sq += inc; // if (sq == to && SQUARE_IS_OK(to)) { // ASSERT(DISTANCE(to,king)==1); // return true; if (DISTANCE(sq,king)<=2){ return true; } } while (board->square[sq] == Empty); } } else { // non-slider for (delta_ptr = PieceDeltaDelta[code][DeltaOffset+(king-from)]; (delta=*delta_ptr) != DeltaNone; delta_ptr++) { ASSERT(delta_is_ok(delta)); to = from + delta; if (SQUARE_IS_OK(to)) { ASSERT(DISTANCE(to,king)==1); return true; } } } return false; }
void attack_init() { int delta; int dir, inc, dist; for (delta = -128; delta < +128; delta++) { DeltaInc[128+delta] = IncNone; DeltaMask[128+delta] = 0; } DeltaMask[128-17] |= BlackPawnFlag; DeltaMask[128-15] |= BlackPawnFlag; DeltaMask[128+15] |= WhitePawnFlag; DeltaMask[128+17] |= WhitePawnFlag; for (dir = 0; dir < 8; dir++) { delta = KnightInc[dir]; ASSERT(delta_is_ok(delta)); DeltaMask[128+delta] |= KnightFlag; } for (dir = 0; dir < 4; dir++) { inc = BishopInc[dir]; ASSERT(inc!=IncNone); for (dist = 1; dist < 8; dist++) { delta = inc*dist; ASSERT(delta_is_ok(delta)); ASSERT(DeltaInc[128+delta]==IncNone); DeltaInc[128+delta] = inc; DeltaMask[128+delta] |= BishopFlag; } } for (dir = 0; dir < 4; dir++) { inc = RookInc[dir]; ASSERT(inc!=IncNone); for (dist = 1; dist < 8; dist++) { delta = inc*dist; ASSERT(delta_is_ok(delta)); ASSERT(DeltaInc[128+delta]==IncNone); DeltaInc[128+delta] = inc; DeltaMask[128+delta] |= RookFlag; } } for (dir = 0; dir < 8; dir++) { delta = KingInc[dir]; ASSERT(delta_is_ok(delta)); DeltaMask[128+delta] |= KingFlag; } }
void vector_init() { int delta; int x, y; int dist, tmp; // Distance[] for (delta = 0; delta < DeltaNb; delta++) Distance[delta] = -1; for (y = -7; y <= +7; y++) { for (x = -7; x <= +7; x++) { delta = y * 16 + x; ASSERT(delta_is_ok(delta)); dist = 0; tmp = x; if (tmp < 0) tmp = -tmp; if (tmp > dist) dist = tmp; tmp = y; if (tmp < 0) tmp = -tmp; if (tmp > dist) dist = tmp; Distance[DeltaOffset+delta] = dist; } } }
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; }
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 void add_attack(int piece, int king, int target) { int size; int i; ASSERT(piece>=0&&piece<4); ASSERT(delta_is_ok(king)); ASSERT(delta_is_ok(target)); size = PieceDeltaSize[piece][DeltaOffset+king]; ASSERT(size>=0&&size<3); for (i = 0; i < size; i++) { if (PieceDeltaDelta[piece][DeltaOffset+king][i] == target) return; // already in the table } if (size < 2) { PieceDeltaDelta[piece][DeltaOffset+king][size] = target; size++; PieceDeltaSize[piece][DeltaOffset+king] = size; } }
bool line_is_empty(const board_t * board, int from, int to) { int delta; int inc, sq; ASSERT(board!=NULL); ASSERT(SQUARE_IS_OK(from)); ASSERT(SQUARE_IS_OK(to)); delta = to - from; ASSERT(delta_is_ok(delta)); inc = DELTA_INC_ALL(delta); ASSERT(inc!=IncNone); sq = from; do { sq += inc; if (sq == to) return true; } while (board->square[sq] == Empty); return false; // blocker }
bool move_is_pseudo(int move, board_t * board) { int me, opp; int from, to; int piece, capture; int inc, delta; ASSERT(move_is_ok(move)); ASSERT(board!=NULL); ASSERT(!board_is_check(board)); // special cases if (MOVE_IS_SPECIAL(move)) { return move_is_pseudo_debug(move,board); } ASSERT((move&~07777)==0); // init me = board->turn; opp = COLOUR_OPP(board->turn); // from from = MOVE_FROM(move); ASSERT(SQUARE_IS_OK(from)); piece = board->square[from]; if (!COLOUR_IS(piece,me)) return false; ASSERT(piece_is_ok(piece)); // to to = MOVE_TO(move); ASSERT(SQUARE_IS_OK(to)); capture = board->square[to]; if (COLOUR_IS(capture,me)) return false; // move if (PIECE_IS_PAWN(piece)) { if (SQUARE_IS_PROMOTE(to)) return false; inc = PAWN_MOVE_INC(me); delta = to - from; ASSERT(delta_is_ok(delta)); if (capture == Empty) { // pawn push if (delta == inc) return true; if (delta == (2*inc) && PAWN_RANK(from,me) == Rank2 && board->square[from+inc] == Empty) { return true; } } else { // pawn capture if (delta == (inc-1) || delta == (inc+1)) return true; } } else { if (PIECE_ATTACK(board,piece,from,to)) return true; } 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)); }
void attack_init() { int delta, inc; int piece; int dir, dist; int size; int king; int from, to; int pos; // clear for (delta = 0; delta < DeltaNb; delta++) { DeltaIncLine[delta] = IncNone; DeltaIncAll[delta] = IncNone; DeltaMask[delta] = 0; } for (inc = 0; inc < IncNb; inc++) { IncMask[inc] = 0; } // pawn attacks DeltaMask[DeltaOffset-17] |= BlackPawnFlag; DeltaMask[DeltaOffset-15] |= BlackPawnFlag; DeltaMask[DeltaOffset+15] |= WhitePawnFlag; DeltaMask[DeltaOffset+17] |= WhitePawnFlag; // knight attacks for (dir = 0; dir < 8; dir++) { delta = KnightInc[dir]; ASSERT(delta_is_ok(delta)); ASSERT(DeltaIncAll[DeltaOffset+delta]==IncNone); DeltaIncAll[DeltaOffset+delta] = delta; DeltaMask[DeltaOffset+delta] |= KnightFlag; } // bishop/queen attacks for (dir = 0; dir < 4; dir++) { inc = BishopInc[dir]; ASSERT(inc!=IncNone); IncMask[IncOffset+inc] |= BishopFlag; for (dist = 1; dist < 8; dist++) { delta = inc*dist; ASSERT(delta_is_ok(delta)); ASSERT(DeltaIncLine[DeltaOffset+delta]==IncNone); DeltaIncLine[DeltaOffset+delta] = inc; ASSERT(DeltaIncAll[DeltaOffset+delta]==IncNone); DeltaIncAll[DeltaOffset+delta] = inc; DeltaMask[DeltaOffset+delta] |= BishopFlag; } } // rook/queen attacks for (dir = 0; dir < 4; dir++) { inc = RookInc[dir]; ASSERT(inc!=IncNone); IncMask[IncOffset+inc] |= RookFlag; for (dist = 1; dist < 8; dist++) { delta = inc*dist; ASSERT(delta_is_ok(delta)); ASSERT(DeltaIncLine[DeltaOffset+delta]==IncNone); DeltaIncLine[DeltaOffset+delta] = inc; ASSERT(DeltaIncAll[DeltaOffset+delta]==IncNone); DeltaIncAll[DeltaOffset+delta] = inc; DeltaMask[DeltaOffset+delta] |= RookFlag; } } // king attacks for (dir = 0; dir < 8; dir++) { delta = KingInc[dir]; ASSERT(delta_is_ok(delta)); DeltaMask[DeltaOffset+delta] |= KingFlag; } // PieceCode[] for (piece = 0; piece < PieceNb; piece++) { PieceCode[piece] = -1; } PieceCode[WN] = 0; PieceCode[WB] = 1; PieceCode[WR] = 2; PieceCode[WQ] = 3; PieceCode[BN] = 0; PieceCode[BB] = 1; PieceCode[BR] = 2; PieceCode[BQ] = 3; // PieceDeltaSize[][] & PieceDeltaDelta[][][] for (piece = 0; piece < 4; piece++) { for (delta = 0; delta < 256; delta++) { PieceDeltaSize[piece][delta] = 0; } } for (king = 0; king < SquareNb; king++) { if (SQUARE_IS_OK(king)) { for (from = 0; from < SquareNb; from++) { if (SQUARE_IS_OK(from)) { // knight for (pos = 0; (inc=KnightInc[pos]) != IncNone; pos++) { to = from + inc; if (SQUARE_IS_OK(to) && DISTANCE(to,king) == 1) { add_attack(0,king-from,to-from); } } // bishop for (pos = 0; (inc=BishopInc[pos]) != IncNone; pos++) { for (to = from+inc; SQUARE_IS_OK(to); to += inc) { if (DISTANCE(to,king) == 1) { add_attack(1,king-from,to-from); break; } } } // rook for (pos = 0; (inc=RookInc[pos]) != IncNone; pos++) { for (to = from+inc; SQUARE_IS_OK(to); to += inc) { if (DISTANCE(to,king) == 1) { add_attack(2,king-from,to-from); break; } } } // queen for (pos = 0; (inc=QueenInc[pos]) != IncNone; pos++) { for (to = from+inc; SQUARE_IS_OK(to); to += inc) { if (DISTANCE(to,king) == 1) { add_attack(3,king-from,to-from); break; } } } } } } } for (piece = 0; piece < 4; piece++) { for (delta = 0; delta < 256; delta++) { size = PieceDeltaSize[piece][delta]; ASSERT(size>=0&&size<3); PieceDeltaDelta[piece][delta][size] = DeltaNone; } } }