- Code: Select all
/*
*******************************************************************************
* *
* EvaluateDraws() detects completely blocked positions as draws (hopefully).*
* *
*******************************************************************************
*/
#define NODRAW 0
#define DRAW 1
int EvaluateDraws(TREE * RESTRICT tree, int wtm)
{
register int square,
fdist,
rdist,
open = 0,
rank = 0;
int i,
sq,
blocked,
defenders,
attackers,
kingpath = 0,
rookpath = 0;
int noblockw[2] =
{0, 0}, noblockb[2] =
{
0, 0};
BITBOARD temp;
int wp,
bp;
for (i = FILEA; i <= FILEH; i++) {
temp = file_mask[i];
if (WhitePawns & temp) {
square = LastOne(WhitePawns & temp);
wp = square;
blocked = 1;
do {
for (sq = square; sq < Min(square + 32, A8); sq += 8) {
if (SetMask(sq + 8) & BlackPieces)
break;
defenders = PopCnt(b_pawn_attacks[sq] & WhitePawns);
attackers = PopCnt(w_pawn_attacks[sq] & BlackPawns);
if (attackers > defenders)
break;
else if (attackers) {
blocked = 0;
break;
}
}
if (sq >= Min(square + 32, A8))
blocked = 0;
}
while (0);
if (blocked) {
if (!(plus8dir[square] & BlackPieces)) {
if (!TotalBlackPieces) {
if (Rank(square) >= RANK4)
blocked = 0;
}
}
}
if (!blocked) {
if (noblockw[0])
noblockw[1] = square;
else
noblockw[0] = square;
}
} else
wp = 0;
if (BlackPawns & temp) {
square = FirstOne(BlackPawns & temp);
bp = square;
blocked = 1;
do {
for (sq = square; sq > Max(square - 32, H1); sq -= 8) {
if (SetMask(sq - 8) & WhitePieces)
break;
attackers = PopCnt(b_pawn_attacks[sq] & WhitePawns);
defenders = PopCnt(w_pawn_attacks[sq] & BlackPawns);
if (attackers > defenders)
break;
else if (attackers) {
blocked = 0;
break;
}
}
if (sq <= Max(square - 32, H1))
blocked = 0;
}
while (0);
if (blocked) {
if (!(minus8dir[square] & WhitePieces)) {
if (!TotalWhitePieces) {
if (Rank(square) <= RANK5)
blocked = 0;
}
}
}
if (!blocked) {
if (noblockb[0])
noblockb[1] = square;
else
noblockb[0] = square;
}
} else
bp = 0;
if (!kingpath) {
if (wp && wp == bp - 8) {
if (rank)
rdist = RankDistance(wp, rank);
else
rdist = 0;
rank = wp;
if (open) {
if (open == 1 && rdist > 1)
kingpath = 1;
else if (open == 2 && rdist)
kingpath = 1;
}
open = 0;
} else if (wp && SetMask(wp) & (BlackPieces << 8)) {
if (rank)
rdist = RankDistance(wp, rank);
else
rdist = 0;
rank = wp;
if (open) {
if (open == 1 && rdist > 1)
kingpath = 1;
else if (open == 2 && rdist)
kingpath = 1;
}
open = 0;
} else if (bp && SetMask(bp) & (WhitePieces >> 8)) {
if (rank)
rdist = RankDistance(bp - 8, rank);
else
rdist = 0;
rank = bp - 8;
if (open) {
if (open == 1 && rdist > 1)
kingpath = 1;
else if (open == 2 && rdist)
kingpath = 1;
}
open = 0;
} else
open++;
if (open > 2)
kingpath = 1;
else if (i == FILEH && open == 2)
kingpath = 1;
}
if (kingpath) {
if (WhiteMajors && BlackMajors)
return (NODRAW);
else if (WhiteMinors > 1 && BlackMinors > 1)
return (NODRAW);
}
if (open)
rookpath = 1;
}
if (!rookpath)
return (DRAW);
else if (!kingpath && !noblockw[0] && !noblockb[0])
return (DRAW);
if (noblockw[1]) {
fdist = FileDistance(noblockw[1], noblockw[0]);
if (WhiteMajors || WhiteMinors > 1)
return (NODRAW);
else if (!TotalBlackPieces) {
if (fdist > 1)
return (NODRAW);
else {
square = noblockw[1];
if (Rank(square) >= RANK4) {
rdist = 7 - Rank(square);
fdist = FileDistance(square, BlackKingSQ);
if (rdist < Max(fdist, 7 - Rank(BlackKingSQ)) - (1 - wtm) ||
(Rank(WhiteKingSQ) >= Rank(square) && kingpath))
return (NODRAW);
}
}
} else if (!noblockb[0] && !kingpath && !BlackMajors && BlackMinors <= 1)
return (DRAW);
}
if (noblockw[0]) {
if (WhiteMajors || WhiteMinors > 1)
return (NODRAW);
else if (!TotalBlackPieces) {
square = noblockw[0];
if (Rank(square) >= RANK4) {
rdist = 7 - Rank(square);
fdist = FileDistance(square, BlackKingSQ);
if (rdist < Max(fdist, 7 - Rank(BlackKingSQ)) - (1 - wtm) ||
(Rank(WhiteKingSQ) >= Rank(square) && kingpath))
return (NODRAW);
else if (!noblockb[0] && !kingpath && !WhiteMajors && WhiteMinors <= 1)
return (DRAW);
}
} else if (!noblockb[0] && !kingpath && !BlackMajors && BlackMinors <= 1)
return (DRAW);
}
if (noblockb[1]) {
fdist = FileDistance(noblockb[1], noblockb[0]);
if (BlackMajors || BlackMinors > 1)
return (NODRAW);
else if (!TotalWhitePieces) {
if (fdist > 1)
return (NODRAW);
else {
square = noblockb[1];
if (Rank(square) <= RANK5) {
fdist = FileDistance(square, WhiteKingSQ);
if (Rank(square) < Max(fdist, Rank(WhiteKingSQ)) - wtm ||
(Rank(BlackKingSQ) <= Rank(square) && kingpath))
return (NODRAW);
}
}
} else if (!noblockw[0] && !kingpath && !WhiteMajors && WhiteMinors <= 1)
return (DRAW);
}
if (noblockb[0]) {
if (BlackMajors || BlackMinors > 1)
return (NODRAW);
else if (!TotalWhitePieces) {
square = noblockb[0];
if (Rank(square) <= RANK5) {
fdist = FileDistance(square, WhiteKingSQ);
if (Rank(square) < Max(fdist, Rank(WhiteKingSQ)) - wtm ||
(Rank(BlackKingSQ) <= Rank(square) && kingpath))
return (NODRAW);
else if (!noblockw[0] && !kingpath && !BlackMajors && BlackMinors <= 1)
return (DRAW);
}
} else if (!noblockw[0] && !kingpath && !WhiteMajors && WhiteMinors <= 1)
return (DRAW);
} else if (!(noblockb[0] || noblockw[0])) {
if (!TotalWhitePieces && !TotalBlackPieces) {
if (!kingpath)
return (DRAW);
else if (HasOpposition(wtm, WhiteKingSQ, BlackKingSQ) &&
Rank(WhiteKingSQ) >= Rank(rank))
return (NODRAW);
else if (HasOpposition(Flip(wtm), BlackKingSQ, WhiteKingSQ) &&
Rank(BlackKingSQ) <= Rank(rank))
return (NODRAW);
else
return (DRAW);
} else if (!TotalWhitePieces) {
if (kingpath && BlackMinors | BlackMajors)
return (NODRAW);
else if (!kingpath && (BlackMinors > 1 || BlackMajors))
return (NODRAW);
else
return (DRAW);
} else if (!TotalBlackPieces) {
if (kingpath && WhiteMinors | WhiteMajors)
return (NODRAW);
else if (!kingpath && (WhiteMinors > 1 || WhiteMajors))
return (NODRAW);
else
return (DRAW);
} else if (!kingpath &&
WhiteMinors + PopCnt(WhiteRooks | WhiteQueens) ==
BlackMinors + PopCnt(BlackRooks | BlackQueens))
return (DRAW);
else
return (NODRAW);
}
return (NODRAW);
}