📄 attack.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 + -