internal static void init_kpk() { var db = new KPKPosition[IndexMax]; int idx, repeat = 1; // Initialize db with known win / draw positions for (idx = 0; idx < IndexMax; idx++) { db[idx].classify_leaf(idx); } // Iterate until all positions are classified (30 cycles needed) while (repeat != 0) { for (repeat = idx = 0; idx < IndexMax; idx++) { if (db[idx].res == ResultC.UNKNOWN && (db[idx].classify(db) != ResultC.UNKNOWN)) { repeat = 1; } } } // Map 32 position results into one KPKBitbase[] entry for (idx = 0; idx < IndexMax; idx++) { if (db[idx].res == ResultC.WIN) { KPKBitbase[idx / 32] |= (uint)(1 << (idx & 31)); } } }
public void Run(object arguments) { string[] args = (string[])arguments; Plug.Write(Utils.engine_info()); Plug.Write(Constants.endl); CheckInfoBroker.init(); EvalInfoBroker.init(); SwapListBroker.init(); MovesSearchedBroker.init(); PositionBroker.init(); StateInfoArrayBroker.init(); MListBroker.init(); LoopStackBroker.init(); MovePickerBroker.init(); StateInfoBroker.init(); Utils.init(); #if WINDOWS_RT #else Book.init(); #endif Position.init(); KPKPosition.init(); Endgame.init(); Search.init(); Evaluate.init(); Threads.init(); // .Net warmup sequence Plug.IsWarmup = true; Position pos = new Position(Uci.StartFEN, false, Threads.main_thread()); Stack <string> stack = Utils.CreateStack("go depth 7"); Uci.go(pos, stack); Threads.wait_for_search_finished(); Plug.IsWarmup = false; StringBuilder sb = new StringBuilder(); for (int i = 1; i < args.Length; i++) { sb.Append(args[i]).Append(" "); } Uci.uci_loop(sb.ToString()); Threads.exit(); }
/// KP vs K. This endgame is evaluated with the help of a bitbase. internal static Value Endgame_KPK(Color strongerSide, Position pos) { Color weakerSide = strongerSide ^ 1; Debug.Assert(pos.non_pawn_material(strongerSide) == ValueC.VALUE_ZERO); Debug.Assert(pos.non_pawn_material(weakerSide) == ValueC.VALUE_ZERO); Debug.Assert(pos.piece_count(strongerSide, PieceTypeC.PAWN) == 1); Debug.Assert(pos.piece_count(weakerSide, PieceTypeC.PAWN) == 0); Square wksq, bksq, wpsq; Color stm; if (strongerSide == ColorC.WHITE) { wksq = pos.king_square(ColorC.WHITE); bksq = pos.king_square(ColorC.BLACK); wpsq = pos.pieceList[ColorC.WHITE][PieceTypeC.PAWN][0]; stm = pos.sideToMove; } else { wksq = Utils.flip_S(pos.king_square(ColorC.BLACK)); bksq = Utils.flip_S(pos.king_square(ColorC.WHITE)); wpsq = Utils.flip_S(pos.pieceList[ColorC.BLACK][PieceTypeC.PAWN][0]); stm = Utils.flip_C(pos.sideToMove); } if (Utils.file_of(wpsq) >= FileC.FILE_E) { wksq = Utils.mirror(wksq); bksq = Utils.mirror(bksq); wpsq = Utils.mirror(wpsq); } if (KPKPosition.probe_kpk_bitbase(wksq, wpsq, bksq, stm) == 0) return ValueC.VALUE_DRAW; Value result = ValueC.VALUE_KNOWN_WIN + Constants.PawnValueEndgame + Utils.rank_of(wpsq); return strongerSide == pos.sideToMove ? result : -result; }
/// K and a pawn vs K and a pawn. This is done by removing the weakest side's /// pawn and probing the KP vs K bitbase: If the weakest side has a draw without /// the pawn, she probably has at least a draw with the pawn as well. The exception /// is when the stronger side's pawn is far advanced and not on a rook file; in /// this case it is often possible to win (e.g. 8/4k3/3p4/3P4/6K1/8/8/8 w - - 0 1). internal static ScaleFactor Endgame_KPKP(Color strongerSide, Position pos) { Color weakerSide = strongerSide ^ 1; Debug.Assert(pos.non_pawn_material(strongerSide) == ValueC.VALUE_ZERO); Debug.Assert(pos.non_pawn_material(weakerSide) == ValueC.VALUE_ZERO); Debug.Assert(pos.piece_count(ColorC.WHITE, PieceTypeC.PAWN) == 1); Debug.Assert(pos.piece_count(ColorC.BLACK, PieceTypeC.PAWN) == 1); Square wksq = pos.king_square(strongerSide); Square bksq = pos.king_square(weakerSide); Square wpsq = pos.pieceList[strongerSide][PieceTypeC.PAWN][0]; Color stm = pos.sideToMove; if (strongerSide == ColorC.BLACK) { wksq = Utils.flip_S(wksq); bksq = Utils.flip_S(bksq); wpsq = Utils.flip_S(wpsq); stm = Utils.flip_C(stm); } if (Utils.file_of(wpsq) >= FileC.FILE_E) { wksq = Utils.mirror(wksq); bksq = Utils.mirror(bksq); wpsq = Utils.mirror(wpsq); } // If the pawn has advanced to the fifth rank or further, and is not a // rook pawn, it's too dangerous to assume that it's at least a draw. if (Utils.rank_of(wpsq) >= RankC.RANK_5 && Utils.file_of(wpsq) != FileC.FILE_A) return ScaleFactorC.SCALE_FACTOR_NONE; // Probe the KPK bitbase with the weakest side's pawn removed. If it's a draw, // it's probably at least a draw even with the pawn. return (KPKPosition.probe_kpk_bitbase(wksq, wpsq, bksq, stm) != 0) ? ScaleFactorC.SCALE_FACTOR_NONE : ScaleFactorC.SCALE_FACTOR_DRAW; }
internal static void init() { Result[] db = new Result[IndexMax]; KPKPosition pos = new KPKPosition(); int idx, bit, repeat = 1; // Initialize table with known win / draw positions for (idx = 0; idx < IndexMax; idx++) { db[idx] = pos.classify_leaf(idx); } // Iterate until all positions are classified (30 cycles needed) while (repeat != 0) { for (repeat = idx = 0; idx < IndexMax; idx++) { if (db[idx] == ResultC.UNKNOWN && (db[idx] = pos.classify_index(idx, db)) != ResultC.UNKNOWN) { repeat = 1; } } } // Map 32 position results into one KPKBitbase[] entry UInt32 one = 1; for (idx = 0; idx < IndexMax / 32; idx++) { for (bit = 0; bit < 32; bit++) { if (db[32 * idx + bit] == ResultC.WIN) { KPKBitbase[idx] |= (one << bit); } } } }
internal static void init() { Result[] db = new Result[IndexMax]; KPKPosition pos = new KPKPosition(); int idx, bit, repeat = 1; // Initialize table with known win / draw positions for (idx = 0; idx < IndexMax; idx++) db[idx] = pos.classify_leaf(idx); // Iterate until all positions are classified (30 cycles needed) while (repeat != 0) for (repeat = idx = 0; idx < IndexMax; idx++) if (db[idx] == ResultC.UNKNOWN && (db[idx] = pos.classify_index(idx, db)) != ResultC.UNKNOWN) repeat = 1; // Map 32 position results into one KPKBitbase[] entry UInt32 one = 1; for (idx = 0; idx < IndexMax / 32; idx++) for (bit = 0; bit < 32; bit++) if (db[32 * idx + bit] == ResultC.WIN) KPKBitbase[idx] |= (one << bit); }
private int classify(int Us, KPKPosition[] db) { // White to Move: If one move leads to a position classified as RESULT_WIN, // the result of the current position is RESULT_WIN. If all moves lead to // positions classified as RESULT_DRAW, the current position is classified // RESULT_DRAW otherwise the current position is classified as RESULT_UNKNOWN. // // Black to Move: If one move leads to a position classified as RESULT_DRAW, // the result of the current position is RESULT_DRAW. If all moves lead to // positions classified as RESULT_WIN, the position is classified RESULT_WIN. // Otherwise, the current position is classified as RESULT_UNKNOWN. var r = ResultC.INVALID; var b = this.k_attacks(Us); while (b != 0) { r |= Us == ColorC.WHITE ? db[index(ColorC.BLACK, bksq, Utils.pop_lsb(ref b), psq)].res : db[index(ColorC.WHITE, Utils.pop_lsb(ref b), wksq, psq)].res; if (Us == ColorC.WHITE && ((r & ResultC.WIN) != 0)) { return res = ResultC.WIN; } if (Us == ColorC.BLACK && ((r & ResultC.DRAW) != 0)) { return res = ResultC.DRAW; } } if (Us == ColorC.WHITE && Utils.rank_of(this.psq) < RankC.RANK_7) { var s = this.psq + SquareC.DELTA_N; r |= db[index(ColorC.BLACK, bksq, wksq, s)].res; // Single push if (Utils.rank_of(s) == RankC.RANK_3 && s != this.wksq && s != this.bksq) { r |= db[index(ColorC.BLACK, bksq, wksq, s + SquareC.DELTA_N)].res; // Double push } if ((r & ResultC.WIN) != 0) { return res = ResultC.WIN; } } return res = (r & ResultC.UNKNOWN) != 0 ? ResultC.UNKNOWN : Us == ColorC.WHITE ? ResultC.DRAW : ResultC.WIN; }
Result classify(KPKPosition[] db) { return classify(stm, db); }