Esempio n. 1
0
static int in_check(board_t *board, int turn)
{
    int i;
    for (i = 0; i < 64; i++)
        if (board->square[i] ==  KING + turn)
            break;

    if (i == 64)
    {
        DBG_ERROR("board is missing a king");
        exit(1);
    }

    return square_attacked(board, i, OPPONENT(turn));
}
Esempio n. 2
0
/* Checks whether a move is valid, except for whether this puts own king in check. */
static int move_is_semi_valid(board_t *board, move_t *move)
{
    /* Bounds check. */
    if ((move->source > 63) || (move->source < 0))
        return 0;

    if ((move->destination > 63) || (move->destination < 0))
        return 0;

    /* Test for moving to same square. */
    if (move->source == move->destination)
        return 0;

    /* Test for empty source square. */
    if (board->square[move->source] == NONE)
        return 0;

    /* Test for moving opponent's piece. */
    if (COLOUR(board->square[move->source]) != board->turn)
        return 0;

    /* Check that a promotion piece is specified for promotion moves. */
    if ((PIECE(board->square[move->source]) == PAWN) && ((move->destination < 8) || (move->destination >= 56)))
    {
        switch (PIECE(move->promotion_piece))
        {
        case KNIGHT:
        case ROOK:
        case BISHOP:
        case QUEEN:
            break;
        default:
            return 0;
        }

        if (COLOUR(move->promotion_piece) != board->turn)
            return 0;
    }
    else if (move->promotion_piece != NONE)
        /* Promotion piece specified for non-promotion move. */
        return 0;

    switch (PIECE(board->square[move->source]))
    {
    case KNIGHT:
        if ((HOR != 1) && (HOR != 2))
            return 0;
        if ((HOR == 1) && (VERT != 2))
            return 0;
        if ((HOR == 2) && (VERT != 1))
            return 0;
        if (board->square[move->destination] == NONE)
            break;
        if (COLOUR(board->square[move->destination]) == COLOUR(board->square[move->source]))
            return 0;
        break;
    case BISHOP:
        if (HOR != VERT)
            return 0;
        if (!ray_ok(board, move))
            return 0;
        break;
    case ROOK:
        if ((HOR != 0) && (VERT != 0))
            return 0;
        if (!ray_ok(board, move))
            return 0;
        break;
    case QUEEN:
        if ((HOR != 0) && (VERT != 0) && (HOR != VERT))
            return 0;
        if (!ray_ok(board, move))
            return 0;
        break;
    case PAWN:
        /* Catch moves in wrong direction. */
        if ((move->destination > move->source) && (COLOUR(board->square[move->source]) == BLACK))
            return 0;
        if ((move->destination < move->source) && (COLOUR(board->square[move->source]) == WHITE))
            return 0;

        if (HOR > 1)
            return 0;

        if (HOR == 0)
        {
            /* Regular or double push. */

            if (VERT > 2)
                return 0;
            if (VERT == 2)
                if (!(((move->source >= 8) && (move->source <= 15)) || ((move->source >= 48) && (move->source <= 55))))
                    return 0;
            /* Use ray checking code with added requirement that destination square is empty. */
            if (!ray_ok(board, move) || (board->square[move->destination] != NONE))
                return 0;
        }
        else
        {
            if (VERT != 1)
                return 0;
            if (!ray_ok(board, move))
                return 0;
            /* En-passant move. */
            if (board->square[move->destination] == NONE)
            {
                if ((COLOUR(board->square[move->source]) == WHITE) && !((move->source >= 32) && (move->source < 40)))
                    return 0;
                if ((COLOUR(board->square[move->source]) == BLACK) && !((move->source >= 24) && (move->source < 32)))
                    return 0;

                if (board->square[move->destination + (COLOUR(board->square[move->source]) == WHITE ? -8 : 8)] !=
                        PAWN + OPPONENT(COLOUR(board->square[move->source])))
                    return 0;
            }

        }
        break;
    case KING:
        if (HOR > 2)
            return 0;
        else if (HOR == 2)
        {
            int white = COLOUR(board->square[move->source]) == WHITE;

            int i, step = (move->destination > move->source ? 1 : -1);
            int rook = (step == 1 ? (white ? 7 : 63) : (white ? 0 : 56));

            /* Castling. */
            if (VERT != 0)
                return 0;

            if (move->source != (white ? 4 : 60))
                return 0;

            if (board->square[rook] != ROOK + COLOUR(board->square[move->source]))
                return 0;

            i = move->source + step;

            while (i != rook)
            {
                if (board->square[i] != NONE)
                    return 0;
                i += step;
            }

            /* Check whether any of the squares the king moves over is under
            ** attack. Note that destination square is checked later.
            */
            if (square_attacked(board, move->source, (white ? BLACK : WHITE)))
                return 0;
            if (square_attacked(board, move->source + step, (white ? BLACK : WHITE)))
                return 0;
        }
        else
        {
            if (VERT > 1)
                return 0;
            if (!ray_ok(board, move))
                return 0;
        }
    }
    return 1;
}
Esempio n. 3
0
int qsearch(s_search_info *info, s_stack *stack, s_board *board, int alpha, int beta)
{
    assert(info != NULL);
    assert(stack != NULL);
    assert(board != NULL);
    assert(alpha < beta);

    int stand_pat = evaluate(board);

    if(stack->ply > info->seldepth)
    {
        info->seldepth = stack->ply-1;
    }

    if(stand_pat >= beta)
    {
        return beta;
    }

#ifdef DELTA_PRUNING
    const int safety = 900; // The value of a queen

    if(stand_pat < alpha - safety && !is_endgame(board))
    {
        return alpha;
    }
#endif

    if(stand_pat > alpha)
    {
        alpha = stand_pat;
    }

    if(stack->ply >= MAX_DEPTH)
    {
        return stand_pat;
    }

    // Set old permissions
    s_irreversible permissions;
    store_irreversible(&permissions, board);

    s_move moves[MAX_MOVES];
    int num_moves = find_moves_captures(board, moves, board->turn);
#ifdef SORT_MOVES
    moves_sort_see(board, moves, num_moves);
#endif

    for(int m = 0; m < num_moves; ++m)
    {
        int val = see_capture(board, moves[m]);
        if(val < -50)
        {
            break;
        }

        move_make(board, &moves[m]);

        if(square_attacked(board, board->pieces[KINGS]&board->colour[!board->turn], board->turn))
        {
            // Restore old permissions
            restore_irreversible(&permissions, board);

            move_undo(board, &moves[m]);
            continue;
        }

        info->nodes++;

        int score = -qsearch(info, stack+1, board, -beta, -alpha);

        // Restore old permissions
        restore_irreversible(&permissions, board);

        move_undo(board, &moves[m]);

        if(score >= beta)
        {
#ifndef NDEBUG
            info->num_cutoffs[m]++;
#endif
            return beta;
        }

        if(score > alpha)
        {
            alpha = score;
        }
    }

    return alpha;
}