Line data Source code
1 : #include "kpk.hpp"
2 :
3 : #include "attack.hpp"
4 : #include "logging.hpp"
5 : #include "position.hpp"
6 :
7 : namespace KPK {
8 :
9 : #if !defined(WITH_SMALL_MEMORY)
10 : namespace {
11 : array1d<uint32_t,KPK::KPKmaxIndex / 32> KPKBitbase; // force 32bit uint
12 : FORCE_FINLINE unsigned KPKindex(Color us, Square bksq, Square wksq, Square psq) {
13 11 : return wksq | (bksq << 6) | (us << 12) | (SQFILE(psq) << 13) | ((6 - SQRANK(psq)) << 15);
14 : }
15 : } // namespace
16 :
17 33 : Square normalizeSquare(const Position& p, const Color strongSide, const Square sq) {
18 33 : assert(BB::countBit(p.pieces_const<P_wp>(strongSide)) == 1); // only for KPK !
19 33 : const Square nsq = SQFILE(BBTools::SquareFromBitBoard(p.pieces_const<P_wp>(strongSide))) >= File_e ? HFlip(sq) : sq;
20 33 : return strongSide == Co_White ? nsq : VFlip(nsq);
21 : }
22 :
23 4325376 : KPKPosition::KPKPosition(const unsigned idx) :
24 4325376 : ksq ({ static_cast<Square>(idx & 0x3F), static_cast<Square>((idx >> 6) & 0x3F) }),
25 4325376 : us (static_cast<Color>((idx >> 12) & 0x01)),
26 4325376 : psq (MakeSquare(File((idx >> 13) & 0x3), Rank(6 - ((idx >> 15) & 0x7)))){ // first init
27 4325376 : if (chebyshevDistance(ksq[Co_White], ksq[Co_Black]) <= 1 || ksq[Co_White] == psq || ksq[Co_Black] == psq ||
28 1848264 : (us == Co_White && (BBTools::mask[psq].pawnAttack[Co_White] & SquareToBitboard(ksq[Co_Black]))))
29 680504 : result = kpk_invalid;
30 3938792 : else if (us == Co_White && SQRANK(psq) == 6 && ksq[us] != psq + 8 &&
31 307604 : (chebyshevDistance(ksq[~us], psq + 8) > 1 || (BBTools::mask[ksq[us]].king & SquareToBitboard(psq + 8))))
32 280500 : result = kpk_win;
33 3364372 : else if (us == Co_Black && (!(BBTools::mask[ksq[us]].king & ~(BBTools::mask[ksq[~us]].king | BBTools::mask[psq].pawnAttack[~us])) ||
34 1848066 : (BBTools::mask[ksq[us]].king & SquareToBitboard(psq) & ~BBTools::mask[ksq[~us]].king)))
35 200354 : result = kpk_draw;
36 : else
37 3164018 : result = kpk_unknown; // done later
38 4325376 : }
39 :
40 11293326 : kpk_result KPKPosition::preCompute(const array1d<KPKPosition, KPKmaxIndex>& db) {
41 11293326 : return us == Co_White ? preCompute<Co_White>(db) : preCompute<Co_Black>(db);
42 : }
43 :
44 11293326 : template<Color Us> kpk_result KPKPosition::preCompute(const array1d<KPKPosition, KPKmaxIndex>& db) {
45 : constexpr Color Them = (Us == Co_White ? Co_Black : Co_White);
46 : constexpr kpk_result good = (Us == Co_White ? kpk_win : kpk_draw);
47 : constexpr kpk_result bad = (Us == Co_White ? kpk_draw : kpk_win);
48 11293326 : kpk_result r = kpk_invalid;
49 84620316 : BB::applyOn(BBTools::mask[ksq[us]].king, [&](const Square & k){ r |= (Us == Co_White ? db[KPKindex(Them, ksq[Them], k, psq)] : db[KPKindex(Them, k, ksq[Them], psq)]); });
50 : if (Us == Co_White) {
51 5472720 : if (SQRANK(psq) < 6) r |= db[KPKindex(Them, ksq[Them], ksq[Us], psq + 8)];
52 5472720 : if (SQRANK(psq) == 1 && psq + 8 != ksq[Us] && psq + 8 != ksq[Them]) r |= db[KPKindex(Them, ksq[Them], ksq[Us], psq + 8 + 8)];
53 : }
54 11293326 : return result = r & good ? good : r & kpk_unknown ? kpk_unknown : bad;
55 : }
56 :
57 11 : bool probe(Square wksq, const Square wpsq, const Square bksq, const Color us) {
58 11 : assert(isValidSquare(wksq));
59 11 : assert(isValidSquare(wpsq));
60 11 : assert(isValidSquare(bksq));
61 11 : assert(SQFILE(wpsq) <= 4);
62 : const unsigned idx = KPKindex(us, bksq, wksq, wpsq);
63 11 : assert(idx < KPKmaxIndex);
64 11 : return KPKBitbase[idx / 32] & (1 << (idx & 0x1F));
65 : }
66 : #endif
67 :
68 22 : void init() {
69 : #if !defined(WITH_SMALL_MEMORY)
70 22 : Logging::LogIt(Logging::logInfo) << "KPK init";
71 22 : Logging::LogIt(Logging::logInfo) << "KPK table size : " << KPKmaxIndex / 32 * sizeof(uint32_t) / 1024 << "Kb";
72 : array1d<KPKPosition, KPKmaxIndex> db;
73 : bool repeat = true;
74 4325398 : for (unsigned idx = 0; idx < KPKmaxIndex; ++idx) db[idx] = KPKPosition(idx); // init
75 : // loop until all the dababase is filled
76 : //int count = 0;
77 352 : while (repeat){
78 : repeat = false;
79 : //std::cout << count++ << std::endl;
80 64880970 : for (unsigned idx = 0; idx < KPKmaxIndex; ++idx){
81 126989434 : repeat |= (db[idx] == kpk_unknown && db[idx].preCompute(db) != kpk_unknown);
82 : }
83 : }
84 : // compress
85 4325398 : for (unsigned idx = 0; idx < KPKmaxIndex; ++idx) {
86 4325376 : if (db[idx] == kpk_win) { KPKBitbase[idx / 32] |= 1 << (idx & 0x1F); }
87 : }
88 : #endif
89 22 : }
90 :
91 : } // namespace KPK
|