public KPKPosition(uint idx) { wksq = Square((idx >> 0) & 0x3F); bksq = Square((idx >> 6) & 0x3F); us = Color((idx >> 12) & 0x01); psq = GlobalMembersTypes.make_square(File((idx >> 13) & 0x3), Rank.RANK_7 - Rank((idx >> 15) & 0x7)); result = Result.UNKNOWN; // Check if two pieces are on the same square or if a king can be captured if (GlobalMembersBitboard.distance(wksq, bksq) <= 1 || wksq == psq || bksq == psq || (us == Color.WHITE && (StepAttacksBB[(int)PieceType.PAWN][(int)psq] & (int)bksq))) { result = Result.INVALID; } else if (us == Color.WHITE) { // Immediate win if a pawn can be promoted without getting captured if (GlobalMembersTypes.rank_of(psq) == Rank.RANK_7 && wksq != psq + Square.DELTA_N && (GlobalMembersBitboard.distance(bksq, psq + Square.DELTA_N) > 1 || (StepAttacksBB[(int)PieceType.KING][(int)wksq] & (psq + Square.DELTA_N)))) { result = Result.WIN; } } // Immediate draw if it is a stalemate or a king captures undefended pawn else if (!(StepAttacksBB[(int)PieceType.KING][(int)bksq] & ~(StepAttacksBB[(int)PieceType.KING][(int)wksq] | StepAttacksBB[(int)PieceType.PAWN][(int)psq])) || (StepAttacksBB[(int)PieceType.KING][(int)bksq] & (int)psq & ~StepAttacksBB[(int)PieceType.KING][(int)wksq])) { result = Result.DRAW; } }
public void init() { for (Square s = Square.SQ_A1; s <= Square.SQ_H8; ++s) { SquareBB[(int)s] = 1UL << s; BSFTable[GlobalMembersBitboard.bsf_index(SquareBB[(int)s])] = s; } for (uint long b = 1; b < 256; ++b) { MS1BTable[b] = GlobalMembersBitboard.more_than_one(b) ? MS1BTable[b - 1] : GlobalMembersBitboard.lsb(b); } for (File f = File.FILE_A; f <= File.FILE_H; ++f) { FileBB[(int)f] = f > ((int)File.FILE_A) != 0 ? FileBB[(int)f - 1] << 1 : FileABB; } for (Rank r = Rank.RANK_1; r <= Rank.RANK_8; ++r) { RankBB[(int)r] = r > ((int)Rank.RANK_1) != 0 ? RankBB[(int)r - 1] << 8 : Rank1BB; } for (File f = File.FILE_A; f <= File.FILE_H; ++f) { AdjacentFilesBB[(int)f] = (f > ((int)File.FILE_A) != 0 ? FileBB[(int)f - 1] : 0) | (f < ((int)File.FILE_H) != 0 ? FileBB[(int)f + 1] : 0); } for (Rank r = Rank.RANK_1; r < Rank.RANK_8; ++r) { InFrontBB[(int)Color.WHITE][(int)r] = ~(InFrontBB[(int)Color.BLACK][(int)r + 1] = InFrontBB[(int)Color.BLACK][(int)r] | RankBB[(int)r]); } for (Color c = Color.WHITE; c <= Color.BLACK; ++c) { for (Square s = Square.SQ_A1; s <= Square.SQ_H8; ++s) { ForwardBB[(int)c][(int)s] = InFrontBB[(int)c][(int)GlobalMembersTypes.rank_of(s)] & FileBB[(int)GlobalMembersTypes.file_of(s)]; PawnAttackSpan[(int)c][(int)s] = InFrontBB[(int)c][(int)GlobalMembersTypes.rank_of(s)] & AdjacentFilesBB[(int)GlobalMembersTypes.file_of(s)]; PassedPawnMask[(int)c][(int)s] = ForwardBB[(int)c][(int)s] | PawnAttackSpan[(int)c][(int)s]; } } for (Square s1 = Square.SQ_A1; s1 <= Square.SQ_H8; ++s1) { for (Square s2 = Square.SQ_A1; s2 <= Square.SQ_H8; ++s2) { if (s1 != s2) { SquareDistance[(int)s1, (int)s2] = Math.Max(GlobalMembersBitboard.distance <File>(s1, s2), GlobalMembersBitboard.distance <Rank>(s1, s2)); DistanceRingBB[(int)s1][SquareDistance[(int)s1, (int)s2] - 1] |= s2; } } } int[,] steps = { {, 0, 0, 0, 0, 0, 0, 0, 0 }, { 7, 9, 0, 0, 0, 0, 0, 0, 0 }, { 17, 15, 10, 6, -6, -10, -15, -17, 0 }, {, 0, 0, 0, 0, 0, 0, 0, 0 }, {, 0, 0, 0, 0, 0, 0, 0, 0 }, {, 0, 0, 0, 0, 0, 0, 0, 0 }, { 9, 7, -7, -9, 8, 1, -1, -8, 0 } };
/* * Stockfish, a UCI chess playing engine derived from Glaurung 2.1 * Copyright (C) 2004-2008 Tord Romstad (Glaurung author) * Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad * * Stockfish is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Stockfish is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ public static void t_main(int argc, string[] argv) { Console.Write(GlobalMembersMisc.engine_info()); Console.Write("\n"); GlobalMembersBitboard.init(GlobalMembersUcioption.Options); GlobalMembersBitboard.init(); Position.init(); Bitbases.init(); GlobalMembersBitboard.init(); GlobalMembersBitboard.init(); GlobalMembersBitboard.init(); GlobalMembersThread.Threads.init(); Tablebases.init(GlobalMembersUcioption.Options["SyzygyPath"]); GlobalMembersTt.TT.resize(GlobalMembersUcioption.Options["Hash"]); GlobalMembersUci.loop(argc, argv); GlobalMembersThread.Threads.exit(); }
internal static int probe_dtz_table(Position pos, int wdl, ref int success) { TBEntry ptr; ulong idx; int i; int res; int[] p = new int[DefineConstants.TBPIECES]; // Obtain the position's material signature key. ulong key = pos.material_key(); if (GlobalMembersTbcore.DTZ_table[0].key1 != key && GlobalMembersTbcore.DTZ_table[0].key2 != key) { for (i = 1; i < DefineConstants.DTZ_ENTRIES; i++) { if (GlobalMembersTbcore.DTZ_table[i].key1 == key) { break; } } if (i < DefineConstants.DTZ_ENTRIES) { DTZTableEntry table_entry = GlobalMembersTbcore.DTZ_table[i]; for (; i > 0; i--) { GlobalMembersTbcore.DTZ_table[i] = GlobalMembersTbcore.DTZ_table[i - 1]; } GlobalMembersTbcore.DTZ_table[0] = table_entry; } else { TBHashEntry[] ptr2 = GlobalMembersTbcore.TB_hash[key >> (64 - DefineConstants.TBHASHBITS)]; for (i = 0; i < DefineConstants.HSHMAX; i++) { if (ptr2[i].key == key) { break; } } if (i == DefineConstants.HSHMAX) { success = 0; return(0); } ptr = ptr2[i].ptr; string str = new string(new char[16]); int mirror = (ptr.key != key); GlobalMembersTbprobe.prt_str(pos, str, mirror); if (GlobalMembersTbcore.DTZ_table[DefineConstants.DTZ_ENTRIES - 1].entry != null) { GlobalMembersTbcore.free_dtz_entry(GlobalMembersTbcore.DTZ_table[DefineConstants.DTZ_ENTRIES - 1].entry); } for (i = DefineConstants.DTZ_ENTRIES - 1; i > 0; i--) { GlobalMembersTbcore.DTZ_table[i] = GlobalMembersTbcore.DTZ_table[i - 1]; } GlobalMembersTbcore.load_dtz_table(ref str, GlobalMembersTbprobe.calc_key(pos, mirror), GlobalMembersTbprobe.calc_key(pos, mirror == 0)); } } ptr = GlobalMembersTbcore.DTZ_table[0].entry; if (ptr == null) { success = 0; return(0); } int bside; int mirror; int cmirror; if (ptr.symmetric == 0) { if (key != ptr.key) { cmirror = 8; mirror = 0x38; bside = (pos.side_to_move() == Color.WHITE); } else { cmirror = mirror = 0; bside = !(pos.side_to_move() == Color.WHITE); } } else { cmirror = (int)pos.side_to_move() == ((int)Color.WHITE) != 0 ? 0 : 8; mirror = (int)pos.side_to_move() == ((int)Color.WHITE) != 0 ? 0 : 0x38; bside = 0; } if (ptr.has_pawns == 0) { DTZEntry_piece entry = (DTZEntry_piece)ptr; if ((entry.flags & 1) != bside && entry.symmetric == 0) { success = -1; return(0); } byte[] pc = entry.pieces; for (i = 0; i < entry.num;) { uint GlobalMembersBitboard.long bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3), (PieceType)(pc[i] & 0x07)); do { p[i++] = (int)GlobalMembersBitboard.pop_lsb(ref bb); } while (bb); } idx = GlobalMembersTbcore.encode_piece((TBEntry_piece)entry, entry.norm, p, entry.factor); res = GlobalMembersTbcore.decompress_pairs(entry.precomp, idx); if ((entry.flags & 2) != 0) { res = entry.map[entry.map_idx[GlobalMembersTbcore.wdl_to_map[wdl + 2]] + res]; } if (!(entry.flags & GlobalMembersTbcore.pa_flags[wdl + 2]) || (wdl & 1)) { res *= 2; } } else { DTZEntry_pawn entry = (DTZEntry_pawn)ptr; int k = entry.file[0].pieces[0] ^ cmirror; uint GlobalMembersBitboard.long bb = pos.pieces((Color)(k >> 3), (PieceType)(k & 0x07)); i = 0; do { p[i++] = (int)GlobalMembersBitboard.pop_lsb(ref bb) ^ mirror; } while (bb); int f = GlobalMembersTbcore.pawn_file((TBEntry_pawn)entry, p); if ((entry.flags[f] & 1) != bside) { success = -1; return(0); } byte[] pc = entry.file[f].pieces; for (; i < entry.num;) { bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3), (PieceType)(pc[i] & 0x07)); do { p[i++] = (int)GlobalMembersBitboard.pop_lsb(ref bb) ^ mirror; } while (bb); } idx = GlobalMembersTbcore.encode_pawn((TBEntry_pawn)entry, entry.file[f].norm, p, entry.file[f].factor); res = GlobalMembersTbcore.decompress_pairs(entry.file[f].precomp, idx); if ((entry.flags[f] & 2) != 0) { res = entry.map[entry.map_idx[f, GlobalMembersTbcore.wdl_to_map[wdl + 2]] + res]; } if (!(entry.flags[f] & GlobalMembersTbcore.pa_flags[wdl + 2]) || (wdl & 1)) { res *= 2; } } return(res); }
// probe_wdl_table and probe_dtz_table require similar adaptations. internal static int probe_wdl_table(Position pos, ref int success) { TBEntry ptr; TBHashEntry[] ptr2; ulong idx; ulong key; int i; byte res; int[] p = new int[DefineConstants.TBPIECES]; // Obtain the position's material signature key. key = pos.material_key(); // Test for KvK. if (key == (Zobrist.psq[(int)Color.WHITE][(int)PieceType.KING][0] ^ Zobrist.psq[(int)Color.BLACK][(int)PieceType.KING][0])) { return(0); } ptr2 = GlobalMembersTbcore.TB_hash[key >> (64 - DefineConstants.TBHASHBITS)]; for (i = 0; i < DefineConstants.HSHMAX; i++) { if (ptr2[i].key == key) { break; } } if (i == DefineConstants.HSHMAX) { success = 0; return(0); } ptr = ptr2[i].ptr; if (ptr.ready == 0) { LOCK(GlobalMembersTbcore.TB_mutex); if (ptr.ready == 0) { string str = new string(new char[16]); GlobalMembersTbprobe.prt_str(pos, str, ptr.key != key); if (GlobalMembersTbcore.init_table_wdl(ptr, ref str) == 0) { ptr2[i].key = 0UL; success = 0; UNLOCK(GlobalMembersTbcore.TB_mutex); return(0); } // Memory barrier to ensure ptr->ready = 1 is not reordered. #if _MSC_VER _ReadWriteBarrier(); #else __asm__ __volatile__ = new __asm__("" global::: "memory"); #endif ptr.ready = 1; } UNLOCK(GlobalMembersTbcore.TB_mutex); } int bside; int mirror; int cmirror; if (ptr.symmetric == 0) { if (key != ptr.key) { cmirror = 8; mirror = 0x38; bside = (pos.side_to_move() == Color.WHITE); } else { cmirror = mirror = 0; bside = !(pos.side_to_move() == Color.WHITE); } } else { cmirror = (int)pos.side_to_move() == ((int)Color.WHITE) != 0 ? 0 : 8; mirror = (int)pos.side_to_move() == ((int)Color.WHITE) != 0 ? 0 : 0x38; bside = 0; } // p[i] is to contain the square 0-63 (A1-H8) for a piece of type // pc[i] ^ cmirror, where 1 = white pawn, ..., 14 = black king. // Pieces of the same type are guaranteed to be consecutive. if (ptr.has_pawns == 0) { TBEntry_piece entry = (TBEntry_piece)ptr; byte[] pc = entry.pieces[bside]; for (i = 0; i < entry.num;) { uint GlobalMembersBitboard.long bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3), (PieceType)(pc[i] & 0x07)); do { p[i++] = (int)GlobalMembersBitboard.pop_lsb(ref bb); } while (bb); } idx = GlobalMembersTbcore.encode_piece(entry, entry.norm[bside], p, entry.factor[bside]); res = GlobalMembersTbcore.decompress_pairs(entry.precomp[bside], idx); } else { TBEntry_pawn entry = (TBEntry_pawn)ptr; int k = entry.file[0].pieces[0, 0] ^ cmirror; uint GlobalMembersBitboard.long bb = pos.pieces((Color)(k >> 3), (PieceType)(k & 0x07)); i = 0; do { p[i++] = (int)GlobalMembersBitboard.pop_lsb(ref bb) ^ mirror; } while (bb); int f = GlobalMembersTbcore.pawn_file(entry, p); byte[] pc = entry.file[f].pieces[bside]; for (; i < entry.num;) { bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3), (PieceType)(pc[i] & 0x07)); do { p[i++] = (int)GlobalMembersBitboard.pop_lsb(ref bb) ^ mirror; } while (bb); } idx = GlobalMembersTbcore.encode_pawn(entry, entry.file[f].norm[bside], p, entry.file[f].factor[bside]); res = GlobalMembersTbcore.decompress_pairs(entry.file[f].precomp[bside], idx); } return(((int)res) - 2); }