Advertisement
Guest User

Untitled

a guest
Nov 15th, 2014
258
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 254.87 KB | None | 0 0
  1. #define W32_BUILD
  2. #undef W32_BUILD
  3.  
  4. #ifdef W32_BUILD
  5. #define NTDDI_VERSION 0x05010200
  6. #define _WIN32_WINNT 0x0501
  7. #endif
  8.  
  9. #ifndef W32_BUILD
  10. #define HNI
  11. #undef HNI
  12. #endif
  13.  
  14. #define CPU_TIMING
  15. #undef CPU_TIMING
  16.  
  17. #define TUNER
  18. #undef TUNER
  19.  
  20. #include <iostream>
  21. #include "setjmp.h"
  22. #include "windows.h"
  23. #ifdef TUNER
  24. #include "time.h"
  25.  
  26. //#define PGN
  27. #define RANDOM_SPHERICAL
  28. //#define WIN_PR
  29. //#define TIMING
  30. //#define RECORD_GAMES
  31.  
  32. #endif
  33.  
  34. #define EXPLAIN_EVAL
  35. #undef EXPLAIN_EVAL
  36.  
  37. #define LARGE_PAGES
  38. //#undef LARGE_PAGES
  39.  
  40. #define MP_NPS
  41. //#undef MP_NPS
  42.  
  43. #define TIME_TO_DEPTH
  44. //#undef TIME_TO_DEPTH
  45.  
  46. using namespace std;
  47.  
  48. typedef unsigned char uint8;
  49. typedef char sint8;
  50. typedef unsigned short uint16;
  51. typedef short sint16;
  52. typedef unsigned int uint32;
  53. typedef int sint32;
  54. typedef unsigned long long uint64;
  55. typedef long long sint64;
  56.  
  57. #define Convert(x,type) ((type)(x))
  58.  
  59. #define Abs(x) ((x) > 0 ? (x) : (-(x)))
  60. #define Sgn(x) ((x) == 0 ? 0 : ((x) > 0 ? 1 : (-1)))
  61. #define Min(x,y) ((x) < (y) ? (x) : (y))
  62. #define Max(x,y) ((x) > (y) ? (x) : (y))
  63. #define Sqr(x) ((x) * (x))
  64. #define T(x) ((x) != 0)
  65. #define F(x) ((x) == 0)
  66. #define Even(x) F((x) & 1)
  67. #define Odd(x) T((x) & 1)
  68. #define Combine(x,y) ((x) | ((y) << 16))
  69. #define Compose(x,y) ((x) + ((y) << 16))
  70. #define Compose16(x,y) Compose((x)/16,(y)/16)
  71. #define Compose64(x,y) Compose((x)/64,(y)/64)
  72. #define Compose256(x,y) Compose((x)/256,(y)/256)
  73. #define Opening(x) Convert((x) & 0xFFFF,sint16)
  74. #define Endgame(x) ((((x) >> 15) & 1) + Convert((x) >> 16,sint16))
  75.  
  76. #define File(x) ((x) & 7)
  77. #define Rank(x) ((x) >> 3)
  78. #define CRank(me,x) ((me) ? (7 - Rank(x)) : Rank(x))
  79. #define NDiag(x) (7 - File(x) + Rank(x))
  80. #define SDiag(x) (File(x) + Rank(x))
  81. #define Dist(x,y) Max(Abs(Rank(x)-Rank(y)),Abs(File(x)-File(y)))
  82. #define VarC(var,me) ((me) ? (var##_b) : (var##_w))
  83. #define PVarC(prefix,var,me) ((me) ? (prefix##.##var##_b) : (prefix##.##var##_w))
  84.  
  85. #define Bit(x) (Convert(1,uint64) << (x))
  86. #ifndef HNI
  87. #define Cut(x) (x &= (x) - 1)
  88. #else
  89. #define Cut(x) (x = _blsr_u64(x))
  90. #endif
  91. #define Multiple(x) T((x) & ((x) - 1))
  92. #define Single(x) F((x) & ((x) - 1))
  93. #define Add(x,b) (x |= Bit(b))
  94.  
  95. #define From(move) (((move) >> 6) & 0x3f)
  96. #define To(move) ((move) & 0x3f)
  97. #define SetScore(move,score) ((move) = (((move) & 0xFFFF) | ((score) << 16)))
  98. #define BitFrom(move) Bit(From(move))
  99. #define BitTo(move) Bit(To(move))
  100. #define MakeMove(from,to) ((from) << 6) | (to))
  101. #define MakeMoveF(from,to,flags) ((from) << 6) | (to) | (flags))
  102. #define MakeMoveFS(from,to,flags,score) ((from) << 6) | (to) | (flags) | (score))
  103. #define PieceAtOrigin(move) Square(From(move))
  104. #define Target(move) Square(To(move))
  105.  
  106. #define Empty Convert(0,uint64)
  107. #define Filled (~Empty)
  108. #define Interior Convert(0x007E7E7E7E7E7E00,uint64)
  109. #define Boundary (~Interior)
  110. #define WhiteArea Convert(0x00000000FFFFFFFF,uint64)
  111. #define BlackArea (~WhiteArea)
  112. #define LightArea Convert(0x55AA55AA55AA55AA,uint64)
  113. #define DarkArea (~LightArea)
  114. #define FileA Convert(0x0101010101010101,uint64)
  115. #define Line0 Convert(0x00000000000000FF,uint64)
  116.  
  117. #define High32(x) ((x) >> 32)
  118. #define Low32(x) Convert(x,uint32)
  119.  
  120. #define White 0
  121. #define Black 1
  122. #define WhitePawn 2
  123. #define BlackPawn 3
  124. #define WhiteKnight 4
  125. #define BlackKnight 5
  126. #define WhiteLight 6
  127. #define BlackLight 7
  128. #define WhiteDark 8
  129. #define BlackDark 9
  130. #define WhiteRook 10
  131. #define BlackRook 11
  132. #define WhiteQueen 12
  133. #define BlackQueen 13
  134. #define WhiteKing 14
  135. #define BlackKing 15
  136.  
  137. #define IsSlider(x) T(0x3FC0 & Bit(x))
  138.  
  139. #define CanCastle_OO 1
  140. #define CanCastle_oo 2
  141. #define CanCastle_OOO 4
  142. #define CanCastle_ooo 8
  143.  
  144. #define FlagCastling 0x1000
  145. #define FlagEP 0x2000
  146. #define FlagPKnight 0x4000
  147. #define FlagPLight 0x6000
  148. #define FlagPDark 0x8000
  149. #define FlagPRook 0xA000
  150. #define FlagPQueen 0xC000
  151.  
  152. #define IsPromotion(move) T((move) & 0xC000)
  153. #define IsCastling(move) T((move) & 0x1000)
  154. #define IsEP(move) (((move) & 0xF000) == 0x2000)
  155. #define Promotion(move,side) ((side) + (((move) & 0xF000) >> 12))
  156.  
  157. const uint8 UpdateCastling[64] = {
  158.     0xFF^CanCastle_OOO,0xFF,0xFF,0xFF,0xFF^(CanCastle_OO|CanCastle_OOO),0xFF,0xFF,0xFF^CanCastle_OO,
  159.     0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  160.     0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  161.     0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  162.     0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  163.     0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  164.     0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  165.     0xFF^CanCastle_ooo,0xFF,0xFF,0xFF,0xFF^(CanCastle_oo|CanCastle_ooo),0xFF,0xFF,0xFF^CanCastle_oo
  166. };
  167.  
  168. const uint64 BMagic[64] = {
  169.     0x0048610528020080, 0x00c4100212410004, 0x0004180181002010, 0x0004040188108502,
  170.     0x0012021008003040, 0x0002900420228000, 0x0080808410c00100, 0x000600410c500622,
  171.     0x00c0056084140184, 0x0080608816830050, 0x00a010050200b0c0, 0x0000510400800181,
  172.     0x0000431040064009, 0x0000008820890a06, 0x0050028488184008, 0x00214a0104068200,
  173.     0x004090100c080081, 0x000a002014012604, 0x0020402409002200, 0x008400c240128100,
  174.     0x0001000820084200, 0x0024c02201101144, 0x002401008088a800, 0x0003001045009000,
  175.     0x0084200040981549, 0x0001188120080100, 0x0048050048044300, 0x0008080000820012,
  176.     0x0001001181004003, 0x0090038000445000, 0x0010820800a21000, 0x0044010108210110,
  177.     0x0090241008204e30, 0x000c04204004c305, 0x0080804303300400, 0x00a0020080080080,
  178.     0x0000408020220200, 0x0000c08200010100, 0x0010008102022104, 0x0008148118008140,
  179.     0x0008080414809028, 0x0005031010004318, 0x0000603048001008, 0x0008012018000100,
  180.     0x0000202028802901, 0x004011004b049180, 0x0022240b42081400, 0x00c4840c00400020,
  181.     0x0084009219204000, 0x000080c802104000, 0x0002602201100282, 0x0002040821880020,
  182.     0x0002014008320080, 0x0002082078208004, 0x0009094800840082, 0x0020080200b1a010,
  183.     0x0003440407051000, 0x000000220e100440, 0x00480220a4041204, 0x00c1800011084800,
  184.     0x000008021020a200, 0x0000414128092100, 0x0000042002024200, 0x0002081204004200
  185. };
  186.  
  187. const uint64 RMagic[64] = {
  188.     0x00800011400080a6, 0x004000100120004e, 0x0080100008600082, 0x0080080016500080,
  189.     0x0080040008000280, 0x0080020005040080, 0x0080108046000100, 0x0080010000204080,
  190.     0x0010800424400082, 0x00004002c8201000, 0x000c802000100080, 0x00810010002100b8,
  191.     0x00ca808014000800, 0x0002002884900200, 0x0042002148041200, 0x00010000c200a100,
  192.     0x00008580004002a0, 0x0020004001403008, 0x0000820020411600, 0x0002120021401a00,
  193.     0x0024808044010800, 0x0022008100040080, 0x00004400094a8810, 0x0000020002814c21,
  194.     0x0011400280082080, 0x004a050e002080c0, 0x00101103002002c0, 0x0025020900201000,
  195.     0x0001001100042800, 0x0002008080022400, 0x000830440021081a, 0x0080004200010084,
  196.     0x00008000c9002104, 0x0090400081002900, 0x0080220082004010, 0x0001100101000820,
  197.     0x0000080011001500, 0x0010020080800400, 0x0034010224009048, 0x0002208412000841,
  198.     0x000040008020800c, 0x001000c460094000, 0x0020006101330040, 0x0000a30010010028,
  199.     0x0004080004008080, 0x0024000201004040, 0x0000300802440041, 0x00120400c08a0011,
  200.     0x0080006085004100, 0x0028600040100040, 0x00a0082110018080, 0x0010184200221200,
  201.     0x0040080005001100, 0x0004200440104801, 0x0080800900220080, 0x000a01140081c200,
  202.     0x0080044180110021, 0x0008804001001225, 0x00a00c4020010011, 0x00001000a0050009,
  203.     0x0011001800021025, 0x00c9000400620811, 0x0032009001080224, 0x001400810044086a
  204. };
  205.  
  206. const int BShift[64] = {
  207.     58, 59, 59, 59, 59, 59, 59, 58,
  208.     59, 59, 59, 59, 59, 59, 59, 59,
  209.     59, 59, 57, 57, 57, 57, 59, 59,
  210.     59, 59, 57, 55, 55, 57, 59, 59,
  211.     59, 59, 57, 55, 55, 57, 59, 59,
  212.     59, 59, 57, 57, 57, 57, 59, 59,
  213.     59, 59, 59, 59, 59, 59, 59, 59,
  214.     58, 59, 59, 59, 59, 59, 59, 58
  215. };
  216.  
  217. const int BOffset[64] = {
  218.     0, 64, 96, 128, 160, 192, 224, 256,
  219.     320, 352, 384, 416, 448, 480, 512, 544,
  220.     576, 608, 640, 768, 896, 1024, 1152, 1184,
  221.     1216, 1248, 1280, 1408, 1920, 2432, 2560, 2592,
  222.     2624, 2656, 2688, 2816, 3328, 3840, 3968, 4000,
  223.     4032, 4064, 4096, 4224, 4352, 4480, 4608, 4640,
  224.     4672, 4704, 4736, 4768, 4800, 4832, 4864, 4896,
  225.     4928, 4992, 5024, 5056, 5088, 5120, 5152, 5184
  226. };
  227.  
  228. const int RShift[64] = {
  229.     52, 53, 53, 53, 53, 53, 53, 52,
  230.     53, 54, 54, 54, 54, 54, 54, 53,
  231.     53, 54, 54, 54, 54, 54, 54, 53,
  232.     53, 54, 54, 54, 54, 54, 54, 53,
  233.     53, 54, 54, 54, 54, 54, 54, 53,
  234.     53, 54, 54, 54, 54, 54, 54, 53,
  235.     53, 54, 54, 54, 54, 54, 54, 53,
  236.     52, 53, 53, 53, 53, 53, 53, 52
  237. };
  238.  
  239. const int ROffset[64] = {
  240.     5248, 9344, 11392, 13440, 15488, 17536, 19584, 21632,
  241.     25728, 27776, 28800, 29824, 30848, 31872, 32896, 33920,
  242.     35968, 38016, 39040, 40064, 41088, 42112, 43136, 44160,
  243.     46208, 48256, 49280, 50304, 51328, 52352, 53376, 54400,
  244.     56448, 58496, 59520, 60544, 61568, 62592, 63616, 64640,
  245.     66688, 68736, 69760, 70784, 71808, 72832, 73856, 74880,
  246.     76928, 78976, 80000, 81024, 82048, 83072, 84096, 85120,
  247.     87168, 91264, 93312, 95360, 97408, 99456, 101504, 103552
  248. };
  249. uint64 * BOffsetPointer[64];
  250. uint64 * ROffsetPointer[64];
  251.  
  252. #ifndef HNI
  253. #define BishopAttacks(sq,occ) (*(BOffsetPointer[sq] + (((BMagicMask[sq] & (occ)) * BMagic[sq]) >> BShift[sq])))
  254. #define RookAttacks(sq,occ) (*(ROffsetPointer[sq] + (((RMagicMask[sq] & (occ)) * RMagic[sq]) >> RShift[sq])))
  255. #else
  256. #define BishopAttacks(sq,occ) (*(BOffsetPointer[sq] + _pext_u64(occ,BMagicMask[sq])))
  257. #define RookAttacks(sq,occ) (*(ROffsetPointer[sq] + _pext_u64(occ,RMagicMask[sq])))
  258. #endif
  259. #define QueenAttacks(sq,occ) (BishopAttacks(sq,occ) | RookAttacks(sq,occ))
  260.  
  261. #define MatWQ 1
  262. #define MatBQ 3
  263. #define MatWR (3 * 3)
  264. #define MatBR (3 * 3 * 3)
  265. #define MatWL (3 * 3 * 3 * 3)
  266. #define MatBL (3 * 3 * 3 * 3 * 2)
  267. #define MatWD (3 * 3 * 3 * 3 * 2 * 2)
  268. #define MatBD (3 * 3 * 3 * 3 * 2 * 2 * 2)
  269. #define MatWN (3 * 3 * 3 * 3 * 2 * 2 * 2 * 2)
  270. #define MatBN (3 * 3 * 3 * 3 * 2 * 2 * 2 * 2 * 3)
  271. #define MatWP (3 * 3 * 3 * 3 * 2 * 2 * 2 * 2 * 3 * 3)
  272. #define MatBP (3 * 3 * 3 * 3 * 2 * 2 * 2 * 2 * 3 * 3 * 9)
  273. #define TotalMat ((2*(MatWQ+MatBQ)+MatWL+MatBL+MatWD+MatBD+2*(MatWR+MatBR+MatWN+MatBN)+8*(MatWP+MatBP)) + 1)
  274. #define FlagUnusualMaterial (1 << 30)
  275.  
  276. const int MatCode[16] = {0,0,MatWP,MatBP,MatWN,MatBN,MatWL,MatBL,MatWD,MatBD,MatWR,MatBR,MatWQ,MatBQ,0,0};
  277. const uint64 File[8] = {FileA,FileA<<1,FileA<<2,FileA<<3,FileA<<4,FileA<<5,FileA<<6,FileA<<7};
  278. const uint64 Line[8] = {Line0,(Line0<<8),(Line0<<16),(Line0<<24),(Line0<<32),(Line0<<40),(Line0<<48),(Line0<<56)};
  279.  
  280. #define opp (1 ^ (me))
  281.  
  282. #define IPawn(me) (WhitePawn | (me))
  283. #define IKnight(me) (WhiteKnight | (me))
  284. #define ILight(me) (WhiteLight | (me))
  285. #define IDark(me) (WhiteDark | (me))
  286. #define IRook(me) (WhiteRook | (me))
  287. #define IQueen(me) (WhiteQueen | (me))
  288. #define IKing(me) (WhiteKing | (me))
  289.  
  290. #define BB(i) Board->bb[i]
  291. #define Pawn(me) (BB(WhitePawn | (me)))
  292. #define Knight(me) (BB(WhiteKnight | (me)))
  293. #define Bishop(me) (BB(WhiteLight | (me)) | BB(WhiteDark | (me)))
  294. #define Rook(me) (BB(WhiteRook | (me)))
  295. #define Queen(me) (BB(WhiteQueen | (me)))
  296. #define King(me) (BB(WhiteKing | (me)))
  297. #define Piece(me) (BB(me))
  298. #define NonPawn(me) (Piece(me) ^ Pawn(me))
  299. #define NonPawnKing(me) (NonPawn(me) ^ King(me))
  300. #define BSlider(me) (Bishop(me) | Queen(me))
  301. #define RSlider(me) (Rook(me) | Queen(me))
  302. #define Major(me) RSlider(me)
  303. #define Minor(me) (Knight(me) | Bishop(me))
  304. #define Slider(me) (BSlider(me) | RSlider(me))
  305. #define PieceAll (Piece(White) | Piece(Black))
  306. #define SliderAll (Slider(White) | Slider(Black))
  307. #define PawnAll (Pawn(White) | Pawn(Black))
  308. #define NonPawnKingAll (NonPawnKing(White) | NonPawnKing(Black))
  309. #define KingPos(me) (lsb(King(me)))
  310.  
  311. #define ShiftNW(target) (((target) & (~(File[0] | Line[7]))) << 7)
  312. #define ShiftNE(target) (((target) & (~(File[7] | Line[7]))) << 9)
  313. #define ShiftSE(target) (((target) & (~(File[7] | Line[0]))) >> 7)
  314. #define ShiftSW(target) (((target) & (~(File[0] | Line[0]))) >> 9)
  315. #define ShiftW(me,target) ((me) ? ShiftSW(target) : ShiftNW(target))
  316. #define ShiftE(me,target) ((me) ? ShiftSE(target) : ShiftNE(target))
  317. #define ShiftN(target) ((target) << 8)
  318. #define ShiftS(target) ((target) >> 8)
  319. #define Shift(me,target) ((me) ? ShiftS(target) : ShiftN(target))
  320. #define PushW(me) ((me) ? (-9) : (7))
  321. #define PushE(me) ((me) ? (-7) : (9))
  322. #define Push(me) ((me) ? (-8) : (8))
  323. #define Dir(me) ((me) ? (-1) : (1))
  324. #define IsGreater(me,x,y) ((me) ? ((x) < (y)) : ((x) > (y)))
  325.  
  326. #define Line(me,n) ((me) ? Line[7 - n] : Line[n])
  327. #define Square(sq) Board->square[sq]
  328. #define AddMove(from,to,flags,score) { *list = ((from) << 6) | (to) | (flags) | (score); list++; }
  329. #define AddCapture(from,to,flags) AddMove(from,to,flags,MvvLva[Square(from)][Square(to)])
  330. #define AddCaptureP(piece,from,to,flags) AddMove(from,to,flags,MvvLva[piece][Square(to)])
  331. #define AddHistoryP(piece,from,to,flags) AddMove(from,to,flags,HistoryP(piece,from,to))
  332. #define AddHistory(from,to) AddMove(from,to,0,History(from,to))
  333. #define AddDeltaP(piece,from,to,flags) AddMove(from,to,flags,Convert(DeltaScore(piece,from,to)+(sint16)0x4000,int) << 16)
  334. #define AddDelta(from,to) AddMove(from,to,0,Convert(Delta(from,to)+(sint16)0x4000,int) << 16)
  335. #define AddCDeltaP(piece,from,to,flags) {if (DeltaScore(piece,from,to) >= Current->margin) AddMove(from,to,flags,Convert(DeltaScore(piece,from,to)+(sint16)0x4000,int) << 16)}
  336. #define AddCDelta(from,to) {if (Delta(from,to) >= Current->margin) AddMove(from,to,0,Convert(Delta(from,to)+(sint16)0x4000,int) << 16)}
  337.  
  338. #define Check(me) T(Current->att[(me) ^ 1] & King(me))
  339. #define IsIllegal(me,move) ((T(Current->xray[opp] & Bit(From(move))) && F(Bit(To(move)) & FullLine[lsb(King(me))][From(move)])) \
  340.     || (IsEP(move) && T(Line[Rank(From(move))] & King(me)) && T(Line[Rank(From(move))] & Major(opp)) && \
  341.     T(RookAttacks(lsb(King(me)),PieceAll ^ Bit(From(move)) ^ Bit(Current->ep_square - Push(me))) & Major(opp))))
  342. #define IsRepetition(margin,move) ((margin) > 0 && Current->ply >= 2 && (Current-1)->move == ((To(move) << 6) | From(move)) && F(Square(To(move))) && F((move) & 0xF000))
  343.  
  344. #ifdef EXPLAIN_EVAL
  345. FILE * fexplain;
  346. int explain = 0, cpp_length;
  347. char GullCppFile[16384][256];
  348. #define IncV(var,x) (explain ? (me ? ((var -= (x)) && fprintf(fexplain,"(%d, %d): %s [Black]: %s",Opening(-(x)),Endgame(-(x)),__FUNCTION__,GullCppFile[Min(__LINE__-1,cpp_length)])) : ((var += (x)) && fprintf(fexplain,"(%d, %d): %s [White]: %s",Opening(x),Endgame(x),__FUNCTION__,GullCppFile[Min(__LINE__-1,cpp_length)]))) : (me ? (var -= (x)) : (var += (x))))
  349. #else
  350. #define IncV(var,x) (me ? (var -= (x)) : (var += (x)))
  351. #endif
  352. #define DecV(var,x) IncV(var,-(x))
  353.  
  354. #define KpkValue 300
  355. #define EvalValue 30000
  356. #define MateValue 32760
  357.  
  358. /*
  359. general move:
  360. 0 - 11: from & to
  361. 12 - 15: flags
  362. 16 - 23: history
  363. 24 - 25: spectial moves: killers, refutations...
  364. 26 - 30: MvvLva
  365. delta move:
  366. 0 - 11: from & to
  367. 12 - 15: flags
  368. 16 - 31: sint16 delta + (sint16)0x4000
  369. */
  370. const int MvvLvaVictim[16] = {0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 3};
  371. const int MvvLvaAttacker[16] = {0, 0, 5, 5, 4, 4, 3, 3, 3, 3, 2, 2, 1, 1, 6, 6};
  372. const int MvvLvaAttackerKB[16] = {0, 0, 9, 9, 7, 7, 5, 5, 5, 5, 3, 3, 1, 1, 11, 11};
  373. #define PawnCaptureMvvLva(attacker) (MvvLvaAttacker[attacker])
  374. #define MaxPawnCaptureMvvLva (MvvLvaAttacker[15]) // 6
  375. #define KnightCaptureMvvLva(attacker) (MaxPawnCaptureMvvLva + MvvLvaAttackerKB[attacker])
  376. #define MaxKnightCaptureMvvLva (MaxPawnCaptureMvvLva + MvvLvaAttackerKB[15]) // 17
  377. #define BishopCaptureMvvLva(attacker) (MaxPawnCaptureMvvLva + MvvLvaAttackerKB[attacker] + 1)
  378. #define MaxBishopCaptureMvvLva (MaxPawnCaptureMvvLva + MvvLvaAttackerKB[15] + 1) // 18
  379. #define RookCaptureMvvLva(attacker) (MaxBishopCaptureMvvLva + MvvLvaAttacker[attacker])
  380. #define MaxRookCaptureMvvLva (MaxBishopCaptureMvvLva + MvvLvaAttacker[15]) // 24
  381. #define QueenCaptureMvvLva(attacker) (MaxRookCaptureMvvLva + MvvLvaAttacker[attacker])
  382.  
  383. #define MvvLvaPromotion (MvvLva[WhiteQueen][BlackQueen])
  384. #define MvvLvaPromotionKnight (MvvLva[WhiteKnight][BlackKnight])
  385. #define MvvLvaPromotionCap(capture) (MvvLva[((capture) < WhiteRook) ? WhiteRook : ((capture) >= WhiteQueen ? WhiteKing : WhiteKnight)][BlackQueen])
  386. #define MvvLvaPromotionKnightCap(capture) (MvvLva[WhiteKing][capture])
  387. #define MvvLvaXray (MvvLva[WhiteQueen][WhitePawn])
  388. #define MvvLvaXrayCap(capture) (MvvLva[WhiteKing][capture])
  389. #define RefOneScore ((0xFF << 16) | (3 << 24))
  390. #define RefTwoScore ((0xFF << 16) | (2 << 24))
  391. #define KillerOneScore ((0xFF << 16) | (1 << 24))
  392. #define KillerTwoScore (0xFF << 16)
  393.  
  394. #define halt_check if ((Current - Data) >= 126) {evaluate(); return Current->score;} \
  395.     if (Current->ply >= 100) return 0; \
  396.     for (i = 4; i <= Current->ply; i+= 2) if (Stack[sp-i] == Current->key) return 0
  397. #define ExtFlag(ext) ((ext) << 16)
  398. #define Ext(flags) (((flags) >> 16) & 0xF)
  399. #define FlagHashCheck (1 << 20) // first 20 bits are reserved for the hash killer and extension
  400. #define FlagHaltCheck (1 << 21)
  401. #define FlagCallEvaluation (1 << 22)
  402. #define FlagDisableNull (1 << 23)
  403. #define FlagNeatSearch (FlagHashCheck | FlagHaltCheck | FlagCallEvaluation)
  404. #define FlagNoKillerUpdate (1 << 24)
  405. #define FlagReturnBestMove (1 << 25)
  406.  
  407. #define MSBZ(x) ((x) ? msb(x) : 63)
  408. #define LSBZ(x) ((x) ? lsb(x) : 0)
  409. #define NB(me, x) ((me) ? msb(x) : lsb(x))
  410. #define NBZ(me, x) ((me) ? MSBZ(x) : LSBZ(x))
  411.  
  412. typedef struct {
  413.     uint64 bb[16];
  414.     uint8 square[64];
  415. } GBoard;
  416. __declspec(align(64)) GBoard Board[1];
  417. uint64 Stack[2048];
  418. int sp, save_sp;
  419. uint64 nodes, check_node, check_node_smp;
  420. GBoard SaveBoard[1];
  421.  
  422. typedef struct {
  423.     uint64 key, pawn_key;
  424.     uint16 move;
  425.     uint8 turn, castle_flags, ply, ep_square, piece, capture;
  426.     uint8 square[64];
  427.     int pst, material;
  428. } GPosData;
  429. typedef struct {
  430.     uint64 key, pawn_key, eval_key, att[2], patt[2], passer, xray[2], pin[2], threat, mask;
  431.     uint8 turn, castle_flags, ply, ep_square, capture, gen_flags, piece, stage, mul, dummy;
  432.     sint16 score;
  433.     uint16 move, killer[3], ref[2];
  434.     int best;
  435.     int material, pst;
  436.     int margin, *start, *current;
  437.     int moves[230];
  438. } GData;
  439. __declspec(align(64)) GData Data[128];
  440. GData *Current = Data;
  441. #define FlagSort (1 << 0)
  442. #define FlagNoBcSort (1 << 1)
  443. GData SaveData[1];
  444.  
  445. enum {
  446.     stage_search, s_hash_move, s_good_cap, s_special, s_quiet, s_bad_cap, s_none,
  447.     stage_evasion, e_hash_move, e_ev, e_none,
  448.     stage_razoring, r_hash_move, r_cap, r_checks, r_none
  449. };
  450. #define StageNone ((1 << s_none) | (1 << e_none) | (1 << r_none))
  451.  
  452. typedef struct {
  453.     uint32 key;
  454.     uint16 date;
  455.     uint16 move;
  456.     sint16 low;
  457.     sint16 high;
  458.     uint16 flags;
  459.     uint8 low_depth;
  460.     uint8 high_depth;
  461. } GEntry;
  462. #ifndef TUNER
  463. #define initial_hash_size (1024 * 1024)
  464. #else
  465. #define initial_hash_size (64 * 1024)
  466. GEntry HashOne[initial_hash_size];
  467. GEntry HashTwo[initial_hash_size];
  468. #endif
  469. sint64 hash_size = initial_hash_size;
  470. uint64 hash_mask = (initial_hash_size - 4);
  471. GEntry * Hash;
  472.  
  473. typedef struct {
  474.     uint64 key;
  475.     sint16 shelter[2];
  476.     uint8 passer[2], draw[2];
  477.     int score;
  478. } GPawnEntry;
  479. #ifndef TUNER
  480. #define pawn_hash_size (1024 * 1024)
  481. __declspec(align(64)) GPawnEntry PawnHash[pawn_hash_size];
  482. #else
  483. #define pawn_hash_size (32 * 1024)
  484. __declspec(align(64)) GPawnEntry PawnHashOne[pawn_hash_size];
  485. __declspec(align(64)) GPawnEntry PawnHashTwo[pawn_hash_size];
  486. GPawnEntry * PawnHash = PawnHashOne;
  487. #endif
  488. #define pawn_hash_mask (pawn_hash_size - 1)
  489.  
  490. typedef struct {
  491.     uint32 key;
  492.     uint16 date;
  493.     uint16 move;
  494.     sint16 value;
  495.     sint16 exclusion;
  496.     uint8 depth;
  497.     uint8 ex_depth;
  498.     int knodes;
  499.     int ply;
  500. } GPVEntry;
  501. #ifndef TUNER
  502. #define pv_hash_size (1024 * 1024)
  503. #else
  504. #define pv_hash_size (16 * 1024)
  505. GPVEntry PVHashOne[pv_hash_size];
  506. GPVEntry PVHashTwo[pv_hash_size];
  507. #endif
  508. #define pv_cluster_size 4
  509. #define pv_hash_mask (pv_hash_size - pv_cluster_size)
  510. GPVEntry * PVHash = NULL;
  511.  
  512. int RootList[256];
  513.  
  514. #define prefetch(a,mode) _mm_prefetch(a,mode)
  515.  
  516. uint64 Forward[2][8];
  517. uint64 West[8];
  518. uint64 East[8];
  519. uint64 PIsolated[8];
  520. uint64 HLine[64];
  521. uint64 VLine[64];
  522. uint64 NDiag[64];
  523. uint64 SDiag[64];
  524. uint64 RMask[64];
  525. uint64 BMask[64];
  526. uint64 QMask[64];
  527. uint64 BMagicMask[64];
  528. uint64 RMagicMask[64];
  529. uint64 NAtt[64];
  530. uint64 SArea[64];
  531. uint64 DArea[64];
  532. uint64 NArea[64];
  533. uint64 BishopForward[2][64];
  534. uint64 PAtt[2][64];
  535. uint64 PMove[2][64];
  536. uint64 PWay[2][64];
  537. uint64 PSupport[2][64];
  538. uint64 Between[64][64];
  539. uint64 FullLine[64][64];
  540.  
  541. #define magic_size 107648
  542. uint64 * MagicAttacks;
  543. typedef struct {
  544.     sint16 score;
  545.     uint8 phase, flags;
  546.     uint8 mul[2], pieces[2];
  547. #ifdef TUNER
  548.     uint32 generation;
  549. #endif
  550. } GMaterial;
  551. GMaterial * Material;
  552. #define FlagSingleBishop_w (1 << 0)
  553. #define FlagSingleBishop_b (1 << 1)
  554. #define FlagCallEvalEndgame_w (1 << 2)
  555. #define FlagCallEvalEndgame_b (1 << 3)
  556.  
  557. #ifndef TUNER
  558. int Pst[16 * 64];
  559. #else
  560. int PstOne[16 * 64];
  561. int PstTwo[16 * 64];
  562. int * Pst = PstOne;
  563. #endif
  564. #define Pst(piece,sq) Pst[((piece) << 6) | (sq)]
  565. int MvvLva[16][16]; // [piece][capture]
  566. uint64 TurnKey;
  567. uint64 PieceKey[16][64];
  568. uint64 CastleKey[16];
  569. uint64 EPKey[8];
  570. uint16 date;
  571.  
  572. uint64 Kpk[2][64][64];
  573.  
  574. #ifndef TUNER
  575. sint16 History[16 * 64];
  576. #else
  577. sint16 HistoryOne[16 * 64];
  578. sint16 HistoryTwo[16 * 64];
  579. sint16 * History = HistoryOne;
  580. #endif
  581. #define HistoryScore(piece,from,to) History[((piece) << 6) | (to)]
  582. #define HistoryP(piece,from,to) ((Convert(HistoryScore(piece,from,to) & 0xFF00,int)/Convert(HistoryScore(piece,from,to) & 0x00FF,int)) << 16)
  583. #define History(from,to) HistoryP(Square(from),from,to)
  584. #define HistoryM(move) HistoryScore(Square(From(move)),From(move),To(move))
  585. #define HistoryInc(depth) Min(((depth) >> 1) * ((depth) >> 1), 64)
  586. #define HistoryGood(move) if ((HistoryM(move) & 0x00FF) >= 256 - HistoryInc(depth)) \
  587.     HistoryM(move) = ((HistoryM(move) & 0xFEFE) >> 1) + ((HistoryInc(depth) << 8) | HistoryInc(depth)); \
  588.     else HistoryM(move) += ((HistoryInc(depth) << 8) | HistoryInc(depth))
  589. #define HistoryBad(move) if ((HistoryM(move) & 0x00FF) >= 256 - HistoryInc(depth)) \
  590.     HistoryM(move) = ((HistoryM(move) & 0xFEFE) >> 1) + HistoryInc(depth); else HistoryM(move) += HistoryInc(depth)
  591.  
  592. #ifndef TUNER
  593. sint16 Delta[16 * 4096];
  594. #else
  595. sint16 DeltaOne[16 * 4096];
  596. sint16 DeltaTwo[16 * 4096];
  597. sint16 * Delta = DeltaOne;
  598. #endif
  599. #define DeltaScore(piece,from,to) Delta[((piece) << 12) | ((from) << 6) | (to)]
  600. #define Delta(from,to) DeltaScore(Square(from),from,to)
  601. #define DeltaM(move) Delta(From(move),To(move))
  602. #define UpdateDelta if (F(Current->capture) && T(Current->move) && F(Current->move & 0xE000) && Current > Data) { \
  603.     if (DeltaScore(Current->piece,From(Current->move),To(Current->move)) <= -Current->score - ((Current - 1)->score)) \
  604.     DeltaScore(Current->piece,From(Current->move),To(Current->move)) = -Current->score - ((Current - 1)->score); \
  605.     else DeltaScore(Current->piece,From(Current->move),To(Current->move))--; }
  606. #define DeltaMarginP(piece,from,to) (DeltaScore(piece,from,to) >= Current->margin)
  607. #define DeltaMargin(from,to) (Delta(from,to) >= Current->margin)
  608.  
  609. typedef struct {
  610.     uint16 ref[2];
  611.     uint16 check_ref[2];
  612. } GRef;
  613. #ifndef TUNER
  614. GRef Ref[16 * 64];
  615. #else
  616. GRef RefOne[16 * 64];
  617. GRef RefTwo[16 * 64];
  618. GRef * Ref = RefOne;
  619. #endif
  620. #define RefPointer(piece,from,to) Ref[((piece) << 6) | (to)]
  621. #define RefM(move) RefPointer(Square(To(move)),From(move),To(move))
  622. #define UpdateRef(ref_move) if (T(Current->move) && RefM(Current->move).ref[0] != (ref_move)) { \
  623.     RefM(Current->move).ref[1] = RefM(Current->move).ref[0]; RefM(Current->move).ref[0] = (ref_move); }
  624. #define UpdateCheckRef(ref_move) if (T(Current->move) && RefM(Current->move).check_ref[0] != (ref_move)) { \
  625.     RefM(Current->move).check_ref[1] = RefM(Current->move).check_ref[0]; RefM(Current->move).check_ref[0] = (ref_move); }
  626.  
  627. uint64 seed = 1;
  628. uint8 PieceFromChar[256];
  629. uint16 PV[128];
  630. char info_string[1024];
  631. char pv_string[1024];
  632. char score_string[16];
  633. char mstring[65536];
  634. int MultiPV[256];
  635. int pvp;
  636. int pv_length;
  637. int best_move, best_score;
  638. int TimeLimit1, TimeLimit2, Console, HardwarePopCnt;
  639. int DepthLimit, LastDepth, LastTime, LastValue, LastExactValue, PrevMove, InstCnt;
  640. sint64 LastSpeed;
  641. int PVN, Stop, Print, Input = 1, PVHashing = 1, Infinite, MoveTime, SearchMoves, SMPointer, Ponder, Searching, Previous;
  642. typedef struct {
  643.     int Bad, Change, Singular, Early, FailLow, FailHigh;
  644. } GSearchInfo;
  645. GSearchInfo CurrentSI[1], BaseSI[1];
  646. #ifdef CPU_TIMING
  647. int CpuTiming = 0, UciMaxDepth = 0, UciMaxKNodes = 0, UciBaseTime = 1000, UciIncTime = 5;
  648. int GlobalTime[2] = { 0, 0 };
  649. int GlobalInc[2] = { 0, 0 };
  650. int GlobalTurn = 0;
  651. #define CyclesPerMSec Convert(3400000, sint64)
  652. #endif
  653. int Aspiration = 1, LargePages = 1;
  654. #define TimeSingTwoMargin 20
  655. #define TimeSingOneMargin 30
  656. #define TimeNoPVSCOMargin 60
  657. #define TimeNoChangeMargin 70
  658. #define TimeRatio 120
  659. #define PonderRatio 120
  660. #define MovesTg 30
  661. #define InfoLag 5000
  662. #define InfoDelay 1000
  663. sint64 StartTime, InfoTime, CurrTime;
  664. uint16 SMoves[256];
  665.  
  666. jmp_buf Jump, ResetJump;
  667. HANDLE StreamHandle;
  668.  
  669. #define ExclSingle(depth) 8
  670. #define ExclDouble(depth) 16
  671. #define ExclSinglePV(depth) 8
  672. #define ExclDoublePV(depth) 16
  673.  
  674. // EVAL
  675.  
  676. const sint8 DistC[8] = {3, 2, 1, 0, 0, 1, 2, 3};
  677. const sint8 RankR[8] = {-3, -2, -1, 0, 1, 2, 3, 4};
  678.  
  679. const int SeeValue[16] = {0, 0, 90, 90, 325, 325, 325, 325, 325, 325, 510, 510, 975, 975, 30000, 30000};
  680. const int PieceType[16] = {0, 0, 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 5};
  681.  
  682. #ifndef TUNER
  683. #define V(x) (x)
  684. #else
  685. #define MaxVariables 1024
  686. int var_number, active_vars;
  687. typedef struct {
  688.     char line[256];
  689. } GString;
  690. GString SourceFile[1000], VarName[1000];
  691. int VarIndex[1000];
  692. int src_str_num = 0, var_name_num = 0;
  693. int Variables[MaxVariables];
  694. uint8 Active[MaxVariables];
  695. double Var[MaxVariables], Base[MaxVariables], FE[MaxVariables], SE[MaxVariables], Grad[MaxVariables];
  696. #define V(x) Variables[x]
  697. double EvalOne[MaxVariables], EvalTwo[MaxVariables];
  698. int RecordGames = 0;
  699. char RecordString[65536], PosStr[256], *Buffer;
  700. FILE * frec;
  701. #endif
  702. #define GullCpp "C:/Users/Administrator/Documents/Visual Studio 2010/Projects/Gull/Gull/Gull.cpp"
  703.  
  704. #define ArrayIndex(width,row,column) (((row) * (width)) + (column))
  705. #ifndef TUNER
  706. #define Av(x,width,row,column) (*((x) + ArrayIndex(width,row,column)))
  707. #else
  708. #define Av(x,width,row,column) V((I##x) + ArrayIndex(width,row,column))
  709. #endif
  710. #define TrAv(x,w,r,c) Av(x,0,0,(((r)*(2*(w)-(r)+1))/2)+(c))
  711.  
  712. #define Sa(x,y) Av(x,0,0,y)
  713. #define Ca(x,y) Compose(Av(x,0,0,((y) * 2)),Av(x,0,0,((y) * 2)+1))
  714.  
  715. // EVAL WEIGHTS
  716.  
  717. // tuner: start
  718. enum { // tuner: enum
  719.     IMatLinear,
  720.     IMatQuadMe = IMatLinear + 5,
  721.     IMatQuadOpp = IMatQuadMe + 14,
  722.     IBishopPairQuad = IMatQuadOpp + 10,
  723.     IMatSpecial = IBishopPairQuad + 9,
  724.     IPstQuadWeights = IMatSpecial + 20,
  725.     IPstLinearWeights = IPstQuadWeights + 48,
  726.     IPstQuadMixedWeights = IPstLinearWeights + 48,
  727.     IMobilityLinear = IPstQuadMixedWeights + 24,
  728.     IMobilityLog = IMobilityLinear + 8,
  729.     IShelterValue = IMobilityLog + 8,
  730.     IStormQuad = IShelterValue + 15,
  731.     IStormLinear = IStormQuad + 5,
  732.     IStormHof = IStormLinear + 5,
  733.     IPasserQuad = IStormHof + 2,
  734.     IPasserLinear = IPasserQuad + 18,
  735.     IPasserAttDefQuad = IPasserLinear + 18,
  736.     IPasserAttDefLinear = IPasserAttDefQuad + 4,
  737.     IPasserSpecial = IPasserAttDefLinear + 4,
  738.     IIsolated = IPasserSpecial + 4,
  739.     IUnprotected = IIsolated + 10,
  740.     IBackward = IUnprotected + 6,
  741.     IDoubled = IBackward + 4,
  742.     IRookSpecial = IDoubled + 4,
  743.     ITactical = IRookSpecial + 20,
  744.     IKingDefence = ITactical + 12,
  745.     IPawnSpecial = IKingDefence + 8,
  746.     IBishopSpecial = IPawnSpecial + 8,
  747.     IKnightSpecial = IBishopSpecial + 4,
  748.     IPin = IKnightSpecial + 10,
  749.     IKingRay = IPin + 10,
  750.     IKingAttackWeight = IKingRay + 6
  751. };
  752.  
  753. const int Phase[5] = {
  754.     0, 325, 325, 510, 975
  755. };
  756. #define MaxPhase (16 * Phase[0] + 4 * Phase[1] + 4 * Phase[2] + 4 * Phase[3] + 2 * Phase[4])
  757. #define PhaseMin (2 * Phase[3] + Phase[1] + Phase[2])
  758. #define PhaseMax (MaxPhase - Phase[1] - Phase[2])
  759.  
  760. const int MatLinear[5] = { // tuner: type=array, var=50, active=0
  761.     3, 0, 3, 19, 0
  762. };
  763. // pawn, knight, bishop, rook, queen
  764. const int MatQuadMe[14] = { // tuner: type=array, var=1000, active=0
  765.     -33, 17, -23, -155, -247,
  766.     15, 296, -105, -83,
  767.     -162, 327, 315,
  768.     -861, -1013
  769. };
  770. const int MatQuadOpp[10] = { // tuner: type=array, var=1000, active=0
  771.     -14, 47, -20, -278,
  772.     35, 39, 49,
  773.     9, -2,
  774.     75
  775. };
  776. const int BishopPairQuad[9] = { // tuner: type=array, var=1000, active=0
  777.     -38, 164, 99, 246, -84, -57, -184, 88, -186
  778. };
  779.  
  780. enum { MatRB, MatRN, MatQRR, MatQRB, MatQRN, MatQ3, MatBBR, MatBNR, MatNNR, MatM };
  781. const int MatSpecial[20] = { // tuner: type=array, var=30, active=0
  782.     13, -13, 10, -9, 8, 12, 4, 6, 5, 9, -3, -8, -4, 7, 2, 0, 0, -6, 1, 3
  783. };
  784.  
  785. // piece type (6) * direction (4: h center dist, v center dist, diag dist, rank) * phase (2)
  786. const int PstQuadWeights[48] = { // tuner: type=array, var=100, active=0
  787.     -15, -19, -70, -13, 33, -20, 0, 197, -36, -122, 0, -60, -8, -3, -17, -28,
  788.     -27, -63, -17, -7, 14, 0, -24, -5, -64, -2, 0, -38, -8, 0, 77, 11,
  789.     -67, 3, -4, -92, -2, 12, -13, -42, -62, -84, -175, -42, -2, -17, 40, -19
  790. };
  791. const int PstLinearWeights[48] = { // tuner: type=array, var=500, active=0
  792.     -107, 67, -115, 83, -55, 67, 92, 443, -177, 5, -82, -61, -106, -104, 273, 130,
  793.     0, -145, -105, -58, -99, -37, -133, 14, -185, -43, -67, -53, 53, -65, 174, 134,
  794.     -129, 7, 98, -231, 107, -40, -27, 311, 256, -117, 813, -181, 2, -215, -44, 344
  795. };
  796. // piece type (6) * type (2: h * v, h * rank) * phase (2)
  797. const int PstQuadMixedWeights[24] = { // tuner: type=array, var=100, active=0
  798.     14, -6, 1, -4, -8, -2, 4, -4,
  799.     1, -7, -12, 0, -2, -1, -5, 4,
  800.     5, -10, 0, 4, -2, 5, 4, -2
  801. };
  802. // piece type (4) * phase (2)
  803. const int MobilityLinear[8] = { // tuner: type=array, var=300, active=0
  804.     328, 171, 311, 102, 284, 164, 155, 288
  805. };
  806. const int MobilityLog[8] = { // tuner: type=array, var=500, active=0
  807.     485, -21, 388, 389, -168, 313, 438, -276
  808. };
  809. int Mobility[4][32];
  810.  
  811. // file type (3) * distance from 2d rank/open (5)
  812. const int ShelterValue[15] = {  // tuner: type=array, var=10, active=0
  813.     2, 9, 11, 0, 0, 12, 18, 11, 0, 2, 24, 7, 8, 0, 0
  814. };
  815. sint16 Shelter[3][8];
  816.  
  817. enum { StormBlockedMul, StormShelterAttMul, StormConnectedMul, StormOpenMul, StormFreeMul };
  818. const int StormQuad[5] = { // tuner: type=array, var=250, active=0
  819.     126, 328, 463, 215, 89
  820. };
  821. const int StormLinear[5] = { // tuner: type=array, var=500, active=0
  822.     83, 156, 438, 321, 12
  823. };
  824. enum { StormHofValue, StormOfValue };
  825. const int StormHof[2] = { // tuner: type=array, var=20, active=1
  826.     0, 22
  827. };
  828. sint16 StormBlocked[4];
  829. sint16 StormShelterAtt[4];
  830. sint16 StormConnected[4];
  831. sint16 StormOpen[4];
  832. sint16 StormFree[4];
  833.  
  834. // type (7: general, blocked, free, supported, protected, connected, outside, candidate, clear) * phase (2)
  835. const int PasserQuad[18] = { // tuner: type=array, var=50, active=0
  836.     19, 13, 21, 3, -24, 126, 0, 65, 32, 56, 27, -5, 32, -16, 13, 4, 1, 1
  837. };
  838. const int PasserLinear[18] = { // tuner: type=array, var=200, active=0
  839.     41, 2, 111, 86, 178, 113, 202, 15, -61, 21, 93, 166, 86, 92, 27, 34, -18, -7
  840. };
  841. // type (2: att, def) * scaling (2: linear, log)
  842. const int PasserAttDefQuad[4] = { // tuner: type=array, var=500, active=0
  843.     191, 51, 83, 19
  844. };
  845. const int PasserAttDefLinear[4] = { // tuner: type=array, var=500, active=0
  846.     634, 4, 233, 66
  847. };
  848. enum { PasserOnePiece, PasserOpKingControl, PasserOpMinorControl, PasserOpRookBlock };
  849. const int PasserSpecial[4] = { // tuner: type=array, var=100, active=0
  850.     0, 0, 0, 13
  851. };
  852.  
  853. uint8 LogDist[16];
  854. int PasserGeneral[8];
  855. int PasserBlocked[8];
  856. int PasserFree[8];
  857. int PasserSupported[8];
  858. int PasserProtected[8];
  859. int PasserConnected[8];
  860. int PasserOutside[8];
  861. int PasserCandidate[8];
  862. int PasserClear[8];
  863. sint16 PasserAtt[8];
  864. sint16 PasserDef[8];
  865. sint16 PasserAttLog[8];
  866. sint16 PasserDefLog[8];
  867.  
  868. enum { IsolatedOpen, IsolatedClosed, IsolatedBlocked, IsolatedDoubledOpen, IsolatedDoubledClosed };
  869. const int Isolated[10] = { // tuner: type=array, var=10, active=0
  870.     6, 6, 8, 2, -8, 0, -1, 10, 7, 9
  871. };
  872. enum { UpBlocked, PasserTarget, ChainRoot };
  873. const int Unprotected[6] = { // tuner: type=array, var=10, active=0
  874.     4, 5, -5, -1, 9, -1
  875. };
  876. enum { BackwardOpen, BackwardClosed };
  877. const int Backward[4] = { // tuner: type=array, var=10, active=0
  878.     17, 10, 4, 1
  879. };
  880. enum { DoubledOpen, DoubledClosed };
  881. const int Doubled[4] = { // tuner: type=array, var=10, active=0
  882.     3, 0, 1, 0
  883. };
  884.  
  885. enum { RookHof, RookHofWeakPAtt, RookOf, RookOfOpen, RookOfMinorFixed, RookOfMinorHaging, RookOfKingAtt, Rook7th, Rook7thK8th, Rook7thDoubled };
  886. const int RookSpecial[20] = { // tuner: type=array, var=10, active=0
  887.     8, 0, 2, 0, 11, 8, -1, 2, -1, -1, 14, -1, 5, -5, -5, 0, -6, 8, -7, 31
  888. };
  889.  
  890. enum { TacticalMajorPawn, TacticalMinorPawn, TacticalMajorMinor, TacticalMinorMinor, TacticalThreat, TacticalDoubleThreat };
  891. const int Tactical[12] = { // tuner: type=array, var=20, active=0
  892.     -1, 5, 0, 5, 11, 29, 23, 32, 19, 11, 41, 12
  893. };
  894.  
  895. enum { KingDefKnight, KingDefBishop, KingDefRook, KingDefQueen };
  896. const int KingDefence[8] = { // tuner: type=array, var=5, active=0
  897.     2, 0, 0, 1, 0, 0, 4, 0
  898. };
  899.  
  900. enum { PawnChainLinear, PawnChain, PawnBlocked, PawnFileSpan };
  901. const int PawnSpecial[8] = { // tuner: type=array, var=10, active=0
  902.     11, 9, 9, 4, 0, 9, 1, 1
  903. };
  904.  
  905. enum { BishopNonForwardPawn, BishopPawnBlock };
  906. const int BishopSpecial[4] = { // tuner: type=array, var=5, active=0
  907.     0, 0, 0, 3
  908. };
  909.  
  910. const uint64 Outpost[2] = { Convert(0x00007E7E3C000000, uint64), Convert(0x0000003C7E7E0000, uint64) };
  911. enum { KnightOutpost, KnightOutpostProtected, KnightOutpostPawnAtt, KnightOutpostBishopAtt, KnightOutpostKingAtt };
  912. const int KnightSpecial[10] = { // tuner: type=array, var=10, active=0
  913.     11, 7, 23, 0, 13, 6, 1, 5, 26, 6
  914. };
  915.  
  916. enum { WeakPin, StrongPin, ThreatPin, SelfPawnPin, SelfPiecePin };
  917. const int Pin[10] = { // tuner: type=array, var=20, active=0
  918.     21, 39, 6, 80, 45, 29, 8, 9, 48, 27
  919. };
  920.  
  921. enum { QKingRay, RKingRay, BKingRay };
  922. const int KingRay[6] = { // tuner: type=array, var=20, active=0
  923.     4, 8, -4, 11, 11, -3
  924. };
  925.  
  926. const int KingAttackWeight[7] = { // tuner: type=array, var=20, active=0
  927.     17, 14, 22, 45, 48, 64, 64
  928. };
  929. #define KingNAttack Compose(1, Av(KingAttackWeight, 0, 0, 0))
  930. #define KingBAttack Compose(1, Av(KingAttackWeight, 0, 0, 1))
  931. #define KingRAttack Compose(1, Av(KingAttackWeight, 0, 0, 2))
  932. #define KingQAttack Compose(1, Av(KingAttackWeight, 0, 0, 3))
  933. #define KingAttack Compose(1, 0)
  934. #define KingAttackSquare Av(KingAttackWeight, 0, 0, 4)
  935. #define KingNoMoves Av(KingAttackWeight, 0, 0, 5)
  936. #define KingShelterQuad Av(KingAttackWeight, 0, 0, 6)
  937.  
  938. const int KingAttackScale[16] = { 0, 1, 4, 9, 16, 25, 36, 49, 64, 64, 64, 64, 64, 64, 64, 64 };
  939. // tuner: stop
  940.  
  941. // END EVAL WEIGHTS
  942.  
  943. // SMP
  944.  
  945. #define MaxPrN 1
  946. #ifndef DEBUG
  947. #ifndef TUNER
  948. #undef MaxPrN
  949. #ifndef W32_BUILD
  950. #define MaxPrN 64 // mustn't exceed 64
  951. #else
  952. #define MaxPrN 32 // mustn't exceed 32
  953. #endif
  954. #endif
  955. #endif
  956.  
  957. int PrN = 1, CPUs = 1, HT = 0, parent = 1, child = 0, WinParId, Id = 0, ResetHash = 1, NewPrN = 0;
  958. HANDLE ChildPr[MaxPrN];
  959. #define SplitDepth 10
  960. #define SplitDepthPV 4
  961. #define MaxSplitPoints 64 // mustn't exceed 64
  962.  
  963. typedef struct {
  964.     GPosData Position[1];
  965.     uint64 stack[100];
  966.     uint16 killer[16][2];
  967.     int sp, date;
  968. } GPos;
  969.  
  970. #define FlagClaimed (1 << 1)
  971. #define FlagFinished (1 << 2)
  972.  
  973. typedef struct {
  974.     volatile uint16 move;
  975.     volatile uint8 reduced_depth, research_depth, stage, ext, id, flags;
  976. } GMove;
  977.  
  978. typedef struct {
  979.     volatile LONG lock;
  980.     volatile int claimed, active, finished, pv, move_number, current, depth, alpha, beta, singular, split, best_move, height;
  981.     GMove move[128];
  982.     jmp_buf jump;
  983.     GPos Pos[1];
  984. } GSP;
  985.  
  986. typedef struct {
  987.     volatile long long nodes, active_sp, searching;
  988. #ifndef W32_BUILD
  989.     volatile long long stop, fail_high;
  990. #else
  991.     volatile long stop, fail_high;
  992. #endif
  993.     volatile sint64 hash_size;
  994.     volatile int PrN;
  995.     GSP Sp[MaxSplitPoints];
  996. } GSMPI;
  997.  
  998. #define SharedMaterialOffset (sizeof(GSMPI))
  999. #define SharedMagicOffset (SharedMaterialOffset + TotalMat * sizeof(GMaterial))
  1000. #define SharedPVHashOffset (SharedMagicOffset + magic_size * sizeof(uint64))
  1001.  
  1002. GSMPI * Smpi;
  1003.  
  1004. jmp_buf CheckJump;
  1005.  
  1006. HANDLE SHARED = NULL, HASH = NULL;
  1007.  
  1008. #ifndef W32_BUILD
  1009. #define SET_BIT(var,bit) (InterlockedOr(&(var),1 << (bit)))
  1010. #define SET_BIT_64(var,bit) (InterlockedOr64(&(var),Bit(bit)));
  1011. #define ZERO_BIT_64(var,bit) (InterlockedAnd64(&(var),~Bit(bit)));
  1012. #define TEST_RESET_BIT(var,bit) (InterlockedBitTestAndReset64(&(var),bit))
  1013. #define TEST_RESET(var) (InterlockedExchange64(&(var),0))
  1014. #else
  1015. #define SET_BIT(var,bit) (_InterlockedOr(&(var),1 << (bit)))
  1016. #define SET_BIT_64(var,bit) {if ((bit) < 32) _InterlockedOr((LONG*)&(var),1 << (bit)); else _InterlockedOr(((LONG*)(&(var))) + 1,1 << ((bit) - 32));}
  1017. #define ZERO_BIT_64(var,bit) {if ((bit) < 32) _InterlockedAnd((LONG*)&(var),~(1 << (bit))); else _InterlockedAnd(((LONG*)(&(var))) + 1,~(1 << ((bit) - 32)));}
  1018. #define TEST_RESET_BIT(var,bit) (InterlockedBitTestAndReset(&(var),bit))
  1019. #define TEST_RESET(var) (InterlockedExchange(&(var),0))
  1020. #endif
  1021. #define SET(var,value) (InterlockedExchange(&(var),value))
  1022.  
  1023. #define LOCK(lock) {while (InterlockedCompareExchange(&(lock),1,0)) _mm_pause();}
  1024. #define UNLOCK(lock) {SET(lock,0);}
  1025.  
  1026. // END SMP
  1027.  
  1028. __forceinline int lsb(uint64 x);
  1029. __forceinline int msb(uint64 x);
  1030. __forceinline int popcnt(uint64 x);
  1031. __forceinline int MinF(int x, int y);
  1032. __forceinline int MaxF(int x, int y);
  1033. __forceinline double MinF(double x, double y);
  1034. __forceinline double MaxF(double x, double y);
  1035. template <bool HPopCnt> __forceinline int popcount(uint64 x);
  1036. uint64 BMagicAttacks(int i, uint64 occ);
  1037. uint64 RMagicAttacks(int i, uint64 occ);
  1038. uint16 rand16();
  1039. uint64 random();
  1040. void init_pst();
  1041. void init_eval();
  1042. void init();
  1043. void init_search(int clear_hash);
  1044. void setup_board();
  1045. void get_board(const char fen[]);
  1046. void init_hash();
  1047. void move_to_string(int move, char string[]);
  1048. int move_from_string(char string[]);
  1049. void pick_pv();
  1050. template <bool me> void do_move(int move);
  1051. template <bool me> void undo_move(int move);
  1052. void do_null();
  1053. void undo_null();
  1054. __forceinline void evaluate();
  1055. template <bool me> int is_legal(int move);
  1056. template <bool me> int is_check(int move);
  1057. void hash_high(int value, int depth);
  1058. void hash_low(int move, int value, int depth);
  1059. void hash_exact(int move, int value, int depth, int exclusion, int ex_depth, int knodes);
  1060. __forceinline int pick_move();
  1061. template <bool me, bool root> int get_move();
  1062. template <bool me> int see(int move, int margin);
  1063. template <bool me> void gen_root_moves();
  1064. template <bool me> int * gen_captures(int * list);
  1065. template <bool me> int * gen_evasions(int * list);
  1066. void mark_evasions(int * list);
  1067. template <bool me> int * gen_quiet_moves(int * list);
  1068. template <bool me> int * gen_checks(int * list);
  1069. template <bool me> int * gen_delta_moves(int * list);
  1070. template <bool me, bool pv> int q_search(int alpha, int beta, int depth, int flags);
  1071. template <bool me, bool pv> int q_evasion(int alpha, int beta, int depth, int flags);
  1072. template <bool me, bool exclusion> int search(int beta, int depth, int flags);
  1073. template <bool me, bool exclusion> int search_evasion(int beta, int depth, int flags);
  1074. template <bool me, bool root> int pv_search(int alpha, int beta, int depth, int flags);
  1075. template <bool me> void root();
  1076. template <bool me> int multipv(int depth);
  1077. void send_pv(int depth, int alpha, int beta, int score);
  1078. void send_multipv(int depth, int curr_number);
  1079. void send_best_move();
  1080. void get_position(char string[]);
  1081. void get_time_limit(char string[]);
  1082. sint64 get_time();
  1083. int time_to_stop(GSearchInfo * SI, int time, int searching);
  1084. void check_time(int searching);
  1085. void check_time(int time, int searching);
  1086. int input();
  1087. void uci();
  1088.  
  1089. #ifdef TUNER
  1090. #ifndef RECORD_GAMES
  1091. int ResignThreshold = 150;
  1092. #else
  1093. int ResignThreshold = 1500;
  1094. #endif
  1095.  
  1096. typedef struct {
  1097.     int wins, draws, losses;
  1098. } GMatchInfo;
  1099. GMatchInfo MatchInfo[1] = {(0, 0, 0)};
  1100.  
  1101. char Fen[65536][128];
  1102. int opening_positions = 0;
  1103.  
  1104. int Client = 0, Server = 0, Local = 1, cmd_number = 0;
  1105. int generation = 0;
  1106.  
  1107. #ifdef PGN
  1108. typedef struct {
  1109.     uint64 bb[6]; // white, black, pawns, minor, major, queens and knights
  1110.     uint8 ep_square, turn, ply, castle_flags;
  1111. } GPos;
  1112. GPos Pos[65536];
  1113. int pgn_positions = 0;
  1114.  
  1115. void position_to_pos(GPos * pos) {
  1116.     pos->bb[0] = Piece(White);
  1117.     pos->bb[1] = Piece(Black);
  1118.     pos->bb[2] = PawnAll;
  1119.     pos->bb[3] = Minor(White) | Minor(Black);
  1120.     pos->bb[4] = Major(White) | Major(Black);
  1121.     pos->bb[5] = Queen(White) | Queen(Black) | Knight(White) | Knight(Black);
  1122.     pos->ep_square = Current->ep_square;
  1123.     pos->turn = Current->turn;
  1124.     pos->castle_flags = Current->castle_flags;
  1125. }
  1126.  
  1127. void position_from_pos(GPos * pos) {
  1128.     Current = Data;
  1129.     memset(Board, 0, sizeof(GBoard));
  1130.     memset(Current, 0, sizeof(GData));
  1131.     BB(White) = pos->bb[0];
  1132.     BB(Black) = pos->bb[1];
  1133.     for (int me = 0; me < 2; me++) {
  1134.         BB(me) = pos->bb[me];
  1135.         BB(IPawn(me)) = pos->bb[2] & BB(me);
  1136.         BB(IKnight(me)) = pos->bb[3] & pos->bb[5] & BB(me);
  1137.         BB(ILight(me)) = pos->bb[3] & (~pos->bb[5]) & LightArea & BB(me);
  1138.         BB(IDark(me)) = pos->bb[3] & (~pos->bb[5]) & DarkArea & BB(me);
  1139.         BB(IRook(me)) = pos->bb[4] & (~pos->bb[5]) & BB(me);
  1140.         BB(IQueen(me)) = pos->bb[4] & pos->bb[5] & BB(me);
  1141.         BB(IKing(me)) = BB(me) & (~(pos->bb[2] | pos->bb[3] | pos->bb[4]));
  1142.     }
  1143.     for (int i = 2; i < 16; i++) for (uint64 u = BB(i); u; Cut(u)) Square(lsb(u)) = i;
  1144.     Current->ep_square = pos->ep_square;
  1145.     Current->ply = pos->ply;
  1146.     Current->castle_flags = pos->castle_flags;
  1147.     Current->turn = pos->turn;
  1148.     setup_board();
  1149. }
  1150.  
  1151. int pos_shelter_tune() {
  1152.     if (!Queen(White) || !Queen(Black)) return 0;
  1153.     if (popcnt(NonPawnKingAll) < 10) return 0;
  1154.     if (Current->castle_flags) return 0;
  1155.     if (File(lsb(King(White))) <= 2 && File(lsb(King(Black))) >= 5) return 1;
  1156.     if (File(lsb(King(White))) >= 5 && File(lsb(King(Black))) <= 2) return 1;
  1157.     return 0;
  1158. }
  1159. int pos_passer_tune() {
  1160.     if (Current->passer) return 1;
  1161.     return 0;
  1162. }
  1163. #endif
  1164.  
  1165. void init_openings() {
  1166.     FILE * ffen = NULL;
  1167.     ffen = fopen("8moves.epd","r");
  1168.     if (ffen != NULL) {
  1169.         for (int i = 0; i < 65536; i++) {
  1170.             fgets(Fen[i],128,ffen);
  1171.             if (feof(ffen)) {
  1172.                 opening_positions = Max(opening_positions - 1, 0);
  1173.                 break;
  1174.             } else opening_positions++;
  1175.         }
  1176.     } else {
  1177.         fprintf(stdout,"File '8moves.epd' not found\n");
  1178.         exit(0);
  1179.         goto no_fen;
  1180.     }
  1181.     fclose(ffen);
  1182. no_fen:
  1183.     if (opening_positions == 0) {
  1184.         sprintf(Fen[0],"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1\n");
  1185.         opening_positions = 1;
  1186.     }
  1187. #ifdef PGN
  1188.     FILE * fpgn = fopen("uci_games.pgn", "r");
  1189.     if (fpgn == NULL) {
  1190.         fprintf(stdout, "File 'uci_games.pgn' not found\n");
  1191.         exit(0);
  1192.     }
  1193.     while (pgn_positions < 65536) {
  1194.         fgets(mstring, 65536, fpgn);
  1195.         if (feof(fpgn)) {
  1196.             pgn_positions = Max(pgn_positions - 1, 0);
  1197.             break;
  1198.         }
  1199.         if (strstr(mstring, "FEN")) get_board(mstring + 6);
  1200.         if (strchr(mstring, '[')) continue;
  1201.         if (strlen(mstring) < 100) continue;
  1202.         char * ptr = mstring;
  1203.         while (*ptr != 0) {
  1204.             evaluate();
  1205.             if (pos_passer_tune()) {
  1206.                 position_to_pos(&Pos[pgn_positions++]);
  1207.                 break;
  1208.             }
  1209.             pv_string[0] = *ptr++;
  1210.             pv_string[1] = *ptr++;
  1211.             pv_string[2] = *ptr++;
  1212.             pv_string[3] = *ptr++;
  1213.             if (*ptr == 0 || *ptr == ' ') pv_string[4] = 0;
  1214.             else {
  1215.                 pv_string[4] = *ptr++;
  1216.                 pv_string[5] = 0;
  1217.             }
  1218.             if (pv_string[0] == '1' || pv_string[0] == '0') break;
  1219.             int move = move_from_string(pv_string);
  1220.             if (Current->turn) {
  1221.                 if (!is_legal<1>(move)) break;
  1222.                 do_move<1>(move);
  1223.             } else {
  1224.                 if (!is_legal<0>(move)) break;
  1225.                 do_move<0>(move);
  1226.             }
  1227.             memcpy(Data, Current, sizeof(GData));
  1228.             Current = Data;
  1229.             while (*ptr == ' ') ptr++;
  1230.         }
  1231.     }
  1232.     fclose(fpgn);
  1233.     fprintf(stdout, "%d PGN positions\n", pgn_positions);
  1234. #endif
  1235. }
  1236. void init_variables() {
  1237.     int i, j, k, start = 0;
  1238.     FILE * f;
  1239.  
  1240.     if (Local) f = fopen(GullCpp, "r");
  1241.     else if (Server) f = fopen("./Server/Gull.cpp", "r");
  1242.     else f = fopen("./Client/Gull.cpp", "r");
  1243.     while (!feof(f)) {
  1244.         (void)fgets(mstring, 256, f);
  1245.         if (!start && memcmp(mstring, "// tuner: start", 15)) continue;
  1246.         start = 1;
  1247.         if (!memcmp(mstring, "// tuner: stop", 14)) break;
  1248.         memcpy(SourceFile[src_str_num].line, mstring, 256);
  1249.         src_str_num++;
  1250.     }
  1251.     fclose(f);
  1252.  
  1253.     var_number = 0;
  1254.     active_vars = 0;
  1255.  
  1256.     int curr_ind = -1, active, indexed[MaxVariables];
  1257.     double var;
  1258.     char *p, *q;
  1259.     memset(VarName, 0, 1000 * sizeof(GString)); memset(indexed, 0, MaxVariables * sizeof(int));
  1260.     for (i = 0; i < src_str_num; i++) {
  1261.         if (!strstr(SourceFile[i].line, "tuner: enum")) continue;
  1262.         for (i++; !strstr(SourceFile[i].line, "};"); i++) {
  1263.             p = strchr(SourceFile[i].line, 'I') + 1;
  1264.             strcpy(VarName[var_name_num].line, p);
  1265.             for (j = 0; VarName[var_name_num].line[j] >= '0' && VarName[var_name_num].line[j] <= 'z'; j++);
  1266.             VarName[var_name_num].line[j] = '\n';
  1267.             for (k = j + 1; k < 1000; k++) VarName[var_name_num].line[k] = 0;
  1268.             q = strchr(p, '+');
  1269.             if (q != NULL) curr_ind += atoi(q + 1);
  1270.             else curr_ind++;
  1271.             VarIndex[var_name_num] = curr_ind;
  1272.             var_name_num++;
  1273.         }
  1274.         break;
  1275.     }
  1276.     for (i = 0; i < src_str_num; i++) {
  1277.         if (!(p = strstr(SourceFile[i].line, "tuner:"))) continue;
  1278.         q = strstr(p, "type="); if (q == NULL) continue; q += 5;
  1279.         p = strstr(q, "active=");
  1280.         if (p == NULL) active = 1;
  1281.         else active = atoi(p + 7);
  1282.         uint8 active_mask[1024];
  1283.         memset(active_mask, 1, 1024);
  1284.         if (p = strstr(q, "mask=")) {
  1285.             p += 5;
  1286.             j = 0;
  1287.             while (p[0] != ' ') {
  1288.                 int value = 0; if (p[0] == 's') value = 1;
  1289.                 if (p[1] == '&') {
  1290.                     if (value == 1) break;
  1291.                     for (k = j; k < 1024; k++) active_mask[k] = 0;
  1292.                     break;
  1293.                 }
  1294.                 for (k = 0; k < p[1] - '0'; k++) active_mask[j + k] = value;
  1295.                 j += p[1] - '0';
  1296.                 p += 2;
  1297.             }
  1298.         }
  1299.         p = strstr(q, "var=");
  1300.         if (p == NULL) var = 1000.0;
  1301.         else var = (double)atoi(p + 4);
  1302.         if (!memcmp(q, "array", 5)) {
  1303.             p = strstr(SourceFile[i].line, "int "); p += 4;
  1304.             q = strchr(p, '[');
  1305.             for (j = 0; j < var_name_num; j++) if (!memcmp(p, VarName[j].line, (int)(q - p))) break;
  1306.             curr_ind = VarIndex[j];
  1307.             fprintf(stdout, "Array (%d) active=%d var=%.2lf: %s", curr_ind, active, var, VarName[j].line);
  1308.         }
  1309.         i++;
  1310.         memset(mstring, 0, strlen(mstring));
  1311.         while (!strstr(SourceFile[i].line, "};")) {
  1312.             strcat(mstring, SourceFile[i].line);
  1313.             i++;
  1314.         }
  1315.         i--;
  1316.         p = mstring - 1;
  1317.         int cnt = 0;
  1318.         do {
  1319.             p++;
  1320.             Variables[curr_ind] = atoi(p); var_number++;
  1321.             if (indexed[curr_ind]) { fprintf(stdout, "index mismatch: %d (%s)\n", curr_ind, VarName[j].line); exit(0); }
  1322.             indexed[curr_ind]++;
  1323.             int activate = 0;
  1324.             if (active && active_mask[cnt]) activate = 1;
  1325.             if (activate) Var[active_vars] = var;
  1326.             Active[curr_ind++] = activate; active_vars += activate; cnt++;
  1327.         } while (p = strchr(p, ','));
  1328.     }
  1329.     for (i = 0; i < curr_ind; i++) if (!indexed[i]) { fprintf(stdout, "index skipped %d\n", i); exit(0); }
  1330.     fprintf(stdout, "%d variables, %d active\n", var_number, active_vars);
  1331. }
  1332. void eval_to_cpp(const char * filename, double * list) {
  1333.     FILE * f = fopen(filename, "w");
  1334.     for (int i = 0; i < var_name_num; i++) VarName[i].line[strlen(VarName[i].line) - 1] = 0;
  1335.     for (int i = 0; i < src_str_num; i++) {
  1336.         fprintf(f, "%s", SourceFile[i].line);
  1337.         if (!strstr(SourceFile[i].line, "type=array") || strstr(SourceFile[i].line, "active=0")) continue;
  1338.         for (int j = 0; j < var_name_num; j++) if (strstr(SourceFile[i].line, VarName[j].line)) {
  1339.             int n = 0;
  1340. start:
  1341.             i++;
  1342.             fprintf(f, "    ");
  1343.             int cnt = 0, index = 0; for (int k = 0; k < VarIndex[j]; k++) if (Active[k]) index++;
  1344.             char * p = SourceFile[i].line, *end;
  1345.             while ((p = strchr(p+1, ',')) != NULL) cnt++; if (end = strstr(SourceFile[i + 1].line, "};")) cnt++;
  1346.             for (int k = 0; k < cnt; k++) {
  1347.                 fprintf(f, "%d", (int)list[index + (n++)]);
  1348.                 if (k + 1 < cnt) fprintf(f, ", ");
  1349.                 else if (end == NULL) fprintf(f, ",\n");
  1350.                 else fprintf(f, "\n");
  1351.             }
  1352.             if (end == NULL) goto start;
  1353.         }
  1354.     }
  1355.     fclose(f);
  1356. }
  1357. void print_eval() {
  1358.     int i, j;
  1359.     FILE * f = fopen("eval.txt", "w");
  1360.     fprintf(f, "Pst\n");
  1361.     for (j = 2; j < 16; j += 2) {
  1362.         if (j == 8) continue;
  1363.         fprintf(f, "%d:\n", j);
  1364.         for (i = 0; i < 64; i++) {
  1365.             fprintf(f, "(%d,%d), ", Opening(Pst(j, i)), Endgame(Pst(j, i)));
  1366.             if ((i + 1) % 8 == 0) fprintf(f, "\n");
  1367.         }
  1368.     }
  1369.     fprintf(f, "Mobility\n");
  1370.     for (j = 0; j < 4; j++) {
  1371.         fprintf(f, "%d:\n", j);
  1372.         for (i = 0; i < 32; i++) fprintf(f, "(%d,%d), ", Opening(Mobility[j][i]), Endgame(Mobility[j][i]));
  1373.         fprintf(f, "\n");
  1374.     }
  1375.     fprintf(f, "PasserGeneral\n");
  1376.     for (i = 0; i < 8; i++) fprintf(f, "(%d,%d), ", Opening(PasserGeneral[i]), Endgame(PasserGeneral[i]));
  1377.     fprintf(f, "\n");
  1378.  
  1379.     fprintf(f, "PasserBlocked\n");
  1380.     for (i = 0; i < 8; i++) fprintf(f, "(%d,%d), ", Opening(PasserBlocked[i]), Endgame(PasserBlocked[i]));
  1381.     fprintf(f, "\n");
  1382.  
  1383.     fprintf(f, "PasserFree\n");
  1384.     for (i = 0; i < 8; i++) fprintf(f, "(%d,%d), ", Opening(PasserFree[i]), Endgame(PasserFree[i]));
  1385.     fprintf(f, "\n");
  1386.  
  1387.     fprintf(f, "PasserSupported\n");
  1388.     for (i = 0; i < 8; i++) fprintf(f, "(%d,%d), ", Opening(PasserSupported[i]), Endgame(PasserSupported[i]));
  1389.     fprintf(f, "\n");
  1390.  
  1391.     fprintf(f, "PasserProtected\n");
  1392.     for (i = 0; i < 8; i++) fprintf(f, "(%d,%d), ", Opening(PasserProtected[i]), Endgame(PasserProtected[i]));
  1393.     fprintf(f, "\n");
  1394.  
  1395.     fprintf(f, "PasserConnected\n");
  1396.     for (i = 0; i < 8; i++) fprintf(f, "(%d,%d), ", Opening(PasserConnected[i]), Endgame(PasserConnected[i]));
  1397.     fprintf(f, "\n");
  1398.  
  1399.     fprintf(f, "PasserOutside\n");
  1400.     for (i = 0; i < 8; i++) fprintf(f, "(%d,%d), ", Opening(PasserOutside[i]), Endgame(PasserOutside[i]));
  1401.     fprintf(f, "\n");
  1402.  
  1403.     fprintf(f, "PasserCandidate\n");
  1404.     for (i = 0; i < 8; i++) fprintf(f, "(%d,%d), ", Opening(PasserCandidate[i]), Endgame(PasserCandidate[i]));
  1405.     fprintf(f, "\n");
  1406.  
  1407.     fprintf(f, "PasserClear\n");
  1408.     for (i = 0; i < 8; i++) fprintf(f, "(%d,%d), ", Opening(PasserClear[i]), Endgame(PasserClear[i]));
  1409.     fprintf(f, "\n");
  1410.  
  1411.     fprintf(f, "PasserAtt\n");
  1412.     for (i = 0; i < 8; i++) fprintf(f, "%d, ", PasserAtt[i]);
  1413.     fprintf(f, "\n");
  1414.  
  1415.     fprintf(f, "PasserDef\n");
  1416.     for (i = 0; i < 8; i++) fprintf(f, "%d, ", PasserDef[i]);
  1417.     fprintf(f, "\n");
  1418.  
  1419.     fprintf(f, "PasserAttLog\n");
  1420.     for (i = 0; i < 8; i++) fprintf(f, "%d, ", PasserAttLog[i]);
  1421.     fprintf(f, "\n");
  1422.  
  1423.     fprintf(f, "PasserDefLog\n");
  1424.     for (i = 0; i < 8; i++) fprintf(f, "%d, ", PasserDefLog[i]);
  1425.     fprintf(f, "\n");
  1426.  
  1427.     fprintf(f, "StormBlocked\n");
  1428.     for (i = 0; i < 4; i++) fprintf(f, "%d, ", StormBlocked[i]);
  1429.     fprintf(f, "\n");
  1430.  
  1431.     fprintf(f, "StormShelterAtt\n");
  1432.     for (i = 0; i < 4; i++) fprintf(f, "%d, ", StormShelterAtt[i]);
  1433.     fprintf(f, "\n");
  1434.  
  1435.     fprintf(f, "StormConnected\n");
  1436.     for (i = 0; i < 4; i++) fprintf(f, "%d, ", StormConnected[i]);
  1437.     fprintf(f, "\n");
  1438.  
  1439.     fprintf(f, "StormOpen\n");
  1440.     for (i = 0; i < 4; i++) fprintf(f, "%d, ", StormOpen[i]);
  1441.     fprintf(f, "\n");
  1442.  
  1443.     fprintf(f, "StormFree\n");
  1444.     for (i = 0; i < 4; i++) fprintf(f, "%d, ", StormFree[i]);
  1445.     fprintf(f, "\n");
  1446.  
  1447.     fclose(f);
  1448. }
  1449.  
  1450. double ratio_from_elo(double elo) { return 1.0 / (1.0 + exp(((-elo) / 400.0)*log(10.0))); }
  1451. double elo_from_ratio(double ratio) { return -(log((1.0 / MinF(0.99999, Max(ratio, 0.00001))) - 1.0) / log(10.0)) * 400.0; }
  1452. double rand_u() { return MinF(1.0, Max(0.0, ((double)((rand() << 15) | rand())) / (32768.0 * 32768.0))); }
  1453. double gaussian(double mean, double sigma) { return sqrt(Max(0.0000001, -2.0 * log(Max(0.0000001, rand_u())))) * sin(2.0 * 3.14159265358979323846 * rand_u()) * sigma + mean; }
  1454. void int_to_double(double * dst, int * src, int n) {for (int i = 0; i < n; i++) dst[i] = (double)src[i];}
  1455. void double_to_int(int * dst, double * src, int n) {for (int i = 0; i < n; i++) dst[i] = (int)src[i];}
  1456. void double_to_double(double * dst, double * src, int n) {for (int i = 0; i < n; i++) dst[i] = src[i];}
  1457. void int_to_int(int * dst, int * src, int n) {for (int i = 0; i < n; i++) dst[i] = src[i];}
  1458. double scalar(double * one, double * two, int n) {
  1459.     double result = 0.0;
  1460.     for (int i = 0; i < n; i++) result += one[i] * two[i];
  1461.     return result;
  1462. }
  1463. void load_list(double * list) {
  1464.     int i, j = 0;
  1465.     for (i = 0; i < var_number; i++) if (Active[i]) Variables[i] = (int)list[j++];
  1466. }
  1467. void save_list(double * list) {
  1468.     int i, j = 0;
  1469.     for (i = 0; i < var_number; i++) if (Active[i]) list[j++] = (double)Variables[i];
  1470. }
  1471. void log_list(FILE * f, double * list, int n) {
  1472.     fprintf(f,"(");
  1473.     for (int i = 0; i < n; i++) {
  1474.         fprintf(f,"%.2lf",list[i]);
  1475.         if (i < n - 1) fprintf(f,",");
  1476.     }
  1477.     fprintf(f,")\n");
  1478. }
  1479. void log_list(const char * file_name, double * list, int n) {
  1480.     FILE * f = fopen(file_name,"a");
  1481.     log_list(f,list,n);
  1482.     fclose(f);
  1483. }
  1484. void log_list(char * s, double * list, int n, bool precision) {
  1485.     sprintf(s+strlen(s),"(");
  1486.     for (int i = 0; i < n; i++) {
  1487.         if (!precision) sprintf(s+strlen(s),"%.2lf",list[i]);
  1488.         else sprintf(s+strlen(s),"%lf",list[i]);
  1489.         if (i < n - 1) sprintf(s+strlen(s),",");
  1490.     }
  1491.     sprintf(s+strlen(s),") ");
  1492. }
  1493. void read_list(char * string, double * list, int n) {
  1494.     int i = 0;
  1495.     char * p = strchr(string,'(');
  1496.     do {
  1497.         p++;
  1498.         list[i++] = atof(p);
  1499.         if (i >= n) break;
  1500.     } while (p = strchr(p,','));
  1501. }
  1502. void init_eval_data(double * one, double * two) {
  1503.     if (one != EvalOne) double_to_double(EvalOne,one,var_number);
  1504.     if (two != EvalTwo) double_to_double(EvalTwo,two,var_number);
  1505.     load_list(one); Pst = PstOne; init_pst();
  1506.     load_list(two); Pst = PstTwo; init_pst();
  1507. }
  1508. void load_eval(int first) {
  1509.     int i;
  1510.     generation++;
  1511.     for (i = 1; i < 128; i++) Data[i].eval_key = 0;
  1512.     if (first) {
  1513.         load_list(EvalOne);
  1514.         Hash = HashOne;
  1515.         PawnHash = PawnHashOne;
  1516.         PVHash = PVHashOne;
  1517.         Pst = PstOne;
  1518.         History = HistoryOne;
  1519.         Delta = DeltaOne;
  1520.         Ref = RefOne;
  1521.     } else {
  1522.         load_list(EvalTwo);
  1523.         Hash = HashTwo;
  1524.         PawnHash = PawnHashTwo;
  1525.         PVHash = PVHashTwo;
  1526.         Pst = PstTwo;
  1527.         History = HistoryTwo;
  1528.         Delta = DeltaTwo;
  1529.         Ref = RefTwo;
  1530.     }
  1531.     Current->pst = 0;
  1532.     for (i = 0; i < 64; i++) if (Square(i)) Current->pst += Pst(Square(i),i);
  1533.     init_eval();
  1534. }
  1535. void compute_list(double * dst, double * base, double * dir, double * var, double a) {for (int i = 0; i < active_vars; i++) dst[i] = base[i] + dir[i] * var[i] * a;}
  1536. void scale_list(double * list, double r) {
  1537.     int i;
  1538.     double x = 0.0;
  1539.     for (i = 0; i < active_vars; i++) x += Sqr(list[i]);
  1540.     x = r/sqrt(x);
  1541.     for (i = 0; i < active_vars; i++) list[i] *= x;
  1542. }
  1543. int play(int depth) {
  1544.     LastDepth = TimeLimit1 = TimeLimit2 = 0;
  1545. #ifdef TIMING
  1546.     Infinite = 0;
  1547.     int nmoves = MovesTg - 1;
  1548.     if (Current->ply > 40) nmoves += Min(Current->ply - 40, (100 - Current->ply) / 2);
  1549.     TimeLimit1 = Min(GlobalTime[GlobalTurn], (GlobalTime[GlobalTurn] + nmoves * GlobalInc[GlobalTurn]) / nmoves);
  1550.     TimeLimit2 = Min(GlobalTime[GlobalTurn], (GlobalTime[GlobalTurn] + nmoves * GlobalInc[GlobalTurn]) / 3);
  1551.     TimeLimit1 = Min(GlobalTime[GlobalTurn], (TimeLimit1 * TimeRatio) / 100);
  1552.     DepthLimit = 128; Searching = 1; nodes = Stop = 0;
  1553.     StartTime = get_time();
  1554. #else
  1555.     DepthLimit = 2 * depth + 2;
  1556.     Infinite = 1;
  1557. #endif
  1558.     best_score = best_move = 0;
  1559.     Print = 0;
  1560.     if (Current->turn == White) root<0>(); else root<1>();
  1561.     return best_score;
  1562. }
  1563. double play_game(double * one, double * two, int depth, char * fen) {
  1564.     int i, cnt, sdepth, value, previous = 0, im = 0;
  1565.     load_eval(0); init_search(1); load_eval(1); init_search(1);
  1566. #ifndef PGN
  1567.     get_board(fen);
  1568.     if (RecordGames) {
  1569.         RecordString[0] = 0;
  1570.         for (cnt = 0; fen[cnt] != '\n'; cnt++) PosStr[cnt] = fen[cnt];
  1571.         PosStr[cnt] = 0;
  1572.     }
  1573. #else
  1574.     position_from_pos((GPos*)fen);
  1575. #endif
  1576.     init_eval_data(one,two);
  1577.  
  1578. #ifdef TIMING
  1579.     GlobalTime[0] = GlobalTime[1] = Convert((1.0 + rand_u()) * (double)(1000 << (int)(depth)),int);
  1580.     GlobalInc[0] = GlobalInc[1] = GlobalTime[0] / 200;
  1581. #endif
  1582.  
  1583.     for (cnt = 0; cnt < 200 + (RecordGames ? 200 : 0); cnt++) {
  1584.         GlobalTurn = Even(cnt);
  1585.         load_eval(GlobalTurn);
  1586.         memcpy(Data, Current, sizeof(GData));
  1587.         Current = Data;
  1588.         if (Even(cnt)) sdepth = depth + Odd(rand16());
  1589.         value = play(sdepth);
  1590.         if (!best_move) goto loss;
  1591.         if (value < -ResignThreshold && previous > ResignThreshold) goto loss;
  1592.         if (!RecordGames) {
  1593.             if (value == 0 && previous == 0 && cnt >= 60) goto draw;
  1594.             if (Abs(value) <= 3 && Abs(previous) <= 3 && cnt >= 120) goto draw;
  1595.         }
  1596.         if (Current->ply >= 100) goto draw;
  1597.         for (i = 4; i <= Current->ply; i += 2) if (Stack[sp - i] == Current->key) goto draw;
  1598.         int me = 0;
  1599.         if (!PawnAll) {
  1600.             int my_score = 3 * popcnt(Minor(me)) + 5 * popcnt(Rook(me)) + 9 * popcnt(Queen(me));
  1601.             int opp_score = 3 * popcnt(Minor(opp)) + 5 * popcnt(Rook(opp)) + 9 * popcnt(Queen(opp));
  1602.             if (Abs(my_score - opp_score) <= 3 && Max(popcnt(NonPawnKing(me)),popcnt(NonPawnKing(opp))) <= 2) {
  1603.                 im++;
  1604.                 if (im >= 10 && Abs(value) < 50 && Abs(previous) < 50) goto draw;
  1605.             }
  1606.         }
  1607. #ifdef WIN_PR
  1608.         if (cnt >= 6 && (
  1609.             (!Queen(White) && !Queen(Black)) ||
  1610.             (popcnt(NonPawnKing(White)) <= 2 && popcnt(NonPawnKing(Black)) <= 2) ||
  1611.             (!Current->castle_flags && ((File[File(lsb(King(White)))] | PIsolated[File(lsb(King(White)))]) & King(Black)))
  1612.             )) return ratio_from_elo(3.0 * (double)value) + ratio_from_elo(-3.0 * (double)previous);
  1613. #endif
  1614.         previous = value;
  1615.         if (!Current->turn) do_move<0>(best_move);
  1616.         else do_move<1>(best_move);
  1617.         if (RecordGames) {
  1618.             move_to_string(best_move, pv_string);
  1619.             sprintf(RecordString + strlen(RecordString), "%s { %.2lf / %d } ", pv_string, (double)(Current->turn ? value : (-value)) / 100.0, LastDepth/2);
  1620.         }
  1621.     }
  1622. draw:
  1623.     if (RecordGames) sprintf(Buffer + strlen(Buffer), "[FEN \"%s\"]\n[Result \"1/2-1/2\"]\n%s\n", PosStr, RecordString);
  1624.     return 1.0;
  1625. loss:
  1626.     if (Even(cnt)) {
  1627.         if (RecordGames) {
  1628.             if (Current->turn) sprintf(Buffer + strlen(Buffer), "[FEN \"%s\"]\n[Result \"1-0\"]\n%s\n", PosStr, RecordString);
  1629.             else sprintf(Buffer + strlen(Buffer), "[FEN \"%s\"]\n[Result \"0-1\"]\n%s\n", PosStr, RecordString);
  1630.         }
  1631.         return 0.0;
  1632.     } else {
  1633.         if (RecordGames) {
  1634.             if (Current->turn) sprintf(Buffer + strlen(Buffer), "[FEN \"%s\"]\n[Result \"1-0\"]\n%s\n", PosStr, RecordString);
  1635.             else sprintf(Buffer + strlen(Buffer), "[FEN \"%s\"]\n[Result \"0-1\"]\n%s\n", PosStr, RecordString);
  1636.         }
  1637.         return 2.0;
  1638.     }
  1639. }
  1640. double play_position(double * one, double * two, int depth, char * fen, GMatchInfo * MI) {
  1641.     double result, score = 0.0;
  1642.     result = play_game(one, two, depth, fen); if (result >= 1.98) MI->wins++; else if (result <= 0.02) MI->losses++; else MI->draws++;
  1643.     score += result;
  1644.     result = play_game(two, one, depth, fen); if (result >= 1.98) MI->losses++; else if (result <= 0.02) MI->wins++; else MI->draws++;
  1645.     score += 2.0 - result;
  1646.     return score;
  1647. }
  1648. double match(double * one, double * two, int positions, int depth, GMatchInfo * MI) {
  1649.     double score = 0.0;
  1650.     memset(MI,0,sizeof(GMatchInfo));
  1651.     for (int i = 0; i < positions; i++) {
  1652. #ifndef PGN
  1653.         score += play_position(one, two, depth, Fen[random() % (uint64)opening_positions], MI);
  1654. #else
  1655.         score += play_position(one, two, depth, (char*)&Pos[random() % (uint64)pgn_positions], MI);
  1656. #endif
  1657.     }
  1658.     return (25.0 * (double)score)/(double)(positions);
  1659. }
  1660. int match_los(double * one, double * two, int positions, int chunk_size, int depth, double high, double low, double uh, double ul, GMatchInfo * MI, bool print) {
  1661.     int pos = 0;
  1662.     double score, ratio, stdev, wins, draws, losses, total, tot_score = 0.0;
  1663.     cmd_number++;
  1664.  
  1665.     memset(mstring,0,strlen(mstring));
  1666.     sprintf(mstring,"$ Number=%d Command=match Depth=%d Positions=%d",cmd_number,depth,chunk_size);
  1667.     sprintf(mstring+strlen(mstring)," First="); log_list(mstring,one,active_vars,false);
  1668.     sprintf(mstring+strlen(mstring)," Second="); log_list(mstring,two,active_vars,false);
  1669.     fseek(stdin,0,SEEK_END);
  1670.     fprintf(stdout,"%s\n",mstring);
  1671.  
  1672.     memset(MI,0,sizeof(GMatchInfo));
  1673.     while (pos < positions) {
  1674.         pos += chunk_size;
  1675. start:
  1676.         fgets(mstring,65536,stdin);
  1677.         char * p = strstr(mstring,"Number=");
  1678.         if (p == NULL) goto start;
  1679.         if (atoi(p+7) != cmd_number) goto start;
  1680.         p = strstr(mstring, "Wins="); MI->wins += atoi(p + 5);
  1681.         p = strstr(mstring, "Draws="); MI->draws += atoi(p + 6);
  1682.         p = strstr(mstring, "Losses="); MI->losses += atoi(p + 7);
  1683.         p = strstr(mstring, "Result="); tot_score += atof(p + 7);
  1684.  
  1685.         wins = (double)MI->wins; draws = (double)MI->draws; losses = (double)MI->losses; total = Max(wins + losses,1.0);
  1686. #ifndef WIN_PR
  1687.         score = (100.0 * wins + 50.0 * draws)/(total + draws);
  1688. #else
  1689.         score = tot_score / (double)(pos / chunk_size);
  1690. #endif
  1691.         if (print) fprintf(stdout,"%.2lf (%d positions played): %d-%d-%d\n",score,pos,MI->wins,MI->draws,MI->losses);
  1692.         if (total <= 0.99) continue;
  1693.         ratio = wins/total;
  1694.         stdev = 0.5/sqrt(total);
  1695.         if (high > 0.01) {
  1696.             if (ratio >= 0.5 + stdev * high) return 1;
  1697. #ifdef WIN_PR
  1698.             if (score / 100.0 >= 0.5 + stdev * high) return 1;
  1699. #endif
  1700.         }
  1701.         if (low > 0.01) {
  1702.             if (ratio <= 0.5 - stdev * low) return -1;
  1703. #ifdef WIN_PR
  1704.             if (score / 100.0 <= 0.5 - stdev * low) return -1;
  1705. #endif
  1706.         }
  1707.         if (pos >= positions) break;
  1708.         double remaining = ((2.0 * (double)positions - total - draws) * (wins + losses)) / (total + draws);
  1709.         double target_high = 0.5 * (1.0 + (high / sqrt(total + remaining)));
  1710.         double target_low = 0.5 * (1.0 - (low / sqrt(total + remaining)));
  1711.         double ratio_high = target_high + 0.5 * (uh / sqrt(remaining));
  1712.         double ratio_low = target_low - 0.5 * (ul / sqrt(remaining));
  1713.         if (uh > 0.01) if ((wins + ratio_high * remaining) / (total + remaining) < target_high) return -1;
  1714.         if (ul > 0.01) if ((wins + ratio_low * remaining) / (total + remaining) > target_low) return 1;
  1715.     }
  1716.     return 0;
  1717. }
  1718. void gradient(double * base, double * var, int iter, int pos_per_iter, int depth, double radius, double * grad) {
  1719.     int i, j;
  1720.     double dir[MaxVariables], A[MaxVariables], B[MaxVariables], r;
  1721.     memset(grad,0,active_vars * sizeof(double));
  1722.     for (i = 0; i < iter; i++) {
  1723. #ifndef RANDOM_SPHERICAL
  1724.         for (j = 0; j < active_vars; j++) dir[j] = (Odd(rand()) ? 1.0 : (-1.0))/sqrt(active_vars);
  1725. #else
  1726.         for (j = 0, r = 0.0; j < active_vars; j++) {
  1727.             dir[j] = gaussian(0.0, 1.0);
  1728.             r += dir[j] * dir[j];
  1729.         }
  1730.         r = 1.0/sqrt(Max(r, 0.0000001));
  1731.         for (j = 0; j < active_vars; j++) dir[j] *= r;
  1732. #endif
  1733.         compute_list(A,base,dir,Var,-radius);
  1734.         compute_list(B,base,dir,Var,radius);
  1735.         r = 50.0 - match(A,B,pos_per_iter,depth,MatchInfo);
  1736.         for (j = 0; j < active_vars; j++) grad[j] += r * dir[j];
  1737.     }
  1738.     for (i = 0; i < active_vars; i++) grad[i] /= (double)iter;
  1739. }
  1740. void NormalizeVar(double * base, double * base_var, int depth, int positions, double radius, double target, double * var) {
  1741.     int i, j;
  1742.     double A[MaxVariables], r, value, curr_var;
  1743.  
  1744.     fprintf(stdout,"NormalizeVar(): depth=%d, positions=%d, radius=%.2lf, target=%.2lf\n",depth,positions,radius,target);
  1745.     for (i = 0; i < active_vars; i++) {
  1746.         double_to_double(A,base,active_vars);
  1747.         curr_var = base_var[i];
  1748.         fprintf(stdout,"Variable %d (%.2lf):\n",i,curr_var);
  1749.         for (j = 0; j < 10; j++) {
  1750.             A[i] = base[i] + (radius * curr_var);
  1751.             match_los(base,A,positions,16,depth,0.0,0.0,0.0,0.0,MatchInfo,false);
  1752.             r = Convert(100 * MatchInfo->wins + 50 * (double)MatchInfo->draws,double)/(double)(MatchInfo->wins + MatchInfo->draws + MatchInfo->losses);
  1753.             value = elo_from_ratio(r * 0.01);
  1754.             if (value < target) break;
  1755.             curr_var = curr_var * MinF(sqrt(target/Max(value, 1.0)),1.5);
  1756.             fprintf(stdout,"(%.2lf,%.2lf)\n",value,curr_var);
  1757.             if (curr_var > base_var[i]) {
  1758.                 curr_var = base_var[i];
  1759.                 break;
  1760.             }
  1761.         }
  1762.         var[i] = curr_var;
  1763.         fprintf(stdout, "(%.2lf,%.2lf)\n", value, curr_var);
  1764.     }
  1765.     log_list("var.txt",var,active_vars);
  1766. }
  1767.  
  1768. void Gradient(double * base, double * var, int depth, int iter, int pos_per_iter, int max_positions, double radius, double angle_target, double * grad) {
  1769.     typedef struct {
  1770.         double grad[MaxVariables];
  1771.     } GGradient;
  1772.     GGradient A[4], N[4];
  1773.     double list[MaxVariables], av, angle;
  1774.     int i, j, cnt = 0;
  1775.     cmd_number++;
  1776.  
  1777.     fprintf(stdout,"Gradient(): depth=%d, iter=%d, pos_per_iter=%d, max_positions=%d, radius=%.2lf\n",depth,iter,pos_per_iter,max_positions,radius);
  1778.     memset(A,0,4 * sizeof(GGradient));
  1779.     memset(grad,0,active_vars * sizeof(double));
  1780.  
  1781.     memset(mstring,0,strlen(mstring));
  1782.     sprintf(mstring,"$ Number=%d Command=gradient Depth=%d Iter=%d Positions=%d Radius=%lf Var=",cmd_number,depth,iter,pos_per_iter,radius); log_list(mstring,Var,active_vars,false);
  1783.     sprintf(mstring+strlen(mstring)," Base="); log_list(mstring,Base,active_vars,false);
  1784.     fseek(stdin,0,SEEK_END);
  1785.     fprintf(stdout,"%s\n",mstring);
  1786.  
  1787.     while (cnt < max_positions) {
  1788.         for (j = 0; j < 4; j++) {
  1789. start:
  1790.             fgets(mstring,65536,stdin);
  1791.             char * p = strstr(mstring,"Number=");
  1792.             if (p == NULL) goto start;
  1793.             if (atoi(p+7) != cmd_number) goto start;
  1794.             p = strstr(mstring,"Grad="); read_list(p,list,active_vars);
  1795.  
  1796.             for (i = 0; i < active_vars; i++) {
  1797.                 A[j].grad[i] += list[i];
  1798.                 N[j].grad[i] = A[j].grad[i];
  1799.             }
  1800.             scale_list(N[j].grad,1.0);
  1801.         }
  1802.         for (i = 0; i < active_vars; i++) grad[i] = A[0].grad[i] + A[1].grad[i] + A[2].grad[i] + A[3].grad[i];
  1803.         scale_list(grad,1.0);
  1804.         av = 0.0;
  1805.         for (i = 0; i < 4; i++) for (j = i + 1; j < 4; j++) av += scalar(N[i].grad,N[j].grad,active_vars);
  1806.         av /= 6.0;
  1807.         av = Min(0.99999,Max(-0.99999,av));
  1808.         angle = (acos(av) * 180.0)/3.1415926535;
  1809.         cnt += 4 * pos_per_iter * iter;
  1810.         fprintf(stdout,"%d positions: angle = %.2lf, gradient = ",cnt,angle);
  1811.         log_list(stdout,grad,active_vars);
  1812.         if (angle < angle_target) break;
  1813.         FILE * fgrad = fopen("gradient.txt","w");
  1814.         log_list(fgrad,grad,active_vars);
  1815.         fprintf(fgrad,"%d\n",cnt);
  1816.         fclose(fgrad);
  1817.     }
  1818. }
  1819. void GD(double * base, double * var, int depth, double radius, double min_radius, double angle_target, int max_grad_positions, int max_line_positions, double high, double low, double uh, double ul) {
  1820.     double Grad[MaxVariables], a, br, A[MaxVariables], B[MaxVariables];
  1821.     FILE * fbest = fopen("gd.txt","w"); fclose(fbest);
  1822.  
  1823.     fprintf(stdout,"GD()\n");
  1824.     while (true) {
  1825. start:
  1826.         fbest = fopen("gd.txt","a"); fprintf(fbest,"radius = %.2lf:\n",radius); log_list(fbest,base,active_vars); fclose(fbest);
  1827.         log_list(stdout,base,active_vars);
  1828.         //radius = 2.0; read_list("(0.05,-0.04,-0.00,0.04,0.09,-0.10,-0.00,0.06,-0.14,-0.08,-0.06,0.05,-0.21,-0.10,-0.03,0.04,0.06,-0.01,-0.04,0.06,0.01,-0.05,-0.02,-0.06,-0.05,0.14,0.18,-0.01,-0.01,0.02,-0.11,0.05,-0.00,0.18,-0.15,-0.02,0.03,0.01,-0.06,-0.07,-0.03,0.11,0.13,-0.07,0.06,0.02,-0.01,0.06,-0.07,-0.09,0.01,-0.09,0.13,-0.03,0.04,0.03,-0.04,0.16,0.03,-0.21,-0.01,0.04,-0.03,-0.11,0.00,-0.03,-0.03,-0.11,-0.00,-0.06,0.04,-0.05,0.00,-0.03,-0.12,0.00,-0.07,-0.13,-0.08,0.10,0.11,0.03,0.08,0.12,-0.05,-0.07,-0.01,-0.02,0.08,-0.12,-0.05,0.02,0.03,0.13,-0.08,0.05,0.04,0.02,-0.00,0.06,-0.06,-0.07,-0.00,0.05,-0.09,-0.16,-0.02,-0.07,0.16,-0.24,0.09,0.04,-0.09,0.03,-0.06,0.01,-0.05,0.00,-0.10,-0.02,-0.12,-0.05,-0.05,0.07,0.14,0.16,-0.07,0.03,-0.06,-0.16,-0.03,0.04,-0.04,0.02,-0.12,-0.18,0.01,-0.04,-0.04,-0.18,0.08,0.09,-0.06,-0.00,0.02,-0.03,0.10,0.04,-0.02)", Grad, active_vars);
  1829.         Gradient(base,var,depth,32,1,max_grad_positions,radius,angle_target,Grad);
  1830.         min_radius = Min(radius * 0.45, min_radius);
  1831.         a = radius;
  1832.         while (a >= min_radius) {
  1833.             fprintf(stdout,"Verification %.2lf:\n",a);
  1834.             compute_list(A,base,Grad,var,a);
  1835.             //eval_to_cpp("gd.cpp", A);
  1836.             if (match_los(A,base,max_line_positions,32,depth,high,low,uh,ul,MatchInfo,true) == 1) {
  1837.                 br = a;
  1838.                 a *= 0.6;
  1839.                 compute_list(B,base,Grad,var,a);
  1840.                 double_to_double(base,A,active_vars);
  1841.                 log_list("gd.txt",base,active_vars);
  1842.                 eval_to_cpp("gd.cpp", base);
  1843.                 fprintf(stdout,"New best: "); log_list(stdout,base,active_vars);
  1844.                 fprintf(stdout,"Try %.2lf:\n",a);
  1845.                 if (match_los(B,A,max_line_positions,32,depth,2.0,2.0,2.0,0.0,MatchInfo,true) == 1) {
  1846.                     br = a;
  1847.                     double_to_double(base,B,active_vars);
  1848.                     log_list("gd.txt",base,active_vars);
  1849.                     eval_to_cpp("gd.cpp", base);
  1850.                     fprintf(stdout,"New best: "); log_list(stdout,base,active_vars);
  1851.                 }
  1852.                 if (br < radius * 0.29) radius *= 0.7;
  1853.                 goto start;
  1854.             }
  1855.             a *= 0.7;
  1856.         }
  1857.         radius *= 0.7;
  1858.     }
  1859. }
  1860. void get_command() {
  1861.     enum {mode_grad, mode_match};
  1862.     int mode, depth, positions, number;
  1863.     char * p;
  1864.  
  1865.     if (RecordGames) Buffer[0] = 0;
  1866.     fgets(mstring,65536,stdin);
  1867.     fseek(stdin,0,SEEK_END);
  1868.     p = strstr(mstring,"Command=");
  1869.     if (p == NULL) return;
  1870.     if (!memcmp(p+8,"gradient",8)) mode = mode_grad;
  1871.     else if (!memcmp(p+8,"match",5)) mode = mode_match;
  1872.     else return;
  1873.     p = strstr(mstring,"Number="); number = atoi(p+7);
  1874.     p = strstr(mstring,"Depth="); depth = atoi(p+6);
  1875.     p = strstr(mstring,"Positions="); positions = atoi(p+10);
  1876.     if (mode == mode_grad) {
  1877.         p = strstr(mstring,"Iter="); int iter = atoi(p+5);
  1878.         p = strstr(mstring,"Radius="); int radius = atof(p+7);
  1879.         p = strstr(mstring,"Var="); read_list(p,Var,active_vars);
  1880.         p = strstr(mstring,"Base="); read_list(p,Base,active_vars);
  1881.         gradient(Base,Var,iter,positions,depth,radius,Grad);
  1882.         memset(mstring,0,strlen(mstring));
  1883.         sprintf(mstring,"$ Number=%d Grad=",number); log_list(mstring,Grad,active_vars,true);
  1884.         fprintf(stdout,"%s\n",mstring);
  1885.     } else if (mode == mode_match) {
  1886.         p = strstr(mstring,"First="); read_list(p,FE,active_vars);
  1887.         p = strstr(mstring,"Second="); read_list(p,SE,active_vars);
  1888.         double r = match(FE,SE,positions,depth,MatchInfo);
  1889.         if (RecordGames) {
  1890.             frec = fopen("games.pgn", "a");
  1891.             fprintf(frec, "%s\n", Buffer);
  1892.             fclose(frec);
  1893.         }
  1894.         memset(mstring,0,strlen(mstring));
  1895.         sprintf(mstring,"$ Number=%d Result=%lf Wins=%d Draws=%d Losses=%d",number,r,MatchInfo->wins,MatchInfo->draws,MatchInfo->losses);
  1896.         fprintf(stdout,"%s\n",mstring);
  1897.     } else nodes /= 0;
  1898. }
  1899. int get_mat_index(int wq, int bq, int wr, int br, int wl, int bl, int wd, int bd, int wn, int bn, int wp, int bp) {
  1900.     if (wq > 2 || bq > 2 || wr > 2 || br > 2 || wl > 1 || bl > 1 || wd > 1 || bd > 1 || wn > 2 || bn > 2 || wp > 8 || bp > 8) return -1;
  1901.     return wp*MatWP + bp*MatBP + wn*MatWN + bn*MatBN + wl*MatWL + bl*MatBL + wd*MatWD + bd*MatBD + wr*MatWR + br*MatBR + wq*MatWQ + bq*MatBQ;
  1902. }
  1903. int conj_mat_index(int index, int * conj_symm, int * conj_ld, int * conj_ld_symm) {
  1904.     int wq = index % 3; index /= 3;
  1905.     int bq = index % 3; index /= 3;
  1906.     int wr = index % 3; index /= 3;
  1907.     int br = index % 3; index /= 3;
  1908.     int wl = index % 2; index /= 2;
  1909.     int bl = index % 2; index /= 2;
  1910.     int wd = index % 2; index /= 2;
  1911.     int bd = index % 2; index /= 2;
  1912.     int wn = index % 3; index /= 3;
  1913.     int bn = index % 3; index /= 3;
  1914.     int wp = index % 9; index /= 9;
  1915.     int bp = index;
  1916.     *conj_symm = -1;
  1917.     *conj_ld = -1;
  1918.     *conj_ld_symm = -1;
  1919.     if (wq != bq || wr != br || wl != bd || wd != bl || wn != bn || wp != bp) {
  1920.         *conj_symm = get_mat_index(bq, wq, br, wr, bd, wd, bl, wl, bn, wn, bp, wp);
  1921.         if (wl != wd || bl != bd) {
  1922.             *conj_ld = get_mat_index(wq, bq, wr, br, wd, bd, wl, bl, wn, bn, wp, bp);
  1923.             *conj_ld_symm = get_mat_index(bq, wq, br, wr, bl, wl, bd, wd, bn, wn, bp, wp);
  1924.         }
  1925.     }
  1926.     return *conj_symm;
  1927. }
  1928. void pgn_stat() {
  1929. #define elo_eval_ratio 1.0
  1930. #define PosInRow 6
  1931. #define ratio_from_eval(x) ratio_from_elo(elo_eval_ratio * (x))
  1932. #define ind_from_eval(x) (ratio_from_eval((double)(x)) >= 0.5 ? Max(0, (int)((ratio_from_eval((double)(x)) - 0.5) * 100.0)) : Max(0, (int)((0.5 - ratio_from_eval((double)(x))) * 100.0)))
  1933. #define est_from_ind(x) (Eval[x].score/Max(1.0,(double)Eval[x].cnt))
  1934. #define est_from_eval(x) ((x) >= 0 ? est_from_ind(ind_from_eval(x)) : (1.0 - est_from_ind(ind_from_eval(x))))
  1935.     typedef struct {
  1936.         double score;
  1937.         double est;
  1938.         int cnt;
  1939.     } GStat;
  1940.     GStat Eval[64]; for (int i = 0; i < 64; i++) { Eval[i].cnt = 0; Eval[i].score = 1.0; }
  1941.     GStat * Mat = (GStat*)malloc(TotalMat * sizeof(GStat)); memset(Mat, 0, TotalMat * sizeof(GStat));
  1942.     FILE * fpgn;
  1943.     int iter = 0;
  1944. loop:
  1945.     fpgn = fopen("D:/Development/G3T/games.pgn", "r");
  1946.     if (fpgn == NULL) {
  1947.         fprintf(stdout, "File 'games.pgn' not found\n"); getchar();
  1948.         exit(0);
  1949.     }
  1950.     double stat = 0.0, est = 0.0;
  1951.     int cnt = 0;
  1952.     while (true) {
  1953.         fgets(mstring, 65536, fpgn);
  1954.         if (feof(fpgn)) break;
  1955.         if (strstr(mstring, "FEN")) get_board(mstring + 6);
  1956.         double result;
  1957.         if (strstr(mstring, "Result")) {
  1958.             if (strstr(mstring, "1-0")) result = 1.0;
  1959.             else if (strstr(mstring, "0-1")) result = 0.0;
  1960.             else result = 0.5;
  1961.         }
  1962.         if (strchr(mstring, '[')) continue;
  1963.         if (strlen(mstring) < 100) continue;
  1964.         char * ptr = mstring;
  1965.         int eval[20], nc = 0; memset(eval, 0, 20 * sizeof(int));
  1966.         while (*ptr != 0) {
  1967.             if (!Current->capture && !(Current->move & 0xE000)) nc++;
  1968.             else nc = 0;
  1969.             evaluate();
  1970.             if (nc == PosInRow) {
  1971.                 double ratio = ratio_from_eval((double)eval[PosInRow - 2]);
  1972.                 int r_index;
  1973.                 if (ratio >= 0.5) r_index = Max(0, (int)((ratio - 0.5) * 100.0));
  1974.                 else r_index = Max(0, (int)((0.5 - ratio) * 100.0));
  1975.                 if (Even(iter)) {
  1976.                     Eval[r_index].cnt++;
  1977.                     Eval[r_index].score += (ratio >= 0.5 ? result : (1.0 - result));
  1978.                 }
  1979.  
  1980.                 if (!(Current->material & FlagUnusualMaterial) && Odd(iter)) {
  1981.                     int index = Current->material, conj_symm, conj_ld, conj_ld_symm;
  1982.                     conj_mat_index(index, &conj_symm, &conj_ld, &conj_ld_symm);
  1983.                     Mat[index].cnt++; Mat[index].score += result; Mat[index].est += est_from_eval(eval[PosInRow - 1]);
  1984.                     if (conj_symm >= 0) Mat[conj_symm].cnt++; Mat[conj_symm].score += 1.0 - result; Mat[conj_symm].est += 1.0 - est_from_eval(eval[PosInRow - 1]);
  1985.                     if (conj_ld >= 0) Mat[conj_ld].cnt++; Mat[conj_ld].score += result; Mat[conj_ld].est += est_from_eval(eval[PosInRow - 1]);
  1986.                     if (conj_ld_symm >= 0) Mat[conj_ld_symm].cnt++; Mat[conj_ld_symm].score += 1.0 - result; Mat[conj_ld_symm].est += 1.0 - est_from_eval(eval[PosInRow - 1]);
  1987.                 }
  1988.             }
  1989.             pv_string[0] = *ptr++;
  1990.             pv_string[1] = *ptr++;
  1991.             pv_string[2] = *ptr++;
  1992.             pv_string[3] = *ptr++;
  1993.             if (*ptr == 0 || *ptr == ' ') pv_string[4] = 0;
  1994.             else {
  1995.                 pv_string[4] = *ptr++;
  1996.                 pv_string[5] = 0;
  1997.             }
  1998.             int move = move_from_string(pv_string);
  1999.             if (Current->turn) {
  2000.                 if (!is_legal<1>(move)) break;
  2001.                 do_move<1>(move);
  2002.             } else {
  2003.                 if (!is_legal<0>(move)) break;
  2004.                 do_move<0>(move);
  2005.             }
  2006.             memcpy(Data, Current, sizeof(GData));
  2007.             Current = Data;
  2008.             while (*ptr == ' ') ptr++;
  2009.             for (int i = 19; i >= 1; i--) eval[i] = eval[i - 1];
  2010.             eval[0] = (int)(atof(ptr + 2) * 100.0);
  2011.             ptr = strchr(ptr, '}') + 2;
  2012.         }
  2013.     }
  2014.     fclose(fpgn);
  2015.     if (!iter) {
  2016.         for (int i = 0; i < 64; i++) fprintf(stdout, "ratio(eval x %.2lf) in (%.2lf, %.2lf), score = %.2lf\n", elo_eval_ratio, 50.0 + (double)i, 50.0 + (double)(i + 1), (Eval[i].score * 100.0) / Max(1.0, (double)Eval[i].cnt));
  2017.         iter++;
  2018.         goto loop;
  2019.     }
  2020.     FILE * fmat = fopen("material.txt", "w");
  2021.     fprintf(fmat, "const int MaterialShift[MaterialShiftSize] = {\n");
  2022.     int mat_cnt = 0;
  2023.     for (int index = 0; index < TotalMat; index++) {
  2024.         int cnt = Mat[index].cnt;
  2025.         if (cnt < 64) continue;
  2026.         double ratio = Mat[index].score / (double)cnt;
  2027.         double est = Mat[index].est / (double)cnt;
  2028.         bool flag = (ratio < est);
  2029.         double error = (sqrt(2.0) * 0.5) / sqrt((double)cnt);
  2030.         if (Abs(ratio - est) <= error + 0.01) continue;
  2031.         ratio = ((ratio >= est) ? (ratio - error) : (ratio + error));
  2032.         if (est <= 0.5 && ratio > 0.5) ratio = 0.5000001;
  2033.         if (est >= 0.5 && ratio < 0.5) ratio = 0.4999999;
  2034.         double abs_ratio = ((ratio >= 0.5) ? ratio : (1.0 - ratio));
  2035.         double abs_est = ((est >= 0.5) ? est : (1.0 - est));
  2036.         int curr_ind = 0, new_ind = 0;
  2037.         for (int i = 0; i < 64; i++) {
  2038.             if (Eval[i].score / Max(1.0, (double)Eval[i].cnt) < abs_ratio) new_ind = i;
  2039.             if (Eval[i].score / Max(1.0, (double)Eval[i].cnt) < abs_est) curr_ind = i;
  2040.         }
  2041.         if (Abs(curr_ind - new_ind) <= 1) continue;
  2042.         if (new_ind > curr_ind) new_ind--;
  2043.         else new_ind++;
  2044.         double curr_eval = elo_from_ratio(Eval[curr_ind].score / Max(1.0, (double)Eval[curr_ind].cnt)) / elo_eval_ratio;
  2045.         double new_eval = elo_from_ratio(Eval[new_ind].score / Max(1.0, (double)Eval[new_ind].cnt)) / elo_eval_ratio;
  2046.         int score = (int)Abs(curr_eval - new_eval);
  2047.         if (flag) score = -score;
  2048.         if (Sgn(score) != Sgn(Material[index].score)) score = Sgn(score) * Min(Abs(Material[index].score), Abs(score));
  2049.         if (Abs(score) < 5) continue;
  2050.         mat_cnt++;
  2051.         fprintf(fmat, "%d, %d, ", index, score);
  2052.         if ((mat_cnt % 8) == 0) fprintf(fmat, "\n");
  2053.     }
  2054.     fprintf(fmat, "}; %d\n", mat_cnt * 2);
  2055.     fclose(fmat);
  2056.     fprintf(stdout, "Press any key...\n");
  2057. }
  2058. #endif
  2059.  
  2060. #ifndef W32_BUILD
  2061. __forceinline int lsb(uint64 x) {
  2062.     register unsigned long y;
  2063.     _BitScanForward64(&y, x);
  2064.     return y;
  2065. }
  2066.  
  2067. __forceinline int msb(uint64 x) {
  2068.     register unsigned long y;
  2069.     _BitScanReverse64(&y, x);
  2070.     return y;
  2071. }
  2072.  
  2073. __forceinline int popcnt(uint64 x) {
  2074.     x = x - ((x >> 1) & 0x5555555555555555);
  2075.     x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333);
  2076.     x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f;
  2077.     return (x * 0x0101010101010101) >> 56;
  2078. }
  2079.  
  2080. template <bool HPopCnt> __forceinline int popcount(uint64 x) {
  2081.     return HPopCnt ? _mm_popcnt_u64(x) : popcnt(x);
  2082. }
  2083. #else
  2084. __forceinline int lsb(uint64 x) {
  2085.     _asm {
  2086.         mov eax, dword ptr x[0]
  2087.             test eax, eax
  2088.             jz l_high
  2089.             bsf eax, eax
  2090.             jmp l_ret
  2091.         l_high : bsf eax, dword ptr x[4]
  2092.                  add eax, 20h
  2093.              l_ret :
  2094.     }
  2095. }
  2096.  
  2097. __forceinline int msb(uint64 x) {
  2098.     _asm {
  2099.         mov eax, dword ptr x[4]
  2100.             test eax, eax
  2101.             jz l_low
  2102.             bsr eax, eax
  2103.             add eax, 20h
  2104.             jmp l_ret
  2105.         l_low : bsr eax, dword ptr x[0]
  2106.             l_ret :
  2107.     }
  2108. }
  2109.  
  2110. __forceinline int popcnt(uint64 x) {
  2111.     unsigned int x1, x2;
  2112.     x1 = (unsigned int)(x & 0xFFFFFFFF);
  2113.     x1 -= (x1 >> 1) & 0x55555555;
  2114.     x1 = (x1 & 0x33333333) + ((x1 >> 2) & 0x33333333);
  2115.     x1 = (x1 + (x1 >> 4)) & 0x0F0F0F0F;
  2116.     x2 = (unsigned int)(x >> 32);
  2117.     x2 -= (x2 >> 1) & 0x55555555;
  2118.     x2 = (x2 & 0x33333333) + ((x2 >> 2) & 0x33333333);
  2119.     x2 = (x2 + (x2 >> 4)) & 0x0F0F0F0F;
  2120.     return ((x1 * 0x01010101) >> 24) + ((x2 * 0x01010101) >> 24);
  2121. }
  2122.  
  2123. template <bool HPopCnt> __forceinline int popcount(uint64 x) {
  2124.     return HPopCnt ? (__popcnt((int)x) + __popcnt(x >> 32)) : popcnt(x);
  2125. }
  2126. #endif
  2127.  
  2128. __forceinline int MinF(int x, int y) { return Min(x, y); }
  2129. __forceinline int MaxF(int x, int y) { return Max(x, y); }
  2130. __forceinline double MinF(double x, double y) { return Min(x, y); }
  2131. __forceinline double MaxF(double x, double y) { return Max(x, y); }
  2132.  
  2133. uint64 BMagicAttacks(int i, uint64 occ) {
  2134.     uint64 att = 0;
  2135.     for (uint64 u = BMask[i]; T(u); Cut(u)) if (F(Between[i][lsb(u)] & occ)) att |= Between[i][lsb(u)] | Bit(lsb(u));
  2136.     return att;
  2137. }
  2138.  
  2139. uint64 RMagicAttacks(int i, uint64 occ) {
  2140.     uint64 att = 0;
  2141.     for (uint64 u = RMask[i]; T(u); Cut(u)) if (F(Between[i][lsb(u)] & occ)) att |= Between[i][lsb(u)] | Bit(lsb(u));
  2142.     return att;
  2143. }
  2144.  
  2145. uint16 rand16() {
  2146.     seed = (seed * Convert(6364136223846793005,uint64)) + Convert(1442695040888963407,uint64);
  2147.     return Convert((seed >> 32) & 0xFFFF,uint16);
  2148. }
  2149.  
  2150. uint64 random() {
  2151.     uint64 key = Convert(rand16(),uint64); key <<= 16;
  2152.     key |= Convert(rand16(),uint64); key <<= 16;
  2153.     key |= Convert(rand16(),uint64); key <<= 16;
  2154.     return key | Convert(rand16(),uint64);
  2155. }
  2156.  
  2157. void init_misc() {
  2158.     int i, j, k, l, n;
  2159.     uint64 u;
  2160.  
  2161.     for (i = 0; i < 64; i++) {
  2162.         HLine[i] = VLine[i] = NDiag[i] = SDiag[i] = RMask[i] = BMask[i] = QMask[i] = 0;
  2163.         BMagicMask[i] = RMagicMask[i] = NAtt[i] = SArea[i] = DArea[i] = NArea[i] = 0;
  2164.         PAtt[0][i] = PAtt[1][i] = PMove[0][i] = PMove[1][i] = PWay[0][i] = PWay[1][i] = PSupport[0][i] = PSupport[1][i] = BishopForward[0][i] = BishopForward[1][i] = 0;
  2165.         for (j = 0; j < 64; j++) Between[i][j] = FullLine[i][j] = 0;
  2166.     }
  2167.  
  2168.     for (i = 0; i < 64; i++) for (j = 0; j < 64; j++) if (i != j) {
  2169.         u = Bit(j);
  2170.         if (File(i) == File(j)) VLine[i] |= u;
  2171.         if (Rank(i) == Rank(j)) HLine[i] |= u;
  2172.         if (NDiag(i) == NDiag(j)) NDiag[i] |= u;
  2173.         if (SDiag(i) == SDiag(j)) SDiag[i] |= u;
  2174.         if (Dist(i,j) <= 2) {
  2175.             DArea[i] |= u;
  2176.             if (Dist(i,j) <= 1) SArea[i] |= u;
  2177.             if (Abs(Rank(i)-Rank(j)) + Abs(File(i)-File(j)) == 3) NAtt[i] |= u;
  2178.         }
  2179.         if (j == i + 8) PMove[0][i] |= u;
  2180.         if (j == i - 8) PMove[1][i] |= u;
  2181.         if (Abs(File(i) - File(j)) == 1) {
  2182.             if (Rank(j) >= Rank(i)) {
  2183.                 PSupport[1][i] |= u;
  2184.                 if (Rank(j) - Rank(i) == 1) PAtt[0][i] |= u;
  2185.             }
  2186.             if (Rank(j) <= Rank(i)) {
  2187.                 PSupport[0][i] |= u;
  2188.                 if (Rank(i) - Rank(j) == 1) PAtt[1][i] |= u;
  2189.             }
  2190.         } else if (File(i) == File(j)) {
  2191.             if (Rank(j) > Rank(i)) PWay[0][i] |= u;
  2192.             else PWay[1][i] |= u;
  2193.         }
  2194.     }
  2195.     for (i = 0; i < 64; i++) {
  2196.         RMask[i] = HLine[i] | VLine[i];
  2197.         BMask[i] = NDiag[i] | SDiag[i];
  2198.         QMask[i] = RMask[i] | BMask[i];
  2199.         BMagicMask[i] = BMask[i] & Interior;
  2200.         RMagicMask[i] = RMask[i];
  2201.         if (File(i) > 0) RMagicMask[i] &= ~File[0];
  2202.         if (Rank(i) > 0) RMagicMask[i] &= ~Line[0];
  2203.         if (File(i) < 7) RMagicMask[i] &= ~File[7];
  2204.         if (Rank(i) < 7) RMagicMask[i] &= ~Line[7];
  2205.         for (j = 0; j < 64; j++) if (NAtt[i] & NAtt[j]) Add(NArea[i],j);
  2206.     }
  2207.     for (i = 0; i < 8; i++) {
  2208.         West[i] = 0;
  2209.         East[i] = 0;
  2210.         Forward[0][i] = Forward[1][i] = 0;
  2211.         PIsolated[i] = 0;
  2212.         for (j = 0; j < 8; j++) {
  2213.             if (i < j) Forward[0][i] |= Line[j];
  2214.             else if (i > j) Forward[1][i] |= Line[j];
  2215.             if (i < j) East[i] |= File[j];
  2216.             else if (i > j) West[i] |= File[j];
  2217.         }
  2218.         if (i > 0) PIsolated[i] |= File[i - 1];
  2219.         if (i < 7) PIsolated[i] |= File[i + 1];
  2220.     }
  2221.     for (i = 0; i < 64; i++) {
  2222.         for (u = QMask[i]; T(u); Cut(u)) {
  2223.             j = lsb(u);
  2224.             k = Sgn(Rank(j)-Rank(i));
  2225.             l = Sgn(File(j)-File(i));
  2226.             for (n = i + 8 * k + l; n != j; n += (8 * k + l)) Add(Between[i][j],n);
  2227.         }
  2228.         for (u = BMask[i]; T(u); Cut(u)) {
  2229.             j = lsb(u);
  2230.             FullLine[i][j] = BMask[i] & BMask[j];
  2231.         }
  2232.         for (u = RMask[i]; T(u); Cut(u)) {
  2233.             j = lsb(u);
  2234.             FullLine[i][j] = RMask[i] & RMask[j];
  2235.         }
  2236.         BishopForward[0][i] |= PWay[0][i];
  2237.         BishopForward[1][i] |= PWay[1][i];
  2238.         for (j = 0; j < 64; j++) {
  2239.             if ((PWay[1][j] | Bit(j)) & BMask[i] & Forward[0][Rank(i)]) BishopForward[0][i] |= Bit(j);
  2240.             if ((PWay[0][j] | Bit(j)) & BMask[i] & Forward[1][Rank(i)]) BishopForward[1][i] |= Bit(j);
  2241.         }
  2242.     }
  2243.  
  2244.     for (i = 0; i < 16; i++) for (j = 0; j < 16; j++) {
  2245.         if (j < WhitePawn) MvvLva[i][j] = 0;
  2246.         else if (j < WhiteKnight) MvvLva[i][j] = PawnCaptureMvvLva(i) << 26;
  2247.         else if (j < WhiteLight) MvvLva[i][j] = KnightCaptureMvvLva(i) << 26;
  2248.         else if (j < WhiteRook) MvvLva[i][j] = BishopCaptureMvvLva(i) << 26;
  2249.         else if (j < WhiteQueen) MvvLva[i][j] = RookCaptureMvvLva(i) << 26;
  2250.         else MvvLva[i][j] = QueenCaptureMvvLva(i) << 26;
  2251.     }
  2252.  
  2253.     for (i = 0; i < 256; i++) PieceFromChar[i] = 0;
  2254.     PieceFromChar[66] = 6; PieceFromChar[75] = 14; PieceFromChar[78] = 4; PieceFromChar[80] = 2; PieceFromChar[81] = 12; PieceFromChar[82] = 10;
  2255.     PieceFromChar[98] = 7; PieceFromChar[107] = 15; PieceFromChar[110] = 5; PieceFromChar[112] = 3; PieceFromChar[113] = 13; PieceFromChar[114] = 11;
  2256.  
  2257.     TurnKey = random();
  2258.     for (i = 0; i < 8; i++) EPKey[i] = random();
  2259.     for (i = 0; i < 16; i++) CastleKey[i] = random();
  2260.     for (i = 0; i < 16; i++) for (j = 0; j < 64; j++) {
  2261.         if (i == 0) PieceKey[i][j] = 0;
  2262.         else PieceKey[i][j] = random();
  2263.     }
  2264.     for (i = 0; i < 16; i++) LogDist[i] = (int)(10.0 * log(1.01 + (double)i));
  2265. }
  2266.  
  2267. void init_magic() {
  2268.     int i, j, k, index, bits, bit_list[16];
  2269.     uint64 u;
  2270. #ifdef TUNER
  2271.     MagicAttacks = (uint64*)malloc(magic_size * sizeof(uint64));
  2272. #endif
  2273.     for (i = 0; i < 64; i++) {
  2274.         bits = 64 - BShift[i];
  2275.         for (u = BMagicMask[i], j = 0; T(u); Cut(u), j++) bit_list[j] = lsb(u);
  2276.         for (j = 0; j < Bit(bits); j++) {
  2277.             u = 0;
  2278.             for (k = 0; k < bits; k++)
  2279.                 if (Odd(j >> k)) Add(u,bit_list[k]);
  2280. #ifndef HNI
  2281.             index = Convert(BOffset[i] + ((BMagic[i] * u) >> BShift[i]),int);
  2282. #else
  2283.             index = Convert(BOffset[i] + _pext_u64(u,BMagicMask[i]),int);
  2284. #endif
  2285.             MagicAttacks[index] = BMagicAttacks(i,u);
  2286.         }
  2287.         bits = 64 - RShift[i];
  2288.         for (u = RMagicMask[i], j = 0; T(u); Cut(u), j++) bit_list[j] = lsb(u);
  2289.         for (j = 0; j < Bit(bits); j++) {
  2290.             u = 0;
  2291.             for (k = 0; k < bits; k++)
  2292.                 if (Odd(j >> k)) Add(u,bit_list[k]);
  2293. #ifndef HNI
  2294.             index = Convert(ROffset[i] + ((RMagic[i] * u) >> RShift[i]),int);
  2295. #else
  2296.             index = Convert(ROffset[i] + _pext_u64(u,RMagicMask[i]),int);
  2297. #endif
  2298.              MagicAttacks[index] = RMagicAttacks(i,u);
  2299.         }  
  2300.     }
  2301. }
  2302.  
  2303. void gen_kpk() {
  2304.     int turn, wp, wk, bk, to, cnt, old_cnt, un;
  2305.     uint64 bwp, bwk, bbk, u;
  2306.     uint8 Kpk_gen[2][64][64][64];
  2307.  
  2308.     memset(Kpk_gen, 0, 2 * 64 * 64 * 64);
  2309.  
  2310.     cnt = 0;
  2311.     old_cnt = 1;
  2312. start:
  2313.     if (cnt == old_cnt) goto end;
  2314.     old_cnt = cnt;
  2315.     cnt = 0;
  2316.     for (turn = 0; turn < 2; turn++) {
  2317.         for (wp = 0; wp < 64; wp++) {
  2318.             for (wk = 0; wk < 64; wk++) {
  2319.                 for (bk = 0; bk < 64; bk++) {
  2320.                     if (Kpk_gen[turn][wp][wk][bk]) continue;
  2321.                     cnt++;
  2322.                     if (wp < 8 || wp >= 56) goto set_draw;
  2323.                     if (wp == wk || wk == bk || bk == wp) goto set_draw;
  2324.                     bwp = Bit(wp);
  2325.                     bwk = Bit(wk);
  2326.                     bbk = Bit(bk);
  2327.                     if (PAtt[White][wp] & bbk) {
  2328.                         if (turn == White) goto set_draw;
  2329.                         else if (F(SArea[wk] & bwp)) goto set_draw;
  2330.                     }
  2331.                     un = 0;
  2332.                     if (turn == Black) {
  2333.                         u = SArea[bk] & (~(SArea[wk] | PAtt[White][wp]));
  2334.                         if (F(u)) goto set_draw;
  2335.                         for (; T(u); Cut(u)) {
  2336.                             to = lsb(u);
  2337.                             if (Kpk_gen[turn ^ 1][wp][wk][to] == 1) goto set_draw;
  2338.                             else if (Kpk_gen[turn ^ 1][wp][wk][to] == 0) un++;
  2339.                         }
  2340.                         if (F(un)) goto set_win;
  2341.                     }
  2342.                     else {
  2343.                         for (u = SArea[wk] & (~(SArea[bk] | bwp)); T(u); Cut(u)) {
  2344.                             to = lsb(u);
  2345.                             if (Kpk_gen[turn ^ 1][wp][to][bk] == 2) goto set_win;
  2346.                             else if (Kpk_gen[turn ^ 1][wp][to][bk] == 0) un++;
  2347.                         }
  2348.                         to = wp + 8;
  2349.                         if (to != wk && to != bk) {
  2350.                             if (to >= 56) {
  2351.                                 if (F(SArea[to] & bbk)) goto set_win;
  2352.                                 if (SArea[to] & bwk) goto set_win;
  2353.                             }
  2354.                             else {
  2355.                                 if (Kpk_gen[turn ^ 1][to][wk][bk] == 2) goto set_win;
  2356.                                 else if (Kpk_gen[turn ^ 1][to][wk][bk] == 0) un++;
  2357.                                 if (to < 24) {
  2358.                                     to += 8;
  2359.                                     if (to != wk && to != bk) {
  2360.                                         if (Kpk_gen[turn ^ 1][to][wk][bk] == 2) goto set_win;
  2361.                                         else if (Kpk_gen[turn ^ 1][to][wk][bk] == 0) un++;
  2362.                                     }
  2363.                                 }
  2364.                             }
  2365.                         }
  2366.                         if (F(un)) goto set_draw;
  2367.                     }
  2368.                     continue;
  2369.                 set_draw:
  2370.                     Kpk_gen[turn][wp][wk][bk] = 1;
  2371.                     continue;
  2372.                 set_win:
  2373.                     Kpk_gen[turn][wp][wk][bk] = 2;
  2374.                     continue;
  2375.                 }
  2376.             }
  2377.         }
  2378.     }
  2379.     if (cnt) goto start;
  2380. end:
  2381.     for (turn = 0; turn < 2; turn++) {
  2382.         for (wp = 0; wp < 64; wp++) {
  2383.             for (wk = 0; wk < 64; wk++) {
  2384.                 Kpk[turn][wp][wk] = 0;
  2385.                 for (bk = 0; bk < 64; bk++) {
  2386.                     if (Kpk_gen[turn][wp][wk][bk] == 2) Kpk[turn][wp][wk] |= Bit(bk);
  2387.                 }
  2388.             }
  2389.         }
  2390.     }
  2391. }
  2392.  
  2393. void init_pst() {
  2394.     int i, j, k, op, eg, index, r, f, d, e, distQ[4], distL[4], distM[2];
  2395.     memset(Pst,0,16 * 64 * sizeof(int));
  2396.  
  2397.     for (i = 0; i < 64; i++) {
  2398.         r = Rank(i);
  2399.         f = File(i);
  2400.         d = Abs(f - r);
  2401.         e = Abs(f + r - 7);
  2402.         distQ[0] = DistC[f] * DistC[f]; distL[0] = DistC[f];
  2403.         distQ[1] = DistC[r] * DistC[r]; distL[1] = DistC[r];
  2404.         distQ[2] = RankR[d] * RankR[d] + RankR[e] * RankR[e]; distL[2] = RankR[d] + RankR[e];
  2405.         distQ[3] = RankR[r] * RankR[r]; distL[3] = RankR[r];
  2406.         distM[0] = DistC[f] * DistC[r]; distM[1] = DistC[f] * RankR[r];
  2407.         for (j = 2; j < 16; j += 2) {
  2408.             index = PieceType[j];
  2409.             op = eg = 0;
  2410.             for (k = 0; k < 2; k++) {
  2411.                 op += Av(PstQuadMixedWeights, 4, index, (k * 2)) * distM[k];
  2412.                 eg += Av(PstQuadMixedWeights, 4, index, (k * 2) + 1) * distM[k];
  2413.             }
  2414.             for (k = 0; k < 4; k++) {
  2415.                 op += Av(PstQuadWeights,8,index,(k * 2)) * distQ[k];
  2416.                 eg += Av(PstQuadWeights,8,index,(k * 2) + 1) * distQ[k];
  2417.                 op += Av(PstLinearWeights,8,index,(k * 2)) * distL[k];
  2418.                 eg += Av(PstLinearWeights,8,index,(k * 2) + 1) * distL[k];
  2419.             }
  2420.             Pst(j,i) = Compose(op/64, eg/64);
  2421.         }
  2422.     }
  2423.  
  2424.     Pst(WhiteKnight,56) -= Compose(100, 0);
  2425.     Pst(WhiteKnight,63) -= Compose(100, 0);
  2426.     for (i = 0; i < 64; i++) {
  2427.         for (j = 3; j < 16; j+=2) {
  2428.             op = Opening(Pst(j-1,63-i));
  2429.             eg = Endgame(Pst(j-1,63-i));
  2430.             Pst(j,i) = Compose(-op,-eg);
  2431.         }
  2432.     }
  2433.     Current->pst = 0;
  2434.     for (i = 0; i < 64; i++)
  2435.     if (Square(i)) Current->pst += Pst(Square(i),i);
  2436. }
  2437.  
  2438. void init_eval() {
  2439.     int i, j, k, index;
  2440.     memset(Mobility,0,4 * 32 * sizeof(int));
  2441.     for (i = 0; i < 4; i++) for (j = 0; j < 32; j++) {
  2442.         index = i * 2;
  2443.         double op = (double)(Av(MobilityLinear,8,0,index) * j) + log(1.01 + (double)j) * (double)(Av(MobilityLog,8,0,index));
  2444.         index = i * 2 + 1;
  2445.         double eg = (double)(Av(MobilityLinear,8,0,index) * j) + log(1.01 + (double)j) * (double)(Av(MobilityLog,8,0,index));
  2446.         Mobility[i][j] = Compose((int)(op/64.0),(int)(eg/64.0));
  2447.     }
  2448.    
  2449.     for (i = 0; i < 3; i++) for (j = 7; j >= 0; j--) {
  2450.         Shelter[i][j] = 0;
  2451.         if (j > 1) for (k = 1; k < Min(j, 5); k++) Shelter[i][j] += Av(ShelterValue, 0, 0, (i * 5) + k - 1);
  2452.         if (!j) Shelter[i][j] = Shelter[i][7] + Av(ShelterValue, 0, 0, (i * 5) + 4);
  2453.     }
  2454.  
  2455.     for (i = 0; i < 4; i++) {
  2456.         StormBlocked[i] = ((Sa(StormQuad, StormBlockedMul) * i * i) + (Sa(StormLinear, StormBlockedMul) * (i + 1))) / 100;
  2457.         StormShelterAtt[i] = ((Sa(StormQuad, StormShelterAttMul) * i * i) + (Sa(StormLinear, StormShelterAttMul) * (i + 1))) / 100;
  2458.         StormConnected[i] = ((Sa(StormQuad, StormConnectedMul) * i * i) + (Sa(StormLinear, StormConnectedMul) * (i + 1))) / 100;
  2459.         StormOpen[i] = ((Sa(StormQuad, StormOpenMul) * i * i) + (Sa(StormLinear, StormOpenMul) * (i + 1))) / 100;
  2460.         StormFree[i] = ((Sa(StormQuad, StormFreeMul) * i * i) + (Sa(StormLinear, StormFreeMul) * (i + 1))) / 100;
  2461.     }
  2462.  
  2463.     for (i = 0; i < 8; i++) {
  2464.         int l = Max(i - 2, 0);
  2465.         int q = l * l;
  2466.         PasserGeneral[i] = Compose16(Av(PasserQuad, 2, 0, 0) * q + Av(PasserLinear, 2, 0, 0) * l, Av(PasserQuad, 2, 0, 1) * q + Av(PasserLinear, 2, 0, 1) * l);
  2467.         PasserBlocked[i] = Compose16(Av(PasserQuad, 2, 1, 0) * q + Av(PasserLinear, 2, 1, 0) * l, Av(PasserQuad, 2, 1, 1) * q + Av(PasserLinear, 2, 1, 1) * l);
  2468.         PasserFree[i] = Compose16(Av(PasserQuad, 2, 2, 0) * q + Av(PasserLinear, 2, 2, 0) * l, Av(PasserQuad, 2, 2, 1) * q + Av(PasserLinear, 2, 2, 1) * l);
  2469.         PasserSupported[i] = Compose16(Av(PasserQuad, 2, 3, 0) * q + Av(PasserLinear, 2, 3, 0) * l, Av(PasserQuad, 2, 3, 1) * q + Av(PasserLinear, 2, 3, 1) * l);
  2470.         PasserProtected[i] = Compose16(Av(PasserQuad, 2, 4, 0) * q + Av(PasserLinear, 2, 4, 0) * l, Av(PasserQuad, 2, 4, 1) * q + Av(PasserLinear, 2, 4, 1) * l);
  2471.         PasserConnected[i] = Compose16(Av(PasserQuad, 2, 5, 0) * q + Av(PasserLinear, 2, 5, 0) * l, Av(PasserQuad, 2, 5, 1) * q + Av(PasserLinear, 2, 5, 1) * l);
  2472.         PasserOutside[i] = Compose16(Av(PasserQuad, 2, 6, 0) * q + Av(PasserLinear, 2, 6, 0) * l, Av(PasserQuad, 2, 6, 1) * q + Av(PasserLinear, 2, 6, 1) * l);
  2473.         PasserCandidate[i] = Compose16(Av(PasserQuad, 2, 7, 0) * q + Av(PasserLinear, 2, 7, 0) * l, Av(PasserQuad, 2, 7, 1) * q + Av(PasserLinear, 2, 7, 1) * l);
  2474.         PasserClear[i] = Compose16(Av(PasserQuad, 2, 8, 0) * q + Av(PasserLinear, 2, 8, 0) * l, Av(PasserQuad, 2, 8, 1) * q + Av(PasserLinear, 2, 8, 1) * l);
  2475.  
  2476.         PasserAtt[i] = Av(PasserAttDefQuad, 2, 0, 0) * q + Av(PasserAttDefLinear, 2, 0, 0) * l;
  2477.         PasserDef[i] = Av(PasserAttDefQuad, 2, 1, 0) * q + Av(PasserAttDefLinear, 2, 1, 0) * l;
  2478.         PasserAttLog[i] = Av(PasserAttDefQuad, 2, 0, 1) * q + Av(PasserAttDefLinear, 2, 0, 1) * l;
  2479.         PasserDefLog[i] = Av(PasserAttDefQuad, 2, 1, 1) * q + Av(PasserAttDefLinear, 2, 1, 1) * l;
  2480.     }
  2481. }
  2482.  
  2483. void calc_material(int index) {
  2484.     int pawns[2], knights[2], light[2], dark[2], rooks[2], queens[2], bishops[2], major[2], minor[2], tot[2], mat[2], mul[2], quad[2], score, phase, me, i = index;
  2485. #ifdef TUNER
  2486.     Material[index].generation = generation;
  2487. #endif
  2488.     queens[White] = i % 3; i /= 3;
  2489.     queens[Black] = i % 3; i /= 3;
  2490.     rooks[White] = i % 3; i /= 3;
  2491.     rooks[Black] = i % 3; i /= 3;
  2492.     light[White] = i % 2; i /= 2;
  2493.     light[Black] = i % 2; i /= 2;
  2494.     dark[White] = i % 2; i /= 2;
  2495.     dark[Black] = i % 2; i /= 2;
  2496.     knights[White] = i % 3; i /= 3;
  2497.     knights[Black] = i % 3; i /= 3;
  2498.     pawns[White] = i % 9; i /= 9;
  2499.     pawns[Black] = i % 9;
  2500.     for (me = 0; me < 2; me++) {
  2501.         bishops[me] = light[me] + dark[me];
  2502.         major[me] = rooks[me] + queens[me];
  2503.         minor[me] = bishops[me] + knights[me];
  2504.         tot[me] = 3 * minor[me] + 5 * rooks[me] + 9 * queens[me];
  2505.         mat[me] = mul[me] = 32;
  2506.         quad[me] = 0;
  2507.     }
  2508.     score = (SeeValue[WhitePawn] + Av(MatLinear, 0, 0, 0)) * (pawns[White] - pawns[Black]) + (SeeValue[WhiteKnight] + Av(MatLinear, 0, 0, 1)) * (knights[White] - knights[Black])
  2509.         + (SeeValue[WhiteLight] + Av(MatLinear, 0, 0, 2)) * (bishops[White] - bishops[Black]) + (SeeValue[WhiteRook] + Av(MatLinear, 0, 0, 3)) * (rooks[White] - rooks[Black])
  2510.         + (SeeValue[WhiteQueen] + Av(MatLinear, 0, 0, 4)) * (queens[White] - queens[Black]) + 50 * ((bishops[White] / 2) - (bishops[Black] / 2));
  2511.     phase = Phase[PieceType[WhitePawn]] * (pawns[White] + pawns[Black]) + Phase[PieceType[WhiteKnight]] * (knights[White] + knights[Black])
  2512.         + Phase[PieceType[WhiteLight]] * (bishops[White] + bishops[Black]) + Phase[PieceType[WhiteRook]] * (rooks[White] + rooks[Black])
  2513.         + Phase[PieceType[WhiteQueen]] * (queens[White] + queens[Black]);
  2514.     Material[index].phase = Min((Max(phase - PhaseMin, 0) * 128) / (PhaseMax - PhaseMin), 128);
  2515.  
  2516.     int special = 0;
  2517.     for (me = 0; me < 2; me++) {
  2518.         if (queens[me] == queens[opp]) {
  2519.             if (rooks[me] - rooks[opp] == 1) {
  2520.                 if (knights[me] == knights[opp] && bishops[opp] - bishops[me] == 1) IncV(special, Ca(MatSpecial, MatRB));
  2521.                 else if (bishops[me] == bishops[opp] && knights[opp] - knights[me] == 1) IncV(special, Ca(MatSpecial, MatRN));
  2522.                 else if (knights[me] == knights[opp] && bishops[opp] - bishops[me] == 2) DecV(special, Ca(MatSpecial, MatBBR));
  2523.                 else if (bishops[me] == bishops[opp] && knights[opp] - knights[me] == 2) DecV(special, Ca(MatSpecial, MatNNR));
  2524.                 else if (bishops[opp] - bishops[me] == 1 && knights[opp] - knights[me] == 1) DecV(special, Ca(MatSpecial, MatBNR));
  2525.             } else if (rooks[me] == rooks[opp] && minor[me] - minor[opp] == 1) IncV(special, Ca(MatSpecial, MatM));
  2526.         } else if (queens[me] - queens[opp] == 1) {
  2527.             if (rooks[opp] - rooks[me] == 2 && minor[opp] - minor[me] == 0) IncV(special, Ca(MatSpecial, MatQRR));
  2528.             else if (rooks[opp] - rooks[me] == 1 && knights[opp] == knights[me] && bishops[opp] - bishops[me] == 1) IncV(special, Ca(MatSpecial, MatQRB));
  2529.             else if (rooks[opp] - rooks[me] == 1 && knights[opp] - knights[me] == 1 && bishops[opp] == bishops[me]) IncV(special, Ca(MatSpecial, MatQRN));
  2530.             else if ((major[opp] + minor[opp]) - (major[me] + minor[me]) >= 2) IncV(special, Ca(MatSpecial, MatQ3));
  2531.         }
  2532.     }
  2533.     score += (Opening(special) * Material[index].phase + Endgame(special) * (128 - (int)Material[index].phase)) / 128;
  2534.  
  2535.     for (me = 0; me < 2; me++) {
  2536.         quad[me] += pawns[me] * (pawns[me] * TrAv(MatQuadMe, 5, 0, 0) + knights[me] * TrAv(MatQuadMe, 5, 0, 1)
  2537.             + bishops[me] * TrAv(MatQuadMe, 5, 0, 2) + rooks[me] * TrAv(MatQuadMe, 5, 0, 3) + queens[me] * TrAv(MatQuadMe, 5, 0, 4));
  2538.         quad[me] += knights[me] * (knights[me] * TrAv(MatQuadMe, 5, 1, 0)
  2539.             + bishops[me] * TrAv(MatQuadMe, 5, 1, 1) + rooks[me] * TrAv(MatQuadMe, 5, 1, 2) + queens[me] * TrAv(MatQuadMe, 5, 1, 3));
  2540.         quad[me] += bishops[me] * (bishops[me] * TrAv(MatQuadMe, 5, 2, 0) + rooks[me] * TrAv(MatQuadMe, 5, 2, 1) + queens[me] * TrAv(MatQuadMe, 5, 2, 2));
  2541.  
  2542.         quad[me] += rooks[me] * (rooks[me] * TrAv(MatQuadMe, 5, 3, 0) + queens[me] * TrAv(MatQuadMe, 5, 3, 1));
  2543.         quad[me] += pawns[me] * (knights[opp] * TrAv(MatQuadOpp, 4, 0, 0)
  2544.             + bishops[opp] * TrAv(MatQuadOpp, 4, 0, 1) + rooks[opp] * TrAv(MatQuadOpp, 4, 0, 2) + queens[opp] * TrAv(MatQuadOpp, 4, 0, 3));
  2545.         quad[me] += knights[me] * (bishops[opp] * TrAv(MatQuadOpp, 4, 1, 0) + rooks[opp] * TrAv(MatQuadOpp, 4, 1, 1) + queens[opp] * TrAv(MatQuadOpp, 4, 1, 2));
  2546.         quad[me] += bishops[me] * (rooks[opp] * TrAv(MatQuadOpp, 4, 2, 0) + queens[opp] * TrAv(MatQuadOpp, 4, 2, 1));
  2547.         quad[me] += rooks[me] * queens[opp] * TrAv(MatQuadOpp, 4, 3, 0);
  2548.  
  2549.         if (bishops[me] >= 2) quad[me] += pawns[me] * Av(BishopPairQuad, 0, 0, 0) + knights[me] * Av(BishopPairQuad, 0, 0, 1) + rooks[me] * Av(BishopPairQuad, 0, 0, 2)
  2550.             + queens[me] * Av(BishopPairQuad, 0, 0, 3) + pawns[opp] * Av(BishopPairQuad, 0, 0, 4) + knights[opp] * Av(BishopPairQuad, 0, 0, 5)
  2551.             + bishops[opp] * Av(BishopPairQuad, 0, 0, 6) + rooks[opp] * Av(BishopPairQuad, 0, 0, 7) + queens[opp] * Av(BishopPairQuad, 0, 0, 8);
  2552.     }
  2553.     score += (quad[White] - quad[Black]) / 100;
  2554.  
  2555.     for (me = 0; me < 2; me++) {
  2556.         if (tot[me] - tot[opp] <= 3) {
  2557.             if (!pawns[me]) {
  2558.                 if (tot[me] <= 3) mul[me] = 0;
  2559.                 if (tot[me] == tot[opp] && major[me] == major[opp] && minor[me] == minor[opp]) mul[me] = major[me] + minor[me] <= 2 ? 0 : (major[me] + minor[me] <= 3 ? 16 : 32);
  2560.                 else if (minor[me] + major[me] <= 2) {
  2561.                     if (bishops[me] < 2) mat[me] = (bishops[me] && rooks[me]) ? 8 : 1;
  2562.                     else if (bishops[opp] + rooks[opp] >= 1) mat[me] = 1;
  2563.                     else mat[me] = 32;
  2564.                 } else if (tot[me] - tot[opp] < 3 && minor[me] + major[me] - minor[opp] - major[opp] <= 1) mat[me] = 4;
  2565.                 else if (minor[me] + major[me] <= 3) mat[me] = 8 * (1 + bishops[me]);
  2566.                 else mat[me] = 8 * (2 + bishops[me]);
  2567.             }
  2568.             if (pawns[me] <= 1) {
  2569.                 mul[me] = Min(28, mul[me]);
  2570.                 if (rooks[me] == 1 && queens[me] + minor[me] == 0 && rooks[opp] == 1) mat[me] = Min(23, mat[me]);
  2571.             }
  2572.         }
  2573.         if (!major[me]) {
  2574.             if (!minor[me]) {
  2575.                 if (!tot[me] && pawns[me] < pawns[opp]) DecV(score, (pawns[opp] - pawns[me]) * SeeValue[WhitePawn]);
  2576.             } else if (minor[me] == 1) {
  2577.                 if (pawns[me] <= 1 && minor[opp] >= 1) mat[me] = 1;
  2578.                 if (bishops[me] == 1) {
  2579.                     if (minor[opp] == 1 && bishops[opp] == 1 && light[me] != light[opp]) {
  2580.                         mul[me] = Min(mul[me], 15);
  2581.                         if (pawns[me] - pawns[opp] <= 1) mul[me] = Min(mul[me], 11);
  2582.                     }
  2583.                 }
  2584.             } else if (!pawns[me] && knights[me] == 2 && !bishops[me]) {
  2585.                 if (!tot[opp] && pawns[opp]) mat[me] = 6;
  2586.                 else mul[me] = 0;
  2587.             }
  2588.         }
  2589.         if (!mul[me]) mat[me] = 0;
  2590.         if (mat[me] <= 1 && tot[me] != tot[opp]) mul[me] = Min(mul[me], 8);
  2591.     }
  2592.     if (bishops[White] == 1 && bishops[Black] == 1 && light[White] != light[Black]) {
  2593.         mul[White] = Min(mul[White], 24 + 2 * (knights[Black] + major[Black]));
  2594.         mul[Black] = Min(mul[Black], 24 + 2 * (knights[White] + major[White]));
  2595.     } else if (!minor[White] && !minor[Black] && major[White] == 1 && major[Black] == 1 && rooks[White] == rooks[Black]) {
  2596.         mul[White] = Min(mul[White], 25);
  2597.         mul[Black] = Min(mul[Black], 25);
  2598.     }
  2599.     for (me = 0; me < 2; me++) {
  2600.         Material[index].mul[me] = mul[me];
  2601.         Material[index].pieces[me] = major[me] + minor[me];
  2602.     }
  2603.     if (score > 0) score = (score * mat[White]) / 32;
  2604.     else score = (score * mat[Black]) / 32;
  2605.     Material[index].score = score;
  2606.     for (me = 0; me < 2; me++) {
  2607.         if (major[me] == 0 && minor[me] == bishops[me] && minor[me] <= 1) Material[index].flags |= VarC(FlagSingleBishop, me);
  2608.         if (((major[me] == 0 || minor[me] == 0) && major[me] + minor[me] <= 1) || major[opp] + minor[opp] == 0
  2609.             || (!pawns[me] && major[me] == rooks[me] && major[me] == 1 && minor[me] == bishops[me] && minor[me] == 1 && rooks[opp] == 1 && !minor[opp] && !queens[opp])) Material[index].flags |= VarC(FlagCallEvalEndgame, me);
  2610.     }
  2611. }
  2612.  
  2613. void init_material() {
  2614. #ifdef TUNER
  2615.     Material = (GMaterial*)malloc(TotalMat * sizeof(GMaterial));
  2616. #endif
  2617.     memset(Material,0,TotalMat * sizeof(GMaterial));
  2618.     for (int index = 0; index < TotalMat; index++) calc_material(index);
  2619. }
  2620.  
  2621. void init_hash() {
  2622. #ifdef TUNER
  2623.     return;
  2624. #endif
  2625.     char name[256];
  2626.     sint64 size = (hash_size * sizeof(GEntry));
  2627.     sprintf(name, "GULL_HASH_%d", WinParId);
  2628.     int initialized = 0;
  2629.     if (parent && HASH != NULL) {
  2630.         initialized = 1;
  2631.         UnmapViewOfFile(Hash);
  2632.         CloseHandle(HASH);
  2633.     }
  2634.     if (parent) {
  2635.         if (!LargePages) goto no_lp;
  2636. #ifndef LARGE_PAGES
  2637.         goto no_lp;
  2638. #endif
  2639.         typedef int(*GETLARGEPAGEMINIMUM)(void);
  2640.         GETLARGEPAGEMINIMUM pGetLargePageMinimum;
  2641.         HINSTANCE hDll = LoadLibrary(TEXT("kernel32.dll"));
  2642.         if (hDll == NULL) goto no_lp;
  2643.         pGetLargePageMinimum = (GETLARGEPAGEMINIMUM)GetProcAddress(hDll, "GetLargePageMinimum");
  2644.         if (pGetLargePageMinimum == NULL) goto no_lp;
  2645.         int min_page_size = (*pGetLargePageMinimum)();
  2646.         if (size < min_page_size) size = min_page_size;
  2647.         if (!initialized) {
  2648.             TOKEN_PRIVILEGES tp;
  2649.             HANDLE hToken;
  2650.             OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
  2651.             LookupPrivilegeValue(NULL, "SeLockMemoryPrivilege", &tp.Privileges[0].Luid);
  2652.             tp.PrivilegeCount = 1;
  2653.             tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  2654.             AdjustTokenPrivileges(hToken, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
  2655.         }
  2656.         HASH = NULL;
  2657.         HASH = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_COMMIT | SEC_LARGE_PAGES, size >> 32, size & 0xFFFFFFFF, name);
  2658.         if (HASH != NULL) {
  2659.             fprintf(stdout, "Large page hash\n");
  2660.             goto hash_allocated;
  2661.         }
  2662.     no_lp:
  2663.         HASH = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, size >> 32, size & 0xFFFFFFFF, name);
  2664.     } else HASH = OpenFileMapping(FILE_MAP_ALL_ACCESS, 0, name);
  2665. hash_allocated:
  2666.     Hash = (GEntry*)MapViewOfFile(HASH, FILE_MAP_ALL_ACCESS, 0, 0, size);
  2667.     if (parent) memset(Hash, 0, size);
  2668.     hash_mask = hash_size - 4;
  2669. }
  2670.  
  2671. void init_shared() {
  2672. #ifdef TUNER
  2673.     return;
  2674. #endif
  2675.     char name[256];
  2676.     sint64 size = SharedPVHashOffset + pv_hash_size * sizeof(GPVEntry);
  2677.     sprintf(name, "GULL_SHARED_%d", WinParId);
  2678.     if (parent && SHARED != NULL) {
  2679.         UnmapViewOfFile(Smpi);
  2680.         CloseHandle(SHARED);
  2681.     }
  2682.     if (parent) SHARED = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, name);
  2683.     else SHARED = OpenFileMapping(FILE_MAP_ALL_ACCESS, 0, name);
  2684.     Smpi = (GSMPI*)MapViewOfFile(SHARED, FILE_MAP_ALL_ACCESS, 0, 0, size);
  2685.     if (parent) memset(Smpi, 0, size);
  2686.     Material = (GMaterial*)(((char*)Smpi) + SharedMaterialOffset);
  2687.     MagicAttacks = (uint64*)(((char*)Smpi) + SharedMagicOffset);
  2688.     PVHash = (GPVEntry*)(((char*)Smpi) + SharedPVHashOffset);
  2689.     if (parent) memset(PVHash, 0, pv_hash_size * sizeof(GPVEntry));
  2690. }
  2691.  
  2692. void init() {
  2693.     init_shared();
  2694.     init_misc();
  2695.     if (parent) init_magic();
  2696.     for (int i = 0; i < 64; i++) {
  2697.         BOffsetPointer[i] = MagicAttacks + BOffset[i];
  2698.         ROffsetPointer[i] = MagicAttacks + ROffset[i];
  2699.     }
  2700.     gen_kpk();
  2701.     init_pst();
  2702.     init_eval();
  2703.     if (parent) init_material();
  2704. #ifdef EXPLAIN_EVAL
  2705.     memset(GullCppFile, 0, 16384 * 256);
  2706.     FILE * fcpp; fcpp = fopen(GullCpp, "r");
  2707.     for (cpp_length = 0; cpp_length < 16384; cpp_length++) {
  2708.         if (feof(fcpp)) break;
  2709.         fgets(mstring, 65536, fcpp);
  2710.         memcpy(GullCppFile[cpp_length], mstring, 256);
  2711.         if (!strchr(GullCppFile[cpp_length], '\n')) GullCppFile[cpp_length][255] = '\n';
  2712.         char * p; for (p = GullCppFile[cpp_length]; (*p) == '\t'; p++);
  2713.         strcpy(mstring, p); strcpy(GullCppFile[cpp_length], mstring);
  2714.     }
  2715.     cpp_length--;
  2716.     fclose(fcpp);
  2717. #endif
  2718. }
  2719.  
  2720. void init_search(int clear_hash) {
  2721.     memset(History,1,16 * 64 * sizeof(sint16));
  2722.     memset(Delta,0,16 * 4096 * sizeof(sint16));
  2723.     memset(Ref,0,16 * 64 * sizeof(GRef));
  2724.     memset(Data + 1, 0, 127 * sizeof(GData));
  2725.     if (clear_hash) {
  2726.         date = 0;
  2727.         date = 1;
  2728.         memset(Hash,0,hash_size * sizeof(GEntry));
  2729.         memset(PVHash,0,pv_hash_size * sizeof(GPVEntry));
  2730.     }
  2731.     get_board("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");
  2732.     nodes = 0;
  2733.     best_move = best_score = 0;
  2734.     LastTime = LastValue = LastExactValue = InstCnt = 0;
  2735.     LastSpeed = 0;
  2736.     PVN = 1;
  2737.     Infinite = 1;
  2738.     SearchMoves = 0;
  2739.     TimeLimit1 = TimeLimit2 = 0;
  2740.     Stop = Searching = 0;
  2741.     if (MaxPrN > 1) ZERO_BIT_64(Smpi->searching, 0);
  2742.     DepthLimit = 128;
  2743.     LastDepth = 128;
  2744.     Print = 1;
  2745.     memset(CurrentSI,0,sizeof(GSearchInfo));
  2746.     memset(BaseSI,0,sizeof(GSearchInfo));
  2747. #ifdef CPU_TIMING
  2748.     GlobalTime[GlobalTurn] = UciBaseTime;
  2749.     GlobalInc[GlobalTurn] = UciIncTime;
  2750. #endif
  2751. }
  2752.  
  2753. void setup_board() {
  2754.     int i;
  2755.     uint64 occ;
  2756.     GEntry * Entry;
  2757.     GPVEntry * PVEntry;
  2758.  
  2759.     occ = 0;
  2760.     sp = 0;
  2761.     date++;
  2762.     if (date > 0x8000) { // musn't ever happen
  2763.         date = 2;
  2764.         // now GUI must wait for readyok... we have plenty of time :)
  2765.         for (Entry = Hash, i = 0; i < hash_size; i++, Entry++) Entry->date = 1;
  2766.         for (PVEntry = PVHash, i = 0; i < pv_hash_size; i++, PVEntry++) PVEntry->date = 1;
  2767.     }
  2768.     Current->material = 0;
  2769.     Current->pst = 0;
  2770.     Current->key = PieceKey[0][0];
  2771.     if (Current->turn) Current->key ^= TurnKey;
  2772.     Current->key ^= CastleKey[Current->castle_flags];
  2773.     if (Current->ep_square) Current->key ^= EPKey[File(Current->ep_square)];
  2774.     Current->pawn_key = 0;
  2775.     Current->pawn_key ^= CastleKey[Current->castle_flags];
  2776.     for (i = 0; i < 16; i++) BB(i) = 0;
  2777.     for (i = 0; i < 64; i++) {
  2778.         if (Square(i)) {
  2779.             Add(BB(Square(i)),i);
  2780.             Add(BB(Square(i) & 1),i);
  2781.             Add(occ,i);
  2782.             Current->key ^= PieceKey[Square(i)][i];
  2783.             if (Square(i) < WhiteKnight) Current->pawn_key ^= PieceKey[Square(i)][i];
  2784.             if (Square(i) < WhiteKing) Current->material += MatCode[Square(i)];
  2785.             else Current->pawn_key ^= PieceKey[Square(i)][i];
  2786.             Current->pst += Pst(Square(i),i);
  2787.         }
  2788.     }
  2789.     if (popcnt(BB(WhiteKnight)) > 2 || popcnt(BB(WhiteLight)) > 1 || popcnt(BB(WhiteDark)) > 1
  2790.         || popcnt(BB(WhiteRook)) > 2 || popcnt(BB(WhiteQueen)) > 2) Current->material |= FlagUnusualMaterial;
  2791.     if (popcnt(BB(BlackKnight)) > 2 || popcnt(BB(BlackLight)) > 1 || popcnt(BB(BlackDark)) > 1
  2792.         || popcnt(BB(BlackRook)) > 2 || popcnt(BB(BlackQueen)) > 2) Current->material |= FlagUnusualMaterial;
  2793.     Current->capture = 0;
  2794.     Current->killer[1] = Current->killer[2] = 0;
  2795.     Current->ply = 0;
  2796.     Stack[sp] = Current->key;
  2797. }
  2798.  
  2799. void get_board(const char fen[]) {
  2800.     int pos, i, j;
  2801.     unsigned char c;
  2802.  
  2803.     Current = Data;
  2804.     memset(Board,0,sizeof(GBoard));
  2805.     memset(Current,0,sizeof(GData));
  2806.     pos = 0;
  2807.     c = fen[pos];
  2808.     while (c == ' ') c = fen[++pos];
  2809.     for (i = 56; i >= 0; i -= 8) {
  2810.         for (j = 0; j <= 7; ) {
  2811.             if (c <= '8') j += c - '0';
  2812.             else {
  2813.                 Square(i+j) = PieceFromChar[c];
  2814.                 if (Even(SDiag(i+j)) && (Square(i+j)/2) == 3) Square(i+j) += 2;
  2815.                 j++;
  2816.             }
  2817.             c = fen[++pos];
  2818.         }
  2819.         c = fen[++pos];
  2820.     }
  2821.     if (c == 'b') Current->turn = 1;
  2822.     c = fen[++pos]; c = fen[++pos];
  2823.     if (c == '-') c = fen[++pos];
  2824.     if (c == 'K') { Current->castle_flags |= CanCastle_OO; c = fen[++pos]; }
  2825.     if (c == 'Q') { Current->castle_flags |= CanCastle_OOO; c = fen[++pos]; }
  2826.     if (c == 'k') { Current->castle_flags |= CanCastle_oo; c = fen[++pos]; }
  2827.     if (c == 'q') { Current->castle_flags |= CanCastle_ooo; c = fen[++pos]; }
  2828.     c = fen[++pos];
  2829.     if (c != '-') {
  2830.         i = c + fen[++pos] * 8 - 489;
  2831.         j = i ^ 8;
  2832.         if (Square(i) != 0) i = 0;
  2833.         else if (Square(j) != (3 - Current->turn)) i = 0;
  2834.         else if (Square(j-1) != (Current->turn+2) && Square(j+1) != (Current->turn+2)) i = 0;
  2835.         Current->ep_square = i;
  2836.     }
  2837.     setup_board();
  2838. }
  2839.  
  2840. __forceinline GEntry * probe_hash() {
  2841.     for (GEntry * Entry = Hash + (High32(Current->key) & hash_mask); Entry < (Hash + (High32(Current->key) & hash_mask)) + 4; Entry++) if (Low32(Current->key) == Entry->key) {
  2842.         Entry->date = date;
  2843.         return Entry;
  2844.     }
  2845.     return NULL;
  2846. }
  2847.  
  2848. __forceinline GPVEntry * probe_pv_hash() {
  2849.     for (GPVEntry * PVEntry = PVHash + (High32(Current->key) & pv_hash_mask); PVEntry < PVHash + (High32(Current->key) & pv_hash_mask) + pv_cluster_size; PVEntry++) if (Low32(Current->key) == PVEntry->key) {
  2850.         PVEntry->date = date;
  2851.         return PVEntry;
  2852.     }
  2853.     return NULL;
  2854. }
  2855.  
  2856. void move_to_string(int move, char string[]) {
  2857.     int pos = 0;
  2858.     string[pos++] = ((move >> 6) & 7) + 'a';
  2859.     string[pos++] = ((move >> 9) & 7) + '1';
  2860.     string[pos++] = (move & 7) + 'a';
  2861.     string[pos++] = ((move >> 3) & 7) + '1';
  2862.     if (IsPromotion(move)) {
  2863.         if ((move & 0xF000) == FlagPQueen)  string[pos++] = 'q';
  2864.         else if ((move & 0xF000) == FlagPRook)   string[pos++] = 'r';
  2865.         else if ((move & 0xF000) == FlagPLight || (move & 0xF000) == FlagPDark) string[pos++] = 'b';
  2866.         else if ((move & 0xF000) == FlagPKnight) string[pos++] = 'n';
  2867.     }
  2868.     string[pos] = 0;
  2869. }
  2870.  
  2871. int move_from_string(char string[]) {
  2872.     int from, to, move;
  2873.     from = ((string[1] - '1') * 8) + (string[0] - 'a');
  2874.     to  = ((string[3] - '1') * 8) + (string[2] - 'a');
  2875.     move = (from << 6) | to;
  2876.     if (Board->square[from] >= WhiteKing && Abs(to - from) == 2) move |= FlagCastling;
  2877.     if (T(Current->ep_square) && to == Current->ep_square) move |= FlagEP;
  2878.     if (string[4] != 0) {
  2879.         if (string[4] == 'q') move |= FlagPQueen;
  2880.         else if (string[4] == 'r') move |= FlagPRook;
  2881.         else if (string[4] == 'b') {
  2882.             if (Odd(to ^ Rank(to))) move |= FlagPLight;
  2883.             else move |= FlagPDark;
  2884.         } else if (string[4] == 'n') move |= FlagPKnight;
  2885.     }
  2886.     return move;
  2887. }
  2888.  
  2889. void pick_pv() {
  2890.     GEntry * Entry;
  2891.     GPVEntry * PVEntry;
  2892.     int i, depth, move;
  2893.     if (pvp >= Min(pv_length,64)) {
  2894.         PV[pvp] = 0;
  2895.         return;
  2896.     }
  2897.     move = 0;
  2898.     depth = -256;
  2899.     if (Entry = probe_hash()) if (T(Entry->move) && Entry->low_depth > depth) {
  2900.         depth = Entry->low_depth;
  2901.         move = Entry->move;
  2902.     }
  2903.     if (PVEntry = probe_pv_hash()) if (T(PVEntry->move) && PVEntry->depth > depth) {
  2904.         depth = PVEntry->depth;
  2905.         move = PVEntry->move;
  2906.     }
  2907.     evaluate();
  2908.     if (Current->att[Current->turn] & King(Current->turn ^ 1)) PV[pvp] = 0;
  2909.     else if (move && (Current->turn ? is_legal<1>(move) : is_legal<0>(move))) {
  2910.         PV[pvp] = move;
  2911.         pvp++;
  2912.         if (Current->turn) do_move<1>(move);
  2913.         else do_move<0>(move);
  2914.         if (Current->ply >= 100) goto finish;
  2915.         for (i = 4; i <= Current->ply; i+= 2) if (Stack[sp-i] == Current->key) {
  2916.             PV[pvp] = 0;
  2917.             goto finish;
  2918.         }
  2919.         pick_pv();
  2920. finish:
  2921.         if (Current->turn ^ 1) undo_move<1>(move);
  2922.         else undo_move<0>(move);
  2923.     } else PV[pvp] = 0;
  2924. }
  2925.  
  2926. template <bool me> int draw_in_pv() {
  2927.     if ((Current - Data) >= 126) return 1;
  2928.     if (Current->ply >= 100) return 1;
  2929.     for (int i = 4; i <= Current->ply; i += 2) if (Stack[sp - i] == Current->key) return 1;
  2930.     if (GPVEntry * PVEntry = probe_pv_hash()) {
  2931.         if (!PVEntry->value) return 1;
  2932.         if (int move = PVEntry->move) {
  2933.             do_move<me>(move);
  2934.             int value = draw_in_pv<opp>();
  2935.             undo_move<me>(move);
  2936.             return value;
  2937.         }
  2938.     }
  2939.     return 0;
  2940. }
  2941.  
  2942. template <bool me> void do_move(int move) {
  2943.     GEntry * Entry;
  2944.     GPawnEntry * PawnEntry;
  2945.     int from, to, piece, capture;
  2946.     GData * Next;
  2947.     uint64 u, mask_from, mask_to;
  2948.  
  2949.     to = To(move);
  2950.     Next = Current + 1;
  2951.     Next->ep_square = 0;
  2952.     capture = Square(to);
  2953.     if (F(capture)) {
  2954.         Next->capture = 0;
  2955.         goto non_capture;
  2956.     }
  2957.     from = From(move);
  2958.     piece = Square(from);
  2959.     Next->turn = opp;
  2960.     Next->capture = capture;
  2961.     Square(from) = 0;
  2962.     Square(to) = piece;
  2963.     Next->piece = piece;
  2964.     mask_from = Bit(from);
  2965.     mask_to = Bit(to);
  2966.     BB(piece) ^= mask_from;
  2967.     Piece(me) ^= mask_from;
  2968.     BB(capture) ^= mask_to;
  2969.     Piece(opp) ^= mask_to;
  2970.     BB(piece) |= mask_to;
  2971.     Piece(me) |= mask_to;
  2972.     Next->castle_flags = Current->castle_flags & UpdateCastling[to] & UpdateCastling[from];
  2973.     Next->pst = Current->pst + Pst(piece,to) - Pst(piece,from) - Pst(capture,to);
  2974.     Next->key = Current->key ^ PieceKey[piece][from] ^ PieceKey[piece][to] ^ PieceKey[capture][to] ^ CastleKey[Current->castle_flags] ^ CastleKey[Next->castle_flags];
  2975.     if (capture != IPawn(opp)) Next->pawn_key = Current->pawn_key ^ CastleKey[Current->castle_flags] ^ CastleKey[Next->castle_flags]; // of course we can put a lot of operations inside this "if {}" but the speedup won't be worth the effort
  2976.     else Next->pawn_key = Current->pawn_key ^ PieceKey[IPawn(opp)][to] ^ CastleKey[Current->castle_flags] ^ CastleKey[Next->castle_flags];
  2977.     Next->material = Current->material - MatCode[capture];
  2978.     if (T(Current->material & FlagUnusualMaterial) && capture >= WhiteKnight) {
  2979.         if (popcnt(BB(WhiteQueen)) <= 2 && popcnt(BB(BlackQueen)) <= 2) {
  2980.             if (popcnt(BB(WhiteLight)) <= 1 && popcnt(BB(BlackLight)) <= 1 && popcnt(BB(WhiteKnight)) <= 2
  2981.                 && popcnt(BB(BlackKnight)) <= 2 && popcnt(BB(WhiteRook)) <= 2 && popcnt(BB(BlackRook)) <= 2)
  2982.                 Next->material ^= FlagUnusualMaterial;
  2983.         }
  2984.     }
  2985.     if (piece == IPawn(me)) {
  2986.         Next->pawn_key ^= PieceKey[IPawn(me)][from] ^ PieceKey[piece][to];
  2987.         if (IsPromotion(move)) {
  2988.             piece = Promotion(move,me);
  2989.             Square(to) = piece;
  2990.             Next->material += MatCode[piece] - MatCode[IPawn(me)];
  2991.             if (piece < WhiteRook) {
  2992.                 if (piece >= WhiteLight && T(BB(piece))) Next->material |= FlagUnusualMaterial;
  2993.                 if (Multiple(BB(piece))) Next->material |= FlagUnusualMaterial;
  2994.             } else if (Multiple(BB(piece))) Next->material |= FlagUnusualMaterial;
  2995.             Pawn(me) ^= mask_to;
  2996.             BB(piece) |= mask_to;
  2997.             Next->pst += Pst(piece,to) - Pst(IPawn(me),to);
  2998.             Next->key ^= PieceKey[piece][to] ^ PieceKey[IPawn(me)][to];
  2999.             Next->pawn_key ^= PieceKey[IPawn(me)][to];
  3000.         }
  3001.         PawnEntry = PawnHash + (Next->pawn_key & pawn_hash_mask);
  3002.         prefetch((char *)PawnEntry,_MM_HINT_NTA);
  3003.     } else if (piece >= WhiteKing) {
  3004.         Next->pawn_key ^= PieceKey[piece][from] ^ PieceKey[piece][to];
  3005.         PawnEntry = PawnHash + (Next->pawn_key & pawn_hash_mask);
  3006.         prefetch((char *)PawnEntry,_MM_HINT_NTA);
  3007.     } else if (capture < WhiteKnight) {
  3008.         PawnEntry = PawnHash + (Next->pawn_key & pawn_hash_mask);
  3009.         prefetch((char *)PawnEntry,_MM_HINT_NTA);
  3010.     }
  3011.     if (F(Next->material & FlagUnusualMaterial)) prefetch((char *)(Material + Next->material), _MM_HINT_NTA);
  3012.     if (Current->ep_square) Next->key ^= EPKey[File(Current->ep_square)];
  3013.     Next->turn = Current->turn ^ 1;
  3014.     Next->key ^= TurnKey;
  3015.     Entry = Hash + (High32(Next->key) & hash_mask);
  3016.     prefetch((char *)Entry,_MM_HINT_NTA);
  3017.     Next->ply = 0;
  3018.     goto finish;
  3019. non_capture:
  3020.     from = From(move);
  3021.     Next->ply = Current->ply + 1;
  3022.     piece = Square(from);
  3023.     Square(from) = 0;
  3024.     Square(to) = piece;
  3025.     Next->piece = piece;
  3026.     mask_from = Bit(from);
  3027.     mask_to = Bit(to);
  3028.     BB(piece) ^= mask_from;
  3029.     Piece(me) ^= mask_from;
  3030.     BB(piece) |= mask_to;
  3031.     Piece(me) |= mask_to;
  3032.     Next->castle_flags = Current->castle_flags & UpdateCastling[to] & UpdateCastling[from];
  3033.     Next->pst = Current->pst + Pst(piece,to) - Pst(piece,from);
  3034.     Next->key = Current->key ^ PieceKey[piece][to] ^ PieceKey[piece][from] ^ CastleKey[Current->castle_flags] ^ CastleKey[Next->castle_flags];
  3035.     Next->material = Current->material;
  3036.     if (piece == IPawn(me)) {
  3037.         Next->ply = 0;
  3038.         Next->pawn_key = Current->pawn_key ^ PieceKey[IPawn(me)][to] ^ PieceKey[IPawn(me)][from] ^ CastleKey[Current->castle_flags] ^ CastleKey[Next->castle_flags];
  3039.         if (IsEP(move)) {
  3040.             Square(to ^ 8) = 0;
  3041.             u = Bit(to ^ 8);
  3042.             Next->key ^= PieceKey[IPawn(opp)][to ^ 8];
  3043.             Next->pawn_key ^= PieceKey[IPawn(opp)][to ^ 8];
  3044.             Next->pst -= Pst(IPawn(opp),to ^ 8);
  3045.             Pawn(opp) &= ~u;
  3046.             Piece(opp) &= ~u;
  3047.             Next->material -= MatCode[IPawn(opp)];
  3048.         } else if (IsPromotion(move)) {
  3049.             piece = Promotion(move,me);
  3050.             Square(to) = piece;
  3051.             Next->material += MatCode[piece] - MatCode[IPawn(me)];
  3052.             if (piece < WhiteRook) {
  3053.                 if (piece >= WhiteLight && T(BB(piece))) Next->material |= FlagUnusualMaterial;
  3054.                 if (Multiple(BB(piece))) Next->material |= FlagUnusualMaterial;
  3055.             } else if (Multiple(BB(piece))) Next->material |= FlagUnusualMaterial;
  3056.             Pawn(me) ^= mask_to;
  3057.             BB(piece) |= mask_to;
  3058.             Next->pst += Pst(piece,to) - Pst(IPawn(me),to);
  3059.             Next->key ^= PieceKey[piece][to] ^ PieceKey[IPawn(me)][to];
  3060.             Next->pawn_key ^= PieceKey[IPawn(me)][to];
  3061.         } else if ((to ^ from) == 16) {
  3062.             if (PAtt[me][(to + from) >> 1] & Pawn(opp)) {
  3063.                 Next->ep_square = (to + from) >> 1;
  3064.                 Next->key ^= EPKey[File(Next->ep_square)];
  3065.             }
  3066.         }
  3067.         PawnEntry = PawnHash + (Next->pawn_key & pawn_hash_mask);
  3068.         prefetch((char *)PawnEntry,_MM_HINT_NTA);
  3069.     } else {
  3070.         if (piece < WhiteKing) Next->pawn_key = Current->pawn_key ^ CastleKey[Current->castle_flags] ^ CastleKey[Next->castle_flags];
  3071.         else {
  3072.             Next->pawn_key = Current->pawn_key ^ PieceKey[piece][to] ^ PieceKey[piece][from] ^ CastleKey[Current->castle_flags] ^ CastleKey[Next->castle_flags];
  3073.             PawnEntry = PawnHash + (Next->pawn_key & pawn_hash_mask);
  3074.             prefetch((char *)PawnEntry,_MM_HINT_NTA);
  3075.         }
  3076.         if (IsCastling(move)) {
  3077.             int rold, rnew;
  3078.             Next->ply = 0;
  3079.             if (to == 6) {
  3080.                 rold = 7;
  3081.                 rnew = 5;
  3082.             } else if (to == 2) {
  3083.                 rold = 0;
  3084.                 rnew = 3;
  3085.             } else if (to == 62) {
  3086.                 rold = 63;
  3087.                 rnew = 61;
  3088.             } else if (to == 58) {
  3089.                 rold = 56;
  3090.                 rnew = 59;
  3091.             }
  3092.             Add(mask_to,rnew);
  3093.             Square(rold) = 0;
  3094.             Square(rnew) = IRook(me);
  3095.             BB(IRook(me)) ^= Bit(rold);
  3096.             Piece(me) ^= Bit(rold);
  3097.             BB(IRook(me)) |= Bit(rnew);
  3098.             Piece(me) |= Bit(rnew);
  3099.             Next->pst += Pst(IRook(me),rnew) - Pst(IRook(me),rold);
  3100.             Next->key ^= PieceKey[IRook(me)][rnew] ^ PieceKey[IRook(me)][rold];
  3101.         }
  3102.     }
  3103.  
  3104.     if (Current->ep_square) Next->key ^= EPKey[File(Current->ep_square)];
  3105.     Next->turn = opp;
  3106.     Next->key ^= TurnKey;
  3107.     Entry = Hash + (High32(Next->key) & hash_mask);
  3108.     prefetch((char *)Entry,_MM_HINT_NTA);
  3109. finish:
  3110.     sp++;
  3111.     Stack[sp] = Next->key;
  3112.     Next->move = move;
  3113.     Next->gen_flags = 0;
  3114.     Current++;
  3115.     nodes++;
  3116. }
  3117.  
  3118. template <bool me> void undo_move(int move) {
  3119.     int to, from, piece;
  3120.     from = From(move);
  3121.     to = To(move);
  3122.     if (IsPromotion(move)) {
  3123.         BB(Square(to)) ^= Bit(to);
  3124.         piece = IPawn(me);
  3125.     } else piece = Square(to);
  3126.     Square(from) = piece;
  3127.     BB(piece) |= Bit(from);
  3128.     Piece(me) |= Bit(from);
  3129.     BB(piece) &= ~Bit(to);
  3130.     Piece(me) ^= Bit(to);
  3131.     Square(to) = Current->capture;
  3132.     if (Current->capture) {
  3133.         BB(Current->capture) |= Bit(to);
  3134.         Piece(opp) |= Bit(to);
  3135.     } else {
  3136.         if (IsCastling(move)) {
  3137.             int rold, rnew;
  3138.             if (to == 6) {
  3139.                 rold = 7;
  3140.                 rnew = 5;
  3141.             } else if (to == 2) {
  3142.                 rold = 0;
  3143.                 rnew = 3;
  3144.             } else if (to == 62) {
  3145.                 rold = 63;
  3146.                 rnew = 61;
  3147.             } else if (to == 58) {
  3148.                 rold = 56;
  3149.                 rnew = 59;
  3150.             }
  3151.             Square(rnew) = 0;
  3152.             Square(rold) = IRook(me);
  3153.             Rook(me) ^= Bit(rnew);
  3154.             Piece(me) ^= Bit(rnew);
  3155.             Rook(me) |= Bit(rold);
  3156.             Piece(me) |= Bit(rold);
  3157.         } else if (IsEP(move)) {
  3158.             to = to ^ 8;
  3159.             piece = IPawn(opp);
  3160.             Square(to) = piece;
  3161.             Piece(opp) |= Bit(to);
  3162.             Pawn(opp) |= Bit(to);
  3163.         }
  3164.     }
  3165.     Current--;
  3166.     sp--;
  3167. }
  3168.  
  3169. void do_null() {
  3170.     GData * Next;
  3171.     GEntry * Entry;
  3172.  
  3173.     Next = Current + 1;
  3174.     Next->key = Current->key ^ TurnKey;
  3175.     Entry = Hash + (High32(Next->key) & hash_mask);
  3176.     prefetch((char *)Entry,_MM_HINT_NTA);
  3177.     Next->pawn_key = Current->pawn_key;
  3178.     Next->eval_key = 0;
  3179.     Next->turn = Current->turn ^ 1;
  3180.     Next->material = Current->material;
  3181.     Next->pst = Current->pst;
  3182.     Next->ply = 0;
  3183.     Next->castle_flags = Current->castle_flags;
  3184.     Next->ep_square = 0;
  3185.     Next->capture = 0;
  3186.     if (Current->ep_square) Next->key ^= EPKey[File(Current->ep_square)];
  3187.     sp++;  
  3188.     Next->att[White] = Current->att[White];
  3189.     Next->att[Black] = Current->att[Black];
  3190.     Next->patt[White] = Current->patt[White];
  3191.     Next->patt[Black] = Current->patt[Black];
  3192.     Next->xray[White] = Current->xray[White];
  3193.     Next->xray[Black] = Current->xray[Black];
  3194.     Next->pin[White] = Current->pin[White];
  3195.     Next->pin[Black] = Current->pin[Black];
  3196.     Stack[sp] = Next->key;
  3197.     Next->threat = Current->threat;
  3198.     Next->passer = Current->passer;
  3199.     Next->score = -Current->score;
  3200.     Next->move = 0;
  3201.     Next->gen_flags = 0;
  3202.     Current++;
  3203.     nodes++;
  3204. }
  3205.  
  3206. void undo_null() {
  3207.     Current--;
  3208.     sp--;
  3209. }
  3210.  
  3211. template <bool me> int krbkrx() {
  3212.     if (King(opp) & Interior) return 1;
  3213.     return 16;
  3214. }
  3215. template <bool me> int kpkx() {
  3216.     uint64 u;
  3217.     if (me == White) u = Kpk[Current->turn][lsb(Pawn(White))][lsb(King(White))] & Bit(lsb(King(Black)));
  3218.     else u = Kpk[Current->turn ^ 1][63 - lsb(Pawn(Black))][63 - lsb(King(Black))] & Bit(63 - lsb(King(White)));
  3219.     if (u) return 32;
  3220.     else if (Piece(opp) ^ King(opp)) return 1;
  3221.     else return 0;
  3222. }
  3223. template <bool me> int knpkx() {
  3224.     if (Pawn(me) & Line(me, 6) & (File[0] | File[7])) {
  3225.         int sq = lsb(Pawn(me));
  3226.         if (SArea[sq] & King(opp) & (Line(me, 6) | Line(me, 7))) return 0;
  3227.         if (Square(sq + Push(me)) == IKing(me) && (SArea[lsb(King(me))] && SArea[lsb(King(opp))] & Line(me, 7))) return 0;
  3228.     } else if (Pawn(me) & Line(me, 5) & (File[0] | File[7])) {
  3229.         int sq = lsb(Pawn(me));
  3230.         if (Square(sq + Push(me)) == IPawn(opp)) {
  3231.             if (SArea[sq + Push(me)] & King(opp) & Line(me, 7)) return 0;
  3232.             if ((SArea[sq + Push(me)] & SArea[lsb(King(opp))] & Line(me, 7)) && (!(NAtt[sq + Push(me)] & Knight(me)) || Current->turn == opp)) return 0;
  3233.         }
  3234.     }
  3235.     return 32;
  3236. }
  3237. template <bool me> int krpkrx() {
  3238.     int mul = 32;
  3239.     int sq = lsb(Pawn(me));
  3240.     int rrank = CRank(me, sq);
  3241.     int o_king = lsb(King(opp));
  3242.     int o_rook = lsb(Rook(opp));
  3243.     int m_king = lsb(King(me));
  3244.     int add_mat = T(Piece(opp) ^ King(opp) ^ Rook(opp));
  3245.     int clear = F(add_mat) || F((PWay[opp][sq] | PIsolated[File(sq)]) & Forward[opp][Rank(sq + Push(me))] & (Piece(opp) ^ King(opp) ^ Rook(opp)));
  3246.  
  3247.     if (!clear) return 32;
  3248.     if (!add_mat && !(Pawn(me) & (File[0] | File[7]))) {
  3249.         int m_rook = lsb(Rook(me));
  3250.         if (CRank(me, o_king) < CRank(me, m_rook) && CRank(me, m_rook) < rrank && CRank(me, m_king) >= rrank - 1 && CRank(me, m_king) > CRank(me, m_rook)
  3251.             && ((SArea[m_king] & Pawn(me)) || (Current->turn == me && Abs(File(sq) - File(m_king)) <= 1 && Abs(rrank - CRank(me, m_king)) <= 2))) return 128;
  3252.         if (SArea[m_king] & Pawn(me)) {
  3253.             if (rrank >= 4) {
  3254.                 if ((File(sq) < File(m_rook) && File(m_rook) < File(o_king)) || (File(sq) > File(m_rook) && File(m_rook) > File(o_king))) return 128;
  3255.             } else if (rrank >= 2) {
  3256.                 if (!(Pawn(me) & (File[1] | File[6])) && rrank + Abs(File(sq) - File(m_rook)) > 4
  3257.                     && ((File(sq) < File(m_rook) && File(m_rook) < File(o_king)) || (File(sq) > File(m_rook) && File(m_rook) > File(o_king)))) return 128;
  3258.             }
  3259.         }
  3260.     }
  3261.  
  3262.     if (PWay[me][sq] & King(opp)) {
  3263.         if (Pawn(me) & (File[0] | File[7])) mul = Min(mul, add_mat << 3);
  3264.         if (rrank <= 3) mul = Min(mul, add_mat << 3);
  3265.         if (rrank == 4 && CRank(me, m_king) <= 4 && CRank(me, o_rook) == 5 && T(King(opp) & (Line(me, 6) | Line(me, 7)))
  3266.             && (Current->turn != me || F(PAtt[me][sq] & RookAttacks(lsb(Rook(me)), PieceAll) & (~SArea[o_king])))) mul = Min(mul, add_mat << 3);
  3267.         if (rrank >= 5 && CRank(me, o_rook) <= 1 && (Current->turn != me || Check(me) || Dist(m_king, sq) >= 2)) mul = Min(mul, add_mat << 3);
  3268.         if (T(King(opp) & (File[1] | File[2] | File[6] | File[7])) && T(Rook(opp) & Line(me, 7)) && T(Between[o_king][o_rook] & (File[3] | File[4])) && F(Rook(me) & Line(me, 7))) mul = Min(mul, add_mat << 3);
  3269.         return mul;
  3270.     } else if (rrank == 6 && (Pawn(me) & (File[0] | File[7])) && ((PSupport[me][sq] | PWay[opp][sq]) & Rook(opp)) && CRank(me, o_king) >= 6) {
  3271.         int dist = Abs(File(sq) - File(o_king));
  3272.         if (dist <= 3)  mul = Min(mul, add_mat << 3);
  3273.         if (dist == 4 && ((PSupport[me][o_king] & Rook(me)) || Current->turn == opp)) mul = Min(mul, add_mat << 3);
  3274.     }
  3275.  
  3276.     if (SArea[o_king] & PWay[me][sq] & Line(me, 7)) {
  3277.         if (rrank <= 4 && CRank(me, m_king) <= 4 && CRank(me, o_rook) == 5) mul = Min(mul, add_mat << 3);
  3278.         if (rrank == 5 && CRank(me, o_rook) <= 1 && Current->turn != me || (F(SArea[m_king] & PAtt[me][sq] & (~SArea[o_king])) && (Check(me) || Dist(m_king, sq) >= 2)))
  3279.             mul = Min(mul, add_mat << 3);
  3280.     }
  3281.  
  3282.     if (T(PWay[me][sq] & Rook(me)) && T(PWay[opp][sq] & Rook(opp))) {
  3283.         if (King(opp) & (File[0] | File[1] | File[6] | File[7]) & Line(me, 6)) mul = Min(mul, add_mat << 3);
  3284.         else if ((Pawn(me) & (File[0] | File[7])) && (King(opp) & (Line(me, 5) | Line(me, 6))) && Abs(File(sq) - File(o_king)) <= 2 && File(sq) != File(o_king)) mul = Min(mul, add_mat << 3);
  3285.     }
  3286.  
  3287.     if (Abs(File(sq) - File(o_king)) <= 1 && Abs(File(sq) - File(o_rook)) <= 1 && CRank(me, o_rook) > rrank && CRank(me, o_king) > rrank) mul = Min(mul, (Pawn(me) & (File[3] | File[4])) ? 12 : 16);
  3288.  
  3289.     return mul;
  3290. }
  3291. template <bool me> int krpkbx() {
  3292.     if (!(Pawn(me) & Line(me, 5))) return 32;
  3293.     int sq = lsb(Pawn(me));
  3294.     if (!(PWay[me][sq] & King(opp))) return 32;
  3295.     int diag_sq = NB(me, BMask[sq + Push(me)]);
  3296.     if (CRank(me, diag_sq) > 1) return 32;
  3297.     uint64 mdiag = FullLine[sq + Push(me)][diag_sq] | Bit(sq + Push(me)) | Bit(diag_sq);
  3298.     int check_sq = NB(me, BMask[sq - Push(me)]);
  3299.     uint64 cdiag = FullLine[sq - Push(me)][check_sq] | Bit(sq - Push(me)) | Bit(check_sq);
  3300.     if ((mdiag | cdiag) & (Piece(opp) ^ King(opp) ^ Bishop(opp))) return 32;
  3301.     if (cdiag & Bishop(opp)) return 0;
  3302.     if ((mdiag & Bishop(opp)) && (Current->turn == opp || !(King(me) & PAtt[opp][sq + Push(me)]))) return 0;
  3303.     return 32;
  3304. }
  3305. template <bool me> int kqkp() {
  3306.     if (F(SArea[lsb(King(opp))] & Pawn(opp) & Line(me, 1) & (File[0] | File[2] | File[5] | File[7]))) return 32;
  3307.     if (PWay[opp][lsb(Pawn(opp))] & (King(me) | Queen(me))) return 32;
  3308.     if (Pawn(opp) & (File[0] | File[7])) return 1;
  3309.     else return 4;
  3310. }
  3311. template <bool me> int kqkrpx() {
  3312.     int rsq = lsb(Rook(opp));
  3313.     uint64 pawns = SArea[lsb(King(opp))] & PAtt[me][rsq] & Pawn(opp) & Interior & Line(me, 6);
  3314.     if (pawns && CRank(me, lsb(King(me))) <= 4) return 0;
  3315.     return 32;
  3316. }
  3317. template <bool me> int krkpx() {
  3318.     if (T(SArea[lsb(King(opp))] & Pawn(opp) & Line(me, 1)) & F(PWay[opp][NB(me, Pawn(opp))] & King(me))) return 0;
  3319.     return 32;
  3320. }
  3321. template <bool me> int krppkrpx() {
  3322.     if (Current->passer & Pawn(me)) {
  3323.         if (Single(Current->passer & Pawn(me))) {
  3324.             int sq = lsb(Current->passer & Pawn(me));
  3325.             if (PWay[me][sq] & King(opp) & (File[0] | File[1] | File[6] | File[7])) {
  3326.                 int opp_king = lsb(King(opp));
  3327.                 if (SArea[opp_king] & Pawn(opp)) {
  3328.                     int king_file = File(opp_king);
  3329.                     if (!((~(File[king_file] | PIsolated[king_file])) & Pawn(me))) return 1;
  3330.                 }
  3331.             }
  3332.         }
  3333.         return 32;
  3334.     }
  3335.     if (F((~(PWay[opp][lsb(King(opp))] | PSupport[me][lsb(King(opp))])) & Pawn(me))) return 0;
  3336.     return 32;
  3337. }
  3338. template <bool me> int krpppkrppx() {
  3339.     if (T(Current->passer & Pawn(me)) || F((SArea[lsb(Pawn(opp))] | SArea[msb(Pawn(opp))]) & Pawn(opp))) return 32;
  3340.     if (F((~(PWay[opp][lsb(King(opp))] | PSupport[me][lsb(King(opp))])) & Pawn(me))) return 0;
  3341.     return 32;
  3342. }
  3343. template <bool me> int kbpkbx() {
  3344.     int sq = lsb(Pawn(me));
  3345.     uint64 u;
  3346.     if ((T(Board->bb[ILight(me)]) && T(Board->bb[IDark(opp)])) || (T(Board->bb[IDark(me)]) && T(Board->bb[ILight(opp)]))) {
  3347.         if (CRank(me, sq) <= 4) return 0;
  3348.         if (T(PWay[me][sq] & King(opp)) && CRank(me, sq) <= 5) return 0;
  3349.         for (u = Bishop(opp); T(u); Cut(u)) {
  3350.             if (CRank(me, lsb(u)) <= 4 && T(BishopAttacks(lsb(u), PieceAll) & PWay[me][sq])) return 0;
  3351.             if (Current->turn == opp && T(BishopAttacks(lsb(u), PieceAll) & Pawn(me))) return 0;
  3352.         }
  3353.     } else if (T(PWay[me][sq] & King(opp)) && T(King(opp) & LightArea) != T(Bishop(me) & LightArea)) return 0;
  3354.     return 32;
  3355. }
  3356. template <bool me> int kbpknx() {
  3357.     uint64 u;
  3358.     if (T(PWay[me][lsb(Pawn(me))] & King(opp)) && T(King(opp) & LightArea) != T(Bishop(me) & LightArea)) return 0;
  3359.     if (Current->turn == opp)
  3360.     for (u = Knight(opp); T(u); Cut(u))
  3361.     if (NAtt[lsb(u)] & Pawn(me)) return 0;
  3362.     return 32;
  3363. }
  3364. template <bool me> int kbppkbx() {
  3365.     int sq1 = NB(me, Pawn(me));
  3366.     int sq2 = NB(opp, Pawn(me));
  3367.     int o_king = lsb(King(opp));
  3368.     int o_bishop = lsb(Bishop(opp));
  3369.  
  3370.     if (File(sq1) == File(sq2)) {
  3371.         if (CRank(me, sq2) <= 3) return 0;
  3372.         if (T(PWay[me][sq2] & King(opp)) && CRank(me, sq2) <= 5) return 0;
  3373.     } else if (PIsolated[File(sq1)] & Pawn(me)) {
  3374.         if (T(King(opp) & LightArea) != T(Bishop(me) & LightArea)) {
  3375.             if (T((SArea[o_king] | King(opp)) & Bit(sq2 + Push(me))) && T(BishopAttacks(o_bishop, PieceAll) & Bit(sq2 + Push(me))))
  3376.             if (T((SArea[o_king] | King(opp)) & Bit((sq2 & 0xFFFFFFF8) | File(sq1))) && T(BishopAttacks(o_bishop, PieceAll) & Bit((sq2 & 0xFFFFFFF8) | File(sq1)))) return 0;
  3377.         }
  3378.     }
  3379.     return 32;
  3380. }
  3381. template <bool me> int krppkrx() {
  3382.     int sq1 = NB(me, Pawn(me));
  3383.     int sq2 = NB(opp, Pawn(me));
  3384.  
  3385.     if ((Piece(opp) ^ King(opp) ^ Rook(opp)) & Forward[me][Rank(sq1 - Push(me))]) return 32;
  3386.     if (File(sq1) == File(sq2)) {
  3387.         if (T(PWay[me][sq2] & King(opp))) return 16;
  3388.         return 32;
  3389.     }
  3390.     if (T(PIsolated[File(sq2)] & Pawn(me)) && T((File[0] | File[7]) & Pawn(me)) && T(King(opp) & Shift(me, Pawn(me)))) {
  3391.         if (CRank(me, sq2) == 5 && CRank(me, sq1) == 4 && T(Rook(opp) & (Line(me, 5) | Line(me, 6)))) return 10;
  3392.         else if (CRank(me, sq2) < 5) return 16;
  3393.     }
  3394.     return 32;
  3395. }
  3396. typedef struct {
  3397.     int king_w, king_b, score;
  3398.     uint64 patt_w, patt_b, double_att_w, double_att_b;
  3399. } GPawnEvalInfo;
  3400.  
  3401. template <bool me, bool HPopCnt> __forceinline void eval_pawns(GPawnEntry * PawnEntry, GPawnEvalInfo &PEI) {
  3402.     int kf = File(PVarC(PEI, king, me));
  3403.     int kr = Rank(PVarC(PEI, king, me));
  3404.     int start, inc;
  3405.     if (kf <= 3) {
  3406.         start = Max(kf - 1, 0);
  3407.         inc = 1;
  3408.     } else {
  3409.         start = Min(kf + 1, 7);
  3410.         inc = -1;
  3411.     }
  3412.     int shelter = 0;
  3413.     uint64 mpawns = Pawn(me) & Forward[me][me ? Min(kr + 1, 7) : Max(kr - 1, 0)];
  3414.     for (int file = start, i = 0; i < 3; file += inc, i++) {
  3415.         shelter += Shelter[i][CRank(me, NBZ(me, mpawns & File[file]))];
  3416.         int rank;
  3417.         if (Pawn(opp) & File[file]) {
  3418.             int sq = NB(me, Pawn(opp) & File[file]);
  3419.             if ((rank = CRank(opp, sq)) < 6) {
  3420.                 if (rank >= 3) shelter += StormBlocked[rank - 3];
  3421.                 if (uint64 u = (PIsolated[File(sq)] & Forward[opp][Rank(sq)] & Pawn(me))) {
  3422.                     int square = NB(opp, u);
  3423.                     uint64 att_sq = PAtt[me][square] & PWay[opp][sq]; // may be zero
  3424.                     if ((File[File(square)] | PIsolated[File(square)]) & King(me)) if (!(PVarC(PEI, double_att, me) & att_sq) || (Current->patt[opp] & att_sq)) {
  3425.                         if (PWay[opp][square] & Pawn(me)) continue;
  3426.                         if (!(PawnAll & PWay[opp][sq] & Forward[me][Rank(square)])) {
  3427.                             if (rank >= 3) {
  3428.                                 shelter += StormShelterAtt[rank - 3];
  3429.                                 if (PVarC(PEI, patt, opp) & Bit(sq + Push(opp))) shelter += StormConnected[rank - 3];
  3430.                                 if (!(PWay[opp][sq] & PawnAll)) shelter += StormOpen[rank - 3];
  3431.                             }
  3432.                             if (!((File[File(sq)] | PIsolated[File(sq)]) & King(opp)) && rank <= 4) shelter += StormFree[rank - 1];
  3433.                         }
  3434.                     }
  3435.                 }
  3436.             }
  3437.         } else {
  3438.             shelter += Sa(StormHof, StormHofValue);
  3439.             if (!(Pawn(me) & File[file])) shelter += Sa(StormHof, StormOfValue);
  3440.         }
  3441.     }
  3442.     PawnEntry->shelter[me] = shelter;
  3443.  
  3444.     uint64 b;
  3445.     int min_file = 7, max_file = 0;
  3446.     for (uint64 u = Pawn(me); T(u); u ^= b) {
  3447.         int sq = lsb(u);
  3448.         b = Bit(sq);
  3449.         int rank = Rank(sq);
  3450.         int rrank = CRank(me, sq);
  3451.         int file = File(sq);
  3452.         uint64 way = PWay[me][sq];
  3453.         int next = Square(sq + Push(me));
  3454.         if (file < min_file) min_file = file;
  3455.         if (file > max_file) max_file = file;
  3456.  
  3457.         int isolated = !(Pawn(me) & PIsolated[file]);
  3458.         int doubled = T(Pawn(me) & (File[file] ^ b));
  3459.         int open = !(PawnAll & way);
  3460.         int up = !(PVarC(PEI, patt, me) & b);
  3461.  
  3462.         if (isolated) {
  3463.             if (open) DecV(PEI.score, Ca(Isolated, IsolatedOpen));
  3464.             else {
  3465.                 DecV(PEI.score, Ca(Isolated, IsolatedClosed));
  3466.                 if (next == IPawn(opp)) DecV(PEI.score, Ca(Isolated, IsolatedBlocked));
  3467.             }
  3468.             if (doubled) {
  3469.                 if (open) DecV(PEI.score, Ca(Isolated, IsolatedDoubledOpen));
  3470.                 else DecV(PEI.score, Ca(Isolated, IsolatedDoubledClosed));
  3471.             }
  3472.         } else {
  3473.             if (doubled) {
  3474.                 if (open) DecV(PEI.score, Ca(Doubled, DoubledOpen));
  3475.                 else DecV(PEI.score, Ca(Doubled, DoubledClosed));
  3476.             }
  3477.             if (rrank >= 3 && (b & (File[2] | File[3] | File[4] | File[5])) && next != IPawn(opp) && (PIsolated[file] & Line[rank] & Pawn(me)))
  3478.                 IncV(PEI.score, Ca(PawnSpecial, PawnChainLinear) * (rrank - 3) + Ca(PawnSpecial, PawnChain));
  3479.         }
  3480.         int backward = 0;
  3481.         if (!(PSupport[me][sq] & Pawn(me))) {
  3482.             if (isolated) backward = 1;
  3483.             else if (uint64 v = (PawnAll | PVarC(PEI, patt, opp)) & way) if (IsGreater(me, NB(me, PVarC(PEI, patt, me) & way), NB(me, v))) backward = 1;
  3484.         }
  3485.         if (backward) {
  3486.             if (open) DecV(PEI.score, Ca(Backward, BackwardOpen));
  3487.             else DecV(PEI.score, Ca(Backward, BackwardClosed));
  3488.         } else if (open) if (!(Pawn(opp) & PIsolated[file]) || popcount<HPopCnt>(Pawn(me) & PIsolated[file]) >= popcount<HPopCnt>(Pawn(opp) & PIsolated[file])) IncV(PEI.score,PasserCandidate[rrank]); // IDEA: more precise pawn counting for the case of, say, white e5 candidate with black pawn on f5 or f4...
  3489.         if (up && next == IPawn(opp)) {
  3490.             DecV(PEI.score, Ca(Unprotected, UpBlocked));
  3491.             if (backward) {
  3492.                 if (rrank <= 2) { // IDEA (based on weird passer target tuning result): may be score unprotected/backward depending on rank/file?
  3493.                     DecV(PEI.score, Ca(Unprotected, PasserTarget));
  3494.                     if (rrank <= 1) DecV(PEI.score, Ca(Unprotected, PasserTarget));
  3495.                 }
  3496.                 for (uint64 v = PAtt[me][sq] & Pawn(me); v; Cut(v)) if ((PSupport[me][lsb(v)] & Pawn(me)) == b) {
  3497.                     DecV(PEI.score, Ca(Unprotected, ChainRoot));
  3498.                     break;
  3499.                 }
  3500.             }
  3501.         }
  3502.         if (open && !(PIsolated[file] & Forward[me][rank] & Pawn(opp))) {
  3503.             PawnEntry->passer[me] |= (uint8)(1 << file);
  3504.             if (rrank <= 2) continue;
  3505.             IncV(PEI.score, PasserGeneral[rrank]);
  3506.             int dist_att = Dist(PVarC(PEI, king, opp), sq + Push(me)); // IDEA: average the distance with the distance to the promotion square? or just use the latter?
  3507.             int dist_def = Dist(PVarC(PEI, king, me), sq + Push(me));
  3508.             IncV(PEI.score, Compose256(0, dist_att * (int)PasserAtt[rrank] + LogDist[dist_att] * (int)PasserAttLog[rrank] - dist_def * (int)PasserDef[rrank] - (int)LogDist[dist_def] * (int)PasserDefLog[rrank]));
  3509.             if (PVarC(PEI, patt, me) & b) IncV(PEI.score, PasserProtected[rrank]);
  3510.             if (!(Pawn(opp) & West[file]) || !(Pawn(opp) & East[file])) IncV(PEI.score, PasserOutside[rrank]);
  3511.         }
  3512.     }
  3513.     uint64 files = 0;
  3514.     for (int i = 1; i < 7; i++) files |= (Pawn(me) >> (i << 3)) & 0xFF;
  3515.     int file_span = (files ? (msb(files) - lsb(files)) : 0);
  3516.     IncV(PEI.score, Ca(PawnSpecial, PawnFileSpan) * file_span);
  3517.     PawnEntry->draw[me] = (7 - file_span) * Max(5 - popcount<HPopCnt>(files), 0);
  3518. }
  3519.  
  3520. template <bool HPopCnt> void eval_pawn_structure(GPawnEntry * PawnEntry) {
  3521.     GPawnEvalInfo PEI;
  3522.     for (int i = 0; i < sizeof(GPawnEntry) / sizeof(int); i++) *(((int*)PawnEntry) + i) = 0;
  3523.     PawnEntry->key = Current->pawn_key;
  3524.  
  3525.     PEI.patt_w = ShiftW(White, Pawn(White)) | ShiftE(White, Pawn(White));
  3526.     PEI.patt_b = ShiftW(Black, Pawn(Black)) | ShiftE(Black, Pawn(Black));
  3527.     PEI.double_att_w = ShiftW(White, Pawn(White)) & ShiftE(White, Pawn(White));
  3528.     PEI.double_att_b = ShiftW(Black, Pawn(Black)) & ShiftE(Black, Pawn(Black));
  3529.     PEI.king_w = lsb(King(White));
  3530.     PEI.king_b = lsb(King(Black));
  3531.     PEI.score = 0;
  3532.  
  3533.     eval_pawns<White, HPopCnt>(PawnEntry, PEI);
  3534.     eval_pawns<Black, HPopCnt>(PawnEntry, PEI);
  3535.  
  3536.     PawnEntry->score = PEI.score;
  3537. }
  3538.  
  3539. typedef struct {
  3540.     int score, king_w, king_b, mul;
  3541.     uint64 occ, area_w, area_b, free_w, free_b;
  3542.     uint32 king_att_w, king_att_b;
  3543.     GPawnEntry * PawnEntry;
  3544.     GMaterial * material;
  3545. } GEvalInfo;
  3546.  
  3547. template <bool me, bool HPopCnt> __forceinline void eval_queens(GEvalInfo &EI) {
  3548.     uint64 u, b;
  3549.     for (u = Queen(me); T(u); u ^= b) {
  3550.         int sq = lsb(u);
  3551.         b = Bit(sq);
  3552.         uint64 att = QueenAttacks(sq,EI.occ);
  3553.         Current->att[me] |= att;
  3554.         if (QMask[sq] & King(opp)) if (uint64 v = Between[PVarC(EI,king,opp)][sq] & EI.occ) if (Single(v)) {
  3555.             Current->xray[me] |= v;
  3556.             uint64 square = lsb(v); int piece = Square(square); int katt = 0;
  3557.             if (piece == IPawn(me)) {
  3558.                 if (!Square(square + Push(me))) IncV(EI.score, Ca(Pin, SelfPawnPin));
  3559.             } else if ((piece & 1) == me) {
  3560.                 IncV(EI.score, Ca(Pin, SelfPiecePin));
  3561.                 katt = 1;
  3562.             } else if (piece != IPawn(opp) && !(((BMask[sq] & Bishop(opp)) | (RMask[sq] & Rook(opp)) | Queen(opp)) & v)) {
  3563.                 IncV(EI.score, Ca(Pin, WeakPin));
  3564.                 if (!(Current->patt[opp] & v)) katt = 1;
  3565.             }
  3566.             if (katt && !(att & PVarC(EI, area, opp))) PVarC(EI, king_att, me) += KingAttack;
  3567.         } else if (v == (v & Minor(opp))) IncV(EI.score, Ca(KingRay, QKingRay));
  3568.         if (att & PVarC(EI, area, opp)) {
  3569.             PVarC(EI, king_att, me) += KingQAttack;
  3570.             for (uint64 v = att & PVarC(EI, area, opp); T(v); Cut(v))
  3571.             if (FullLine[sq][lsb(v)] & att & ((Rook(me) & RMask[sq]) | (Bishop(me) & BMask[sq]))) PVarC(EI, king_att, me)++;
  3572.         }
  3573.         IncV(EI.score,Mobility[PieceType[WhiteQueen] - 1][popcount<HPopCnt>(att & PVarC(EI,free,me))]);
  3574.         if (att & PVarC(EI, free, me) & Pawn(opp)) IncV(EI.score, Ca(Tactical, TacticalMajorPawn));
  3575.         if (att & PVarC(EI, free, me) & Minor(opp)) IncV(EI.score, Ca(Tactical, TacticalMajorMinor));
  3576.         if (att & PVarC(EI, area, me)) IncV(EI.score, Ca(KingDefence, KingDefQueen));
  3577.     }
  3578. }
  3579. template <bool me, bool HPopCnt> __forceinline void eval_rooks(GEvalInfo &EI) {
  3580.     uint64 u, b;
  3581.     for (u = Rook(me); T(u); u ^= b) {
  3582.         int sq = lsb(u);
  3583.         b = Bit(sq);
  3584.         uint64 att = RookAttacks(sq,EI.occ);
  3585.         Current->att[me] |= att;
  3586.         if (RMask[sq] & King(opp)) if (uint64 v = Between[PVarC(EI, king, opp)][sq] & EI.occ) if (Single(v)) {
  3587.             Current->xray[me] |= v;
  3588.             uint64 square = lsb(v); int piece = Square(square); int katt = 0;
  3589.             if (piece == IPawn(me)) {
  3590.                 if (!Square(square + Push(me))) IncV(EI.score, Ca(Pin, SelfPawnPin));
  3591.             } else if ((piece & 1) == me) {
  3592.                 IncV(EI.score, Ca(Pin, SelfPiecePin));
  3593.                 katt = 1;
  3594.             } else if (piece != IPawn(opp)) {
  3595.                 if (piece < IRook(opp)) {
  3596.                     IncV(EI.score, Ca(Pin, WeakPin));
  3597.                     if (!(Current->patt[opp] & v)) katt = 1;
  3598.                 } else if (piece == IQueen(opp)) IncV(EI.score, Ca(Pin, ThreatPin));
  3599.             }
  3600.             if (katt && !(att & PVarC(EI, area, opp))) PVarC(EI, king_att, me) += KingAttack;
  3601.         } else if (v == (v & (Minor(opp) | Queen(opp)))) IncV(EI.score, Ca(KingRay, RKingRay));
  3602.         if (att & PVarC(EI, area, opp)) {
  3603.             PVarC(EI, king_att, me) += KingRAttack;
  3604.             for (uint64 v = att & PVarC(EI, area, opp); T(v); Cut(v))
  3605.             if (FullLine[sq][lsb(v)] & att & Major(me)) PVarC(EI, king_att, me)++;
  3606.         }
  3607.         IncV(EI.score,Mobility[PieceType[WhiteRook] - 1][popcount<HPopCnt>(att & PVarC(EI,free,me))]);
  3608.         if (att & PVarC(EI, free, me) & Pawn(opp)) IncV(EI.score, Ca(Tactical, TacticalMajorPawn));
  3609.         if (att & PVarC(EI, free, me) & Minor(opp)) IncV(EI.score, Ca(Tactical, TacticalMajorMinor));
  3610.         if (att & PVarC(EI, area, me)) IncV(EI.score, Ca(KingDefence, KingDefRook));
  3611.         Current->threat |= att & Queen(opp);
  3612.         if (!(PWay[me][sq] & Pawn(me))) {
  3613.             IncV(EI.score, Ca(RookSpecial, RookHof));
  3614.             int hof_score = 0;
  3615.             if (!(PWay[me][sq] & Pawn(opp))) {
  3616.                 IncV(EI.score, Ca(RookSpecial, RookOf));
  3617.                 if (att & Line(me, 7)) hof_score += Ca(RookSpecial, RookOfOpen);
  3618.                 else if (uint64 target = att & PWay[me][sq] & Minor(opp)) {
  3619.                     if (!(Current->patt[opp] & target)) {
  3620.                         hof_score += Ca(RookSpecial, RookOfMinorHaging);
  3621.                         if (PWay[me][sq] & King(opp)) hof_score += Ca(RookSpecial, RookOfKingAtt);
  3622.                     } else hof_score += Ca(RookSpecial, RookOfMinorFixed);
  3623.                 }
  3624.             } else if (att & PWay[me][sq] & Pawn(opp)) {
  3625.                 uint64 square = lsb(att & PWay[me][sq] & Pawn(opp));
  3626.                 if (!(PSupport[opp][square] & Pawn(opp))) hof_score += Ca(RookSpecial, RookHofWeakPAtt);
  3627.             }
  3628.             IncV(EI.score, hof_score);
  3629.             if (PWay[opp][sq] & att & Major(me)) IncV(EI.score, hof_score);
  3630.         }
  3631.         if ((b & Line(me, 6)) && ((King(opp) | Pawn(opp)) & (Line(me, 6) | Line(me, 7)))) {
  3632.             IncV(EI.score, Ca(RookSpecial, Rook7th));
  3633.             if (King(opp) & Line(me, 7)) IncV(EI.score, Ca(RookSpecial, Rook7thK8th));
  3634.             if (Major(me) & att & Line(me, 6)) IncV(EI.score, Ca(RookSpecial, Rook7thDoubled));
  3635.         }
  3636.     }
  3637. }
  3638. template <bool me, bool HPopCnt> __forceinline void eval_bishops(GEvalInfo &EI) {
  3639.     uint64 u, b;
  3640.     for (u = Bishop(me); T(u); u ^= b) {
  3641.         int sq = lsb(u);
  3642.         b = Bit(sq);
  3643.         uint64 att = BishopAttacks(sq, EI.occ);
  3644.         Current->att[me] |= att;
  3645.         if (BMask[sq] & King(opp)) if (uint64 v = Between[PVarC(EI, king, opp)][sq] & EI.occ) if (Single(v)) {
  3646.             Current->xray[me] |= v;
  3647.             uint64 square = lsb(v); int piece = Square(square); int katt = 0;
  3648.             if (piece == IPawn(me)) {
  3649.                 if (!Square(square + Push(me))) IncV(EI.score, Ca(Pin, SelfPawnPin));
  3650.             } else if ((piece & 1) == me) {
  3651.                 IncV(EI.score, Ca(Pin, SelfPiecePin));
  3652.                 katt = 1;
  3653.             } else if (piece != IPawn(opp)) {
  3654.                 if (piece < ILight(opp)) {
  3655.                     IncV(EI.score, Ca(Pin, StrongPin));
  3656.                     if (!(Current->patt[opp] & v)) katt = 1;
  3657.                 } else if (piece >= IRook(opp)) IncV(EI.score, Ca(Pin, ThreatPin));
  3658.             }
  3659.             if (katt && !(att & PVarC(EI, area, opp))) PVarC(EI, king_att, me) += KingAttack;
  3660.         } else if (v == (v & (Knight(opp) | Major(opp)))) IncV(EI.score, Ca(KingRay, BKingRay));
  3661.         if (att & PVarC(EI, area, opp)) PVarC(EI, king_att, me) += KingBAttack;
  3662.         IncV(EI.score, Mobility[PieceType[WhiteLight] - 1][popcount<HPopCnt>(att & PVarC(EI, free, me))]);
  3663.         if (att & PVarC(EI, free, me) & Pawn(opp)) IncV(EI.score, Ca(Tactical, TacticalMinorPawn));
  3664.         if (att & PVarC(EI, free, me) & Knight(opp)) IncV(EI.score, Ca(Tactical, TacticalMinorMinor));
  3665.         if (att & PVarC(EI, area, me)) IncV(EI.score, Ca(KingDefence, KingDefBishop));
  3666.         Current->threat |= att & Major(opp);
  3667.         if (b & LightArea) {
  3668.             for (uint64 v = ((~BishopForward[me][sq]) | (att & Forward[me][Rank(sq)])) & Pawn(opp) & (~Current->patt[opp]) & LightArea; v; Cut(v)) {
  3669.                 uint64 square = lsb(v);
  3670.                 if (!((PSupport[opp][square] | PWay[opp][square]) & Pawn(opp))) IncV(EI.score, Ca(BishopSpecial, BishopNonForwardPawn));
  3671.             }
  3672.             uint64 v = BishopForward[me][sq] & Pawn(me) & LightArea;
  3673.             v |= (v & (File[2] | File[3] | File[4] | File[5] | BMask[sq])) >> 8;
  3674.             DecV(EI.score, Ca(BishopSpecial, BishopPawnBlock) * popcount<HPopCnt>(v));
  3675.         } else {
  3676.             for (uint64 v = ((~BishopForward[me][sq]) | (att & Forward[me][Rank(sq)])) & Pawn(opp) & (~Current->patt[opp]) & DarkArea; v; Cut(v)) {
  3677.                 uint64 square = lsb(v);
  3678.                 if (!((PSupport[opp][square] | PWay[opp][square]) & Pawn(opp))) IncV(EI.score, Ca(BishopSpecial, BishopNonForwardPawn));
  3679.             }
  3680.             uint64 v = BishopForward[me][sq] & Pawn(me) & DarkArea;
  3681.             v |= (v & (File[2] | File[3] | File[4] | File[5] | BMask[sq])) >> 8;
  3682.             DecV(EI.score, Ca(BishopSpecial, BishopPawnBlock) * popcount<HPopCnt>(v));
  3683.         }
  3684.     }
  3685. }
  3686. template <bool me, bool HPopCnt> __forceinline void eval_knights(GEvalInfo &EI) {
  3687.     uint64 u, b;
  3688.     for (u = Knight(me); T(u); u ^= b) {
  3689.         int sq = lsb(u);
  3690.         b = Bit(sq);
  3691.         uint64 att = NAtt[sq];
  3692.         Current->att[me] |= att;
  3693.         if (att & PVarC(EI, area, opp)) PVarC(EI, king_att, me) += KingNAttack;
  3694.         IncV(EI.score, Mobility[PieceType[WhiteKnight] - 1][popcount<HPopCnt>(att & PVarC(EI, free, me))]);
  3695.         if (att & PVarC(EI, free, me) & Pawn(opp)) IncV(EI.score, Ca(Tactical, TacticalMinorPawn));
  3696.         if (att & PVarC(EI, free, me) & Bishop(opp)) IncV(EI.score, Ca(Tactical, TacticalMinorMinor));
  3697.         if (att & PVarC(EI, area, me)) IncV(EI.score, Ca(KingDefence, KingDefKnight));
  3698.         Current->threat |= att & Major(opp);
  3699.         if ((b & Outpost[me]) && !(Pawn(opp) & PIsolated[File(sq)] & Forward[me][Rank(sq)])) {
  3700.             IncV(EI.score, Ca(KnightSpecial, KnightOutpost));
  3701.             if (Current->patt[me] & b) {
  3702.                 IncV(EI.score, Ca(KnightSpecial, KnightOutpostProtected));
  3703.                 if (att & PVarC(EI, free, me) & Pawn(opp)) IncV(EI.score, Ca(KnightSpecial, KnightOutpostPawnAtt));
  3704.                 if (att & PVarC(EI, free, me) & Bishop(opp)) IncV(EI.score, Ca(KnightSpecial, KnightOutpostBishopAtt));
  3705.             }
  3706.         }
  3707.     }
  3708. }
  3709. template <bool me, bool HPopCnt> __forceinline void eval_king(GEvalInfo &EI) {
  3710.     int cnt = Opening(PVarC(EI, king_att, me));
  3711.     int score = Endgame(PVarC(EI, king_att, me));
  3712.     if (cnt >= 2 && T(Queen(me))) {
  3713.         score += (EI.PawnEntry->shelter[opp] * KingShelterQuad)/64;
  3714.         if (uint64 u = Current->att[me] & PVarC(EI, area, opp) & (~Current->att[opp])) score += popcount<HPopCnt>(u) * KingAttackSquare;
  3715.         if (!(SArea[PVarC(EI, king, opp)] & (~(Piece(opp) | Current->att[me])))) score += KingNoMoves;
  3716.     }
  3717.     int adjusted = ((score * KingAttackScale[cnt]) >> 3) + EI.PawnEntry->shelter[opp];
  3718.     if (!Queen(me)) adjusted /= 2;
  3719.     IncV(EI.score, adjusted);
  3720. }
  3721. template <bool me, bool HPopCnt> __forceinline void eval_passer(GEvalInfo &EI) {
  3722.     for (uint64 u = EI.PawnEntry->passer[me]; T(u); Cut(u)) {
  3723.         int file = lsb(u);
  3724.         int sq = NB(opp, File[file] & Pawn(me));
  3725.         int rank = CRank(me, sq);
  3726.         Current->passer |= Bit(sq);
  3727.         if (rank <= 2) continue;
  3728.         if (!Square(sq + Push(me))) IncV(EI.score, PasserBlocked[rank]);
  3729.         uint64 way = PWay[me][sq];
  3730.         int connected = 0, supported = 0, hooked = 0, unsupported = 0, free = 0;
  3731.         if (!(way & Piece(opp))) {
  3732.             IncV(EI.score, PasserClear[rank]);
  3733.             if (PWay[opp][sq] & Major(me)) {
  3734.                 int square = NB(opp, PWay[opp][sq] & Major(me));
  3735.                 if (F(Between[sq][square] & EI.occ)) supported = 1;
  3736.             }
  3737.             if (PWay[opp][sq] & Major(opp)) {
  3738.                 int square = NB(opp, PWay[opp][sq] & Major(opp));
  3739.                 if (F(Between[sq][square] & EI.occ)) hooked = 1;
  3740.             }
  3741.             for (uint64 v = PAtt[me][sq - Push(me)] & Pawn(me); T(v); Cut(v)) {
  3742.                 int square = lsb(v);
  3743.                 if (F(Pawn(opp) & (File[File(square)] | PIsolated[File(square)]) & Forward[me][Rank(square)])) connected++;
  3744.             }
  3745.             if (connected) IncV(EI.score, PasserConnected[rank]);
  3746.             if (!hooked && !(Current->att[opp] & way)) {
  3747.                 IncV(EI.score, PasserFree[rank]);
  3748.                 free = 1;
  3749.             } else {
  3750.                 uint64 attacked = Current->att[opp] | (hooked ? way : 0);
  3751.                 if (supported || (!hooked && connected) || (!(Major(me) & way) && !(attacked & (~Current->att[me])))) IncV(EI.score, PasserSupported[rank]);
  3752.                 else unsupported = 1;
  3753.             }
  3754.         }
  3755.         if (rank == 6) {
  3756.             if ((way & Rook(me)) && !Minor(me) && !Queen(me) && Single(Rook(me))) DecV(EI.score, Compose(0, Sa(PasserSpecial, PasserOpRookBlock)));
  3757.             if (!Major(opp) && (!NonPawnKing(opp) || Single(NonPawnKing(opp)))) {
  3758.                 IncV(EI.score, Compose(0, Sa(PasserSpecial, PasserOnePiece)));
  3759.                 if (!free) {
  3760.                     if (!(SArea[sq + Push(me)] & King(opp))) IncV(EI.score, Compose(0, Sa(PasserSpecial, PasserOpMinorControl)));
  3761.                     else IncV(EI.score, Compose(0, Sa(PasserSpecial, PasserOpKingControl)));
  3762.                 }
  3763.             }
  3764.         }
  3765.     }
  3766. }
  3767. template <bool me, bool HPopCnt> __forceinline void eval_pieces(GEvalInfo &EI) {
  3768.     Current->threat |= Current->att[opp] & (~Current->att[me]) & Piece(me);
  3769.     if (uint64 u = Current->threat & Piece(me)) {
  3770.         DecV(EI.score, Ca(Tactical, TacticalThreat));
  3771.         Cut(u);
  3772.         if (u) {
  3773.             DecV(EI.score, Ca(Tactical, TacticalThreat) + Ca(Tactical, TacticalDoubleThreat));
  3774.             for (Cut(u); u; Cut(u)) DecV(EI.score, Ca(Tactical, TacticalThreat));
  3775.         }
  3776.     }
  3777. }
  3778. template <bool me, bool HPopCnt> void eval_endgame(GEvalInfo &EI) {
  3779.     if ((EI.material->flags & VarC(FlagSingleBishop, me)) && Pawn(me)) {
  3780.         int sq = (Board->bb[ILight(me)] ? (me ? 0 : 63) : (Board->bb[IDark(me)] ? (me ? 7 : 56) : (File(lsb(King(opp))) <= 3 ? (me ? 0 : 56) : (me ? 7 : 63))));
  3781.         if (!(Pawn(me) & (~PWay[opp][sq]))) {
  3782.             if ((SArea[sq] | Bit(sq)) & King(opp)) EI.mul = 0;
  3783.             else if ((SArea[sq] & SArea[lsb(King(opp))] & Line(me, 7)) && Square(sq - Push(me)) == IPawn(opp) && Square(sq - 2 * Push(me)) == IPawn(me)) EI.mul = 0;
  3784.         } else if ((King(opp) & Line(me, 6) | Line(me, 7)) && Abs(File(sq) - File(lsb(King(opp)))) <= 3 && !(Pawn(me) & (~PSupport[me][sq])) && (Pawn(me) & Line(me, 5) & Shift(opp, Pawn(opp)))) EI.mul = 0;
  3785.         if (Single(Pawn(me))) {
  3786.             if (!Bishop(me)) {
  3787.                 EI.mul = MinF(EI.mul, kpkx<me>());
  3788.                 if (Piece(opp) == King(opp) && EI.mul == 32) IncV(Current->score, KpkValue);
  3789.             } else {
  3790.                 sq = lsb(Pawn(me));
  3791.                 if ((Pawn(me) & (File[1] | File[6]) & Line(me, 5)) && Square(sq + Push(me)) == IPawn(opp) && ((PAtt[me][sq + Push(me)] | PWay[me][sq + Push(me)]) & King(opp))) EI.mul = 0;
  3792.             }
  3793.         }
  3794.         if (Bishop(opp) && Single(Bishop(opp)) && T(BB(ILight(me))) != T(BB(ILight(opp)))) {
  3795.             int pcnt = 0;
  3796.             if (T(King(opp) & LightArea) == T(Bishop(opp) & LightArea)) {
  3797.                 for (uint64 u = Pawn(me); u; Cut(u)) {
  3798.                     if (pcnt >= 2) goto check_for_partial_block;
  3799.                     pcnt++;
  3800.                     int sq = lsb(u);
  3801.                     if (!(PWay[me][sq] & (PAtt[me][PVarC(EI, king, opp)] | PAtt[opp][PVarC(EI, king, opp)]))) {
  3802.                         if (!(PWay[me][sq] & Pawn(opp))) goto check_for_partial_block;
  3803.                         int bsq = lsb(Bishop(opp));
  3804.                         uint64 att = BishopAttacks(bsq, EI.occ);
  3805.                         if (!(att & PWay[me][sq] & Pawn(opp))) goto check_for_partial_block;
  3806.                         if (!(BishopForward[me][bsq] & att & PWay[me][sq] & Pawn(opp)) && popcount<HPopCnt>(FullLine[lsb(att & PWay[me][sq] & Pawn(opp))][bsq] & att) <= 2)  goto check_for_partial_block;
  3807.                     }
  3808.                 }
  3809.                 EI.mul = 0;
  3810.                 return;
  3811.             }
  3812.         check_for_partial_block:
  3813.             if (pcnt <= 2 && Multiple(Pawn(me)) && !Pawn(opp) && !(Pawn(me) & Boundary) && EI.mul) {
  3814.                 int sq1 = lsb(Pawn(me));
  3815.                 int sq2 = msb(Pawn(me));
  3816.                 int fd = Abs(File(sq2) - File(sq1));
  3817.                 if (fd >= 5) EI.mul = 32;
  3818.                 else if (fd >= 4) EI.mul = 26;
  3819.                 else if (fd >= 3) EI.mul = 20;
  3820.             }
  3821.             if ((SArea[PVarC(EI, king, opp)] | Current->patt[opp]) & Bishop(opp)) {
  3822.                 uint64 push = Shift(me, Pawn(me));
  3823.                 if (!(push & (~(Piece(opp) | Current->att[opp]))) && (King(opp) & (Board->bb[ILight(opp)] ? LightArea : DarkArea))) {
  3824.                     EI.mul = Min(EI.mul, 8);
  3825.                     int bsq = lsb(Bishop(opp));
  3826.                     uint64 att = BishopAttacks(bsq, EI.occ);
  3827.                     uint64 prp = (att | SArea[PVarC(EI, king, opp)]) & Pawn(opp) & (Board->bb[ILight(opp)] ? LightArea : DarkArea);
  3828.                     uint64 patt = ShiftW(opp, prp) | ShiftE(opp, prp);
  3829.                     if ((SArea[PVarC(EI, king, opp)] | patt) & Bishop(opp)) {
  3830.                         uint64 double_att = (SArea[PVarC(EI, king, opp)] & patt) | (patt & att) | (SArea[PVarC(EI, king, opp)] & att);
  3831.                         if (!(push & (~(King(opp) | Bishop(opp) | prp | double_att)))) {
  3832.                             EI.mul = 0;
  3833.                             return;
  3834.                         }
  3835.                     }
  3836.                 }
  3837.             }
  3838.         }
  3839.     }
  3840.     if (F(Major(me))) {
  3841.         if (T(Bishop(me)) && F(Knight(me)) && Single(Bishop(me)) && T(Pawn(me))) {
  3842.             int number = popcount<HPopCnt>(Pawn(me));
  3843.             if (number == 1) {
  3844.                 if (Bishop(opp)) EI.mul = MinF(EI.mul, kbpkbx<me>());
  3845.                 else if (Knight(opp)) EI.mul = MinF(EI.mul, kbpknx<me>());
  3846.             } else if (number == 2 && T(Bishop(opp))) EI.mul = MinF(EI.mul, kbppkbx<me>());
  3847.         } else if (!Bishop(me) && Knight(me) && Single(Knight(me)) && Pawn(me) && Single(Pawn(me))) EI.mul = MinF(EI.mul, knpkx<me>());
  3848.     } else if (F(Minor(me))) {
  3849.         if (F(Pawn(me)) && F(Rook(me)) && T(Queen(me)) && T(Pawn(opp))) {
  3850.             if (F(NonPawnKing(opp)) && Single(Pawn(opp))) EI.mul = MinF(EI.mul, kqkp<me>());
  3851.             else if (Rook(opp)) EI.mul = MinF(EI.mul, kqkrpx<me>());
  3852.         } else if (F(Queen(me)) && T(Rook(me)) && Single(Rook(me))) {
  3853.             int number = popcount<HPopCnt>(Pawn(me));
  3854.             if (number <= 3) {
  3855.                 if (number == 0) {
  3856.                     if (Pawn(opp)) EI.mul = MinF(EI.mul, krkpx<me>());
  3857.                 } else if (Rook(opp)) {
  3858.                     if (number == 1) {
  3859.                         int new_mul = krpkrx<me>();
  3860.                         EI.mul = (new_mul <= 32 ? Min(EI.mul, new_mul) : new_mul);
  3861.                     } else {
  3862.                         if (number == 2) EI.mul = MinF(EI.mul, krppkrx<me>());
  3863.                         if (Pawn(opp)) {
  3864.                             if (number == 2) EI.mul = MinF(EI.mul, krppkrpx<me>());
  3865.                             else if (Multiple(Pawn(opp))) EI.mul = MinF(EI.mul, krpppkrppx<me>());
  3866.                         }
  3867.                     }
  3868.                 } else if (number == 1 && Bishop(opp)) EI.mul = MinF(EI.mul, krpkbx<me>());
  3869.             }
  3870.         }
  3871.     } else if (!Pawn(me) && Single(Rook(me)) && !Queen(me) && Single(Bishop(me)) && !Knight(me) && Rook(opp)) EI.mul = MinF(EI.mul, krbkrx<me>());
  3872.     if (F(NonPawnKing(opp)) && Current->turn == opp && F(Current->att[me] & King(opp)) && !(SArea[PVarC(EI, king, opp)] & (~(Current->att[me] | Piece(opp))))
  3873.         && F(Current->patt[opp] & Piece(me)) && F(Shift(opp, Pawn(opp)) & (~EI.occ)))
  3874.         EI.mul = 0;
  3875. }
  3876. template <bool HPopCnt> void eval_unusual_material(GEvalInfo &EI) {
  3877.     int wp, bp, wlight, blight, wr, br, wq, bq;
  3878.     wp = popcount<HPopCnt>(Pawn(White));
  3879.     bp = popcount<HPopCnt>(Pawn(Black));
  3880.     wlight = popcount<HPopCnt>(Minor(White));
  3881.     blight = popcount<HPopCnt>(Minor(Black));
  3882.     wr = popcount<HPopCnt>(Rook(White));
  3883.     br = popcount<HPopCnt>(Rook(Black));
  3884.     wq = popcount<HPopCnt>(Queen(White));
  3885.     bq = popcount<HPopCnt>(Queen(Black));
  3886.     int phase = Min(24, (wlight + blight) + 2 * (wr + br) + 4 * (wq + bq));
  3887.     int mat_score = SeeValue[WhitePawn] * (wp - bp) + SeeValue[WhiteKnight] * (wlight - blight) + SeeValue[WhiteRook] * (wr - br) + SeeValue[WhiteQueen] * (wq - bq);
  3888.     mat_score = Compose(mat_score,mat_score);
  3889.     Current->score = (((Opening(mat_score + EI.score) * phase) + (Endgame(mat_score + EI.score) * (24 - phase)))/24);
  3890.     if (Current->turn) Current->score = -Current->score;
  3891.     UpdateDelta
  3892. }
  3893.  
  3894. template <bool HPopCnt> void evaluation() {
  3895.     GEvalInfo EI;
  3896.    
  3897.     if (Current->eval_key == Current->key) return;
  3898.     Current->eval_key = Current->key;
  3899.  
  3900.     EI.king_w = lsb(King(White));
  3901.     EI.king_b = lsb(King(Black));
  3902.     EI.occ = PieceAll;
  3903.     Current->patt[White] = ShiftW(White,Pawn(White)) | ShiftE(White,Pawn(White));
  3904.     Current->patt[Black] = ShiftW(Black,Pawn(Black)) | ShiftE(Black,Pawn(Black));
  3905.     EI.area_w = (SArea[EI.king_w] | King(White)) & ((~Current->patt[White]) | Current->patt[Black]);
  3906.     EI.area_b = (SArea[EI.king_b] | King(Black)) & ((~Current->patt[Black]) | Current->patt[White]);
  3907.     Current->att[White] = Current->patt[White];
  3908.     Current->att[Black] = Current->patt[Black];
  3909.     Current->passer = 0;
  3910.     Current->threat = (Current->patt[White] & NonPawn(Black)) | (Current->patt[Black] & NonPawn(White));
  3911.     EI.score = Current->pst;
  3912.  
  3913. #define me White
  3914.     Current->xray[me] = 0;
  3915.     PVarC(EI, free, me) = Queen(opp) | King(opp) | (~(Current->patt[opp] | Pawn(me) | King(me)));
  3916.     DecV(EI.score, popcount<HPopCnt>(Shift(opp, EI.occ) & Pawn(me)) * Ca(PawnSpecial, PawnBlocked));
  3917.     if (Current->patt[me] & PVarC(EI, area, opp)) PVarC(EI, king_att, me) = KingAttack;
  3918.     else PVarC(EI, king_att, me) = 0;
  3919.     eval_queens<me, HPopCnt>(EI);
  3920.     PVarC(EI, free, me) |= Rook(opp);
  3921.     eval_rooks<me, HPopCnt>(EI);
  3922.     PVarC(EI, free, me) |= Minor(opp);
  3923.     eval_bishops<me, HPopCnt>(EI);
  3924.     eval_knights<me, HPopCnt>(EI);
  3925. #undef me
  3926. #define me Black
  3927.     Current->xray[me] = 0;
  3928.     PVarC(EI, free, me) = Queen(opp) | King(opp) | (~(Current->patt[opp] | Pawn(me) | King(me)));
  3929.     DecV(EI.score, popcount<HPopCnt>(Shift(opp, EI.occ) & Pawn(me)) * Ca(PawnSpecial, PawnBlocked));
  3930.     if (Current->patt[me] & PVarC(EI, area, opp)) PVarC(EI, king_att, me) = KingAttack;
  3931.     else PVarC(EI, king_att, me) = 0;
  3932.     eval_queens<me, HPopCnt>(EI);
  3933.     PVarC(EI, free, me) |= Rook(opp);
  3934.     eval_rooks<me, HPopCnt>(EI);
  3935.     PVarC(EI, free, me) |= Minor(opp);
  3936.     eval_bishops<me, HPopCnt>(EI);
  3937.     eval_knights<me, HPopCnt>(EI);
  3938. #undef me
  3939.  
  3940.     EI.PawnEntry = PawnHash + (Current->pawn_key & pawn_hash_mask);
  3941.     if (Current->pawn_key != EI.PawnEntry->key) eval_pawn_structure<HPopCnt>(EI.PawnEntry);
  3942.     EI.score += EI.PawnEntry->score;
  3943.  
  3944.     eval_king<White, HPopCnt>(EI);
  3945.     eval_king<Black, HPopCnt>(EI);
  3946.     Current->att[White] |= SArea[EI.king_w];
  3947.     Current->att[Black] |= SArea[EI.king_b];
  3948.  
  3949.     eval_passer<White, HPopCnt>(EI);
  3950.     eval_pieces<White, HPopCnt>(EI);
  3951.     eval_passer<Black, HPopCnt>(EI);
  3952.     eval_pieces<Black, HPopCnt>(EI);
  3953.  
  3954.     if (Current->material & FlagUnusualMaterial) {
  3955.         eval_unusual_material<HPopCnt>(EI);
  3956.         return;
  3957.     }
  3958.     EI.material = &Material[Current->material];
  3959. #ifdef TUNER
  3960.     if (EI.material->generation != generation) calc_material(Current->material);
  3961. #endif
  3962.     Current->score = EI.material->score + (((Opening(EI.score) * EI.material->phase) + (Endgame(EI.score) * (128 - (int)EI.material->phase)))/128);
  3963.  
  3964.     if (Current->ply >= 50) Current->score /= 2;
  3965.     if (Current->score > 0) {
  3966.         EI.mul = EI.material->mul[White];
  3967.         if (EI.material->flags & FlagCallEvalEndgame_w) eval_endgame<White, HPopCnt>(EI);
  3968.         Current->score -= (Min(Current->score, 100) * (int)EI.PawnEntry->draw[White]) / 64;
  3969.     } else if (Current->score < 0) {
  3970.         EI.mul = EI.material->mul[Black];
  3971.         if (EI.material->flags & FlagCallEvalEndgame_b) eval_endgame<Black, HPopCnt>(EI);
  3972.         Current->score += (Min(-Current->score, 100) * (int)EI.PawnEntry->draw[Black]) / 64;
  3973.     } else EI.mul = Min(EI.material->mul[White], EI.material->mul[Black]);
  3974.     Current->score = (Current->score * EI.mul)/32;
  3975.  
  3976.     if (Current->turn) Current->score = -Current->score;
  3977.     UpdateDelta
  3978. }
  3979.  
  3980. __forceinline void evaluate() {
  3981.     HardwarePopCnt ? evaluation<1>() : evaluation<0>();
  3982. }
  3983.  
  3984. template <bool me> int is_legal(int move) {
  3985.     int from, to, piece, capture;
  3986.     uint64 u, occ;
  3987.  
  3988.     from = From(move);
  3989.     to = To(move);
  3990.     piece = Board->square[from];
  3991.     capture = Board->square[to];
  3992.     if (piece == 0) return 0;
  3993.     if ((piece & 1) != Current->turn) return 0;
  3994.     if (capture) {
  3995.         if ((capture & 1) == (piece & 1)) return 0;
  3996.         if (capture >= WhiteKing) return 0;
  3997.     }
  3998.     occ = PieceAll;
  3999.     u = Bit(to);
  4000.     if (piece >= WhiteLight && piece < WhiteKing) {
  4001.         if ((QMask[from] & u) == 0) return 0;
  4002.         if (Between[from][to] & occ) return 0;
  4003.     }
  4004.     if (IsEP(move)) {
  4005.         if (piece >= WhiteKnight) return 0;
  4006.         if (Current->ep_square != to) return 0;
  4007.         return 1;
  4008.     }
  4009.     if (IsCastling(move) && Board->square[from] < WhiteKing) return 0;
  4010.     if (IsPromotion(move) && Board->square[from] >= WhiteKnight) return 0;
  4011.     if (piece == IPawn(me)) {
  4012.         if (u & PMove[me][from]) {
  4013.             if (capture) return 0;
  4014.             if (T(u & Line(me,7)) && !IsPromotion(move)) return 0;
  4015.             return 1;
  4016.         } else if (to == (from + 2 * Push(me))) {
  4017.             if (capture) return 0;
  4018.             if (Square(to - Push(me))) return 0;
  4019.             if (F(u & Line(me,3))) return 0;
  4020.             return 1;
  4021.         } else if (u & PAtt[me][from]) {
  4022.             if (capture == 0) return 0;
  4023.             if (T(u & Line(me,7)) && !IsPromotion(move)) return 0;
  4024.             return 1;
  4025.         } else return 0;
  4026.     } else if (piece == IKing(me)) {
  4027.         if (me == White) {
  4028.             if (IsCastling(move)) {
  4029.                 if (u & 0x40) {
  4030.                     if (((Current->castle_flags) & CanCastle_OO) == 0) return 0;
  4031.                     if (occ & 0x60) return 0;
  4032.                     if (Current->att[Black] & 0x70) return 0;
  4033.                 } else {
  4034.                     if (((Current->castle_flags) & CanCastle_OOO) == 0) return 0;
  4035.                     if (occ & 0xE) return 0;
  4036.                     if (Current->att[Black] & 0x1C) return 0;
  4037.                 }
  4038.                 return 1;
  4039.             }
  4040.         } else {
  4041.             if (IsCastling(move)) {
  4042.                 if (u & 0x4000000000000000) {
  4043.                     if (((Current->castle_flags) & CanCastle_oo) == 0) return 0;
  4044.                     if (occ & 0x6000000000000000) return 0;
  4045.                     if (Current->att[White] & 0x7000000000000000) return 0;
  4046.                 } else {
  4047.                     if (((Current->castle_flags) & CanCastle_ooo) == 0) return 0;
  4048.                     if (occ & 0x0E00000000000000) return 0;
  4049.                     if (Current->att[White] & 0x1C00000000000000) return 0;
  4050.                 }
  4051.                 return 1;
  4052.             }
  4053.         }
  4054.         if (F(SArea[from] & u)) return 0;
  4055.         if (Current->att[opp] & u) return 0;
  4056.         return 1;
  4057.     }
  4058.     piece = (piece >> 1) - 2;
  4059.     if (piece == 0) {
  4060.         if (u & NAtt[from]) return 1;
  4061.         else return 0;
  4062.     } else {
  4063.         if (piece <= 2) {
  4064.             if (BMask[from] & u) return 1;
  4065.         } else if (piece == 3) {
  4066.             if (RMask[from] & u) return 1;
  4067.         } else return 1;
  4068.         return 0;
  4069.     }
  4070. }
  4071.  
  4072. template <bool me> int is_check(int move) { // doesn't detect castling and ep checks
  4073.     uint64 king;
  4074.     int from, to, piece, king_sq;
  4075.  
  4076.     from = From(move);
  4077.     to = To(move);
  4078.     king = King(opp);
  4079.     king_sq = lsb(king);
  4080.     piece = Square(from);
  4081.     if (T(Bit(from) & Current->xray[me]) && F(FullLine[king_sq][from] & Bit(to))) return 1;
  4082.     if (piece < WhiteKnight) {
  4083.         if (PAtt[me][to] & king) return 1;
  4084.         if (T(Bit(to) & Line(me, 7)) && T(king & Line(me, 7)) && F(Between[to][king_sq] & PieceAll)) return 1;
  4085.     } else if (piece < WhiteLight) {
  4086.         if (NAtt[to] & king) return 1;
  4087.     } else if (piece < WhiteRook) {
  4088.         if (BMask[to] & king) if (F(Between[king_sq][to] & PieceAll)) return 1;
  4089.     } else if (piece < WhiteQueen) {
  4090.         if (RMask[to] & king) if (F(Between[king_sq][to] & PieceAll)) return 1;
  4091.     } else if (piece < WhiteKing) {
  4092.         if (QMask[to] & king) if (F(Between[king_sq][to] & PieceAll)) return 1;
  4093.     }
  4094.     return 0;
  4095. }
  4096.  
  4097. void hash_high(int value, int depth) {
  4098.     int i, score, min_score;
  4099.     GEntry *best, *Entry;
  4100.  
  4101.     min_score = 0x70000000;
  4102.     for (i = 0, best = Entry = Hash + (High32(Current->key) & hash_mask); i < 4; i++, Entry++) {
  4103.         if (Entry->key == Low32(Current->key)) {
  4104.             Entry->date = date;
  4105.             if (depth > Entry->high_depth || (depth == Entry->high_depth && value < Entry->high)) {
  4106.                 if (Entry->low <= value) {
  4107.                     Entry->high_depth = depth;
  4108.                     Entry->high = value;
  4109.                 } else if (Entry->low_depth < depth) {
  4110.                     Entry->high_depth = depth;
  4111.                     Entry->high = value;
  4112.                     Entry->low = value;
  4113.                 }
  4114.             }
  4115.             return;
  4116.         } else score = (Convert(Entry->date,int) << 3) + Convert(Max(Entry->high_depth, Entry->low_depth),int);
  4117.         if (score < min_score) {
  4118.             min_score = score;
  4119.             best = Entry;
  4120.         }
  4121.     }
  4122.     best->date = date;
  4123.     best->key = Low32(Current->key);
  4124.     best->high = value;
  4125.     best->high_depth = depth;
  4126.     best->low = 0;
  4127.     best->low_depth = 0;
  4128.     best->move = 0;
  4129.     best->flags = 0;
  4130.     return;
  4131. }
  4132.  
  4133. void hash_low(int move, int value, int depth) {
  4134.     int i, score, min_score;
  4135.     GEntry *best, *Entry;
  4136.  
  4137.     min_score = 0x70000000;
  4138.     move &= 0xFFFF;
  4139.     for (i = 0, best = Entry = Hash + (High32(Current->key) & hash_mask); i < 4; i++, Entry++) {
  4140.         if (Entry->key == Low32(Current->key)) {
  4141.             Entry->date = date;
  4142.             if (depth > Entry->low_depth || (depth == Entry->low_depth && value > Entry->low)) {
  4143.                 if (move) Entry->move = move;
  4144.                 if (Entry->high >= value) {
  4145.                     Entry->low_depth = depth;
  4146.                     Entry->low = value;
  4147.                 } else if (Entry->high_depth < depth) {
  4148.                     Entry->low_depth = depth;
  4149.                     Entry->low = value;
  4150.                     Entry->high = value;
  4151.                 }
  4152.             } else if (F(Entry->move)) Entry->move = move;
  4153.             return;
  4154.         } else score = (Convert(Entry->date,int) << 3) + Convert(Max(Entry->high_depth, Entry->low_depth),int);
  4155.         if (score < min_score) {
  4156.             min_score = score;
  4157.             best = Entry;
  4158.         }
  4159.     }
  4160.     best->date = date;
  4161.     best->key = Low32(Current->key);
  4162.     best->high = 0;
  4163.     best->high_depth = 0;
  4164.     best->low = value;
  4165.     best->low_depth = depth;
  4166.     best->move = move;
  4167.     best->flags = 0;
  4168.     return;
  4169. }
  4170.  
  4171. void hash_exact(int move, int value, int depth, int exclusion, int ex_depth, int knodes) {
  4172.     int i, score, min_score;
  4173.     GPVEntry *best;
  4174.     GPVEntry * PVEntry;
  4175.  
  4176.     min_score = 0x70000000;
  4177.     for (i = 0, best = PVEntry = PVHash + (High32(Current->key) & pv_hash_mask); i < pv_cluster_size; i++, PVEntry++) {
  4178.         if (PVEntry->key == Low32(Current->key)) {
  4179.             PVEntry->date = date;
  4180.             PVEntry->knodes += knodes;
  4181.             if (PVEntry->depth <= depth) {
  4182.                 PVEntry->value = value;
  4183.                 PVEntry->depth = depth;
  4184.                 PVEntry->move = move;
  4185.                 PVEntry->ply = Current->ply;
  4186.                 if (ex_depth) {
  4187.                     PVEntry->exclusion = exclusion;
  4188.                     PVEntry->ex_depth = ex_depth;
  4189.                 }
  4190.             }
  4191.             return;
  4192.         }
  4193.         score = (Convert(PVEntry->date,int) << 3) + Convert(PVEntry->depth,int);
  4194.         if (score < min_score) {
  4195.             min_score = score;
  4196.             best = PVEntry;
  4197.         }
  4198.     }
  4199.     best->key = Low32(Current->key);
  4200.     best->date = date;
  4201.     best->value = value;
  4202.     best->depth = depth;
  4203.     best->move = move;
  4204.     best->exclusion = exclusion;
  4205.     best->ex_depth = ex_depth;
  4206.     best->knodes = knodes;
  4207.     best->ply = Current->ply;
  4208. }
  4209.  
  4210. template <bool pv> __forceinline int extension(int move, int depth) {
  4211.     register int ext = 0;
  4212.     if (pv) {
  4213.         if (T(Current->passer & Bit(From(move))) && CRank(Current->turn, From(move)) >= 5 && depth < 16) ext = 2;
  4214.     } else {
  4215.         if (T(Current->passer & Bit(From(move))) && CRank(Current->turn, From(move)) >= 5 && depth < 16) ext = 1;
  4216.     }
  4217.     return ext;
  4218. }
  4219.  
  4220. void sort(int * start, int * finish) {
  4221.     for (int * p = start; p < finish - 1; p++) {
  4222.         int * best = p;
  4223.         int value = *p;
  4224.         int previous = *p;
  4225.         for (int * q = p + 1; q < finish; q++) if ((*q) > value) {
  4226.             value = *q;
  4227.             best = q;
  4228.         }
  4229.         *best = previous;
  4230.         *p = value;
  4231.     }
  4232. }
  4233.  
  4234. void sort_moves(int * start, int * finish) {
  4235.     for (int * p = start + 1; p < finish; p++) for (int * q = p - 1; q >= start; q--) if (((*q) >> 16) < ((*(q+1)) >> 16)) {
  4236.         int move = *q;
  4237.         *q = *(q+1);
  4238.         *(q+1)=move;
  4239.     }
  4240. }
  4241.  
  4242. __forceinline int pick_move() {
  4243.     register int move, *p, *best;
  4244.     move = *(Current->current);
  4245.     if (F(move)) return 0;
  4246.     best = Current->current;
  4247.     for (p = Current->current + 1; T(*p); p++) {
  4248.         if ((*p) > move) {
  4249.             best = p;
  4250.             move = *p;
  4251.         }
  4252.     }
  4253.     *best = *(Current->current);
  4254.     *(Current->current) = move;
  4255.     Current->current++;
  4256.     return move & 0xFFFF;
  4257. }
  4258.  
  4259. template <bool me> void gen_next_moves() {
  4260.     int *p, *q, *r;
  4261.     Current->gen_flags &= ~FlagSort;
  4262.     switch (Current->stage) {
  4263.     case s_hash_move: case r_hash_move: case e_hash_move:
  4264.         Current->moves[0] = Current->killer[0];
  4265.         Current->moves[1] = 0;
  4266.         return;
  4267.     case s_good_cap:
  4268.         Current->mask = Piece(opp);
  4269.         r = gen_captures<me>(Current->moves);
  4270.         for (q = r - 1, p = Current->moves; q >= p;) {
  4271.             int move = (*q) & 0xFFFF;
  4272.             if (!see<me>(move,0)) {
  4273.                 int next = *p;
  4274.                 *p = *q;
  4275.                 *q = next;
  4276.                 p++;
  4277.             } else q--;
  4278.         }
  4279.         Current->start = p;
  4280.         Current->current = p;
  4281.         sort(p, r);
  4282.         return;
  4283.     case s_special:
  4284.         Current->current = Current->start;
  4285.         p = Current->start;
  4286.         if (Current->killer[1]) {*p = Current->killer[1]; p++;}
  4287.         if (Current->killer[2]) {*p = Current->killer[2]; p++;}
  4288.         if (Current->ref[0] && Current->ref[0] != Current->killer[1] && Current->ref[0] != Current->killer[2]) {*p = Current->ref[0]; p++;}
  4289.         if (Current->ref[1] && Current->ref[1] != Current->killer[1] && Current->ref[1] != Current->killer[2]) {*p = Current->ref[1]; p++;}
  4290.         *p = 0;
  4291.         return;
  4292.     case s_quiet:
  4293.         gen_quiet_moves<me>(Current->start);
  4294.         Current->current = Current->start;
  4295.         Current->gen_flags |= FlagSort;
  4296.         return;
  4297.     case s_bad_cap:
  4298.         *(Current->start) = 0;
  4299.         Current->current = Current->moves;
  4300.         if (!(Current->gen_flags & FlagNoBcSort)) sort(Current->moves, Current->start);
  4301.         return;
  4302.     case r_cap:
  4303.         r = gen_captures<me>(Current->moves);
  4304.         Current->current = Current->moves;
  4305.         sort(Current->moves, r);
  4306.         return;
  4307.     case r_checks:
  4308.         r = gen_checks<me>(Current->moves);
  4309.         Current->current = Current->moves;
  4310.         sort(Current->moves, r);
  4311.         return;
  4312.     case e_ev:
  4313.         Current->mask = Filled;
  4314.         r = gen_evasions<me>(Current->moves);
  4315.         mark_evasions(Current->moves);
  4316.         sort(Current->moves, r);
  4317.         Current->current = Current->moves;
  4318.         return;
  4319.     }
  4320. }
  4321.  
  4322. template <bool me, bool root> int get_move() {
  4323.     int move;
  4324.    
  4325.     if (root) {
  4326.         move = (*Current->current) & 0xFFFF;
  4327.         Current->current++;
  4328.         return move;
  4329.     }
  4330. start:
  4331.     if (F(*Current->current)) {
  4332.         Current->stage++;
  4333.         if ((1 << Current->stage) & StageNone) return 0;
  4334.         gen_next_moves<me>();
  4335.         goto start;
  4336.     }
  4337.     if (Current->gen_flags & FlagSort) move = pick_move();
  4338.     else {
  4339.         move = (*Current->current) & 0xFFFF;
  4340.         Current->current++;
  4341.     }
  4342.     if (Current->stage == s_quiet) {
  4343.         if (move == Current->killer[1] || move == Current->killer[2] || move == Current->ref[0] || move == Current->ref[1]) goto start;
  4344.     } else if (Current->stage == s_special && (Square(To(move)) || !is_legal<me>(move))) goto start;
  4345.     return move;
  4346. }
  4347.  
  4348. template <bool me> int see(int move, int margin) {
  4349.     int from, to, piece, capture, delta, sq, pos;
  4350.     uint64 clear, def, att, occ, b_area, r_slider_att, b_slider_att, r_slider_def, b_slider_def, r_area, u, new_att, my_bishop, opp_bishop;
  4351.     from = From(move);
  4352.     to = To(move);
  4353.     piece = SeeValue[Square(from)];
  4354.     capture = SeeValue[Square(to)];
  4355.     delta = piece - capture;
  4356.     if (delta <= -margin) return 1;
  4357.     if (piece == SeeValue[WhiteKing]) return 1;
  4358.     if (Current->xray[me] & Bit(from)) return 1;
  4359.     if (T(Current->pin[me] & Bit(from)) && piece <= SeeValue[WhiteDark]) return 1;
  4360.     if (piece > (SeeValue[WhiteKing] >> 1)) return 1;
  4361.     if (IsEP(move)) return 1;
  4362.     if (F(Current->att[opp] & Bit(to))) return 1;
  4363.     att = PAtt[me][to] & Pawn(opp);
  4364.     if (T(att) && delta + margin > SeeValue[WhitePawn]) return 0;
  4365.     clear = ~Bit(from);
  4366.     def = PAtt[opp][to] & Pawn(me) & clear;
  4367.     if (T(def) && delta + SeeValue[WhitePawn] + margin <= 0) return 1;
  4368.     att |= NAtt[to] & Knight(opp);
  4369.     if (T(att) && delta > SeeValue[WhiteDark] - margin) return 0;
  4370.     occ = PieceAll & clear;
  4371.     b_area = BishopAttacks(to,occ);
  4372.     opp_bishop = Bishop(opp);
  4373.     if (delta > SeeValue[IDark(me)] - margin) if (b_area & opp_bishop) return 0;
  4374.     my_bishop = Bishop(me);
  4375.     b_slider_att = BMask[to] & (opp_bishop | Queen(opp));
  4376.     r_slider_att = RMask[to] & Major(opp);
  4377.     b_slider_def = BMask[to] & (my_bishop | Queen(me)) & clear;
  4378.     r_slider_def = RMask[to] & Major(me) & clear;
  4379.     att |= (b_slider_att & b_area);
  4380.     def |= NAtt[to] & Knight(me) & clear;
  4381.     r_area = RookAttacks(to,occ);
  4382.     att |= (r_slider_att & r_area);
  4383.     def |= (b_slider_def & b_area);
  4384.     def |= (r_slider_def & r_area);
  4385.     att |= SArea[to] & King(opp);
  4386.     def |= SArea[to] & King(me) & clear;
  4387.     while (true) {
  4388.         if (u = (att & Pawn(opp))) {
  4389.             capture -= piece;
  4390.             piece = SeeValue[WhitePawn];
  4391.             sq = lsb(u);
  4392.             occ ^= Bit(sq);
  4393.             att ^= Bit(sq);
  4394.             for (new_att = FullLine[to][sq] & b_slider_att & occ & (~att); T(new_att); Cut(new_att)) {
  4395.                 pos = lsb(new_att);
  4396.                 if (F(Between[to][pos] & occ)) {
  4397.                     Add(att,pos);
  4398.                     break;
  4399.                 }
  4400.             }
  4401.         } else if (u = (att & Knight(opp))) {
  4402.             capture -= piece;
  4403.             piece = SeeValue[WhiteKnight];
  4404.             att ^= (~(u-1)) & u;
  4405.         } else if (u = (att & opp_bishop)) {
  4406.             capture -= piece;
  4407.             piece = SeeValue[WhiteDark];
  4408.             sq = lsb(u);
  4409.             occ ^= Bit(sq);
  4410.             att ^= Bit(sq);
  4411.             for (new_att = FullLine[to][sq] & b_slider_att & occ & (~att); T(new_att); Cut(new_att)) {
  4412.                 pos = lsb(new_att);
  4413.                 if (F(Between[to][pos] & occ)) {
  4414.                     Add(att,pos);
  4415.                     break;
  4416.                 }
  4417.             }
  4418.         } else if (u = (att & Rook(opp))) {
  4419.             capture -= piece;
  4420.             piece = SeeValue[WhiteRook];
  4421.             sq = lsb(u);
  4422.             occ ^= Bit(sq);
  4423.             att ^= Bit(sq);
  4424.             for (new_att = FullLine[to][sq] & r_slider_att & occ & (~att); T(new_att); Cut(new_att)) {
  4425.                 pos = lsb(new_att);
  4426.                 if (F(Between[to][pos] & occ)) {
  4427.                     Add(att,pos);
  4428.                     break;
  4429.                 }
  4430.             }
  4431.         } else if (u = (att & Queen(opp))) {
  4432.             capture -= piece;
  4433.             piece = SeeValue[WhiteQueen];
  4434.             sq = lsb(u);
  4435.             occ ^= Bit(sq);
  4436.             att ^= Bit(sq);
  4437.             for (new_att = FullLine[to][sq] & (r_slider_att | b_slider_att) & occ & (~att); T(new_att); Cut(new_att)) {
  4438.                 pos = lsb(new_att);
  4439.                 if (F(Between[to][pos] & occ)) {
  4440.                     Add(att,pos);
  4441.                     break;
  4442.                 }
  4443.             }
  4444.         } else if (u = (att & King(opp))) {
  4445.             capture -= piece;
  4446.             piece = SeeValue[WhiteKing];
  4447.         } else return 1;
  4448.         if (capture < -(SeeValue[WhiteKing] >> 1)) return 0;
  4449.         if (piece + capture < margin) return 0;
  4450.         if (u = (def & Pawn(me))) {
  4451.             capture += piece;
  4452.             piece = SeeValue[WhitePawn];
  4453.             sq = lsb(u);
  4454.             occ ^= Bit(sq);
  4455.             def ^= Bit(sq);
  4456.             for (new_att = FullLine[to][sq] & b_slider_def & occ & (~att); T(new_att); Cut(new_att)) {
  4457.                 pos = lsb(new_att);
  4458.                 if (F(Between[to][pos] & occ)) {
  4459.                     Add(def,pos);
  4460.                     break;
  4461.                 }
  4462.             }
  4463.         } else if (u = (def & Knight(me))) {
  4464.             capture += piece;
  4465.             piece = SeeValue[WhiteKnight];
  4466.             def ^= (~(u-1)) & u;
  4467.         } else if (u = (def & my_bishop)) {
  4468.             capture += piece;
  4469.             piece = SeeValue[WhiteDark];
  4470.             sq = lsb(u);
  4471.             occ ^= Bit(sq);
  4472.             def ^= Bit(sq);
  4473.             for (new_att = FullLine[to][sq] & b_slider_def & occ & (~att); T(new_att); Cut(new_att)) {
  4474.                 pos = lsb(new_att);
  4475.                 if (F(Between[to][pos] & occ)) {
  4476.                     Add(def,pos);
  4477.                     break;
  4478.                 }
  4479.             }
  4480.         } else if (u = (def & Rook(me))) {
  4481.             capture += piece;
  4482.             piece = SeeValue[WhiteRook];
  4483.             sq = lsb(u);
  4484.             occ ^= Bit(sq);
  4485.             def ^= Bit(sq);
  4486.             for (new_att = FullLine[to][sq] & r_slider_def & occ & (~att); T(new_att); Cut(new_att)) {
  4487.                 pos = lsb(new_att);
  4488.                 if (F(Between[to][pos] & occ)) {
  4489.                     Add(def,pos);
  4490.                     break;
  4491.                 }
  4492.             }
  4493.         } else if (u = (def & Queen(me))) {
  4494.             capture += piece;
  4495.             piece = SeeValue[WhiteQueen];
  4496.             sq = lsb(u);
  4497.             occ ^= Bit(sq);
  4498.             def ^= Bit(sq);
  4499.             for (new_att = FullLine[to][sq] & (r_slider_def | b_slider_def) & occ & (~att); T(new_att); Cut(new_att)) {
  4500.                 pos = lsb(new_att);
  4501.                 if (F(Between[to][pos] & occ)) {
  4502.                     Add(def,pos);
  4503.                     break;
  4504.                 }
  4505.             }
  4506.         } else if (u = (def & King(me))) {
  4507.             capture += piece;
  4508.             piece = SeeValue[WhiteKing];
  4509.         } else return 0;
  4510.         if (capture > (SeeValue[WhiteKing] >> 1)) return 1;
  4511.         if (capture - piece >= margin) return 1;
  4512.     }
  4513. }
  4514.  
  4515. template <bool me> void gen_root_moves() {
  4516.     int i, *p, killer, depth = -256, move;
  4517.     GEntry * Entry;
  4518.     GPVEntry * PVEntry;
  4519.  
  4520.     killer = 0;
  4521.     if (Entry = probe_hash()) {
  4522.         if (T(Entry->move) && Entry->low_depth > depth) {
  4523.             depth = Entry->low_depth;
  4524.             killer = Entry->move;
  4525.         }
  4526.     }
  4527.     if (PVEntry = probe_pv_hash()) {
  4528.         if (PVEntry->depth > depth && T(PVEntry->move)) {
  4529.             depth = PVEntry->depth;
  4530.             killer = PVEntry->move;
  4531.         }
  4532.     }
  4533.  
  4534.     Current->killer[0] = killer;
  4535.     if (Check(me)) Current->stage = stage_evasion;
  4536.     else {
  4537.         Current->stage = stage_search;
  4538.         Current->ref[0] = RefM(Current->move).ref[0];
  4539.         Current->ref[1] = RefM(Current->move).ref[1];
  4540.     }
  4541.     Current->gen_flags = 0;
  4542.     p = RootList;
  4543.     Current->current = Current->moves;
  4544.     Current->moves[0] = 0;
  4545.     while (move = get_move<me,0>()) {
  4546.         if (IsIllegal(me,move)) continue;
  4547.         if (p > RootList && move == killer) continue;
  4548.         if (SearchMoves) {
  4549.             for (i = 0; i < SMPointer; i++)
  4550.                 if (SMoves[i] == move) goto keep_move;
  4551.             continue;
  4552.         }
  4553. keep_move:
  4554.         *p = move;
  4555.         p++;
  4556.     }
  4557.     *p = 0;
  4558. }
  4559.  
  4560. template <bool me> int * gen_captures(int * list) {
  4561.     uint64 u, v;
  4562.  
  4563.     if (Current->ep_square)
  4564.         for (v = PAtt[opp][Current->ep_square] & Pawn(me); T(v); Cut(v)) AddMove(lsb(v),Current->ep_square,FlagEP,MvvLva[IPawn(me)][IPawn(opp)])
  4565.     for (u = Pawn(me) & Line(me,6); T(u); Cut(u))
  4566.         if (F(Square(lsb(u) + Push(me)))) {
  4567.             AddMove(lsb(u),lsb(u) + Push(me),FlagPQueen,MvvLvaPromotion)
  4568.             if (NAtt[lsb(King(opp))] & Bit(lsb(u) + Push(me))) AddMove(lsb(u),lsb(u) + Push(me),FlagPKnight,MvvLvaPromotionKnight)
  4569.         }
  4570.     for (v = ShiftW(opp,Current->mask) & Pawn(me) & Line(me,6); T(v); Cut(v)) {
  4571.         AddMove(lsb(v),lsb(v)+PushE(me),FlagPQueen,MvvLvaPromotionCap(Square(lsb(v)+PushE(me))))
  4572.         if (NAtt[lsb(King(opp))] & Bit(lsb(v) + PushE(me))) AddMove(lsb(v),lsb(v)+PushE(me),FlagPKnight,MvvLvaPromotionKnightCap(Square(lsb(v)+PushE(me))))
  4573.     }
  4574.     for (v = ShiftE(opp,Current->mask) & Pawn(me) & Line(me,6); T(v); Cut(v)) {
  4575.         AddMove(lsb(v),lsb(v)+PushW(me),FlagPQueen,MvvLvaPromotionCap(Square(lsb(v)+PushW(me))))
  4576.         if (NAtt[lsb(King(opp))] & Bit(lsb(v) + PushW(me))) AddMove(lsb(v),lsb(v)+PushW(me),FlagPKnight,MvvLvaPromotionKnightCap(Square(lsb(v)+PushE(me))))
  4577.     }
  4578.     if (F(Current->att[me] & Current->mask)) goto finish;
  4579.     for (v = ShiftW(opp,Current->mask) & Pawn(me) & (~Line(me,6)); T(v); Cut(v)) AddCaptureP(IPawn(me),lsb(v),lsb(v)+PushE(me),0)
  4580.     for (v = ShiftE(opp,Current->mask) & Pawn(me) & (~Line(me,6)); T(v); Cut(v)) AddCaptureP(IPawn(me),lsb(v),lsb(v)+PushW(me),0)
  4581.     for (v = SArea[lsb(King(me))] & Current->mask & (~Current->att[opp]); T(v); Cut(v)) AddCaptureP(IKing(me),lsb(King(me)),lsb(v),0)
  4582.     for (u = Knight(me); T(u); Cut(u))
  4583.         for (v = NAtt[lsb(u)] & Current->mask; T(v); Cut(v)) AddCaptureP(IKnight(me),lsb(u),lsb(v),0)
  4584.     for (u = Bishop(me); T(u); Cut(u))
  4585.         for (v = BishopAttacks(lsb(u),PieceAll) & Current->mask; T(v); Cut(v)) AddCapture(lsb(u),lsb(v),0)
  4586.     for (u = Rook(me); T(u); Cut(u))
  4587.         for (v = RookAttacks(lsb(u),PieceAll) & Current->mask; T(v); Cut(v)) AddCaptureP(IRook(me),lsb(u),lsb(v),0)
  4588.     for (u = Queen(me); T(u); Cut(u))
  4589.         for (v = QueenAttacks(lsb(u),PieceAll) & Current->mask; T(v); Cut(v)) AddCaptureP(IQueen(me),lsb(u),lsb(v),0)
  4590. finish:
  4591.     *list = 0;
  4592.     return list;
  4593. }
  4594.  
  4595. template <bool me> int * gen_evasions(int * list) {
  4596.     int king, att_sq, from;
  4597.     uint64 att, esc, b, u;
  4598.  
  4599.     king = lsb(King(me));
  4600.     att = (NAtt[king] & Knight(opp)) | (PAtt[me][king] & Pawn(opp));
  4601.     for (u = (BMask[king] & BSlider(opp)) | (RMask[king] & RSlider(opp)); T(u); u ^= b) {
  4602.         b = Bit(lsb(u));
  4603.         if (F(Between[king][lsb(u)] & PieceAll)) att |= b;
  4604.     }
  4605.     att_sq = lsb(att);
  4606.     esc = SArea[king] & (~(Piece(me) | Current->att[opp])) & Current->mask;
  4607.     if (Square(att_sq) >= WhiteLight) esc &= ~FullLine[king][att_sq];
  4608.     Cut(att);
  4609.     if (att) {
  4610.         att_sq = lsb(att);
  4611.         if (Square(att_sq) >= WhiteLight) esc &= ~FullLine[king][att_sq];
  4612.         for (; T(esc); Cut(esc)) AddCaptureP(IKing(me),king,lsb(esc),0)
  4613.         *list = 0;
  4614.         return list;
  4615.     }
  4616.     if (Bit(att_sq) & Current->mask) {
  4617.         if (T(Current->ep_square) && Current->ep_square == att_sq + Push(me))
  4618.             for (u = PAtt[opp][att_sq + Push(me)] & Pawn(me); T(u); Cut(u)) AddMove(lsb(u),att_sq + Push(me),FlagEP,MvvLva[IPawn(me)][IPawn(opp)])
  4619.     }
  4620.     for (u = PAtt[opp][att_sq] & Pawn(me); T(u); Cut(u)) {
  4621.         from = lsb(u);
  4622.         if (Bit(att_sq) & Line(me,7)) AddMove(from,att_sq,FlagPQueen,MvvLvaPromotionCap(Square(att_sq)))
  4623.         else if (Bit(att_sq) & Current->mask) AddCaptureP(IPawn(me),from,att_sq,0)
  4624.     }
  4625.     for ( ; T(esc); Cut(esc)) AddCaptureP(IKing(me),king,lsb(esc),0)
  4626.     att = Between[king][att_sq];
  4627.     for (u = Shift(opp,att) & Pawn(me); T(u); Cut(u)) {
  4628.         from = lsb(u);
  4629.         if (Bit(from) & Line(me,6)) AddMove(from,from + Push(me),FlagPQueen,MvvLvaPromotion)
  4630.         else if (F(~Current->mask)) AddMove(from,from + Push(me),0,0)
  4631.     }
  4632.     if (F(~Current->mask)) {
  4633.         for (u = Shift(opp,Shift(opp,att)) & Line(me, 1) & Pawn(me); T(u); Cut(u))
  4634.             if (F(Square(lsb(u)+Push(me)))) AddMove(lsb(u),lsb(u) + 2 * Push(me),0,0)
  4635.     }
  4636.     att |= Bit(att_sq);
  4637.     for (u = Knight(me); T(u); Cut(u))
  4638.         for (esc = NAtt[lsb(u)] & att; T(esc); esc ^= b) {
  4639.             b = Bit(lsb(esc));
  4640.             if (b & Current->mask) AddCaptureP(IKnight(me),lsb(u),lsb(esc),0)
  4641.         }
  4642.     for (u = Bishop(me); T(u); Cut(u))
  4643.         for (esc = BishopAttacks(lsb(u),PieceAll) & att; T(esc); esc ^= b) {
  4644.             b = Bit(lsb(esc));
  4645.             if (b & Current->mask) AddCapture(lsb(u),lsb(esc),0)
  4646.         }
  4647.     for (u = Rook(me); T(u); Cut(u))
  4648.         for (esc = RookAttacks(lsb(u),PieceAll) & att; T(esc); esc ^= b) {
  4649.             b = Bit(lsb(esc));
  4650.             if (b & Current->mask) AddCaptureP(IRook(me),lsb(u),lsb(esc),0)
  4651.         }
  4652.     for (u = Queen(me); T(u); Cut(u))
  4653.         for (esc = QueenAttacks(lsb(u),PieceAll) & att; T(esc); esc ^= b) {
  4654.             b = Bit(lsb(esc));
  4655.             if (b & Current->mask) AddCaptureP(IQueen(me),lsb(u),lsb(esc),0)
  4656.         }
  4657.     *list = 0;
  4658.     return list;
  4659. }
  4660.  
  4661. void mark_evasions(int * list) {
  4662.     for (; T(*list); list++) {
  4663.         register int move = (*list) & 0xFFFF;
  4664.         if (F(Square(To(move))) && F(move & 0xE000)) {
  4665.             if (move == Current->ref[0]) *list |= RefOneScore;
  4666.             else if (move == Current->ref[1]) *list |= RefTwoScore;
  4667.             else if (move == Current->killer[1]) *list |= KillerOneScore;
  4668.             else if (move == Current->killer[2]) *list |= KillerTwoScore;
  4669.             else *list |= HistoryP(Square(From(move)),From(move),To(move));
  4670.         }
  4671.     }
  4672. }
  4673.  
  4674. template <bool me> int * gen_quiet_moves(int * list) {
  4675.     int to;
  4676.     uint64 u, v, free, occ;
  4677.  
  4678.     occ = PieceAll;
  4679.     free = ~occ;
  4680.     if (me == White) {
  4681.         if (T(Current->castle_flags & CanCastle_OO) && F(occ & 0x60) && F(Current->att[Black] & 0x70)) AddHistoryP(IKing(White),4,6,FlagCastling)
  4682.         if (T(Current->castle_flags & CanCastle_OOO) && F(occ & 0xE) && F(Current->att[Black] & 0x1C)) AddHistoryP(IKing(White),4,2,FlagCastling)
  4683.     } else {
  4684.         if (T(Current->castle_flags & CanCastle_oo) && F(occ & 0x6000000000000000) && F(Current->att[White] & 0x7000000000000000)) AddHistoryP(IKing(Black),60,62,FlagCastling)
  4685.         if (T(Current->castle_flags & CanCastle_ooo) && F(occ & 0x0E00000000000000) && F(Current->att[White] & 0x1C00000000000000)) AddHistoryP(IKing(Black),60,58,FlagCastling)
  4686.     }
  4687.     for (v = Shift(me,Pawn(me)) & free & (~Line(me,7)); T(v); Cut(v)) {
  4688.         to = lsb(v);
  4689.         if (T(Bit(to) & Line(me,2)) && F(Square(to + Push(me)))) AddHistoryP(IPawn(me),to - Push(me),to + Push(me),0)
  4690.         AddHistoryP(IPawn(me),to - Push(me),to,0)
  4691.     }
  4692.     for (u = Knight(me); T(u); Cut(u))
  4693.         for (v = free & NAtt[lsb(u)]; T(v); Cut(v)) AddHistoryP(IKnight(me),lsb(u),lsb(v),0)
  4694.     for (u = Bishop(me); T(u); Cut(u))
  4695.         for (v = free & BishopAttacks(lsb(u),occ); T(v); Cut(v)) AddHistory(lsb(u),lsb(v))
  4696.     for (u = Rook(me); T(u); Cut(u))
  4697.         for (v = free & RookAttacks(lsb(u),occ); T(v); Cut(v)) AddHistoryP(IRook(me),lsb(u),lsb(v),0)
  4698.     for (u = Queen(me); T(u); Cut(u))
  4699.         for (v = free & QueenAttacks(lsb(u),occ); T(v); Cut(v)) AddHistoryP(IQueen(me),lsb(u),lsb(v),0)
  4700.     for (v = SArea[lsb(King(me))] & free & (~Current->att[opp]); T(v); Cut(v)) AddHistoryP(IKing(me),lsb(King(me)),lsb(v),0)
  4701.     *list = 0;
  4702.     return list;
  4703. }
  4704.  
  4705. template <bool me> int * gen_checks(int * list) {
  4706.     int king, from;
  4707.     uint64 u, v, target, b_target, r_target, clear, xray;
  4708.  
  4709.     clear = ~(Piece(me) | Current->mask);
  4710.     king = lsb(King(opp));
  4711.     for (u = Current->xray[me] & Piece(me); T(u); Cut(u)) {
  4712.         from = lsb(u);
  4713.         target = clear & (~FullLine[king][from]);
  4714.         if (Square(from) == IPawn(me)) {
  4715.             if (F(Bit(from + Push(me)) & Line(me,7))) {
  4716.                 if (T(Bit(from + Push(me)) & target) && F(Square(from + Push(me)))) AddMove(from,from + Push(me),0,MvvLvaXray)
  4717.                 for (v = PAtt[me][from] & target & Piece(opp); T(v); Cut(v)) AddMove(from,lsb(v),0,MvvLvaXrayCap(Square(lsb(v))))
  4718.             }
  4719.         } else {
  4720.             if (Square(from) < WhiteLight) v = NAtt[from] & target;
  4721.             else if (Square(from) < WhiteRook) v = BishopAttacks(from,PieceAll) & target;
  4722.             else if (Square(from) < WhiteQueen) v = RookAttacks(from,PieceAll) & target;
  4723.             else if (Square(from) < WhiteKing) v = QueenAttacks(from,PieceAll) & target;
  4724.             else v = SArea[from] & target & (~Current->att[opp]);
  4725.             for ( ; T(v); Cut(v)) AddMove(from,lsb(v),0,MvvLvaXrayCap(Square(lsb(v))))
  4726.         }
  4727.     }
  4728.     xray = ~(Current->xray[me] & Board->bb[me]);
  4729.     for (u = Knight(me) & NArea[king] & xray; T(u); Cut(u))
  4730.         for (v = NAtt[king] & NAtt[lsb(u)] & clear; T(v); Cut(v)) AddCaptureP(IKnight(me),lsb(u),lsb(v),0)
  4731.     for (u = DArea[king] & Pawn(me) & (~Line(me,6)) & xray; T(u); Cut(u)) {
  4732.         from = lsb(u);
  4733.         for (v = PAtt[me][from] & PAtt[opp][king] & clear & Piece(opp); T(v); Cut(v)) AddCaptureP(IPawn(me),from,lsb(v),0)
  4734.         if (F(Square(from + Push(me))) && T(Bit(from + Push(me)) & PAtt[opp][king])) AddMove(from,from + Push(me),0,0)
  4735.     }
  4736.     b_target = BishopAttacks(king,PieceAll) & clear;
  4737.     r_target = RookAttacks(king,PieceAll) & clear;
  4738.     for (u = (Odd(king ^ Rank(king)) ? Board->bb[WhiteLight | me] : Board->bb[WhiteDark | me]) & xray; T(u); Cut(u))
  4739.         for (v = BishopAttacks(lsb(u),PieceAll) & b_target; T(v); Cut(v)) AddCapture(lsb(u),lsb(v),0)
  4740.     for (u = Rook(me) & xray; T(u); Cut(u))
  4741.         for (v = RookAttacks(lsb(u),PieceAll) & r_target; T(v); Cut(v)) AddCaptureP(IRook(me),lsb(u),lsb(v),0)
  4742.     for (u = Queen(me) & xray; T(u); Cut(u))
  4743.         for (v = QueenAttacks(lsb(u),PieceAll) & (b_target | r_target); T(v); Cut(v)) AddCaptureP(IQueen(me),lsb(u),lsb(v),0)
  4744.     *list = 0;
  4745.     return list;
  4746. }
  4747.  
  4748. template <bool me> int * gen_delta_moves(int * list) {
  4749.     int to;
  4750.     uint64 u, v, free, occ;
  4751.  
  4752.     occ = PieceAll;
  4753.     free = ~occ;
  4754.     if (me == White) {
  4755.         if (T(Current->castle_flags & CanCastle_OO) && F(occ & 0x60) && F(Current->att[Black] & 0x70)) AddCDeltaP(IKing(White),4,6,FlagCastling)
  4756.         if (T(Current->castle_flags & CanCastle_OOO) && F(occ & 0xE) && F(Current->att[Black] & 0x1C)) AddCDeltaP(IKing(White),4,2,FlagCastling)
  4757.     } else {
  4758.         if (T(Current->castle_flags & CanCastle_oo) && F(occ & 0x6000000000000000) && F(Current->att[White] & 0x7000000000000000)) AddCDeltaP(IKing(Black),60,62,FlagCastling)
  4759.         if (T(Current->castle_flags & CanCastle_ooo) && F(occ & 0x0E00000000000000) && F(Current->att[White] & 0x1C00000000000000)) AddCDeltaP(IKing(Black),60,58,FlagCastling)
  4760.     }
  4761.     for (v = Shift(me,Pawn(me)) & free & (~Line(me,7)); T(v); Cut(v)) {
  4762.         to = lsb(v);
  4763.         if (T(Bit(to) & Line(me,2)) && F(Square(to + Push(me)))) AddCDeltaP(IPawn(me),to - Push(me),to + Push(me),0)
  4764.         AddCDeltaP(IPawn(me),to - Push(me),to,0)
  4765.     }
  4766.     for (u = Knight(me); T(u); Cut(u))
  4767.         for (v = free & NAtt[lsb(u)]; T(v); Cut(v)) AddCDeltaP(IKnight(me),lsb(u),lsb(v),0)
  4768.     for (u = Bishop(me); T(u); Cut(u))
  4769.         for (v = free & BishopAttacks(lsb(u),occ); T(v); Cut(v)) AddCDelta(lsb(u),lsb(v))
  4770.     for (u = Rook(me); T(u); Cut(u))
  4771.         for (v = free & RookAttacks(lsb(u),occ); T(v); Cut(v)) AddCDeltaP(IRook(me),lsb(u),lsb(v),0)
  4772.     for (u = Queen(me); T(u); Cut(u))
  4773.         for (v = free & QueenAttacks(lsb(u),occ); T(v); Cut(v)) AddCDeltaP(IQueen(me),lsb(u),lsb(v),0)
  4774.     for (v = SArea[lsb(King(me))] & free & (~Current->att[opp]); T(v); Cut(v)) AddCDeltaP(IKing(me),lsb(King(me)),lsb(v),0)
  4775.     *list = 0;
  4776.     return list;
  4777. }
  4778.  
  4779. template <bool me> int singular_extension(int ext, int prev_ext, int margin_one, int margin_two, int depth, int killer) {
  4780.     int value = -MateValue;
  4781.     int singular = 0;
  4782.     if (ext < 1 + (prev_ext < 1)) {
  4783.         if (Check(me)) value = search_evasion<me, 1>(margin_one, depth, killer);
  4784.         else value = search<me, 1>(margin_one, depth, killer);
  4785.         if (value < margin_one) singular = 1;
  4786.     }
  4787.     if (value < margin_one && ext < 2 + (prev_ext < 1) - (prev_ext >= 2)) {
  4788.         if (Check(me)) value = search_evasion<me, 1>(margin_two, depth, killer);
  4789.         else value = search<me, 1>(margin_two, depth, killer);
  4790.         if (value < margin_two) singular = 2;
  4791.     }
  4792.     return singular;
  4793. }
  4794.  
  4795. template <bool me> __forceinline void capture_margin(int alpha, int &score) {
  4796.     if (Current->score + 200 < alpha) {
  4797.         if (Current->att[me] & Pawn(opp)) {
  4798.             Current->mask ^= Pawn(opp);
  4799.             score = Current->score + 200;
  4800.         }
  4801.         if (Current->score + 500 < alpha) {
  4802.             if (Current->att[me] & Minor(opp)) {
  4803.                 Current->mask ^= Minor(opp);
  4804.                 score = Current->score + 500;
  4805.             }
  4806.             if (Current->score + 700 < alpha) {
  4807.                 if (Current->att[me] & Rook(opp)) {
  4808.                     Current->mask ^= Rook(opp);
  4809.                     score = Current->score + 700;
  4810.                 }
  4811.                 if (Current->score + 1400 < alpha && (Current->att[me] & Queen(opp))) {
  4812.                     Current->mask ^= Queen(opp);
  4813.                     score = Current->score + 1400;
  4814.                 }
  4815.             }
  4816.         }
  4817.     }
  4818. }
  4819.  
  4820. template <bool me, bool pv> int q_search(int alpha, int beta, int depth, int flags) {
  4821.     int i, value, score, move, hash_move, hash_depth, cnt;
  4822.     GEntry * Entry;
  4823.  
  4824.     if (flags & FlagHaltCheck) halt_check;
  4825. #ifdef CPU_TIMING
  4826. #ifndef TIMING
  4827.     if (nodes > check_node + 0x4000) {
  4828. #else
  4829.     if (nodes > check_node + 0x100) {
  4830. #endif
  4831.         check_node = nodes;
  4832. #ifdef TIMING
  4833.         if (LastDepth >= 6)
  4834. #endif
  4835.         check_time(1);
  4836. #ifdef TUNER
  4837.         if (nodes > 64 * 1024 * 1024) longjmp(Jump, 1);
  4838. #endif
  4839.     }
  4840. #endif
  4841.     if (flags & FlagCallEvaluation) evaluate();
  4842.     if (Check(me)) return q_evasion<me, pv>(alpha, beta, depth, FlagHashCheck);
  4843.     score = Current->score + 3;
  4844.     if (score > alpha) {
  4845.         alpha = score;
  4846.         if (score >= beta) return score;
  4847.     }
  4848.  
  4849.     hash_move = hash_depth = 0;
  4850.     if (flags & FlagHashCheck) {
  4851.         for (i = 0, Entry = Hash + (High32(Current->key) & hash_mask); i < 4; Entry++, i++) {
  4852.             if (Low32(Current->key) == Entry->key) {
  4853.                 if (T(Entry->low_depth)) {
  4854.                     if (Entry->low >= beta && !pv) return Entry->low;
  4855.                     if (Entry->low_depth > hash_depth && T(Entry->move)) {
  4856.                         hash_move = Entry->move;
  4857.                         hash_depth = Entry->low_depth;
  4858.                     }
  4859.                 }
  4860.                 if (T(Entry->high_depth) && Entry->high <= alpha && !pv) return Entry->high;
  4861.                 break;
  4862.             }
  4863.         }
  4864.     }
  4865.  
  4866.     Current->mask = Piece(opp);
  4867.     capture_margin<me>(alpha, score);
  4868.  
  4869.     cnt = 0;
  4870.     if (T(hash_move)) {
  4871.         if (F(Bit(To(hash_move)) & Current->mask) && F(hash_move & 0xE000) && (depth < -8 || (Current->score + DeltaM(hash_move) <= alpha && F(is_check<me>(hash_move))))) goto skip_hash_move;
  4872.         if (is_legal<me>(move = hash_move)) {
  4873.             if (IsIllegal(me,move)) goto skip_hash_move;
  4874.             if (SeeValue[Square(To(move))] > SeeValue[Square(From(move))]) cnt++;
  4875.             do_move<me>(move);
  4876.             value = -q_search<opp, pv>(-beta, -alpha, depth - 1, FlagNeatSearch);
  4877.             undo_move<me>(move);
  4878.             if (value > score) {
  4879.                 score = value;
  4880.                 if (value > alpha) {
  4881.                     alpha = value;
  4882.                     if (value >= beta) goto cut;
  4883.                 }
  4884.             }
  4885.             if (F(Bit(To(hash_move)) & Current->mask) && F(hash_move & 0xE000) && (depth < -2 || depth <= -1 && Current->score + 50 < alpha) && alpha >= beta - 1 && !pv) return alpha;
  4886.         }
  4887.     }
  4888. skip_hash_move:
  4889.     gen_captures<me>(Current->moves);
  4890.     Current->current = Current->moves;
  4891.     while (move = pick_move()) {
  4892.         if (move == hash_move) continue;
  4893.         if (IsIllegal(me,move)) continue;
  4894.         if (F(see<me>(move,-50))) continue;
  4895.         if (SeeValue[Square(To(move))] > SeeValue[Square(From(move))]) cnt++;
  4896.         do_move<me>(move);
  4897.         value = -q_search<opp, pv>(-beta, -alpha, depth - 1, FlagNeatSearch);
  4898.         undo_move<me>(move);
  4899.         if (value > score) {
  4900.             score = value;
  4901.             if (value > alpha) {
  4902.                 alpha = value;
  4903.                 if (value >= beta) goto cut;
  4904.             }
  4905.         }
  4906.     }
  4907.  
  4908.     if (depth < -2) goto finish;
  4909.     if (depth <= -1 && Current->score + 50 < alpha) goto finish;
  4910.     gen_checks<me>(Current->moves);
  4911.     Current->current = Current->moves;
  4912.     while (move = pick_move()) {
  4913.         if (move == hash_move) continue;
  4914.         if (IsIllegal(me,move)) continue;
  4915.         if (IsRepetition(alpha + 1,move)) continue;
  4916.         if (F(see<me>(move,-50))) continue;
  4917.         do_move<me>(move);
  4918.         value = -q_evasion<opp, pv>(-beta, -alpha, depth - 1, FlagNeatSearch);
  4919.         undo_move<me>(move);
  4920.         if (value > score) {
  4921.             score = value;
  4922.             if (value > alpha) {
  4923.                 alpha = value;
  4924.                 if (value >= beta) goto cut;
  4925.             }
  4926.         }
  4927.     }
  4928.  
  4929.     if (T(cnt) || Current->score + 30 < alpha || T(Current->threat & Piece(me)) || T((Current->xray[opp] | Current->pin[opp]) & NonPawn(opp))
  4930.         || T(Pawn(opp) & Line(me, 1) & Shift(me,~PieceAll))) goto finish;
  4931.     Current->margin = alpha - Current->score + 6;
  4932.     gen_delta_moves<me>(Current->moves);
  4933.     Current->current = Current->moves;
  4934.     while (move = pick_move()) {
  4935.         if (move == hash_move) continue;
  4936.         if (IsIllegal(me,move)) continue;
  4937.         if (IsRepetition(alpha + 1,move)) continue;
  4938.         if (F(see<me>(move,-50))) continue;
  4939.         cnt++;
  4940.         do_move<me>(move);
  4941.         value = -q_search<opp, pv>(-beta, -alpha, depth - 1, FlagNeatSearch);
  4942.         undo_move<me>(move);
  4943.         if (value > score) {
  4944.             score = value;
  4945.             if (value > alpha) {
  4946.                 alpha = value;
  4947.                 if (value >= beta) {
  4948.                     if (Current->killer[1] != move) {
  4949.                         Current->killer[2] = Current->killer[1];
  4950.                         Current->killer[1] = move;
  4951.                     }
  4952.                     goto cut;
  4953.                 }
  4954.             }
  4955.         }
  4956.         if (cnt >= 3) break;
  4957.     }
  4958.  
  4959. finish:
  4960.     if (depth >= -2 && (depth >= 0 || Current->score + 50 >= alpha)) hash_high(score, 1);
  4961.     return score;
  4962. cut:
  4963.     hash_low(move, score, 1);
  4964.     return score;
  4965. }
  4966.  
  4967. template <bool me, bool pv> int q_evasion(int alpha, int beta, int depth, int flags) {
  4968.     int i, value, pext, score, move, cnt, hash_move, hash_depth;
  4969.     int *p;
  4970.     GEntry * Entry;
  4971.  
  4972.     score = Convert((Current - Data),int) - MateValue;
  4973.     if (flags & FlagHaltCheck) halt_check;
  4974.  
  4975.     hash_move = hash_depth = 0;
  4976.     if (flags & FlagHashCheck) {
  4977.         for (i = 0, Entry = Hash + (High32(Current->key) & hash_mask); i < 4; Entry++, i++) {
  4978.             if (Low32(Current->key) == Entry->key) {
  4979.                 if (T(Entry->low_depth)) {
  4980.                     if (Entry->low >= beta && !pv) return Entry->low;
  4981.                     if (Entry->low_depth > hash_depth && T(Entry->move)) {
  4982.                         hash_move = Entry->move;
  4983.                         hash_depth = Entry->low_depth;
  4984.                     }
  4985.                 }
  4986.                 if (T(Entry->high_depth) && Entry->high <= alpha && !pv) return Entry->high;
  4987.                 break;
  4988.             }
  4989.         }
  4990.     }
  4991.  
  4992.     if (flags & FlagCallEvaluation) evaluate();
  4993.     Current->mask = Filled;
  4994.     if (Current->score - 10 <= alpha && !pv) {
  4995.         Current->mask = Piece(opp);
  4996.         score = Current->score - 10;
  4997.         capture_margin<me>(alpha, score);
  4998.     }
  4999.  
  5000.     alpha = Max(score, alpha);
  5001.     pext = 0;
  5002.     gen_evasions<me>(Current->moves);
  5003.     Current->current = Current->moves;
  5004.     if (F(Current->moves[0])) return score;
  5005.     if (F(Current->moves[1])) pext = 1;
  5006.     else {
  5007.         Current->ref[0] = RefM(Current->move).check_ref[0];
  5008.         Current->ref[1] = RefM(Current->move).check_ref[1];
  5009.         mark_evasions(Current->moves);
  5010.         if (T(hash_move) && (T(Bit(To(hash_move)) & Current->mask) || T(hash_move & 0xE000))) {
  5011.             for (p = Current->moves; T(*p); p++) {
  5012.                 if (((*p) & 0xFFFF) == hash_move) {
  5013.                     *p |= 0x7FFF0000;
  5014.                     break;
  5015.                 }
  5016.             }
  5017.         }
  5018.     }
  5019.     cnt = 0;
  5020.     while (move = pick_move()) {
  5021.         if (IsIllegal(me,move)) continue;
  5022.         cnt++;
  5023.         if (IsRepetition(alpha + 1,move)) {
  5024.             score = Max(0, score);
  5025.             continue;
  5026.         }
  5027.         if (F(Square(To(move))) && F(move & 0xE000)) {
  5028.             if (cnt > 3 && F(is_check<me>(move)) && !pv) continue;
  5029.             if ((value = Current->score + DeltaM(move) + 10) <= alpha && !pv) {
  5030.                 score = Max(value, score);
  5031.                 continue;
  5032.             }
  5033.         }
  5034.         do_move<me>(move);
  5035.         value = -q_search<opp, pv>(-beta, -alpha, depth - 1 + pext, FlagNeatSearch);
  5036.         undo_move<me>(move);
  5037.         if (value > score) {
  5038.             score = value;
  5039.             if (value > alpha) {
  5040.                 alpha = value;
  5041.                 if (value >= beta) goto cut;
  5042.             }
  5043.         }
  5044.     }
  5045.     return score;
  5046. cut:
  5047.     return score;
  5048. }
  5049.  
  5050. void send_position(GPos * Pos) {
  5051.     Pos->Position->key = Current->key;
  5052.     Pos->Position->pawn_key = Current->pawn_key;
  5053.     Pos->Position->move = Current->move;
  5054.     Pos->Position->capture = Current->capture;
  5055.     Pos->Position->turn = Current->turn;
  5056.     Pos->Position->castle_flags = Current->castle_flags;
  5057.     Pos->Position->ply = Current->ply;
  5058.     Pos->Position->ep_square = Current->ep_square;
  5059.     Pos->Position->piece = Current->piece;
  5060.     Pos->Position->pst = Current->pst;
  5061.     Pos->Position->material = Current->material;
  5062.     for (int i = 0; i < 64; i++) Pos->Position->square[i] = Board->square[i];
  5063.     Pos->date = date;
  5064.     Pos->sp = sp;
  5065.     for (int i = 0; i <= Current->ply; i++) Pos->stack[i] = Stack[sp - i];
  5066.     for (int i = 0; i < Min(16, 126 - (int)(Current - Data)); i++) {
  5067.         Pos->killer[i][0] = (Current + i + 1)->killer[1];
  5068.         Pos->killer[i][1] = (Current + i + 1)->killer[2];
  5069.     }
  5070.     for (int i = Min(16, 126 - (int)(Current - Data)); i < 16; i++) Pos->killer[i][0] = Pos->killer[i][1] = 0;
  5071. }
  5072.  
  5073. void retrieve_board(GPos * Pos) {
  5074.     for (int i = 0; i < 16; i++) Board->bb[i] = 0;
  5075.     for (int i = 0; i < 64; i++) {
  5076.         int piece = Pos->Position->square[i];
  5077.         Board->square[i] = piece;
  5078.         if (piece) {
  5079.             Board->bb[piece & 1] |= Bit(i);
  5080.             Board->bb[piece] |= Bit(i);
  5081.         }
  5082.     }
  5083. }
  5084.  
  5085. void retrieve_position(GPos * Pos, int copy_stack) {
  5086.     Current->key = Pos->Position->key;
  5087.     Current->pawn_key = Pos->Position->pawn_key;
  5088.     Current->move = Pos->Position->move;
  5089.     Current->capture = Pos->Position->capture;
  5090.     Current->turn = Pos->Position->turn;
  5091.     Current->castle_flags = Pos->Position->castle_flags;
  5092.     Current->ply = Pos->Position->ply;
  5093.     Current->ep_square = Pos->Position->ep_square;
  5094.     Current->piece = Pos->Position->piece;
  5095.     Current->pst = Pos->Position->pst;
  5096.     Current->material = Pos->Position->material;
  5097.     retrieve_board(Pos);
  5098.     date = Pos->date;
  5099.     if (copy_stack) {
  5100.         sp = Current->ply;
  5101.         for (int i = 0; i <= sp; i++) Stack[sp - i] = Pos->stack[i];
  5102.     } else sp = Pos->sp;
  5103.     for (int i = 0; i < 16; i++) {
  5104.         (Current + i + 1)->killer[1] = Pos->killer[i][0];
  5105.         (Current + i + 1)->killer[2] = Pos->killer[i][1];
  5106.     }
  5107. }
  5108.  
  5109. void halt_all(GSP * Sp, int locked) {
  5110.     GMove * M;
  5111.     if (!locked) LOCK(Sp->lock);
  5112.     if (Sp->active) {
  5113.         for (int i = 0; i < Sp->move_number; i++) {
  5114.             M = &Sp->move[i];
  5115.             if ((M->flags & FlagClaimed) && !(M->flags & FlagFinished) && M->id != Id) SET_BIT_64(Smpi->stop, M->id);
  5116.         }
  5117.         Sp->active = Sp->claimed = 0;
  5118.         ZERO_BIT_64(Smpi->active_sp, (int)(Sp - Smpi->Sp));
  5119.     }
  5120.     if (!locked) UNLOCK(Sp->lock);
  5121. }
  5122.  
  5123. void halt_all(int from, int to) {
  5124.     for (uint64 u = Smpi->active_sp; u; Cut(u)) {
  5125.         GSP * Sp = &Smpi->Sp[lsb(u)];
  5126.         LOCK(Sp->lock);
  5127.         if (Sp->height >= from && Sp->height <= to) halt_all(Sp, 1);
  5128.         UNLOCK(Sp->lock);
  5129.     }
  5130. }
  5131.  
  5132. void init_sp(GSP * Sp, int alpha, int beta, int depth, int pv, int singular, int height) {
  5133.     Sp->claimed = 1;
  5134.     Sp->active = Sp->finished = 0;
  5135.     Sp->best_move = 0;
  5136.     Sp->alpha = alpha;
  5137.     Sp->beta = beta;
  5138.     Sp->depth = depth;
  5139.     Sp->split = 0;
  5140.     Sp->singular = singular;
  5141.     Sp->height = height;
  5142.     Sp->move_number = 0;
  5143.     Sp->pv = pv;
  5144. }
  5145.  
  5146. template <bool me> int smp_search(GSP * Sp) {
  5147.     int i, value, move, alpha, iter = 0;
  5148.     if (!Sp->move_number) return Sp->alpha;
  5149.     send_position(Sp->Pos);
  5150.     if (setjmp(Sp->jump)) {
  5151.         LOCK(Sp->lock);
  5152.         halt_all(Sp, 1);
  5153.         UNLOCK(Sp->lock);
  5154.         halt_all(Sp->height + 1, 127);
  5155.         Current = Data + Sp->height;
  5156.         sp = Sp->Pos->sp;
  5157.         retrieve_board(Sp->Pos);
  5158.         return Sp->beta;
  5159.     }
  5160.     LOCK(Sp->lock);
  5161.     SET_BIT_64(Smpi->active_sp, (int)(Sp - Smpi->Sp));
  5162.     Sp->active = 1;
  5163.     Sp->claimed = Sp->finished = 0;
  5164. loop:
  5165.     for (i = 0; i < Sp->move_number; i++) {
  5166.         GMove * M = &Sp->move[i];
  5167.         if (!iter) Sp->current = i;
  5168.         if (M->flags & FlagFinished) continue;
  5169.         if (!iter) {
  5170.             if (M->flags & FlagClaimed) continue;
  5171.             M->flags |= FlagClaimed;
  5172.             M->id = Id;
  5173.         } else if (M->flags & FlagClaimed) {
  5174.             SET_BIT_64(Smpi->stop, M->id);
  5175.             M->id = Id;
  5176.         }
  5177.         move = M->move;
  5178.         alpha = Sp->alpha;
  5179.         UNLOCK(Sp->lock);
  5180.         do_move<me>(move);
  5181.         value = -search<opp, 0>(-alpha, M->reduced_depth, FlagNeatSearch | ExtFlag(M->ext));
  5182.         if (value > alpha && (Sp->pv || M->reduced_depth < M->research_depth)) {
  5183.             if (Sp->pv) value = -pv_search<opp, 0>(-Sp->beta, -Sp->alpha, M->research_depth, FlagNeatSearch | ExtFlag(M->ext));
  5184.             else value = -search<opp, 0>(-alpha, M->research_depth, FlagNeatSearch | FlagDisableNull | ExtFlag(M->ext));
  5185.         }
  5186.         undo_move<me>(move);
  5187.         LOCK(Sp->lock);
  5188.         if (Sp->finished) goto cut;
  5189.         M->flags |= FlagFinished;
  5190.         if (value > Sp->alpha) {
  5191.             Sp->best_move = move;
  5192.             Sp->alpha = Min(value, Sp->beta);
  5193.             if (value >= Sp->beta) goto cut;
  5194.         }
  5195.     }
  5196.     if (!iter) {
  5197.         iter++;
  5198.         goto loop;
  5199.     }
  5200.     halt_all(Sp, 1);
  5201.     UNLOCK(Sp->lock);
  5202.     return Sp->alpha;
  5203. cut:
  5204.     halt_all(Sp, 1);
  5205.     UNLOCK(Sp->lock);
  5206.     return Sp->beta;
  5207. }
  5208.  
  5209. template <bool me, bool exclusion> int search(int beta, int depth, int flags) {
  5210.     int i, value, cnt, flag, moves_to_play, check, score, move, ext, margin, hash_move, do_split, sp_init, singular, played,
  5211.         high_depth, high_value, hash_value, new_depth, move_back, hash_depth, *p;
  5212.     int height = (int)(Current - Data);
  5213.     GSP * Sp;
  5214.  
  5215. #ifndef TUNER
  5216.     if (nodes > check_node_smp + 0x10) {
  5217. #ifndef W32_BUILD
  5218.         InterlockedAdd64(&Smpi->nodes, (long long)(nodes)-(long long)(check_node_smp));
  5219. #else
  5220.         Smpi->nodes += (long long)(nodes)-(long long)(check_node_smp);
  5221. #endif
  5222.         check_node_smp = nodes;
  5223.         check_state();
  5224.         if (nodes > check_node + 0x4000 && parent) {
  5225.             check_node = nodes;
  5226.             check_time(1);
  5227.             if (Searching) SET_BIT_64(Smpi->searching, Id); // BUG, don't know why this is necessary
  5228.         }
  5229.     }
  5230. #endif
  5231.  
  5232.     if (depth <= 1) return q_search<me, 0>(beta - 1, beta, 1, flags);
  5233.     if (flags & FlagHaltCheck) {
  5234.         if (height - MateValue >= beta) return beta;
  5235.         if (MateValue - height < beta) return beta - 1;
  5236.         halt_check;
  5237.     }
  5238.  
  5239.     if (exclusion) {
  5240.         cnt = high_depth = do_split = sp_init = singular = played = 0;
  5241.         flag = 1;
  5242.         score = beta - 1;
  5243.         high_value = MateValue;
  5244.         hash_value = -MateValue;
  5245.         hash_depth = -1;
  5246.         hash_move = flags & 0xFFFF;
  5247.         goto skip_hash_move;
  5248.     }
  5249.  
  5250.     if (flags & FlagCallEvaluation) evaluate();
  5251.     if (Check(me)) return search_evasion<me, 0>(beta, depth, flags & (~(FlagHaltCheck | FlagCallEvaluation)));
  5252.  
  5253.     if ((value = Current->score - 90 - (depth << 3) - (Max(depth - 5, 0) << 5)) >= beta && F(Pawn(opp) & Line(me, 1) & Shift(me,~PieceAll)) && T(NonPawnKing(me)) && F(flags & (FlagReturnBestMove | FlagDisableNull)) && depth <= 13) return value;
  5254.     if ((value = Current->score + 50) < beta && depth <= 3) return MaxF(value, q_search<me, 0>(beta - 1, beta, 1, FlagHashCheck | (flags & 0xFFFF)));
  5255.  
  5256.     high_depth = 0;
  5257.     high_value = MateValue;
  5258.     hash_value = -MateValue;
  5259.     hash_depth = -1;
  5260.     Current->best = hash_move = flags & 0xFFFF;
  5261.     if (GEntry * Entry = probe_hash()) {
  5262.         if (Entry->high_depth > high_depth) {
  5263.             high_depth = Entry->high_depth;
  5264.             high_value = Entry->high;
  5265.         }
  5266.         if (Entry->high < beta && Entry->high_depth >= depth) return Entry->high;
  5267.         if (T(Entry->move) && Entry->low_depth > hash_depth) {
  5268.             Current->best = hash_move = Entry->move;
  5269.             hash_depth = Entry->low_depth;
  5270.             if (Entry->low_depth) hash_value = Entry->low;
  5271.         }
  5272.         if (Entry->low >= beta && Entry->low_depth >= depth) {
  5273.             if (Entry->move) {
  5274.                 Current->best = Entry->move;
  5275.                 if (F(Square(To(Entry->move))) && F(Entry->move & 0xE000)) {
  5276.                     if (Current->killer[1] != Entry->move && F(flags & FlagNoKillerUpdate)) {
  5277.                         Current->killer[2] = Current->killer[1];
  5278.                         Current->killer[1] = Entry->move;
  5279.                     }
  5280.                     UpdateRef(Entry->move);
  5281.                 }
  5282.                 return Entry->low;
  5283.             }
  5284.             if (F(flags & FlagReturnBestMove)) return Entry->low;
  5285.         }
  5286.     }
  5287.     if (depth >= 20) if (GPVEntry * PVEntry = probe_pv_hash()) {
  5288.         hash_low(PVEntry->move,PVEntry->value,PVEntry->depth);
  5289.         hash_high(PVEntry->value,PVEntry->depth);
  5290.         if (PVEntry->depth >= depth) {
  5291.             if (PVEntry->move) Current->best = PVEntry->move;
  5292.             if (F(flags & FlagReturnBestMove) && ((Current->ply <= 50 && PVEntry->ply <= 50) || (Current->ply >= 50 && PVEntry->ply >= 50))) return PVEntry->value;
  5293.         }
  5294.         if (T(PVEntry->move) && PVEntry->depth > hash_depth) {
  5295.             Current->best = hash_move = PVEntry->move;
  5296.             hash_depth = PVEntry->depth;
  5297.             hash_value = PVEntry->value;
  5298.         }
  5299.     }
  5300.     if (depth < 10) score = height - MateValue;
  5301.     else score = beta - 1;
  5302.     if (depth >= 12 && (F(hash_move) || hash_value < beta || hash_depth < depth - 12) && (high_value >= beta || high_depth < depth - 12) && F(flags & FlagDisableNull)) {
  5303.         new_depth = depth - 8;
  5304.         value = search<me, 0>(beta, new_depth, FlagHashCheck | FlagNoKillerUpdate | FlagDisableNull | FlagReturnBestMove | hash_move);
  5305.         if (value >= beta) {
  5306.             if (Current->best) hash_move = Current->best;
  5307.             hash_depth = new_depth;
  5308.             hash_value = beta;
  5309.         }
  5310.     }
  5311.     if (depth >= 4 && Current->score + 3 >= beta && F(flags & (FlagDisableNull | FlagReturnBestMove))
  5312.         && (high_value >= beta || high_depth < depth - 10) && (depth < 12 || (hash_value >= beta && hash_depth >= depth - 12)) && beta > -EvalValue && T(NonPawnKing(me))) {
  5313.         new_depth = depth - 8;
  5314.         do_null();
  5315.         value = -search<opp, 0>(1 - beta, new_depth, FlagHashCheck);
  5316.         undo_null();
  5317.         if (value >= beta) {
  5318.             if (depth < 12) hash_low(0, value, depth);
  5319.             return value;
  5320.         }
  5321.     }
  5322.  
  5323.     cnt = flag = singular = played = 0;
  5324.     if (T(hash_move) && is_legal<me>(move = hash_move)) {
  5325.         if (IsIllegal(me,move)) goto skip_hash_move;
  5326.         cnt++;
  5327.         check = is_check<me>(move);
  5328.         if (check) ext = 1 + (depth < 16);
  5329.         else ext = extension<0>(move, depth);
  5330.         if (depth >= 16 && hash_value >= beta && hash_depth >= (new_depth = depth - Min(12, depth/2))) {
  5331.             int margin_one = beta - ExclSingle(depth);
  5332.             int margin_two = beta - ExclDouble(depth);
  5333.             int prev_ext = Ext(flags);
  5334.             singular = singular_extension<me>(ext,prev_ext,margin_one,margin_two,new_depth,hash_move);
  5335.             if (singular) ext = Max(ext, singular + (prev_ext < 1) - (singular >= 2 && prev_ext >= 2));
  5336.         }
  5337.         if (depth < 16 && To(move) == To(Current->move) && T(Square(To(move)))) ext = Max(ext, 2);
  5338.         new_depth = depth - 2 + ext;
  5339.         do_move<me>(move);
  5340.         value = -search<opp, 0>(1 - beta, new_depth, FlagNeatSearch | ((hash_value >= beta && hash_depth >= depth - 12) ? FlagDisableNull : 0) | ExtFlag(ext));
  5341.         undo_move<me>(move);
  5342.         played++;
  5343.         if (value > score) {
  5344.             score = value;
  5345.             if (value >= beta) goto cut;
  5346.         }
  5347.     }
  5348. skip_hash_move:
  5349.     Current->killer[0] = 0;
  5350.     Current->stage = stage_search;
  5351.     Current->gen_flags = 0;
  5352.     Current->ref[0] = RefM(Current->move).ref[0];
  5353.     Current->ref[1] = RefM(Current->move).ref[1];
  5354.     move_back = 0;
  5355.     if (beta > 0 && Current->ply >= 2) {
  5356.         if (F((Current - 1)->move & 0xF000)) {
  5357.             move_back = (To((Current - 1)->move) << 6) | From((Current - 1)->move);
  5358.             if (Square(To(move_back))) move_back = 0;
  5359.         }
  5360.     }
  5361.     moves_to_play = 3 + (depth * depth)/6;
  5362.     margin = Current->score + 70 + (depth << 3) + (Max(depth - 7, 0) << 5);
  5363.     if ((value = margin) < beta && depth <= 19) {
  5364.         flag = 1;
  5365.         score = Max(value, score);
  5366.         Current->stage = stage_razoring;
  5367.         Current->mask = Piece(opp);
  5368.         if ((value = Current->score + 200 + (depth << 5)) < beta) {
  5369.             score = Max(value, score);
  5370.             Current->mask ^= Pawn(opp);
  5371.         }
  5372.     }
  5373.     Current->current = Current->moves;
  5374.     Current->moves[0] = 0;
  5375.     if (depth <= 5) Current->gen_flags |= FlagNoBcSort;
  5376.    
  5377.     do_split = sp_init = 0;
  5378.     if (depth >= SplitDepth && PrN > 1 && parent && !exclusion) do_split = 1;
  5379.  
  5380.     while (move = get_move<me,0>()) {
  5381.         if (move == hash_move) continue;
  5382.         if (IsIllegal(me,move)) continue;
  5383.         cnt++;
  5384.         if (move == move_back) {
  5385.             score = Max(0, score);
  5386.             continue;
  5387.         }
  5388.         if (Current->stage == r_checks) check = 1;
  5389.         else check = is_check<me>(move);
  5390.         if (T(check) && T(see<me>(move, 0))) ext = 1 + (depth < 16);
  5391.         else ext = extension<0>(move, depth);
  5392.         new_depth = depth - 2 + ext;
  5393.         if (F(Square(To(move))) && F(move & 0xE000)) {
  5394.             if (move != Current->killer[1] && move != Current->killer[2]) {
  5395.                 if (F(check) && cnt > moves_to_play) {
  5396.                     Current->gen_flags &= ~FlagSort;
  5397.                     continue;
  5398.                 }
  5399.                 if (depth >= 6) {
  5400.                     int reduction = msb(cnt);
  5401.                     if (move == Current->ref[0] || move == Current->ref[1]) reduction = Max(0, reduction - 1);
  5402.                     if (reduction >= 2 && !(Queen(White) | Queen(Black)) && popcnt(NonPawnKingAll) <= 4) reduction += reduction / 2;
  5403.                     if (new_depth - reduction > 3)
  5404.                         if (F(see<me>(move, -50))) reduction += 2;
  5405.                     if (T(reduction) && reduction < 2 && new_depth - reduction > 3) {
  5406.                         if (cnt > 3) reduction = 2;
  5407.                         else reduction = 0;
  5408.                     }
  5409.                     new_depth = Max(3, new_depth - reduction);
  5410.                 }
  5411.             }
  5412.             if (F(check)) {
  5413.                 if ((value = Current->score + DeltaM(move) + 10) < beta && depth <= 3) {
  5414.                     score = Max(value, score);
  5415.                     continue;
  5416.                 }
  5417.                 if (cnt > 7 && (value = margin + DeltaM(move) - 25 * msb(cnt)) < beta && depth <= 19) {
  5418.                     score = Max(value, score);
  5419.                     continue;
  5420.                 }
  5421.             }
  5422.             if (depth <= 9 && T(NonPawnKing(me)) && F(see<me>(move,-50))) continue;
  5423.         } else {
  5424.             if (Current->stage == r_cap) {
  5425.                 if (F(check) && depth <= 9 && F(see<me>(move,-50))) continue;
  5426.             } else if (Current->stage == s_bad_cap && F(check) && depth <= 5) continue;
  5427.         }
  5428.         if (do_split && played >= 1) {
  5429.             if (!sp_init) {
  5430.                 sp_init = 1;
  5431.                 uint64 u = ~Smpi->active_sp;
  5432.                 if (!u) {
  5433.                     do_split = 0;
  5434.                     goto make_move;
  5435.                 }
  5436.                 Sp = &Smpi->Sp[lsb(u)];
  5437.                 init_sp(Sp, beta - 1, beta, depth, 0, singular, height);
  5438.             }
  5439.             GMove * M = &Sp->move[Sp->move_number++];
  5440.             M->ext = ext;
  5441.             M->flags = 0;
  5442.             M->move = move;
  5443.             M->reduced_depth = new_depth;
  5444.             M->research_depth = depth - 2 + ext;
  5445.             M->stage = Current->stage;
  5446.             continue;
  5447.         }
  5448. make_move:
  5449.         do_move<me>(move);
  5450.         value = -search<opp, 0>(1 - beta, new_depth, FlagNeatSearch | ExtFlag(ext));
  5451.         if (value >= beta && new_depth < depth - 2 + ext) value = -search<opp, 0>(1 - beta, depth - 2 + ext, FlagNeatSearch | FlagDisableNull | ExtFlag(ext));
  5452.         undo_move<me>(move);
  5453.         played++;
  5454.         if (value > score) {
  5455.             score = value;
  5456.             if (value >= beta) goto cut;
  5457.         }
  5458.     }
  5459.     if (do_split && sp_init) {
  5460.         value = smp_search<me>(Sp);
  5461.         if (value >= beta && Sp->best_move) {
  5462.             score = beta;
  5463.             Current->best = move = Sp->best_move;
  5464.             for (i = 0; i < Sp->move_number; i++) {
  5465.                 GMove * M = &Sp->move[i];
  5466.                 if ((M->flags & FlagFinished) && M->stage == s_quiet && M->move != move) HistoryBad(M->move);
  5467.             }
  5468.         }
  5469.         if (value >= beta) goto cut;
  5470.     }
  5471.     if (F(cnt) && F(flag)) {
  5472.         hash_high(0, 127);
  5473.         hash_low(0, 0, 127);
  5474.         return 0;
  5475.     }
  5476.     if (F(exclusion)) hash_high(score, depth);
  5477.     return score;
  5478. cut:
  5479.     if (exclusion) return score;
  5480.     Current->best = move;
  5481.     if (depth >= 10) score = Min(beta, score);
  5482.     hash_low(move, score, depth);
  5483.     if (F(Square(To(move))) && F(move & 0xE000)) {
  5484.         if (Current->killer[1] != move && F(flags & FlagNoKillerUpdate)) {
  5485.             Current->killer[2] = Current->killer[1];
  5486.             Current->killer[1] = move;
  5487.         }
  5488.         HistoryGood(move);
  5489.         if (move != hash_move && Current->stage == s_quiet && !sp_init) for (p = Current->start; p < (Current->current - 1); p++) HistoryBad(*p);
  5490.         UpdateRef(move);
  5491.     }
  5492.     return score;
  5493. }
  5494.  
  5495. template <bool me, bool exclusion> int search_evasion(int beta, int depth, int flags) {
  5496.     int i, value, score, pext, move, cnt, hash_value = -MateValue, hash_depth, hash_move, new_depth, ext, check, moves_to_play;
  5497.     int height = (int)(Current - Data);
  5498.  
  5499.     if (depth <= 1) return q_evasion<me, 0>(beta - 1, beta, 1, flags);
  5500.     score = height - MateValue;
  5501.     if (flags & FlagHaltCheck) {
  5502.         if (score >= beta) return beta;
  5503.         if (MateValue - height < beta) return beta - 1;
  5504.         halt_check;
  5505.     }
  5506.  
  5507.     hash_depth = -1;
  5508.     hash_move = flags & 0xFFFF;
  5509.     if (exclusion) {
  5510.         cnt = pext = 0;
  5511.         score = beta - 1;
  5512.         gen_evasions<me>(Current->moves);
  5513.         if (F(Current->moves[0])) return score;
  5514.         goto skip_hash_move;
  5515.     }
  5516.     Current->best = hash_move;
  5517.     if (GEntry * Entry = probe_hash()) {
  5518.         if (Entry->high < beta && Entry->high_depth >= depth) return Entry->high;
  5519.         if (T(Entry->move) && Entry->low_depth > hash_depth) {
  5520.             Current->best = hash_move = Entry->move;
  5521.             hash_depth = Entry->low_depth;
  5522.         }
  5523.         if (Entry->low >= beta && Entry->low_depth >= depth) {
  5524.             if (Entry->move) {
  5525.                 Current->best = Entry->move;
  5526.                 if (F(Square(To(Entry->move))) && F(Entry->move & 0xE000)) UpdateCheckRef(Entry->move);
  5527.             }
  5528.             return Entry->low;
  5529.         }
  5530.         if (Entry->low_depth >= depth - 8 && Entry->low > hash_value) hash_value = Entry->low;
  5531.     }
  5532.  
  5533.     if (depth >= 20) if (GPVEntry * PVEntry  = probe_pv_hash()) {
  5534.         hash_low(PVEntry->move,PVEntry->value,PVEntry->depth);
  5535.         hash_high(PVEntry->value,PVEntry->depth);
  5536.         if (PVEntry->depth >= depth) {
  5537.             if (PVEntry->move) Current->best = PVEntry->move;
  5538.             return PVEntry->value;
  5539.         }
  5540.         if (T(PVEntry->move) && PVEntry->depth > hash_depth) {
  5541.             Current->best = hash_move = PVEntry->move;
  5542.             hash_depth = PVEntry->depth;
  5543.             hash_value = PVEntry->value;
  5544.         }
  5545.     }
  5546.  
  5547.     if (hash_depth >= depth && hash_value > -EvalValue) score = Min(beta - 1, Max(score, hash_value));
  5548.     if (flags & FlagCallEvaluation) evaluate();
  5549.  
  5550.     Current->mask = Filled;
  5551.     if (Current->score - 10 < beta && depth <= 3) {
  5552.         Current->mask = Piece(opp);
  5553.         score = Current->score - 10;
  5554.         capture_margin<me>(beta, score);
  5555.     }
  5556.     cnt = 0;
  5557.     pext = 0;
  5558.     gen_evasions<me>(Current->moves);
  5559.     if (F(Current->moves[0])) return score;
  5560.     if (F(Current->moves[1])) pext = 2;
  5561.  
  5562.     if (T(hash_move) && is_legal<me>(move = hash_move)) {
  5563.         if (IsIllegal(me,move)) goto skip_hash_move;
  5564.         cnt++;
  5565.         check = is_check<me>(move);
  5566.         if (check) ext = Max(pext, 1 + (depth < 16));
  5567.         else ext = MaxF(pext, extension<0>(move, depth));
  5568.         if (depth >= 16 && hash_value >= beta && hash_depth >= (new_depth = depth - Min(12, depth/2))) {
  5569.             int margin_one = beta - ExclSingle(depth);
  5570.             int margin_two = beta - ExclDouble(depth);
  5571.             int prev_ext = Ext(flags);
  5572.             int singular = singular_extension<me>(ext,prev_ext,margin_one,margin_two,new_depth,hash_move);
  5573.             if (singular) ext = Max(ext, singular + (prev_ext < 1) - (singular >= 2 && prev_ext >= 2));
  5574.         }
  5575.         new_depth = depth - 2 + ext;
  5576.         do_move<me>(move);
  5577.         evaluate();
  5578.         if (Current->att[opp] & King(me)) {
  5579.             undo_move<me>(move);
  5580.             cnt--;
  5581.             goto skip_hash_move;
  5582.         }
  5583.         value = -search<opp, 0>(1 - beta, new_depth, FlagHaltCheck | FlagHashCheck | ((hash_value >= beta && hash_depth >= depth - 12) ? FlagDisableNull : 0) | ExtFlag(ext));
  5584.         undo_move<me>(move);
  5585.         if (value > score) {
  5586.             score = value;
  5587.             if (value >= beta) goto cut;
  5588.         }
  5589.     }
  5590. skip_hash_move:
  5591.     moves_to_play = 3 + ((depth * depth) / 6);
  5592.     Current->ref[0] = RefM(Current->move).check_ref[0];
  5593.     Current->ref[1] = RefM(Current->move).check_ref[1];
  5594.     mark_evasions(Current->moves);
  5595.     Current->current = Current->moves;
  5596.     while (move = pick_move()) {
  5597.         if (move == hash_move) continue;
  5598.         if (IsIllegal(me,move)) continue;
  5599.         cnt++;
  5600.         if (IsRepetition(beta,move)) {
  5601.             score = Max(0, score);
  5602.             continue;
  5603.         }
  5604.         check = is_check<me>(move);
  5605.         if (check) ext = Max(pext, 1 + (depth < 16));
  5606.         else ext = MaxF(pext, extension<0>(move, depth));
  5607.         new_depth = depth - 2 + ext;
  5608.         if (F(Square(To(move))) && F(move & 0xE000)) {
  5609.             if (F(check)) {
  5610.                 if (cnt > moves_to_play) continue;
  5611.                 if ((value = Current->score + DeltaM(move) + 10) < beta && depth <= 3) {
  5612.                     score = Max(value, score);
  5613.                     continue;
  5614.                 }
  5615.             }
  5616.             if (depth >= 6 && cnt > 3) {
  5617.                 int reduction = msb(cnt);
  5618.                 if (reduction >= 2 && !(Queen(White) | Queen(Black)) && popcnt(NonPawnKingAll) <= 4) reduction += reduction / 2;
  5619.                 new_depth = Max(3, new_depth - reduction);
  5620.             }
  5621.         }
  5622.         do_move<me>(move);
  5623.         value = -search<opp, 0>(1 - beta, new_depth, FlagNeatSearch | ExtFlag(ext));
  5624.         if (value >= beta && new_depth < depth - 2 + ext) value = -search<opp, 0>(1 - beta, depth - 2 + ext, FlagNeatSearch | FlagDisableNull | ExtFlag(ext));
  5625.         undo_move<me>(move);
  5626.         if (value > score) {
  5627.             score = value;
  5628.             if (value >= beta) goto cut;
  5629.         }
  5630.     }
  5631.     if (F(exclusion)) hash_high(score, depth);
  5632.     return score;
  5633. cut:
  5634.     if (exclusion) return score;
  5635.     Current->best = move;
  5636.     hash_low(move, score, depth);
  5637.     if (F(Square(To(move))) && F(move & 0xE000)) UpdateCheckRef(move);
  5638.     return score;
  5639. }
  5640.  
  5641. template <bool me, bool root> int pv_search(int alpha, int beta, int depth, int flags) {
  5642.     int i, value, move, cnt, pext = 0, ext, check, hash_value = -MateValue, margin, do_split = 0, sp_init = 0, singular = 0, played = 0,
  5643.         new_depth, hash_move, hash_depth, old_alpha = alpha, old_best, ex_depth = 0, ex_value = 0, start_knodes = (nodes >> 10);
  5644.     GSP * Sp;
  5645.     int height = (int)(Current - Data);
  5646.  
  5647.     if (root) {
  5648.         depth = Max(depth, 2);
  5649.         flags |= ExtFlag(1);
  5650.         if (F(RootList[0])) return 0;
  5651.         if (Print) {
  5652.             fprintf(stdout,"info depth %d\n",(depth/2));
  5653.             fflush(stdout);
  5654.         }
  5655.         int * p;
  5656.         for (p = RootList; *p; p++);
  5657.         sort_moves(RootList,p);
  5658.         for (p = RootList; *p; p++) *p &= 0xFFFF;
  5659.         SetScore(RootList[0],2);
  5660.         goto check_hash;
  5661.     }
  5662.     if (depth <= 1) return q_search<me, 1>(alpha, beta, 1, FlagNeatSearch);
  5663.     if (Convert((Current - Data),int) - MateValue >= beta) return beta;
  5664.     if (MateValue - Convert((Current - Data),int) <= alpha) return alpha;
  5665.     halt_check;
  5666.  
  5667. check_hash:
  5668.     hash_depth = -1;
  5669.     Current->best = hash_move = 0;
  5670.     if (GPVEntry * PVEntry = probe_pv_hash()) {
  5671.         hash_low(PVEntry->move,PVEntry->value,PVEntry->depth);
  5672.         hash_high(PVEntry->value,PVEntry->depth);
  5673.         if (PVEntry->depth >= depth && T(PVHashing)) {
  5674.             if (PVEntry->move) Current->best = PVEntry->move;
  5675.             if ((Current->ply <= 50 && PVEntry->ply <= 50) || (Current->ply >= 50 && PVEntry->ply >= 50)) if (!PVEntry->value || !draw_in_pv<me>()) return PVEntry->value;
  5676.         }
  5677.         if (T(PVEntry->move) && PVEntry->depth > hash_depth) {
  5678.             Current->best = hash_move = PVEntry->move;
  5679.             hash_depth = PVEntry->depth;
  5680.             hash_value = PVEntry->value;
  5681.         }
  5682.     }
  5683.     if (GEntry * Entry = probe_hash()) {
  5684.         if (T(Entry->move) && Entry->low_depth > hash_depth) {
  5685.             Current->best = hash_move = Entry->move;
  5686.             hash_depth = Entry->low_depth;
  5687.             if (Entry->low_depth) hash_value = Entry->low;
  5688.         }
  5689.     }
  5690.  
  5691.     if (root) {
  5692.         hash_move = RootList[0];
  5693.         hash_value = Previous;
  5694.         hash_depth = Max(0, depth - 2);
  5695.     }
  5696.  
  5697.     evaluate();
  5698.  
  5699.     if (F(root) && depth >= 6 && (F(hash_move) || hash_value <= alpha || hash_depth < depth - 8)) {
  5700.         if (F(hash_move)) new_depth = depth - 2;
  5701.         else new_depth = depth - 4;
  5702.         value = pv_search<me, 0>(alpha, beta, new_depth, hash_move);
  5703.         if (value > alpha) {
  5704. hash_move_found:
  5705.             if (Current->best) hash_move = Current->best;
  5706.             hash_depth = new_depth;
  5707.             hash_value = value;
  5708.             goto skip_iid;
  5709.         } else {
  5710.             i = 0;     
  5711.             new_depth = depth - 8;
  5712. iid_loop:
  5713.             margin = alpha - (8 << i);
  5714.             if (T(hash_move) && hash_depth >= Min(new_depth, depth - 8) && hash_value >= margin) goto skip_iid;
  5715.             value = search<me, 0>(margin, new_depth, FlagHashCheck | FlagNoKillerUpdate | FlagDisableNull | FlagReturnBestMove | hash_move);
  5716.             if (value >= margin) goto hash_move_found;
  5717.             i++;
  5718.             if (i < 5) goto iid_loop;
  5719.         }
  5720.     }
  5721. skip_iid:
  5722.     if (F(root) && Check(me)) {
  5723.         alpha = Max(Convert((Current - Data),int) - MateValue, alpha);
  5724.         Current->mask = Filled;
  5725.         gen_evasions<me>(Current->moves);
  5726.         if (F(Current->moves[0])) return Convert((Current - Data),int) - MateValue;
  5727.         if (F(Current->moves[1])) pext = 2;
  5728.     }
  5729.  
  5730.     cnt = 0;
  5731.     if (hash_move && is_legal<me>(move = hash_move)) {
  5732.         cnt++;
  5733.         if (root) {
  5734. #ifndef TUNER
  5735.             memset(Data + 1, 0, 127 * sizeof(GData));
  5736. #endif
  5737.             move_to_string(move,score_string);
  5738.             if (Print) sprintf(info_string,"info currmove %s currmovenumber %d\n",score_string,cnt);
  5739.         }
  5740.         check = is_check<me>(move);
  5741.         if (check) ext = 2;
  5742.         else ext = MaxF(pext, extension<1>(move, depth));
  5743.         if (depth >= 12 && hash_value > alpha && hash_depth >= (new_depth = depth - Min(12,depth/2))) {
  5744.             int margin_one = hash_value - ExclSinglePV(depth);
  5745.             int margin_two = hash_value - ExclDoublePV(depth);
  5746.             int prev_ext = Ext(flags);
  5747.             singular = singular_extension<me>(root ? 0 : ext,root ? 0 : prev_ext,margin_one,margin_two,new_depth,hash_move);
  5748.             if (singular) {
  5749.                 ext = Max(ext, singular + (prev_ext < 1) - (singular >= 2 && prev_ext >= 2));
  5750.                 if (root) CurrentSI->Singular = singular;
  5751.                 ex_depth = new_depth;
  5752.                 ex_value = (singular >= 2 ? margin_two : margin_one) - 1;
  5753.             }
  5754.         }
  5755.         new_depth = depth - 2 + ext;
  5756.         do_move<me>(move);
  5757.         if (PrN > 1) {
  5758.             evaluate();
  5759.             if (Current->att[opp] & King(me)) {
  5760.                 undo_move<me>(move);
  5761.                 cnt--;
  5762.                 goto skip_hash_move;
  5763.             }
  5764.         }
  5765.         value = -pv_search<opp, 0>(-beta, -alpha, new_depth, ExtFlag(ext));
  5766.         undo_move<me>(move);
  5767.         played++;
  5768.         if (value > alpha) {
  5769.             if (root) {
  5770.                 CurrentSI->FailLow = 0;
  5771.                 best_move = move;
  5772.                 best_score = value;
  5773.                 hash_low(best_move,value,depth);
  5774.                 if (depth >= 14 || T(Console)) send_pv(depth/2, old_alpha, beta, value);
  5775.             }
  5776.             alpha = value;
  5777.             Current->best = move;
  5778.             if (value >= beta) goto cut;
  5779.         } else if (root) {
  5780.             CurrentSI->FailLow = 1;
  5781.             CurrentSI->FailHigh = 0;
  5782.             CurrentSI->Singular = 0;
  5783.             if (depth >= 14 || T(Console)) send_pv(depth/2, old_alpha, beta, value);
  5784.         }
  5785.     }
  5786. skip_hash_move:
  5787.     Current->gen_flags = 0;
  5788.     if (F(Check(me))) {
  5789.         Current->stage = stage_search;
  5790.         Current->ref[0] = RefM(Current->move).ref[0];
  5791.         Current->ref[1] = RefM(Current->move).ref[1];
  5792.     } else {
  5793.         Current->stage = stage_evasion;
  5794.         Current->ref[0] = RefM(Current->move).check_ref[0];
  5795.         Current->ref[1] = RefM(Current->move).check_ref[1];
  5796.     }
  5797.     Current->killer[0] = 0;
  5798.     Current->moves[0] = 0;
  5799.     if (root) Current->current = RootList + 1;
  5800.     else Current->current = Current->moves;
  5801.  
  5802.     if (PrN > 1 && !root && parent && depth >= SplitDepthPV) do_split = 1;
  5803.  
  5804.     while (move = get_move<me,root>()) {
  5805.         if (move == hash_move) continue;
  5806.         if (IsIllegal(me,move)) continue;
  5807.         cnt++;
  5808.         if (root) {
  5809. #ifndef TUNER
  5810.             memset(Data + 1, 0, 127 * sizeof(GData));
  5811. #endif
  5812.             move_to_string(move,score_string);
  5813.             if (Print) sprintf(info_string,"info currmove %s currmovenumber %d\n",score_string,cnt);
  5814.         }
  5815.         if (IsRepetition(alpha + 1,move)) continue;
  5816.         check = is_check<me>(move);
  5817.         if (check) ext = 2;
  5818.         else ext = MaxF(pext, extension<1>(move, depth));
  5819.         new_depth = depth - 2 + ext;
  5820.         if (depth >= 6 && F(move & 0xE000) && F(Square(To(move))) && (T(root) || (move != Current->killer[1] && move != Current->killer[2]) || T(Check(me))) && cnt > 3) {
  5821.             int reduction = msb(cnt) - 1;
  5822.             if (move == Current->ref[0] || move == Current->ref[1]) reduction = Max(0, reduction - 1);
  5823.             if (reduction >= 2 && !(Queen(White) | Queen(Black)) && popcnt(NonPawnKingAll) <= 4) reduction += reduction / 2;
  5824.             new_depth = Max(3, new_depth - reduction);
  5825.         }
  5826.         if (do_split && played >= 1) {
  5827.             if (!sp_init) {
  5828.                 sp_init = 1;
  5829.                 uint64 u = ~Smpi->active_sp;
  5830.                 if (!u) {
  5831.                     do_split = 0;
  5832.                     goto make_move;
  5833.                 }
  5834.                 Sp = &Smpi->Sp[lsb(u)];
  5835.                 init_sp(Sp, alpha, beta, depth, 1, singular, height);
  5836.             }
  5837.             GMove * M = &Sp->move[Sp->move_number++];
  5838.             M->ext = ext;
  5839.             M->flags = 0;
  5840.             M->move = move;
  5841.             M->reduced_depth = new_depth;
  5842.             M->research_depth = depth - 2 + ext;
  5843.             M->stage = Current->stage;
  5844.             continue;
  5845.         }
  5846. make_move:
  5847.         do_move<me>(move);
  5848.         if (new_depth <= 1) value = -pv_search<opp, 0>(-beta, -alpha, new_depth, ExtFlag(ext));
  5849.         else value = -search<opp, 0>(-alpha, new_depth, FlagNeatSearch | ExtFlag(ext));
  5850.         if (value > alpha && new_depth > 1) {
  5851.             if (root) {
  5852.                 SetScore(RootList[cnt - 1],1);
  5853.                 CurrentSI->Early = 0;
  5854.                 old_best = best_move;
  5855.                 best_move = move;
  5856.             }
  5857.             new_depth = depth - 2 + ext;
  5858.             value = -pv_search<opp, 0>(-beta, -alpha, new_depth, ExtFlag(ext));
  5859.             if (T(root) && value <= alpha) best_move = old_best;
  5860.         }
  5861.         undo_move<me>(move);
  5862.         played++;
  5863.         if (value > alpha) {
  5864.             if (root) {
  5865.                 SetScore(RootList[cnt - 1],cnt + 3);
  5866.                 CurrentSI->Change = 1;
  5867.                 CurrentSI->FailLow = 0;
  5868.                 best_move = move;
  5869.                 best_score = value;
  5870.                 hash_low(best_move,value,depth);
  5871.                 if (depth >= 14 || T(Console)) send_pv(depth/2, old_alpha, beta, value);
  5872.             }
  5873.             alpha = value;
  5874.             Current->best = move;
  5875.             if (value >= beta) goto cut;
  5876.         }
  5877.     }
  5878.     if (do_split && sp_init) {
  5879.         value = smp_search<me>(Sp);
  5880.         if (value > alpha && Sp->best_move) {
  5881.             alpha = value;
  5882.             Current->best = move = Sp->best_move;
  5883.         }
  5884.         if (value >= beta) goto cut;
  5885.     }
  5886.     if (F(cnt) && F(Check(me))) {
  5887.         hash_high(0, 127);
  5888.         hash_low(0, 0, 127);
  5889.         hash_exact(0, 0, 127, 0, 0, 0);
  5890.         return 0;
  5891.     }
  5892.     if (F(root) || F(SearchMoves)) hash_high(alpha, depth);
  5893.     if (alpha > old_alpha) {
  5894.         hash_low(Current->best,alpha,depth);
  5895.         if (Current->best != hash_move) ex_depth = 0;
  5896.         if (F(root) || F(SearchMoves)) hash_exact(Current->best,alpha,depth,ex_value,ex_depth,Convert(nodes >> 10,int) - start_knodes);
  5897.     }
  5898.     return alpha;
  5899. cut:
  5900.     hash_low(move, alpha, depth);
  5901.     return alpha;
  5902. }
  5903.  
  5904. template <bool me> void root() {
  5905.     int i, depth, value, alpha, beta, delta, start_depth = 2, hash_depth = 0, hash_value, store_time = 0, time_est, ex_depth = 0, ex_value, prev_time = 0, knodes = 0;
  5906.     sint64 time;
  5907.     GPVEntry * PVEntry;
  5908.  
  5909.     date++;
  5910.     nodes = check_node = check_node_smp = 0;
  5911. #ifndef TUNER
  5912.     if (parent) Smpi->nodes = 0;
  5913. #endif
  5914.     memcpy(Data,Current,sizeof(GData));
  5915.     Current = Data;
  5916.     evaluate();
  5917.     gen_root_moves<me>();
  5918.     if (PVN > 1) {
  5919.         memset(MultiPV,0,128 * sizeof(int));
  5920.         for (i = 0; MultiPV[i] = RootList[i]; i++);
  5921.     }
  5922.     best_move = RootList[0];
  5923.     if (F(best_move)) return;
  5924.     if (F(Infinite) && !RootList[1]) {
  5925.         Infinite = 1;
  5926.         value = pv_search<me, 1>(-MateValue, MateValue, 4, FlagNeatSearch);
  5927.         Infinite = 0;
  5928.         LastDepth = 128;
  5929.         send_pv(6, -MateValue, MateValue, value);
  5930.         send_best_move();
  5931.         Searching = 0;
  5932.         if (MaxPrN > 1) ZERO_BIT_64(Smpi->searching, 0);
  5933.         return;
  5934.     }
  5935.  
  5936.     memset(CurrentSI,0,sizeof(GSearchInfo));
  5937.     memset(BaseSI,0,sizeof(GSearchInfo));
  5938.     Previous = -MateValue;
  5939.     if (PVEntry = probe_pv_hash()) {
  5940.         if (is_legal<me>(PVEntry->move) && PVEntry->move == best_move && PVEntry->depth > hash_depth) {
  5941.             hash_depth = PVEntry->depth;
  5942.             hash_value = PVEntry->value;
  5943.             ex_depth = PVEntry->ex_depth;
  5944.             ex_value = PVEntry->exclusion;
  5945.             knodes = PVEntry->knodes;
  5946.         }
  5947.     }
  5948.     if (T(hash_depth) && PVN == 1) {
  5949.         Previous = best_score = hash_value;
  5950.         depth = hash_depth;
  5951.         if (PVHashing) {
  5952.             send_pv(depth/2, -MateValue, MateValue, best_score);
  5953.             start_depth = (depth + 2) & (~1);
  5954.         }
  5955.         if ((depth >= LastDepth - 8 || T(store_time)) && LastValue >= LastExactValue && hash_value >= LastExactValue && T(LastTime) && T(LastSpeed)) {
  5956.             time = TimeLimit1;
  5957.             if (ex_depth >= depth - Min(12, depth/2) && ex_value <= hash_value - ExclSinglePV(depth)) {
  5958.                 BaseSI->Early = 1;
  5959.                 BaseSI->Singular = 1;
  5960.                 if (ex_value <= hash_value - ExclDoublePV(depth)) {
  5961.                     time = (time * TimeSingTwoMargin)/100;
  5962.                     BaseSI->Singular = 2;
  5963.                 }
  5964.                 else time = (time * TimeSingOneMargin)/100;
  5965.             }
  5966.             time_est = Min(LastTime,(knodes << 10)/LastSpeed);
  5967.             time_est = Max(time_est, store_time);
  5968. set_prev_time:
  5969.             LastTime = prev_time = time_est;
  5970.             if (prev_time >= time && F(Infinite)) {
  5971.                 InstCnt++;
  5972.                 if (time_est <= store_time) InstCnt = 0;
  5973.                 if (InstCnt > 2) {
  5974.                     if (T(store_time) && store_time < time_est) {
  5975.                         time_est = store_time;
  5976.                         goto set_prev_time;
  5977.                     }
  5978.                     LastSpeed = 0;
  5979.                     LastTime = 0;
  5980.                     prev_time = 0;
  5981.                     goto set_jump;
  5982.                 }
  5983.                 if (hash_value > 0 && Current->ply >= 2 && F(Square(To(best_move))) && F(best_move & 0xF000) && PrevMove == ((To(best_move) << 6) | From(best_move))) goto set_jump;
  5984.                 do_move<me>(best_move);
  5985.                 if (Current->ply >= 100) {
  5986.                     undo_move<me>(best_move);
  5987.                     goto set_jump;
  5988.                 }
  5989.                 for (i = 4; i <= Current->ply; i+=2) if (Stack[sp-i] == Current->key) {
  5990.                     undo_move<me>(best_move);
  5991.                     goto set_jump;
  5992.                 }
  5993.                 undo_move<me>(best_move);
  5994.                 LastDepth = depth;
  5995.                 LastTime = prev_time;
  5996.                 LastValue = LastExactValue = hash_value;
  5997.                 send_best_move();
  5998.                 Searching = 0;
  5999.                 if (MaxPrN > 1) ZERO_BIT_64(Smpi->searching, 0);
  6000.                 return;
  6001.             } else goto set_jump;
  6002.         }
  6003.     }
  6004.     LastTime = 0;
  6005. set_jump:
  6006.     memcpy(SaveBoard,Board,sizeof(GBoard));
  6007.     memcpy(SaveData,Data,sizeof(GData));
  6008.     save_sp = sp;
  6009.     if (setjmp(Jump)) {
  6010.         Current = Data;
  6011.         Searching = 0;
  6012.         if (MaxPrN > 1) {
  6013.             halt_all(0, 127);
  6014.             ZERO_BIT_64(Smpi->searching, 0);
  6015.         }
  6016.         memcpy(Board,SaveBoard,sizeof(GBoard));
  6017.         memcpy(Data,SaveData,sizeof(GData));
  6018.         sp = save_sp;
  6019.         send_best_move();
  6020.         return;
  6021.     }
  6022.     for (depth = start_depth; depth < DepthLimit; depth += 2) {
  6023. #ifndef TUNER
  6024.         memset(Data + 1, 0, 127 * sizeof(GData));
  6025. #endif
  6026.         CurrentSI->Early = 1;
  6027.         CurrentSI->Change = CurrentSI->FailHigh = CurrentSI->FailLow = CurrentSI->Singular = 0;
  6028.         if (PVN > 1) value = multipv<me>(depth);
  6029.         else if ((depth/2) < 7 || F(Aspiration)) LastValue = LastExactValue = value = pv_search<me, 1>(-MateValue, MateValue, depth, FlagNeatSearch);
  6030.         else {
  6031.             delta = 8;
  6032.             alpha = Previous - delta;
  6033.             beta = Previous + delta;
  6034. loop:
  6035.             if (delta >= 16 * 32) {
  6036.                 LastValue = LastExactValue = value = pv_search<me, 1>(-MateValue, MateValue, depth, FlagNeatSearch);
  6037.                 goto finish;
  6038.             }
  6039.             value = pv_search<me, 1>(alpha, beta, depth, FlagNeatSearch);
  6040.             if (value <= alpha) {
  6041.                 CurrentSI->FailHigh = 0;
  6042.                 CurrentSI->FailLow = 1;
  6043.                 alpha -= delta;
  6044.                 delta *= 2;
  6045.                 LastValue = value;
  6046.                 memcpy(BaseSI,CurrentSI,sizeof(GSearchInfo));
  6047.                 goto loop;
  6048.             } else if (value >= beta) {
  6049.                 CurrentSI->FailHigh = 1;
  6050.                 CurrentSI->FailLow = 0;
  6051.                 CurrentSI->Early = 1;
  6052.                 CurrentSI->Change = 0;
  6053.                 CurrentSI->Singular = Max(CurrentSI->Singular, 1);
  6054.                 beta += delta;
  6055.                 delta *= 2;
  6056.                 LastDepth = depth;
  6057.                 LastTime = MaxF(prev_time,get_time() - StartTime);
  6058.                 LastSpeed = nodes/Max(LastTime, 1);
  6059.                 if (depth + 2 < DepthLimit) depth += 2;
  6060.                 InstCnt = 0;
  6061. #ifdef TIMING
  6062.                 if (depth >= 6)
  6063. #endif
  6064.                 check_time(LastTime,0);
  6065. #ifndef TUNER
  6066.                 memset(Data + 1, 0, 127 * sizeof(GData));
  6067. #endif
  6068.                 LastValue = value;
  6069.                 memcpy(BaseSI,CurrentSI,sizeof(GSearchInfo));
  6070.                 goto loop;
  6071.             } else LastValue = LastExactValue = value;
  6072.         }
  6073. finish:
  6074.         if (value < Previous - 50) CurrentSI->Bad = 1;
  6075.         else CurrentSI->Bad = 0;
  6076.         memcpy(BaseSI,CurrentSI,sizeof(GSearchInfo));
  6077.         LastDepth = depth;
  6078.         LastTime = MaxF(prev_time,get_time() - StartTime);
  6079.         LastSpeed = nodes/Max(LastTime, 1);
  6080.         Previous = value;
  6081.         InstCnt = 0;
  6082. #ifdef TIMING
  6083.         if (depth >= 6)
  6084. #endif
  6085.         check_time(LastTime,0);
  6086.     }
  6087.     Searching = 0;
  6088.     if (MaxPrN > 1) ZERO_BIT_64(Smpi->searching, 0);
  6089.     if (F(Infinite) || DepthLimit < 128) send_best_move();
  6090. }
  6091.  
  6092. template <bool me> int multipv(int depth) {
  6093.     int move, low = MateValue, value, i, cnt, ext, new_depth = depth;
  6094.     fprintf(stdout,"info depth %d\n",(depth/2)); fflush(stdout);
  6095.     for (cnt = 0; cnt < PVN && T(move = (MultiPV[cnt] & 0xFFFF)); cnt++) {
  6096.         MultiPV[cnt] = move;
  6097.         move_to_string(move,score_string);
  6098.         if (T(Print)) sprintf(info_string,"info currmove %s currmovenumber %d\n",score_string,cnt + 1);
  6099.         new_depth = depth - 2 + (ext = extension<1>(move, depth));
  6100.         do_move<me>(move);
  6101.         value = -pv_search<opp, 0>(-MateValue,MateValue,new_depth,ExtFlag(ext));
  6102.         MultiPV[cnt] |= value << 16;
  6103.         if (value < low) low = value;
  6104.         undo_move<me>(move);
  6105.         for (i = cnt - 1; i >= 0; i--) {
  6106.             if ((MultiPV[i] >> 16) < value) {
  6107.                 MultiPV[i + 1] = MultiPV[i];
  6108.                 MultiPV[i] = move | (value << 16);
  6109.             }
  6110.         }
  6111.         best_move = MultiPV[0] & 0xFFFF;
  6112.         Current->score = MultiPV[0] >> 16;
  6113.         send_multipv((depth/2), cnt);
  6114.     }
  6115.     for (;T(move = (MultiPV[cnt] & 0xFFFF)); cnt++) {
  6116.         MultiPV[cnt] = move;
  6117.         move_to_string(move,score_string);
  6118.         if (T(Print)) sprintf(info_string,"info currmove %s currmovenumber %d\n",score_string,cnt + 1);
  6119.         new_depth = depth - 2 + (ext = extension<1>(move, depth));
  6120.         do_move<me>(move);
  6121.         value = -search<opp, 0>(-low, new_depth, FlagNeatSearch | ExtFlag(ext));
  6122.         if (value > low) value = -pv_search<opp, 0>(-MateValue,-low,new_depth,ExtFlag(ext));
  6123.         MultiPV[cnt] |= value << 16;
  6124.         undo_move<me>(move);
  6125.         if (value > low) {
  6126.             for (i = cnt; i >= PVN; i--) MultiPV[i] = MultiPV[i - 1];
  6127.             MultiPV[PVN - 1] = move | (value << 16);
  6128.             for (i = PVN - 2; i >= 0; i--) {
  6129.                 if ((MultiPV[i] >> 16) < value) {
  6130.                     MultiPV[i + 1] = MultiPV[i];
  6131.                     MultiPV[i] = move | (value << 16);
  6132.                 }
  6133.             }
  6134.             best_move = MultiPV[0] & 0xFFFF;
  6135.             Current->score = MultiPV[0] >> 16;
  6136.             low = MultiPV[PVN - 1] >> 16;
  6137.             send_multipv((depth/2), cnt);
  6138.         }
  6139.     }
  6140.     return Current->score;
  6141. }
  6142.  
  6143. void send_pv(int depth, int alpha, int beta, int score) {
  6144.     int i, pos, move, mate = 0, mate_score, sel_depth;
  6145.     sint64 nps, snodes;
  6146.     if (F(Print)) return;
  6147.     for (sel_depth = 1; sel_depth < 127 && T((Data + sel_depth)->att[0]); sel_depth++);
  6148.     sel_depth--;
  6149.     pv_length = 64;
  6150.     if (F(move = best_move)) move = RootList[0];
  6151.     if (F(move)) return;
  6152.     PV[0] = move;
  6153.     if (Current->turn) do_move<1>(move);
  6154.     else do_move<0>(move);
  6155.     pvp = 1;
  6156.     pick_pv();
  6157.     if (Current->turn ^ 1) undo_move<1>(move);
  6158.     else undo_move<0>(move);
  6159.     pos = 0;
  6160.     for (i = 0; i < 64 && T(PV[i]); i++) {
  6161.         if (pos > 0) {
  6162.             pv_string[pos] = ' ';
  6163.             pos++;
  6164.         }
  6165.         move = PV[i];
  6166.         pv_string[pos++] = ((move >> 6) & 7) + 'a';
  6167.         pv_string[pos++] = ((move >> 9) & 7) + '1';
  6168.         pv_string[pos++] = (move & 7) + 'a';
  6169.         pv_string[pos++] = ((move >> 3) & 7) + '1';
  6170.         if (IsPromotion(move)) {
  6171.             if ((move & 0xF000) == FlagPQueen)  pv_string[pos++] = 'q';
  6172.             else if ((move & 0xF000) == FlagPRook)   pv_string[pos++] = 'r';
  6173.             else if ((move & 0xF000) == FlagPLight || (move & 0xF000) == FlagPDark) pv_string[pos++] = 'b';
  6174.             else if ((move & 0xF000) == FlagPKnight) pv_string[pos++] = 'n';
  6175.         }
  6176.         pv_string[pos] = 0;
  6177.     }
  6178.     score_string[0] = 'c';
  6179.     score_string[1] = 'p';
  6180.     if (score > EvalValue) {
  6181.         mate = 1;
  6182.         strcpy(score_string,"mate ");
  6183.         mate_score = (MateValue - score + 1)/2;
  6184.         score_string[6] = 0;
  6185.     } else if (score < -EvalValue) {
  6186.         mate = 1;
  6187.         strcpy(score_string,"mate ");
  6188.         mate_score = -(score + MateValue + 1)/2;
  6189.         score_string[6] = 0;
  6190.     } else {
  6191.         score_string[0] = 'c';
  6192.         score_string[1] = 'p';
  6193.         score_string[2] = ' ';
  6194.         score_string[3] = 0;
  6195.     }
  6196.     nps = get_time() - StartTime;
  6197. #ifdef MP_NPS
  6198.     snodes = Smpi->nodes;
  6199. #else
  6200.     snodes = nodes;
  6201. #endif
  6202.     if (nps) nps = (snodes * 1000)/nps;
  6203.     if (score < beta) {
  6204.         if (score <= alpha) fprintf(stdout,"info depth %d seldepth %d score %s%d upperbound nodes %I64d nps %I64d pv %s\n",depth,sel_depth,score_string,(mate ? mate_score : score),snodes,nps,pv_string);
  6205.         else fprintf(stdout,"info depth %d seldepth %d score %s%d nodes %I64d nps %I64d pv %s\n",depth,sel_depth,score_string,(mate ? mate_score : score),snodes,nps,pv_string);
  6206.     } else fprintf(stdout,"info depth %d seldepth %d score %s%d lowerbound nodes %I64d nps %I64d pv %s\n",depth,sel_depth,score_string,(mate ? mate_score : score),snodes,nps,pv_string);
  6207.     fflush(stdout);
  6208. }
  6209.  
  6210. void send_multipv(int depth, int curr_number) {
  6211.     int i, j, pos, move, score;
  6212.     sint64 nps, snodes;
  6213.     if (F(Print)) return;
  6214.     for (j = 0; j < PVN && T(MultiPV[j]); j++) {
  6215.         pv_length = 63;
  6216.         pvp = 0;
  6217.         move = MultiPV[j] & 0xFFFF;
  6218.         score = MultiPV[j] >> 16;
  6219.         memset(PV,0,64 * sizeof(uint16));
  6220.         if (Current->turn) do_move<1>(move);
  6221.         else do_move<0>(move);
  6222.         pick_pv();
  6223.         if (Current->turn ^ 1) undo_move<1>(move);
  6224.         else undo_move<0>(move);
  6225.         for (i = 63; i > 0; i--) PV[i] = PV[i - 1];
  6226.         PV[0] = move;
  6227.         pos = 0;
  6228.         for (i = 0; i < 64 && T(PV[i]); i++) {
  6229.             if (pos > 0) {
  6230.                 pv_string[pos] = ' ';
  6231.                 pos++;
  6232.             }
  6233.             move = PV[i];
  6234.             pv_string[pos++] = ((move >> 6) & 7) + 'a';
  6235.             pv_string[pos++] = ((move >> 9) & 7) + '1';
  6236.             pv_string[pos++] = (move & 7) + 'a';
  6237.             pv_string[pos++] = ((move >> 3) & 7) + '1';
  6238.             if (IsPromotion(move)) {
  6239.                 if ((move & 0xF000) == FlagPQueen)  pv_string[pos++] = 'q';
  6240.                 else if ((move & 0xF000) == FlagPRook)   pv_string[pos++] = 'r';
  6241.                 else if ((move & 0xF000) == FlagPLight || (move & 0xF000) == FlagPDark) pv_string[pos++] = 'b';
  6242.                 else if ((move & 0xF000) == FlagPKnight) pv_string[pos++] = 'n';
  6243.             }
  6244.             pv_string[pos] = 0;
  6245.         }
  6246.         score_string[0] = 'c';
  6247.         score_string[1] = 'p';
  6248.         if (score > EvalValue) {
  6249.             strcpy(score_string,"mate ");
  6250.             score = (MateValue - score + 1)/2;
  6251.             score_string[6] = 0;
  6252.         } else if (score < -EvalValue) {
  6253.             strcpy(score_string,"mate ");
  6254.             score = -(score + MateValue + 1)/2;
  6255.             score_string[6] = 0;
  6256.         } else {
  6257.             score_string[0] = 'c';
  6258.             score_string[1] = 'p';
  6259.             score_string[2] = ' ';
  6260.             score_string[3] = 0;
  6261.         }
  6262.         nps = get_time() - StartTime;
  6263. #ifdef MP_NPS
  6264.         snodes = Smpi->nodes;
  6265. #else
  6266.         snodes = nodes;
  6267. #endif
  6268.         if (nps) nps = (snodes * 1000)/nps;
  6269.         fprintf(stdout,"info multipv %d depth %d score %s%d nodes %I64d nps %I64d pv %s\n",j + 1,(j <= curr_number ? depth : depth - 1),score_string,score,snodes,nps,pv_string);
  6270.         fflush(stdout);
  6271.     }
  6272. }
  6273.  
  6274. void send_best_move() {
  6275.     uint64 snodes;
  6276.     int ponder;
  6277. #ifdef CPU_TIMING
  6278.     GlobalTime[GlobalTurn] -= Convert(get_time() - StartTime, int) - GlobalInc[GlobalTurn];
  6279.     if (GlobalTime[GlobalTurn] < GlobalInc[GlobalTurn]) GlobalTime[GlobalTurn] = GlobalInc[GlobalTurn];
  6280. #endif
  6281.     if (F(Print)) return;
  6282. #ifdef MP_NPS
  6283.     snodes = Smpi->nodes;
  6284. #else
  6285.     snodes = nodes;
  6286. #endif
  6287.     fprintf(stdout,"info nodes %I64d score cp %d\n",snodes,best_score);
  6288.     if (!best_move) return;
  6289.     Current = Data;
  6290.     evaluate();
  6291.     if (Current->turn) do_move<1>(best_move);
  6292.     else do_move<0>(best_move);
  6293.     pv_length = 1;
  6294.     pvp = 0;
  6295.     pick_pv();
  6296.     ponder = PV[0];
  6297.     if (Current->turn ^ 1) undo_move<1>(best_move);
  6298.     else undo_move<0>(best_move);
  6299.     move_to_string(best_move,pv_string);
  6300.     if (ponder) {
  6301.         move_to_string(ponder,score_string);
  6302.         fprintf(stdout,"bestmove %s ponder %s\n",pv_string,score_string);
  6303.     } else fprintf(stdout,"bestmove %s\n",pv_string);
  6304.     fflush(stdout);
  6305. }
  6306.  
  6307. void get_position(char string[]) {
  6308.     const char * fen;
  6309.     char * moves;
  6310.     const char * ptr;
  6311.     int move, move1 = 0;
  6312.  
  6313.     fen = strstr(string,"fen ");
  6314.     moves = strstr(string,"moves ");
  6315.     if (fen != NULL) get_board(fen+4);
  6316.     else get_board("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");
  6317.     PrevMove = 0;
  6318.     if (moves != NULL) {
  6319.         ptr = moves+6;
  6320.         while (*ptr != 0) {
  6321.             pv_string[0] = *ptr++;
  6322.             pv_string[1] = *ptr++;
  6323.             pv_string[2] = *ptr++;
  6324.             pv_string[3] = *ptr++;
  6325.             if (*ptr == 0 || *ptr == ' ') pv_string[4] = 0;
  6326.             else {
  6327.                 pv_string[4] = *ptr++;
  6328.                 pv_string[5] = 0;
  6329.             }
  6330.             evaluate();
  6331.             move = move_from_string(pv_string);
  6332.             PrevMove = move1;
  6333.             move1 = move;
  6334.             if (Current->turn) do_move<1>(move);
  6335.             else do_move<0>(move);
  6336.             memcpy(Data,Current,sizeof(GData));
  6337.             Current = Data;
  6338.             while (*ptr == ' ') ptr++;
  6339.         }
  6340.     }
  6341.     memcpy(Stack, Stack + sp - Current->ply, (Current->ply + 1) * sizeof(uint64));
  6342.     sp = Current->ply;
  6343. }
  6344.  
  6345. void get_time_limit(char string[]) {
  6346.     const char * ptr;
  6347.     int i, time, inc, wtime, btime, winc, binc, moves, pondering, movetime = 0, exp_moves = MovesTg - 1;
  6348.  
  6349.     Infinite = 1;
  6350.     MoveTime = 0;
  6351.     SearchMoves = 0;
  6352.     SMPointer = 0;
  6353.     pondering = 0;
  6354.     TimeLimit1 = 0;
  6355.     TimeLimit2 = 0;
  6356.     wtime = btime = 0;
  6357.     winc = binc = 0;
  6358.     moves = 0;
  6359.     Stop = 0;
  6360.     DepthLimit = 128;
  6361.     ptr = strtok(string," ");
  6362.     for (ptr = strtok(NULL," "); ptr != NULL; ptr = strtok(NULL," ")) {
  6363.         if (!strcmp(ptr,"binc")) {
  6364.             ptr = strtok(NULL," ");
  6365.             binc = atoi(ptr);
  6366.             Infinite = 0;
  6367.         } else if (!strcmp(ptr,"btime")) {
  6368.             ptr = strtok(NULL," ");
  6369.             btime = atoi(ptr);
  6370.             Infinite = 0;
  6371.         } else if (!strcmp(ptr,"depth")) {
  6372.             ptr = strtok(NULL," ");
  6373.             DepthLimit = 2 * atoi(ptr) + 2;
  6374.             Infinite = 1;
  6375.         } else if (!strcmp(ptr,"infinite")) {
  6376.             Infinite = 1;
  6377.         } else if (!strcmp(ptr,"movestogo")) {
  6378.             ptr = strtok(NULL," ");
  6379.             moves = atoi(ptr);
  6380.             Infinite = 0;
  6381.         } else if (!strcmp(ptr,"winc")) {
  6382.             ptr = strtok(NULL," ");
  6383.             winc = atoi(ptr);
  6384.             Infinite = 0;
  6385.         } else if (!strcmp(ptr,"wtime")) {
  6386.             ptr = strtok(NULL," ");
  6387.             wtime = atoi(ptr);
  6388.             Infinite = 0;
  6389.         } else if (!strcmp(ptr,"movetime")) {
  6390.             ptr = strtok(NULL," ");
  6391.             movetime = atoi(ptr);
  6392.             MoveTime = 1;
  6393.             Infinite = 0;
  6394.         } else if (!strcmp(ptr,"searchmoves")) {
  6395.             if (F(SearchMoves)) {
  6396.                 for (i = 0; i < 256; i++) SMoves[i] = 0;
  6397.             }
  6398.             SearchMoves = 1;
  6399.             ptr += 12;
  6400.             while (ptr != NULL && ptr[0] >= 'a' && ptr[0] <= 'h' && ptr[1] >= '1' && ptr[1] <= '8') {
  6401.                 pv_string[0] = *ptr++;
  6402.                 pv_string[1] = *ptr++;
  6403.                 pv_string[2] = *ptr++;
  6404.                 pv_string[3] = *ptr++;
  6405.                 if (*ptr == 0 || *ptr == ' ') pv_string[4] = 0;
  6406.                 else {
  6407.                     pv_string[4] = *ptr++;
  6408.                     pv_string[5] = 0;
  6409.                 }
  6410.                 SMoves[SMPointer] = move_from_string(pv_string);
  6411.                 SMPointer++;
  6412.                 ptr = strtok(NULL," ");
  6413.             }
  6414.         } else if (!strcmp(ptr,"ponder")) pondering = 1;
  6415.     }
  6416.     if (pondering) Infinite = 1;
  6417.     if (Current->turn == White) {
  6418.         time = wtime;
  6419.         inc = winc;
  6420.     } else {
  6421.         time = btime;
  6422.         inc = binc;
  6423.     }
  6424. #ifdef CPU_TIMING
  6425.     if (CpuTiming) {
  6426.         time = GlobalTime[GlobalTurn];
  6427.         inc = GlobalInc[GlobalTurn];
  6428.         if (UciMaxDepth) DepthLimit = 2 * UciMaxDepth + 2;
  6429.     }
  6430. #endif
  6431.     if (moves) moves = Max(moves - 1, 1);
  6432.     int time_max = Max(time - Min(1000, time/2), 0);
  6433.     int nmoves;
  6434.     if (moves) nmoves = moves;
  6435.     else {
  6436.         nmoves = MovesTg - 1;
  6437.         if (Current->ply > 40) nmoves += Min(Current->ply - 40, (100 - Current->ply)/2);
  6438.         exp_moves = nmoves;
  6439.     }
  6440.     TimeLimit1 = Min(time_max, (time_max + (Min(exp_moves, nmoves) * inc))/Min(exp_moves, nmoves));
  6441.     TimeLimit2 = Min(time_max, (time_max + (Min(exp_moves, nmoves) * inc))/Min(3,Min(exp_moves, nmoves)));
  6442.     TimeLimit1 = Min(time_max, (TimeLimit1 * TimeRatio)/100);
  6443.     if (Ponder) TimeLimit1 = (TimeLimit1 * PonderRatio)/100;
  6444.     if (MoveTime) {
  6445.         TimeLimit2 = movetime;
  6446.         TimeLimit1 = TimeLimit2 * 100;
  6447.     }
  6448.     InfoTime = StartTime = get_time();
  6449.     Searching = 1;
  6450.     if (MaxPrN > 1) SET_BIT_64(Smpi->searching, 0);
  6451.     if (F(Infinite)) PVN = 1;
  6452.     if (Current->turn == White) root<0>(); else root<1>();
  6453. }
  6454.  
  6455. sint64 get_time() {
  6456. #ifdef CPU_TIMING
  6457. #ifndef TIMING
  6458.     if (CpuTiming) {
  6459. #endif
  6460.         uint64 ctime;
  6461.         QueryProcessCycleTime(GetCurrentProcess(), &ctime);
  6462. #ifdef TIMING
  6463.         return ctime / (CyclesPerMSec / 1000);
  6464. #endif
  6465.         return (ctime / CyclesPerMSec);
  6466. #ifndef TIMING
  6467.     }
  6468. #endif
  6469. #endif
  6470.     return GetTickCount();
  6471. }
  6472.  
  6473. int time_to_stop(GSearchInfo * SI, int time, int searching) {
  6474.     if (Infinite) return 0;
  6475.     if (time > TimeLimit2) return 1;
  6476.     if (searching) return 0;
  6477.     if (2 * time > TimeLimit2 && F(MoveTime)) return 1;
  6478.     if (SI->Bad) return 0;
  6479.     if (time > TimeLimit1) return 1;
  6480.     if (T(SI->Change) || T(SI->FailLow)) return 0;
  6481.     if (time * 100 > TimeLimit1 * TimeNoChangeMargin) return 1;
  6482.     if (F(SI->Early)) return 0;
  6483.     if (time * 100 > TimeLimit1 * TimeNoPVSCOMargin) return 1;
  6484.     if (SI->Singular < 1) return 0;
  6485.     if (time * 100 > TimeLimit1 * TimeSingOneMargin) return 1;
  6486.     if (SI->Singular < 2) return 0;
  6487.     if (time * 100 > TimeLimit1 * TimeSingTwoMargin) return 1;
  6488.     return 0;
  6489. }
  6490.  
  6491. void check_time(int searching) {
  6492. #ifdef CPU_TIMING
  6493.     if (CpuTiming && UciMaxKNodes && nodes > UciMaxKNodes * 1024) Stop = 1;
  6494. #endif
  6495. #ifdef TUNER
  6496. #ifndef TIMING
  6497.     return;
  6498. #endif
  6499. #else
  6500.     while (!Stop && input()) uci();
  6501. #endif
  6502.     if (Stop) goto jump;
  6503.     CurrTime = get_time();
  6504.     int Time = Convert(CurrTime - StartTime,int);
  6505.     if (T(Print) && Time > InfoLag && CurrTime - InfoTime > InfoDelay) {
  6506.         InfoTime = CurrTime;
  6507.         if (info_string[0]) {
  6508.             fprintf(stdout,"%s",info_string);
  6509.             info_string[0] = 0;
  6510.             fflush(stdout);
  6511.         }
  6512.     }
  6513.     if (time_to_stop(CurrentSI, Time, searching)) goto jump;
  6514.     return;
  6515. jump:
  6516.     Stop = 1;
  6517.     longjmp(Jump,1);
  6518. }
  6519.  
  6520. void check_time(int time, int searching) {
  6521. #ifdef TUNER
  6522. #ifndef TIMING
  6523.     return;
  6524. #endif
  6525. #else
  6526.     while (!Stop && input()) uci();
  6527. #endif
  6528.     if (Stop) goto jump;
  6529.     CurrTime = get_time();
  6530.     int Time = Convert(CurrTime - StartTime,int);
  6531.     if (T(Print) && Time > InfoLag && CurrTime - InfoTime > InfoDelay) {
  6532.         InfoTime = CurrTime;
  6533.         if (info_string[0]) {
  6534.             fprintf(stdout,"%s",info_string);
  6535.             info_string[0] = 0;
  6536.             fflush(stdout);
  6537.         }
  6538.     }
  6539.     if (time_to_stop(CurrentSI, time, searching)) goto jump;
  6540.     return;
  6541. jump:
  6542.     Stop = 1;
  6543.     longjmp(Jump,1);
  6544. }
  6545.  
  6546. void check_state() {
  6547.     GSP *Sp, *Spc;
  6548.     int n, nc, score, best, pv, alpha, beta, new_depth, r_depth, ext, move, value;
  6549.     GMove * M;
  6550.  
  6551.     if (parent) {
  6552.         for (uint64 u = TEST_RESET(Smpi->fail_high); u; Cut(u)) {
  6553.             Sp = &Smpi->Sp[lsb(u)];
  6554.             LOCK(Sp->lock);
  6555.             if (Sp->active && Sp->finished) {
  6556.                 UNLOCK(Sp->lock);
  6557.                 longjmp(Sp->jump, 1);
  6558.             }
  6559.             UNLOCK(Sp->lock);
  6560.         }
  6561.         return;
  6562.     }
  6563.  
  6564. start:
  6565.     if (TEST_RESET_BIT(Smpi->stop, Id)) longjmp(CheckJump, 1);
  6566.     if (Smpi->searching & Bit(Id)) return;
  6567.     if (!(Smpi->searching & 1)) {
  6568.         Sleep(1);
  6569.         return;
  6570.     }
  6571.     while ((Smpi->searching & 1) && !Smpi->active_sp) _mm_pause();
  6572.     while ((Smpi->searching & 1) && !(Smpi->searching & Bit(Id - 1))) _mm_pause();
  6573.  
  6574.     Sp = NULL; best = -0x7FFFFFFF;
  6575.     for (uint64 u = Smpi->active_sp; u; Cut(u)) {
  6576.         Spc = &Smpi->Sp[lsb(u)];
  6577.         if (!Spc->active || Spc->finished || Spc->lock) continue;
  6578.         for (nc = Spc->current + 1; nc < Spc->move_number; nc++) if (!(Spc->move[nc].flags & FlagClaimed)) break;
  6579.         if (nc < Spc->move_number) score = 1024 * 1024 + 512 * 1024 * (Spc->depth >= 20) + 128 * 1024 * (!(Spc->split))
  6580.             + ((Spc->depth + 2 * Spc->singular) * 1024) - (((16 * 1024) * (nc - Spc->current)) / nc);
  6581.         else continue;
  6582.         if (score > best) {
  6583.             best = score;
  6584.             Sp = Spc;
  6585.             n = nc;
  6586.         }
  6587.     }
  6588.  
  6589.     if (Sp == NULL) goto start;
  6590.     if (!Sp->active || Sp->finished || (Sp->move[n].flags & FlagClaimed) || n <= Sp->current || n >= Sp->move_number) goto start;
  6591.     if (Sp->lock) goto start;
  6592.  
  6593.     LOCK(Sp->lock);
  6594.     if (!Sp->active || Sp->finished || (Sp->move[n].flags & FlagClaimed) || n <= Sp->current || n >= Sp->move_number) {
  6595.         UNLOCK(Sp->lock);
  6596.         goto start;
  6597.     }
  6598.  
  6599.     M = &Sp->move[n];
  6600.     M->flags |= FlagClaimed;
  6601.     M->id = Id;
  6602.     Sp->split |= Bit(Id);
  6603.     pv = Sp->pv;
  6604.     alpha = Sp->alpha;
  6605.     beta = Sp->beta;
  6606.     new_depth = M->reduced_depth;
  6607.     r_depth = M->research_depth;
  6608.     ext = M->ext;
  6609.     move = M->move;
  6610.  
  6611.     Current = Data;
  6612.     retrieve_position(Sp->Pos, 1);
  6613.     evaluate();
  6614.     SET_BIT_64(Smpi->searching, Id);
  6615.     UNLOCK(Sp->lock);
  6616.  
  6617.     if (setjmp(CheckJump)) {
  6618.         ZERO_BIT_64(Smpi->searching, Id);
  6619.         return;
  6620.     }
  6621.     if (Current->turn == White) {
  6622.         do_move<0>(move);
  6623.         if (pv) {
  6624.             value = -search<1, 0>(-alpha, new_depth, FlagNeatSearch | ExtFlag(ext));
  6625.             if (value > alpha) value = -pv_search<1, 0>(-beta, -alpha, r_depth, ExtFlag(ext));
  6626.         } else {
  6627.             value = -search<1, 0>(1 - beta, new_depth, FlagNeatSearch | ExtFlag(ext));
  6628.             if (value >= beta && new_depth < r_depth) value = -search<1, 0>(1 - beta, r_depth, FlagNeatSearch | FlagDisableNull | ExtFlag(ext));
  6629.         }
  6630.         undo_move<0>(move);
  6631.     } else {
  6632.         do_move<1>(move);
  6633.         if (pv) {
  6634.             value = -search<0, 0>(-alpha, new_depth, FlagNeatSearch | ExtFlag(ext));
  6635.             if (value > alpha) value = -pv_search<0, 0>(-beta, -alpha, r_depth, ExtFlag(ext));
  6636.         } else {
  6637.             value = -search<0, 0>(1 - beta, new_depth, FlagNeatSearch | ExtFlag(ext));
  6638.             if (value >= beta && new_depth < r_depth) value = -search<0, 0>(1 - beta, r_depth, FlagNeatSearch | FlagDisableNull | ExtFlag(ext));
  6639.         }
  6640.         undo_move<1>(move);
  6641.     }
  6642.  
  6643.     LOCK(Sp->lock);
  6644.     ZERO_BIT_64(Smpi->searching, Id);
  6645.     if (TEST_RESET_BIT(Smpi->stop, Id)) {
  6646.         UNLOCK(Sp->lock);
  6647.         return;
  6648.     }
  6649.     M->flags |= FlagFinished;
  6650.     if (value > Sp->alpha) {
  6651.         Sp->alpha = Min(value, beta);
  6652.         Sp->best_move = move;
  6653.         if (value >= beta) {
  6654.             Sp->finished = 1;
  6655.             SET_BIT_64(Smpi->fail_high, (int)(Sp - Smpi->Sp));
  6656.         }
  6657.     }
  6658.     UNLOCK(Sp->lock);
  6659. }
  6660.  
  6661. int input() {
  6662.     if (child) return 0;
  6663.     DWORD p;
  6664.     if (F(Input)) return 0;
  6665.     if (F(Console)) {
  6666.         if (PeekNamedPipe(StreamHandle,NULL,0,NULL,&p,NULL)) return (p > 0);
  6667.         else return 1;
  6668.     } else return 0;
  6669. }
  6670.  
  6671. void epd_test(char string[], int time_limit) {
  6672.     int n = 0, positions = 4000;
  6673.     uint64 Time, all_nodes = 0, new_time, total_time;
  6674.     double prod = 0.0;
  6675.     char * ptr;
  6676.     FILE * f = fopen(string, "r");
  6677.     if (f == NULL) {
  6678.         fprintf(stdout, "File not found\n");
  6679.         return;
  6680.     }
  6681.     Infinite = 1;
  6682.     Time = get_time();
  6683.     int total_depth = 0;
  6684.     Print = 0;
  6685.     Input = 0;
  6686.     total_time = 1;
  6687.     while (!feof(f) && n < positions) {
  6688.     new_position:
  6689.         (void)fgets(mstring, 65536, f);
  6690.         ptr = strchr(mstring, '\n');
  6691.         if (ptr != NULL) *ptr = 0;
  6692.         get_board(mstring);
  6693.         evaluate();
  6694.         if (Current->turn == White) {
  6695.             gen_root_moves<0>();
  6696.         } else {
  6697.             gen_root_moves<1>();
  6698.         }
  6699.         Infinite = 0;
  6700.         MoveTime = TimeLimit1 = 100000000;
  6701. #ifndef TIME_TO_DEPTH
  6702.         TimeLimit2 = time_limit;
  6703. #else
  6704.         TimeLimit2 = TimeLimit1;
  6705. #endif
  6706.         DepthLimit = 127;
  6707.         n++;
  6708.         Stop = 0;
  6709.         Smpi->nodes = nodes = check_node = check_node_smp = 0;
  6710.         StartTime = get_time();
  6711.         if (setjmp(Jump)) {
  6712.             halt_all(0, 127);
  6713.         stop_searching:
  6714.             ZERO_BIT_64(Smpi->searching, Id);
  6715.             Searching = 0;
  6716.             Current = Data;
  6717.             new_time = Max(get_time() - StartTime, 1);
  6718.             total_time += new_time;
  6719. #ifdef MP_NPS
  6720.             all_nodes += Smpi->nodes;
  6721. #else
  6722.             all_nodes += nodes;
  6723. #endif
  6724.             total_depth += LastDepth / 2;
  6725. #ifndef TIME_TO_DEPTH
  6726.             fprintf(stdout, "Position %d: %d [%lf, %d]\n", n, LastDepth / 2, ((double)total_depth) / ((double)n), (all_nodes * Convert(1000, uint64)) / total_time);
  6727. #else
  6728.             prod += log((double)new_time);
  6729.             fprintf(stdout, "Position %d: %d [%.0lf, %d]\n", n, new_time, exp(prod / (double)n), (all_nodes * Convert(1000, uint64)) / total_time);
  6730. #endif
  6731.             goto new_position;
  6732.         }
  6733.         for (int d = 4; d < 128; d += 2) {
  6734.             LastDepth = d;
  6735.             Searching = 1;
  6736.             SET_BIT_64(Smpi->searching, Id);
  6737.             if (Current->turn == White) {
  6738.                 pv_search<0, 1>(-MateValue, MateValue, d, FlagNeatSearch);
  6739.             } else {
  6740.                 pv_search<1, 1>(-MateValue, MateValue, d, FlagNeatSearch);
  6741.             }
  6742. #ifdef TIME_TO_DEPTH
  6743.             if (d >= (time_limit * 2)) goto stop_searching;
  6744. #endif
  6745.         }
  6746.     }
  6747.     if (n == 0) {
  6748.         fprintf(stdout, "Empty file\n");
  6749.         return;
  6750.     }
  6751.     fclose(f);
  6752. }
  6753.  
  6754. void uci() {
  6755.     char *ptr = NULL;
  6756.     int i;
  6757.     sint64 value;
  6758.  
  6759.     (void)fgets(mstring, 65536, stdin);
  6760.     if (feof(stdin)) exit(0);
  6761.     ptr = strchr(mstring, '\n');
  6762.     if (ptr != NULL) *ptr = 0;
  6763.     if (!strcmp(mstring, "uci")) {
  6764. #ifndef W32_BUILD
  6765.         fprintf(stdout,"id name Gull 3 x64\n");
  6766. #else
  6767.         fprintf(stdout,"id name Gull 3\n");
  6768. #endif
  6769.         fprintf(stdout,"id author ThinkingALot\n");
  6770. #ifndef W32_BUILD
  6771.         fprintf(stdout,"option name Hash type spin min 1 max 65536 default 16\n");
  6772. #else
  6773.         fprintf(stdout,"option name Hash type spin min 1 max 1024 default 16\n");
  6774. #endif
  6775.         fprintf(stdout,"option name Ponder type check default false\n");
  6776.         fprintf(stdout,"option name MultiPV type spin min 1 max 64 default 1\n");
  6777.         fprintf(stdout,"option name Clear Hash type button\n");
  6778.         fprintf(stdout,"option name PV Hash type check default true\n");
  6779.         fprintf(stdout,"option name Aspiration window type check default true\n");
  6780. #ifdef CPU_TIMING
  6781.         fprintf(stdout, "option name CPUTiming type check default false\n");
  6782.         fprintf(stdout, "option name MaxDepth type spin min 0 max 128 default 0\n");
  6783.         fprintf(stdout, "option name MaxKNodes type spin min 0 max 65536 default 0\n");
  6784.         fprintf(stdout, "option name BaseTime type spin min 0 max 1000000 default 1000\n");
  6785.         fprintf(stdout, "option name IncTime type spin min 0 max 1000000 default 5\n");
  6786. #endif
  6787.         fprintf(stdout, "option name Threads type spin min 1 max %d default %d\n", Min(CPUs, MaxPrN), PrN);
  6788. #ifdef LARGE_PAGES
  6789.         fprintf(stdout, "option name Large memory pages type check default true\n");
  6790. #endif
  6791.         fprintf(stdout,"uciok\n");
  6792.         if (F(Searching)) init_search(1);
  6793.     } else if (!strcmp(mstring,"ucinewgame")) {
  6794.         Stop = 0;
  6795.         init_search(1);
  6796.     } else if (!strcmp(mstring,"isready")) {
  6797.         fprintf(stdout,"readyok\n");
  6798.         fflush(stdout);
  6799.     }  else if (!memcmp(mstring,"position",8)) {
  6800.         if (F(Searching)) get_position(mstring);
  6801.     } else if (!memcmp(mstring,"go",2)) {
  6802.         if (F(Searching)) get_time_limit(mstring);
  6803.     } else if (!memcmp(mstring,"setoption",9)) {
  6804.         ptr = strtok(mstring," ");
  6805.         for (ptr = strtok(NULL," "); ptr != NULL; ptr = strtok(NULL," ")) {
  6806.             if (!memcmp(ptr,"Hash",4) && !Searching) {
  6807.                 ptr += 11;
  6808.                 value = atoi(ptr);
  6809.                 if (value < 1) value = 1;
  6810. #ifdef W32_BUILD
  6811.                 if (value > 1024) value = 1024;
  6812. #else
  6813.                 if (value > 65536) value = 65536;
  6814. #endif
  6815.                 value = (Bit(msb(value)) * Convert(1024 * 1024, sint64)) / Convert(sizeof(GEntry), sint64);
  6816.                 if (value != hash_size) {
  6817.                     ResetHash = 1;
  6818.                     hash_size = value;
  6819.                     longjmp(ResetJump, 1);
  6820.                 }
  6821.             } else if (!memcmp(ptr, "Threads", 7) && !Searching) {
  6822.                 ptr += 14;
  6823.                 value = atoi(ptr);
  6824.                 if (value != PrN) {
  6825.                     NewPrN = Max(1, Min(MaxPrN, value));
  6826.                     ResetHash = 0;
  6827.                     longjmp(ResetJump, 1);
  6828.                 }
  6829.             } else if (!memcmp(ptr, "MultiPV", 7)) {
  6830.                 ptr += 14;
  6831.                 PVN = atoi(ptr);
  6832.                 Stop = 1;
  6833.             } else if (!memcmp(ptr,"Ponder",6)) {
  6834.                 ptr += 13;
  6835.                 if (ptr[0] == 't') Ponder = 1;
  6836.                 else Ponder = 0;
  6837.             } else if (!memcmp(ptr,"Clear",5)) {
  6838.                 init_search(1);
  6839.                 break;
  6840.             } else if (!memcmp(ptr,"PV",2)) {
  6841.                 ptr += 14;
  6842.                 if (ptr[0] == 't') PVHashing = 1;
  6843.                 else PVHashing = 0;
  6844.             } else if (!memcmp(ptr, "Large", 5) && !Searching) {
  6845.                 ptr += 25;
  6846.                 if (ptr[0] == 't') {
  6847.                     if (LargePages) return;
  6848.                     LargePages = 1;
  6849.                 } else {
  6850.                     if (!LargePages) return;
  6851.                     LargePages = 0;
  6852.                 }
  6853.                 ResetHash = 1;
  6854.                 longjmp(ResetJump, 1);
  6855.             } else if (!memcmp(ptr, "Aspiration", 10)) {
  6856.                 ptr += 24;
  6857.                 if (ptr[0] == 't') Aspiration = 1;
  6858.                 else Aspiration = 0;
  6859.             }
  6860. #ifdef CPU_TIMING
  6861.             else if (!memcmp(ptr, "CPUTiming", 9)) {
  6862.                 ptr += 16;
  6863.                 if (ptr[0] == 't') CpuTiming = 1;
  6864.                 else CpuTiming = 0;
  6865.             } else if (!memcmp(ptr, "MaxDepth", 8)) UciMaxDepth = atoi(ptr + 15);
  6866.             else if (!memcmp(ptr, "MaxKNodes", 9)) UciMaxKNodes = atoi(ptr + 16);
  6867.             else if (!memcmp(ptr, "BaseTime", 8)) UciBaseTime = atoi(ptr + 15);
  6868.             else if (!memcmp(ptr, "IncTime", 7)) UciIncTime = atoi(ptr + 14);
  6869. #endif
  6870.         }
  6871.     } else if (!strcmp(mstring,"stop")) {
  6872.         Stop = 1;
  6873.         if (F(Searching)) send_best_move();
  6874.     } else if (!strcmp(mstring,"ponderhit")) {
  6875.         Infinite = 0;
  6876.         if (!RootList[1]) Stop = 1;
  6877.         if (F(CurrentSI->Bad) && F(CurrentSI->FailLow) && time_to_stop(BaseSI, LastTime, 0)) Stop = 1;
  6878.         if (F(Searching)) send_best_move();
  6879.     } else if (!strcmp(mstring, "quit")) {
  6880.         for (i = 1; i < PrN; i++) {
  6881.             TerminateProcess(ChildPr[i], 0);
  6882.             CloseHandle(ChildPr[i]);
  6883.         }
  6884.         exit(0);
  6885.     } else if (!memcmp(mstring, "epd", 3)) {
  6886.         ptr = mstring + 4;
  6887.         value = atoi(ptr);
  6888.         epd_test("op.epd", value);
  6889.     }
  6890. }
  6891.  
  6892. HANDLE CreateChildProcess(int child_id) {
  6893.     char name[1024];
  6894.     TCHAR szCmdline[1024];
  6895.     PROCESS_INFORMATION piProcInfo;
  6896.     STARTUPINFO siStartInfo;
  6897.     BOOL bSuccess = FALSE;
  6898.  
  6899.     ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
  6900.     ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
  6901.     ZeroMemory(szCmdline, 1024 * sizeof(TCHAR));
  6902.     ZeroMemory(name, 1024);
  6903.  
  6904.     siStartInfo.cb = sizeof(STARTUPINFO);
  6905.     siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
  6906.  
  6907.     GetModuleFileName(NULL, name, 1024);
  6908.     sprintf(szCmdline, " child %d %d", WinParId, child_id);
  6909.  
  6910.     bSuccess = CreateProcess(TEXT(name), TEXT(szCmdline), NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &siStartInfo, &piProcInfo);
  6911.  
  6912.     if (bSuccess) {
  6913.         CloseHandle(piProcInfo.hThread);
  6914.         return piProcInfo.hProcess;
  6915.     } else {
  6916.         fprintf(stdout, "Error %d\n", GetLastError());
  6917.         return NULL;
  6918.     }
  6919. }
  6920.  
  6921. void main(int argc, char *argv[]) {
  6922.     DWORD p;
  6923.     int i, HT = 0;
  6924.     SYSTEM_INFO sysinfo;
  6925.  
  6926.     if (argc >= 2) if (!memcmp(argv[1], "child", 5)) {
  6927.         child = 1; parent = 0;
  6928.         WinParId = atoi(argv[2]);
  6929.         Id = atoi(argv[3]);
  6930.     }
  6931.  
  6932.     int CPUInfo[4] = { -1 };
  6933.     __cpuid(CPUInfo, 1);
  6934.     HardwarePopCnt = (CPUInfo[2] >> 23) & 1;
  6935.  
  6936.     if (parent) {
  6937.         if (((CPUInfo[3] >> 28) & 1) && GetProcAddress(GetModuleHandle(TEXT("kernel32")), "GetLogicalProcessorInformation") != NULL) {
  6938.             SYSTEM_LOGICAL_PROCESSOR_INFORMATION syslogprocinfo[1];
  6939.             p = sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
  6940. #ifndef W32_BUILD
  6941.             GetLogicalProcessorInformation(syslogprocinfo, &p);
  6942.             if (syslogprocinfo->ProcessorCore.Flags == 1) HT = 1;
  6943. #endif
  6944.         }
  6945.         WinParId = GetProcessId(GetCurrentProcess());
  6946.         HANDLE JOB = CreateJobObject(NULL, NULL);
  6947.         JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
  6948.         jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
  6949.         SetInformationJobObject(JOB, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli));
  6950.         AssignProcessToJobObject(JOB, GetCurrentProcess());
  6951.         if (MaxPrN > 1) {
  6952.             GetSystemInfo(&sysinfo);
  6953.             CPUs = sysinfo.dwNumberOfProcessors;
  6954.             PrN = Min(CPUs, MaxPrN);
  6955.             if (HT) PrN = Max(1, Min(PrN, CPUs / 2));
  6956.         }
  6957.     }
  6958.  
  6959. #ifdef CPU_TIMING
  6960.     SetPriorityClass(GetCurrentProcess(), IDLE_PRIORITY_CLASS);
  6961. #endif
  6962.  
  6963.     init();
  6964.  
  6965.     StreamHandle = GetStdHandle(STD_INPUT_HANDLE);
  6966.     Console = GetConsoleMode(StreamHandle, &p);
  6967.     if (Console) {
  6968.         SetConsoleMode(StreamHandle, p & (~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT)));
  6969.         FlushConsoleInputBuffer(StreamHandle);
  6970.     }
  6971.  
  6972.     setbuf(stdout, NULL);
  6973.     setbuf(stdin, NULL);
  6974.     setvbuf(stdout, NULL, _IONBF, 0);
  6975.     setvbuf(stdin, NULL, _IONBF, 0);
  6976.     fflush(NULL);
  6977.  
  6978. #ifndef W32_BUILD
  6979.     fprintf(stdout, "Gull 3 x64\n");
  6980. #else
  6981.     fprintf(stdout, "Gull 3\n");
  6982. #endif
  6983.  
  6984. reset_jump:
  6985. #ifndef TUNER
  6986.     if (parent) {
  6987.         if (setjmp(ResetJump)) {
  6988.             for (i = 1; i < PrN; i++) TerminateProcess(ChildPr[i], 0);
  6989.             for (i = 1; i < PrN; i++) {
  6990.                 WaitForSingleObject(ChildPr[i], INFINITE);
  6991.                 CloseHandle(ChildPr[i]);
  6992.             }
  6993.             Smpi->searching = Smpi->active_sp = Smpi->stop = 0;
  6994.             for (i = 0; i < MaxSplitPoints; i++) Smpi->Sp->active = Smpi->Sp->claimed = 0;
  6995.                
  6996.             Smpi->hash_size = hash_size;
  6997.             if (NewPrN) Smpi->PrN = PrN = NewPrN;
  6998.             goto reset_jump;
  6999.         }
  7000.         Smpi->hash_size = hash_size;
  7001.         Smpi->PrN = PrN;
  7002.     } else {
  7003.         hash_size = Smpi->hash_size;
  7004.         PrN = Smpi->PrN;
  7005.     }
  7006. #endif
  7007.     if (ResetHash) init_hash();
  7008.     init_search(0);
  7009.  
  7010.     if (child) while (true) check_state();
  7011.     if (parent) for (i = 1; i < PrN; i++) ChildPr[i] = CreateChildProcess(i);
  7012.  
  7013. #ifdef EXPLAIN_EVAL
  7014.     get_board("3rr1k1/1pp2qpp/pnn1pp2/8/3PPB2/PQ3N1P/1PR2PP1/2R3K1 b - - 0 28");
  7015.     fexplain = fopen("evaluation.txt", "w");
  7016.     explain = 1; evaluate();
  7017.     fclose(fexplain);
  7018.     fprintf(stdout, "Press any key...\n"); getchar(); exit(0);
  7019. #endif
  7020.  
  7021. #ifdef TUNER
  7022.     if (argc >= 2) {
  7023.         if (!memcmp(argv[1], "client", 6)) Client = 1;
  7024.         else if (!memcmp(argv[1], "server", 6)) Server = 1;
  7025.         if (Client || Server) Local = 0;
  7026.     }
  7027.     fprintf(stdout, Client ? "Client\n" : (Server ? "Server\n" : "Local\n"));
  7028.  
  7029.     uint64 ctime; QueryProcessCycleTime(GetCurrentProcess(), &ctime); srand(time(NULL) + 123 * GetProcessId(GetCurrentProcess()) + ctime);
  7030.     QueryProcessCycleTime(GetCurrentProcess(), &ctime); seed = (uint64)(time(NULL) + 345 * GetProcessId(GetCurrentProcess()) + ctime);
  7031.     init_openings();
  7032.     init_variables();
  7033.  
  7034.     if (Client) {
  7035. #ifdef RECORD_GAMES
  7036.         RecordGames = 1;
  7037.         Buffer = (char*)malloc(16 * 1024 * 1024);
  7038. #endif
  7039.         while (true) get_command();
  7040.     }
  7041.  
  7042.     init_pst();
  7043.     init_eval();
  7044.     print_eval();
  7045.  
  7046.     //read_list("(-0.24,0.69,-3.56,14.38,-18.97,-9.43,31.93,-42.58,-84.76,-239.60,62.93,83.44,-124.95,25.59,-22.50,152.24,472.44,-652.13,-903.63,-16.63,11.50,-0.02,-202.44,29.65,-2.27,-62.69,-81.95,61.32,-492.11,-51.01,-23.03,-15.79,283.90,-116.64,-4.38,-92.49,-30.59,-48.53,-35.85,15.25,-83.44,-32.20,33.31,-14.71,27.13,215.48,-48.91,-107.82,5.28,-59.32,-9.16,-16.93,-21.26,-21.12,-35.52,-41.67,-35.52,-16.59,21.48,-1.20,-26.27,-23.81,-58.82,-9.36,38.87,-34.02,-10.33,0.07,101.64,11.30,-66.04,-4.39,10.43,-60.66,-6.41,0.68,-15.18,-69.89,-41.54,-84.48,-143.38,-46.16,-3.12,-13.96,31.00,-16.14,-89.96,100.44,-137.64,97.51,-85.03,62.93,78.39,444.37,-143.70,25.65,-74.57,-143.94,-106.03,-128.86,285.08,111.90,-24.94,-104.36,-142.29,-59.11,-92.95,-32.91,-153.55,15.40,-181.39,-35.76,14.98,-5.08,76.49,-80.38,177.51,132.39,-134.36,-6.67,49.81,-260.99,101.53,-41.31,-26.30,418.42,220.09,-127.18,762.99,-117.88,246.62,-203.99,18.52,266.32,290.73,112.16,292.84,127.11,277.25,189.46,214.95,304.06,399.54,-195.77,280.34,351.89,-485.96,-2.82,251.09,38.25,82.39,152.04,53.11,8.04,7.61,-21.45,10.43,-0.53,4.19,-9.26,13.89,14.56,19.18,7.64,-2.16,138.97,6.71,57.43,0.28,56.89,0.92,-9.14,35.31,1.05,8.57,10.12,34.71,0.23,71.71,76.05,153.65,114.23,85.39,1.34,-12.79,26.11,48.42,125.83,147.73,148.27,41.60,42.53,-14.37,6.87,-6.88,-2.23,130.20,22.09,45.46,15.40,13.11,8.80,2.28,2.99,-0.83,-3.11,-0.81,4.40,6.09,6.27,5.79,5.24,-2.88,-0.26,16.45,-2.67,11.20,7.72,6.17,1.23,3.61,0.08,-0.51,-0.25,9.09,2.08,0.69,0.35,13.18,6.69,0.52,1.58,1.56,-0.95,11.40,0.81,-6.78,3.32,-4.89,8.87,-5.50,31.67,0.30,2.94,0.18,5.42,14.11,33.51,28.03,32.65,21.20,11.16,48.32,14.90,4.31,2.41,2.18,2.69,0.78,0.05,4.27,1.51,17.77,7.82,5.21,1.29,0.15,4.35,-0.12,-0.06,-0.25,3.24,5.37,5.85,14.36,-1.62,9.45,0.47,4.07,5.19,26.33,2.20,20.31,37.81,1.02,82.85,56.61,23.77,19.82,-3.83,47.50,25.50)", Base, active_vars);
  7047.     //eval_to_cpp("gd.cpp", Base);
  7048.  
  7049.     save_list(Base);
  7050.  
  7051.     //pgn_stat();
  7052. #ifdef RECORD_GAMES
  7053.     match_los(Base, Base, 4 * 64 * 1024, 512, 7, 0.0, 0.0, 0.0, 0.0, MatchInfo, 1);
  7054. #endif
  7055.  
  7056.     double NormalizedVar[MaxVariables]; NormalizeVar(Base,Var,2,256,10.0,20.0,NormalizedVar); double_to_double(Var,NormalizedVar,active_vars);
  7057.     //read_list("(4.10,3.41,7.24,11.13,44.59,41.51,67.17,126.38,183.25,328.40,95.55,442.95,110.04,439.85,199.82,506.49,1000.00,531.27,1000.00,94.70,40.64,96.88,182.65,154.15,152.52,490.96,231.09,605.53,1000.00,36.49,55.68,30.62,35.70,21.40,18.08,38.61,48.23,17.96,33.78,25.56,31.86,16.40,22.84,18.78,35.36,26.99,27.03,27.50,41.10,24.01,21.96,28.26,24.41,19.37,21.28,49.80,30.27,10.66,12.25,43.65,28.65,35.98,75.89,26.88,47.37,8.62,37.29,22.31,60.45,28.59,18.53,100.00,54.22,9.86,10.63,83.68,25.20,124.05,121.47,93.76,81.23,48.30,56.78,56.15,67.16,78.24,169.91,68.80,114.34,43.30,55.89,95.85,122.56,102.36,77.96,112.11,88.70,53.74,76.44,47.93,46.64,70.83,57.70,137.88,108.52,125.92,79.97,33.71,49.84,44.58,192.99,129.64,271.09,79.00,145.01,69.40,193.09,156.78,186.59,391.22,150.93,346.72,80.75,230.85,128.81,46.74,49.53,19.18,39.71,27.84,39.56,60.18,55.76,40.46,31.10,34.48,41.23,25.69,22.04,14.65,27.90,31.79,85.75,49.45,100.00,48.27,25.91,60.07,62.46)", Var, active_vars);
  7058.  
  7059.     GD(Base,Var,7,5.0,1.0,50.0,16 * 1024,16 * 1024,3.0,2.0,2.0,0.0);
  7060.  
  7061.     double New[1024]; read_list("(5.07,27.02,27.37,15.16,28.60,14.62,40.93,8.61,14.02,172.58,178.09,180.83,457.03,128.24,172.66,178.21,343.44,1281.53,45.85)", New, active_vars);
  7062.     for (i = 7; i < 64; i++) {
  7063.         fprintf(stdout, "\ndepth = %d/%d: \n", i, i + 1);
  7064.         match_los(New, Base, 4 * 1024, 128, i, 3.0, 3.0, 0.0, 0.0, MatchInfo, 1);
  7065.     }
  7066. #endif
  7067.  
  7068.     while (true) uci();
  7069. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement