root/src/move_evasion.cpp
/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- gen_legal_evasions
- gen_pseudo_evasions
- legal_evasion_exist
- gen_evasions
- add_pawn_moves
- add_pawn_captures
- add_piece_moves
// move_evasion.cpp
// includes
#include "attack.h"
#include "board.h"
#include "colour.h"
#include "list.h"
#include "move.h"
#include "move_evasion.h"
#include "move_gen.h"
#include "piece.h"
#include "util.h"
// prototypes
static bool gen_evasions (list_t * list, const board_t * board, const attack_t * attack, bool legal, bool stop);
static bool add_pawn_moves (list_t * list, const board_t * board, int to, bool legal, bool stop);
static bool add_pawn_captures (list_t * list, const board_t * board, int to, bool legal, bool stop);
static bool add_piece_moves (list_t * list, const board_t * board, int to, bool legal, bool stop);
// functions
// gen_legal_evasions()
void gen_legal_evasions(list_t * list, const board_t * board, const attack_t * attack) {
ASSERT(list!=NULL);
ASSERT(board!=NULL);
ASSERT(attack!=NULL);
gen_evasions(list,board,attack,true,false);
// debug
ASSERT(list_is_ok(list));
}
// gen_pseudo_evasions()
void gen_pseudo_evasions(list_t * list, const board_t * board, const attack_t * attack) {
ASSERT(list!=NULL);
ASSERT(board!=NULL);
ASSERT(attack!=NULL);
gen_evasions(list,board,attack,false,false);
// debug
ASSERT(list_is_ok(list));
}
// legal_evasion_exist()
bool legal_evasion_exist(const board_t * board, const attack_t * attack) {
list_t list[1]; // dummy
ASSERT(board!=NULL);
ASSERT(attack!=NULL);
return gen_evasions(list,board,attack,true,true);
}
// gen_evasions()
static bool gen_evasions(list_t * list, const board_t * board, const attack_t * attack, bool legal, bool stop) {
int me, opp;
int opp_flag;
int king;
const inc_t * inc_ptr;
int inc;
int to;
int piece;
ASSERT(list!=NULL);
ASSERT(board!=NULL);
ASSERT(attack!=NULL);
ASSERT(legal==true||legal==false);
ASSERT(stop==true||stop==false);
ASSERT(board_is_check(board));
ASSERT(ATTACK_IN_CHECK(attack));
// init
LIST_CLEAR(list);
me = board->turn;
opp = COLOUR_OPP(me);
opp_flag = COLOUR_FLAG(opp);
king = KING_POS(board,me);
for (inc_ptr = KingInc; (inc=*inc_ptr) != IncNone; inc_ptr++) {
if (inc != -attack->di[0] && inc != -attack->di[1]) { // avoid escaping along a check line
to = king + inc;
piece = board->square[to];
if (piece == Empty || FLAG_IS(piece,opp_flag)) {
if (!legal || !is_attacked(board,to,opp)) {
if (stop) return true;
LIST_ADD(list,MOVE_MAKE(king,to));
}
}
}
}
if (attack->dn >= 2) return false; // double check, we are done
// single check
ASSERT(attack->dn==1);
// capture the checking piece
if (add_pawn_captures(list,board,attack->ds[0],legal,stop) && stop) return true;
if (add_piece_moves(list,board,attack->ds[0],legal,stop) && stop) return true;
// interpose a piece
inc = attack->di[0];
if (inc != IncNone) { // line
for (to = king+inc; to != attack->ds[0]; to += inc) {
ASSERT(SQUARE_IS_OK(to));
ASSERT(board->square[to]==Empty);
if (add_pawn_moves(list,board,to,legal,stop) && stop) return true;
if (add_piece_moves(list,board,to,legal,stop) && stop) return true;
}
}
return false;
}
// add_pawn_moves()
static bool add_pawn_moves(list_t * list, const board_t * board, int to, bool legal, bool stop) {
int me;
int inc;
int pawn;
int from;
int piece;
ASSERT(list!=NULL);
ASSERT(board!=NULL);
ASSERT(SQUARE_IS_OK(to));
ASSERT(legal==true||legal==false);
ASSERT(stop==true||stop==false);
ASSERT(board->square[to]==Empty);
me = board->turn;
inc = PAWN_MOVE_INC(me);
pawn = PAWN_MAKE(me);
from = to - inc;
piece = board->square[from];
if (piece == pawn) { // single push
if (!legal || !is_pinned(board,from,me)) {
if (stop) return true;
add_pawn_move(list,from,to);
}
} else if (piece == Empty && PAWN_RANK(to,me) == Rank4) { // double push
from = to - (2*inc);
if (board->square[from] == pawn) {
if (!legal || !is_pinned(board,from,me)) {
if (stop) return true;
ASSERT(!SQUARE_IS_PROMOTE(to));
LIST_ADD(list,MOVE_MAKE(from,to));
}
}
}
return false;
}
// add_pawn_captures()
static bool add_pawn_captures(list_t * list, const board_t * board, int to, bool legal, bool stop) {
int me;
int inc;
int pawn;
int from;
ASSERT(list!=NULL);
ASSERT(board!=NULL);
ASSERT(SQUARE_IS_OK(to));
ASSERT(legal==true||legal==false);
ASSERT(stop==true||stop==false);
ASSERT(COLOUR_IS(board->square[to],COLOUR_OPP(board->turn)));
me = board->turn;
inc = PAWN_MOVE_INC(me);
pawn = PAWN_MAKE(me);
from = to - (inc-1);
if (board->square[from] == pawn) {
if (!legal || !is_pinned(board,from,me)) {
if (stop) return true;
add_pawn_move(list,from,to);
}
}
from = to - (inc+1);
if (board->square[from] == pawn) {
if (!legal || !is_pinned(board,from,me)) {
if (stop) return true;
add_pawn_move(list,from,to);
}
}
if (board->ep_square != SquareNone
&& to == SQUARE_EP_DUAL(board->ep_square)) {
ASSERT(PAWN_RANK(to,me)==Rank5);
ASSERT(PIECE_IS_PAWN(board->square[to]));
to = board->ep_square;
ASSERT(PAWN_RANK(to,me)==Rank6);
ASSERT(board->square[to]==Empty);
from = to - (inc-1);
if (board->square[from] == pawn) {
if (!legal || !is_pinned(board,from,me)) {
if (stop) return true;
ASSERT(!SQUARE_IS_PROMOTE(to));
LIST_ADD(list,MOVE_MAKE_FLAGS(from,to,MoveEnPassant));
}
}
from = to - (inc+1);
if (board->square[from] == pawn) {
if (!legal || !is_pinned(board,from,me)) {
if (stop) return true;
ASSERT(!SQUARE_IS_PROMOTE(to));
LIST_ADD(list,MOVE_MAKE_FLAGS(from,to,MoveEnPassant));
}
}
}
return false;
}
// add_piece_moves()
static bool add_piece_moves(list_t * list, const board_t * board, int to, bool legal, bool stop) {
int me;
const sq_t * ptr;
int from, piece;
ASSERT(list!=NULL);
ASSERT(board!=NULL);
ASSERT(SQUARE_IS_OK(to));
ASSERT(legal==true||legal==false);
ASSERT(stop==true||stop==false);
me = board->turn;
for (ptr = &board->piece[me][1]; (from=*ptr) != SquareNone; ptr++) { // HACK: no king
piece = board->square[from];
if (PIECE_ATTACK(board,piece,from,to)) {
if (!legal || !is_pinned(board,from,me)) {
if (stop) return true;
LIST_ADD(list,MOVE_MAKE(from,to));
}
}
}
return false;
}
// end of move_evasion.cpp