short SqAtakd (short sq, short side) /************************************************************************** * * To determine if sq is attacked by any pieces from side. * **************************************************************************/ { register BitBoard *a, b, *c, d, blocker; int t; a = board.b[side]; /* Knights */ if (a[knight] & MoveArray[knight][sq]) return (true); /* Kings */ if (a[king] & MoveArray[king][sq]) return (true); /* Pawns */ if (a[pawn] & MoveArray[ptype[1^side]][sq]) return (true); c = FromToRay[sq]; blocker = board.blocker; /* Bishops & Queen */ b = (a[bishop] | a[queen]) & MoveArray[bishop][sq]; d = ~b & blocker; while (b) { t = leadz (b); if (!(c[t] & d)) return (true); CLEARBIT (b, t); } /* Rooks & Queen */ b = (a[rook] | a[queen]) & MoveArray[rook][sq]; d = ~b & blocker; while (b) { t = leadz (b); if (!(c[t] & d)) return (true); CLEARBIT (b, t); } return (false); }
void AddXrayPiece (int t, int sq, int side, BitBoard *b, BitBoard *c) /*************************************************************************** * * The purpose of this routine is to find a piece which attack through * another piece (e.g. two rooks, Q+B, B+P, etc.) Side is the side attacking * the square where the swapping is to be done. * ***************************************************************************/ { int dir, nsq, piece; BitBoard a; dir = directions[t][sq]; a = Ray[sq][dir] & board.blocker; if (a == NULLBITBOARD) return; nsq = (t < sq ? leadz (a) : trailz (a)); piece = cboard[nsq]; if ((piece == queen) || (piece == rook && dir > 3) || (piece == bishop && dir < 4)) { if (BitPosArray[nsq] & board.friends[side]) *b |= BitPosArray[nsq]; else *c |= BitPosArray[nsq]; } return; }
BitBoard AttackTo (int sq, int side) /*************************************************************************** * * Generate a bitboard of all squares with pieces belonging to side * which attack sq. * ***************************************************************************/ { register BitBoard *a, b, *c, e, blocker; int t; a = board.b[side]; /* Knights */ e = (a[knight] & MoveArray[knight][sq]); /* Kings */ e |= (a[king] & MoveArray[king][sq]); /* Pawns */ e |= (a[pawn] & MoveArray[ptype[1^side]][sq]); c = FromToRay[sq]; blocker = board.blocker; /* Bishops & Queen */ b = (a[bishop] | a[queen]) & MoveArray[bishop][sq]; while (b) { t = leadz (b); CLEARBIT (b, t); if (!(c[t] & blocker & NotBitPosArray[t])) e |= BitPosArray[t]; } /* Rooks & Queen */ b = (a[rook] | a[queen]) & MoveArray[rook][sq]; while (b) { t = leadz (b); CLEARBIT (b, t); if (!(c[t] & blocker & NotBitPosArray[t])) e |= BitPosArray[t]; } return (e); }
int PinnedOnKing (int sq, int side) /*************************************************************************** * * Determine if the piece on sq is pinned against the King. * Side is the color of the piece. * Caveat: PinnedOnKing should only be called by GenCheckEscapes(). * The more generic FindPins() function should be used for evaluating * pins against other pieces. * ***************************************************************************/ { int xside; int KingSq, dir, sq1; BitBoard b, blocker; KingSq = board.king[side]; if ((dir = directions[KingSq][sq]) == -1) return (false); xside = 1 ^ side; blocker = board.blocker; /* Path from piece to king is blocked, so no pin */ if (FromToRay[KingSq][sq] & NotBitPosArray[sq] & blocker) return (false); b = (Ray[KingSq][dir] ^ FromToRay[KingSq][sq]) & blocker; if (b == NULLBITBOARD) return (false); sq1 = (sq > KingSq ? leadz (b) : trailz (b)); /* If diagonal */ if (dir <= 3 && BitPosArray[sq1] & (board.b[xside][queen] | board.b[xside][bishop])) return (true); /* Rank / file */ if (dir >= 4 && BitPosArray[sq1] & (board.b[xside][queen] | board.b[xside][rook])) return (true); return (false); }
int SwapOff (int move) /**************************************************************************** * * A Static Exchange Evaluator (or SEE for short). * First determine the target square. Create a bitboard of all squares * attacking the target square for both sides. Using these 2 bitboards, * we take turn making captures from smallest piece to largest piece. * When a sliding piece makes a capture, we check behind it to see if * another attacker piece has been exposed. If so, add this to the bitboard * as well. When performing the "captures", we stop if one side is ahead * and doesn't need to capture, a form of pseudo-minimaxing. * ****************************************************************************/ { int f, t, sq, piece, lastval; int side, xside; int swaplist[MAXPLYDEPTH], n; BitBoard b, c, *d, *e, r; f = FROMSQ (move); t = TOSQ (move); side = ((board.friends[white] & BitPosArray[f]) ? white : black); xside = 1^side; /* Squares attacking t for side and xside */ b = AttackTo (t, side); c = AttackTo (t, xside); CLEARBIT(b, f); if (xray[cboard[f]]) AddXrayPiece (t, f, side, &b, &c); d = board.b[side]; e = board.b[xside]; if (move & PROMOTION) { swaplist[0] = Value[PROMOTEPIECE (move)] - ValueP; lastval = -Value[PROMOTEPIECE (move)]; } else { swaplist[0] = (move & ENPASSANT ? ValueP : Value[cboard[t]]); lastval = -Value[cboard[f]]; } n = 1; while (1) { if (c == NULLBITBOARD) break; for (piece = pawn; piece <= king; piece++) { r = c & e[piece]; if (r) { sq = leadz (r); CLEARBIT (c, sq); if (xray[piece]) AddXrayPiece (t, sq, xside, &c, &b); swaplist[n] = swaplist[n-1] + lastval; n++; lastval = Value[piece]; break; } } if (b == NULLBITBOARD) break; for (piece = pawn; piece <= king; piece++) { r = b & d[piece]; if (r) { sq = leadz (r); CLEARBIT (b, sq); if (xray[piece]) AddXrayPiece (t, sq, side, &b, &c); swaplist[n] = swaplist[n-1] + lastval; n++; lastval = -Value[piece]; break; } } } /**************************************************************************** * * At this stage, we have the swap scores in a list. We just need to * mini-max the scores from the bottom up to the top of the list. * ****************************************************************************/ --n; while (n) { if (n & 1) { if (swaplist[n] <= swaplist[n-1]) swaplist[n-1] = swaplist[n]; } else { if (swaplist[n] >= swaplist[n-1]) swaplist[n-1] = swaplist[n]; } --n; } return (swaplist[0]); }
int ParseEPD (char *p) /************************************************************************** * * Parses an EPD input line. A few global variables are updated e.g. * current board, side to move, en passant, castling status, etc. * **************************************************************************/ { int r, c, sq; char *str_p; r = 56; c = 0; memset (&board, 0, sizeof (board)); while (p && *p != ' ') { sq = r + c; switch (*p) { case 'P' : SETBIT (board.b[white][pawn], sq); SETBIT (board.blockerr90, r90[sq]); SETBIT (board.blockerr45, r45[sq]); SETBIT (board.blockerr315, r315[sq]); board.material[white] += ValueP; break; case 'N' : SETBIT (board.b[white][knight], sq); SETBIT (board.blockerr90, r90[sq]); SETBIT (board.blockerr45, r45[sq]); SETBIT (board.blockerr315, r315[sq]); board.material[white] += ValueN; break; case 'B' : SETBIT (board.b[white][bishop], sq); SETBIT (board.blockerr90, r90[sq]); SETBIT (board.blockerr45, r45[sq]); SETBIT (board.blockerr315, r315[sq]); board.material[white] += ValueB; break; case 'R' : SETBIT (board.b[white][rook], sq); SETBIT (board.blockerr90, r90[sq]); SETBIT (board.blockerr45, r45[sq]); SETBIT (board.blockerr315, r315[sq]); board.material[white] += ValueR; break; case 'Q' : SETBIT (board.b[white][queen], sq); SETBIT (board.blockerr90, r90[sq]); SETBIT (board.blockerr45, r45[sq]); SETBIT (board.blockerr315, r315[sq]); board.material[white] += ValueQ; break; case 'K' : SETBIT (board.b[white][king], sq); SETBIT (board.blockerr90, r90[sq]); SETBIT (board.blockerr45, r45[sq]); SETBIT (board.blockerr315, r315[sq]); break; case 'p' : SETBIT (board.b[black][pawn], sq); SETBIT (board.blockerr90, r90[sq]); SETBIT (board.blockerr45, r45[sq]); SETBIT (board.blockerr315, r315[sq]); board.material[black] += ValueP; break; case 'n' : SETBIT (board.b[black][knight], sq); SETBIT (board.blockerr90, r90[sq]); SETBIT (board.blockerr45, r45[sq]); SETBIT (board.blockerr315, r315[sq]); board.material[black] += ValueN; break; case 'b' : SETBIT (board.b[black][bishop], sq); SETBIT (board.blockerr90, r90[sq]); SETBIT (board.blockerr45, r45[sq]); SETBIT (board.blockerr315, r315[sq]); board.material[black] += ValueB; break; case 'r' : SETBIT (board.b[black][rook], sq); SETBIT (board.blockerr90, r90[sq]); SETBIT (board.blockerr45, r45[sq]); SETBIT (board.blockerr315, r315[sq]); board.material[black] += ValueR; break; case 'q' : SETBIT (board.b[black][queen], sq); SETBIT (board.blockerr90, r90[sq]); SETBIT (board.blockerr45, r45[sq]); SETBIT (board.blockerr315, r315[sq]); board.material[black] += ValueQ; break; case 'k' : SETBIT (board.b[black][king], sq); SETBIT (board.blockerr90, r90[sq]); SETBIT (board.blockerr45, r45[sq]); SETBIT (board.blockerr315, r315[sq]); break; case '/' : r -= 8; c = -1; break; default : break; } if (isdigit (*p)) c += (*p - '0'); else c++; /* * Special case, a trailing "/" is accepted on the * end of the board settings. */ if (r == -8 && p[1] == ' ') r = 0; if (r < 0 || c > 8) return EPD_ERROR; if (c == 8 && p[1] != '/' && p[1] != ' ') return EPD_ERROR; p++; } board.pmaterial[white] = board.material[white] - nbits(board.b[white][pawn]) * ValueP; board.pmaterial[black] = board.material[black] - nbits(board.b[black][pawn]) * ValueP; board.king[white] = leadz (board.b[white][king]); board.king[black] = leadz (board.b[black][king]); UpdateFriends (); UpdateCBoard (); UpdateMvboard (); /* Get side to move */ if (!++p) return EPD_ERROR; if (*p == 'w') board.side = white; else if (*p == 'b') board.side = black; else return EPD_ERROR; /* Isn't this one cute? */ if (!++p || *p != ' ' || !++p) return EPD_ERROR; /* Castling status */ while (p && *p != ' ') { if (*p == 'K') board.flag |= WKINGCASTLE; else if (*p == 'Q') board.flag |= WQUEENCASTLE; else if (*p == 'k') board.flag |= BKINGCASTLE; else if (*p == 'q') board.flag |= BQUEENCASTLE; else if (*p == '-') { p++; break; } else return EPD_ERROR; p++; } if (!p || *p != ' ' || !++p) return EPD_ERROR; /* * En passant square, can only be '-' or [a-h][36] * In fact, one could add more sanity checks here. */ if (*p != '-') { if (!p[1] || *p < 'a' || *p > 'h' || !(p[1] == '3' || p[1] == '6')) return EPD_ERROR; board.ep = (*p - 'a') + (p[1] - '1')*8; p++; } else { board.ep = -1; } solution[0] = '\0'; id[0] = '\0'; if (!++p) return EPD_SUCCESS; /* The opcodes are optional, so we should not generate errors here */ /* Read in best move; "bm" operator */ str_p = strstr(p, "bm"); if (str_p) sscanf (str_p, "bm %63[^;];", solution); /* Read in the description; "id" operator */ str_p = strstr(p, "id"); if (str_p) sscanf (p, "id %31[^;];", id); phase = PHASE; return EPD_SUCCESS; }
void GenAtaks (void) /************************************************************************* * * To generate the attack table. * Ataks[side][0] holds the total attack tables. * Ataks[side][pawn] holds the BitBoard of squares attacked by all pawns. * *************************************************************************/ { int side; int sq; register BitBoard *a, b, *t, *a0; memset (Ataks, 0, sizeof (Ataks)); for (side = white; side <= black; side++) { a = board.b[side]; /* Knight */ t = &Ataks[side][knight]; b = a[knight]; while (b) { sq = leadz (b); CLEARBIT (b, sq); *t |= MoveArray[knight][sq]; } /* Bishops */ t = &Ataks[side][bishop]; b = a[bishop]; while (b) { sq = leadz (b); CLEARBIT (b, sq); *t |= BishopAttack(sq); } /* Rooks */ t = &Ataks[side][rook]; b = a[rook]; while (b) { sq = leadz (b); CLEARBIT (b, sq); *t |= RookAttack(sq); } /* Queen */ t = &Ataks[side][queen]; b = a[queen]; while (b) { sq = leadz (b); CLEARBIT (b, sq); *t |= QueenAttack(sq); } /* King */ t = &Ataks[side][king]; b = a[king]; while (b) { sq = leadz (b); CLEARBIT (b, sq); *t |= MoveArray[king][sq]; } /* pawns */ t = &Ataks[side][pawn]; if (side == white) { b = board.b[white][pawn] & ~FileBit[0]; *t |= (b >> 7); b = board.b[white][pawn] & ~FileBit[7]; *t |= (b >> 9); } else {