internal static void init() { var db = new KPKPosition[MAX_INDEX]; uint idx, repeat = 1; // Initialize db with known win / draw positions for (idx = 0; idx < MAX_INDEX; ++idx) { db[idx] = new KPKPosition(idx); } // Iterate through the positions until none of the unknown positions can be // changed to either wins or draws (15 cycles needed). while (repeat != 0) { for (repeat = idx = 0; idx < MAX_INDEX; ++idx) { repeat |= ((db[idx] == Result.UNKNOWN && db[idx].classify(db) != Result.UNKNOWN)) ? 1u : 0; } } // Map 32 results into one KPKBitbase[] entry for (idx = 0; idx < MAX_INDEX; ++idx) { if (db[idx] == Result.WIN) { KPKBitbase[idx/32] |= (uint) (1 << (int) (idx & 0x1F)); } } }
internal Result classify(ColorT Us, KPKPosition[] db) { // White to move: If one move leads to a position classified as WIN, the result // of the current position is WIN. If all moves lead to positions classified // as DRAW, the current position is classified as DRAW, otherwise the current // position is classified as UNKNOWN. // // Black to move: If one move leads to a position classified as DRAW, the result // of the current position is DRAW. If all moves lead to positions classified // as WIN, the position is classified as WIN, otherwise the current position is // classified as UNKNOWN. var Them = (Us == Color.WHITE ? Color.BLACK : Color.WHITE); var Good = (Us == Color.WHITE ? Result.WIN : Result.DRAW); var Bad = (Us == Color.WHITE ? Result.DRAW : Result.WIN); var r = Result.INVALID; var b = Utils.StepAttacksBB[PieceType.KING, ksq[Us]]; while (b != 0) { r |= Us == Color.WHITE ? db[Bitbases.index(Them, ksq[Them], Utils.pop_lsb(ref b), psq)] : db[Bitbases.index(Them, Utils.pop_lsb(ref b), ksq[Them], psq)]; } if (Us == Color.WHITE) { if (Square.rank_of(psq) < Rank.RANK_7) // Single push { r |= db[Bitbases.index(Them, ksq[Them], ksq[Us], psq + Square.DELTA_N)]; } if (Square.rank_of(psq) == Rank.RANK_2 // Double push && psq + Square.DELTA_N != ksq[Us] && psq + Square.DELTA_N != ksq[Them]) { r |= db[Bitbases.index(Them, ksq[Them], ksq[Us], psq + Square.DELTA_N + Square.DELTA_N)]; } } return result = (r & Good) != 0 ? Good : (r & Result.UNKNOWN) != 0 ? Result.UNKNOWN : Bad; }
internal Result classify(KPKPosition[] db) { return us == Color.WHITE ? classify(Color.WHITE, db) : classify(Color.BLACK, db); }