1 package com.alonsoruibal.chess.bitboard;
2
3 import com.alonsoruibal.chess.Board;
4 import com.alonsoruibal.chess.log.Logger;
5
6
7
8
9 public class BitboardAttacks {
10 private static final Logger logger = Logger.getLogger("BitboardAttacksGwt");
11 public static boolean initialized = false;
12
13 public final static byte rookShiftBits[] = {
14 12, 11, 11, 11, 11, 11, 11, 12,
15 11, 10, 10, 10, 10, 10, 10, 11,
16 11, 10, 10, 10, 10, 10, 10, 11,
17 11, 10, 10, 10, 10, 10, 10, 11,
18 11, 10, 10, 10, 10, 10, 10, 11,
19 11, 10, 10, 10, 10, 10, 10, 11,
20 11, 10, 10, 10, 10, 10, 10, 11,
21 12, 11, 11, 11, 11, 11, 11, 12
22 };
23
24 public final static byte bishopShiftBits[] = {
25 6, 5, 5, 5, 5, 5, 5, 6,
26 5, 5, 5, 5, 5, 5, 5, 5,
27 5, 5, 7, 7, 7, 7, 5, 5,
28 5, 5, 7, 9, 9, 7, 5, 5,
29 5, 5, 7, 9, 9, 7, 5, 5,
30 5, 5, 7, 7, 7, 7, 5, 5,
31 5, 5, 5, 5, 5, 5, 5, 5,
32 6, 5, 5, 5, 5, 5, 5, 6
33 };
34
35
36
37
38
39
40
41
42
43
44
45 public static long[][] bishopMagic;
46 public static long[] knight;
47 public static long[] king;
48 public static long[] pawnDownwards;
49 public static long[] pawnUpwards;
50
51 static {
52 init();
53 }
54
55 static long squareAttackedAux(long square, int shift, long border) {
56 if ((square & border) == 0) {
57 if (shift > 0) square <<= shift; else square >>>= -shift;
58 return square;
59 }
60 return 0;
61 }
62
63 static long squareAttackedAuxSlider(long square, int shift, long border) {
64 long ret = 0;
65 while ((square & border) == 0) {
66 if (shift > 0) square <<= shift; else square >>>= -shift;
67 ret |= square;
68 }
69 return ret;
70 }
71
72 static long squareAttackedAuxSliderMask(long square, int shift, long border) {
73 long ret = 0;
74 while ((square & border) == 0) {
75 if (shift > 0) square <<= shift; else square >>>= -shift;
76 if ((square & border) == 0) ret |= square;
77 }
78 return ret;
79 }
80
81 public static void generateAttacks() {
82 logger.debug("Generating attack tables...");
83 long time1 = System.currentTimeMillis();
84
85
86
87
88
89 bishopMagic = new long[64][];
90 knight = new long[64];
91 king = new long[64];
92 pawnDownwards = new long[64];
93 pawnUpwards = new long[64];
94
95 long square = 1;
96 byte i = 0;
97 while (square != 0) {
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118 knight[i] = squareAttackedAux(square, +17, BitboardUtils.b2_u | BitboardUtils.b_l)
119 | squareAttackedAux(square, +15, BitboardUtils.b2_u | BitboardUtils.b_r)
120 | squareAttackedAux(square, -15, BitboardUtils.b2_d | BitboardUtils.b_l)
121 | squareAttackedAux(square, -17, BitboardUtils.b2_d | BitboardUtils.b_r)
122 | squareAttackedAux(square, +10, BitboardUtils.b_u | BitboardUtils.b2_l)
123 | squareAttackedAux(square, +6, BitboardUtils.b_u | BitboardUtils.b2_r)
124 | squareAttackedAux(square, -6, BitboardUtils.b_d | BitboardUtils.b2_l)
125 | squareAttackedAux(square, -10, BitboardUtils.b_d | BitboardUtils.b2_r);
126
127 pawnUpwards[i] = squareAttackedAux(square, 7, BitboardUtils.b_u | BitboardUtils.b_r)
128 | squareAttackedAux(square, 9, BitboardUtils.b_u | BitboardUtils.b_l);
129
130 pawnDownwards[i] = squareAttackedAux(square, -7, BitboardUtils.b_d | BitboardUtils.b_l)
131 | squareAttackedAux(square, -9, BitboardUtils.b_d | BitboardUtils.b_r);
132
133 king[i] = squareAttackedAux(square, +8, BitboardUtils.b_u)
134 | squareAttackedAux(square, -8, BitboardUtils.b_d)
135 | squareAttackedAux(square, -1, BitboardUtils.b_r)
136 | squareAttackedAux(square, +1, BitboardUtils.b_l)
137 | squareAttackedAux(square, +9, BitboardUtils.b_u | BitboardUtils.b_l)
138 | squareAttackedAux(square, +7, BitboardUtils.b_u | BitboardUtils.b_r)
139 | squareAttackedAux(square, -7, BitboardUtils.b_d | BitboardUtils.b_l)
140 | squareAttackedAux(square, -9, BitboardUtils.b_d | BitboardUtils.b_r);
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159 square <<= 1;
160 i++;
161 }
162 long time2 = System.currentTimeMillis();
163 initialized = true;
164 logger.debug("Generated attack tables in " + (time2-time1) + "ms");
165 }
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188 public static void init() {
189
190
191
192
193
194
195
196
197
198
199 if (initialized) return;
200 generateAttacks();
201 }
202
203
204
205
206 public static boolean isSquareAttacked(Board board, long square, boolean white) {
207 return isIndexAttacked(board, BitboardUtils.square2Index(square), white);
208 }
209
210
211
212
213 public static boolean isIndexAttacked(Board board, byte index, boolean white) {
214 if (index < 0 || index > 63) return false;
215 long others = (white ? board.blacks : board.whites);
216 long all = board.getAll();
217
218 if (((white ? BitboardAttacks.pawnUpwards[index] : BitboardAttacks.pawnDownwards[index]) & board.pawns & others) != 0) return true;
219 if ((BitboardAttacks.king[index] & board.kings & others) != 0) return true;
220 if ((BitboardAttacks.knight[index] & board.knights & others) != 0) return true;
221 if ((getRookAttacks(index, all) & (board.rooks | board.queens) & others) != 0) return true;
222 if ((getBishopAttacks(index, all) & (board.bishops | board.queens) & others) != 0) return true;
223 return false;
224 }
225
226
227
228
229 public static long getIndexAttacks(Board board, int index) {
230 if (index < 0 || index > 63) return 0;
231 long all = board.getAll();
232
233 return ((board.blacks & BitboardAttacks.pawnUpwards[index] | board.whites & BitboardAttacks.pawnDownwards[index]) & board.pawns) |
234 (BitboardAttacks.king[index] & board.kings) |
235 (BitboardAttacks.knight[index] & board.knights) |
236 (getRookAttacks(index, all) & (board.rooks | board.queens)) |
237 (getBishopAttacks(index, all) & (board.bishops | board.queens));
238 }
239
240 public static long getXrayAttacks(Board board, int index, long all) {
241 if (index < 0 || index > 63) return 0;
242
243 return ((getRookAttacks(index, all) & (board.rooks | board.queens)) |
244 (getBishopAttacks(index, all) & (board.bishops | board.queens))) & all;
245 }
246
247
248
249
250 public static long getRookAttacks(int index, long all) {
251 return getRookShiftAttacks(BitboardUtils.index2Square((byte) index), all);
252
253
254 }
255
256 public static long getBishopAttacks(int index, long all) {
257 return getBishopShiftAttacks(BitboardUtils.index2Square((byte) index), all);
258
259
260 }
261
262 public static int magicTransform(long b, long magic, byte bits) {
263 return (int)((b * magic) >>> (64 - bits));
264 }
265
266
267
268
269
270
271 public static long generatePieces(int index, int bits, long mask) {
272 int i;
273 long lsb;
274 long result = 0L;
275 for (i = 0; i < bits; i++) {
276 lsb = mask & (-mask);
277 mask ^= lsb;
278 if ((index & (1 << i)) != 0) result |= lsb;
279 }
280 return result;
281 }
282
283
284
285
286 public static long getRookShiftAttacks(long square, long all) {
287 return checkSquareAttackedAux(square, all, +8, BitboardUtils.b_u) |
288 checkSquareAttackedAux(square, all, -8, BitboardUtils.b_d) |
289 checkSquareAttackedAux(square, all, -1, BitboardUtils.b_r) |
290 checkSquareAttackedAux(square, all, +1, BitboardUtils.b_l);
291 }
292
293 public static long getBishopShiftAttacks(long square, long all) {
294 return checkSquareAttackedAux(square, all, +9, BitboardUtils.b_u | BitboardUtils.b_l) |
295 checkSquareAttackedAux(square, all, +7, BitboardUtils.b_u | BitboardUtils.b_r) |
296 checkSquareAttackedAux(square, all, -7, BitboardUtils.b_d | BitboardUtils.b_l) |
297 checkSquareAttackedAux(square, all, -9, BitboardUtils.b_d | BitboardUtils.b_r);
298 }
299
300
301
302
303 private static long checkSquareAttackedAux(long square, long all, int shift, long border) {
304 long ret = 0;
305 while ((square & border) == 0) {
306 if (shift>0) square <<= shift; else square >>>= -shift;
307 ret |= square;
308
309 if ((square & all) != 0) break;
310 }
311 return ret;
312 }
313 }