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) 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
 * tbprobe.cpp
21
 *
22
 *  Created on: Jun 2, 2014
23
 *      Author: petero
24
 */
25
 
26
#include "tbprobe.hpp"
27
#include "gtb/gtb-probe.h"
28
#include "syzygy/rtb-probe.hpp"
29
#include "bitBoard.hpp"
30
#include "position.hpp"
31
#include "moveGen.hpp"
32
#include "constants.hpp"
33
#include <unordered_map>
34
#include <cassert>
35
 
36
#include "util/timeUtil.hpp"
37
 
38
static std::string currentGtbPath;
39
static int currentGtbCacheMB;
40
static int currentGtbWdlFraction;
41
static std::string currentRtbPath;
42
 
43
static const char** gtbPaths = nullptr;
44
static int gtbMaxPieces = 0;
45
 
46
static std::unordered_map<int,int> maxDTM; // MatId -> Max DTM value in GTB TB
47
static std::unordered_map<int,int> maxDTZ; // MatId -> Max DTZ value in RTB TB
48
struct IIPairHash {
49
    size_t operator()(const std::pair<int,int>& p) const {
50
        return p.first * 0x714d3559 + p.second;
51
    }
52
};
53
// (MatId,maxPawnMoves) -> Max DTM in sub TBs
54
static std::unordered_map<std::pair<int,int>,int,IIPairHash> maxSubDTM;
55
 
56
 
57
void
58
TBProbe::initialize(const std::string& gtbPath, int cacheMB,
59
                    const std::string& rtbPath) {
60
    if (rtbPath != currentRtbPath) {
61
        Syzygy::init(rtbPath);
62
        currentRtbPath = rtbPath;
63
    }
64
 
65
    int wdlFraction = (Syzygy::TBLargest >= 5) ? 8 : 96;
66
    if ((gtbPath != currentGtbPath) ||
67
        (cacheMB != currentGtbCacheMB) ||
68
        (wdlFraction != currentGtbWdlFraction)) {
69
        gtbInitialize(gtbPath, cacheMB, wdlFraction);
70
        currentGtbPath = gtbPath;
71
        currentGtbCacheMB = cacheMB;
72
        currentGtbWdlFraction = wdlFraction;
73
    }
74
 
75
    static bool initialized = false;
76
    if (!initialized) {
77
        initWDLBounds();
78
        initialized = true;
79
    }
80
}
81
 
82
bool
83
TBProbe::tbEnabled() {
84
    return Syzygy::TBLargest > 0 || gtbMaxPieces > 0;
85
}
86
 
87
bool
88
TBProbe::tbProbe(Position& pos, int ply, int alpha, int beta,
89
                 TranspositionTable::TTEntry& ent) {
90
    const int nPieces = BitBoard::bitCount(pos.occupiedBB());
91
    bool mateSearch = SearchConst::isLoseScore(alpha) || SearchConst::isWinScore(beta);
92
 
93
    if (mateSearch || pos.getHalfMoveClock() > 0) {
94
        // Need DTM or DTZ probe
95
        int dtmScore;
96
        bool hasDtm = false;
97
        if (nPieces <= gtbMaxPieces && gtbProbeDTM(pos, ply, dtmScore)) {
98
            if (SearchConst::MATE0 - 1 - abs(dtmScore) - ply <= 100 - pos.getHalfMoveClock()) {
99
                ent.setScore(dtmScore, ply);
100
                ent.setType(TType::T_EXACT);
101
                return true;
102
            }
103
            hasDtm = true;
104
        }
105
        int dtzScore;
106
        if (nPieces <= Syzygy::TBLargest && rtbProbeDTZ(pos, ply, dtzScore)) {
107
            ent.setScore(dtzScore, ply);
108
            if (dtzScore > 0)
109
                ent.setType(TType::T_GE);
110
            else if (dtzScore < 0)
111
                ent.setType(TType::T_LE);
112
            else
113
                ent.setType(TType::T_EXACT);
114
            return true;
115
        }
116
        if (hasDtm) {
117
            ent.setScore(dtmScore, ply);
118
            ent.setType(TType::T_EXACT);
119
            return true;
120
        }
121
    }
122
 
123
    if (pos.getHalfMoveClock() == 0) {
124
        // Try WDL probe if DTM/DTZ not needed or not available
125
        int wdlScore;
126
        if ((nPieces <= Syzygy::TBLargest && rtbProbeWDL(pos, ply, wdlScore)) ||
127
                (nPieces <= gtbMaxPieces && gtbProbeWDL(pos, ply, wdlScore))) {
128
            ent.setScore(wdlScore, ply);
129
            if (wdlScore > 0)
130
                ent.setType(TType::T_GE);
131
            else if (wdlScore < 0)
132
                ent.setType(TType::T_LE);
133
            else
134
                ent.setType(TType::T_EXACT);
135
            return true;
136
        }
137
    }
138
    return false;
139
}
140
 
141
bool
142
TBProbe::getSearchMoves(Position& pos, const MoveList& legalMoves,
143
                        std::vector<Move>& movesToSearch) {
144
    const int mate0 = SearchConst::MATE0;
145
    const int ply = 0;
146
    TranspositionTable::TTEntry rootEnt;
147
    if (!tbProbe(pos, ply, -mate0, mate0, rootEnt) || rootEnt.getType() == TType::T_LE)
148
        return false;
149
    const int rootScore = rootEnt.getScore(ply);
150
    if (!SearchConst::isWinScore(rootScore))
151
        return false;
152
 
153
    // Root position is TB win
154
    bool hasProgress = false;
155
    UndoInfo ui;
156
    for (int mi = 0; mi < legalMoves.size; mi++) {
157
        const Move& m = legalMoves[mi];
158
        pos.makeMove(m, ui);
159
        TranspositionTable::TTEntry ent;
160
        ent.clear();
161
        bool progressMove = false;
162
        bool badMove = false;
163
        if (tbProbe(pos, ply+1, -mate0, mate0, ent)) {
164
            const int type = ent.getType();
165
            const int score = -ent.getScore(ply+1);
166
            if (score >= rootScore && (type == TType::T_EXACT || type == TType::T_LE))
167
                progressMove = true;
168
            if ((score < rootScore)) //  && (type == TType::T_EXACT || type == TType::T_GE))
169
                badMove = true;
170
        }
171
        if (progressMove)
172
            hasProgress = true;
173
        if (!badMove)
174
            movesToSearch.push_back(m);
175
        pos.unMakeMove(m, ui);
176
    }
177
 
178
    return !hasProgress && !movesToSearch.empty();
179
}
180
 
181
void
182
TBProbe::extendPV(const Position& rootPos, std::vector<Move>& pv) {
183
    Position pos(rootPos);
184
    UndoInfo ui;
185
    int ply = 0;
186
    int score;
187
    for (int i = 0; i < (int)pv.size(); i++) {
188
        const Move& m = pv[i];
189
        pos.makeMove(m, ui);
190
        if (TBProbe::gtbProbeDTM(pos, ply, score) && SearchConst::isWinScore(std::abs(score)) &&
191
            (SearchConst::MATE0 - 1 - abs(score) - ply <= 100 - pos.getHalfMoveClock())) {
192
            // TB win, replace rest of PV since it may be inaccurate
193
            pv.erase(pv.begin()+i+1, pv.end());
194
            break;
195
        }
196
    }
197
    if (!TBProbe::gtbProbeDTM(pos, ply, score) || !SearchConst::isWinScore(std::abs(score)))
198
        return; // No TB win
199
    if (SearchConst::MATE0 - 1 - abs(score) - ply > 100 - pos.getHalfMoveClock())
200
        return; // Mate too far away, perhaps 50-move draw
201
    if (!pos.isWhiteMove())
202
        score = -score;
203
    while (true) {
204
        MoveList moveList;
205
        MoveGen::pseudoLegalMoves(pos, moveList);
206
        MoveGen::removeIllegal(pos, moveList);
207
        bool extended = false;
208
        for (int mi = 0; mi < moveList.size; mi++) {
209
            const Move& m = moveList[mi];
210
            pos.makeMove(m, ui);
211
            int newScore;
212
            if (TBProbe::gtbProbeDTM(pos, ply+1, newScore)) {
213
                if (!pos.isWhiteMove())
214
                    newScore = -newScore;
215
                if (newScore == score) {
216
                    pv.push_back(m);
217
                    ply++;
218
                    extended = true;
219
                    break;
220
                }
221
            }
222
            pos.unMakeMove(m, ui);
223
        }
224
        if (!extended)
225
            break;
226
    }
227
}
228
 
