Subversion Repositories Games.Chess Giants

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
99 pmbaty 1
/*
2
    Texel - A UCI chess engine.
3
    Copyright (C) 2012-2014  Peter Ă–sterlund, peterosterlund2@gmail.com
4
 
5
    This program is free software: you can redistribute it and/or modify
6
    it under the terms of the GNU General Public License as published by
7
    the Free Software Foundation, either version 3 of the License, or
8
    (at your option) any later version.
9
 
10
    This program is distributed in the hope that it will be useful,
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
    GNU General Public License for more details.
14
 
15
    You should have received a copy of the GNU General Public License
16
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
*/
18
 
19
/*
20
 * bitBoard.cpp
21
 *
22
 *  Created on: Feb 25, 2012
23
 *      Author: petero
24
 */
25
 
26
#include "bitBoard.hpp"
27
#include "position.hpp"
28
#include <cassert>
29
#include <iostream>
30
 
31
U64 BitBoard::kingAttacks[64];
32
U64 BitBoard::knightAttacks[64];
33
U64 BitBoard::wPawnAttacks[64];
34
U64 BitBoard::bPawnAttacks[64];
35
U64 BitBoard::wPawnBlockerMask[64];
36
U64 BitBoard::bPawnBlockerMask[64];
37
 
38
const U64 BitBoard::maskFile[8] = {
39
    0x0101010101010101ULL,
40
    0x0202020202020202ULL,
41
    0x0404040404040404ULL,
42
    0x0808080808080808ULL,
43
    0x1010101010101010ULL,
44
    0x2020202020202020ULL,
45
    0x4040404040404040ULL,
46
    0x8080808080808080ULL
47
};
48
 
49
U64 BitBoard::epMaskW[8];
50
U64 BitBoard::epMaskB[8];
51
 
52
const U64 BitBoard::maskRow1;
53
const U64 BitBoard::maskRow2;
54
const U64 BitBoard::maskRow3;
55
const U64 BitBoard::maskRow4;
56
const U64 BitBoard::maskRow5;
57
const U64 BitBoard::maskRow6;
58
const U64 BitBoard::maskRow7;
59
const U64 BitBoard::maskRow8;
60
const U64 BitBoard::maskRow1Row8;
61
const U64 BitBoard::maskDarkSq;
62
const U64 BitBoard::maskLightSq;
63
const U64 BitBoard::maskCorners;
64
 
65
U64* BitBoard::rTables[64];
66
U64 BitBoard::rMasks[64];
67
int BitBoard::rBits[64] = { 12, 11, 11, 11, 11, 11, 11, 12,
68
                            11, 10, 10, 11, 10, 10, 10, 11,
69
                            11, 10, 10, 10, 10, 10, 10, 11,
70
                            11, 10, 10, 10, 10, 10, 10, 11,
71
                            11, 10, 10, 10, 10, 10, 10, 11,
72
                            11, 10, 10, 11, 10, 10, 10, 11,
73
                            10,  9,  9,  9,  9,  9, 10, 10,
74
                            11, 10, 10, 10, 10, 11, 10, 11 };
