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){
317 j -= (j >= (int)BlackPawn) ? (int)BlackPawn :(int)WhitePawn;
318 if(j > (int)WhiteQueen) j++; // make space for King
319 if(j > (int) WhiteKing) j = (int)WhiteQueen + 1;
320 p_enc = 2*j + ((int)p < (int)BlackPawn);
321 // holdings squares get nmbers immediately after board; first left, then right holdings
322 if(f == BOARD_LEFT-2) squareNr = (BOARD_RGHT - BOARD_LEFT)*BOARD_HEIGHT + r; else
323 if(f == BOARD_RGHT+1) squareNr = (BOARD_RGHT - BOARD_LEFT + 1)*BOARD_HEIGHT + r; else
324 squareNr = (BOARD_RGHT - BOARD_LEFT)*r + (f - BOARD_LEFT);
325 // note that in normal Chess squareNr < 64 and p_enc < 12. The following code
326 // maps other pieces and squares in this range, and then modify the corresponding
327 // Zobrist random by rotating its bitpattern according to what the piece really was.
328 pieceGroup = p_enc / 12;
330 Zobrist = RandomPiece[64*p_enc + (squareNr & 63)];
332 case 1: // pieces 5-10 (FEACWM)
333 Zobrist = (Zobrist << 16) ^ (Zobrist >> 48);
335 case 2: // pieces 11-16 (OHIJGD)
336 Zobrist = (Zobrist << 32) ^ (Zobrist >> 32);
338 case 3: // pieces 17-20 (VLSU)
339 Zobrist = (Zobrist << 48) ^ (Zobrist >> 16);
342 if(squareNr >= 64) Zobrist = (Zobrist << 8) ^ (Zobrist >> 56);
343 // holdings have separate (additive) key, to encode presence of multiple pieces on same square
344 if(f == BOARD_LEFT-2) holdingsKey += Zobrist * boards[moveNr][r][f+1]; else
345 if(f == BOARD_RGHT+1) holdingsKey += Zobrist * boards[moveNr][r][f-1]; else
351 if(boards[moveNr][CASTLING][2] != NoRights) {
352 if(boards[moveNr][CASTLING][0] != NoRights) key^=RandomCastle[0];
353 if(boards[moveNr][CASTLING][1] != NoRights) key^=RandomCastle[1];
355 if(boards[moveNr][CASTLING][5] != NoRights) {
356 if(boards[moveNr][CASTLING][3] != NoRights) key^=RandomCastle[2];
357 if(boards[moveNr][CASTLING][4] != NoRights) key^=RandomCastle[3];
360 f = boards[moveNr][EP_STATUS];
362 if(!WhiteOnMove(moveNr)){
363 // the test for neighboring Pawns might not be needed,
364 // as epStatus already kept track of it, but better safe than sorry.
365 if((f>0 && boards[moveNr][3][f-1]==BlackPawn)||
366 (f<7 && boards[moveNr][3][f+1]==BlackPawn)){
367 key^=RandomEnPassant[f];
370 if((f>0 && boards[moveNr][4][f-1]==WhitePawn)||
371 (f<7 && boards[moveNr][4][f+1]==WhitePawn)){
372 key^=RandomEnPassant[f];
377 if(WhiteOnMove(moveNr)){
380 return key + holdingsKey;
385 // fs routines read from memory buffer if no file specified
387 static unsigned char *memBuf, *memPtr;
392 fsseek (FILE *f, int n, int mode)
394 if(f) return fseek(f, n, mode);
395 if(mode == SEEK_SET) memPtr = memBuf + n; else
396 if(mode == SEEK_END) memPtr = memBuf + 16*bufSize + n;
397 return memPtr < memBuf || memPtr > memBuf + 16*bufSize;
403 if(f) return ftell(f);
404 return memPtr - memBuf;
410 if(f) return fgetc(f);
411 if(memPtr >= memBuf + 16*bufSize) return EOF;
416 int_from_file (FILE *f, int l, uint64 *r)
430 entry_from_file (FILE *f, entry_t *entry)
434 if(!f) { *entry = *(entry_t*) memPtr; memPtr += 16; return 0; }
435 ret=int_from_file(f,8,&r);
438 ret=int_from_file(f,2,&r);
441 ret=int_from_file(f,2,&r);
444 ret=int_from_file(f,2,&r);
447 ret=int_from_file(f,2,&r);
449 entry->learnPoints=r;
454 find_key (FILE *f, uint64 key, entry_t *entry)
456 int first, last, middle;
457 entry_t last_entry,middle_entry;
459 if(fsseek(f,-16,SEEK_END)){
461 entry->key=key+1; //hack
465 entry_from_file(f,&last_entry);
471 middle=(first+last)/2;
472 fsseek(f,16*middle,SEEK_SET);
473 entry_from_file(f,&middle_entry);
474 if(key<=middle_entry.key){
476 last_entry=middle_entry;
484 move_to_string (char move_s[6], uint16 move)
486 int f,fr,ff,t,tr,tf,p;
487 int width = BOARD_RGHT - BOARD_LEFT, size; // allow for alternative board formats
489 size = width * BOARD_HEIGHT;
490 p = move / (size*size);
491 move = move % (size*size);
498 move_s[0] = ff + 'a';
499 move_s[1] = fr + '1' - (BOARD_HEIGHT > 9);
500 move_s[2] = tf + 'a';
501 move_s[3] = tr + '1' - (BOARD_HEIGHT > 9);
503 // kludge: encode drops as special promotion code
504 if(gameInfo.holdingsSize && p == 9) {
505 move_s[0] = f + '@'; // from square encodes piece type
506 move_s[1] = '@'; // drop symbol
510 // add promotion piece, if any
512 move_s[4] = promote_pieces[p];
518 if(gameInfo.variant != VariantNormal) return;
520 // correct FRC-style castlings in variant normal.
521 // [HGM] This is buggy code! e1h1 could very well be a normal R or Q move.
522 if(!strcmp(move_s,"e1h1")){
523 safeStrCpy(move_s,"e1g1", 6);
524 }else if(!strcmp(move_s,"e1a1")){
525 safeStrCpy(move_s,"e1c1", 6);
526 }else if(!strcmp(move_s,"e8h8")){
527 safeStrCpy(move_s,"e8g8", 6);
528 }else if(!strcmp(move_s,"e8a8")){
529 safeStrCpy(move_s,"e8c8", 6);
534 GetBookMoves (FILE *f, int moveNr, entry_t entries[], int max)
535 { // retrieve all entries for given position from book in 'entries', return number.
543 if(appData.debugMode) fprintf(debugFP, "book key = %08x%08x\n", (unsigned int)(key>>32), (unsigned int)key);
545 offset=find_key(f, key, &entry);
546 if(entry.key != key) {
551 fsseek(f, 16*(offset+1), SEEK_SET);
553 ret=entry_from_file(f, &entry);
557 if(entry.key != key){
560 if(count == max) break;
561 entries[count++] = entry;
567 ReadFromBookFile (int moveNr, char *book, entry_t entries[])
568 { // retrieve all entries for given position from book in 'entries', return number.
569 static FILE *f = NULL;
570 static char curBook[MSG_SIZ];
572 if(book == NULL) return -1;
573 if(!f || strcmp(book, curBook)){ // keep book file open until book changed
574 strncpy(curBook, book, MSG_SIZ);
576 f = fopen(book,"rb");
579 DisplayError(_("Polyglot book not valid"), 0);
580 appData.usePolyglotBook = FALSE;
584 return GetBookMoves(f, moveNr, entries, MOVE_BUF);
587 // next three made into subroutines to facilitate future changes in storage scheme (e.g. 2 x 3 bytes)
592 return e->learnPoints;
598 return e->learnCount;
602 CountMove (entry_t *e, int result)
605 case 0: e->learnCount ++; break;
606 case 1: e->learnCount ++; // count draw as win + loss
607 case 2: e->learnPoints ++; break;
611 #define MERGESIZE 2048
612 #define HASHSIZE 1024*1024*4
614 entry_t *memBook, *hashTab, *mergeBuf;
615 int bookSize=1, mergeSize=1, mask = HASHSIZE-1;
620 static int initDone = FALSE;
622 memBook = (entry_t *) calloc(1024*1024, sizeof(entry_t));
623 hashTab = (entry_t *) calloc(HASHSIZE, sizeof(entry_t));
624 mergeBuf = (entry_t *) calloc(MERGESIZE+5, sizeof(entry_t));
625 memBook[0].key = -1LL;
626 mergeBuf[0].key = -1LL;
633 int count, count2, games, i, choice=0;
634 entry_t entries[MOVE_BUF];
635 float nominal[MOVE_BUF], tot, deficit, max, min;
636 static char move_s[6];
639 memBuf = (unsigned char*) memBook; bufSize = bookSize; // in MC mode book resides in memory
640 count = GetBookMoves(NULL, moveNr, entries, MOVE_BUF);
641 if(count < 0) count = 0; // don't care about miss yet
642 memBuf = (unsigned char*) mergeBuf; bufSize = mergeSize; // there could be moves still waiting to be merged
643 count2 = count + GetBookMoves(NULL, moveNr, entries+count, MOVE_BUF - count);
644 if(appData.debugMode) fprintf(debugFP, "MC probe: %d/%d (%d+%d)\n", count, count2,bookSize,mergeSize);
645 if(!count2) return NULL;
647 for(i=0; i<count2; i++) {
648 float w = wins(entries+i) + 10., l = losses(entries+i) + 10.;
649 float h = (w*w*w*w + 22500.*w*w) / (l*l*l*l + 22500.*l*l);
650 tot += nominal[i] = h;
651 games += wins(entries+i) + losses(entries+i);
653 tot = games / tot; max = min = 0;
654 for(i=0; i<count2; i++) {
655 nominal[i] *= tot; // normalize so they sum to games
656 deficit = nominal[i] - (wins(entries+i) + losses(entries+i));
657 if(deficit > max) max = deficit, choice = i;
658 if(deficit < min) min = deficit;
659 } // note that a single move will never be underplayed
660 if(max - min > 0.5*sqrt(nominal[choice])) { // if one of the listed moves is significantly under-played, play it now.
661 move_to_string(move_s, entries[choice].move);
662 if(appData.debugMode) fprintf(debugFP, "book move field = %d\n", entries[choice].move);
665 return NULL; // otherwise fake book miss to force engine think, hoping for hitherto unplayed move.
669 *ProbeBook (int moveNr, char *book)
671 entry_t entries[MOVE_BUF];
674 static char move_s[6];
677 if(moveNr >= 2*appData.bookDepth) return NULL;
678 if(mcMode) return MCprobe(moveNr);
680 if((count = ReadFromBookFile(moveNr, book, entries)) <= 0) return NULL; // no book, or no hit
682 if(appData.bookStrength != 50) { // transform weights
683 double power = 0, maxWeight = 0.0;
684 if(appData.bookStrength) power = (100.-appData.bookStrength)/appData.bookStrength;
685 for(i=0; i<count; i++) if(entries[i].weight > maxWeight) maxWeight = entries[i].weight;
686 for(i=0; i<count; i++){
687 double weight = entries[i].weight / maxWeight;
689 entries[i].weight = appData.bookStrength || weight == 1.0 ? 1e4*exp(power * log(weight)) + 0.5 : 0.0;
693 for(i=0; i<count; i++){
694 total_weight += entries[i].weight;
696 if(total_weight == 0) return NULL; // force book miss rather than playing moves with weight 0.
697 j = (random() & 0xFFF) * total_weight >> 12; // create random < total_weight
699 for(i=0; i<count; i++){
700 total_weight += entries[i].weight;
701 if(total_weight > j) break;
703 if(i >= count) DisplayFatalError(_("Book Fault"), 0, 1); // safety catch, cannot happen
704 move_to_string(move_s, entries[i].move);
705 if(appData.debugMode) fprintf(debugFP, "book move field = %d\n", entries[i].move);
710 extern char yy_textstr[];
711 entry_t lastEntries[MOVE_BUF];
714 MovesToText(int count, entry_t *entries)
716 int i, totalWeight = 0;
718 char *p = (char*) malloc(40*count+1);
719 for(i=0; i<count; i++) totalWeight += entries[i].weight;
721 for(i=0; i<count; i++) {
723 move_to_string(algMove, entries[i].move);
725 if(entries[i].learnCount || entries[i].learnPoints)
726 snprintf(buf, MSG_SIZ, " {%d/%d}", entries[i].learnPoints, entries[i].learnCount);
727 snprintf(p+strlen(p), 40, "%5.1f%% %5d %s%s\n", 100*entries[i].weight/(totalWeight+0.001),
728 entries[i].weight, algMove, buf);
729 //lastEntries[i] = entries[i];
735 CoordsToMove (int fromX, int fromY, int toX, int toY, char promoChar)
737 int i, width = BOARD_RGHT - BOARD_LEFT;
738 int to = toX - BOARD_LEFT + toY * width;
739 int from = fromX - BOARD_LEFT + fromY * width;
740 for(i=0; promote_pieces[i]; i++) if(promote_pieces[i] == promoChar) break;
741 if(!promote_pieces[i]) i = 0;
742 if(fromY == DROP_RANK) i = 9, from = ToUpper(PieceToChar(fromX)) - '@';
743 return to + (i * width * BOARD_HEIGHT + from) * width * BOARD_HEIGHT;
747 TextToMoves (char *text, int moveNum, entry_t *entries)
750 uint64 hashKey = hash(moveNum);
751 int fromX, fromY, toX, toY;
753 char promoChar, valid;
756 entries[0].key = hashKey; // make sure key is returned even if no moves
757 while((i=sscanf(text, "%f%%%d", &dummy, &w))==2 || (i=sscanf(text, "%d", &w))==1) {
758 if(i == 2) text = strchr(text, '%') + 1; // skip percentage
759 if(w == 1) text = strstr(text, "1 ") + 2; // skip weight that could be recognized as move number one
760 valid = ParseOneMove(text, moveNum, &moveType, &fromX, &fromY, &toX, &toY, &promoChar);
761 text = strstr(text, yy_textstr) + strlen(yy_textstr); // skip what we parsed
762 if(!valid || moveType != NormalMove && moveType != WhiteDrop && moveType != BlackDrop
763 && moveType != WhitePromotion && moveType != BlackPromotion
764 && moveType != WhiteCapturesEnPassant && moveType != BlackCapturesEnPassant
765 && moveType != WhiteKingSideCastle && moveType != BlackKingSideCastle
766 && moveType != WhiteQueenSideCastle && moveType != BlackQueenSideCastle
767 && moveType != WhiteNonPromotion && moveType != BlackNonPromotion) continue;
768 if(*text == ' ' && sscanf(text+1, "{%hd/%hd}", &entries[count].learnPoints, &entries[count].learnCount) == 2) {
769 text = strchr(text+1, '}') + 1;
771 entries[count].learnPoints = 0;
772 entries[count].learnCount = 0;
774 entries[count].move = CoordsToMove(fromX, fromY, toX, toY, promoChar);
775 entries[count].key = hashKey;
776 entries[count].weight = w;
786 DisplayBook (int moveNr)
788 entry_t entries[MOVE_BUF];
791 if(!bookUp) return FALSE;
792 count = currentCount = ReadFromBookFile(moveNr, appData.polyglotBook, entries);
793 if(count < 0) return FALSE;
794 p = MovesToText(count, entries);
795 EditTagsPopUp(p, NULL);
797 addToBookFlag = FALSE;
805 bookUp = DisplayBook(currentMove);
809 int_to_file (FILE *f, int l, uint64 r)
812 for(i=l-1;i>=0;i--) fputc(r>>8*i & 255, f);
816 entry_to_file (FILE *f, entry_t *entry)
818 int_to_file(f,8,entry->key);
819 int_to_file(f,2,entry->move);
820 int_to_file(f,2,entry->weight);
821 int_to_file(f,2,entry->learnCount);
822 int_to_file(f,2,entry->learnPoints);
825 char buf1[4096], buf2[4096];
828 SaveToBook (char *text)
830 entry_t entries[MOVE_BUF], entry;
831 int count = TextToMoves(text, currentMove, entries);
832 int offset, i, len1=0, len2, readpos=0, writepos=0;
834 if(!count && !currentCount) return;
835 f=fopen(appData.polyglotBook, "rb+");
836 if(!f){ DisplayError(_("Polyglot book not valid"), 0); return; }
837 offset=find_key(f, entries[0].key, &entry);
838 if(entries[0].key != entry.key && currentCount) {
839 DisplayError(_("Hash keys are different"), 0);
843 if(count != currentCount) {
844 readpos = 16*(offset + currentCount);
845 writepos = 16*(offset + count);
846 fsseek(f, readpos, SEEK_SET);
847 readpos += len1 = fread(buf1, 1, 4096 - 16*currentCount, f); // salvage some entries immediately behind change
849 fsseek(f, 16*(offset), SEEK_SET);
850 for(i=0; i<count; i++) entry_to_file(f, entries + i); // save the change
851 if(count != currentCount) {
853 for(i=0; i<len1; i++) buf2[i] = buf1[i]; len2 = len1;
854 if(readpos > writepos) {
855 fsseek(f, readpos, SEEK_SET);
856 readpos += len1 = fread(buf1, 1, 4096, f);
857 } else len1 = 0; // wrote already past old EOF
858 fsseek(f, writepos, SEEK_SET);
859 fwrite(buf2, 1, len2, f);
867 NewEntry (entry_t *e, uint64 key, int move, int result)
873 CountMove(e, result);
881 if(appData.debugMode) fprintf(debugFP, "book merge %d moves (old size %d)\n", mergeSize, bookSize);
883 bookSize += --mergeSize;
884 for(i=bookSize-1; mergeSize; i--) {
885 while(mergeSize && (i < mergeSize || mergeBuf[mergeSize-1].key >= memBook[i-mergeSize].key))
886 memBook[i--] = mergeBuf[--mergeSize];
888 memBook[i] = memBook[i-mergeSize];
890 if(mergeSize) DisplayFatalError("merge error", 0, 0); // impossible
892 mergeBuf[0].key = -1LL;
896 AddToBook (int moveNr, int result)
899 int offset, start, move;
901 int i, j, fromY, toY;
902 char fromX, toX, promo;
903 extern char moveList[][MOVE_LEN];
905 if(!moveList[moveNr][0] || moveList[moveNr][0] == '\n') return; // could be terminal position
907 if(appData.debugMode) fprintf(debugFP, "add move %d to book %s", moveNr, moveList[moveNr]);
909 // calculate key and book representation of move
911 if(moveList[moveNr][1] == '@') {
912 sscanf(moveList[moveNr], "%c@%c%d", &promo, &toX, &toY);
913 fromX = CharToPiece(WhiteOnMove(moveNr) ? ToUpper(promo) : ToLower(promo));
914 fromY = DROP_RANK; promo = NULLCHAR;
915 } else sscanf(moveList[moveNr], "%c%d%c%d%c", &fromX, &fromY, &toX, &toY, &promo), fromX -= AAA, fromY -= ONE - '0';
916 move = CoordsToMove(fromX, fromY, toX-AAA, toY-ONE+'0', promo);
918 // if move already in book, just add count
919 memBuf = (unsigned char*) memBook; bufSize = bookSize; // in MC mode book resides in memory
920 offset = find_key(NULL, key, &entry);
921 while(memBook[offset].key == key) {
922 if(memBook[offset].move == move) {
923 CountMove(memBook+offset, result); return;
926 // move did not occur in the main book
927 memBuf = (unsigned char*) mergeBuf; bufSize = mergeSize; // it could be amongst moves still waiting to be merged
928 start = offset = find_key(NULL, key, &entry);
929 while(mergeBuf[offset].key == key) {
930 if(mergeBuf[offset].move == move) {
931 if(appData.debugMode) fprintf(debugFP, "found in book merge buf @ %d\n", offset);
932 CountMove(mergeBuf+offset, result); return;
935 if(start != offset) { // position was in mergeBuf, but move is new
936 if(appData.debugMode) fprintf(debugFP, "add in book merge buf @ %d\n", offset);
937 for(i=mergeSize++; i>offset; i--) mergeBuf[i] = mergeBuf[i-1]; // make room
938 NewEntry(mergeBuf+offset, key, move, result);
941 // position was not in mergeBuf; look in hash table
942 i = (key & mask); offset = -1;
943 while(hashTab[i].key) { // search in hash table (necessary because sought item could be re-hashed)
944 if(hashTab[i].key == 1 && offset < 0) offset = i; // remember first invalidated entry we pass
945 if(!((hashTab[i].key - key) & ~1)) { // hit
946 if(hashTab[i].move == move) {
947 CountMove(hashTab+i, result);
948 for(j=mergeSize++; j>start; j--) mergeBuf[j] = mergeBuf[j-1];
950 // position already in hash now occurs with different move; move both moves to mergeBuf
951 for(j=mergeSize+1; j>start+1; j--) mergeBuf[j] = mergeBuf[j-2];
952 NewEntry(mergeBuf+start+1, key, move, result); mergeSize += 2;
954 hashTab[i].key = 1; // kludge to invalidate hash entry
955 mergeBuf[start] = hashTab[i]; mergeBuf[start].key = key;
956 if(mergeSize >= MERGESIZE) Merge();
959 i = i+1 & mask; // wrap!
961 // position did not yet occur in hash table. Put it there
962 if(offset < 0) offset = i;
963 NewEntry(hashTab+offset, key, move, result);
964 if(appData.debugMode)
965 fprintf(debugFP, "book hash @ %d (%d-%d)\n", offset, hashTab[offset].learnPoints, hashTab[offset].learnCount);
969 AddGameToBook (int always)
973 if(!mcMode && !always) return;
976 switch(gameInfo.result) {
977 case GameIsDrawn: result = 1; break;
978 case WhiteWins: result = 2; break;
979 case BlackWins: result = 0; break;
980 default: return; // don't treat games with unknown result
983 if(appData.debugMode) fprintf(debugFP, "add game to book (%d-%d)\n", backwardMostMove, forwardMostMove);
985 for(i=backwardMostMove; i<forwardMostMove && i < 2*appData.bookDepth; i++)
986 AddToBook(i, WhiteOnMove(i) ? result : 2-result); // flip result when black moves
990 PlayBookMove(char *text, int index)
992 char *start = text+index, *end = start;
993 while(start > text && start[-1] != ' ' && start[-1] != '\t') start--;
994 while(*end && *++end != ' ' && *end != '\n'); *end = NULLCHAR; // find clicked word
995 if(start != end) TypeInDoneEvent(start); // fake it was typed in move type-in
1005 Merge(); // flush merge buffer to memBook
1007 if(f = fopen(appData.polyglotBook, "wb")) {
1008 for(i=0; i<bookSize; i++) {
1009 entry_t entry = memBook[i];
1010 entry.weight = entry.learnPoints;
1011 // entry.learnPoints = 0;
1012 // entry.learnCount = 0;
1013 entry_to_file(f, &entry);
1015 } else DisplayError(_("Could not create book"), 0);