229
template <typename ProbeFunc>
230
static void handleEP(Position& pos, int ply, int& score, bool& ret, ProbeFunc probeFunc) {
231
    const bool inCheck = MoveGen::inCheck(pos);
232
    MoveList moveList;
233
    if (inCheck) MoveGen::checkEvasions(pos, moveList);
234
    else         MoveGen::pseudoLegalMoves(pos, moveList);
235
    const int pawn = pos.isWhiteMove() ? Piece::WPAWN : Piece::BPAWN;
236
    int bestEP = std::numeric_limits<int>::min();
237
    UndoInfo ui;
238
    for (int m = 0; m < moveList.size; m++) {
239
        const Move& move = moveList[m];
240
        if ((move.to() == pos.getEpSquare()) && (pos.getPiece(move.from()) == pawn)) {
241
            if (MoveGen::isLegal(pos, move, inCheck)) {
242
                pos.makeMove(move, ui);
243
                int score2;
244
                bool ret2 = probeFunc(pos, ply+1, score2);
245
                pos.unMakeMove(move, ui);
246
                if (!ret2) {
247
                    ret = false;
248
                    return;
249
                }
250
                bestEP = std::max(bestEP, -score2);
251
            }
252
        } else if (MoveGen::isLegal(pos, move, inCheck))
253
            return;
254
    }
255
    if (bestEP != std::numeric_limits<int>::min())
256
        score = bestEP;
257
}
258
 
259
bool
260
TBProbe::gtbProbeDTM(Position& pos, int ply, int& score) {
261
    if (BitBoard::bitCount(pos.occupiedBB()) > gtbMaxPieces)
262
        return false;
263
 
264
    GtbProbeData gtbData;
265
    getGTBProbeData(pos, gtbData);
266
    bool ret = gtbProbeDTM(gtbData, ply, score);
267
    if (ret && score == 0 && pos.getEpSquare() != -1)
268
        handleEP(pos, ply, score, ret, [](Position& pos, int ply, int& score) -> bool {
269
            return TBProbe::gtbProbeDTM(pos, ply, score);
270
        });
271
    return ret;
272
}
273
 
274
bool
275
TBProbe::gtbProbeWDL(Position& pos, int ply, int& score) {
276
    if (BitBoard::bitCount(pos.occupiedBB()) > gtbMaxPieces)
277
        return false;
278
 
279
    GtbProbeData gtbData;
280
    getGTBProbeData(pos, gtbData);
281
    bool ret = gtbProbeWDL(gtbData, ply, score);
282
    if (ret && score == 0 && pos.getEpSquare() != -1)
283
        handleEP(pos, ply, score, ret, [](Position& pos, int ply, int& score) -> bool {
284
            return TBProbe::gtbProbeWDL(pos, ply, score);
285
        });
286
    return ret;
287
}
288
 
289
bool
290
TBProbe::rtbProbeDTZ(Position& pos, int ply, int& score) {
291
    const int nPieces = BitBoard::bitCount(pos.occupiedBB());
292
    if (nPieces > Syzygy::TBLargest)
293
        return false;
294
    if (pos.getCastleMask())
295
        return false;
296
 
297
    int success;
298
    const int dtz = Syzygy::probe_dtz(pos, &success);
299
    if (!success)
300
        return false;
301
    if (dtz == 0) {
302
        score = 0;
303
        return true;
304
    }
305
    const int maxHalfMoveClock = std::abs(dtz) + pos.getHalfMoveClock();
306
    if (abs(dtz) <= 2) {
307
        if (maxHalfMoveClock > 101) {
308
            score = 0;
309
            return true;
310
        } else if (maxHalfMoveClock == 101)
311
            return false; // DTZ can be wrong when mate-in-1
312
    } else {
313
        if (maxHalfMoveClock > 100) {
314
            score = 0;
315
            return true;
316
        }
317
        // FIXME!! Are there positions where maxHalfMoveclock==101 needs special handling?
318
    }
319
    int plyToMate = getMaxSubMate(pos) + std::abs(dtz);
320
    if (dtz > 0) {
321
        score = SearchConst::MATE0 - ply - plyToMate - 2;
322
    } else {
323
        score = -(SearchConst::MATE0 - ply - plyToMate - 2);
324
    }
325
    return true;
326
}
327
 
328
bool
329
TBProbe::rtbProbeWDL(Position& pos, int ply, int& score) {
330
    if (BitBoard::bitCount(pos.occupiedBB()) > Syzygy::TBLargest)
331
        return false;
332
    if (pos.getCastleMask())
333
        return false;
334
 
335
    int success;
336
    int wdl = Syzygy::probe_wdl(pos, &success);
337
    if (!success)
338
        return false;
339
    int plyToMate;
340
    switch (wdl) {
341
    case 0: case 1: case -1:
342
        score = 0;
343
        break;
344
    case 2:
345
        plyToMate = getMaxSubMate(pos) + getMaxDTZ(pos.materialId());
346
        score = SearchConst::MATE0 - ply - plyToMate - 2;
347
        break;
348
    case -2:
349
        plyToMate = getMaxSubMate(pos) + getMaxDTZ(pos.materialId());
350
        score = -(SearchConst::MATE0 - ply - plyToMate - 2);
351
        break;
352
    default:
353
        return false;
354
    }
355
 
356
    return true;
357
}
358
 
359
void
360
TBProbe::gtbInitialize(const std::string& path, int cacheMB, int wdlFraction) {
361
    static_assert((int)tb_A1 == (int)A1, "Incompatible square numbering");
362
    static_assert((int)tb_A8 == (int)A8, "Incompatible square numbering");
363
    static_assert((int)tb_H1 == (int)H1, "Incompatible square numbering");
364
    static_assert((int)tb_H8 == (int)H8, "Incompatible square numbering");
365
 
366
    tbpaths_done(gtbPaths);
367
 
368
    gtbMaxPieces = 0;
369
    gtbPaths = tbpaths_init();
370
    gtbPaths = tbpaths_add(gtbPaths, path.c_str());
371
 
372
    TB_compression_scheme scheme = tb_CP4;
373
    int verbose = 0;
374
    int cacheSize = 1024 * 1024 * cacheMB;
375
    static bool isInitialized = false;
376
    if (isInitialized) {
377
        tb_restart(verbose, scheme, gtbPaths);
378
        tbcache_restart(cacheSize, wdlFraction);
379
    } else {
380
        tb_init(verbose, scheme, gtbPaths);
381
        tbcache_init(cacheSize, wdlFraction);
382
    }
383
    isInitialized = true;
384
 
385
    unsigned int av = tb_availability();
386
    if (av & 3)
387
        gtbMaxPieces = 3;
388
    if (av & 12)
389
        gtbMaxPieces = 4;
390
    if (av & 48)
391
        gtbMaxPieces = 5;
392
}
393
 
394
void
395
TBProbe::getGTBProbeData(const Position& pos, GtbProbeData& gtbData) {
396
    gtbData.stm = pos.isWhiteMove() ? tb_WHITE_TO_MOVE : tb_BLACK_TO_MOVE;
397
    gtbData.epsq = pos.getEpSquare() >= 0 ? pos.getEpSquare() : tb_NOSQUARE;
398
 
399
    gtbData.castles = 0;
400
    if (pos.a1Castle()) gtbData.castles |= tb_WOOO;
401
    if (pos.h1Castle()) gtbData.castles |= tb_WOO;
402
    if (pos.a8Castle()) gtbData.castles |= tb_BOOO;
403
    if (pos.h8Castle()) gtbData.castles |= tb_BOO;
404
 
405
    int cnt = 0;
406
    U64 m = pos.whiteBB();
407
    while (m != 0) {
408
        int sq = BitBoard::extractSquare(m);
409
        gtbData.wSq[cnt] = sq;
410
        switch (pos.getPiece(sq)) {
411
        case Piece::WKING:   gtbData.wP[cnt] = tb_KING;   break;
412
        case Piece::WQUEEN:  gtbData.wP[cnt] = tb_QUEEN;  break;
413
        case Piece::WROOK:   gtbData.wP[cnt] = tb_ROOK;   break;
414
        case Piece::WBISHOP: gtbData.wP[cnt] = tb_BISHOP; break;
415
        case Piece::WKNIGHT: gtbData.wP[cnt] = tb_KNIGHT; break;
416
        case Piece::WPAWN:   gtbData.wP[cnt] = tb_PAWN;   break;
417
        default:
418
            assert(false);
419
        }
420
        cnt++;
421
    }
422
    gtbData.wSq[cnt] = tb_NOSQUARE;
423
    gtbData.wP[cnt] = tb_NOPIECE;
424
 
425
    cnt = 0;
426
    m = pos.blackBB();
427
    while (m != 0) {
428
        int sq = BitBoard::extractSquare(m);
429
        gtbData.bSq[cnt] = sq;
430
        switch (pos.getPiece(sq)) {
431
        case Piece::BKING:   gtbData.bP[cnt] = tb_KING;   break;
432
        case Piece::BQUEEN:  gtbData.bP[cnt] = tb_QUEEN;  break;
433
        case Piece::BROOK:   gtbData.bP[cnt] = tb_ROOK;   break;
434
        case Piece::BBISHOP: gtbData.bP[cnt] = tb_BISHOP; break;
435
        case Piece::BKNIGHT: gtbData.bP[cnt] = tb_KNIGHT; break;
436
        case Piece::BPAWN:   gtbData.bP[cnt] = tb_PAWN;   break;
437
        default:
438
            assert(false);
439
        }
440
        cnt++;
441
    }
442
    gtbData.bSq[cnt] = tb_NOSQUARE;
443
    gtbData.bP[cnt] = tb_NOPIECE;
444
    gtbData.materialId = pos.materialId();
445
}
446
 