75
const U64 BitBoard::rMagics[64] = {
76
    0x19a80065ff2bffffULL, 0x3fd80075ffebffffULL, 0x4010000df6f6fffeULL, 0x0050001faffaffffULL,
77
    0x0050028004ffffb0ULL, 0x7f600280089ffff1ULL, 0x7f5000b0029ffffcULL, 0x5b58004848a7fffaULL,
78
    0x002a90005547ffffULL, 0x000050007f13ffffULL, 0x007fa0006013ffffULL, 0x006a9005656fffffULL,
79
    0x007f600f600affffULL, 0x007ec007e6bfffe2ULL, 0x007ec003eebffffbULL, 0x0071d002382fffdaULL,
80
    0x009f803000e7fffaULL, 0x00680030008bffffULL, 0x00606060004f3ffcULL, 0x001a00600bff9ffdULL,
81
    0x000d006005ff9fffULL, 0x0001806003005fffULL, 0x00000300040bfffaULL, 0x000192500065ffeaULL,
82
    0x00fff112d0006800ULL, 0x007ff037d000c004ULL, 0x003fd062001a3ff8ULL, 0x00087000600e1ffcULL,
83
    0x000fff0100100804ULL, 0x0007ff0100080402ULL, 0x0003ffe0c0060003ULL, 0x0001ffd53000d300ULL,
84
    0x00fffd3000600061ULL, 0x007fff7f95900040ULL, 0x003fff8c00600060ULL, 0x001ffe2587a01860ULL,
85
    0x000fff3fbf40180cULL, 0x0007ffc73f400c06ULL, 0x0003ff86d2c01405ULL, 0x0001fffeaa700100ULL,
86
    0x00fffdfdd8005000ULL, 0x007fff80ebffb000ULL, 0x003fffdf603f6000ULL, 0x001fffe050405000ULL,
87
    0x000fff400700c00cULL, 0x0007ff6007bf600aULL, 0x0003ffeebffec005ULL, 0x0001fffdf3feb001ULL,
88
    0x00ffff39ff484a00ULL, 0x007fff3fff486300ULL, 0x003fff99ffac2e00ULL, 0x001fff31ff2a6a00ULL,
89
    0x000fff19ff15b600ULL, 0x0007fff5fff28600ULL, 0x0003fffddffbfee0ULL, 0x0001fff5f63c96a0ULL,
90
    0x00ffff5dff65cfb6ULL, 0x007fffbaffd1c5aeULL, 0x003fff71ff6cbceaULL, 0x001fffd9ffd4756eULL,
91
    0x000ffff5fff338e6ULL, 0x0007fffdfffe24f6ULL, 0x0003ffef27eebe74ULL, 0x0001ffff23ff605eULL
92
};
93
 
94
U64* BitBoard::bTables[64];
95
U64 BitBoard::bMasks[64];
96
const int BitBoard::bBits[64] = { 5, 4, 5, 5, 5, 5, 4, 5,
97
                                  4, 4, 5, 5, 5, 5, 4, 4,
98
                                  4, 4, 7, 7, 7, 7, 4, 4,
99
                                  5, 5, 7, 9, 9, 7, 5, 5,
100
                                  5, 5, 7, 9, 9, 7, 5, 5,
101
                                  4, 4, 7, 7, 7, 7, 4, 4,
102
                                  4, 4, 5, 5, 5, 5, 4, 4,
103
                                  5, 4, 5, 5, 5, 5, 4, 5 };
104
const U64 BitBoard::bMagics[64] = {
105
    0x0006eff5367ff600ULL, 0x00345835ba77ff2bULL, 0x00145f68a3f5dab6ULL, 0x003a1863fb56f21dULL,
106
    0x0012eb6bfe9d93cdULL, 0x000d82827f3420d6ULL, 0x00074bcd9c7fec97ULL, 0x000034fe99f9ffffULL,
107
    0x0000746f8d6717f6ULL, 0x00003acb32e1a3f7ULL, 0x0000185daf1ffb8aULL, 0x00003a1867f17067ULL,
108
    0x0000038ee0ccf92eULL, 0x000002a2b7ff926eULL, 0x000006c9aa93ff14ULL, 0x00000399b5e5bf87ULL,
109
    0x00400f342c951ffcULL, 0x0020230579ed8ff0ULL, 0x007b008a0077dbfdULL, 0x001d00010c13fd46ULL,
110
    0x00040022031c1ffbULL, 0x000fa00fd1cbff79ULL, 0x000400a4bc9affdfULL, 0x000200085e9cffdaULL,
111
    0x002a14560a3dbfbdULL, 0x000a0a157b9eafd1ULL, 0x00060600fd002ffaULL, 0x004006000c009010ULL,
112
    0x001a002042008040ULL, 0x001a00600fd1ffc0ULL, 0x000d0ace50bf3f8dULL, 0x000183a48434efd1ULL,
113
    0x001fbd7670982a0dULL, 0x000fe24301d81a0fULL, 0x0007fbf82f040041ULL, 0x000040c800008200ULL,
114
    0x007fe17018086006ULL, 0x003b7ddf0ffe1effULL, 0x001f92f861df4a0aULL, 0x000fd713ad98a289ULL,
115
    0x000fd6aa751e400cULL, 0x0007f2a63ae9600cULL, 0x0003ff7dfe0e3f00ULL, 0x000003fd2704ce04ULL,
116
    0x00007fc421601d40ULL, 0x007fff5f70900120ULL, 0x003fa66283556403ULL, 0x001fe31969aec201ULL,
117
    0x0007fdfc18ac14bbULL, 0x0003fb96fb568a47ULL, 0x000003f72ea4954dULL, 0x00000003f8dc0383ULL,
118
    0x0000007f3a814490ULL, 0x00007dc5c9cf62a6ULL, 0x007f23d3342897acULL, 0x003fee36eee1565cULL,
119
    0x0003ff3e99fcccc7ULL, 0x000003ecfcfac5feULL, 0x00000003f97f7453ULL, 0x0000000003f8dc03ULL,
120
    0x000000007efa8146ULL, 0x0000007ed3e2ef60ULL, 0x00007f47243adcd6ULL, 0x007fb65afabfb3b5ULL
121
};
122
 
