int get_next_tetri(int const fd, t_list **head, char letter) { int ret; char buf[22]; int resval; ret = read(fd, buf, 21); buf[ret] = '\0'; if (!(resval = is_valid(buf)) && *buf) return (0); if (ret != 0) create_piece(head, buf, letter); return (ret); }
/* * Fill the provided list with all pseudolegal captures in the given position. */ static int generate_pseudo_captures(const position_t* pos, move_t* moves) { move_t* moves_head = moves; color_t side = pos->side_to_move; piece_t piece; square_t from; for (int i = 0; i < pos->num_pieces[side]; ++i) { from = pos->pieces[side][i]; piece = pos->board[from]; generate_piece_captures(pos, from, piece, &moves); } piece = create_piece(side, PAWN); for (int i=0; i<pos->num_pawns[side]; ++i) { from = pos->pawns[side][i]; generate_pawn_captures(pos, from, piece, &moves); } *moves = 0; return moves-moves_head; }
/* * Add all pseudo-legal non-capturing promotions. */ static int generate_promotions(const position_t* pos, move_t* moves) { move_t* moves_head = moves; color_t side = pos->side_to_move; piece_t piece = create_piece(side, PAWN); for (int i = 0; i < pos->num_pawns[side]; ++i) { square_t from = pos->pawns[side][i]; rank_t r_rank = relative_rank[side][square_rank(from)]; if (r_rank < RANK_7) continue; square_t to = from + pawn_push[side]; if (pos->board[to]) continue; for (piece_type_t type=KNIGHT; type<=QUEEN; ++type) { moves = add_move(pos, create_move_promote(from, to, piece, EMPTY, type), moves); } } *moves = 0; return (moves-moves_head); }
static void init_army_pieces( army_type * owner ) { unsigned int row = 7*(1-owner->colour); // piece[0].Init( this, row, 3, 4 ); ... create_piece( owner, row, 3, 4 ); // Queen create_piece( owner, row, 0, 3 ); // Rooks create_piece( owner, row, 7, 3 ); create_piece( owner, row, 2, 2 ); // Bishops create_piece( owner, row, 5, 2 ); create_piece( owner, row, 1, 1 ); // Knights create_piece( owner, row, 6, 1 ); create_piece( owner, row, 4, 5 ); // King row = 5*(1-owner->colour)+1; create_piece( owner, row, 0, 0 ); // Pawns create_piece( owner, row, 1, 0 ); create_piece( owner, row, 2, 0 ); create_piece( owner, row, 3, 0 ); create_piece( owner, row, 4, 0 ); create_piece( owner, row, 5, 0 ); create_piece( owner, row, 6, 0 ); create_piece( owner, row, 7, 0 ); } // init_army_pieces()
static void construct_study( army_type army[] ) { char str[10]; unsigned int i, row, col, pc_num, colour; army_type * owner; piece_type * pc; close_open_book( army->sh ); // Automatically create the 2 kings, // prompting user for coords for( i = 0; i < 2; i++ ) { owner = &army[i]; do { printf( "Coordinates of %s king: ", owner->name ); scanf( "%s", str ); } while( !coord_ext_to_int( str, &row, &col ) || !create_piece( owner, row, col, 5 ) ); if( row != 7*(1-i) || col != 4 ) { printf( "Castling disallowed for %s\n", owner->name ); owner->castle_lost[0] = owner->castle_lost[1] = 0; } } /* Allow creation of extra pieces */ for( ; ; ) { print_board( army ); for( i = 0; i < NUM_PIECE_DEFS; i++ ) { printf( "%d: %s ", i, army->sh->pc_def[i].name ); } printf( "\nCreate which piece (-1 to exit): " ); scanf( "%d", &pc_num ); if( pc_num >= NUM_PIECE_DEFS ) break; do { printf( "Colour (white=%d, black=%d): ", O_WHITE, O_BLACK ); scanf( "%d", &colour ); } while( colour >= 2 ); owner = &army[colour]; if( owner->num_pieces >= MAX_ARMY_SIZE ) { printf( "%s already has %d pieces\n", owner->name, owner->num_pieces ); continue; } do { printf( "Coordinates: " ); scanf( "%s", str ); } while( !coord_ext_to_int( str, &row, &col ) || !create_piece( owner, row, col, pc_num ) ); } // Check rooks for castling for( colour = 0; colour <= 1; colour++ ) { // Army num owner = &army[colour]; for( i = 0; i <= 1; i++ ) { // Castle type if( owner->castle_lost[i] == 0 ) continue; pc = read_board(owner,7*(1-colour),7*(1-i)); if( pc == NULL || pc->owner != owner || pc->def->token != ROOK_TOKEN ) { printf( "%sside castling disallowed for %s\n", (i == 0) ? "King" : "Queen", owner->name ); owner->castle_lost[i] = 0; } } } } // construct_study()
/* * Generate all moves that evade check in the given position. This is purely * legal move generation; no pseudo-legal moves. */ int generate_evasions(const position_t* pos, move_t* moves) { assert(pos->is_check && pos->board[pos->check_square]); move_t* moves_head = moves; color_t side = pos->side_to_move, other_side = side^1; square_t king_sq = pos->pieces[side][0]; square_t check_sq = pos->check_square; piece_t king = create_piece(side, KING); piece_t checker = pos->board[check_sq]; // Generate king moves. // Don't let the king mask its possible destination squares in calls // to is_square_attacked. square_t from = king_sq, to = INVALID_SQUARE; ((position_t*)pos)->board[king_sq] = EMPTY; for (const direction_t* delta = piece_deltas[king]; *delta; ++delta) { to = from + *delta; piece_t capture = pos->board[to]; if (capture != EMPTY && !can_capture(king, capture)) continue; if (is_square_attacked((position_t*)pos,to,other_side)) continue; ((position_t*)pos)->board[king_sq] = king; moves = add_move(pos, create_move(from, to, king, capture), moves); ((position_t*)pos)->board[king_sq] = EMPTY; } ((position_t*)pos)->board[king_sq] = king; // If there are multiple checkers, only king moves are possible. if (pos->is_check > 1) { *moves = 0; return moves-moves_head; } // First, the most common case: a check that can be evaded via an // en passant capture. Note that if we're in check and an en passant // capture is available, the only way the en passant capture would evade // the check is if it's the newly moved pawn that's checking us. direction_t pin_dir; if (pos->ep_square != EMPTY && check_sq+pawn_push[side] == pos->ep_square && pos->board[pos->ep_square] == EMPTY) { piece_t our_pawn = create_piece(side, PAWN); to = pos->ep_square; for (int i=0; i<2; ++i) { from = to-piece_deltas[our_pawn][i]; if (pos->board[from] && pos->board[from] == our_pawn) { pin_dir = pin_direction(pos, from, king_sq); if (pin_dir) continue; moves = add_move(pos, create_move_enpassant(from, to, our_pawn, checker), moves); } } } // Generate captures of the checker. for (int i = 0; i < pos->num_pawns[side]; ++i) { from = pos->pawns[side][i]; piece_t piece = create_piece(side, PAWN); pin_dir = pin_direction(pos, from, king_sq); if (pin_dir) continue; if (!possible_attack(from, check_sq, piece)) continue; if (relative_rank[side][square_rank(from)] == RANK_7) { // Capture and promote. for (piece_t promoted=QUEEN; promoted > PAWN; --promoted) { moves = add_move(pos, create_move_promote(from, check_sq, piece, checker, promoted), moves); } } else { moves = add_move(pos, create_move(from, check_sq, piece, checker), moves); } } for (int i = 1; i < pos->num_pieces[side]; ++i) { from = pos->pieces[side][i]; piece_t piece = pos->board[from]; pin_dir = pin_direction(pos, from, king_sq); if (pin_dir) continue; if (!possible_attack(from, check_sq, piece)) continue; if (piece_slide_type(piece) == NONE) { moves = add_move(pos, create_move(from, check_sq, piece, checker), moves); } else { // A sliding piece, keep going until we hit something. direction_t check_dir = direction(from, check_sq); for (to=from+check_dir; pos->board[to] == EMPTY; to+=check_dir) {} if (to == check_sq) { moves = add_move(pos, create_move(from, to, piece, checker), moves); continue; } } } if (piece_slide_type(checker) == NONE) { *moves = 0; return moves-moves_head; } // A slider is doing the checking; generate blocking moves. direction_t block_dir = direction(check_sq, king_sq); for (int i = 0; i < pos->num_pawns[side]; ++i) { from = pos->pawns[side][i]; piece_t piece = create_piece(side, PAWN); direction_t k_dir; pin_dir = pin_direction(pos, from, king_sq); if (pin_dir) continue; to = from + pawn_push[side]; if (pos->board[to] != EMPTY) continue; rank_t rank = relative_rank[side][square_rank(from)]; k_dir = direction(to, king_sq); if (k_dir == block_dir && ((king_sq < to && check_sq > to) || (king_sq > to && check_sq < to))) { if (rank == RANK_7) { // Block and promote. for (piece_t promoted=QUEEN; promoted > PAWN; --promoted) { moves = add_move(pos, create_move_promote(from, to, piece, EMPTY, promoted), moves); } } else { moves = add_move(pos, create_move(from, to, piece, EMPTY), moves); } } if (rank != RANK_2) continue; to += pawn_push[side]; if (pos->board[to]) continue; k_dir = direction(to, king_sq); if (k_dir == block_dir && ((king_sq < to && check_sq > to) || (king_sq > to && check_sq < to))) { moves = add_move(pos, create_move(from, to, piece, EMPTY), moves); } } for (int i=1; i<pos->num_pieces[side]; ++i) { from = pos->pieces[side][i]; piece_t piece = pos->board[from]; direction_t k_dir; pin_dir = pin_direction(pos, from, king_sq); if (pin_dir) continue; if (piece_is_type(piece, KNIGHT)) { for (const direction_t* delta=piece_deltas[piece]; *delta; ++delta) { to = from + *delta; if (pos->board[to] != EMPTY) continue; k_dir = direction(to, king_sq); if (k_dir == block_dir && ((king_sq < to && check_sq > to) || (king_sq > to && check_sq < to))) { moves = add_move(pos, create_move(from, to, piece, EMPTY), moves); } } } else { for (const direction_t* delta=piece_deltas[piece]; *delta; ++delta) { for (to = from+*delta; pos->board[to] == EMPTY; to+=*delta) { k_dir = direction(to, king_sq); if (k_dir == block_dir && ((king_sq < to && check_sq > to) || (king_sq > to && check_sq < to))) { moves = add_move(pos, create_move(from, to, piece, EMPTY), moves); break; } } } } } *moves = 0; return moves-moves_head; }
/* * Generate pseudo-legal moves which are neither captures nor promotions. */ int generate_pseudo_quiet_moves(const position_t* pos, move_t* moves) { move_t* moves_head = moves; color_t side = pos->side_to_move; piece_t piece; square_t from; // Castling. Castles are considered pseudo-legal if we have appropriate // castling rights, the squares between king and rook are unoccupied, // and the intermediate square is unattacked. Therefore checking for // legality just requires seeing if we're in check afterwards. // This is messy for Chess960, so it's separated into separate cases. square_t my_king_home = king_home + side*A8; if (!options.chess960) { if (has_oo_rights(pos, side) && pos->board[my_king_home+1] == EMPTY && pos->board[my_king_home+2] == EMPTY && !is_square_attacked((position_t*)pos,my_king_home+1,side^1)) { assert(pos->board[my_king_home] == create_piece(pos->side_to_move, KING)); moves = add_move(pos, create_move_castle(my_king_home, my_king_home+2, create_piece(side, KING)), moves); } if (has_ooo_rights(pos, side) && pos->board[my_king_home-1] == EMPTY && pos->board[my_king_home-2] == EMPTY && pos->board[my_king_home-3] == EMPTY && !is_square_attacked((position_t*)pos,my_king_home-1,side^1)) { assert(pos->board[my_king_home] == create_piece(pos->side_to_move, KING)); moves = add_move(pos, create_move_castle(my_king_home, my_king_home-2, create_piece(side, KING)), moves); } } else { if (has_oo_rights(pos, side)) { square_t my_f1 = F1 + side*A8; square_t my_g1 = G1 + side*A8; square_t my_kr = king_rook_home + side*A8; bool castle_ok = true; // Check that rook is unimpeded. for (square_t sq = MIN(my_kr, my_f1); sq <= MAX(my_kr, my_f1); ++sq) { if (sq != my_kr && sq != my_king_home && pos->board[sq] != EMPTY) { castle_ok = false; break; } } // Check that the king is unimpeded and unattacked if (castle_ok) { for (square_t sq = MIN(my_king_home, my_g1); sq <= my_g1; ++sq) { if (sq != my_king_home && sq != my_kr && pos->board[sq] != EMPTY) { castle_ok = false; break; } if (sq != my_g1 && is_square_attacked((position_t*)pos, sq, side^1)) { castle_ok = false; break; } } } if (castle_ok) moves = add_move(pos, create_move_castle(my_king_home, my_g1, create_piece(side, KING)), moves); } if (has_ooo_rights(pos, side)) { square_t my_d1 = D1 + side*A8; square_t my_c1 = C1 + side*A8; square_t my_qr = queen_rook_home + side*A8; bool castle_ok = true; // Check that rook is unimpeded. for (square_t sq = MIN(my_qr, my_d1); sq <= MAX(my_qr, my_d1); ++sq) { if (sq != my_qr && sq != my_king_home && pos->board[sq] != EMPTY) { castle_ok = false; break; } } // Check that the king is unimpeded and unattacked if (castle_ok) { for (square_t sq = MIN(my_king_home, my_c1); sq <= MAX(my_king_home, my_c1); ++sq) { if (sq != my_king_home && sq != my_qr && pos->board[sq] != EMPTY) { castle_ok = false; break; } if (sq != my_c1 && is_square_attacked((position_t*)pos, sq, side^1)) { castle_ok = false; break; } } } if (castle_ok) moves = add_move(pos, create_move_castle(my_king_home, my_c1, create_piece(side, KING)), moves); } } for (int i = 0; i < pos->num_pieces[side]; ++i) { from = pos->pieces[side][i]; piece = pos->board[from]; assert(piece_color(piece) == side && piece_type(piece) != PAWN); generate_piece_noncaptures(pos, from, piece, &moves); } piece = create_piece(side, PAWN); for (int i=0; i<pos->num_pawns[side]; ++i) { from = pos->pawns[side][i]; assert(pos->board[from] == piece); generate_pawn_quiet_moves(pos, from, piece, &moves); } *moves = 0; return (moves-moves_head); }