void board_from_fen(board_t * board, const char fen[]) { int pos; int file, rank, sq; int c; int i, len; int piece; int pawn; ASSERT(board!=NULL); ASSERT(fen!=NULL); board_clear(board); pos = 0; c = fen[pos]; // piece placement for (rank = Rank8; rank >= Rank1; rank--) { for (file = FileA; file <= FileH;) { if (c >= '1' && c <= '8') { // empty square(s) len = c - '0'; for (i = 0; i < len; i++) { if (file > FileH) my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); board->square[SQUARE_MAKE(file,rank)] = Empty; file++; } } else { // piece piece = piece_from_char(c); if (piece == PieceNone256) my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); board->square[SQUARE_MAKE(file,rank)] = piece; file++; } c = fen[++pos]; } if (rank > Rank1) { if (c != '/') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); c = fen[++pos]; } } // active colour if (c != ' ') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); c = fen[++pos]; switch (c) { case 'w': board->turn = White; break; case 'b': board->turn = Black; break; default: my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); break; } c = fen[++pos]; // castling if (c != ' ') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); c = fen[++pos]; board->flags = FlagsNone; if (c == '-') { // no castling rights c = fen[++pos]; } else { if (c == 'K') { if (board->square[E1] == WK && board->square[H1] == WR) board->flags |= FlagsWhiteKingCastle; c = fen[++pos]; } if (c == 'Q') { if (board->square[E1] == WK && board->square[A1] == WR) board->flags |= FlagsWhiteQueenCastle; c = fen[++pos]; } if (c == 'k') { if (board->square[E8] == BK && board->square[H8] == BR) board->flags |= FlagsBlackKingCastle; c = fen[++pos]; } if (c == 'q') { if (board->square[E8] == BK && board->square[A8] == BR) board->flags |= FlagsBlackQueenCastle; c = fen[++pos]; } } // en-passant if (c != ' ') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); c = fen[++pos]; if (c == '-') { // no en-passant sq = SquareNone; c = fen[++pos]; } else { if (c < 'a' || c > 'h') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); file = file_from_char(c); c = fen[++pos]; if (c != (COLOUR_IS_WHITE(board->turn) ? '6' : '3')) my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); rank = rank_from_char(c); c = fen[++pos]; sq = SQUARE_MAKE(file,rank); pawn = SQUARE_EP_DUAL(sq); if (board->square[sq] != Empty || board->square[pawn] != PAWN_MAKE(COLOUR_OPP(board->turn)) || (board->square[pawn-1] != PAWN_MAKE(board->turn) && board->square[pawn+1] != PAWN_MAKE(board->turn))) { sq = SquareNone; } } board->ep_square = sq; // halfmove clock board->ply_nb = 0; if (c != ' ') { if (!Strict) goto update; my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); } c = fen[++pos]; if (!isdigit(c)) { if (!Strict) goto update; my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); } board->ply_nb = atoi(&fen[pos]); // board update update: board_init_list(board); }
static void parse_go(char string[]) { const char * ptr; bool infinite, ponder; int depth, mate, movestogo; sint64 nodes; double binc, btime, movetime, winc, wtime; double time, inc; double time_max, alloc; // init infinite = false; ponder = false; depth = -1; mate = -1; movestogo = -1; nodes = -1; binc = -1.0; btime = -1.0; movetime = -1.0; winc = -1.0; wtime = -1.0; // parse ptr = strtok(string," "); // skip "go" for (ptr = strtok(NULL," "); ptr != NULL; ptr = strtok(NULL," ")) { if (false) { } else if (string_equal(ptr,"binc")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); binc = double(atoi(ptr)) / 1000.0; ASSERT(binc>=0.0); } else if (string_equal(ptr,"btime")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); btime = double(atoi(ptr)) / 1000.0; ASSERT(btime>=0.0); } else if (string_equal(ptr,"depth")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); depth = atoi(ptr); ASSERT(depth>=0); } else if (string_equal(ptr,"infinite")) { infinite = true; } else if (string_equal(ptr,"mate")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); mate = atoi(ptr); ASSERT(mate>=0); } else if (string_equal(ptr,"movestogo")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); movestogo = atoi(ptr); ASSERT(movestogo>=0); } else if (string_equal(ptr,"movetime")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); movetime = double(atoi(ptr)) / 1000.0; ASSERT(movetime>=0.0); } else if (string_equal(ptr,"nodes")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); nodes = my_atoll(ptr); ASSERT(nodes>=0); } else if (string_equal(ptr,"ponder")) { ponder = true; } else if (string_equal(ptr,"searchmoves")) { // dummy } else if (string_equal(ptr,"winc")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); winc = double(atoi(ptr)) / 1000.0; ASSERT(winc>=0.0); } else if (string_equal(ptr,"wtime")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); wtime = double(atoi(ptr)) / 1000.0; ASSERT(wtime>=0.0); } } // init search_clear(); // depth limit // JAS int option_depth = 0; option_depth = option_get_int("Search Depth"); if (option_depth > 0) { depth = option_depth; } // JAS end if (depth >= 0) { SearchInput->depth_is_limited = true; SearchInput->depth_limit = depth; } else if (mate >= 0) { SearchInput->depth_is_limited = true; SearchInput->depth_limit = mate * 2 - 1; // HACK: move -> ply } // time limit if (COLOUR_IS_WHITE(SearchInput->board->turn)) { time = wtime; inc = winc; } else { time = btime; inc = binc; } if (movestogo <= 0 || movestogo > 30) movestogo = 20; // HACK was 30 if (inc < 0.0) inc = 0.0; // JAS int option_movetime = 0; option_movetime = option_get_int("Search Time"); if (option_movetime > 0) { movetime = option_movetime; } // JAS end if (movetime >= 0.0) { // fixed time SearchInput->time_is_limited = true; SearchInput->time_limit_1 = movetime * 5.0; // HACK to avoid early exit SearchInput->time_limit_2 = movetime; } else if (time >= 0.0) { // dynamic allocation time_max = time * 0.95 - 1.0; if (time_max < 0.0) time_max = 0.0; SearchInput->time_is_limited = true; alloc = (time_max + inc * double(movestogo-1)) / double(movestogo); alloc *= (option_get_bool("Ponder") ? PonderRatio : NormalRatio); if (alloc > time_max) alloc = time_max; SearchInput->time_limit_1 = alloc; alloc = (time_max + inc * double(movestogo-1)) * 0.5; if (alloc < SearchInput->time_limit_1) alloc = SearchInput->time_limit_1; if (alloc > time_max) alloc = time_max; SearchInput->time_limit_2 = alloc; } if (infinite || ponder) SearchInput->infinite = true; // search ASSERT(!Searching); ASSERT(!Delay); Searching = true; Infinite = infinite || ponder; Delay = false; search(); search_update_current(); ASSERT(Searching); ASSERT(!Delay); Searching = false; Delay = Infinite; if (!Delay) send_best_move(); }
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 board_to_fen(const board_t * board, char fen[], int size) { int pos; int file, rank; int sq, piece; int c; int len; ASSERT(board!=NULL); ASSERT(fen!=NULL); ASSERT(size>=92); // init if (size < 92) return false; pos = 0; // piece placement for (rank = Rank8; rank >= Rank1; rank--) { for (file = FileA; file <= FileH;) { sq = SQUARE_MAKE(file,rank); piece = board->square[sq]; ASSERT(piece==Empty||piece_is_ok(piece)); if (piece == Empty) { len = 0; for (; file <= FileH && board->square[SQUARE_MAKE(file,rank)] == Empty; file++) { len++; } ASSERT(len>=1&&len<=8); c = '0' + len; } else { c = piece_to_char(piece); file++; } fen[pos++] = c; } fen[pos++] = '/'; } fen[pos-1] = ' '; // HACK: remove the last '/' // active colour fen[pos++] = (COLOUR_IS_WHITE(board->turn)) ? 'w' : 'b'; fen[pos++] = ' '; // castling if (board->flags == FlagsNone) { fen[pos++] = '-'; } else { if ((board->flags & FlagsWhiteKingCastle) != 0) fen[pos++] = 'K'; if ((board->flags & FlagsWhiteQueenCastle) != 0) fen[pos++] = 'Q'; if ((board->flags & FlagsBlackKingCastle) != 0) fen[pos++] = 'k'; if ((board->flags & FlagsBlackQueenCastle) != 0) fen[pos++] = 'q'; } fen[pos++] = ' '; // en-passant if (board->ep_square == SquareNone) { fen[pos++] = '-'; } else { square_to_string(board->ep_square,&fen[pos],3); pos += 2; } fen[pos++] = ' '; // halfmove clock sprintf(&fen[pos],"%d 1",board->ply_nb); return true; }
static void parse_go(char string[]) { const char * ptr; bool infinite, ponder; int depth, mate, movestogo; sint64 nodes; double binc, btime, movetime, winc, wtime; double time, inc; // init infinite = false; ponder = false; depth = -1; mate = -1; movestogo = -1; nodes = -1; binc = -1.0; btime = -1.0; movetime = -1.0; winc = -1.0; wtime = -1.0; // parse ptr = strtok(string," "); // skip "go" for (ptr = strtok(NULL," "); ptr != NULL; ptr = strtok(NULL," ")) { if (false) { } else if (string_equal(ptr,"binc")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); binc = double(atoi(ptr)) / 1000.0; ASSERT(binc>=0.0); } else if (string_equal(ptr,"btime")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); btime = double(atoi(ptr)) / 1000.0; ASSERT(btime>=0.0); } else if (string_equal(ptr,"depth")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); depth = atoi(ptr); ASSERT(depth>=0); } else if (string_equal(ptr,"infinite")) { infinite = true; } else if (string_equal(ptr,"mate")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); mate = atoi(ptr); ASSERT(mate>=0); } else if (string_equal(ptr,"movestogo")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); movestogo = atoi(ptr); ASSERT(movestogo>=0); } else if (string_equal(ptr,"movetime")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); movetime = double(atoi(ptr)) / 1000.0; ASSERT(movetime>=0.0); } else if (string_equal(ptr,"nodes")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); nodes = my_atoll(ptr); ASSERT(nodes>=0); } else if (string_equal(ptr,"ponder")) { ponder = true; } else if (string_equal(ptr,"searchmoves")) { // dummy } else if (string_equal(ptr,"winc")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); winc = double(atoi(ptr)) / 1000.0; ASSERT(winc>=0.0); } else if (string_equal(ptr,"wtime")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); wtime = double(atoi(ptr)) / 1000.0; ASSERT(wtime>=0.0); } } // init search_clear(); tb_clear(); egbb_clear(); eval_init_options(); // depth limit if (depth >= 0) { SearchInput->depth_is_limited = true; SearchInput->depth_limit = depth; } else if (mate >= 0) { SearchInput->depth_is_limited = true; SearchInput->depth_limit = mate * 2 - 1; // HACK: move -> ply } // nodes limit if (nodes > 0) { if (nodes < 1000) nodes = 1000; SearchInput->nodes_is_limited = true; SearchInput->nodes = nodes; } // time limit if (COLOUR_IS_WHITE(SearchInput->board->turn)) { time = wtime; inc = winc; } else { time = btime; inc = binc; } if (movestogo <= 0 || movestogo > 30) movestogo = 30; // HACK if (inc < 0.0) inc = 0.0; if (movetime >= 0.0) { // fixed time SearchInput->time_is_limited = true; SearchInput->time_limit_1 = movetime * 5.0; // HACK to avoid early exit SearchInput->time_limit_2 = movetime; } else if (time >= 0.0) { SearchInput->time_is_limited = true; time_allocation(time,inc,movestogo); } if (infinite || ponder) SearchInput->infinite = true; // search ASSERT(!Searching); ASSERT(!Delay); Searching = true; Infinite = infinite || ponder; Delay = false; search(); search_update_current(); ASSERT(Searching); ASSERT(!Delay); Searching = false; Delay = Infinite; if (!Delay) send_best_move(); }
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; }
uint64 hash_turn_key(int colour) { ASSERT(COLOUR_IS_OK(colour)); return (COLOUR_IS_WHITE(colour)) ? RANDOM_64(RandomTurn) : 0; }
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_captures(list_t * list, const board_t * board) { int me, opp; int opp_flag; const sq_t * ptr; int from, to; int piece, capture; ASSERT(list!=NULL); ASSERT(board!=NULL); me = board->turn; opp = COLOUR_OPP(me); opp_flag = COLOUR_FLAG(opp); // piece captures for (ptr = &board->piece[me][0]; (from=*ptr) != SquareNone; ptr++) { piece = board->square[from]; switch (PIECE_TYPE(piece)) { case Knight64: to = from - 33; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from - 31; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from - 18; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from - 14; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 14; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 18; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 31; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 33; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); break; case Bishop64: for (to = from-17; (capture=board->square[to]) == Empty; to -= 17) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); for (to = from-15; (capture=board->square[to]) == Empty; to -= 15) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); for (to = from+15; (capture=board->square[to]) == Empty; to += 15) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); for (to = from+17; (capture=board->square[to]) == Empty; to += 17) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); break; case Rook64: for (to = from-16; (capture=board->square[to]) == Empty; to -= 16) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); for (to = from-1; (capture=board->square[to]) == Empty; to -= 1) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); for (to = from+1; (capture=board->square[to]) == Empty; to += 1) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); for (to = from+16; (capture=board->square[to]) == Empty; to += 16) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); break; case Queen64: for (to = from-17; (capture=board->square[to]) == Empty; to -= 17) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); for (to = from-16; (capture=board->square[to]) == Empty; to -= 16) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); for (to = from-15; (capture=board->square[to]) == Empty; to -= 15) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); for (to = from-1; (capture=board->square[to]) == Empty; to -= 1) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); for (to = from+1; (capture=board->square[to]) == Empty; to += 1) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); for (to = from+15; (capture=board->square[to]) == Empty; to += 15) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); for (to = from+16; (capture=board->square[to]) == Empty; to += 16) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); for (to = from+17; (capture=board->square[to]) == Empty; to += 17) ; if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); break; case King64: to = from - 17; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from - 16; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from - 15; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from - 1; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 1; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 15; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 16; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); to = from + 17; if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to)); break; default: ASSERT(false); break; } } // pawn captures if (COLOUR_IS_WHITE(me)) { for (ptr = &board->pawn[me][0]; (from=*ptr) != SquareNone; ptr++) { to = from + 15; if (FLAG_IS(board->square[to],opp_flag)) add_pawn_move(list,from,to); to = from + 17; if (FLAG_IS(board->square[to],opp_flag)) add_pawn_move(list,from,to); // promote if (SQUARE_RANK(from) == Rank7) { to = from + 16; if (board->square[to] == Empty) { add_promote(list,MOVE_MAKE(from,to)); } } } } else { // black for (ptr = &board->pawn[me][0]; (from=*ptr) != SquareNone; ptr++) { to = from - 17; if (FLAG_IS(board->square[to],opp_flag)) add_pawn_move(list,from,to); to = from - 15; if (FLAG_IS(board->square[to],opp_flag)) add_pawn_move(list,from,to); // promote if (SQUARE_RANK(from) == Rank2) { to = from - 16; if (board->square[to] == Empty) { add_promote(list,MOVE_MAKE(from,to)); } } } } }