1 #include "chess.h"
2 #include "data.h"
3 /* last modified 01/07/14 */
4 /*
5  *******************************************************************************
6  *                                                                             *
7  *   Attacks() is used to determine if <side> attacks <square>.  The algorithm *
8  *   is simple, and is based on the AttacksTo() algorithm, but, rather than    *
9  *   returning a bitmap of squares attacking <square> it returns a "1" as soon *
10  *   as it finds anything that attacks <square>.                               *
11  *                                                                             *
12  *******************************************************************************
13  */
Attacks(TREE * RESTRICT tree,int side,int square)14 int Attacks(TREE * RESTRICT tree, int side, int square) {
15   if ((rook_attacks[square] & (Rooks(side) | Queens(side)))
16       && (RookAttacks(square,
17               OccupiedSquares) & (Rooks(side) | Queens(side))))
18     return 1;
19   if ((bishop_attacks[square] & (Bishops(side) | Queens(side)))
20       && (BishopAttacks(square,
21               OccupiedSquares) & (Bishops(side) | Queens(side))))
22     return 1;
23   if (KnightAttacks(square) & Knights(side))
24     return 1;
25   if (PawnAttacks(Flip(side), square) & Pawns(side))
26     return 1;
27   if (KingAttacks(square) & Kings(side))
28     return 1;
29   return 0;
30 }
31 
32 /* last modified 01/07/14 */
33 /*
34  *******************************************************************************
35  *                                                                             *
36  *   AttacksTo() is used to produce a bitboard which is a map of all squares   *
37  *   that directly attack this <square>.  The non-sliding pieces are trivial   *
38  *   to detect, but for sliding pieces, we use a bitboard trick.  The idea is  *
39  *   to compute the squares a queen would attack, if it was standing on        *
40  *   <square> and then look at the last square attacked in each direction to   *
41  *   determine if it is a sliding piece that moves in the right direction.  To *
42  *   finish up, we simply need to Or() all these attackers together.           *
43  *                                                                             *
44  *******************************************************************************
45  */
AttacksTo(TREE * RESTRICT tree,int square)46 uint64_t AttacksTo(TREE * RESTRICT tree, int square) {
47   uint64_t attacks =
48       (PawnAttacks(white, square) & Pawns(black)) | (PawnAttacks(black,
49           square) & Pawns(white));
50   uint64_t bsliders =
51       Bishops(white) | Bishops(black) | Queens(white) | Queens(black);
52   uint64_t rsliders =
53       Rooks(white) | Rooks(black) | Queens(white) | Queens(black);
54   attacks |= KnightAttacks(square) & (Knights(black) | Knights(white));
55   if (bishop_attacks[square] & bsliders)
56     attacks |= BishopAttacks(square, OccupiedSquares) & bsliders;
57   if (rook_attacks[square] & rsliders)
58     attacks |= RookAttacks(square, OccupiedSquares) & rsliders;
59   attacks |= KingAttacks(square) & (Kings(black) | Kings(white));
60   return attacks;
61 }
62 
63 /* last modified 01/07/14 */
64 /*
65  *******************************************************************************
66  *                                                                             *
67  *   AttacksFrom() is used to compute the set of squares the piece on <source> *
68  *   attacks.                                                                  *
69  *                                                                             *
70  *******************************************************************************
71  */
AttacksFrom(TREE * RESTRICT tree,int side,int source)72 uint64_t AttacksFrom(TREE * RESTRICT tree, int side, int source) {
73 
74   switch (Abs(PcOnSq(source))) {
75     case queen:
76       return QueenAttacks(source, OccupiedSquares);
77     case rook:
78       return RookAttacks(source, OccupiedSquares);
79     case bishop:
80       return BishopAttacks(source, OccupiedSquares);
81     case knight:
82       return KnightAttacks(source);
83     case pawn:
84       return PawnAttacks(side, source);
85     case king:
86       return KingAttacks(source);
87   }
88   return 0;
89 }
90 
91 /* last modified 01/07/14 */
92 /*
93  *******************************************************************************
94  *                                                                             *
95  *   Attacked() is used to determine if <square> is attacked.  It returns a    *
96  *   two bit value, 01 if <square> is attacked by <side>, 10 if <square> is    *
97  *   attacked by <enemy> and 11 if <square> is attacked by both sides.         *
98  *                                                                             *
99  *******************************************************************************
100  */
Attacked(TREE * RESTRICT tree,int side,uint64_t squares)101 uint64_t Attacked(TREE * RESTRICT tree, int side, uint64_t squares) {
102   uint64_t bsliders, rsliders, set;
103   int square;
104 
105   bsliders = Bishops(side) | Queens(side);
106   rsliders = Rooks(side) | Queens(side);
107   for (set = squares; set; set &= set - 1) {
108     square = LSB(set);
109     do {
110       if (KingAttacks(square) & Kings(side))
111         break;
112       if (KnightAttacks(square) & Knights(side))
113         break;
114       if (bishop_attacks[square] & bsliders &&
115           BishopAttacks(square, OccupiedSquares) & bsliders)
116         break;
117       if (rook_attacks[square] & rsliders &&
118           RookAttacks(square, OccupiedSquares) & rsliders)
119         break;
120       Clear(square, squares);
121     } while (0);
122   }
123   return squares;
124 }
125