1 #include "chess.h"
2 #include "data.h"
3 /* last modified 05/16/14 */
4 /*
5  *******************************************************************************
6  *                                                                             *
7  *   SEE() is used to analyze capture moves to see whether or not they appear  *
8  *   to be profitable.  The basic algorithm is extremely fast since it uses    *
9  *   the bitmaps to determine which squares are attacking the [target] square. *
10  *                                                                             *
11  *   The algorithm is quite simple.  Using the attack bitmaps, we enumerate    *
12  *   all the pieces that are attacking [target] for either side.  Then we      *
13  *   simply use the lowest piece (value) for the correct side to capture on    *
14  *   [target]. we continually "flip" sides taking the lowest piece each time.  *
15  *                                                                             *
16  *   As a piece is used, if it is a sliding piece (pawn, bishop, rook or       *
17  *   queen) we remove the piece, then generate moves of bishop/queen or        *
18  *   rook/queen and then add those in to the attackers, removing any attacks   *
19  *   that have already been used.                                              *
20  *                                                                             *
21  *******************************************************************************
22  */
SEE(TREE * RESTRICT tree,int wtm,int move)23 int SEE(TREE * RESTRICT tree, int wtm, int move) {
24   uint64_t attacks, temp = 0, toccupied = OccupiedSquares;
25   uint64_t bsliders =
26       Bishops(white) | Bishops(black) | Queens(white) | Queens(black);
27   uint64_t rsliders =
28       Rooks(white) | Rooks(black) | Queens(white) | Queens(black);
29   int attacked_piece, piece, nc = 1, see_list[32];
30   int source = From(move), target = To(move);
31 
32 /*
33  ************************************************************
34  *                                                          *
35  *  Determine which squares attack <target> for each side.  *
36  *  initialize by placing the piece on <target> first in    *
37  *  the list as it is being captured to start things off.   *
38  *                                                          *
39  ************************************************************
40  */
41   attacks = AttacksTo(tree, target);
42   attacked_piece = pcval[Captured(move)];
43 /*
44  ************************************************************
45  *                                                          *
46  *  The first piece to capture on <target> is the piece     *
47  *  standing on <source>.                                   *
48  *                                                          *
49  ************************************************************
50  */
51   wtm = Flip(wtm);
52   see_list[0] = attacked_piece;
53   piece = Piece(move);
54   attacked_piece = pcval[piece];
55   Clear(source, toccupied);
56   if (piece & 1)
57     attacks |= BishopAttacks(target, toccupied) & bsliders;
58   if (piece != king && (piece == pawn || piece & 4))
59     attacks |= RookAttacks(target, toccupied) & rsliders;
60 /*
61  ************************************************************
62  *                                                          *
63  *  Now pick out the least valuable piece for the correct   *
64  *  side that is bearing on <target>.  As we find one, we   *
65  *  update the attacks (if this is a sliding piece) to get  *
66  *  the attacks for any sliding piece that is lined up      *
67  *  behind the attacker we are removing.                    *
68  *                                                          *
69  *  Once we know there is a piece attacking the last        *
70  *  capturing piece, add it to the see list and repeat      *
71  *  until one side has no more captures.                    *
72  *                                                          *
73  ************************************************************
74  */
75   for (attacks &= toccupied; attacks; attacks &= toccupied) {
76     for (piece = pawn; piece <= king; piece++)
77       if ((temp = Pieces(wtm, piece) & attacks))
78         break;
79     if (piece > king)
80       break;
81     toccupied ^= (temp & -temp);
82     if (piece & 1)
83       attacks |= BishopAttacks(target, toccupied) & bsliders;
84     if (piece != king && piece & 4)
85       attacks |= RookAttacks(target, toccupied) & rsliders;
86     see_list[nc] = -see_list[nc - 1] + attacked_piece;
87     attacked_piece = pcval[piece];
88     if (see_list[nc++] - attacked_piece > 0)
89       break;
90     wtm = Flip(wtm);
91   }
92 /*
93  ************************************************************
94  *                                                          *
95  *  Starting at the end of the sequence of values, use a    *
96  *  "minimax" like procedure to decide where the captures   *
97  *  will stop.                                              *
98  *                                                          *
99  ************************************************************
100  */
101   while (--nc)
102     see_list[nc - 1] = -Max(-see_list[nc - 1], see_list[nc]);
103   return see_list[0];
104 }
105 
106 /* last modified 05/16/14 */
107 /*
108  *******************************************************************************
109  *                                                                             *
110  *   SEEO() is used to analyze a move already made to see if it appears to be  *
111  *   safe.  It is similar to SEE() except that the move has already been made  *
112  *   and we are checking to see whether the opponent can gain material by      *
113  *   capturing the piece just moved.                                           *
114  *                                                                             *
115  *******************************************************************************
116  */
SEEO(TREE * RESTRICT tree,int wtm,int move)117 int SEEO(TREE * RESTRICT tree, int wtm, int move) {
118   uint64_t attacks, temp = 0, toccupied = OccupiedSquares;
119   uint64_t bsliders =
120       Bishops(white) | Bishops(black) | Queens(white) | Queens(black);
121   uint64_t rsliders =
122       Rooks(white) | Rooks(black) | Queens(white) | Queens(black);
123   int attacked_piece, piece, nc = 1, see_list[32], target = To(move);
124 
125 /*
126  ************************************************************
127  *                                                          *
128  *  Determine which squares attack <target> for each side.  *
129  *  initialize by placing the piece on <target> first in    *
130  *  the list as it is being captured to start things off.   *
131  *                                                          *
132  ************************************************************
133  */
134   attacks = AttacksTo(tree, target);
135   attacked_piece = pcval[Piece(move)];
136 /*
137  ************************************************************
138  *                                                          *
139  *  The first piece to capture on <target> is the piece     *
140  *  standing on that square.  We have to find out the least *
141  *  valuable attacker for that square first.                *
142  *                                                          *
143  ************************************************************
144  */
145   wtm = Flip(wtm);
146   see_list[0] = attacked_piece;
147   for (piece = pawn; piece <= king; piece++)
148     if ((temp = Pieces(wtm, piece) & attacks))
149       break;
150   if (piece > king)
151     return 0;
152   toccupied ^= (temp & -temp);
153   if (piece & 1)
154     attacks |= BishopAttacks(target, toccupied) & bsliders;
155   if (piece != king && piece & 4)
156     attacks |= RookAttacks(target, toccupied) & rsliders;
157   attacked_piece = pcval[piece];
158   wtm = Flip(wtm);
159 /*
160  ************************************************************
161  *                                                          *
162  *  Now pick out the least valuable piece for the correct   *
163  *  side that is bearing on <target>.  As we find one, we   *
164  *  update the attacks (if this is a sliding piece) to get  *
165  *  the attacks for any sliding piece that is lined up      *
166  *  behind the attacker we are removing.                    *
167  *                                                          *
168  *  Once we know there is a piece attacking the last        *
169  *  capturing piece, add it to the see list and repeat      *
170  *  until one side has no more captures.                    *
171  *                                                          *
172  ************************************************************
173  */
174   for (attacks &= toccupied; attacks; attacks &= toccupied) {
175     for (piece = pawn; piece <= king; piece++)
176       if ((temp = Pieces(wtm, piece) & attacks))
177         break;
178     if (piece > king)
179       break;
180     toccupied ^= (temp & -temp);
181     if (piece & 1)
182       attacks |= BishopAttacks(target, toccupied) & bsliders;
183     if (piece != king && piece & 4)
184       attacks |= RookAttacks(target, toccupied) & rsliders;
185     see_list[nc] = -see_list[nc - 1] + attacked_piece;
186     attacked_piece = pcval[piece];
187     if (see_list[nc++] - attacked_piece > 0)
188       break;
189     wtm = Flip(wtm);
190   }
191 /*
192  ************************************************************
193  *                                                          *
194  *  Starting at the end of the sequence of values, use a    *
195  *  "minimax" like procedure to decide where the captures   *
196  *  will stop.                                              *
197  *                                                          *
198  ************************************************************
199  */
200   while (--nc)
201     see_list[nc - 1] = -Max(-see_list[nc - 1], see_list[nc]);
202   return see_list[0];
203 }
204