447
bool
448
TBProbe::gtbProbeDTM(const GtbProbeData& gtbData, int ply, int& score) {
449
    unsigned int tbInfo;
450
    unsigned int plies;
451
    if (!tb_probe_hard(gtbData.stm, gtbData.epsq, gtbData.castles,
452
                       gtbData.wSq, gtbData.bSq,
453
                       gtbData.wP, gtbData.bP,
454
                       &tbInfo, &plies))
455
        return false;
456
 
457
    switch (tbInfo) {
458
    case tb_DRAW:
459
        score = 0;
460
        break;
461
    case tb_WMATE:
462
        score = SearchConst::MATE0 - ply - plies - 1;
463
        break;
464
    case tb_BMATE:
465
        score = -(SearchConst::MATE0 - ply - (int)plies - 1); // Pierre-Marie Baty -- added type cast
466
        break;
467
    default:
468
        return false;
469
    };
470
 
471
    if (gtbData.stm == tb_BLACK_TO_MOVE)
472
        score = -score;
473
 
474
    return true;
475
}
476
 
477
bool
478
TBProbe::gtbProbeWDL(const GtbProbeData& gtbData, int ply, int& score) {
479
    unsigned int tbInfo;
480
    if (!tb_probe_WDL_hard(gtbData.stm, gtbData.epsq, gtbData.castles,
481
                           gtbData.wSq, gtbData.bSq,
482
                           gtbData.wP, gtbData.bP,
483
                           &tbInfo))
484
        return false;
485
 
486
    switch (tbInfo) {
487
    case tb_DRAW:
488
        score = 0;
489
        break;
490
    case tb_WMATE:
491
        score = maxDTM[gtbData.materialId] - ply;
492
        break;
493
    case tb_BMATE:
494
        score = -(maxDTM[gtbData.materialId] - ply);
495
        break;
496
    default:
497
        return false;
498
    };
499
 
500
    if (gtbData.stm == tb_BLACK_TO_MOVE)
501
        score = -score;
502
    return true;
503
}
504
 
505
void
506
TBProbe::initWDLBounds() {
507
    initMaxDTM();
508
    initMaxDTZ();
509
 
510
    // Pre-calculate all interesting maxSubDTM values
511
    for (int wp = 0; wp <= 4; wp++) {
512
        std::vector<int> pieces(Piece::nPieceTypes);
513
        pieces[Piece::WPAWN] = wp;
514
        pieces[Piece::BPAWN] = 4 - wp;
515
        getMaxSubMate(pieces, 4*5);
516
    }
517
}
518
 
519
/** Maximum DTZ value for a given material configuration. */
520
int
521
TBProbe::getMaxDTZ(int matId) {
522
    auto it = maxDTZ.find(matId);
523
    if (it == maxDTZ.end())
524
        return 100;
525
    int val = it->second;
526
    if (val < 0)
527
        return 0;
528
    else
529
        return std::min(val+2, 100); // RTB DTZ values are not exact
530
}
531
 
532
static int
533
getMaxPawnMoves(const Position& pos) {
534
    int maxPawnMoves = 0;
535
    U64 m = pos.pieceTypeBB(Piece::WPAWN);
536
    while (m != 0) {
537
        int sq = BitBoard::extractSquare(m);
538
        maxPawnMoves += 6 - Position::getY(sq);
539
    }
540
    m = pos.pieceTypeBB(Piece::BPAWN);
541
    while (m != 0) {
542
        int sq = BitBoard::extractSquare(m);
543
        maxPawnMoves += Position::getY(sq) - 1;
544
    }
545
    return maxPawnMoves;
546
}
547
 
548
/** Get upper bound on longest mate in all possible material configurations
549
 * after the next zeroing move. */
550
int
551
TBProbe::getMaxSubMate(const Position& pos) {
552
    int maxPawnMoves = getMaxPawnMoves(pos);
553
    int matId = pos.materialId();
554
    matId = std::min(matId, MatId::mirror(matId));
555
    auto it = maxSubDTM.find(std::make_pair(matId,maxPawnMoves));
556
    if (it != maxSubDTM.end())
557
        return it->second;
558
 
559
    std::vector<int> pieces(Piece::nPieceTypes);
560
    for (int p = 0; p < Piece::nPieceTypes; p++)
561
        pieces[p] = BitBoard::bitCount(pos.pieceTypeBB((Piece::Type)p));
562
    pieces[Piece::EMPTY] = pieces[Piece::WKING] = pieces[Piece::BKING] = 0;
563
    return getMaxSubMate(pieces, maxPawnMoves);
564
}
565
 
566
int
567
TBProbe::getMaxSubMate(std::vector<int>& pieces, int pawnMoves) {
568
    assert(pawnMoves >= 0);
569
    if (pawnMoves > (pieces[Piece::WPAWN] + pieces[Piece::BPAWN]) * 5)
570
        return 0;
571
 
572
    MatId matId;
573
    for (int p = 0; p < Piece::nPieceTypes; p++)
574
        matId.addPieceCnt(p, pieces[p]);
575
 
576
    const int matIdMin = std::min(matId(), MatId::mirror(matId()));
577
    auto it = maxSubDTM.find(std::make_pair(matIdMin, pawnMoves));
578
    if (it != maxSubDTM.end())
579
        return it->second;
580
 
581
    int maxSubMate = 0;
582
    if (pawnMoves > 0) { // Pawn move
583
        maxSubMate = getMaxSubMate(pieces, pawnMoves-1) + getMaxDTZ(matId());
584
    }
585
    for (int p = 0; p < Piece::nPieceTypes; p++) { // Capture
586
        if (pieces[p] > 0) {
587
            pieces[p]--;
588
            matId.removePiece(p);
589
            int maxRemovedPawnMoves = 0;
590
            if (p == Piece::WPAWN || p == Piece::BPAWN)
591
                maxRemovedPawnMoves = 5;
592
            for (int i = 0; i <= maxRemovedPawnMoves; i++) {
593
                int newPawnMoves = pawnMoves - i;
594
                if (newPawnMoves >= 0) {
595
                    int tmp = getMaxSubMate(pieces, newPawnMoves) + getMaxDTZ(matId());
596
                    maxSubMate = std::max(maxSubMate, tmp);
597
                }
598
            }
599
            pieces[p]++;
600
            matId.addPiece(p);
601
        }
602
    }
603
    for (int c = 0; c < 2; c++) { // Promotion
604
        const int pawn = (c == 0) ? Piece::WPAWN : Piece::BPAWN;
605
        if (pieces[pawn] > 0) {
606
            const int p0 = (c == 0) ? Piece::WQUEEN : Piece::BQUEEN;
607
            const int p1 = (c == 0) ? Piece::WKNIGHT : Piece::BKNIGHT;
608
            for (int p = p0; p <= p1; p++) {
609
                pieces[pawn]--;
610
                pieces[p]++;
611
                matId.removePiece(pawn);
612
                matId.addPiece(p);
613
                int tmp = getMaxSubMate(pieces, pawnMoves) + getMaxDTZ(matId());
614
                maxSubMate = std::max(maxSubMate, tmp);
615
                pieces[pawn]++;
616
                pieces[p]--;
617
                matId.addPiece(pawn);
618
                matId.removePiece(p);
619
            }
620
        }
621
    }
622
 
623
#if 0
624
    std::cout << "wQ:" << pieces[Piece::WQUEEN]
625
              << " wR:" << pieces[Piece::WROOK]
626
              << " wB:" << pieces[Piece::WBISHOP]
627
              << " wN:" << pieces[Piece::WKNIGHT]
628
              << " wP:" << pieces[Piece::WPAWN]
629
              << " bQ:" << pieces[Piece::BQUEEN]
630
              << " bR:" << pieces[Piece::BROOK]
631
              << " bB:" << pieces[Piece::BBISHOP]
632
              << " bN:" << pieces[Piece::BKNIGHT]
633
              << " bP:" << pieces[Piece::BPAWN]
634
              << " pMoves:" << pawnMoves << " : " << maxSubMate << std::endl;
635
#endif
636
    maxSubDTM[std::make_pair(matIdMin, pawnMoves)] = maxSubMate;
637
    return maxSubMate;
638
}
639
 
