internal static void setup_pieces_pawn(TBEntry_pawn ptr, byte[] data, ulong[] tb_size, int f) { int i; int j; int order; int order2; j = 1 + (ptr.pawns[1] > 0); order = data[0] & 0x0f; order2 = ptr.pawns[1] != 0 ? (data[1] & 0x0f) : 0x0f; for (i = 0; i < ptr.num; i++) { ptr.file[f].pieces[0, i] = (byte)(data[i + j] & 0x0f); } GlobalMembersTbcore.set_norm_pawn(ptr, ptr.file[f].norm[0], ptr.file[f].pieces[0]); tb_size[0] = GlobalMembersTbcore.calc_factors_pawn(ptr.file[f].factor[0], ptr.num, order, order2, ptr.file[f].norm[0], f); order = data[0] >> 4; order2 = ptr.pawns[1] != 0 ? (data[1] >> 4) : 0x0f; for (i = 0; i < ptr.num; i++) { ptr.file[f].pieces[1, i] = (byte)(data[i + j] >> 4); } GlobalMembersTbcore.set_norm_pawn(ptr, ptr.file[f].norm[1], ptr.file[f].pieces[1]); tb_size[1] = GlobalMembersTbcore.calc_factors_pawn(ptr.file[f].factor[1], ptr.num, order, order2, ptr.file[f].norm[1], f); }
internal static void calc_symlen(PairsData d, int s, ref string tmp) { int s1; int s2; byte[] w = d.sympat + 3 * s; s2 = (w[2] << 4) | (w[1] >> 4); if (s2 == 0x0fff) { d.symlen[s] = 0; } else { s1 = ((w[1] & 0xf) << 8) | w[0]; if (!tmp[s1]) { GlobalMembersTbcore.calc_symlen(d, s1, ref tmp); } if (!tmp[s2]) { GlobalMembersTbcore.calc_symlen(d, s2, ref tmp); } d.symlen[s] = (byte)(d.symlen[s1] + d.symlen[s2] + 1); } tmp[s] = 1; }
internal static ulong calc_factors_piece(int[] factor, int num, int order, byte[] norm, byte enc_type) { int i; int k; int n; ulong f; //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method: // static int pivfac[] = { 31332, 28056, 462 }; n = 64 - norm[0]; f = 1; for (i = norm[0], k = 0; i < num || k == order; k++) { if (k == order) { factor[0] = (int)(f); f *= calc_factors_piece_pivfac[enc_type]; } else { factor[i] = (int)(f); f *= GlobalMembersTbcore.subfactor(norm[i], n); n -= norm[i]; i += norm[i]; } } return(f); }
//static ulong calc_key_from_pcs(ref int pcs, int mirror); internal static void free_wdl_entry(TBEntry entry) { GlobalMembersTbcore.unmap_file(ref entry.data, entry.mapping); if (entry.has_pawns == 0) { TBEntry_piece ptr = (TBEntry_piece)entry; //C++ TO C# CONVERTER TODO TASK: The memory management function 'free' has no equivalent in C#: free(ptr.precomp[0]); if (ptr.precomp[1] != null) { //C++ TO C# CONVERTER TODO TASK: The memory management function 'free' has no equivalent in C#: free(ptr.precomp[1]); } } else { TBEntry_pawn ptr = (TBEntry_pawn)entry; int f; for (f = 0; f < 4; f++) { //C++ TO C# CONVERTER TODO TASK: The memory management function 'free' has no equivalent in C#: free(ptr.file[f].precomp[0]); if (ptr.file[f].precomp[1] != null) { //C++ TO C# CONVERTER TODO TASK: The memory management function 'free' has no equivalent in C#: free(ptr.file[f].precomp[1]); } } } }
internal static void setup_pieces_piece_dtz(DTZEntry_piece ptr, byte[] data, ulong[] tb_size) { int i; int order; for (i = 0; i < ptr.num; i++) { ptr.pieces[i] = (byte)(data[i + 1] & 0x0f); } order = data[0] & 0x0f; GlobalMembersTbcore.set_norm_piece((TBEntry_piece)ptr, ptr.norm, ptr.pieces); tb_size[0] = GlobalMembersTbcore.calc_factors_piece(ptr.factor, ptr.num, order, ptr.norm, ptr.enc_type); }
internal static string map_file(string name, string suffix, ref ulong mapping) { FD fd = GlobalMembersTbcore.open_tb(name, suffix); if (fd == DefineConstants.FD_ERR) { return(null); } #if !_WIN32 stat statbuf = new stat(); fstat(fd, statbuf); mapping = statbuf.st_size; //C++ TO C# CONVERTER TODO TASK: C# does not have an equivalent for pointers to value types: //ORIGINAL LINE: sbyte *data = (sbyte *)mmap(null, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0); sbyte data = (string)mmap(null, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0); if (data == (string)(-1)) { Console.Write("Could not mmap() {0}.\n", name); Environment.Exit(1); } #else uint size_low; uint size_high; size_low = GetFileSize(fd, size_high); // *size = ((uint64)size_high) << 32 | ((uint64)size_low); System.IntPtr map = CreateFileMapping(fd, null, PAGE_READONLY, size_high, size_low, null); if (map == null) { Console.Write("CreateFileMapping() failed.\n"); Environment.Exit(1); } mapping = (ulong)map; //C++ TO C# CONVERTER TODO TASK: C# does not have an equivalent for pointers to value types: //ORIGINAL LINE: sbyte *data = (sbyte *)MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0); sbyte data = (string)MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0); if (data == null) { Console.Write("MapViewOfFile() failed, name = {0}{1}, error = {2:D}.\n", name, suffix, GetLastError()); Environment.Exit(1); } #endif GlobalMembersTbcore.close_tb(fd); return(data); }
internal static void setup_pieces_piece(TBEntry_piece ptr, byte[] data, ulong[] tb_size) { int i; int order; for (i = 0; i < ptr.num; i++) { ptr.pieces[0, i] = (byte)(data[i + 1] & 0x0f); } order = data[0] & 0x0f; GlobalMembersTbcore.set_norm_piece(ptr, ptr.norm[0], ptr.pieces[0]); tb_size[0] = GlobalMembersTbcore.calc_factors_piece(ptr.factor[0], ptr.num, order, ptr.norm[0], ptr.enc_type); for (i = 0; i < ptr.num; i++) { ptr.pieces[1, i] = (byte)(data[i + 1] >> 4); } order = data[0] >> 4; GlobalMembersTbcore.set_norm_piece(ptr, ptr.norm[1], ptr.pieces[1]); tb_size[1] = GlobalMembersTbcore.calc_factors_piece(ptr.factor[1], ptr.num, order, ptr.norm[1], ptr.enc_type); }
internal static ulong calc_factors_pawn(int[] factor, int num, int order, int order2, byte[] norm, int file) { int i; int k; int n; ulong f; i = norm[0]; if (order2 < 0x0f) { i += norm[i]; } n = 64 - i; f = 1; for (k = 0; i < num || k == order || k == order2; k++) { if (k == order) { factor[0] = (int)(f); f *= pfactor[norm[0] - 1, file]; } else if (k == order2) { factor[norm[0]] = (int)(f); f *= GlobalMembersTbcore.subfactor(norm[norm[0]], 48 - norm[0]); } else { factor[i] = (int)(f); f *= GlobalMembersTbcore.subfactor(norm[i], n); n -= norm[i]; i += norm[i]; } } return(f); }
internal static PairsData setup_pairs(byte[] data, ulong tb_size, ulong[] size, byte[][] next, ref byte flags, int wdl) { PairsData d; int i; flags = data[0]; if (data[0] & 0x80) { //C++ TO C# CONVERTER TODO TASK: The memory management function 'malloc' has no equivalent in C#: d = (PairsData)malloc(sizeof(PairsData)); d.idxbits = 0; if (wdl != 0) { d.min_len = data[1]; } else { d.min_len = 0; } next = data + 2; size[0] = size[1] = size[2] = 0; return(d); } int blocksize = data[1]; int idxbits = data[2]; int real_num_blocks = GlobalMembersTbcore.ReadUint32(data[4]); int num_blocks = real_num_blocks + (byte)(data[3]); int max_len = data[8]; int min_len = data[9]; int h = max_len - min_len + 1; int num_syms = GlobalMembersTbcore.ReadUshort(data[10 + 2 * h]); //C++ TO C# CONVERTER TODO TASK: The memory management function 'malloc' has no equivalent in C#: d = (PairsData)malloc(sizeof(PairsData) + (h - 1) * sizeof(ulong) + num_syms); d.blocksize = blocksize; d.idxbits = idxbits; d.offset = (ushort)(data[10]); d.symlen = ((byte)d) + sizeof(PairsData) + (h - 1) * sizeof(ulong); d.sympat = data[12 + 2 * h]; d.min_len = min_len; next = &data[12 + 2 * h + 3 * num_syms + (num_syms & 1)]; ulong num_indices = (tb_size + (1UL << idxbits) - 1) >> idxbits; size[0] = 6UL * num_indices; size[1] = 2UL * num_blocks; size[2] = (1UL << blocksize) * real_num_blocks; // char tmp[num_syms]; string tmp = new string(new char[4096]); for (i = 0; i < num_syms; i++) { tmp = StringFunctions.ChangeCharacter(tmp, i, 0); } for (i = 0; i < num_syms; i++) { if (!tmp[i]) { GlobalMembersTbcore.calc_symlen(d, i, ref tmp); } } d.@base[h - 1] = 0; for (i = h - 2; i >= 0; i--) { d.@base[i] = (d.@base[i + 1] + GlobalMembersTbcore.ReadUshort((byte)(d.offset + i)) - GlobalMembersTbcore.ReadUshort((byte)(d.offset + i + 1))) / 2; } for (i = 0; i < h; i++) { d.@base[i] <<= 64 - (min_len + i); } d.offset -= d.min_len; return(d); }
internal static void init_tb(ref string str) { FD fd = new FD(); TBEntry entry; int i; int j; int[] pcs = new int[16]; ulong key; ulong key2; int color; //C++ TO C# CONVERTER TODO TASK: Pointer arithmetic is detected on this variable, so pointers on this variable are left unchanged: sbyte *s; fd = GlobalMembersTbcore.open_tb(str, DefineConstants.WDLSUFFIX); if (fd == DefineConstants.FD_ERR) { return; } GlobalMembersTbcore.close_tb(fd); for (i = 0; i < 16; i++) { pcs[i] = 0; } color = 0; for (s = str; *s; s++) { switch (*s) { case 'P': pcs[DefineConstants.TB_PAWN | color]++; break; case 'N': pcs[DefineConstants.TB_KNIGHT | color]++; break; case 'B': pcs[DefineConstants.TB_BISHOP | color]++; break; case 'R': pcs[DefineConstants.TB_ROOK | color]++; break; case 'Q': pcs[DefineConstants.TB_QUEEN | color]++; break; case 'K': pcs[DefineConstants.TB_KING | color]++; break; case 'v': color = 0x08; break; } } for (i = 0; i < 8; i++) { if (pcs[i] != pcs[i + 8]) { break; } } key = GlobalMembersTbprobe.calc_key_from_pcs(pcs, 0); key2 = GlobalMembersTbprobe.calc_key_from_pcs(pcs, 1); if (pcs[DefineConstants.TB_PAWN] + pcs[DefineConstants.TB_PAWN | 8] == 0) { if (TBnum_piece == DefineConstants.TBMAX_PIECE) { Console.Write("TBMAX_PIECE limit too low!\n"); Environment.Exit(1); } entry = (TBEntry)TB_piece[TBnum_piece++]; } else { if (TBnum_pawn == DefineConstants.TBMAX_PAWN) { Console.Write("TBMAX_PAWN limit too low!\n"); Environment.Exit(1); } entry = (TBEntry)TB_pawn[TBnum_pawn++]; } entry.key = key; entry.ready = 0; entry.num = 0; for (i = 0; i < 16; i++) { entry.num += (byte)pcs[i]; } entry.symmetric = (key == key2); entry.has_pawns = (pcs[DefineConstants.TB_PAWN] + pcs[DefineConstants.TB_PAWN | 8] > 0); if (entry.num > GlobalMembersTbprobe.MaxCardinality) { GlobalMembersTbprobe.MaxCardinality = entry.num; } if (entry.has_pawns != 0) { TBEntry_pawn ptr = (TBEntry_pawn)entry; ptr.pawns[0] = (byte)pcs[DefineConstants.TB_PAWN]; ptr.pawns[1] = (byte)pcs[DefineConstants.TB_PAWN | 8]; if (pcs[DefineConstants.TB_PAWN | 8] > 0 && (pcs[DefineConstants.TB_PAWN] == 0 || pcs[DefineConstants.TB_PAWN | 8] < pcs[DefineConstants.TB_PAWN])) { ptr.pawns[0] = (byte)pcs[DefineConstants.TB_PAWN | 8]; ptr.pawns[1] = (byte)pcs[DefineConstants.TB_PAWN]; } } else { TBEntry_piece ptr = (TBEntry_piece)entry; for (i = 0, j = 0; i < 16; i++) { if (pcs[i] == 1) { j++; } } if (j >= 3) { ptr.enc_type = 0; } else if (j == 2) { ptr.enc_type = 2; } else // only for suicide { j = 16; for (i = 0; i < 16; i++) { if (pcs[i] < j && pcs[i] > 1) { j = pcs[i]; } ptr.enc_type = (byte)(1 + j); } } } GlobalMembersTbcore.add_to_hash(entry, key); if (key2 != key) { GlobalMembersTbcore.add_to_hash(entry, key2); } }
internal static int init_table_dtz(TBEntry entry) { byte[] data = (byte)entry.data; //C++ TO C# CONVERTER TODO TASK: C# does not have an equivalent for pointers to value types: //ORIGINAL LINE: byte *next; byte next; int f; int s; ulong[] tb_size = new ulong[4]; ulong[] size = new ulong[4 * 3]; if (!data) { return(0); } if (data[0] != DTZ_MAGIC[0] || data[1] != DTZ_MAGIC[1] || data[2] != DTZ_MAGIC[2] || data[3] != DTZ_MAGIC[3]) { Console.Write("Corrupted table.\n"); return(0); } int files = (data[4] & 0x02) != 0 ? 4 : 1; data += 5; if (entry.has_pawns == 0) { DTZEntry_piece ptr = (DTZEntry_piece)entry; GlobalMembersTbcore.setup_pieces_piece_dtz(ptr, data, tb_size[0]); data += ptr.num + 1; data += ((ushort)data) & 0x01; ptr.precomp = GlobalMembersTbcore.setup_pairs(data, tb_size[0], size[0], next, ref (ptr.flags), 0); data = next; ptr.map = data; if ((ptr.flags & 2) != 0) { int i; for (i = 0; i < 4; i++) { ptr.map_idx[i] = (ushort)(data + 1 - ptr.map); data += 1 + data[0]; } data += ((ushort)data) & 0x01; } ptr.precomp.indextable = (string)data; data += size[0]; ptr.precomp.sizetable = (ushort)data; data += size[1]; data = (byte)((((ushort)data) + 0x3f) & ~0x3f); ptr.precomp.data = data; data += size[2]; } else { DTZEntry_pawn ptr = (DTZEntry_pawn)entry; s = 1 + (ptr.pawns[1] > 0); for (f = 0; f < 4; f++) { GlobalMembersTbcore.setup_pieces_pawn_dtz(ptr, data, tb_size[f], f); data += ptr.num + s; } data += ((ushort)data) & 0x01; for (f = 0; f < files; f++) { ptr.file[f].precomp = GlobalMembersTbcore.setup_pairs(data, tb_size[f], size[3 * f], next, ref (ptr.flags[f]), 0); data = next; } ptr.map = data; for (f = 0; f < files; f++) { if ((ptr.flags[f] & 2) != 0) { int i; for (i = 0; i < 4; i++) { ptr.map_idx[f, i] = (ushort)(data + 1 - ptr.map); data += 1 + data[0]; } } } data += ((ushort)data) & 0x01; for (f = 0; f < files; f++) { ptr.file[f].precomp.indextable = (string)data; data += size[3 * f]; } for (f = 0; f < files; f++) { ptr.file[f].precomp.sizetable = (ushort)data; data += size[3 * f + 1]; } for (f = 0; f < files; f++) { data = (byte)((((ushort)data) + 0x3f) & ~0x3f); ptr.file[f].precomp.data = data; data += size[3 * f + 2]; } } return(1); }
internal static int init_table_wdl(TBEntry entry, ref string str) { //C++ TO C# CONVERTER TODO TASK: C# does not have an equivalent for pointers to value types: //ORIGINAL LINE: byte *next; byte next; int f; int s; ulong[] tb_size = new ulong[8]; ulong[] size = new ulong[8 * 3]; byte flags; // first mmap the table into memory entry.data = GlobalMembersTbcore.map_file(str, DefineConstants.WDLSUFFIX, ref entry.mapping); if (entry.data == 0) { Console.Write("Could not find {0}" DefineConstants.WDLSUFFIX, str); return(0); } byte[] data = (byte)entry.data; if (data[0] != WDL_MAGIC[0] || data[1] != WDL_MAGIC[1] || data[2] != WDL_MAGIC[2] || data[3] != WDL_MAGIC[3]) { Console.Write("Corrupted table.\n"); GlobalMembersTbcore.unmap_file(ref entry.data, entry.mapping); entry.data = 0; return(0); } int split = data[4] & 0x01; int files = (data[4] & 0x02) != 0 ? 4 : 1; data += 5; if (entry.has_pawns == 0) { TBEntry_piece ptr = (TBEntry_piece)entry; GlobalMembersTbcore.setup_pieces_piece(ptr, data, tb_size[0]); data += ptr.num + 1; data += ((ushort)data) & 0x01; ptr.precomp[0] = GlobalMembersTbcore.setup_pairs(data, tb_size[0], size[0], next, ref flags, 1); data = next; if (split != 0) { ptr.precomp[1] = GlobalMembersTbcore.setup_pairs(data, tb_size[1], size[3], next, ref flags, 1); data = next; } else { ptr.precomp[1] = null; } ptr.precomp[0].indextable = (string)data; data += size[0]; if (split != 0) { ptr.precomp[1].indextable = (string)data; data += size[3]; } ptr.precomp[0].sizetable = (ushort)data; data += size[1]; if (split != 0) { ptr.precomp[1].sizetable = (ushort)data; data += size[4]; } data = (byte)((((ushort)data) + 0x3f) & ~0x3f); ptr.precomp[0].data = data; data += size[2]; if (split != 0) { data = (byte)((((ushort)data) + 0x3f) & ~0x3f); ptr.precomp[1].data = data; } } else { TBEntry_pawn ptr = (TBEntry_pawn)entry; s = 1 + (ptr.pawns[1] > 0); for (f = 0; f < 4; f++) { GlobalMembersTbcore.setup_pieces_pawn((TBEntry_pawn)ptr, data, tb_size[2 * f], f); data += ptr.num + s; } data += ((ushort)data) & 0x01; for (f = 0; f < files; f++) { ptr.file[f].precomp[0] = GlobalMembersTbcore.setup_pairs(data, tb_size[2 * f], size[6 * f], next, ref flags, 1); data = next; if (split != 0) { ptr.file[f].precomp[1] = GlobalMembersTbcore.setup_pairs(data, tb_size[2 * f + 1], size[6 * f + 3], next, ref flags, 1); data = next; } else { ptr.file[f].precomp[1] = null; } } for (f = 0; f < files; f++) { ptr.file[f].precomp[0].indextable = (string)data; data += size[6 * f]; if (split != 0) { ptr.file[f].precomp[1].indextable = (string)data; data += size[6 * f + 3]; } } for (f = 0; f < files; f++) { ptr.file[f].precomp[0].sizetable = (ushort)data; data += size[6 * f + 1]; if (split != 0) { ptr.file[f].precomp[1].sizetable = (ushort)data; data += size[6 * f + 4]; } } for (f = 0; f < files; f++) { data = (byte)((((ushort)data) + 0x3f) & ~0x3f); ptr.file[f].precomp[0].data = data; data += size[6 * f + 2]; if (split != 0) { data = (byte)((((ushort)data) + 0x3f) & ~0x3f); ptr.file[f].precomp[1].data = data; data += size[6 * f + 5]; } } } return(1); }
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); }