Code: Select all
int SEE(int color, int move)
{
int a, b, e, w, piece, his, mine, block, from, to, x, y, h, v, ipiece=0;
static int seq;
block = (seq += 0x100) ^ 0x80000000; /* fresh codes for used/blocked */
/*printf("SEE\n");*/
/* start doing the given capture, and set up window */
to = move & 0x77;
from = move>>8 & 0x77;
/*printf("to = %02x\n", to);*/
if(!(move&0x8000))
{ /* offensive SEE: start with given capture */
a = -1; /* if losing, don't care how bad */
ipiece = board[from];
e = b = move>>16 & 0xFF; /* from MMV pre-sort */
used[ipiece-WHITE] = seq; /* mark as used */
w = qval[ipiece-WHITE]; /* what he is gonna capture next */
} else
{ /* defensive SEE: let him start, and see how bad it is */
a = -100; e = b = ipiece = 0;
w = qval[board[to]-WHITE];
}
/* generate first recapture of opponent, preppare his LVA list */
his = First[COLOR-color]; /* Pieces-only attacker list, in LVA order */
/* Prepend relevant Pawns to list. Other pieces are already sorted. */
from = to - color + 47; /* first pawn square */
piece = board[from];
if((piece & (PAWNS|COLOR)) == ((PAWNS|COLOR)^color)) /* his pawn */
his = piece; /* prepend to list (next-field already set) */
from += 2; /* second pawn square */
piece = board[from];
if((piece & (PAWNS|COLOR)) != ((PAWNS|COLOR)^color)) /* not his pawn */
{ piece = his; his = next[his-WHITE]; } /* take next piece */
/*printf("from = %02x, piece = %02x\n", from, piece);*/
/* 'piece' now holds first piece, 'mine' the second (+ rest of list) */
retry: do {
SDB1
if((x=pos[piece-WHITE])>=0 && /* was already captured */
used[piece-WHITE]!=seq && /* captured in this SEE */
(code[piece-WHITE] & (h=capt_code[to-x]) ))
{ /* pseudo-hit: aligned for capture */
/*printf("pseudo hit\n");*/
if(h & C_CONTACT) break; /* contact attack, always hit */
v = delta_vec[to-x];
y=to;
while((h=board[y-=v])==DUMMY /* scan ray */
|| used[h-WHITE]==seq)
; /* ignore used pieces */
if(x==y) break; /* ray is clear, distant hit */
/* ray is blocked. mark blocker so we can retry later */
used[h-WHITE] = block + piece;
}
if(!(piece = his)) return b; /* out of moves */
his = next[his-WHITE]; /* remaining list */
} while(1);
LVA = piece; if(w>9) return(-100);
/* for first capture, we require legality. So test for pin on King */
y = x = pos[BLACK-color]; /* opponent's King */
if(capt_code[pos[piece-WHITE]-x] & C_QUEEN)
{
/*printf("aligned with King at %02x h= %02x & %02x\n", x, h, C_QUEEN);*/
v = delta_vec[pos[piece-WHITE]-x];
while(board[x+=v] == DUMMY || board[x] == piece
|| board[x] == ipiece);
/*printf("ray ends at %02x, code=%02x & %02x\n", x, h, code[board[x]-WHITE]);*/
if(!(board[x] & COLOR^color) &&
capt_code[y-x] & code[board[x]-WHITE])/* piece was pinned */
{ LVA = 0; /* try next */
if(!(piece = his)) return b; /* out of moves */
his = next[his-WHITE]; /* remaining list */
goto retry;
}
}
if((used[piece-WHITE] & ~0xFF) == block) /* blocked something! */
{
h = used[piece-WHITE] & 0xFF; /* unblocked piece */
if((h&COLOR) != color) /* rewind LVA list for X-ray */
his = h;
else if(mine==0 || kind[mine-WHITE] > kind[h-WHITE])
mine = h; /* for opponent make sure rewind is backwards */
}
SDB2("he")
used[piece-WHITE] = seq; /* mark as used */
e -= w;
w = qval[piece-WHITE];
if(e+w<=a) return a; /* victim not valuable enough to get even, futile */
if(a<e) a=e; /* in any case we have score e: if we stop now. */
/* look if continuing with capture is better: our first LVA recapture */
mine = First[color]; /* pieces-only attacker list, in LVA order */
/* Prepend relevant Pawns to list. Other pieces are already sorted. */
from = to + color - 49; /* first pawn square */
piece = board[from];
if((piece & (PAWNS|COLOR)) == (PAWNS|color)) /* my pawn */
mine = piece; /* prepend to list (next-field already set) */
from += 2; /* second pawn square */
piece = board[from];
if((piece & (PAWNS|COLOR)) != (PAWNS|color)) /* not my pawn */
{ piece = mine; mine = next[mine-WHITE]; } /* next piece */
/* 'piece' now holds first piece, 'mine' the second piece */
do {/* Now Pawns are added to both lists, loop for remaining captures */
/*printf("hoofdloop\n");*/
/* validate capture with 'piece', or find other one from my list */
do {
SDB1
if((x=pos[piece-WHITE])>=0 && /* was already captured */
used[piece-WHITE]!=seq && /* captured in this SEE */
(code[piece-WHITE] & (h=capt_code[to-x]) ))
{ /* pseudo-hit: aligned for capture */
if(h & C_CONTACT) break; /* contact attack, always hit */
v = delta_vec[to-x];
y = to;
while((h=board[y-=v])==DUMMY /* scan ray */
|| used[h-WHITE]==seq); /* ignore used pieces */
if(x==y) break; /* ray is clear, distant hit */
/* ray is blocked. mark blocker so we can retry later */
used[h-WHITE] = block + piece;
}
if(!(piece = mine)) return a; /* out of moves */
mine = next[mine-WHITE]; /* remaining list */
} while(1);
if(w>9) return(b);
if((used[piece-WHITE] & ~0xFF) == block) /* blocked something! */
{
h = used[piece-WHITE] & 0xFF; /* unblocked piece */
if((h&COLOR) == color) /* rewind LVA list for X-ray */
mine = h;
else if(his==0 || kind[his-WHITE] > kind[h-WHITE])
his = h; /* for opponent make sure rewind is backwards */
}
SDB2("I ")
used[piece-WHITE] = seq;
e += w;
w = qval[piece-WHITE];
if(e-w>=b) return b;
if(e<b) b=e;
/* next recapture of opponent from LVA list */
do {
if(!(piece = his)) return b; /* out of moves */
his = next[his-WHITE]; /* remaining list */
SDB1
if((x=pos[piece-WHITE])<0) continue; /* was already captured */
if(used[piece-WHITE]==seq) continue; /* captured in this SEE */
if(code[piece-WHITE] & (h=capt_code[to-x]))
{ /* pseudo-hit: aligned for capture */
if(h & C_CONTACT) break; /* contact attack, always hit */
v = delta_vec[to-x];
y = to;
while((h=board[y-=v])==DUMMY /* scan ray */
|| used[h-WHITE]==seq); /* ignore used pieces */
if(x==y) break; /* ray is clear, distant hit */
/* ray is blocked. mark blocker so we can retry later */
used[h-WHITE] = block + piece;
}
} while(1);
if(w>9) return(a);
if((used[piece-WHITE] & ~0xFF) == block) /* blocked something! */
{
h = used[piece-WHITE] & 0xFF; /* unblocked piece */
/*printf("unblock %x\n", h);*/
if((h&COLOR) != color) /* rewind LVA list for X-ray */
his = h;
else if(mine==0 || kind[mine-WHITE] > kind[h-WHITE])
mine = h; /* for opponent make sure rewind is backwards */
}
SDB2("he")
used[piece-WHITE] = seq;
e -= w;
w = qval[piece-WHITE];
if(e+w<=a) return a;
if(a<e) a=e;
/* unhook next recapture of us from LVA list (to conform to */
/* situation after prepending Pawns, so we can loop) */
if(!(piece = mine)) return a; /* out of moves */
mine = next[mine-WHITE]; /* remaining list */
} while(1);
}