⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 attack.cpp

📁 超强国际象棋引擎
💻 CPP
字号:
// attack.cpp

// includes

#include "attack.h"

// variables

int delta_inc_line[239];
int delta_inc_all[239];

int delta_mask[239];
int inc_mask[35];

static int piece_code[256];

static int piece_delta_size[4][256];     // 4kB
static int piece_delta_delta[4][256][4]; // 16 kB

// prototypes

static void add_attack(int piece, int king, int target);

// functions

// attack_init()

void attack_init()
    {

    int delta, inc;
    int piece;
    int dir, dist;
    int size;
    int king;
    int from, to;
    int pos;

    // clear

    for ( delta = 0; delta < 239; delta++ )
        {
        delta_inc_line[delta] = 0;
        delta_inc_all[delta] = 0;
        delta_mask[delta] = 0;
        }

    for ( inc = 0; inc < 35; inc++ )
        {
        inc_mask[inc] = 0;
        }

    // pawn attacks

    delta_mask[119 - 17] |= (1 << 3);
    delta_mask[119 - 15] |= (1 << 3);

    delta_mask[119 + 15] |= (1 << 2);
    delta_mask[119 + 17] |= (1 << 2);

    // knight attacks

    for ( dir = 0; dir < 8; dir++ )
        {

        delta = knight_inc[dir];
        delta_inc_all[119 + delta] = delta;
        delta_mask[119 + delta] |= (1 << 4);
        }

    // bishop/queen attacks

    for ( dir = 0; dir < 4; dir++ )
        {

        inc = bishop_inc[dir];

        inc_mask[17 + inc] |= (1 << 5);

        for ( dist = 1; dist < 8; dist++ )
            {

            delta = inc * dist;
            delta_inc_line[119 + delta] = inc;
            delta_inc_all[119 + delta] = inc;
            delta_mask[119 + delta] |= (1 << 5);
            }
        }

    // rook/queen attacks

    for ( dir = 0; dir < 4; dir++ )
        {

        inc = rook_inc[dir];
        inc_mask[17 + inc] |= (1 << 6);

        for ( dist = 1; dist < 8; dist++ )
            {

            delta = inc * dist;
            delta_inc_line[119 + delta] = inc;
            delta_inc_all[119 + delta] = inc;
            delta_mask[119 + delta] |= (1 << 6);
            }
        }

    // king attacks

    for ( dir = 0; dir < 8; dir++ )
        {

        delta = king_inc[dir];
        delta_mask[119 + delta] |= (1 << 7);
        }

    // piece_code[]

    for ( piece = 0; piece < 256; piece++ )
        {
        piece_code[piece] = -1;
        }

    piece_code[((1 << 4) | (1 << 0))] = 0;
    piece_code[((1 << 5) | (1 << 0))] = 1;
    piece_code[((1 << 6) | (1 << 0))] = 2;
    piece_code[(((1 << 5) | (1 << 6)) | (1 << 0))] = 3;

    piece_code[((1 << 4) | (1 << 1))] = 0;
    piece_code[((1 << 5) | (1 << 1))] = 1;
    piece_code[((1 << 6) | (1 << 1))] = 2;
    piece_code[(((1 << 5) | (1 << 6)) | (1 << 1))] = 3;

    // piece_delta_size[][] & piece_delta_delta[][][]

    for ( piece = 0; piece < 4; piece++ )
        {
        for ( delta = 0; delta < 256; delta++ )
            {
            piece_delta_size[piece][delta] = 0;
            }
        }

    for ( king = 0; king < 256; king++ )
        {
        if(SQUARE_IS_OK(king))
            {
            for ( from = 0; from < 256; from++ )
                {
                if(SQUARE_IS_OK(from))
                    {

                    // knight

                    for ( pos = 0; (inc = knight_inc[pos]) != 0; pos++ )
                        {
                        to = from + inc;

                        if(SQUARE_IS_OK(to) && DISTANCE(to, king) == 1)
                            {
                            add_attack(0, king - from, to - from);
                            }
                        }

                    // bishop

                    for ( pos = 0; (inc = bishop_inc[pos]) != 0; pos++ )
                        {
                        for ( to = from + inc; SQUARE_IS_OK(to); to += inc )
                            {
                            if(DISTANCE(to, king) == 1)
                                {
                                add_attack(1, king - from, to - from);
                                break;
                                }
                            }
                        }

                    // rook

                    for ( pos = 0; (inc = rook_inc[pos]) != 0; pos++ )
                        {
                        for ( to = from + inc; SQUARE_IS_OK(to); to += inc )
                            {
                            if(DISTANCE(to, king) == 1)
                                {
                                add_attack(2, king - from, to - from);
                                break;
                                }
                            }
                        }

                    // queen

                    for ( pos = 0; (inc = queen_inc[pos]) != 0; pos++ )
                        {
                        for ( to = from + inc; SQUARE_IS_OK(to); to += inc )
                            {
                            if(DISTANCE(to, king) == 1)
                                {
                                add_attack(3, king - from, to - from);
                                break;
                                }
                            }
                        }
                    }
                }
            }
        }

    for ( piece = 0; piece < 4; piece++ )
        {
        for ( delta = 0; delta < 256; delta++ )
            {
            size = piece_delta_size[piece][delta];
            piece_delta_delta[piece][delta][size] = 0;
            }
        }
    }

// add_attack()

