/*
 * Add all pseudo-legal non-capturing moves that the given piece (N/B/Q/K)
 * can make, with the exception of castles.
 */
static void generate_piece_noncaptures(const position_t* pos,
        square_t from,
        piece_t piece,
        move_t** moves_head)
{
    move_t* moves = *moves_head;
    square_t to;
    if (piece_slide_type(piece) == NONE) {
        // not a sliding piece, just iterate over dest. squares
        for (const direction_t* delta = piece_deltas[piece]; *delta; ++delta) {
            to = from + *delta;
            if (pos->board[to] != EMPTY) continue;
            moves = add_move(pos,
                    create_move(from, to, piece, NONE),
                    moves);
        }
    } else {
        // a sliding piece, keep going until we hit something
        for (const direction_t* delta = piece_deltas[piece]; *delta; ++delta) {
            to = from + *delta;
            while (pos->board[to] == EMPTY) {
                moves = add_move(pos,
                        create_move(from, to, piece, NONE),
                        moves);
                to += *delta;
            }
        }
    }
    *moves_head = moves;
}
/*
 * Add all pseudo-legal captures that the given pawn can make.
 */
static void generate_pawn_captures(const position_t* pos,
        square_t from,
        piece_t piece,
        move_t** moves_head)
{
    color_t side = pos->side_to_move;
    int cap_left = side == WHITE ? 15 : -15;
    int cap_right = side == WHITE ? 17 : -17;
    square_t to;
    rank_t r_rank = relative_rank[side][square_rank(from)];
    move_t* moves = *moves_head;
    if (r_rank < RANK_7) {
        // non-promote captures
        to = from + cap_left;
        if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
            moves = add_move(pos, create_move(from, to, piece,
                    pos->board[to]), moves);
        } else if (to == pos->ep_square && pos->board[to] == EMPTY) {
            moves = add_move(pos, create_move_enpassant(from, to, piece,
                    pos->board[to + pawn_push[side^1]]), moves);
        }
        to = from + cap_right;
        if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
            moves = add_move(pos, create_move(from, to, piece,
                    pos->board[to]), moves);
        } else if (to == pos->ep_square && pos->board[to] == EMPTY) {
            moves = add_move(pos, create_move_enpassant(from, to, piece,
                    pos->board[to + pawn_push[side^1]]), moves);
        }
    } else {
        // capture/promotes
        to = from + cap_left;
        if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
            for (piece_t promoted=QUEEN; promoted > PAWN; --promoted) {
                moves = add_move(pos, create_move_promote(from, to, piece,
                        pos->board[to], promoted), moves);
            }
        }
        to = from + cap_right;
        if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
            for (piece_t promoted=QUEEN; promoted > PAWN; --promoted) {
                moves = add_move(pos, create_move_promote(from, to, piece,
                        pos->board[to], promoted), moves);
            }
        }
    }
    *moves_head = moves;
}
Exemplo n.º 3
0
int get_valid_move_count(int x, int y, enum cell_contents board[][BOARD_WIDTH])
{
	int count = 0;
	struct move move;

	/* check all four directions */
	move = create_move(x, y, x - 2, y);
	if (is_valid_move(move, board, NULL)) count++;
	move = create_move(x, y, x + 2, y);
	if (is_valid_move(move, board, NULL)) count++;
	move = create_move(x, y, x, y - 2);
	if (is_valid_move(move, board, NULL)) count++;
	move = create_move(x, y, x, y + 2);
	if (is_valid_move(move, board, NULL)) count++;

	return count;
}
/*
 * Generate all non-capturing, non-promoting pawn moves.
 */