123
vector_aligned<U64> BitBoard::tableData;
124
 
125
const S8 BitBoard::dirTable[] = {
126
       -9,  0,  0,  0,  0,  0,  0, -8,  0,  0,  0,  0,  0,  0, -7,
127
    0,  0, -9,  0,  0,  0,  0,  0, -8,  0,  0,  0,  0,  0, -7,  0,
128
    0,  0,  0, -9,  0,  0,  0,  0, -8,  0,  0,  0,  0, -7,  0,  0,
129
    0,  0,  0,  0, -9,  0,  0,  0, -8,  0,  0,  0, -7,  0,  0,  0,
130
    0,  0,  0,  0,  0, -9,  0,  0, -8,  0,  0, -7,  0,  0,  0,  0,
131
    0,  0,  0,  0,  0,  0, -9,-17, -8,-15, -7,  0,  0,  0,  0,  0,
132
    0,  0,  0,  0,  0,  0,-10, -9, -8, -7, -6,  0,  0,  0,  0,  0,
133
    0, -1, -1, -1, -1, -1, -1, -1,  0,  1,  1,  1,  1,  1,  1,  1,
134
    0,  0,  0,  0,  0,  0,  6,  7,  8,  9, 10,  0,  0,  0,  0,  0,
135
    0,  0,  0,  0,  0,  0,  7, 15,  8, 17,  9,  0,  0,  0,  0,  0,
136
    0,  0,  0,  0,  0,  7,  0,  0,  8,  0,  0,  9,  0,  0,  0,  0,
137
    0,  0,  0,  0,  7,  0,  0,  0,  8,  0,  0,  0,  9,  0,  0,  0,
138
    0,  0,  0,  7,  0,  0,  0,  0,  8,  0,  0,  0,  0,  9,  0,  0,
139
    0,  0,  7,  0,  0,  0,  0,  0,  8,  0,  0,  0,  0,  0,  9,  0,
140
    0,  7,  0,  0,  0,  0,  0,  0,  8,  0,  0,  0,  0,  0,  0,  9
141
};
142
 
143
const S8 BitBoard::kingDistTable[] = {
144
       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
145
    0, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7,
146
    0, 7, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 7,
147
    0, 7, 6, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 6, 7,
148
    0, 7, 6, 5, 4, 3, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7,
149
    0, 7, 6, 5, 4, 3, 2, 2, 2, 2, 2, 3, 4, 5, 6, 7,
150
    0, 7, 6, 5, 4, 3, 2, 1, 1, 1, 2, 3, 4, 5, 6, 7,
151
    0, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7,
152
    0, 7, 6, 5, 4, 3, 2, 1, 1, 1, 2, 3, 4, 5, 6, 7,
153
    0, 7, 6, 5, 4, 3, 2, 2, 2, 2, 2, 3, 4, 5, 6, 7,
154
    0, 7, 6, 5, 4, 3, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7,
155
    0, 7, 6, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 6, 7,
156
    0, 7, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 7,
157
    0, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7,
158
    0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
159
};
160
 
