// piece-square tables. White and black tables interleave. The first two pairs are (0, center) and (hand1, ???)
#define center (pstData + 22*11)
#define hand1 (pstData + 22*11) /* beware: uses off-board part only */
-#define sparePST (pstData + 22*11) /* on-board part still available for something else */
-#define pawnPST (pstData + 22*11*2) /* from here interleaved (white, black) */
-#define kingPST (pstData + 22*11*3)
+#define kingPST (pstData + 22*11*2) /* King and Queen PST */
+#define pawnPST (pstData + 22*11*3) /* from here interleaved (white, black) */
+#define knightPST (pstData + 22*11*4)
+#define owlPST (pstData + 22*11*5)
+#define promoPST (pstData + 22*11*6) /* +90 in zone, for strong promotion */
+#define generalPST (pstData + 22*11*7)/* +30 in central zone */
+#define rookPST (pstData + 22*11*8) /* +45 in zone */
-signed char pstData[22*11*8]; // actual tables (for now 8 pairs)
+signed char pstData[22*11*9]; // actual tables (for now 9 pairs)
int
MyRandom ()
}
PST[WHITE+2] = PST[BLACK+2] = center; // Bishops
for(f=0; f<11; f++) { // pawn tables
+ int d = (nrRanks > 8 || nrRanks == 7); // larger camp
for(r=0; r<=zone; r++) pawnPST[22*(nrRanks - 1 - r) + f] = pawnPST[22*r + f + 11] = 1.2*pieceValues[WHITE]; // in and just before zone ('7th rank')
pawnPST[22*(nrRanks - 2 - zone) + f] = pawnPST[22*(zone + 1) + f + 11] = 0.6*pieceValues[WHITE]; // ('6th rank')
pawnPST[22*(nrRanks - 2) + f + 11] = pawnPST[22 + f] = 10; // discourage leaving 2nd rank
- for(r=2; r<nrRanks-2; r++) kingPST[22*r+f] = -127; kingPST[f] = kingPST[22*(nrRanks-1)+f] = 90;
- for(r=2; r<nrRanks-2; r++) kingPST[22*r+f+11] = -40;
+ for(r=0; r<nrRanks; r++) pawnPST[22*(nrRanks - 1 - r) + f] = pawnPST[22*r + f + 11] -= (r - nrRanks/2)*3 +10;
+ for(r=2+d; r<nrRanks-2-d; r++) kingPST[22*r+f] = -127; kingPST[f] = kingPST[22*(nrRanks-1)+f] = 80; kingPST[22*d+f] = kingPST[22*(nrRanks-1-d)+f] = 90;
+ for(r=2+d; r<nrRanks-2-d; r++) kingPST[22*r+f+11] = -40;
+ knightPST[22*3+f] = knightPST[22*4+11+f] = 12; // only used for zh
+ knightPST[22*4+f] = knightPST[22*3+11+f] = 20;
+ knightPST[22*5+f] = knightPST[22*2+11+f] = 17;
}
PST[WHITE] = pawnPST; PST[BLACK] = pawnPST + 11;
PST[WHITE+31] = PST[BLACK+31] = kingPST;
+ for(f=0; f<nrFiles; f++) for(r=0; r<nrRanks; r++) {
+ int xr = nrRanks - 1 - r; double mr = (nrRanks - 1.)/2., mf = (nrFiles - 1.)/2.;
+ generalPST[22*r+f] = generalPST[22*xr+f+11] = (r-mr)*5 - r*(f-mf)*(f-mf) + 10*(xr < zone) - 20*(xr == 0);
+ owlPST[22*r+f] = owlPST[22*xr+f+11] = (r == 1)*10 + (xr < zone ? 90 : -90) + 90*(xr == zone);
+ promoPST[22*r+f] = promoPST[22*xr+f+11] = 90*(xr < zone);
+ rookPST[22*r+f] = rookPST[22*xr+f+11] = 45*(xr < zone);
+ }
+
InitCaptureCodes(variants[v].codes);
pinCodes = (v == 3 ? 0xFF2C : 0xFF1F); // rays along which pinning ispossible
}
}
int
+DiscoTest (int stm, int fromSqr, int king, StackFrame *f)
+{
+ int vec = king - fromSqr;
+ int match = captCode[vec] & pinCodes;
+ if(match) { // from-square is aligned
+ int x = king, v = deltaVec[vec];
+ while(board[x-=v] == 0) {} // scan ray
+ if(f->checker != x && !(board[x] & stm) && captCode[king-x] & pieceCode[board[x]]) { // discovered check
+ if(f->checker != CK_NONE) f->checker = CK_DOUBLE;
+ else f->checker = x, f->checkDir = v, f->checkDist = dist[x-king];
+ }
+ }
+}
+
+void
+CheckTest (int stm, StackFrame *ff, StackFrame *f)
+{
+ int king = location[stm+31]; // own King
+ int vec = king - ff->toSqr;
+ int match = captCode[vec] & pieceCode[ff->toPiece];
+ f->checker = CK_NONE; f->checkDist = 0; // assume not in check
+ if(match & C_DISTANT) { // moving piece is aligned
+ int x = ff->toSqr, v = deltaVec[vec];
+ while(board[x+=v] == 0) {} // scan ray
+ if(x == king) f->checker = ff->toSqr, f->checkDir = v, f->checkDist = dist[vec]; // ray is clear, distant check
+ } else if(match & C_CONTACT) f->checker = ff->toSqr, f->checkDir = 0; // contact check
+ if(ff->mutation != -1) { // board move (no drop)
+ DiscoTest(stm, ff->fromSqr, king, ff);
+ if(board[ff->captSqr] == 0) DiscoTest(stm, ff->captSqr, king, ff); // e.p. capture can discover check as well
+ }
+}
+
+int
+Pinned (int stm, int fromSqr, int xking)
+{
+ int vec = xking - fromSqr;
+ int match = captCode[vec] & pinCodes;
+ if(match) {
+ int x = xking, v = deltaVec[vec];
+ while(board[x-=v] == 0) {}
+ if(!(board[x] & stm) && captCode[xking-x] & pieceCode[board[x]]) return 1; // guards & counters tests as own piece!
+ }
+ return 0;
+}
+
+int
NonEvade (StackFrame *f)
{
if((f->fromPiece & ~COLOR) != 31) { // moves non-royal (or drops)
int curEval, score;
// legality
- int earlyGen = (ff->toPiece == stm+31 || ff->toSqr != ff->captSqr); // King was moved, or e.p.
+ int earlyGen = (ff->toPiece == stm+31); // King was moved
if(ply > 90) Dump("maxply");
f.xking = location[stm+31]; // opponent King, as stm not yet toggled
- if(!earlyGen) { // if other piece was moved, abort with +INF score if it was pinned
- if(ff->mutation > 0) { // exclude drops
- int vec = f.xking - ff->fromSqr;
- int match = captCode[vec] & pinCodes;
- if(match) {
- int x = f.xking, v = deltaVec[vec];
- while(board[x-=v] == 0) {}
- if(!(board[x] & stm) && captCode[f.xking-x] & pieceCode[board[x]]) return INF; // guards & counters tests as own piece!
- }
- }
+ if(!earlyGen && ff->mutation > 0) { // if other piece was moved (not dropped!), abort with +INF score if it was pinned
+ if(Pinned(stm, ff->fromSqr, f.xking)) return INF;
+ if(board[ff->captSqr] == 0 && Pinned(stm, ff->captSqr, f.xking)) return INF; // also check 'e.p. pin'
}
+
// some housekeeping
stm ^= COLOR;
f.hashKey = ff->newKey;
// check test
- if(f.checker == CK_UNKNOWN) { // hash did not supply it
- int king = location[stm+31]; // own King
- int vec = king - ff->toSqr;
- int match = captCode[vec] & pieceCode[ff->toPiece];
- f.checker = CK_NONE; f.checkDist = 0; // assume not in check
- if(match & C_DISTANT) { // moving piece is aligned
- int x = ff->toSqr, v = deltaVec[vec];
- while(board[x+=v] == 0) {} // scan ray
- if(x == king) f.checker = ff->toSqr, f.checkDir = v, f.checkDist = dist[vec]; // ray is clear, distant check
- } else if(match & C_CONTACT) f.checker = ff->toSqr, f.checkDir = 0; // contact check
- if(ff->mutation != -1) { // board move (no drop)
- vec = king - ff->fromSqr;
- match = captCode[vec] & pinCodes;
- if(match) { // from-square is aligned
- int x = king, v = deltaVec[vec];
- while(board[x-=v] == 0) {} // scan ray
- if(f.checker != x && !(board[x] & stm) && captCode[king-x] & pieceCode[board[x]]) { // discovered check
- if(f.checker != CK_NONE) f.checker = CK_DOUBLE;
- else f.checker = x, f.checkDir = v, f.checkDist = dist[x-king];
- }
- }
- if(board[ff->captSqr] == 0) { // e.p. capture can discover check as well
- vec = king - ff->captSqr;
- match = captCode[vec] & pinCodes;
- if(match) { // from-square is aligned
- int x = king, v = deltaVec[vec];
- while(board[x-=v] == 0) {} // scan ray
- if(f.checker != x && !(board[x] & stm) && captCode[king-x] & pieceCode[board[x]]) { // discovered check
- if(f.checker != CK_NONE) f.checker = CK_DOUBLE;
- else f.checker = x, f.checkDir = v, f.checkDist = dist[x-king];
- }
- }
- }
- }
- }
+ if(f.checker == CK_UNKNOWN) CheckTest(stm, ff, &f); // test for check if hash did not supply it
if(f.checker != CK_NONE) depth++, maxDepth++, reduction = 0; // extend check evasions
else if(depth > 3) {
if(depth - reduction < 3) reduction = depth - 3; // never reduce to below 3 ply