640
void
641
TBProbe::initMaxDTM() {
642
    using MI = MatId;
643
    auto add = [](int id, int value) {
644
        maxDTM[id] = value;
645
        maxDTM[MatId::mirror(id)] = value;
646
    };
647
 
648
    add(MI::WQ, 31979);
649
    add(MI::WR, 31967);
650
    add(MI::WP, 31943);
651
 
652
    add(MI::WQ*2, 31979);
653
    add(MI::WQ+MI::WR, 31967);
654
    add(MI::WQ+MI::WB, 31979);
655
    add(MI::WQ+MI::WN, 31979);
656
    add(MI::WQ+MI::WP, 31943);
657
    add(MI::WR*2, 31967);
658
    add(MI::WR+MI::WB, 31967);
659
    add(MI::WR+MI::WN, 31967);
660
    add(MI::WR+MI::WP, 31943);
661
    add(MI::WB*2, 31961);
662
    add(MI::WB+MI::WN, 31933);
663
    add(MI::WB+MI::WP, 31937);
664
    add(MI::WN*2, 31998);
665
    add(MI::WN+MI::WP, 31943);
666
    add(MI::WP*2, 31935);
667
    add(MI::WQ+MI::BQ, 31974);
668
    add(MI::WR+MI::BQ, 31929);
669
    add(MI::WR+MI::BR, 31961);
670
    add(MI::WB+MI::BQ, 31965);
671
    add(MI::WB+MI::BR, 31941);
672
    add(MI::WB+MI::BB, 31998);
673
    add(MI::WN+MI::BQ, 31957);
674
    add(MI::WN+MI::BR, 31919);
675
    add(MI::WN+MI::BB, 31998);
676
    add(MI::WN+MI::BN, 31998);
677
    add(MI::WP+MI::BQ, 31942);
678
    add(MI::WP+MI::BR, 31914);
679
    add(MI::WP+MI::BB, 31942);
680
    add(MI::WP+MI::BN, 31942);
681
    add(MI::WP+MI::BP, 31933);
682
 
683
    add(MI::WQ*3, 31991);
684
    add(MI::WQ*2+MI::WR, 31987);
685
    add(MI::WQ*2+MI::WB, 31983);
686
    add(MI::WQ*2+MI::WN, 31981);
687
    add(MI::WQ*2+MI::WP, 31979);
688
    add(MI::WQ+MI::WR*2, 31985);
689
    add(MI::WQ+MI::WR+MI::WB, 31967);
690
    add(MI::WQ+MI::WR+MI::WN, 31967);
691
    add(MI::WQ+MI::WR+MI::WP, 31967);
692
    add(MI::WQ+MI::WB*2, 31961);
693
    add(MI::WQ+MI::WB+MI::WN, 31933);
694
    add(MI::WQ+MI::WB+MI::WP, 31937);
695
    add(MI::WQ+MI::WN*2, 31981);
696
    add(MI::WQ+MI::WN+MI::WP, 31945);
697
    add(MI::WQ+MI::WP*2, 31935);
698
    add(MI::WR*3, 31985);
699
    add(MI::WR*2+MI::WB, 31967);
700
    add(MI::WR*2+MI::WN, 31967);
701
    add(MI::WR*2+MI::WP, 31967);
702
    add(MI::WR+MI::WB*2, 31961);
703
    add(MI::WR+MI::WB+MI::WN, 31933);
704
    add(MI::WR+MI::WB+MI::WP, 31937);
705
    add(MI::WR+MI::WN*2, 31967);
706
    add(MI::WR+MI::WN+MI::WP, 31945);
707
    add(MI::WR+MI::WP*2, 31935);
708
    add(MI::WB*3, 31961);
709
    add(MI::WB*2+MI::WN, 31933);
710
    add(MI::WB*2+MI::WP, 31937);
711
    add(MI::WB+MI::WN*2, 31931);
712
    add(MI::WB+MI::WN+MI::WP, 31933);
713
    add(MI::WB+MI::WP*2, 31935);
714
    add(MI::WN*3, 31957);
715
    add(MI::WN*2+MI::WP, 31943);
716
    add(MI::WN+MI::WP*2, 31935);
717
    add(MI::WP*3, 31933);
718
    add(MI::WQ*2+MI::BQ, 31939);
719
    add(MI::WQ*2+MI::BR, 31929);
720
    add(MI::WQ*2+MI::BB, 31965);
721
    add(MI::WQ*2+MI::BN, 31957);
722
    add(MI::WQ*2+MI::BP, 31939);
723
    add(MI::WQ+MI::WR+MI::BQ, 31865);
724
    add(MI::WQ+MI::WR+MI::BR, 31929);
725
    add(MI::WQ+MI::WR+MI::BB, 31941);
726
    add(MI::WQ+MI::WR+MI::BN, 31919);
727
    add(MI::WQ+MI::WR+MI::BP, 31865);
728
    add(MI::WQ+MI::WB+MI::BQ, 31933);
729
    add(MI::WQ+MI::WB+MI::BR, 31919);
730
    add(MI::WQ+MI::WB+MI::BB, 31965);
731
    add(MI::WQ+MI::WB+MI::BN, 31957);
732
    add(MI::WQ+MI::WB+MI::BP, 31933);
733
    add(MI::WQ+MI::WN+MI::BQ, 31917);
734
    add(MI::WQ+MI::WN+MI::BR, 31918);
735
    add(MI::WQ+MI::WN+MI::BB, 31965);
736
    add(MI::WQ+MI::WN+MI::BN, 31957);
737
    add(MI::WQ+MI::WN+MI::BP, 31917);
738
    add(MI::WQ+MI::WP+MI::BQ, 31752);
739
    add(MI::WQ+MI::WP+MI::BR, 31913);
740
    add(MI::WQ+MI::WP+MI::BB, 31941);
741
    add(MI::WQ+MI::WP+MI::BN, 31939);
742
    add(MI::WQ+MI::WP+MI::BP, 31755);
743
    add(MI::WR*2+MI::BQ, 31901);
744
    add(MI::WR*2+MI::BR, 31937);
745
    add(MI::WR*2+MI::BB, 31941);
746
    add(MI::WR*2+MI::BN, 31919);
747
    add(MI::WR*2+MI::BP, 31900);
748
    add(MI::WR+MI::WB+MI::BQ, 31859);
749
    add(MI::WR+MI::WB+MI::BR, 31870);
750
    add(MI::WR+MI::WB+MI::BB, 31939);
751
    add(MI::WR+MI::WB+MI::BN, 31919);
752
    add(MI::WR+MI::WB+MI::BP, 31860);
753
    add(MI::WR+MI::WN+MI::BQ, 31861);
754
    add(MI::WR+MI::WN+MI::BR, 31918);
755
    add(MI::WR+MI::WN+MI::BB, 31937);
756
    add(MI::WR+MI::WN+MI::BN, 31919);
757
    add(MI::WR+MI::WN+MI::BP, 31864);
758
    add(MI::WR+MI::WP+MI::BQ, 31792);
759
    add(MI::WR+MI::WP+MI::BR, 31851);
760
    add(MI::WR+MI::WP+MI::BB, 31853);
761
    add(MI::WR+MI::WP+MI::BN, 31891);
762
    add(MI::WR+MI::WP+MI::BP, 31794);
763
    add(MI::WB*2+MI::BQ, 31837);
764
    add(MI::WB*2+MI::BR, 31938);
765
    add(MI::WB*2+MI::BB, 31955);
766
    add(MI::WB*2+MI::BN, 31843);
767
    add(MI::WB*2+MI::BP, 31834);
768
    add(MI::WB+MI::WN+MI::BQ, 31893);
769
    add(MI::WB+MI::WN+MI::BR, 31918);
770
    add(MI::WB+MI::WN+MI::BB, 31921);
771
    add(MI::WB+MI::WN+MI::BN, 31786);
772
    add(MI::WB+MI::WN+MI::BP, 31791);
773
    add(MI::WB+MI::WP+MI::BQ, 31899);
774
    add(MI::WB+MI::WP+MI::BR, 31910);
775
    add(MI::WB+MI::WP+MI::BB, 31898);
776
    add(MI::WB+MI::WP+MI::BN, 31800);
777
    add(MI::WB+MI::WP+MI::BP, 31865);
778
    add(MI::WN*2+MI::BQ, 31855);
779
    add(MI::WN*2+MI::BR, 31918);
780
    add(MI::WN*2+MI::BB, 31992);
781
    add(MI::WN*2+MI::BN, 31986);
782
    add(MI::WN*2+MI::BP, 31770);
783
    add(MI::WN+MI::WP+MI::BQ, 31875);
784
    add(MI::WN+MI::WP+MI::BR, 31866);
785
    add(MI::WN+MI::WP+MI::BB, 31914);
786
    add(MI::WN+MI::WP+MI::BN, 31805);
787
    add(MI::WN+MI::WP+MI::BP, 31884);
788
    add(MI::WP*2+MI::BQ, 31752);
789
    add(MI::WP*2+MI::BR, 31892);
790
    add(MI::WP*2+MI::BB, 31913);
791
    add(MI::WP*2+MI::BN, 31899);
792
    add(MI::WP*2+MI::BP, 31745);
793
}
794
 