161
const S8 BitBoard::taxiDistTable[] = {
162
      14,13,12,11,10, 9, 8, 7, 8, 9,10,11,12,13,14,
163
    0,13,12,11,10, 9, 8, 7, 6, 7, 8, 9,10,11,12,13,
164
    0,12,11,10, 9, 8, 7, 6, 5, 6, 7, 8, 9,10,11,12,
165
    0,11,10, 9, 8, 7, 6, 5, 4, 5, 6, 7, 8, 9,10,11,
166
    0,10, 9, 8, 7, 6, 5, 4, 3, 4, 5, 6, 7, 8, 9,10,
167
    0, 9, 8, 7, 6, 5, 4, 3, 2, 3, 4, 5, 6, 7, 8, 9,
168
    0, 8, 7, 6, 5, 4, 3, 2, 1, 2, 3, 4, 5, 6, 7, 8,
169
    0, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7,
170
    0, 8, 7, 6, 5, 4, 3, 2, 1, 2, 3, 4, 5, 6, 7, 8,
171
    0, 9, 8, 7, 6, 5, 4, 3, 2, 3, 4, 5, 6, 7, 8, 9,
172
    0,10, 9, 8, 7, 6, 5, 4, 3, 4, 5, 6, 7, 8, 9,10,
173
    0,11,10, 9, 8, 7, 6, 5, 4, 5, 6, 7, 8, 9,10,11,
174
    0,12,11,10, 9, 8, 7, 6, 5, 6, 7, 8, 9,10,11,12,
175
    0,13,12,11,10, 9, 8, 7, 6, 7, 8, 9,10,11,12,13,
176
    0,14,13,12,11,10, 9, 8, 7, 8, 9,10,11,12,13,14
177
};
178
 
179
const int BitBoard::trailingZ[64] = {
180
    63,  0, 58,  1, 59, 47, 53,  2,
181
    60, 39, 48, 27, 54, 33, 42,  3,
182
    61, 51, 37, 40, 49, 18, 28, 20,
183
    55, 30, 34, 11, 43, 14, 22,  4,
184
    62, 57, 46, 52, 38, 26, 32, 41,
185
    50, 36, 17, 19, 29, 10, 13, 21,
186
    56, 45, 25, 31, 35, 16,  9, 12,
187
    44, 24, 15,  8, 23,  7,  6,  5
188
};
189
 
190
U64 BitBoard::squaresBetween[64][64];
191
 
192
static U64 createPattern(int i, U64 mask) {
193
    U64 ret = 0ULL;
194
    for (int j = 0; ; j++) {
195
        U64 nextMask = mask & (mask - 1);
196
        U64 bit = mask ^ nextMask;
197
        if ((i & (1ULL << j)) != 0)
198
            ret |= bit;
199
        mask = nextMask;
200
        if (mask == 0)
201
            break;
202
    }
203
    return ret;
204
}
205
 
206
static U64 addRay(U64 mask, int x, int y, int dx, int dy,
207
                  U64 occupied, bool inner) {
208
    int lo = inner ? 1 : 0;
209
    int hi = inner ? 6 : 7;
210
    while (true) {
211
        if (dx != 0) {
212
            x += dx; if ((x < lo) || (x > hi)) break;
213
        }
214
        if (dy != 0) {
215
            y += dy; if ((y < lo) || (y > hi)) break;
216
        }
217
        int sq = Position::getSquare(x, y);
218
        mask |= 1ULL << sq;
219
        if ((occupied & (1ULL << sq)) != 0)
220
            break;
221
    }
222
    return mask;
223
}
224
 
225
static U64 addRookRays(int x, int y, U64 occupied, bool inner) {
226
    U64 mask = 0;
227
    mask = addRay(mask, x, y,  1,  0, occupied, inner);
228
    mask = addRay(mask, x, y, -1,  0, occupied, inner);
229
    mask = addRay(mask, x, y,  0,  1, occupied, inner);
230
    mask = addRay(mask, x, y,  0, -1, occupied, inner);
231
    return mask;
232
}
233
 