static void generate_pawn_quiet_moves(const position_t* pos,
        square_t from,
        piece_t piece,
        move_t** moves_head)
{
    color_t side = pos->side_to_move;
    square_t to;
    rank_t r_rank = relative_rank[side][square_rank(from)];
    move_t* moves = *moves_head;
    to = from + pawn_push[side];
    if (r_rank == RANK_7 || pos->board[to] != EMPTY) return;
    moves = add_move(pos, create_move(from, to, piece, EMPTY), moves);
    to += pawn_push[side];
    if (r_rank == RANK_2 && pos->board[to] == EMPTY) {
        // initial two-square push
        moves = add_move(pos,
                create_move(from, to, piece, EMPTY),
                moves);
    }
    *moves_head = moves;
}
Exemplo n.º 5
0
Move str_to_move(char *string)
{
    for(int i = 0; i < 4; i += 1)
        if(string[i] == '\0') return 0;
    if(!((string[0] >= 'a' && string[0] <= 'h') &&
         (string[1] >= '1' && string[1] <= '8') &&
         (string[2] >= 'a' && string[2] <= 'h') &&
         (string[3] >= '1' && string[3] <= '8'))) return 0;
    
    int from = ('8' - string[1] + 2) * 10 + (string[0] - 'a' + 1);
    int to   = ('8' - string[3] + 2) * 10 + (string[2] - 'a' + 1);
    int broken = board[to];
    int turn = 0;
    switch(string[4])
    {
        case 'q':  turn = create_figure(turn_to_move, QUEEN); break;
        case 'r':  turn = create_figure(turn_to_move, ROOK); break;
        case 'b':  turn = create_figure(turn_to_move, BISHOP); break;
        case 'n':  turn = create_figure(turn_to_move, KNIGHT); break;
    }
    return create_move(from, to, broken, turn);
}
Exemplo n.º 6
0
int
movegen(struct Game* game, int move_count)
{
    U64 temp_move, temp_move2, temp_piece;
    U32 from, to, move;

    U64 free_squares = game->board[OCCUPIED][0];

    if (game->to_move == WHITE)
    {
        /***************/
        /* WHITE PAWNS */
        /***************/
        temp_move = step_up(game->board[PAWNS][WHITE]) & free_squares;
        temp_move2 = temp_move;

        /* single pushes */
        while (temp_move)
        {
            to = bit_scan_forward(temp_move);
            if (to/8 == 7)
            { /* time for a promotion */
                game->move_buffer[move_count++] = create_move(to-8,to,BISHOP_PROMO_FLAG);
                game->move_buffer[move_count++] = create_move(to-8,to,KNIGHT_PROMO_FLAG);
                game->move_buffer[move_count++] = create_move(to-8,to,ROOK_PROMO_FLAG);
                game->move_buffer[move_count++] = create_move(to-8,to,QUEEN_PROMO_FLAG);
            } else game->move_buffer[move_count++] = create_move(to-8,to,QUIET_FLAG);
            temp_move &= temp_move - 1;
        }

        /* double pushes */
        temp_move2 = step_up(temp_move2) & free_squares & rank4;
        while (temp_move2)
        {
            to = bit_scan_forward(temp_move2);
            game->move_buffer[move_count++] = create_move(to-16,to,DOUBLE_PAWN_PUSH_FLAG);
            temp_move2 &= temp_move2 - 1;
        }

        /* captures */
        /* TODO: add en passante capture */
        temp_piece = game->board[PAWNS][WHITE];
        while (temp_piece)
        {
            from = bit_scan_forward(temp_piece);
            temp_move = pawn_attacks[WHITE][from] & game->board[PIECES][BLACK];
            while (temp_move)
            {
                to = bit_scan_forward(temp_move);
                if (to/8 == 7)
                { /* time for a promotion */
                    game->move_buffer[move_count++] = create_move(from,to,BISHOP_PROMO_CAPTURE_FLAG);
                    game->move_buffer[move_count++] = create_move(from,to,KNIGHT_PROMO_CAPTURE_FLAG);
                    game->move_buffer[move_count++] = create_move(from,to,ROOK_PROMO_CAPTURE_FLAG);
                    game->move_buffer[move_count++] = create_move(from,to,QUEEN_PROMO_CAPTURE_FLAG);
                } else game->move_buffer[move_count++] = create_move(from,to,CAPTURE_FLAG);
                temp_move &= temp_move - 1;
            }
            temp_piece &= temp_piece - 1;
        }

        /*****************/
        /* WHITE KNIGHTS */
        /*****************/
        temp_piece = game->board[KNIGHTS][WHITE];
        while (temp_piece)
        {
            from = bit_scan_forward(temp_piece);

            /* quiets */
            temp_move = knight_table[from] & free_squares;
            while (temp_move)
            {
                to = bit_scan_forward(temp_move);
                game->move_buffer[move_count++] = create_move(from,to,QUIET_FLAG);
                temp_move &= temp_move - 1;
            }

            /* captures */
            temp_move = knight_table[from] & game->board[PIECES][BLACK];
            while (temp_move)
            {
                to = bit_scan_forward(temp_move);
                game->move_buffer[move_count++] = create_move(from,to,CAPTURE_FLAG);
                temp_move &= temp_move - 1;
            }

            temp_piece &= temp_piece - 1;
        }

        /*****************/
        /* WHITE BISHOPS */
        /*****************/
        temp_piece = game->board[BISHOPS][WHITE];
        while (temp_piece)
        {
            from = bit_scan_forward(temp_piece);
            temp_move2 = get_bishop_attacks(game->board[OCCUPIED][1], from);

            /* quiets */
            temp_move = temp_move2 & free_squares;
            while (temp_move)
            {
                to = bit_scan_forward(temp_move);
                game->move_buffer[move_count++] = create_move(from,to,QUIET_FLAG);
                temp_move &= temp_move - 1;
            }

            /* captures */
            temp_move = temp_move2 & game->board[PIECES][BLACK];
            while (temp_move)
            {
                to = bit_scan_forward(temp_move);
                game->move_buffer[move_count++] = create_move(from,to,CAPTURE_FLAG);
                temp_move &= temp_move - 1;
            }

            temp_piece &= temp_piece - 1;
        }

        /***************/
        /* WHITE ROOKS */
        /***************/
        temp_piece = game->board[ROOKS][WHITE];
        while (temp_piece)
        {
            from = bit_scan_forward(temp_piece);
            temp_move2 = get_rook_attacks(game->board[OCCUPIED][1], from);

            /* quiets */
            temp_move = temp_move2 & free_squares;
            while (temp_move)
            {
                to = bit_scan_forward(temp_move);
                game->move_buffer[move_count++] = create_move(from,to,QUIET_FLAG);
                temp_move &= temp_move - 1;
            }

            /* captures */
            temp_move = temp_move2 & game->board[PIECES][BLACK];
            while (temp_move)
            {
                to = bit_scan_forward(temp_move);
                game->move_buffer[move_count++] = create_move(from,to,CAPTURE_FLAG);
                temp_move &= temp_move - 1;
            }

            temp_piece &= temp_piece - 1;
        }

        /****************/
        /* WHITE QUEENS */
        /****************/
        temp_piece = game->board[QUEENS][WHITE];
        while (temp_piece)
        {
            from = bit_scan_forward(temp_piece);
            temp_move2 = get_queen_attacks(game->board[OCCUPIED][1], from);

            /* quiets */
            temp_move = temp_move2 & free_squares;
            while (temp_move)
            {
                to = bit_scan_forward(temp_move);
                game->move_buffer[move_count++] = create_move(from,to,QUIET_FLAG);
                temp_move &= temp_move - 1;
            }

            /* captures */
            temp_move = temp_move2 & game->board[PIECES][BLACK];
            while (temp_move)
            {
                to = bit_scan_forward(temp_move);
                game->move_buffer[move_count++] = create_move(from,to,CAPTURE_FLAG);
                temp_move &= temp_move - 1;
            }

            temp_piece &= temp_piece - 1;
        }

        /**************/
        /* WHITE KINGS */
        /**************/
        temp_piece = game->board[KINGS][WHITE];
        from = bit_scan_forward(temp_piece);

        /* quiets */
        temp_move = king_table[from] & free_squares;
        while (temp_move)
        {
            to = bit_scan_forward(temp_move);
            game->move_buffer[move_count++] = create_move(from,to,QUIET_FLAG);
            temp_move &= temp_move - 1;
        }

        /* captures */
        temp_move = king_table[from] & game->board[PIECES][BLACK];
        while (temp_move)
        {
            to = bit_scan_forward(temp_move);
            game->move_buffer[move_count++] = create_move(from,to,CAPTURE_FLAG);
            temp_move &= temp_move - 1;
        }

        /* TODO: add castling moves here after writing is_attacked function */

    } else { /* to_move == BLACK */
        /***************/
        /* BLACK PAWNS */
        /***************/
        temp_move = step_down(game->board[PAWNS][BLACK]) & free_squares;
        temp_move2 = temp_move;

        /* single pushes */
        while (temp_move)
        {
            to = bit_scan_forward(temp_move);
            if (to/8 == 0)
            { /* time for a promotion */
                game->move_buffer[move_count++] = create_move(to+8,to,BISHOP_PROMO_FLAG);
                game->move_buffer[move_count++] = create_move(to+8,to,KNIGHT_PROMO_FLAG);
                game->move_buffer[move_count++] = create_move(to+8,to,ROOK_PROMO_FLAG);
                game->move_buffer[move_count++] = create_move(to+8,to,QUEEN_PROMO_FLAG);
            } else game->move_buffer[move_count++] = create_move(to+8,to,QUIET_FLAG);
            temp_move &= temp_move - 1;
        }

        /* double pushes */
        temp_move2 = step_down(temp_move2) & free_squares & rank5;
        while (temp_move2)
        {
            to = bit_scan_forward(temp_move2);
            game->move_buffer[move_count++] = create_move(to+16,to,DOUBLE_PAWN_PUSH_FLAG);
            temp_move2 &= temp_move2 - 1;
        }

        /* captures */
        /* TODO: add en passante capture */
        temp_piece = game->board[PAWNS][BLACK];
        while (temp_piece)
        {
            from = bit_scan_forward(temp_piece);
            temp_move = pawn_attacks[BLACK][from] & game->board[PIECES][WHITE];
            while (temp_move)
            {
                to = bit_scan_forward(temp_move);
                if (to/8 == 7)
                { /* time for a promotion */
                    game->move_buffer[move_count++] = create_move(from,to,BISHOP_PROMO_CAPTURE_FLAG);
                    game->move_buffer[move_count++] = create_move(from,to,KNIGHT_PROMO_CAPTURE_FLAG);
                    game->move_buffer[move_count++] = create_move(from,to,ROOK_PROMO_CAPTURE_FLAG);
                    game->move_buffer[move_count++] = create_move(from,to,QUEEN_PROMO_CAPTURE_FLAG);
                } else game->move_buffer[move_count++] = create_move(from,to,CAPTURE_FLAG);
                temp_move &= temp_move - 1;
            }
            temp_piece &= temp_piece - 1;
        }

        /*****************/
        /* BLACK KNIGHTS */
        /*****************/
        temp_piece = game->board[KNIGHTS][BLACK];
        while (temp_piece)
        {
            from = bit_scan_forward(temp_piece);

            /* quiets */
            temp_move = knight_table[from] & free_squares;
            while (temp_move)
            {
                to = bit_scan_forward(temp_move);
                game->move_buffer[move_count++] = create_move(from,to,QUIET_FLAG);
                temp_move &= temp_move - 1;
            }

            /* captures */
            temp_move = knight_table[from] & game->board[PIECES][WHITE];
            while (temp_move)
            {
                to = bit_scan_forward(temp_move);
                game->move_buffer[move_count++] = create_move(from,to,CAPTURE_FLAG);
                temp_move &= temp_move - 1;
            }

            temp_piece &= temp_piece - 1;
        }

        /*****************/
        /* BLACK BISHOPS */
        /*****************/
        temp_piece = game->board[BISHOPS][BLACK];
        while (temp_piece)
        {
            from = bit_scan_forward(temp_piece);
            temp_move2 = get_bishop_attacks(game->board[OCCUPIED][1], from);

            /* quiets */
            temp_move = temp_move2 & free_squares;
            while (temp_move)
            {
                to = bit_scan_forward(temp_move);
                game->move_buffer[move_count++] = create_move(from,to,QUIET_FLAG);
                temp_move &= temp_move - 1;
            }

            /* captures */
            temp_move = temp_move2 & game->board[PIECES][WHITE];
            while (temp_move)
            {
                to = bit_scan_forward(temp_move);
                game->move_buffer[move_count++] = create_move(from,to,CAPTURE_FLAG);
                temp_move &= temp_move - 1;
            }

            temp_piece &= temp_piece - 1;
        }

        /***************/
        /* BLACK ROOKS */
        /***************/
        temp_piece = game->board[ROOKS][BLACK];
        while (temp_piece)
        {
            from = bit_scan_forward(temp_piece);
            temp_move2 = get_rook_attacks(game->board[OCCUPIED][1], from);

            /* quiets */
            temp_move = temp_move2 & free_squares;
            while (temp_move)
            {
                to = bit_scan_forward(temp_move);
                game->move_buffer[move_count++] = create_move(from,to,QUIET_FLAG);
                temp_move &= temp_move - 1;
            }

            /* captures */
            temp_move = temp_move2 & game->board[PIECES][WHITE];
            while (temp_move)
            {
                to = bit_scan_forward(temp_move);
                game->move_buffer[move_count++] = create_move(from,to,CAPTURE_FLAG);
                temp_move &= temp_move - 1;
            }

            temp_piece &= temp_piece - 1;
        }

        /****************/
        /* BLACK QUEENS */
        /****************/
        temp_piece = game->board[QUEENS][BLACK];
        while (temp_piece)
        {
            from = bit_scan_forward(temp_piece);
            temp_move2 = get_queen_attacks(game->board[OCCUPIED][1], from);

            /* quiets */
            temp_move = temp_move2 & free_squares;
            while (temp_move)
            {
                to = bit_scan_forward(temp_move);
                game->move_buffer[move_count++] = create_move(from,to,QUIET_FLAG);
                temp_move &= temp_move - 1;
            }

            /* captures */
            temp_move = temp_move2 & game->board[PIECES][WHITE];
            while (temp_move)
            {
                to = bit_scan_forward(temp_move);
                game->move_buffer[move_count++] = create_move(from,to,CAPTURE_FLAG);
                temp_move &= temp_move - 1;
            }

            temp_piece &= temp_piece - 1;
        }

        /**************/
        /* BLACK KINGS */
        /**************/
        temp_piece = game->board[KINGS][BLACK];
        from = bit_scan_forward(temp_piece);

        /* quiets */
        temp_move = king_table[from] & free_squares;
        while (temp_move)
        {
            to = bit_scan_forward(temp_move);
            game->move_buffer[move_count++] = create_move(from,to,QUIET_FLAG);
            temp_move &= temp_move - 1;
        }

        /* captures */
        temp_move = king_table[from] & game->board[PIECES][WHITE];
        while (temp_move)
        {
            to = bit_scan_forward(temp_move);
            game->move_buffer[move_count++] = create_move(from,to,CAPTURE_FLAG);
            temp_move &= temp_move - 1;
        }

    }

    return move_count;
}
Exemplo n.º 7
0
int generate_captures(Move *movelist)
{
    int horizontal2 = turn_to_move == WHITE? 8 : 3;
    int horizontal7 = turn_to_move == WHITE? 3 : 8;
    int direction_of_pawns = turn_to_move == WHITE? -10: 10;
    int captures_of_pawns[2] = {direction_of_pawns + 1, direction_of_pawns - 1};
    int place_of_king = turn_to_move == WHITE? place_of_white_king:
                                               place_of_black_king;
    int n = 0;
    
    for(int i = 0; i < 8; i += 1)
    {
        int tmp = place_of_king + moves_of_king[i];
        if(get_color(board[tmp]) == not_turn_to_move)
        {
            movelist[n] = create_move(place_of_king, tmp, board[tmp], 0);
            n += 1;
        }
    }
    for(int i64 = 0; i64 < 64; i64 += 1)
    {
        int current_cell = board64[i64];
        int figure = board[current_cell];
        if(get_color(figure) != turn_to_move)
            continue;
        switch(get_value(figure))
        {
            case QUEEN:
                for(int i = 0; i < 8; i += 1)
                {
                    int inc = directions_of_queen[i];
                    int x = current_cell + inc;
                    while(board[x] == EMPTY)
                        x += inc;
                    if(get_color(board[x]) == not_turn_to_move)
                    {
                        movelist[n] = create_move(current_cell, x, board[x], 0);
                        n += 1;
                    }
                }
                break;
            case ROOK:
                for(int i = 0; i < 4; i += 1)
                {
                    int inc = directions_of_rook[i];
                    int x = current_cell + inc;
                    while(board[x] == EMPTY)
                        x += inc;
                    if(get_color(board[x]) == not_turn_to_move)
                    {
                        movelist[n] = create_move(current_cell, x, board[x], 0);
                        n += 1;
                    }
                }
                break;
            case BISHOP:
                for(int i = 0; i < 4; i += 1)
                {
                    int inc = directions_of_bishop[i];
                    int x = current_cell + inc;
                    while(board[x] == EMPTY)
                        x += inc;
                    if(get_color(board[x]) == not_turn_to_move)
                    {
                        movelist[n] = create_move(current_cell, x, board[x], 0);
                        n += 1;
                    }
                }
                break;
            case KNIGHT:
                for(int i = 0; i < 8; i += 1)
                {
                    int tmp = current_cell + moves_of_knight[i];
                    if(get_color(board[tmp]) == not_turn_to_move)
                    {
                        movelist[n] = create_move(current_cell, tmp, board[tmp], 0);
                        n += 1;
                    }
                }
                break;
            case PAWN:
                for(int i = 0; i < 2; i += 1)
                {
                    int tmp = current_cell + captures_of_pawns[i];
                    if(get_color(board[tmp]) == not_turn_to_move)
                    {
                        movelist[n] = create_move(current_cell, tmp, board[tmp], 0);
                        n += 1;
                    }
                }
        }
    }
    for(int i = 0; i < n; i += 1)
    {
        Move i_move = movelist[i];
        make_move(i_move);
        if(in_check(not_turn_to_move))
        {
            movelist[i] = movelist[n - 1];
            n -= 1;
            i -= 1;
        }
        unmake_move(i_move);
    }
    return n;
}
Exemplo n.º 8
0
int generate_moves(Move *movelist)
{
    int horizontal2 = turn_to_move == WHITE? 8 : 3;
    int horizontal7 = turn_to_move == WHITE? 3 : 8;
    int direction_of_pawns = turn_to_move == WHITE? -10: 10;
    int captures_of_pawns[2] = {direction_of_pawns + 1, direction_of_pawns - 1};
    int place_of_king = turn_to_move == WHITE? place_of_white_king:
                                               place_of_black_king;
    int n = 0;
    
    int king_castling, queen_castling;
    if(turn_to_move == WHITE)
    {
        king_castling  = ply->castlings & K_castling;
        queen_castling = ply->castlings & Q_castling;
    }
    else
    {
        king_castling  = ply->castlings & k_castling;
        queen_castling = ply->castlings & q_castling;
    }
    int is_in_check = in_check(turn_to_move);
    for(int i = 0; i < 8; i += 1)
    {
        int i_move = moves_of_king[i];
        int tmp = place_of_king + i_move;
        if(board[tmp] == EMPTY || get_color(board[tmp]) == not_turn_to_move)
        {
            int i_move_is_possible = 0;
            Move tmp_move = create_move(place_of_king, tmp, board[tmp], 0);
            make_move(tmp_move);
            if(!in_check(not_turn_to_move))
            {
                i_move_is_possible = 1;
                movelist[n] = tmp_move;
                n += 1;
            }
            unmake_move(tmp_move);
            
            if(is_in_check || !i_move_is_possible || board[tmp] != EMPTY)
                continue;
            if(i_move == 1 && king_castling && board[place_of_king + 2] == EMPTY)
            {
                movelist[n] = create_move(place_of_king, place_of_king + 2, 0, 0);
                n += 1;
            }
            if(i_move == -1 && queen_castling &&
               board[place_of_king - 2] == EMPTY &&
               board[place_of_king - 3] == EMPTY)
            {
                movelist[n] = create_move(place_of_king, place_of_king - 2, 0, 0);
                n += 1;
            }
        }
    }
    
    if(ply->en_passant)
    {
        for(int i = 0; i < 2; i += 1)
        {
            int tmp = ply->en_passant - captures_of_pawns[i];
            if(board[tmp] == create_figure(turn_to_move, PAWN))
            {
                movelist[n] = create_move(tmp, ply->en_passant, 0, 0);
                n += 1;
            }
        }
    }
    for(int i64 = 0; i64 < 64; i64 += 1)
    {
        int current_cell = board64[i64];
        int figure = board[current_cell];
        if(get_color(figure) != turn_to_move)
            continue;
        switch(get_value(figure))
        {
            case QUEEN:
                for(int i = 0; i < 8; i += 1)
                {
                    int inc = directions_of_queen[i];
                    int x = current_cell + inc;
                    while(board[x] == EMPTY)
                    {
                        movelist[n] = create_move(current_cell, x, 0, 0);
                        n += 1;
                        x += inc;
                    }
                    if(get_color(board[x]) == not_turn_to_move )
                    {
                        movelist[n] = create_move(current_cell, x, board[x], 0);
                        n += 1;
                    }
                }
                break;
            case ROOK:
                for(int i = 0; i < 4; i += 1)
                {
                    int inc = directions_of_rook[i];
                    int x = current_cell + inc;
                    while(board[x] == EMPTY)
                    {
                        movelist[n] = create_move(current_cell, x, 0, 0);
                        n += 1;
                        x += inc;
                    }
                    if(get_color(board[x]) == not_turn_to_move)
                    {
                        movelist[n] = create_move(current_cell, x, board[x], 0);
                        n += 1;
                    }
                }
                break;
            case BISHOP:
                for(int i = 0; i < 4; i += 1)
                {
                    int inc = directions_of_bishop[i];
                    int x = current_cell + inc;
                    while(board[x] == EMPTY)
                    {
                        movelist[n] = create_move(current_cell, x, 0, 0);
                        n += 1;
                        x += inc;
                    }
                    if(get_color(board[x]) == not_turn_to_move)
                    {
                        movelist[n] = create_move(current_cell, x, board[x], 0);
                        n += 1;
                    }
                }
                break;
            case KNIGHT:
                for(int i = 0; i < 8; i += 1)
                {
                    int tmp = current_cell + moves_of_knight[i];
                    if(board[tmp] == EMPTY ||
                        get_color(board[tmp]) == not_turn_to_move)
                    {
                        movelist[n] = create_move(current_cell, tmp, board[tmp], 0);
                        n += 1;
                    }
                }
                break;
            case PAWN:
                ;int tmp = current_cell + direction_of_pawns;
                if(board[tmp] == EMPTY)
                {
                    if(current_cell/10 == horizontal7)
                    {
                        for(int j = 0; j < 4; j += 1)
                        {
                            movelist[n] = create_move(current_cell, tmp, 0,
                                create_figure(turn_to_move, turn_figures[j]));
                            n += 1;
                        }
                    }
                    else
                    {
                        movelist[n] = create_move(current_cell, tmp, 0, 0);
                        n += 1;
                    }
                    tmp += direction_of_pawns;
                    if(board[tmp] == EMPTY && current_cell/10 == horizontal2)
                    {
                        movelist[n] = create_move(current_cell, tmp, 0, 0);
                        n += 1;
                    }
                }
                for(int i = 0; i < 2; i += 1)
                {
                    int tmp = current_cell + captures_of_pawns[i];
                    if(get_color(board[tmp]) == not_turn_to_move)
                    {
                        if(current_cell/10 == horizontal7)
                        {
                            for(int j = 0; j < 4; j += 1)
                            {
                                movelist[n] = create_move(current_cell, tmp, board[tmp],
                                    create_figure(turn_to_move, turn_figures[j]));
                                n += 1;
                            }
                        }
                        else
                        {
                            movelist[n] = create_move(current_cell, tmp, board[tmp], 0);
                            n += 1;
                        }
                    }
                }
        }
    }
    for(int i = 0; i < n; i += 1)
    {
        Move i_move = movelist[i];
        make_move(i_move);
        if(in_check(not_turn_to_move))
        {
            movelist[i] = movelist[n - 1];
            n -= 1;
            i -= 1;
        }
        unmake_move(i_move);
    }
    return n;
}
/*
 * Add all pseudo-legal captures that the given piece (N/B/Q/K) can make.
 */
static void generate_piece_captures(const position_t* pos,
        square_t from,
        piece_t piece,
        move_t** moves_head)
{
    move_t* moves = *moves_head;
    square_t to;
    // Note: I unrolled all these loops to handle each direction explicitly.
    // The idea was to increase performance, but it's only about 1% faster
    // for much more code, so it's possible I'll change this back later.
    switch (piece_type(piece)) {
        case KING:
            to = from - 17;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from - 16;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from - 15;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from - 1;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from + 1;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from + 15;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from + 16;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from + 17;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            break;
        case KNIGHT:
            to = from - 33;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from - 31;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from - 18;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from - 14;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from + 14;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from + 18;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from + 31;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from + 33;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            break;
        case BISHOP:
            for (to=from-17; pos->board[to]==EMPTY; to-=17) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            for (to=from-15; pos->board[to]==EMPTY; to-=15) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            for (to=from+15; pos->board[to]==EMPTY; to+=15) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            for (to=from+17; pos->board[to]==EMPTY; to+=17) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            break;
        case ROOK:
            for (to=from-16; pos->board[to]==EMPTY; to-=16) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            for (to=from-1; pos->board[to]==EMPTY; to-=1) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            for (to=from+1; pos->board[to]==EMPTY; to+=1) {}
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            for (to=from+16; pos->board[to]==EMPTY; to+=16) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            break;
        case QUEEN:
            for (to=from-17; pos->board[to]==EMPTY; to-=17) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            for (to=from-16; pos->board[to]==EMPTY; to-=16) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            for (to=from-15; pos->board[to]==EMPTY; to-=15) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            for (to=from-1; pos->board[to]==EMPTY; to-=1) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            for (to=from+1; pos->board[to]==EMPTY; to+=1) {}
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            for (to=from+15; pos->board[to]==EMPTY; to+=15) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            for (to=from+16; pos->board[to]==EMPTY; to+=16) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            for (to=from+17; pos->board[to]==EMPTY; to+=17) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            break;
        default: assert(false);
    }
    *moves_head = moves;
}
/*
 * Generate all non-capturing, non-promoting, pseudo-legal checks. Used for
 * quiescent move generation.
 */