795
void
796
TBProbe::initMaxDTZ() {
797
    using MI = MatId;
798
    auto add = [](int id, int value) {
799
        maxDTZ[id] = value;
800
        maxDTZ[MatId::mirror(id)] = value;
801
    };
802
 
803
    // 2-men
804
    add(0, -1);
805
 
806
    // 3-men
807
    add(MI::WQ, 20);
808
    add(MI::WR, 32);
809
    add(MI::WB, -1);
810
    add(MI::WN, -1);
811
    add(MI::WP, 20);
812
 
813
    // 4-men
814
    add(MI::WQ+MI::BQ, 19);
815
    add(MI::WN*2, 1);
816
    add(MI::WQ*2, 6);
817
    add(MI::WP*2, 14);
818
    add(MI::WR*2, 10);
819
    add(MI::WR+MI::BR, 7);
820
    add(MI::WQ+MI::WB, 12);
821
    add(MI::WQ+MI::WR, 8);
822
    add(MI::WQ+MI::WN, 14);
823
    add(MI::WR+MI::BB, 35);
824
    add(MI::WB+MI::BB, 1);
825
    add(MI::WQ+MI::WP, 6);
826
    add(MI::WB*2, 37);
827
    add(MI::WB+MI::BN, 2);
828
    add(MI::WR+MI::WP, 6);
829
    add(MI::WN+MI::BN, 1);
830
    add(MI::WR+MI::BN, 53);
831
    add(MI::WP+MI::BP, 21);
832
    add(MI::WB+MI::BP, 7);
833
    add(MI::WR+MI::WB, 24);
834
    add(MI::WQ+MI::BN, 38);
835
    add(MI::WR+MI::WN, 24);
836
    add(MI::WB+MI::WP, 26);
837
    add(MI::WN+MI::BP, 16);
838
    add(MI::WN+MI::WP, 26);
839
    add(MI::WQ+MI::BR, 62);
840
    add(MI::WQ+MI::BB, 24);
841
    add(MI::WR+MI::BP, 25);
842
    add(MI::WQ+MI::BP, 52);
843
    add(MI::WB+MI::WN, 65);
844
 
845
    // 5-men
846
    add(MI::WQ*3, 6);
847
    add(MI::WQ*2+MI::WR, 6);
848
    add(MI::WR*3, 8);
849
    add(MI::WQ*2+MI::WB, 6);
850
    add(MI::WQ*2+MI::WN, 8);
851
    add(MI::WQ*2+MI::WP, 6);
852
    add(MI::WQ+MI::WR+MI::WN, 8);
853
    add(MI::WQ+MI::WR*2, 8);
854
    add(MI::WQ+MI::WR+MI::WB, 8);
855
    add(MI::WQ+MI::WP*2, 6);
856
    add(MI::WQ+MI::WB+MI::WN, 8);
857
    add(MI::WR*2+MI::WP, 6);
858
    add(MI::WQ+MI::WB*2, 12);
859
    add(MI::WB*3, 20);
860
    add(MI::WR*2+MI::WN, 10);
861
    add(MI::WR*2+MI::WB, 10);
862
    add(MI::WQ+MI::WR+MI::WP, 6);
863
    add(MI::WQ+MI::WN*2, 14);
864
    add(MI::WQ+MI::WB+MI::WP, 6);
865
    add(MI::WQ+MI::WN+MI::WP, 6);
866
    add(MI::WR+MI::WP*2, 6);
867
    add(MI::WR+MI::WB*2, 20);
868
    add(MI::WP*3, 14);
869
    add(MI::WR+MI::WN*2, 20);
870
    add(MI::WQ*2+MI::BQ, 50);
871
    add(MI::WQ*2+MI::BN, 8);
872
    add(MI::WQ*2+MI::BB, 8);
873
    add(MI::WR+MI::WB+MI::WN, 14);
874
    add(MI::WB+MI::WP*2, 18);
875
    add(MI::WB*2+MI::WP, 24);
876
    add(MI::WQ*2+MI::BR, 28);
877
    add(MI::WB*2+MI::WN, 26);
878
    add(MI::WN+MI::WP*2, 12);
879
    add(MI::WQ+MI::WB+MI::BQ, 59);
880
    add(MI::WB+MI::WN*2, 26);
881
    add(MI::WN*2+MI::WP, 16);
882
    add(MI::WQ*2+MI::BP, 6);
883
    add(MI::WN*3, 41);
884
    add(MI::WQ+MI::WN+MI::BQ, 69);
885
    add(MI::WQ+MI::WR+MI::BQ, 100);
886
    add(MI::WQ+MI::WR+MI::BN, 10);
887
    add(MI::WQ+MI::WR+MI::BB, 10);
888
    add(MI::WQ+MI::WR+MI::BR, 30);
889
    add(MI::WR+MI::WB+MI::WP, 8);
890
    add(MI::WQ+MI::WB+MI::BN, 14);
891
    add(MI::WQ+MI::WB+MI::BR, 38);
892
    add(MI::WQ+MI::WB+MI::BB, 16);
893
    add(MI::WB+MI::WN+MI::WP, 10);
894
    add(MI::WR+MI::WN+MI::WP, 8);
895
    add(MI::WR*2+MI::BQ, 40);
896
    add(MI::WQ+MI::WN+MI::BN, 18);
897
    add(MI::WR+MI::WB+MI::BR, 100);
898
    add(MI::WQ+MI::WN+MI::BB, 18);
899
    add(MI::WQ+MI::WR+MI::BP, 6);
900
    add(MI::WR+MI::WB+MI::BQ, 82);
901
    add(MI::WQ+MI::WP+MI::BQ, 100);
902
    add(MI::WQ+MI::WP+MI::BP, 10);
903
    add(MI::WQ+MI::WB+MI::BP, 22);
904
    add(MI::WR+MI::WN+MI::BR, 64);
905
    add(MI::WR*2+MI::BN, 14);
906
    add(MI::WR*2+MI::BP, 18);
907
    add(MI::WQ+MI::WN+MI::BR, 44);
908
    add(MI::WR+MI::WN+MI::BQ, 92);
909
    add(MI::WR*2+MI::BB, 20);
910
    add(MI::WQ+MI::WN+MI::BP, 34);
911
    add(MI::WR*2+MI::BR, 50);
912
    add(MI::WB*2+MI::BR, 16);
913
    add(MI::WB*2+MI::BB, 11);
914
    add(MI::WQ+MI::WP+MI::BN, 12);
915
    add(MI::WR+MI::WB+MI::BN, 42);
916
    add(MI::WQ+MI::WP+MI::BB, 10);
917
    add(MI::WB+MI::WN+MI::BR, 24);
918
    add(MI::WB+MI::WN+MI::BB, 24);
919
    add(MI::WB*2+MI::BN, 100);
920
    add(MI::WB+MI::WN+MI::BN, 100);
921
    add(MI::WQ+MI::WP+MI::BR, 34);
922
    add(MI::WR+MI::WP+MI::BP, 19);
923
    add(MI::WR+MI::WP+MI::BR, 70);
924
    add(MI::WR+MI::WB+MI::BB, 50);
925
    add(MI::WB*2+MI::BP, 42);
926
    add(MI::WB*2+MI::BQ, 100);
927
    add(MI::WR+MI::WB+MI::BP, 22);
928
    add(MI::WN*2+MI::BR, 20);
929
    add(MI::WN*2+MI::BB, 6);
930
    add(MI::WB+MI::WP+MI::BR, 36);
931
    add(MI::WN*2+MI::BN, 12);
932
    add(MI::WB+MI::WP+MI::BB, 50);
933
    add(MI::WR+MI::WN+MI::BN, 48);
934
    add(MI::WN+MI::WP+MI::BR, 78);
935
    add(MI::WN*2+MI::BQ, 100);
936
    add(MI::WR+MI::WN+MI::BB, 50);
937
    add(MI::WR+MI::WN+MI::BP, 29);
938
    add(MI::WB+MI::WP+MI::BN, 60);
939
    add(MI::WB+MI::WN+MI::BQ, 84);
940
    add(MI::WB+MI::WP+MI::BP, 74);
941
    add(MI::WN*2+MI::BP, 100);
942
    add(MI::WN+MI::WP+MI::BB, 48);
943
    add(MI::WP*2+MI::BB, 24);
944
    add(MI::WP*2+MI::BQ, 58);
945
    add(MI::WP*2+MI::BP, 42);
946
    add(MI::WP*2+MI::BN, 27);
947
    add(MI::WP*2+MI::BR, 30);
948
    add(MI::WN+MI::WP+MI::BN, 59);
949
    add(MI::WN+MI::WP+MI::BP, 46);
950
    add(MI::WR+MI::WP+MI::BN, 62);
951
    add(MI::WR+MI::WP+MI::BB, 100);
952
    add(MI::WN+MI::WP+MI::BQ, 86);
953
    add(MI::WB+MI::WN+MI::BP, 40);
954
    add(MI::WR+MI::WP+MI::BQ, 100);
955
    add(MI::WB+MI::WP+MI::BQ, 84);
956
 
957
    // 6-men
958
    add(MI::WB*4, 20);
959
    add(MI::WB*3+MI::BB, 40);
960
    add(MI::WB*3+MI::BN, 28);
961
    add(MI::WB*3+MI::BP, 24);
962
    add(MI::WB*3+MI::BQ, 100);
963
    add(MI::WB*3+MI::BR, 100);
964
    add(MI::WB*3+MI::WN, 26);
965
    add(MI::WB*3+MI::WP, 24);
966
    add(MI::WB*2+MI::BB*2, 11);
967
    add(MI::WB*2+MI::BB+MI::BN, 40);
968
    add(MI::WB*2+MI::BB+MI::BP, 69);
969
    add(MI::WB*2+MI::BN*2, 56);
970
    add(MI::WB*2+MI::BN+MI::BP, 100);
971
    add(MI::WB*2+MI::BP*2, 39);
972
    add(MI::WB*2+MI::WN+MI::BB, 72);
973
    add(MI::WB*2+MI::WN+MI::BN, 62);
974
    add(MI::WB*2+MI::WN+MI::BP, 32);
975
    add(MI::WB*2+MI::WN+MI::BQ, 100);
976
    add(MI::WB*2+MI::WN+MI::BR, 100);
977
    add(MI::WB*2+MI::WN*2, 20);
978
    add(MI::WB*2+MI::WN+MI::WP, 10);
979
    add(MI::WB*2+MI::WP+MI::BB, 56);
980
    add(MI::WB*2+MI::WP+MI::BN, 100);
981
    add(MI::WB*2+MI::WP+MI::BP, 29);
982
    add(MI::WB*2+MI::WP+MI::BQ, 100);
983
    add(MI::WB*2+MI::WP+MI::BR, 100);
984
    add(MI::WB*2+MI::WP*2, 12);
985
    add(MI::WB+MI::WN+MI::BB+MI::BN, 17);
986
    add(MI::WB+MI::WN+MI::BB+MI::BP, 56);
987
    add(MI::WB+MI::WN+MI::BN*2, 24);
988
    add(MI::WB+MI::WN+MI::BN+MI::BP, 98);
989
    add(MI::WB+MI::WN+MI::BP*2, 48);
990
    add(MI::WB+MI::WN*2+MI::BB, 76);
991
    add(MI::WB+MI::WN*2+MI::BN, 58);
992
    add(MI::WB+MI::WN*2+MI::BP, 33);
993
    add(MI::WB+MI::WN*2+MI::BQ, 98);
994
    add(MI::WB+MI::WN*2+MI::BR, 96);
995
    add(MI::WB+MI::WN*3, 20);
996
    add(MI::WB+MI::WN*2+MI::WP, 10);
997
    add(MI::WB+MI::WN+MI::WP+MI::BB, 86);
998
    add(MI::WB+MI::WN+MI::WP+MI::BN, 77);
999
    add(MI::WB+MI::WN+MI::WP+MI::BP, 21);
1000
    add(MI::WB+MI::WN+MI::WP+MI::BQ, 100);
1001
    add(MI::WB+MI::WN+MI::WP+MI::BR, 100);
1002
    add(MI::WB+MI::WN+MI::WP*2, 10);
1003
    add(MI::WB+MI::WP+MI::BB+MI::BP, 65);
1004
    add(MI::WB+MI::WP+MI::BN*2, 48);
1005
    add(MI::WB+MI::WP+MI::BN+MI::BP, 62);
1006
    add(MI::WB+MI::WP+MI::BP*2, 75);
1007
    add(MI::WB+MI::WP*2+MI::BB, 86);
1008
    add(MI::WB+MI::WP*2+MI::BN, 100);
1009
    add(MI::WB+MI::WP*2+MI::BP, 61);
1010
    add(MI::WB+MI::WP*2+MI::BQ, 78);
1011
    add(MI::WB+MI::WP*2+MI::BR, 66);
1012
    add(MI::WB+MI::WP*3, 18);
1013
    add(MI::WN*2+MI::BN*2, 13);
1014
    add(MI::WN*2+MI::BN+MI::BP, 56);
1015
    add(MI::WN*2+MI::BP*2, 100);
1016
    add(MI::WN*3+MI::BB, 100);
1017
    add(MI::WN*3+MI::BN, 100);
1018
    add(MI::WN*3+MI::BP, 41);
1019
    add(MI::WN*3+MI::BQ, 70);
1020
    add(MI::WN*3+MI::BR, 22);
1021
    add(MI::WN*4, 22);
1022
    add(MI::WN*3+MI::WP, 12);
1023
    add(MI::WN*2+MI::WP+MI::BB, 100);
1024
    add(MI::WN*2+MI::WP+MI::BN, 100);
1025
    add(MI::WN*2+MI::WP+MI::BP, 33);
1026
    add(MI::WN*2+MI::WP+MI::BQ, 100);
1027
    add(MI::WN*2+MI::WP+MI::BR, 91);
1028
    add(MI::WN*2+MI::WP*2, 12);
1029
    add(MI::WN+MI::WP+MI::BN+MI::BP, 57);
1030
    add(MI::WN+MI::WP+MI::BP*2, 66);
1031
    add(MI::WN+MI::WP*2+MI::BB, 97);
1032
    add(MI::WN+MI::WP*2+MI::BN, 96);
1033
    add(MI::WN+MI::WP*2+MI::BP, 40);
1034
    add(MI::WN+MI::WP*2+MI::BQ, 78);
1035
    add(MI::WN+MI::WP*2+MI::BR, 81);
1036
    add(MI::WN+MI::WP*3, 10);
1037
    add(MI::WP*2+MI::BP*2, 31);
1038
    add(MI::WP*3+MI::BB, 36);
1039
    add(MI::WP*3+MI::BN, 42);
1040
    add(MI::WP*3+MI::BP, 40);
1041
    add(MI::WP*3+MI::BQ, 65);
1042
    add(MI::WP*3+MI::BR, 44);
1043
    add(MI::WP*4, 14);
1044
    add(MI::WQ+MI::WB*3, 12);
1045
    add(MI::WQ+MI::WB*2+MI::BB, 16);
1046
    add(MI::WQ+MI::WB*2+MI::BN, 14);
1047
    add(MI::WQ+MI::WB*2+MI::BP, 10);
1048
    add(MI::WQ+MI::WB*2+MI::BQ, 100);
1049
    add(MI::WQ+MI::WB*2+MI::BR, 40);
1050
    add(MI::WQ+MI::WB*2+MI::WN, 10);
1051
    add(MI::WQ+MI::WB*2+MI::WP, 6);
1052
    add(MI::WQ+MI::WB+MI::BB*2, 26);
1053
    add(MI::WQ+MI::WB+MI::BB+MI::BN, 32);
1054
    add(MI::WQ+MI::WB+MI::BB+MI::BP, 44);
1055
    add(MI::WQ+MI::WB+MI::BN*2, 26);
1056
    add(MI::WQ+MI::WB+MI::BN+MI::BP, 53);
1057
    add(MI::WQ+MI::WB+MI::BP*2, 34);
1058
    add(MI::WQ+MI::WB+MI::BQ+MI::BB, 91);
1059
    add(MI::WQ+MI::WB+MI::BQ+MI::BN, 72);
1060
    add(MI::WQ+MI::WB+MI::BQ+MI::BP, 100);
1061
    add(MI::WQ+MI::WB+MI::BR+MI::BB, 83);
1062
    add(MI::WQ+MI::WB+MI::BR+MI::BN, 54);
1063
    add(MI::WQ+MI::WB+MI::BR+MI::BP, 77);
1064
    add(MI::WQ+MI::WB+MI::BR*2, 100);
1065
    add(MI::WQ+MI::WB+MI::WN+MI::BB, 14);
1066
    add(MI::WQ+MI::WB+MI::WN+MI::BN, 12);
1067
    add(MI::WQ+MI::WB+MI::WN+MI::BP, 8);
1068
    add(MI::WQ+MI::WB+MI::WN+MI::BQ, 100);
1069
    add(MI::WQ+MI::WB+MI::WN+MI::BR, 44);
1070
    add(MI::WQ+MI::WB+MI::WN*2, 10);
1071
    add(MI::WQ+MI::WB+MI::WN+MI::WP, 6);
1072
    add(MI::WQ+MI::WB+MI::WP+MI::BB, 12);
1073
    add(MI::WQ+MI::WB+MI::WP+MI::BN, 12);
1074
    add(MI::WQ+MI::WB+MI::WP+MI::BP, 8);
1075
    add(MI::WQ+MI::WB+MI::WP+MI::BQ, 100);
1076
    add(MI::WQ+MI::WB+MI::WP+MI::BR, 62);
1077
    add(MI::WQ+MI::WB+MI::WP*2, 8);
1078
    add(MI::WQ+MI::WN+MI::BB*2, 30);
1079
    add(MI::WQ+MI::WN+MI::BB+MI::BN, 34);
1080
    add(MI::WQ+MI::WN+MI::BB+MI::BP, 67);
1081
    add(MI::WQ+MI::WN+MI::BN*2, 32);
1082
    add(MI::WQ+MI::WN+MI::BN+MI::BP, 62);
1083
    add(MI::WQ+MI::WN+MI::BP*2, 44);
1084
    add(MI::WQ+MI::WN+MI::BQ+MI::BN, 57);
1085
    add(MI::WQ+MI::WN+MI::BQ+MI::BP, 100);
1086
    add(MI::WQ+MI::WN+MI::BR+MI::BB, 52);
1087
    add(MI::WQ+MI::WN+MI::BR+MI::BN, 80);
1088
    add(MI::WQ+MI::WN+MI::BR+MI::BP, 83);
1089
    add(MI::WQ+MI::WN+MI::BR*2, 100);
1090
    add(MI::WQ+MI::WN*2+MI::BB, 22);
1091
    add(MI::WQ+MI::WN*2+MI::BN, 18);
1092
    add(MI::WQ+MI::WN*2+MI::BP, 20);
1093
    add(MI::WQ+MI::WN*2+MI::BQ, 100);
1094
    add(MI::WQ+MI::WN*2+MI::BR, 44);
1095
    add(MI::WQ+MI::WN*3, 10);
1096
    add(MI::WQ+MI::WN*2+MI::WP, 6);
1097
    add(MI::WQ+MI::WN+MI::WP+MI::BB, 12);
1098
    add(MI::WQ+MI::WN+MI::WP+MI::BN, 12);
1099
    add(MI::WQ+MI::WN+MI::WP+MI::BP, 12);
1100
    add(MI::WQ+MI::WN+MI::WP+MI::BQ, 100);
1101
    add(MI::WQ+MI::WN+MI::WP+MI::BR, 42);
1102
    add(MI::WQ+MI::WN+MI::WP*2, 10);
1103
    add(MI::WQ+MI::WP+MI::BB*2, 44);
1104
    add(MI::WQ+MI::WP+MI::BB+MI::BN, 36);
1105
    add(MI::WQ+MI::WP+MI::BB+MI::BP, 99);
1106
    add(MI::WQ+MI::WP+MI::BN*2, 92);
1107
    add(MI::WQ+MI::WP+MI::BN+MI::BP, 54);
1108
    add(MI::WQ+MI::WP+MI::BP*2, 35);
1109
    add(MI::WQ+MI::WP+MI::BQ+MI::BP, 100);
1110
    add(MI::WQ+MI::WP+MI::BR+MI::BB, 100);
1111
    add(MI::WQ+MI::WP+MI::BR+MI::BN, 100);
1112
    add(MI::WQ+MI::WP+MI::BR+MI::BP, 100);
1113
    add(MI::WQ+MI::WP+MI::BR*2, 100);
1114
    add(MI::WQ+MI::WP*2+MI::BB, 12);
1115
    add(MI::WQ+MI::WP*2+MI::BN, 12);
1116
    add(MI::WQ+MI::WP*2+MI::BP, 10);
1117
    add(MI::WQ+MI::WP*2+MI::BQ, 100);
1118
    add(MI::WQ+MI::WP*2+MI::BR, 42);
1119
    add(MI::WQ+MI::WP*3, 6);
1120
    add(MI::WQ*2+MI::WB*2, 6);
1121
    add(MI::WQ*2+MI::WB+MI::BB, 10);
1122
    add(MI::WQ*2+MI::WB+MI::BN, 10);
1123
    add(MI::WQ*2+MI::WB+MI::BP, 6);
1124
    add(MI::WQ*2+MI::WB+MI::BQ, 58);
1125
    add(MI::WQ*2+MI::WB+MI::BR, 52);
1126
    add(MI::WQ*2+MI::WB+MI::WN, 8);
1127
    add(MI::WQ*2+MI::WB+MI::WP, 6);
1128
    add(MI::WQ*2+MI::BB*2, 16);
1129
    add(MI::WQ*2+MI::BB+MI::BN, 16);
1130
    add(MI::WQ*2+MI::BB+MI::BP, 12);
1131
    add(MI::WQ*2+MI::BN*2, 14);
1132
    add(MI::WQ*2+MI::BN+MI::BP, 11);
1133
    add(MI::WQ*2+MI::BP*2, 6);
1134
    add(MI::WQ*2+MI::BQ+MI::BB, 100);
1135
    add(MI::WQ*2+MI::BQ+MI::BN, 100);
1136
    add(MI::WQ*2+MI::BQ+MI::BP, 79);
1137
    add(MI::WQ*2+MI::BQ*2, 87);
1138
    add(MI::WQ*2+MI::BQ+MI::BR, 100);
1139
    add(MI::WQ*2+MI::BR+MI::BB, 27);
1140
    add(MI::WQ*2+MI::BR+MI::BN, 28);
1141
    add(MI::WQ*2+MI::BR+MI::BP, 38);
1142
    add(MI::WQ*2+MI::BR*2, 36);
1143
    add(MI::WQ*2+MI::WN+MI::BB, 8);
1144
    add(MI::WQ*2+MI::WN+MI::BN, 10);
1145
    add(MI::WQ*2+MI::WN+MI::BP, 6);
1146
    add(MI::WQ*2+MI::WN+MI::BQ, 56);
1147
    add(MI::WQ*2+MI::WN+MI::BR, 48);
1148
    add(MI::WQ*2+MI::WN*2, 8);
1149
    add(MI::WQ*2+MI::WN+MI::WP, 6);
1150
    add(MI::WQ*2+MI::WP+MI::BB, 8);
1151
    add(MI::WQ*2+MI::WP+MI::BN, 10);
1152
    add(MI::WQ*2+MI::WP+MI::BP, 6);
1153
    add(MI::WQ*2+MI::WP+MI::BQ, 70);
1154
    add(MI::WQ*2+MI::WP+MI::BR, 48);
1155
    add(MI::WQ*2+MI::WP*2, 6);
1156
    add(MI::WQ*3+MI::WB, 6);
1157
    add(MI::WQ*3+MI::BB, 6);
1158
    add(MI::WQ*3+MI::BN, 8);
1159
    add(MI::WQ*3+MI::BP, 6);
1160
    add(MI::WQ*3+MI::BQ, 38);
1161
    add(MI::WQ*3+MI::BR, 40);
1162
    add(MI::WQ*3+MI::WN, 6);
1163
    add(MI::WQ*3+MI::WP, 6);
1164
    add(MI::WQ*4, 6);
1165
    add(MI::WQ*3+MI::WR, 6);
1166
    add(MI::WQ*2+MI::WR+MI::WB, 6);
1167
    add(MI::WQ*2+MI::WR+MI::BB, 8);
1168
    add(MI::WQ*2+MI::WR+MI::BN, 10);
1169
    add(MI::WQ*2+MI::WR+MI::BP, 6);
1170
    add(MI::WQ*2+MI::WR+MI::BQ, 56);
1171
    add(MI::WQ*2+MI::WR+MI::BR, 48);
1172
    add(MI::WQ*2+MI::WR+MI::WN, 8);
1173
    add(MI::WQ*2+MI::WR+MI::WP, 6);
1174
    add(MI::WQ*2+MI::WR*2, 6);
1175
    add(MI::WQ+MI::WR+MI::WB*2, 8);
1176
    add(MI::WQ+MI::WR+MI::WB+MI::BB, 10);
1177
    add(MI::WQ+MI::WR+MI::WB+MI::BN, 10);
1178
    add(MI::WQ+MI::WR+MI::WB+MI::BP, 6);
1179
    add(MI::WQ+MI::WR+MI::WB+MI::BQ, 98);
1180
    add(MI::WQ+MI::WR+MI::WB+MI::BR, 50);
1181
    add(MI::WQ+MI::WR+MI::WB+MI::WN, 8);
1182
    add(MI::WQ+MI::WR+MI::WB+MI::WP, 8);
1183
    add(MI::WQ+MI::WR+MI::BB*2, 24);
1184
    add(MI::WQ+MI::WR+MI::BB+MI::BN, 22);
1185
    add(MI::WQ+MI::WR+MI::BB+MI::BP, 28);
1186
    add(MI::WQ+MI::WR+MI::BN*2, 21);
1187
    add(MI::WQ+MI::WR+MI::BN+MI::BP, 26);
1188
    add(MI::WQ+MI::WR+MI::BP*2, 12);
1189
    add(MI::WQ+MI::WR+MI::BQ+MI::BB, 100);
1190
    add(MI::WQ+MI::WR+MI::BQ+MI::BN, 100);
1191
    add(MI::WQ+MI::WR+MI::BQ+MI::BP, 100);
1192
    add(MI::WQ+MI::WR+MI::BQ+MI::BR, 100);
1193
    add(MI::WQ+MI::WR+MI::BR+MI::BB, 42);
1194
    add(MI::WQ+MI::WR+MI::BR+MI::BN, 42);
1195
    add(MI::WQ+MI::WR+MI::BR+MI::BP, 44);
1196
    add(MI::WQ+MI::WR+MI::BR*2, 68);
1197
    add(MI::WQ+MI::WR+MI::WN+MI::BB, 8);
1198
    add(MI::WQ+MI::WR+MI::WN+MI::BN, 12);
1199
    add(MI::WQ+MI::WR+MI::WN+MI::BP, 7);
1200
    add(MI::WQ+MI::WR+MI::WN+MI::BQ, 100);
1201
    add(MI::WQ+MI::WR+MI::WN+MI::BR, 48);
1202
    add(MI::WQ+MI::WR+MI::WN*2, 8);
1203
    add(MI::WQ+MI::WR+MI::WN+MI::WP, 8);
1204
    add(MI::WQ+MI::WR+MI::WP+MI::BB, 8);
1205
    add(MI::WQ+MI::WR+MI::WP+MI::BN, 10);
1206
    add(MI::WQ+MI::WR+MI::WP+MI::BP, 7);
1207
    add(MI::WQ+MI::WR+MI::WP+MI::BQ, 100);
1208
    add(MI::WQ+MI::WR+MI::WP+MI::BR, 60);
1209
    add(MI::WQ+MI::WR+MI::WP*2, 6);
1210
    add(MI::WQ+MI::WR*2+MI::WB, 8);
1211
    add(MI::WQ+MI::WR*2+MI::BB, 8);
1212
    add(MI::WQ+MI::WR*2+MI::BN, 10);
1213
    add(MI::WQ+MI::WR*2+MI::BP, 6);
1214
    add(MI::WQ+MI::WR*2+MI::BQ, 82);
1215
    add(MI::WQ+MI::WR*2+MI::BR, 46);
1216
    add(MI::WQ+MI::WR*2+MI::WN, 8);
1217
    add(MI::WQ+MI::WR*2+MI::WP, 6);
1218
    add(MI::WQ+MI::WR*3, 8);
1219
    add(MI::WR+MI::WB*3, 20);
1220
    add(MI::WR+MI::WB*2+MI::BB, 36);
1221
    add(MI::WR+MI::WB*2+MI::BN, 23);
1222
    add(MI::WR+MI::WB*2+MI::BP, 24);
1223
    add(MI::WR+MI::WB*2+MI::BQ, 88);
1224
    add(MI::WR+MI::WB*2+MI::BR, 71);
1225
    add(MI::WR+MI::WB*2+MI::WN, 14);
1226
    add(MI::WR+MI::WB*2+MI::WP, 10);
1227
    add(MI::WR+MI::WB+MI::BB*2, 100);
1228
    add(MI::WR+MI::WB+MI::BB+MI::BN, 100);
1229
    add(MI::WR+MI::WB+MI::BB+MI::BP, 76);
1230
    add(MI::WR+MI::WB+MI::BN*2, 100);
1231
    add(MI::WR+MI::WB+MI::BN+MI::BP, 90);
1232
    add(MI::WR+MI::WB+MI::BP*2, 47);
1233
    add(MI::WR+MI::WB+MI::BR+MI::BB, 33);
1234
    add(MI::WR+MI::WB+MI::BR+MI::BN, 40);
1235
    add(MI::WR+MI::WB+MI::BR+MI::BP, 94);
1236
    add(MI::WR+MI::WB+MI::WN+MI::BB, 26);
1237
    add(MI::WR+MI::WB+MI::WN+MI::BN, 24);
1238
    add(MI::WR+MI::WB+MI::WN+MI::BP, 31);
1239
    add(MI::WR+MI::WB+MI::WN+MI::BQ, 100);
1240
    add(MI::WR+MI::WB+MI::WN+MI::BR, 72);
1241
    add(MI::WR+MI::WB+MI::WN*2, 14);
1242
    add(MI::WR+MI::WB+MI::WN+MI::WP, 10);
1243
    add(MI::WR+MI::WB+MI::WP+MI::BB, 20);
1244
    add(MI::WR+MI::WB+MI::WP+MI::BN, 20);
1245
    add(MI::WR+MI::WB+MI::WP+MI::BP, 21);
1246
    add(MI::WR+MI::WB+MI::WP+MI::BQ, 100);
1247
    add(MI::WR+MI::WB+MI::WP+MI::BR, 100);
1248
    add(MI::WR+MI::WB+MI::WP*2, 8);
1249
    add(MI::WR+MI::WN+MI::BB*2, 100);
1250
    add(MI::WR+MI::WN+MI::BB+MI::BN, 100);
1251
    add(MI::WR+MI::WN+MI::BB+MI::BP, 100);
1252
    add(MI::WR+MI::WN+MI::BN*2, 100);
1253
    add(MI::WR+MI::WN+MI::BN+MI::BP, 100);
1254
    add(MI::WR+MI::WN+MI::BP*2, 48);
1255
    add(MI::WR+MI::WN+MI::BR+MI::BN, 41);
1256
    add(MI::WR+MI::WN+MI::BR+MI::BP, 72);
1257
    add(MI::WR+MI::WN*2+MI::BB, 24);
1258
    add(MI::WR+MI::WN*2+MI::BN, 25);
1259
    add(MI::WR+MI::WN*2+MI::BP, 30);
1260
    add(MI::WR+MI::WN*2+MI::BQ, 81);
1261
    add(MI::WR+MI::WN*2+MI::BR, 78);
1262
    add(MI::WR+MI::WN*3, 14);
1263
    add(MI::WR+MI::WN*2+MI::WP, 8);
1264
    add(MI::WR+MI::WN+MI::WP+MI::BB, 26);
1265
    add(MI::WR+MI::WN+MI::WP+MI::BN, 20);
1266
    add(MI::WR+MI::WN+MI::WP+MI::BP, 27);
1267
    add(MI::WR+MI::WN+MI::WP+MI::BQ, 100);
1268
    add(MI::WR+MI::WN+MI::WP+MI::BR, 100);
1269
    add(MI::WR+MI::WN+MI::WP*2, 10);
1270
    add(MI::WR+MI::WP+MI::BB*2, 79);
1271
    add(MI::WR+MI::WP+MI::BB+MI::BN, 100);
1272
    add(MI::WR+MI::WP+MI::BB+MI::BP, 100);
1273
    add(MI::WR+MI::WP+MI::BN*2, 84);
1274
    add(MI::WR+MI::WP+MI::BN+MI::BP, 100);
1275
    add(MI::WR+MI::WP+MI::BP*2, 31);
1276
    add(MI::WR+MI::WP+MI::BR+MI::BP, 73);
1277
    add(MI::WR+MI::WP*2+MI::BB, 36);
1278
    add(MI::WR+MI::WP*2+MI::BN, 36);
1279
    add(MI::WR+MI::WP*2+MI::BP, 26);
1280
    add(MI::WR+MI::WP*2+MI::BQ, 100);
1281
    add(MI::WR+MI::WP*2+MI::BR, 90);
1282
    add(MI::WR+MI::WP*3, 6);
1283
    add(MI::WR*2+MI::WB*2, 12);
1284
    add(MI::WR*2+MI::WB+MI::BB, 14);
1285
    add(MI::WR*2+MI::WB+MI::BN, 12);
1286
    add(MI::WR*2+MI::WB+MI::BP, 8);
1287
    add(MI::WR*2+MI::WB+MI::BQ, 100);
1288
    add(MI::WR*2+MI::WB+MI::BR, 62);
1289
    add(MI::WR*2+MI::WB+MI::WN, 12);
1290
    add(MI::WR*2+MI::WB+MI::WP, 8);
1291
    add(MI::WR*2+MI::BB*2, 74);
1292
    add(MI::WR*2+MI::BB+MI::BN, 51);
1293
    add(MI::WR*2+MI::BB+MI::BP, 52);
1294
    add(MI::WR*2+MI::BN*2, 66);
1295
    add(MI::WR*2+MI::BN+MI::BP, 50);
1296
    add(MI::WR*2+MI::BP*2, 50);
1297
    add(MI::WR*2+MI::BR+MI::BB, 100);
1298
    add(MI::WR*2+MI::BR+MI::BN, 100);
1299
    add(MI::WR*2+MI::BR+MI::BP, 100);
1300
    add(MI::WR*2+MI::BR*2, 35);
1301
    add(MI::WR*2+MI::WN+MI::BB, 14);
1302
    add(MI::WR*2+MI::WN+MI::BN, 14);
1303
    add(MI::WR*2+MI::WN+MI::BP, 18);
1304
    add(MI::WR*2+MI::WN+MI::BQ, 100);
1305
    add(MI::WR*2+MI::WN+MI::BR, 66);
1306
    add(MI::WR*2+MI::WN*2, 12);
1307
    add(MI::WR*2+MI::WN+MI::WP, 8);
1308
    add(MI::WR*2+MI::WP+MI::BB, 14);
1309
    add(MI::WR*2+MI::WP+MI::BN, 12);
1310
    add(MI::WR*2+MI::WP+MI::BP, 22);
1311
    add(MI::WR*2+MI::WP+MI::BQ, 100);
1312
    add(MI::WR*2+MI::WP+MI::BR, 56);
1313
    add(MI::WR*2+MI::WP*2, 6);
1314
    add(MI::WR*3+MI::WB, 10);
1315
    add(MI::WR*3+MI::BB, 10);
1316
    add(MI::WR*3+MI::BN, 12);
1317
    add(MI::WR*3+MI::BP, 6);
1318
    add(MI::WR*3+MI::BQ, 100);
1319
    add(MI::WR*3+MI::BR, 42);
1320
    add(MI::WR*3+MI::WN, 10);
1321
    add(MI::WR*3+MI::WP, 8);
1322
    add(MI::WR*4, 8);
1323
}