234
static U64 addBishopRays(int x, int y, U64 occupied, bool inner) {
235
    U64 mask = 0;
236
    mask = addRay(mask, x, y,  1,  1, occupied, inner);
237
    mask = addRay(mask, x, y, -1, -1, occupied, inner);
238
    mask = addRay(mask, x, y,  1, -1, occupied, inner);
239
    mask = addRay(mask, x, y, -1,  1, occupied, inner);
240
    return mask;
241
}
242
 
243
static StaticInitializer<BitBoard> bbInit;
244
 
245
void
246
BitBoard::staticInitialize() {
247
 
248
    for (int f = 0; f < 8; f++) {
249
        U64 m = 0;
250
        if (f > 0) m |= 1ULL << Position::getSquare(f-1, 3);
251
        if (f < 7) m |= 1ULL << Position::getSquare(f+1, 3);
252
        epMaskW[f] = m;
253
 
254
        m = 0;
255
        if (f > 0) m |= 1ULL << Position::getSquare(f-1, 4);
256
        if (f < 7) m |= 1ULL << Position::getSquare(f+1, 4);
257
        epMaskB[f] = m;
258
    }
259
 
260
    // Compute king attacks
261
    for (int sq = 0; sq < 64; sq++) {
262
        U64 m = 1ULL << sq;
263
        U64 mask = (((m >> 1) | (m << 7) | (m >> 9)) & maskAToGFiles) |
264
                   (((m << 1) | (m << 9) | (m >> 7)) & maskBToHFiles) |
265
                    (m << 8) | (m >> 8);
266
        kingAttacks[sq] = mask;
267
    }
268
 
269
    // Compute knight attacks
270
    for (int sq = 0; sq < 64; sq++) {
271
        U64 m = 1ULL << sq;
272
        U64 mask = (((m <<  6) | (m >> 10)) & maskAToFFiles) |
273
                   (((m << 15) | (m >> 17)) & maskAToGFiles) |
274
                   (((m << 17) | (m >> 15)) & maskBToHFiles) |
275
                   (((m << 10) | (m >>  6)) & maskCToHFiles);
276
        knightAttacks[sq] = mask;
277
    }
278
 
279
    // Compute pawn attacks
280
    for (int sq = 0; sq < 64; sq++) {
281
        U64 m = 1ULL << sq;
282
        U64 mask = ((m << 7) & maskAToGFiles) | ((m << 9) & maskBToHFiles);
283
        wPawnAttacks[sq] = mask;
284
        mask = ((m >> 9) & maskAToGFiles) | ((m >> 7) & maskBToHFiles);
285
        bPawnAttacks[sq] = mask;
286
 
287
        int x = Position::getX(sq);
288
        int y = Position::getY(sq);
289
        m = 0;
290
        for (int y2 = y+1; y2 < 8; y2++) {
291
            if (x > 0) m |= 1ULL << Position::getSquare(x-1, y2);
292
                       m |= 1ULL << Position::getSquare(x  , y2);
293
            if (x < 7) m |= 1ULL << Position::getSquare(x+1, y2);
294
        }
295
        wPawnBlockerMask[sq] = m;
296
        m = 0;
297
        for (int y2 = y-1; y2 >= 0; y2--) {
298
            if (x > 0) m |= 1ULL << Position::getSquare(x-1, y2);
299
                       m |= 1ULL << Position::getSquare(x  , y2);
300
            if (x < 7) m |= 1ULL << Position::getSquare(x+1, y2);
301
        }
302
        bPawnBlockerMask[sq] = m;
303
    }
304
 
305
    // Rook magics
306
    int rTableSize = 0;
307
    for (int sq = 0; sq < 64; sq++)
308
        rTableSize += 1 << rBits[sq];
309
    int bTableSize = 0;
310
    for (int sq = 0; sq < 64; sq++)
311
        bTableSize += 1 << bBits[sq];
312
    tableData.resize(rTableSize + bTableSize);
313
 
314
    int tableUsed = 0;
315
    for (int sq = 0; sq < 64; sq++) {
316
        int x = Position::getX(sq);
317
        int y = Position::getY(sq);
318
        rMasks[sq] = addRookRays(x, y, 0ULL, true);
319
        int tableSize = 1 << rBits[sq];
320
        U64* table = &tableData[tableUsed];
321
        tableUsed += tableSize;
322
        const U64 unInit = 0xffffffffffffffffULL;
323
        for (int i = 0; i < tableSize; i++) table[i] = unInit;
324
        int nPatterns = 1 << BitBoard::bitCount(rMasks[sq]);
325
        for (int i = 0; i < nPatterns; i++) {
326
            U64 p = createPattern(i, rMasks[sq]);
327
            int entry = (int)((p * rMagics[sq]) >> (64 - rBits[sq]));
328
            U64 atks = addRookRays(x, y, p, false);
329
            if (table[entry] == unInit) {
330
                table[entry] = atks;
331
            } else {
332
                assert(table[entry] == atks);
333
            }
334
        }
335
        rTables[sq] = table;
336
    }
337
 
338
    // Bishop magics
339
    for (int sq = 0; sq < 64; sq++) {
340
        int x = Position::getX(sq);
341
        int y = Position::getY(sq);
342
        bMasks[sq] = addBishopRays(x, y, 0ULL, true);
343
        int tableSize = 1 << bBits[sq];
344
        U64* table = &tableData[tableUsed];
345
        tableUsed += tableSize;
346
        const U64 unInit = 0xffffffffffffffffULL;
347
        for (int i = 0; i < tableSize; i++) table[i] = unInit;
348
        int nPatterns = 1 << BitBoard::bitCount(bMasks[sq]);
349
        for (int i = 0; i < nPatterns; i++) {
350
            U64 p = createPattern(i, bMasks[sq]);
351
            int entry = (int)((p * bMagics[sq]) >> (64 - bBits[sq]));
352
            U64 atks = addBishopRays(x, y, p, false);
353
            if (table[entry] == unInit) {
354
                table[entry] = atks;
355
            } else {
356
                assert(table[entry] == atks);
357
            }
358
        }
359
        bTables[sq] = table;
360
    }
361
 
362
    // squaresBetween
363
    for (int sq1 = 0; sq1 < 64; sq1++) {
364
        for (int j = 0; j < 64; j++)
365
            squaresBetween[sq1][j] = 0;
366
        for (int dx = -1; dx <= 1; dx++) {
367
            for (int dy = -1; dy <= 1; dy++) {
368
                if ((dx == 0) && (dy == 0))
369
                    continue;
370
                U64 m = 0;
371
                int x = Position::getX(sq1);
372
                int y = Position::getY(sq1);
373
                while (true) {
374
                    x += dx; y += dy;
375
                    if ((x < 0) || (x > 7) || (y < 0) || (y > 7))
376
                        break;
377
                    int sq2 = Position::getSquare(x, y);
378
                    squaresBetween[sq1][sq2] = m;
379
                    m |= 1ULL << sq2;
380
                }
381
            }
382
        }
383
    }
384
}
385
 
386
U64 BitBoard::mirrorX(U64 mask) {
387
    U64 ret = 0;
388
    while (mask != 0) {
389
        int sq = extractSquare(mask);
390
        int x = Position::getX(sq);
391
        int y = Position::getY(sq);
392
        int sq2 = Position::getSquare(7-x, y);
393
        ret |= (1ULL << sq2);
394
    }
395
    return ret;
396
}
397
 
398
U64 BitBoard::mirrorY(U64 mask) {
399
    U64 ret = 0;
400
    while (mask != 0) {
401
        int sq = extractSquare(mask);
402
        int x = Position::getX(sq);
403
        int y = Position::getY(sq);
404
        int sq2 = Position::getSquare(x, 7-y);
405
        ret |= (1ULL << sq2);
406
    }
407
    return ret;
408
}