static void add_en_passant_captures(list_t * list, const board_t * board) { int from, to; int me; int inc; int pawn; ASSERT(list!=NULL); ASSERT(board!=NULL); to = board->ep_square; if (to != SquareNone) { me = board->turn; inc = PAWN_MOVE_INC(me); pawn = PAWN_MAKE(me); from = to - (inc-1); if (board->square[from] == pawn) { ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE_FLAGS(from,to,MoveEnPassant)); } from = to - (inc+1); if (board->square[from] == pawn) { ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE_FLAGS(from,to,MoveEnPassant)); } } }
void add_promote(list_t * list, int move) { ASSERT(list!=NULL); ASSERT(move_is_ok(move)); ASSERT((move&~07777)==0); // HACK ASSERT(SQUARE_IS_PROMOTE(MOVE_TO(move))); LIST_ADD(list,move|MovePromoteQueen); LIST_ADD(list,move|MovePromoteKnight); LIST_ADD(list,move|MovePromoteRook); LIST_ADD(list,move|MovePromoteBishop); }
static bool add_pawn_moves(list_t * list, const board_t * board, int to, bool legal, bool stop) { int me; int inc; int pawn; int from; int piece; ASSERT(list!=NULL); ASSERT(board!=NULL); ASSERT(SQUARE_IS_OK(to)); ASSERT(legal==true||legal==false); ASSERT(stop==true||stop==false); ASSERT(board->square[to]==Empty); me = board->turn; inc = PAWN_MOVE_INC(me); pawn = PAWN_MAKE(me); from = to - inc; piece = board->square[from]; if (piece == pawn) { // single push if (!legal || !is_pinned(board,from,me)) { if (stop) return true; add_pawn_move(list,from,to); } } else if (piece == Empty && PAWN_RANK(to,me) == Rank4) { // double push from = to - (2*inc); if (board->square[from] == pawn) { if (!legal || !is_pinned(board,from,me)) { if (stop) return true; ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE(from,to)); } } } return false; }
static int see_rec(alists_t * alists, const board_t * board, int colour, int to, int piece_value) { int from, piece; int value; ASSERT(alists!=NULL); ASSERT(board!=NULL); ASSERT(COLOUR_IS_OK(colour)); ASSERT(SQUARE_IS_OK(to)); ASSERT(piece_value>0); // find the least valuable attacker from = alist_pop(alists->alist[colour],board); if (from == SquareNone) return 0; // no more attackers // find hidden attackers alists_hidden(alists,board,from,to); // calculate the capture value value = +piece_value; // captured piece if (value == ValueKing) return value; // do not allow an answer to a king capture piece = board->square[from]; ASSERT(piece_is_ok(piece)); ASSERT(COLOUR_IS(piece,colour)); piece_value = VALUE_PIECE(piece); // promote if (piece_value == ValuePawn && SQUARE_IS_PROMOTE(to)) { // HACK: PIECE_IS_PAWN(piece) ASSERT(PIECE_IS_PAWN(piece)); piece_value = ValueQueen; value += ValueQueen - ValuePawn; } value -= see_rec(alists,board,COLOUR_OPP(colour),to,piece_value); if (value < 0) value = 0; return value; }
void add_pawn_move(list_t * list, int from, int to) { int move; ASSERT(list!=NULL); ASSERT(SQUARE_IS_OK(from)); ASSERT(SQUARE_IS_OK(to)); move = MOVE_MAKE(from,to); if (SQUARE_IS_PROMOTE(to)) { LIST_ADD(list,move|MovePromoteQueen); LIST_ADD(list,move|MovePromoteKnight); LIST_ADD(list,move|MovePromoteRook); LIST_ADD(list,move|MovePromoteBishop); } else { LIST_ADD(list,move); } }
static void add_quiet_moves(list_t * list, const board_t * board) { int me; const sq_t * ptr; int from, to; int piece; ASSERT(list!=NULL); ASSERT(board!=NULL); me = board->turn; // piece moves for (ptr = &board->piece[me][0]; (from=*ptr) != SquareNone; ptr++) { piece = board->square[from]; switch (PIECE_TYPE(piece)) { case Knight64: to = from - 33; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from - 31; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from - 18; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from - 14; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 14; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 18; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 31; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 33; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); break; case Bishop64: for (to = from-17; board->square[to] == Empty; to -= 17) { LIST_ADD(list,MOVE_MAKE(from,to)); } for (to = from-15; board->square[to] == Empty; to -= 15) { LIST_ADD(list,MOVE_MAKE(from,to)); } for (to = from+15; board->square[to] == Empty; to += 15) { LIST_ADD(list,MOVE_MAKE(from,to)); } for (to = from+17; board->square[to] == Empty; to += 17) { LIST_ADD(list,MOVE_MAKE(from,to)); } break; case Rook64: for (to = from-16; board->square[to] == Empty; to -= 16) { LIST_ADD(list,MOVE_MAKE(from,to)); } for (to = from-1; board->square[to] == Empty; to -= 1) { LIST_ADD(list,MOVE_MAKE(from,to)); } for (to = from+1; board->square[to] == Empty; to += 1) { LIST_ADD(list,MOVE_MAKE(from,to)); } for (to = from+16; board->square[to] == Empty; to += 16) { LIST_ADD(list,MOVE_MAKE(from,to)); } break; case Queen64: for (to = from-17; board->square[to] == Empty; to -= 17) { LIST_ADD(list,MOVE_MAKE(from,to)); } for (to = from-16; board->square[to] == Empty; to -= 16) { LIST_ADD(list,MOVE_MAKE(from,to)); } for (to = from-15; board->square[to] == Empty; to -= 15) { LIST_ADD(list,MOVE_MAKE(from,to)); } for (to = from-1; board->square[to] == Empty; to -= 1) { LIST_ADD(list,MOVE_MAKE(from,to)); } for (to = from+1; board->square[to] == Empty; to += 1) { LIST_ADD(list,MOVE_MAKE(from,to)); } for (to = from+15; board->square[to] == Empty; to += 15) { LIST_ADD(list,MOVE_MAKE(from,to)); } for (to = from+16; board->square[to] == Empty; to += 16) { LIST_ADD(list,MOVE_MAKE(from,to)); } for (to = from+17; board->square[to] == Empty; to += 17) { LIST_ADD(list,MOVE_MAKE(from,to)); } break; case King64: to = from - 17; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from - 16; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from - 15; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from - 1; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 1; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 15; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 16; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 17; if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to)); break; default: ASSERT(false); break; } } // pawn moves if (COLOUR_IS_WHITE(me)) { for (ptr = &board->pawn[me][0]; (from=*ptr) != SquareNone; ptr++) { // non promotes if (SQUARE_RANK(from) != Rank7) { to = from + 16; if (board->square[to] == Empty) { ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE(from,to)); if (SQUARE_RANK(from) == Rank2) { to = from + 32; if (board->square[to] == Empty) { ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE(from,to)); } } } } } } else { // black for (ptr = &board->pawn[me][0]; (from=*ptr) != SquareNone; ptr++) { // non promotes if (SQUARE_RANK(from) != Rank2) { to = from - 16; if (board->square[to] == Empty) { ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE(from,to)); if (SQUARE_RANK(from) == Rank7) { to = from - 32; if (board->square[to] == Empty) { ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE(from,to)); } } } } } } }
static void add_moves(list_t * list, const board_t * board) { int me, opp; int opp_flag; const sq_t * ptr; int from, to; int piece, capture; const inc_t * inc_ptr; int inc; ASSERT(list!=NULL); ASSERT(board!=NULL); me = board->turn; opp = COLOUR_OPP(me); opp_flag = COLOUR_FLAG(opp); // piece moves for (ptr = &board->piece[me][0]; (from=*ptr) != SquareNone; ptr++) { 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; (capture=board->square[to]) == Empty; to += inc) { LIST_ADD(list,MOVE_MAKE(from,to)); } if (FLAG_IS(capture,opp_flag)) { LIST_ADD(list,MOVE_MAKE(from,to)); } } } else { for (; (inc=*inc_ptr) != IncNone; inc_ptr++) { to = from + inc; capture = board->square[to]; if (capture == Empty || FLAG_IS(capture,opp_flag)) { LIST_ADD(list,MOVE_MAKE(from,to)); } } } } // pawn moves inc = PAWN_MOVE_INC(me); for (ptr = &board->pawn[me][0]; (from=*ptr) != SquareNone; ptr++) { to = from + (inc-1); if (FLAG_IS(board->square[to],opp_flag)) { add_pawn_move(list,from,to); } to = from + (inc+1); if (FLAG_IS(board->square[to],opp_flag)) { add_pawn_move(list,from,to); } to = from + inc; if (board->square[to] == Empty) { add_pawn_move(list,from,to); if (PAWN_RANK(from,me) == Rank2) { to = from + (2*inc); if (board->square[to] == Empty) { ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE(from,to)); } } } } }
static bool add_pawn_captures(list_t * list, const board_t * board, int to, bool legal, bool stop) { int me; int inc; int pawn; int from; ASSERT(list!=NULL); ASSERT(board!=NULL); ASSERT(SQUARE_IS_OK(to)); ASSERT(legal==true||legal==false); ASSERT(stop==true||stop==false); ASSERT(COLOUR_IS(board->square[to],COLOUR_OPP(board->turn))); me = board->turn; inc = PAWN_MOVE_INC(me); pawn = PAWN_MAKE(me); from = to - (inc-1); if (board->square[from] == pawn) { if (!legal || !is_pinned(board,from,me)) { if (stop) return true; add_pawn_move(list,from,to); } } from = to - (inc+1); if (board->square[from] == pawn) { if (!legal || !is_pinned(board,from,me)) { if (stop) return true; add_pawn_move(list,from,to); } } if (board->ep_square != SquareNone && to == SQUARE_EP_DUAL(board->ep_square)) { ASSERT(PAWN_RANK(to,me)==Rank5); ASSERT(PIECE_IS_PAWN(board->square[to])); to = board->ep_square; ASSERT(PAWN_RANK(to,me)==Rank6); ASSERT(board->square[to]==Empty); from = to - (inc-1); if (board->square[from] == pawn) { if (!legal || !is_pinned(board,from,me)) { if (stop) return true; ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE_FLAGS(from,to,MoveEnPassant)); } } from = to - (inc+1); if (board->square[from] == pawn) { if (!legal || !is_pinned(board,from,me)) { if (stop) return true; ASSERT(!SQUARE_IS_PROMOTE(to)); LIST_ADD(list,MOVE_MAKE_FLAGS(from,to,MoveEnPassant)); } } } 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 board_is_ok(const board_t * board) { int sq, piece, colour; int size, pos; if (board == NULL) return false; // optional heavy DEBUG mode if (!UseSlowDebug) return true; // squares for (sq = 0; sq < SquareNb; sq++) { piece = board->square[sq]; pos = board->pos[sq]; if (SQUARE_IS_OK(sq)) { // inside square if (piece == Empty) { if (pos != -1) return false; } else { if (!piece_is_ok(piece)) return false; if (!PIECE_IS_PAWN(piece)) { colour = PIECE_COLOUR(piece); if (pos < 0 || pos >= board->piece_size[colour]) return false; if (board->piece[colour][pos] != sq) return false; } else { // pawn if (SQUARE_IS_PROMOTE(sq)) return false; colour = PIECE_COLOUR(piece); if (pos < 0 || pos >= board->pawn_size[colour]) return false; if (board->pawn[colour][pos] != sq) return false; } } } else { // edge square if (piece != Edge) return false; if (pos != -1) return false; } } // piece lists for (colour = 0; colour < ColourNb; colour++) { // piece list size = board->piece_size[colour]; if (size < 1 || size > 16) return false; for (pos = 0; pos < size; pos++) { sq = board->piece[colour][pos]; if (!SQUARE_IS_OK(sq)) return false; if (board->pos[sq] != pos) return false; piece = board->square[sq]; if (!COLOUR_IS(piece,colour)) return false; if (pos == 0 && !PIECE_IS_KING(piece)) return false; if (pos != 0 && PIECE_IS_KING(piece)) return false; if (pos != 0 && PIECE_ORDER(piece) > PIECE_ORDER(board->square[board->piece[colour][pos-1]])) { return false; } } sq = board->piece[colour][size]; if (sq != SquareNone) return false; // pawn list size = board->pawn_size[colour]; if (size < 0 || size > 8) return false; for (pos = 0; pos < size; pos++) { sq = board->pawn[colour][pos]; if (!SQUARE_IS_OK(sq)) return false; if (SQUARE_IS_PROMOTE(sq)) return false; if (board->pos[sq] != pos) return false; piece = board->square[sq]; if (!COLOUR_IS(piece,colour)) return false; if (!PIECE_IS_PAWN(piece)) return false; } sq = board->pawn[colour][size]; if (sq != SquareNone) return false; // piece total if (board->piece_size[colour] + board->pawn_size[colour] > 16) return false; } // material if (board->piece_nb != board->piece_size[White] + board->pawn_size[White] + board->piece_size[Black] + board->pawn_size[Black]) { return false; } if (board->number[WhitePawn12] != board->pawn_size[White]) return false; if (board->number[BlackPawn12] != board->pawn_size[Black]) return false; if (board->number[WhiteKing12] != 1) return false; if (board->number[BlackKing12] != 1) return false; // misc if (!COLOUR_IS_OK(board->turn)) return false; if (board->ply_nb < 0) return false; if (board->sp < board->ply_nb) return false; if (board->cap_sq != SquareNone && !SQUARE_IS_OK(board->cap_sq)) return false; if (board->opening != board_opening(board)) return false; if (board->endgame != board_endgame(board)) return false; if (board->key != hash_key(board)) return false; if (board->pawn_key != hash_pawn_key(board)) return false; if (board->material_key != hash_material_key(board)) return false; return true; }
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)); }
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; }