2 * book.c -- code for probing Polyglot opening books
4 * This code was first released in the public domain by Michel Van den Bergh.
5 * The array Random64 is taken from the Polyglot source code.
6 * I am pretty sure that a table of random numbers is never protected
9 * It s adapted by H.G. Muller for working with xboard / Winboard
11 * The following terms apply to the enhanced version of XBoard distributed
12 * by the Free Software Foundation:
13 * ------------------------------------------------------------------------
15 * GNU XBoard is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation, either version 3 of the License, or (at
18 * your option) any later version.
20 * GNU XBoard is distributed in the hope that it will be useful, but
21 * WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program. If not, see http://www.gnu.org/licenses/. *
28 * ------------------------------------------------------------------------
46 # define _(s) gettext (s)
47 # define N_(s) gettext_noop (s)
54 typedef unsigned __int64 uint64;
56 typedef unsigned long long int uint64;
60 # define U64(u) (u##ui64)
62 # define U64(u) (u##ULL)
65 typedef unsigned char uint8;
66 typedef unsigned short uint16;
67 typedef unsigned int uint32;
77 entry_t entry_none = {
81 char *promote_pieces=" nbrqac=+";
83 uint64 Random64[781] = {
84 U64(0x9D39247E33776D41), U64(0x2AF7398005AAA5C7), U64(0x44DB015024623547), U64(0x9C15F73E62A76AE2),
85 U64(0x75834465489C0C89), U64(0x3290AC3A203001BF), U64(0x0FBBAD1F61042279), U64(0xE83A908FF2FB60CA),
86 U64(0x0D7E765D58755C10), U64(0x1A083822CEAFE02D), U64(0x9605D5F0E25EC3B0), U64(0xD021FF5CD13A2ED5),
87 U64(0x40BDF15D4A672E32), U64(0x011355146FD56395), U64(0x5DB4832046F3D9E5), U64(0x239F8B2D7FF719CC),
88 U64(0x05D1A1AE85B49AA1), U64(0x679F848F6E8FC971), U64(0x7449BBFF801FED0B), U64(0x7D11CDB1C3B7ADF0),
89 U64(0x82C7709E781EB7CC), U64(0xF3218F1C9510786C), U64(0x331478F3AF51BBE6), U64(0x4BB38DE5E7219443),
90 U64(0xAA649C6EBCFD50FC), U64(0x8DBD98A352AFD40B), U64(0x87D2074B81D79217), U64(0x19F3C751D3E92AE1),
91 U64(0xB4AB30F062B19ABF), U64(0x7B0500AC42047AC4), U64(0xC9452CA81A09D85D), U64(0x24AA6C514DA27500),
92 U64(0x4C9F34427501B447), U64(0x14A68FD73C910841), U64(0xA71B9B83461CBD93), U64(0x03488B95B0F1850F),
93 U64(0x637B2B34FF93C040), U64(0x09D1BC9A3DD90A94), U64(0x3575668334A1DD3B), U64(0x735E2B97A4C45A23),
94 U64(0x18727070F1BD400B), U64(0x1FCBACD259BF02E7), U64(0xD310A7C2CE9B6555), U64(0xBF983FE0FE5D8244),
95 U64(0x9F74D14F7454A824), U64(0x51EBDC4AB9BA3035), U64(0x5C82C505DB9AB0FA), U64(0xFCF7FE8A3430B241),
96 U64(0x3253A729B9BA3DDE), U64(0x8C74C368081B3075), U64(0xB9BC6C87167C33E7), U64(0x7EF48F2B83024E20),
97 U64(0x11D505D4C351BD7F), U64(0x6568FCA92C76A243), U64(0x4DE0B0F40F32A7B8), U64(0x96D693460CC37E5D),
98 U64(0x42E240CB63689F2F), U64(0x6D2BDCDAE2919661), U64(0x42880B0236E4D951), U64(0x5F0F4A5898171BB6),
99 U64(0x39F890F579F92F88), U64(0x93C5B5F47356388B), U64(0x63DC359D8D231B78), U64(0xEC16CA8AEA98AD76),
100 U64(0x5355F900C2A82DC7), U64(0x07FB9F855A997142), U64(0x5093417AA8A7ED5E), U64(0x7BCBC38DA25A7F3C),
101 U64(0x19FC8A768CF4B6D4), U64(0x637A7780DECFC0D9), U64(0x8249A47AEE0E41F7), U64(0x79AD695501E7D1E8),
102 U64(0x14ACBAF4777D5776), U64(0xF145B6BECCDEA195), U64(0xDABF2AC8201752FC), U64(0x24C3C94DF9C8D3F6),
103 U64(0xBB6E2924F03912EA), U64(0x0CE26C0B95C980D9), U64(0xA49CD132BFBF7CC4), U64(0xE99D662AF4243939),
104 U64(0x27E6AD7891165C3F), U64(0x8535F040B9744FF1), U64(0x54B3F4FA5F40D873), U64(0x72B12C32127FED2B),
105 U64(0xEE954D3C7B411F47), U64(0x9A85AC909A24EAA1), U64(0x70AC4CD9F04F21F5), U64(0xF9B89D3E99A075C2),
106 U64(0x87B3E2B2B5C907B1), U64(0xA366E5B8C54F48B8), U64(0xAE4A9346CC3F7CF2), U64(0x1920C04D47267BBD),
107 U64(0x87BF02C6B49E2AE9), U64(0x092237AC237F3859), U64(0xFF07F64EF8ED14D0), U64(0x8DE8DCA9F03CC54E),
108 U64(0x9C1633264DB49C89), U64(0xB3F22C3D0B0B38ED), U64(0x390E5FB44D01144B), U64(0x5BFEA5B4712768E9),
109 U64(0x1E1032911FA78984), U64(0x9A74ACB964E78CB3), U64(0x4F80F7A035DAFB04), U64(0x6304D09A0B3738C4),
110 U64(0x2171E64683023A08), U64(0x5B9B63EB9CEFF80C), U64(0x506AACF489889342), U64(0x1881AFC9A3A701D6),
111 U64(0x6503080440750644), U64(0xDFD395339CDBF4A7), U64(0xEF927DBCF00C20F2), U64(0x7B32F7D1E03680EC),
112 U64(0xB9FD7620E7316243), U64(0x05A7E8A57DB91B77), U64(0xB5889C6E15630A75), U64(0x4A750A09CE9573F7),
113 U64(0xCF464CEC899A2F8A), U64(0xF538639CE705B824), U64(0x3C79A0FF5580EF7F), U64(0xEDE6C87F8477609D),
114 U64(0x799E81F05BC93F31), U64(0x86536B8CF3428A8C), U64(0x97D7374C60087B73), U64(0xA246637CFF328532),
115 U64(0x043FCAE60CC0EBA0), U64(0x920E449535DD359E), U64(0x70EB093B15B290CC), U64(0x73A1921916591CBD),
116 U64(0x56436C9FE1A1AA8D), U64(0xEFAC4B70633B8F81), U64(0xBB215798D45DF7AF), U64(0x45F20042F24F1768),
117 U64(0x930F80F4E8EB7462), U64(0xFF6712FFCFD75EA1), U64(0xAE623FD67468AA70), U64(0xDD2C5BC84BC8D8FC),
118 U64(0x7EED120D54CF2DD9), U64(0x22FE545401165F1C), U64(0xC91800E98FB99929), U64(0x808BD68E6AC10365),
119 U64(0xDEC468145B7605F6), U64(0x1BEDE3A3AEF53302), U64(0x43539603D6C55602), U64(0xAA969B5C691CCB7A),
120 U64(0xA87832D392EFEE56), U64(0x65942C7B3C7E11AE), U64(0xDED2D633CAD004F6), U64(0x21F08570F420E565),
121 U64(0xB415938D7DA94E3C), U64(0x91B859E59ECB6350), U64(0x10CFF333E0ED804A), U64(0x28AED140BE0BB7DD),
122 U64(0xC5CC1D89724FA456), U64(0x5648F680F11A2741), U64(0x2D255069F0B7DAB3), U64(0x9BC5A38EF729ABD4),
123 U64(0xEF2F054308F6A2BC), U64(0xAF2042F5CC5C2858), U64(0x480412BAB7F5BE2A), U64(0xAEF3AF4A563DFE43),
124 U64(0x19AFE59AE451497F), U64(0x52593803DFF1E840), U64(0xF4F076E65F2CE6F0), U64(0x11379625747D5AF3),
125 U64(0xBCE5D2248682C115), U64(0x9DA4243DE836994F), U64(0x066F70B33FE09017), U64(0x4DC4DE189B671A1C),
126 U64(0x51039AB7712457C3), U64(0xC07A3F80C31FB4B4), U64(0xB46EE9C5E64A6E7C), U64(0xB3819A42ABE61C87),
127 U64(0x21A007933A522A20), U64(0x2DF16F761598AA4F), U64(0x763C4A1371B368FD), U64(0xF793C46702E086A0),
128 U64(0xD7288E012AEB8D31), U64(0xDE336A2A4BC1C44B), U64(0x0BF692B38D079F23), U64(0x2C604A7A177326B3),
129 U64(0x4850E73E03EB6064), U64(0xCFC447F1E53C8E1B), U64(0xB05CA3F564268D99), U64(0x9AE182C8BC9474E8),
130 U64(0xA4FC4BD4FC5558CA), U64(0xE755178D58FC4E76), U64(0x69B97DB1A4C03DFE), U64(0xF9B5B7C4ACC67C96),
131 U64(0xFC6A82D64B8655FB), U64(0x9C684CB6C4D24417), U64(0x8EC97D2917456ED0), U64(0x6703DF9D2924E97E),
132 U64(0xC547F57E42A7444E), U64(0x78E37644E7CAD29E), U64(0xFE9A44E9362F05FA), U64(0x08BD35CC38336615),
133 U64(0x9315E5EB3A129ACE), U64(0x94061B871E04DF75), U64(0xDF1D9F9D784BA010), U64(0x3BBA57B68871B59D),
134 U64(0xD2B7ADEEDED1F73F), U64(0xF7A255D83BC373F8), U64(0xD7F4F2448C0CEB81), U64(0xD95BE88CD210FFA7),
135 U64(0x336F52F8FF4728E7), U64(0xA74049DAC312AC71), U64(0xA2F61BB6E437FDB5), U64(0x4F2A5CB07F6A35B3),
136 U64(0x87D380BDA5BF7859), U64(0x16B9F7E06C453A21), U64(0x7BA2484C8A0FD54E), U64(0xF3A678CAD9A2E38C),
137 U64(0x39B0BF7DDE437BA2), U64(0xFCAF55C1BF8A4424), U64(0x18FCF680573FA594), U64(0x4C0563B89F495AC3),
138 U64(0x40E087931A00930D), U64(0x8CFFA9412EB642C1), U64(0x68CA39053261169F), U64(0x7A1EE967D27579E2),
139 U64(0x9D1D60E5076F5B6F), U64(0x3810E399B6F65BA2), U64(0x32095B6D4AB5F9B1), U64(0x35CAB62109DD038A),
140 U64(0xA90B24499FCFAFB1), U64(0x77A225A07CC2C6BD), U64(0x513E5E634C70E331), U64(0x4361C0CA3F692F12),
141 U64(0xD941ACA44B20A45B), U64(0x528F7C8602C5807B), U64(0x52AB92BEB9613989), U64(0x9D1DFA2EFC557F73),
142 U64(0x722FF175F572C348), U64(0x1D1260A51107FE97), U64(0x7A249A57EC0C9BA2), U64(0x04208FE9E8F7F2D6),
143 U64(0x5A110C6058B920A0), U64(0x0CD9A497658A5698), U64(0x56FD23C8F9715A4C), U64(0x284C847B9D887AAE),
144 U64(0x04FEABFBBDB619CB), U64(0x742E1E651C60BA83), U64(0x9A9632E65904AD3C), U64(0x881B82A13B51B9E2),
145 U64(0x506E6744CD974924), U64(0xB0183DB56FFC6A79), U64(0x0ED9B915C66ED37E), U64(0x5E11E86D5873D484),
146 U64(0xF678647E3519AC6E), U64(0x1B85D488D0F20CC5), U64(0xDAB9FE6525D89021), U64(0x0D151D86ADB73615),
147 U64(0xA865A54EDCC0F019), U64(0x93C42566AEF98FFB), U64(0x99E7AFEABE000731), U64(0x48CBFF086DDF285A),
148 U64(0x7F9B6AF1EBF78BAF), U64(0x58627E1A149BBA21), U64(0x2CD16E2ABD791E33), U64(0xD363EFF5F0977996),
149 U64(0x0CE2A38C344A6EED), U64(0x1A804AADB9CFA741), U64(0x907F30421D78C5DE), U64(0x501F65EDB3034D07),
150 U64(0x37624AE5A48FA6E9), U64(0x957BAF61700CFF4E), U64(0x3A6C27934E31188A), U64(0xD49503536ABCA345),
151 U64(0x088E049589C432E0), U64(0xF943AEE7FEBF21B8), U64(0x6C3B8E3E336139D3), U64(0x364F6FFA464EE52E),
152 U64(0xD60F6DCEDC314222), U64(0x56963B0DCA418FC0), U64(0x16F50EDF91E513AF), U64(0xEF1955914B609F93),
153 U64(0x565601C0364E3228), U64(0xECB53939887E8175), U64(0xBAC7A9A18531294B), U64(0xB344C470397BBA52),
154 U64(0x65D34954DAF3CEBD), U64(0xB4B81B3FA97511E2), U64(0xB422061193D6F6A7), U64(0x071582401C38434D),
155 U64(0x7A13F18BBEDC4FF5), U64(0xBC4097B116C524D2), U64(0x59B97885E2F2EA28), U64(0x99170A5DC3115544),
156 U64(0x6F423357E7C6A9F9), U64(0x325928EE6E6F8794), U64(0xD0E4366228B03343), U64(0x565C31F7DE89EA27),
157 U64(0x30F5611484119414), U64(0xD873DB391292ED4F), U64(0x7BD94E1D8E17DEBC), U64(0xC7D9F16864A76E94),
158 U64(0x947AE053EE56E63C), U64(0xC8C93882F9475F5F), U64(0x3A9BF55BA91F81CA), U64(0xD9A11FBB3D9808E4),
159 U64(0x0FD22063EDC29FCA), U64(0xB3F256D8ACA0B0B9), U64(0xB03031A8B4516E84), U64(0x35DD37D5871448AF),
160 U64(0xE9F6082B05542E4E), U64(0xEBFAFA33D7254B59), U64(0x9255ABB50D532280), U64(0xB9AB4CE57F2D34F3),
161 U64(0x693501D628297551), U64(0xC62C58F97DD949BF), U64(0xCD454F8F19C5126A), U64(0xBBE83F4ECC2BDECB),
162 U64(0xDC842B7E2819E230), U64(0xBA89142E007503B8), U64(0xA3BC941D0A5061CB), U64(0xE9F6760E32CD8021),
163 U64(0x09C7E552BC76492F), U64(0x852F54934DA55CC9), U64(0x8107FCCF064FCF56), U64(0x098954D51FFF6580),
164 U64(0x23B70EDB1955C4BF), U64(0xC330DE426430F69D), U64(0x4715ED43E8A45C0A), U64(0xA8D7E4DAB780A08D),
165 U64(0x0572B974F03CE0BB), U64(0xB57D2E985E1419C7), U64(0xE8D9ECBE2CF3D73F), U64(0x2FE4B17170E59750),
166 U64(0x11317BA87905E790), U64(0x7FBF21EC8A1F45EC), U64(0x1725CABFCB045B00), U64(0x964E915CD5E2B207),
167 U64(0x3E2B8BCBF016D66D), U64(0xBE7444E39328A0AC), U64(0xF85B2B4FBCDE44B7), U64(0x49353FEA39BA63B1),
168 U64(0x1DD01AAFCD53486A), U64(0x1FCA8A92FD719F85), U64(0xFC7C95D827357AFA), U64(0x18A6A990C8B35EBD),
169 U64(0xCCCB7005C6B9C28D), U64(0x3BDBB92C43B17F26), U64(0xAA70B5B4F89695A2), U64(0xE94C39A54A98307F),
170 U64(0xB7A0B174CFF6F36E), U64(0xD4DBA84729AF48AD), U64(0x2E18BC1AD9704A68), U64(0x2DE0966DAF2F8B1C),
171 U64(0xB9C11D5B1E43A07E), U64(0x64972D68DEE33360), U64(0x94628D38D0C20584), U64(0xDBC0D2B6AB90A559),
172 U64(0xD2733C4335C6A72F), U64(0x7E75D99D94A70F4D), U64(0x6CED1983376FA72B), U64(0x97FCAACBF030BC24),
173 U64(0x7B77497B32503B12), U64(0x8547EDDFB81CCB94), U64(0x79999CDFF70902CB), U64(0xCFFE1939438E9B24),
174 U64(0x829626E3892D95D7), U64(0x92FAE24291F2B3F1), U64(0x63E22C147B9C3403), U64(0xC678B6D860284A1C),
175 U64(0x5873888850659AE7), U64(0x0981DCD296A8736D), U64(0x9F65789A6509A440), U64(0x9FF38FED72E9052F),
176 U64(0xE479EE5B9930578C), U64(0xE7F28ECD2D49EECD), U64(0x56C074A581EA17FE), U64(0x5544F7D774B14AEF),
177 U64(0x7B3F0195FC6F290F), U64(0x12153635B2C0CF57), U64(0x7F5126DBBA5E0CA7), U64(0x7A76956C3EAFB413),
178 U64(0x3D5774A11D31AB39), U64(0x8A1B083821F40CB4), U64(0x7B4A38E32537DF62), U64(0x950113646D1D6E03),
179 U64(0x4DA8979A0041E8A9), U64(0x3BC36E078F7515D7), U64(0x5D0A12F27AD310D1), U64(0x7F9D1A2E1EBE1327),
180 U64(0xDA3A361B1C5157B1), U64(0xDCDD7D20903D0C25), U64(0x36833336D068F707), U64(0xCE68341F79893389),
181 U64(0xAB9090168DD05F34), U64(0x43954B3252DC25E5), U64(0xB438C2B67F98E5E9), U64(0x10DCD78E3851A492),
182 U64(0xDBC27AB5447822BF), U64(0x9B3CDB65F82CA382), U64(0xB67B7896167B4C84), U64(0xBFCED1B0048EAC50),
183 U64(0xA9119B60369FFEBD), U64(0x1FFF7AC80904BF45), U64(0xAC12FB171817EEE7), U64(0xAF08DA9177DDA93D),
184 U64(0x1B0CAB936E65C744), U64(0xB559EB1D04E5E932), U64(0xC37B45B3F8D6F2BA), U64(0xC3A9DC228CAAC9E9),
185 U64(0xF3B8B6675A6507FF), U64(0x9FC477DE4ED681DA), U64(0x67378D8ECCEF96CB), U64(0x6DD856D94D259236),
186 U64(0xA319CE15B0B4DB31), U64(0x073973751F12DD5E), U64(0x8A8E849EB32781A5), U64(0xE1925C71285279F5),
187 U64(0x74C04BF1790C0EFE), U64(0x4DDA48153C94938A), U64(0x9D266D6A1CC0542C), U64(0x7440FB816508C4FE),
188 U64(0x13328503DF48229F), U64(0xD6BF7BAEE43CAC40), U64(0x4838D65F6EF6748F), U64(0x1E152328F3318DEA),
189 U64(0x8F8419A348F296BF), U64(0x72C8834A5957B511), U64(0xD7A023A73260B45C), U64(0x94EBC8ABCFB56DAE),
190 U64(0x9FC10D0F989993E0), U64(0xDE68A2355B93CAE6), U64(0xA44CFE79AE538BBE), U64(0x9D1D84FCCE371425),
191 U64(0x51D2B1AB2DDFB636), U64(0x2FD7E4B9E72CD38C), U64(0x65CA5B96B7552210), U64(0xDD69A0D8AB3B546D),
192 U64(0x604D51B25FBF70E2), U64(0x73AA8A564FB7AC9E), U64(0x1A8C1E992B941148), U64(0xAAC40A2703D9BEA0),
193 U64(0x764DBEAE7FA4F3A6), U64(0x1E99B96E70A9BE8B), U64(0x2C5E9DEB57EF4743), U64(0x3A938FEE32D29981),
194 U64(0x26E6DB8FFDF5ADFE), U64(0x469356C504EC9F9D), U64(0xC8763C5B08D1908C), U64(0x3F6C6AF859D80055),
195 U64(0x7F7CC39420A3A545), U64(0x9BFB227EBDF4C5CE), U64(0x89039D79D6FC5C5C), U64(0x8FE88B57305E2AB6),
196 U64(0xA09E8C8C35AB96DE), U64(0xFA7E393983325753), U64(0xD6B6D0ECC617C699), U64(0xDFEA21EA9E7557E3),
197 U64(0xB67C1FA481680AF8), U64(0xCA1E3785A9E724E5), U64(0x1CFC8BED0D681639), U64(0xD18D8549D140CAEA),
198 U64(0x4ED0FE7E9DC91335), U64(0xE4DBF0634473F5D2), U64(0x1761F93A44D5AEFE), U64(0x53898E4C3910DA55),
199 U64(0x734DE8181F6EC39A), U64(0x2680B122BAA28D97), U64(0x298AF231C85BAFAB), U64(0x7983EED3740847D5),
200 U64(0x66C1A2A1A60CD889), U64(0x9E17E49642A3E4C1), U64(0xEDB454E7BADC0805), U64(0x50B704CAB602C329),
201 U64(0x4CC317FB9CDDD023), U64(0x66B4835D9EAFEA22), U64(0x219B97E26FFC81BD), U64(0x261E4E4C0A333A9D),
202 U64(0x1FE2CCA76517DB90), U64(0xD7504DFA8816EDBB), U64(0xB9571FA04DC089C8), U64(0x1DDC0325259B27DE),
203 U64(0xCF3F4688801EB9AA), U64(0xF4F5D05C10CAB243), U64(0x38B6525C21A42B0E), U64(0x36F60E2BA4FA6800),
204 U64(0xEB3593803173E0CE), U64(0x9C4CD6257C5A3603), U64(0xAF0C317D32ADAA8A), U64(0x258E5A80C7204C4B),
205 U64(0x8B889D624D44885D), U64(0xF4D14597E660F855), U64(0xD4347F66EC8941C3), U64(0xE699ED85B0DFB40D),
206 U64(0x2472F6207C2D0484), U64(0xC2A1E7B5B459AEB5), U64(0xAB4F6451CC1D45EC), U64(0x63767572AE3D6174),
207 U64(0xA59E0BD101731A28), U64(0x116D0016CB948F09), U64(0x2CF9C8CA052F6E9F), U64(0x0B090A7560A968E3),
208 U64(0xABEEDDB2DDE06FF1), U64(0x58EFC10B06A2068D), U64(0xC6E57A78FBD986E0), U64(0x2EAB8CA63CE802D7),
209 U64(0x14A195640116F336), U64(0x7C0828DD624EC390), U64(0xD74BBE77E6116AC7), U64(0x804456AF10F5FB53),
210 U64(0xEBE9EA2ADF4321C7), U64(0x03219A39EE587A30), U64(0x49787FEF17AF9924), U64(0xA1E9300CD8520548),
211 U64(0x5B45E522E4B1B4EF), U64(0xB49C3B3995091A36), U64(0xD4490AD526F14431), U64(0x12A8F216AF9418C2),
212 U64(0x001F837CC7350524), U64(0x1877B51E57A764D5), U64(0xA2853B80F17F58EE), U64(0x993E1DE72D36D310),
213 U64(0xB3598080CE64A656), U64(0x252F59CF0D9F04BB), U64(0xD23C8E176D113600), U64(0x1BDA0492E7E4586E),
214 U64(0x21E0BD5026C619BF), U64(0x3B097ADAF088F94E), U64(0x8D14DEDB30BE846E), U64(0xF95CFFA23AF5F6F4),
215 U64(0x3871700761B3F743), U64(0xCA672B91E9E4FA16), U64(0x64C8E531BFF53B55), U64(0x241260ED4AD1E87D),
216 U64(0x106C09B972D2E822), U64(0x7FBA195410E5CA30), U64(0x7884D9BC6CB569D8), U64(0x0647DFEDCD894A29),
217 U64(0x63573FF03E224774), U64(0x4FC8E9560F91B123), U64(0x1DB956E450275779), U64(0xB8D91274B9E9D4FB),
218 U64(0xA2EBEE47E2FBFCE1), U64(0xD9F1F30CCD97FB09), U64(0xEFED53D75FD64E6B), U64(0x2E6D02C36017F67F),
219 U64(0xA9AA4D20DB084E9B), U64(0xB64BE8D8B25396C1), U64(0x70CB6AF7C2D5BCF0), U64(0x98F076A4F7A2322E),
220 U64(0xBF84470805E69B5F), U64(0x94C3251F06F90CF3), U64(0x3E003E616A6591E9), U64(0xB925A6CD0421AFF3),
221 U64(0x61BDD1307C66E300), U64(0xBF8D5108E27E0D48), U64(0x240AB57A8B888B20), U64(0xFC87614BAF287E07),
222 U64(0xEF02CDD06FFDB432), U64(0xA1082C0466DF6C0A), U64(0x8215E577001332C8), U64(0xD39BB9C3A48DB6CF),
223 U64(0x2738259634305C14), U64(0x61CF4F94C97DF93D), U64(0x1B6BACA2AE4E125B), U64(0x758F450C88572E0B),
224 U64(0x959F587D507A8359), U64(0xB063E962E045F54D), U64(0x60E8ED72C0DFF5D1), U64(0x7B64978555326F9F),
225 U64(0xFD080D236DA814BA), U64(0x8C90FD9B083F4558), U64(0x106F72FE81E2C590), U64(0x7976033A39F7D952),
226 U64(0xA4EC0132764CA04B), U64(0x733EA705FAE4FA77), U64(0xB4D8F77BC3E56167), U64(0x9E21F4F903B33FD9),
227 U64(0x9D765E419FB69F6D), U64(0xD30C088BA61EA5EF), U64(0x5D94337FBFAF7F5B), U64(0x1A4E4822EB4D7A59),
228 U64(0x6FFE73E81B637FB3), U64(0xDDF957BC36D8B9CA), U64(0x64D0E29EEA8838B3), U64(0x08DD9BDFD96B9F63),
229 U64(0x087E79E5A57D1D13), U64(0xE328E230E3E2B3FB), U64(0x1C2559E30F0946BE), U64(0x720BF5F26F4D2EAA),
230 U64(0xB0774D261CC609DB), U64(0x443F64EC5A371195), U64(0x4112CF68649A260E), U64(0xD813F2FAB7F5C5CA),
231 U64(0x660D3257380841EE), U64(0x59AC2C7873F910A3), U64(0xE846963877671A17), U64(0x93B633ABFA3469F8),
232 U64(0xC0C0F5A60EF4CDCF), U64(0xCAF21ECD4377B28C), U64(0x57277707199B8175), U64(0x506C11B9D90E8B1D),
233 U64(0xD83CC2687A19255F), U64(0x4A29C6465A314CD1), U64(0xED2DF21216235097), U64(0xB5635C95FF7296E2),
234 U64(0x22AF003AB672E811), U64(0x52E762596BF68235), U64(0x9AEBA33AC6ECC6B0), U64(0x944F6DE09134DFB6),
235 U64(0x6C47BEC883A7DE39), U64(0x6AD047C430A12104), U64(0xA5B1CFDBA0AB4067), U64(0x7C45D833AFF07862),
236 U64(0x5092EF950A16DA0B), U64(0x9338E69C052B8E7B), U64(0x455A4B4CFE30E3F5), U64(0x6B02E63195AD0CF8),
237 U64(0x6B17B224BAD6BF27), U64(0xD1E0CCD25BB9C169), U64(0xDE0C89A556B9AE70), U64(0x50065E535A213CF6),
238 U64(0x9C1169FA2777B874), U64(0x78EDEFD694AF1EED), U64(0x6DC93D9526A50E68), U64(0xEE97F453F06791ED),
239 U64(0x32AB0EDB696703D3), U64(0x3A6853C7E70757A7), U64(0x31865CED6120F37D), U64(0x67FEF95D92607890),
240 U64(0x1F2B1D1F15F6DC9C), U64(0xB69E38A8965C6B65), U64(0xAA9119FF184CCCF4), U64(0xF43C732873F24C13),
241 U64(0xFB4A3D794A9A80D2), U64(0x3550C2321FD6109C), U64(0x371F77E76BB8417E), U64(0x6BFA9AAE5EC05779),
242 U64(0xCD04F3FF001A4778), U64(0xE3273522064480CA), U64(0x9F91508BFFCFC14A), U64(0x049A7F41061A9E60),
243 U64(0xFCB6BE43A9F2FE9B), U64(0x08DE8A1C7797DA9B), U64(0x8F9887E6078735A1), U64(0xB5B4071DBFC73A66),
244 U64(0x230E343DFBA08D33), U64(0x43ED7F5A0FAE657D), U64(0x3A88A0FBBCB05C63), U64(0x21874B8B4D2DBC4F),
245 U64(0x1BDEA12E35F6A8C9), U64(0x53C065C6C8E63528), U64(0xE34A1D250E7A8D6B), U64(0xD6B04D3B7651DD7E),
246 U64(0x5E90277E7CB39E2D), U64(0x2C046F22062DC67D), U64(0xB10BB459132D0A26), U64(0x3FA9DDFB67E2F199),
247 U64(0x0E09B88E1914F7AF), U64(0x10E8B35AF3EEAB37), U64(0x9EEDECA8E272B933), U64(0xD4C718BC4AE8AE5F),
248 U64(0x81536D601170FC20), U64(0x91B534F885818A06), U64(0xEC8177F83F900978), U64(0x190E714FADA5156E),
249 U64(0xB592BF39B0364963), U64(0x89C350C893AE7DC1), U64(0xAC042E70F8B383F2), U64(0xB49B52E587A1EE60),
250 U64(0xFB152FE3FF26DA89), U64(0x3E666E6F69AE2C15), U64(0x3B544EBE544C19F9), U64(0xE805A1E290CF2456),
251 U64(0x24B33C9D7ED25117), U64(0xE74733427B72F0C1), U64(0x0A804D18B7097475), U64(0x57E3306D881EDB4F),
252 U64(0x4AE7D6A36EB5DBCB), U64(0x2D8D5432157064C8), U64(0xD1E649DE1E7F268B), U64(0x8A328A1CEDFE552C),
253 U64(0x07A3AEC79624C7DA), U64(0x84547DDC3E203C94), U64(0x990A98FD5071D263), U64(0x1A4FF12616EEFC89),
254 U64(0xF6F7FD1431714200), U64(0x30C05B1BA332F41C), U64(0x8D2636B81555A786), U64(0x46C9FEB55D120902),
255 U64(0xCCEC0A73B49C9921), U64(0x4E9D2827355FC492), U64(0x19EBB029435DCB0F), U64(0x4659D2B743848A2C),
256 U64(0x963EF2C96B33BE31), U64(0x74F85198B05A2E7D), U64(0x5A0F544DD2B1FB18), U64(0x03727073C2E134B1),
257 U64(0xC7F6AA2DE59AEA61), U64(0x352787BAA0D7C22F), U64(0x9853EAB63B5E0B35), U64(0xABBDCDD7ED5C0860),
258 U64(0xCF05DAF5AC8D77B0), U64(0x49CAD48CEBF4A71E), U64(0x7A4C10EC2158C4A6), U64(0xD9E92AA246BF719E),
259 U64(0x13AE978D09FE5557), U64(0x730499AF921549FF), U64(0x4E4B705B92903BA4), U64(0xFF577222C14F0A3A),
260 U64(0x55B6344CF97AAFAE), U64(0xB862225B055B6960), U64(0xCAC09AFBDDD2CDB4), U64(0xDAF8E9829FE96B5F),
261 U64(0xB5FDFC5D3132C498), U64(0x310CB380DB6F7503), U64(0xE87FBB46217A360E), U64(0x2102AE466EBB1148),
262 U64(0xF8549E1A3AA5E00D), U64(0x07A69AFDCC42261A), U64(0xC4C118BFE78FEAAE), U64(0xF9F4892ED96BD438),
263 U64(0x1AF3DBE25D8F45DA), U64(0xF5B4B0B0D2DEEEB4), U64(0x962ACEEFA82E1C84), U64(0x046E3ECAAF453CE9),
264 U64(0xF05D129681949A4C), U64(0x964781CE734B3C84), U64(0x9C2ED44081CE5FBD), U64(0x522E23F3925E319E),
265 U64(0x177E00F9FC32F791), U64(0x2BC60A63A6F3B3F2), U64(0x222BBFAE61725606), U64(0x486289DDCC3D6780),
266 U64(0x7DC7785B8EFDFC80), U64(0x8AF38731C02BA980), U64(0x1FAB64EA29A2DDF7), U64(0xE4D9429322CD065A),
267 U64(0x9DA058C67844F20C), U64(0x24C0E332B70019B0), U64(0x233003B5A6CFE6AD), U64(0xD586BD01C5C217F6),
268 U64(0x5E5637885F29BC2B), U64(0x7EBA726D8C94094B), U64(0x0A56A5F0BFE39272), U64(0xD79476A84EE20D06),
269 U64(0x9E4C1269BAA4BF37), U64(0x17EFEE45B0DEE640), U64(0x1D95B0A5FCF90BC6), U64(0x93CBE0B699C2585D),
270 U64(0x65FA4F227A2B6D79), U64(0xD5F9E858292504D5), U64(0xC2B5A03F71471A6F), U64(0x59300222B4561E00),
271 U64(0xCE2F8642CA0712DC), U64(0x7CA9723FBB2E8988), U64(0x2785338347F2BA08), U64(0xC61BB3A141E50E8C),
272 U64(0x150F361DAB9DEC26), U64(0x9F6A419D382595F4), U64(0x64A53DC924FE7AC9), U64(0x142DE49FFF7A7C3D),
273 U64(0x0C335248857FA9E7), U64(0x0A9C32D5EAE45305), U64(0xE6C42178C4BBB92E), U64(0x71F1CE2490D20B07),
274 U64(0xF1BCC3D275AFE51A), U64(0xE728E8C83C334074), U64(0x96FBF83A12884624), U64(0x81A1549FD6573DA5),
275 U64(0x5FA7867CAF35E149), U64(0x56986E2EF3ED091B), U64(0x917F1DD5F8886C61), U64(0xD20D8C88C8FFE65F),
276 U64(0x31D71DCE64B2C310), U64(0xF165B587DF898190), U64(0xA57E6339DD2CF3A0), U64(0x1EF6E6DBB1961EC9),
277 U64(0x70CC73D90BC26E24), U64(0xE21A6B35DF0C3AD7), U64(0x003A93D8B2806962), U64(0x1C99DED33CB890A1),
278 U64(0xCF3145DE0ADD4289), U64(0xD0E4427A5514FB72), U64(0x77C621CC9FB3A483), U64(0x67A34DAC4356550B),
279 U64(0xF8D626AAAF278509),
282 uint64 *RandomPiece =Random64;
283 uint64 *RandomCastle =Random64+768;
284 uint64 *RandomEnPassant =Random64+772;
285 uint64 *RandomTurn =Random64+780;
291 int r, f, p_enc, squareNr, pieceGroup;
292 uint64 key=0, holdingsKey=0, Zobrist;
293 VariantClass v = gameInfo.variant;
297 case VariantFischeRandom: // compatible with normal
298 case VariantNoCastle:
299 case VariantXiangqi: // for historic reasons; does never collide anyway because of other King type
301 case VariantGiveaway: // in opening same as suicide
302 key += VariantSuicide;
304 case VariantGothic: // these are special cases of CRC, and can share book
305 case VariantCapablanca:
306 v = VariantCapaRandom;
308 key += v; // variant type incorporated in key to allow mixed books without collisions
311 for(f=0; f<BOARD_WIDTH; f++){
312 for(r=0; r<BOARD_HEIGHT;r++){
313 ChessSquare p = boards[moveNr][r][f];
314 if(f == BOARD_LEFT-1 || f == BOARD_RGHT) continue; // between board and holdings
315 if(p != EmptySquare){
316 int j = (int)p, promoted = 0;
317 j -= (j >= (int)BlackPawn) ? (int)BlackPawn :(int)WhitePawn;
318 if(j >= CHUPROMOTED WhitePawn) promoted++, j -= CHUPROMOTED WhitePawn;
319 if(j > (int)WhiteQueen) j++; // make space for King
320 if(j > (int) WhiteKing) j = (int)WhiteQueen + 1;
321 p_enc = 2*j + ((int)p < (int)BlackPawn);
322 // holdings squares get nmbers immediately after board; first left, then right holdings
323 if(f == BOARD_LEFT-2) squareNr = (BOARD_RGHT - BOARD_LEFT)*BOARD_HEIGHT + r; else
324 if(f == BOARD_RGHT+1) squareNr = (BOARD_RGHT - BOARD_LEFT + 1)*BOARD_HEIGHT + r; else
325 squareNr = (BOARD_RGHT - BOARD_LEFT)*r + (f - BOARD_LEFT);
326 // note that in normal Chess squareNr < 64 and p_enc < 12. The following code
327 // maps other pieces and squares in this range, and then modify the corresponding
328 // Zobrist random by rotating its bitpattern according to what the piece really was.
329 pieceGroup = p_enc / 12;
331 Zobrist = RandomPiece[64*p_enc + (squareNr & 63)];
332 if(pieceGroup & 4) Zobrist *= 987654321;
333 switch(pieceGroup & 3) {
334 case 1: // pieces 5-10 (FEACWM)
335 Zobrist = (Zobrist << 16) ^ (Zobrist >> 48);
337 case 2: // pieces 11-16 (OHIJGD)
338 Zobrist = (Zobrist << 32) ^ (Zobrist >> 32);
340 case 3: // pieces 17-20 (VLSU)
341 Zobrist = (Zobrist << 48) ^ (Zobrist >> 16);
344 if(promoted) Zobrist ^= 123456789*RandomPiece[squareNr & 63];
345 if(squareNr & 64) Zobrist = (Zobrist << 8) ^ (Zobrist >> 56);
346 if(squareNr & 128) Zobrist = (Zobrist << 4) ^ (Zobrist >> 60);
347 // holdings have separate (additive) key, to encode presence of multiple pieces on same square
348 if(f == BOARD_LEFT-2) holdingsKey += Zobrist * boards[moveNr][r][f+1]; else
349 if(f == BOARD_RGHT+1) holdingsKey += Zobrist * boards[moveNr][r][f-1]; else
355 if(boards[moveNr][CASTLING][2] != NoRights) {
356 if(boards[moveNr][CASTLING][0] != NoRights) key^=RandomCastle[0];
357 if(boards[moveNr][CASTLING][1] != NoRights) key^=RandomCastle[1];
359 if(boards[moveNr][CASTLING][5] != NoRights) {
360 if(boards[moveNr][CASTLING][3] != NoRights) key^=RandomCastle[2];
361 if(boards[moveNr][CASTLING][4] != NoRights) key^=RandomCastle[3];
364 f = boards[moveNr][EP_STATUS];
366 if(!WhiteOnMove(moveNr)){
367 // the test for neighboring Pawns might not be needed,
368 // as epStatus already kept track of it, but better safe than sorry.
369 if((f>0 && boards[moveNr][3][f-1]==BlackPawn)||
370 (f<7 && boards[moveNr][3][f+1]==BlackPawn)){
371 key^=RandomEnPassant[f];
374 if((f>0 && boards[moveNr][4][f-1]==WhitePawn)||
375 (f<7 && boards[moveNr][4][f+1]==WhitePawn)){
376 key^=RandomEnPassant[f];
381 if(WhiteOnMove(moveNr)){
384 return key + holdingsKey;
389 // fs routines read from memory buffer if no file specified
391 static unsigned char *memBuf, *memPtr;
396 fsseek (FILE *f, int n, int mode)
398 if(f) return fseek(f, n, mode);
399 if(mode == SEEK_SET) memPtr = memBuf + n; else
400 if(mode == SEEK_END) memPtr = memBuf + 16*bufSize + n;
401 return memPtr < memBuf || memPtr > memBuf + 16*bufSize;
407 if(f) return ftell(f);
408 return memPtr - memBuf;
414 if(f) return fgetc(f);
415 if(memPtr >= memBuf + 16*bufSize) return EOF;
420 int_from_file (FILE *f, int l, uint64 *r)
434 entry_from_file (FILE *f, entry_t *entry)
438 if(!f) { *entry = *(entry_t*) memPtr; memPtr += 16; return 0; }
439 ret=int_from_file(f,8,&r);
442 ret=int_from_file(f,2,&r);
445 ret=int_from_file(f,2,&r);
448 ret=int_from_file(f,2,&r);
451 ret=int_from_file(f,2,&r);
453 entry->learnPoints=r;
458 find_key (FILE *f, uint64 key, entry_t *entry)
460 int first, last, middle;
461 entry_t last_entry,middle_entry;
463 if(fsseek(f,-16,SEEK_END)){
465 entry->key=key+1; //hack
469 entry_from_file(f,&last_entry);
475 middle=(first+last)/2;
476 fsseek(f,16*middle,SEEK_SET);
477 entry_from_file(f,&middle_entry);
478 if(key<=middle_entry.key){
480 last_entry=middle_entry;
488 move_to_string (char move_s[6], uint16 move)
490 int f,fr,ff,t,tr,tf,p;
491 int width = BOARD_RGHT - BOARD_LEFT, size; // allow for alternative board formats
493 size = width * BOARD_HEIGHT;
494 p = move / (size*size);
495 move = move % (size*size);
502 move_s[0] = ff + 'a';
503 move_s[1] = fr + '1' - (BOARD_HEIGHT == 10);
504 move_s[2] = tf + 'a';
505 move_s[3] = tr + '1' - (BOARD_HEIGHT == 10);
507 if(IS_SHOGI(gameInfo.variant) && p) {
508 if(p == 2) p = 10; // Lion moves, for boards so big that 10 is out of range
509 else if(p != 7) p = 8; // use '+' for all others that do not explicitly defer
512 // kludge: encode drops as special promotion code
513 if(gameInfo.holdingsSize && p == 9) {
514 move_s[0] = f + '@'; // from square encodes piece type
515 move_s[1] = '@'; // drop symbol
517 } else if(p == 10) { // decode Lion move
522 // add promotion piece, if any
524 move_s[4] = promote_pieces[p];
530 if(gameInfo.variant != VariantNormal) return;
532 // correct FRC-style castlings in variant normal.
533 // [HGM] This is buggy code! e1h1 could very well be a normal R or Q move.
534 if(!strcmp(move_s,"e1h1")){
535 safeStrCpy(move_s,"e1g1", 6);
536 }else if(!strcmp(move_s,"e1a1")){
537 safeStrCpy(move_s,"e1c1", 6);
538 }else if(!strcmp(move_s,"e8h8")){
539 safeStrCpy(move_s,"e8g8", 6);
540 }else if(!strcmp(move_s,"e8a8")){
541 safeStrCpy(move_s,"e8c8", 6);
546 GetBookMoves (FILE *f, int moveNr, entry_t entries[], int max)
547 { // retrieve all entries for given position from book in 'entries', return number.
555 if(appData.debugMode) fprintf(debugFP, "book key = %08x%08x\n", (unsigned int)(key>>32), (unsigned int)key);
557 offset=find_key(f, key, &entry);
558 if(entry.key != key) {
563 fsseek(f, 16*(offset+1), SEEK_SET);
565 ret=entry_from_file(f, &entry);
569 if(entry.key != key){
572 if(count == max) break;
573 entries[count++] = entry;
581 ReadFromBookFile (int moveNr, char *book, entry_t entries[])
582 { // retrieve all entries for given position from book in 'entries', return number.
583 static FILE *f = NULL;
584 static char curBook[MSG_SIZ];
586 if(book == NULL) return -1;
587 if(dirty) { if(f) fclose(f); dirty = 0; f = NULL; }
588 if(!f || strcmp(book, curBook)){ // keep book file open until book changed
589 strncpy(curBook, book, MSG_SIZ);
591 f = fopen(book,"rb");
594 DisplayError(_("Polyglot book not valid"), 0);
595 appData.usePolyglotBook = FALSE;
599 return GetBookMoves(f, moveNr, entries, MOVE_BUF);
602 // next three made into subroutines to facilitate future changes in storage scheme (e.g. 2 x 3 bytes)
607 return e->learnPoints;
613 return e->learnCount;
617 CountMove (entry_t *e, int result)
620 case 0: e->learnCount ++; break;
621 case 1: e->learnCount ++; // count draw as win + loss
622 case 2: e->learnPoints ++; break;
626 #define MERGESIZE 2048
627 #define HASHSIZE 1024*1024*4
629 entry_t *memBook, *hashTab, *mergeBuf;
630 int bookSize=1, mergeSize=1, mask = HASHSIZE-1;
635 static int initDone = FALSE;
637 memBook = (entry_t *) calloc(1024*1024, sizeof(entry_t));
638 hashTab = (entry_t *) calloc(HASHSIZE, sizeof(entry_t));
639 mergeBuf = (entry_t *) calloc(MERGESIZE+5, sizeof(entry_t));
640 memBook[0].key = -1LL;
641 mergeBuf[0].key = -1LL;
648 int count, count2, games, i, choice=0;
649 entry_t entries[MOVE_BUF];
650 float nominal[MOVE_BUF], tot, deficit, max, min;
651 static char move_s[6];
654 memBuf = (unsigned char*) memBook; bufSize = bookSize; // in MC mode book resides in memory
655 count = GetBookMoves(NULL, moveNr, entries, MOVE_BUF);
656 if(count < 0) count = 0; // don't care about miss yet
657 memBuf = (unsigned char*) mergeBuf; bufSize = mergeSize; // there could be moves still waiting to be merged
658 count2 = count + GetBookMoves(NULL, moveNr, entries+count, MOVE_BUF - count);
659 if(appData.debugMode) fprintf(debugFP, "MC probe: %d/%d (%d+%d)\n", count, count2,bookSize,mergeSize);
660 if(!count2) return NULL;
662 for(i=0; i<count2; i++) {
663 float w = wins(entries+i) + 10., l = losses(entries+i) + 10.;
664 float h = (w*w*w*w + 22500.*w*w) / (l*l*l*l + 22500.*l*l);
665 tot += nominal[i] = h;
666 games += wins(entries+i) + losses(entries+i);
668 tot = games / tot; max = min = 0;
669 for(i=0; i<count2; i++) {
670 nominal[i] *= tot; // normalize so they sum to games
671 deficit = nominal[i] - (wins(entries+i) + losses(entries+i));
672 if(deficit > max) max = deficit, choice = i;
673 if(deficit < min) min = deficit;
674 } // note that a single move will never be underplayed
675 if(max - min > 0.5*sqrt(nominal[choice])) { // if one of the listed moves is significantly under-played, play it now.
676 move_to_string(move_s, entries[choice].move);
677 if(appData.debugMode) fprintf(debugFP, "book move field = %d\n", entries[choice].move);
680 return NULL; // otherwise fake book miss to force engine think, hoping for hitherto unplayed move.
684 *ProbeBook (int moveNr, char *book)
686 entry_t entries[MOVE_BUF];
689 static char move_s[6];
692 if(moveNr >= 2*appData.bookDepth) return NULL;
693 if(mcMode) return MCprobe(moveNr);
695 if((count = ReadFromBookFile(moveNr, book, entries)) <= 0) return NULL; // no book, or no hit
697 if(appData.bookStrength != 50) { // transform weights
698 double power = 0, maxWeight = 0.0;
699 if(appData.bookStrength) power = (100.-appData.bookStrength)/appData.bookStrength;
700 for(i=0; i<count; i++) if(entries[i].weight > maxWeight) maxWeight = entries[i].weight;
701 for(i=0; i<count; i++){
702 double weight = entries[i].weight / maxWeight;
704 entries[i].weight = appData.bookStrength || weight == 1.0 ? 1e4*exp(power * log(weight)) + 0.5 : 0.0;
708 for(i=0; i<count; i++){
709 total_weight += entries[i].weight;
711 if(total_weight == 0) return NULL; // force book miss rather than playing moves with weight 0.
712 j = (random() & 0xFFF) * total_weight >> 12; // create random < total_weight
714 for(i=0; i<count; i++){
715 total_weight += entries[i].weight;
716 if(total_weight > j) break;
718 if(i >= count) DisplayFatalError(_("Book Fault"), 0, 1); // safety catch, cannot happen
719 move_to_string(move_s, entries[i].move);
720 if(appData.debugMode) fprintf(debugFP, "book move field = %d\n", entries[i].move);
725 extern char yy_textstr[];
726 entry_t lastEntries[MOVE_BUF];
729 MovesToText(int count, entry_t *entries)
731 int i, totalWeight = 0;
733 char *p = (char*) malloc(40*count+1);
734 for(i=0; i<count; i++) totalWeight += entries[i].weight;
736 for(i=0; i<count; i++) {
738 move_to_string(algMove, entries[i].move);
740 if(entries[i].learnCount || entries[i].learnPoints)
741 snprintf(buf, MSG_SIZ, " {%d/%d}", entries[i].learnPoints, entries[i].learnCount);
742 snprintf(p+strlen(p), 40, "%5.1f%% %5d %s%s\n", 100*entries[i].weight/(totalWeight+0.001),
743 entries[i].weight, algMove, buf);
744 //lastEntries[i] = entries[i];
750 CoordsToMove (int fromX, int fromY, int toX, int toY, char promoChar)
752 int i, width = BOARD_RGHT - BOARD_LEFT;
753 int to = toX - BOARD_LEFT + toY * width;
754 int from = fromX - BOARD_LEFT + fromY * width;
755 for(i=0; promote_pieces[i]; i++) if(promote_pieces[i] == promoChar) break;
756 if(!promote_pieces[i]) i = 0;
757 else if(i == 9 && gameInfo.variant == VariantChu) i = 1; // on 12x12 only 3 promotion codes available, so use 1 to indicate promotion
758 if(fromY == DROP_RANK) i = 9, from = ToUpper(PieceToChar(fromX)) - '@';
759 return to + (i * width * BOARD_HEIGHT + from) * width * BOARD_HEIGHT;
763 TextToMoves (char *text, int moveNum, entry_t *entries)
766 uint64 hashKey = hash(moveNum);
767 int fromX, fromY, toX, toY;
769 char promoChar, valid;
772 entries[0].key = hashKey; // make sure key is returned even if no moves
773 while((i=sscanf(text, "%f%%%d", &dummy, &w))==2 || (i=sscanf(text, "%d", &w))==1) {
774 if(i == 2) text = strchr(text, '%') + 1; // skip percentage
775 if(w == 1) text = strstr(text, "1 ") + 2; // skip weight that could be recognized as move number one
776 valid = ParseOneMove(text, moveNum, &moveType, &fromX, &fromY, &toX, &toY, &promoChar);
777 text = strstr(text, yy_textstr) + strlen(yy_textstr); // skip what we parsed
778 if(!valid || moveType != NormalMove && moveType != WhiteDrop && moveType != BlackDrop
779 && moveType != WhitePromotion && moveType != BlackPromotion
780 && moveType != WhiteCapturesEnPassant && moveType != BlackCapturesEnPassant
781 && moveType != WhiteKingSideCastle && moveType != BlackKingSideCastle
782 && moveType != WhiteQueenSideCastle && moveType != BlackQueenSideCastle
783 && moveType != WhiteNonPromotion && moveType != BlackNonPromotion) continue;
784 if(*text == ' ' && sscanf(text+1, "{%hd/%hd}", &entries[count].learnPoints, &entries[count].learnCount) == 2) {
785 text = strchr(text+1, '}') + 1;
787 entries[count].learnPoints = 0;
788 entries[count].learnCount = 0;
790 entries[count].move = CoordsToMove(fromX, fromY, toX, toY, promoChar);
791 entries[count].key = hashKey;
792 entries[count].weight = w;
802 DisplayBook (int moveNr)
804 entry_t entries[MOVE_BUF];
807 if(!bookUp) return FALSE;
808 count = currentCount = ReadFromBookFile(moveNr, appData.polyglotBook, entries);
809 if(count < 0) return FALSE;
810 p = MovesToText(count, entries);
811 EditTagsPopUp(p, NULL);
813 addToBookFlag = FALSE;
821 bookUp = DisplayBook(currentMove);
825 int_to_file (FILE *f, int l, uint64 r)
828 for(i=l-1;i>=0;i--) fputc(r>>8*i & 255, f);
832 entry_to_file (FILE *f, entry_t *entry)
834 int_to_file(f,8,entry->key);
835 int_to_file(f,2,entry->move);
836 int_to_file(f,2,entry->weight);
837 int_to_file(f,2,entry->learnCount);
838 int_to_file(f,2,entry->learnPoints);
841 char buf1[4096], buf2[4096];
844 SaveToBook (char *text)
846 entry_t entries[MOVE_BUF], entry;
847 int count = TextToMoves(text, currentMove, entries);
848 int offset, i, len1=0, len2, readpos=0, writepos=0;
850 if(!count && !currentCount) return;
851 f=fopen(appData.polyglotBook, "rb+");
852 if(!f){ DisplayError(_("Polyglot book not valid"), 0); return; }
853 offset=find_key(f, entries[0].key, &entry);
854 if(entries[0].key != entry.key && currentCount) {
855 DisplayError(_("Hash keys are different"), 0);
859 if(count != currentCount) {
860 readpos = 16*(offset + currentCount);
861 writepos = 16*(offset + count);
862 fsseek(f, readpos, SEEK_SET);
863 readpos += len1 = fread(buf1, 1, 4096 - 16*currentCount, f); // salvage some entries immediately behind change
865 fsseek(f, 16*(offset), SEEK_SET);
866 for(i=0; i<count; i++) entry_to_file(f, entries + i); // save the change
867 if(count != currentCount) {
869 for(i=0; i<len1; i++) buf2[i] = buf1[i]; len2 = len1;
870 if(readpos > writepos) {
871 fsseek(f, readpos, SEEK_SET);
872 readpos += len1 = fread(buf1, 1, 4096, f);
873 } else len1 = 0; // wrote already past old EOF
874 fsseek(f, writepos, SEEK_SET);
875 fwrite(buf2, 1, len2, f);
884 NewEntry (entry_t *e, uint64 key, int move, int result)
890 CountMove(e, result);
898 if(appData.debugMode) fprintf(debugFP, "book merge %d moves (old size %d)\n", mergeSize, bookSize);
900 bookSize += --mergeSize;
901 for(i=bookSize-1; mergeSize; i--) {
902 while(mergeSize && (i < mergeSize || mergeBuf[mergeSize-1].key >= memBook[i-mergeSize].key))
903 memBook[i--] = mergeBuf[--mergeSize];
905 memBook[i] = memBook[i-mergeSize];
907 if(mergeSize) DisplayFatalError("merge error", 0, 0); // impossible
909 mergeBuf[0].key = -1LL;
913 AddToBook (int moveNr, int result)
916 int offset, start, move;
918 int i, j, fromY, toY;
919 char fromX, toX, promo;
920 extern char moveList[][MOVE_LEN];
922 if(!moveList[moveNr][0] || moveList[moveNr][0] == '\n') return; // could be terminal position
924 if(appData.debugMode) fprintf(debugFP, "add move %d to book %s", moveNr, moveList[moveNr]);
926 // calculate key and book representation of move
928 if(moveList[moveNr][1] == '@') {
929 sscanf(moveList[moveNr], "%c@%c%d", &promo, &toX, &toY);
930 fromX = CharToPiece(WhiteOnMove(moveNr) ? ToUpper(promo) : ToLower(promo));
931 fromY = DROP_RANK; promo = NULLCHAR;
932 } else sscanf(moveList[moveNr], "%c%d%c%d%c", &fromX, &fromY, &toX, &toY, &promo), fromX -= AAA, fromY -= ONE - '0';
933 move = CoordsToMove(fromX, fromY, toX-AAA, toY-ONE+'0', promo);
935 // if move already in book, just add count
936 memBuf = (unsigned char*) memBook; bufSize = bookSize; // in MC mode book resides in memory
937 offset = find_key(NULL, key, &entry);
938 while(memBook[offset].key == key) {
939 if(memBook[offset].move == move) {
940 CountMove(memBook+offset, result); return;
943 // move did not occur in the main book
944 memBuf = (unsigned char*) mergeBuf; bufSize = mergeSize; // it could be amongst moves still waiting to be merged
945 start = offset = find_key(NULL, key, &entry);
946 while(mergeBuf[offset].key == key) {
947 if(mergeBuf[offset].move == move) {
948 if(appData.debugMode) fprintf(debugFP, "found in book merge buf @ %d\n", offset);
949 CountMove(mergeBuf+offset, result); return;
952 if(start != offset) { // position was in mergeBuf, but move is new
953 if(appData.debugMode) fprintf(debugFP, "add in book merge buf @ %d\n", offset);
954 for(i=mergeSize++; i>offset; i--) mergeBuf[i] = mergeBuf[i-1]; // make room
955 NewEntry(mergeBuf+offset, key, move, result);
958 // position was not in mergeBuf; look in hash table
959 i = (key & mask); offset = -1;
960 while(hashTab[i].key) { // search in hash table (necessary because sought item could be re-hashed)
961 if(hashTab[i].key == 1 && offset < 0) offset = i; // remember first invalidated entry we pass
962 if(!((hashTab[i].key - key) & ~1)) { // hit
963 if(hashTab[i].move == move) {
964 CountMove(hashTab+i, result);
965 for(j=mergeSize++; j>start; j--) mergeBuf[j] = mergeBuf[j-1];
967 // position already in hash now occurs with different move; move both moves to mergeBuf
968 for(j=mergeSize+1; j>start+1; j--) mergeBuf[j] = mergeBuf[j-2];
969 NewEntry(mergeBuf+start+1, key, move, result); mergeSize += 2;
971 hashTab[i].key = 1; // kludge to invalidate hash entry
972 mergeBuf[start] = hashTab[i]; mergeBuf[start].key = key;
973 if(mergeSize >= MERGESIZE) Merge();
976 i = i+1 & mask; // wrap!
978 // position did not yet occur in hash table. Put it there
979 if(offset < 0) offset = i;
980 NewEntry(hashTab+offset, key, move, result);
981 if(appData.debugMode)
982 fprintf(debugFP, "book hash @ %d (%d-%d)\n", offset, hashTab[offset].learnPoints, hashTab[offset].learnCount);
986 AddGameToBook (int always)
990 if(!mcMode && !always) return;
993 switch(gameInfo.result) {
994 case GameIsDrawn: result = 1; break;
995 case WhiteWins: result = 2; break;
996 case BlackWins: result = 0; break;
997 default: return; // don't treat games with unknown result
1000 if(appData.debugMode) fprintf(debugFP, "add game to book (%d-%d)\n", backwardMostMove, forwardMostMove);
1001 for(i=backwardMostMove; i<forwardMostMove && i < 2*appData.bookDepth; i++)
1002 AddToBook(i, WhiteOnMove(i) ? result : 2-result); // flip result when black moves
1006 PlayBookMove(char *text, int index)
1008 char *start = text+index, *end = start;
1009 while(start > text && start[-1] != ' ' && start[-1] != '\t') start--;
1010 while(*end && *++end != ' ' && *end != '\n'); *end = NULLCHAR; // find clicked word
1011 if(start != end) TypeInDoneEvent(start); // fake it was typed in move type-in
1021 Merge(); // flush merge buffer to memBook
1023 if(f = fopen(appData.polyglotBook, "wb")) {
1024 for(i=0; i<bookSize; i++) {
1025 entry_t entry = memBook[i];
1026 entry.weight = entry.learnPoints;
1027 // entry.learnPoints = 0;
1028 // entry.learnCount = 0;
1029 entry_to_file(f, &entry);
1031 } else DisplayError(_("Could not create book"), 0);