int generate_pseudo_checks(const position_t* pos, move_t* moves)
{
    move_t* moves_head = moves;
    color_t side = pos->side_to_move, other_side = side^1;
    square_t king_sq = pos->pieces[other_side][0];
    for (int i = 0; i < pos->num_pawns[side]; ++i) {
        square_t from = pos->pawns[side][i];
        square_t to = INVALID_SQUARE;
        piece_t piece = pos->board[from];
        // Figure out whether or not we can discover check by moving.
        direction_t discover_check_dir = 0;
        bool will_discover_check;
        const attack_data_t* king_atk = &get_attack_data(from, king_sq);
        if ((king_atk->possible_attackers & Q_FLAG) == 0) {
            discover_check_dir = 0;
        } else {
            direction_t king_dir = king_atk->relative_direction;
            square_t sq;
            for (sq = from+king_dir; pos->board[sq] == EMPTY; sq+=king_dir) {}
            if (sq == king_sq) {
                // Nothing between us and the king. Is there anything
                // behind us to do the check when we move?
                for (sq = from-king_dir; pos->board[sq] == EMPTY;
                        sq -= king_dir) {}
                if (side == piece_color(pos->board[sq]) &&
                        (king_atk->possible_attackers &
                         get_piece_flag(pos->board[sq]))) {
                    discover_check_dir = king_dir;
                }
            }
        }
        // Generate checking moves.
        will_discover_check = discover_check_dir && abs(discover_check_dir)!=N;
        to = from + pawn_push[side];
        if (pos->board[to] != EMPTY) continue;
        rank_t r_rank =
            relative_rank[side][square_rank(from)];
        if (r_rank == RANK_7) continue; // non-promotes only
        for (const direction_t* delta = piece_deltas[piece]; *delta; ++delta) {
            if (will_discover_check || to + *delta == king_sq) {
                moves = add_move(pos,
                        create_move(from, to, piece, EMPTY),
                        moves);
                break;
            }
        }
        to += pawn_push[side];
        if (r_rank == RANK_2 && pos->board[to] == EMPTY) {
            for (const direction_t* delta = piece_deltas[piece];
                    *delta; ++delta) {
                if (will_discover_check || to + *delta == king_sq) {
                    moves = add_move(pos,
                            create_move(from, to, piece, EMPTY),
                            moves);
                    break;
                }
            }
        }
    }

    for (int i = 0; i < pos->num_pieces[side]; ++i) {
        square_t from = pos->pieces[side][i];
        square_t to = INVALID_SQUARE;
        piece_t piece = pos->board[from];
        // Figure out whether or not we can discover check by moving.
        direction_t discover_check_dir = 0;
        bool will_discover_check;
        const attack_data_t* king_atk = &get_attack_data(from, king_sq);
        if ((king_atk->possible_attackers & Q_FLAG) == 0) {
            discover_check_dir = 0;
        } else {
            direction_t king_dir = king_atk->relative_direction;
            square_t sq;
            for (sq = from+king_dir; pos->board[sq] == EMPTY; sq+=king_dir) {}
            if (sq == king_sq) {
                // Nothing between us and the king. Is there anything
                // behind us to do the check when we move?
                for (sq = from - king_dir; pos->board[sq] == EMPTY;
                        sq -= king_dir) {}
                if (side == piece_color(pos->board[sq]) &&
                        (king_atk->possible_attackers &
                         get_piece_flag(pos->board[sq]))) {
                    discover_check_dir = king_dir;
                }
            }
        }
        // Generate checking moves.
        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;
                if (discover_check_dir ||
                        possible_attack(to, king_sq, WN)) {
                    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) {
                    will_discover_check = discover_check_dir &&
                        abs(discover_check_dir) != abs(*delta);
                    if (will_discover_check) {
                        moves = add_move(pos,
                                create_move(from, to, piece, NONE),
                                moves);
                        continue;
                    }
                    if (possible_attack(to, king_sq, piece)) {
                        const direction_t to_king = direction(to, king_sq);
                        square_t x = to + to_king;
                        for (; pos->board[x] == EMPTY; x+=to_king) {}
                        if (x == king_sq) {
                            moves = add_move(pos,
                                    create_move(from, to, piece, NONE),
                                    moves);
                        }
                    }
                }
            }
        }
    }
    *moves = 0;
    return moves-moves_head;
}
/*
 * 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;
}