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