static void add_attack(int piece, int king, int target)
    {

    int size;
    int i;

    size = piece_delta_size[piece][119 + king];

    for ( i = 0; i < size; i++ )
        {
        if(piece_delta_delta[piece][119 + king][i] == target)
            return; // already in the table
        }

    if(size < 2)
        {
        piece_delta_delta[piece][119 + king][size] = target;
        size++;
        piece_delta_size[piece][119 + king] = size;
        }
    }

// is_attacked()

bool is_attacked(const board_t *board, int to, int color)
    {

    int inc;
    int pawn;
    const sq_t *ptr;
    int from;
    int piece;
    int delta;
    int sq;

    // pawn attack

    inc = PAWN_MOVE_INC(color);
    pawn = PAWN_MAKE(color);

    if(board->square[to - (inc - 1)] == pawn)
        return true;

    if(board->square[to - (inc + 1)] == pawn)
        return true;

    // piece attack

    for ( ptr = &board->piece[color][0]; (from = *ptr) != 0; ptr++ )
        {

        piece = board->square[from];
        delta = to - from;

        if(PSEUDO_ATTACK(piece, delta))
            {

            inc = DELTA_INC_ALL(delta);

            sq = from;

            do
                {
                sq += inc;

                if(sq == to)
                    return true;
                } while (board->square[sq] == 0);
            }
        }

    return false;
    }

// line_is_empty()

bool line_is_empty(const board_t *board, int from, int to)
    {

    int delta;
    int inc, sq;

    delta = to - from;

    inc = DELTA_INC_ALL(delta);

    sq = from;

    do
        {
        sq += inc;

        if(sq == to)
            return true;
        } while (board->square[sq] == 0);

    return false; // blocker
    }

// is_pinned()

bool is_pinned(const board_t *board, int square, int color)
    {

    int from, to;
    int inc;
    int sq, piece;

    from = square;
    to = KING_POS(board, color);

    inc = DELTA_INC_LINE(to - from);

    if(inc == 0)
        return false; // not a line

    sq = from;
    do sq += inc;

    while(board->square[sq] == 0);

    if(sq != to)
        return false; // blocker

    sq = from;
    do sq -= inc;

    while((piece = board->square[sq]) == 0);

    return COLOUR_IS(piece, COLOUR_OPP(color)) && SLIDER_ATTACK(piece, inc);
    }

// attack_is_ok()

bool attack_is_ok(const attack_t *attack)
    {

    int i;
    int sq, inc;

    if(attack == NULL)
        return false;

    // checks

    if(attack->dn < 0 || attack->dn > 2)
        return false;

    for ( i = 0; i < attack->dn; i++ )
        {
        sq = attack->ds[i];

        if(!SQUARE_IS_OK(sq))
            return false;

        inc = attack->di[i];

        if(inc != 0 && !inc_is_ok(inc))
            return false;
        }

    if(attack->ds[attack->dn] != 0)
        return false;

    if(attack->di[attack->dn] != 0)
        return false;

    return true;
    }

// attack_set()

void attack_set(attack_t *attack, const board_t *board)
    {

    int me, opp;
    const sq_t *ptr;
    int from, to;
    int inc;
    int pawn;
    int delta, piece;
    int sq;

    // init

    attack->dn = 0;

    me = board->turn;
    opp = COLOUR_OPP(me);

    to = KING_POS(board, me);

    // pawn attacks

    inc = PAWN_MOVE_INC(opp);
    pawn = PAWN_MAKE(opp);

    from = to - (inc - 1);

    if(board->square[from] == pawn)
        {
        attack->ds[attack->dn] = from;
        attack->di[attack->dn] = 0;
        attack->dn++;
        }

    from = to - (inc + 1);

    if(board->square[from] == pawn)
        {
        attack->ds[attack->dn] = from;
        attack->di[attack->dn] = 0;
        attack->dn++;
        }

    // piece attacks

    for ( ptr = &board->piece[opp][1]; (from = *ptr) != 0; ptr++ )
        {

        piece = board->square[from];

        delta = to - from;

        if(PSEUDO_ATTACK(piece, delta))
            {

            inc = 0;

            if(PIECE_IS_SLIDER(piece))
                {

                // check for blockers

                inc = DELTA_INC_LINE(delta);
                sq = from;
                do sq += inc;

                while(board->square[sq] == 0);

                if(sq != to)
                    continue; // blocker => next attacker
                }

            attack->ds[attack->dn] = from;
            attack->di[attack->dn] = -inc;
            attack->dn++;
            }
        }

    attack->ds[attack->dn] = 0;
    attack->di[attack->dn] = 0;
    }

// piece_attack_king()

bool piece_attack_king(const board_t *board, int piece, int from, int king)
    {

    int code;
    const int *delta_ptr;
    int delta, inc;
    int to;
    int sq;

    code = piece_code[piece];

    if(PIECE_IS_SLIDER(piece))
        {
        for ( delta_ptr = piece_delta_delta[code][119 + (king - from)]; (delta = *delta_ptr) != 0; delta_ptr++ )
            {

            inc = delta_inc_line[119 + delta];
            to = from + delta;
            sq = from;

            do
                {
                sq += inc;

                if(DISTANCE(sq, king) <= 2 && SQUARE_IS_OK(sq))
                    {
                    return true;
                    }
                } while (board->square[sq] == 0);
            }
        }
    else
        { // non-slider
        for ( delta_ptr = piece_delta_delta[code][119 + (king - from)]; (delta = *delta_ptr) != 0; delta_ptr++ )
            {

            to = from + delta;

            if(SQUARE_IS_OK(to))
                {
                return true;
                }
            }
        }

    return false;
    }

// end of attack.cpp

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -