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)];
331 if(pieceGroup & 4) Zobrist *= 987654321;
332 switch(pieceGroup & 3) {
333 case 1: // pieces 5-10 (FEACWM)
334 Zobrist = (Zobrist << 16) ^ (Zobrist >> 48);
336 case 2: // pieces 11-16 (OHIJGD)
337 Zobrist = (Zobrist << 32) ^ (Zobrist >> 32);
339 case 3: // pieces 17-20 (VLSU)
340 Zobrist = (Zobrist << 48) ^ (Zobrist >> 16);
343 if(squareNr & 64) Zobrist = (Zobrist << 8) ^ (Zobrist >> 56);
344 if(squareNr & 128) Zobrist = (Zobrist << 4) ^ (Zobrist >> 60);
345 // holdings have separate (additive) key, to encode presence of multiple pieces on same square
346 if(f == BOARD_LEFT-2) holdingsKey += Zobrist * boards[moveNr][r][f+1]; else
347 if(f == BOARD_RGHT+1) holdingsKey += Zobrist * boards[moveNr][r][f-1]; else
353 if(boards[moveNr][CASTLING][2] != NoRights) {
354 if(boards[moveNr][CASTLING][0] != NoRights) key^=RandomCastle[0];
355 if(boards[moveNr][CASTLING][1] != NoRights) key^=RandomCastle[1];
357 if(boards[moveNr][CASTLING][5] != NoRights) {
358 if(boards[moveNr][CASTLING][3] != NoRights) key^=RandomCastle[2];
359 if(boards[moveNr][CASTLING][4] != NoRights) key^=RandomCastle[3];
362 f = boards[moveNr][EP_STATUS];
364 if(!WhiteOnMove(moveNr)){
365 // the test for neighboring Pawns might not be needed,
366 // as epStatus already kept track of it, but better safe than sorry.
367 if((f>0 && boards[moveNr][3][f-1]==BlackPawn)||
368 (f<7 && boards[moveNr][3][f+1]==BlackPawn)){
369 key^=RandomEnPassant[f];
372 if((f>0 && boards[moveNr][4][f-1]==WhitePawn)||
373 (f<7 && boards[moveNr][4][f+1]==WhitePawn)){
374 key^=RandomEnPassant[f];
379 if(WhiteOnMove(moveNr)){
382 return key + holdingsKey;
387 // fs routines read from memory buffer if no file specified
389 static unsigned char *memBuf, *memPtr;
394 fsseek (FILE *f, int n, int mode)
396 if(f) return fseek(f, n, mode);
397 if(mode == SEEK_SET) memPtr = memBuf + n; else
398 if(mode == SEEK_END) memPtr = memBuf + 16*bufSize + n;
399 return memPtr < memBuf || memPtr > memBuf + 16*bufSize;
405 if(f) return ftell(f);
406 return memPtr - memBuf;
412 if(f) return fgetc(f);
413 if(memPtr >= memBuf + 16*bufSize) return EOF;
418 int_from_file (FILE *f, int l, uint64 *r)
432 entry_from_file (FILE *f, entry_t *entry)
436 if(!f) { *entry = *(entry_t*) memPtr; memPtr += 16; return 0; }
437 ret=int_from_file(f,8,&r);
440 ret=int_from_file(f,2,&r);
443 ret=int_from_file(f,2,&r);
446 ret=int_from_file(f,2,&r);
449 ret=int_from_file(f,2,&r);
451 entry->learnPoints=r;
456 find_key (FILE *f, uint64 key, entry_t *entry)
458 int first, last, middle;
459 entry_t last_entry,middle_entry;
461 if(fsseek(f,-16,SEEK_END)){
463 entry->key=key+1; //hack
467 entry_from_file(f,&last_entry);
473 middle=(first+last)/2;
474 fsseek(f,16*middle,SEEK_SET);
475 entry_from_file(f,&middle_entry);
476 if(key<=middle_entry.key){
478 last_entry=middle_entry;
486 move_to_string (char move_s[6], uint16 move)
488 int f,fr,ff,t,tr,tf,p;
489 int width = BOARD_RGHT - BOARD_LEFT, size; // allow for alternative board formats
491 size = width * BOARD_HEIGHT;
492 p = move / (size*size);
493 move = move % (size*size);
500 move_s[0] = ff + 'a';
501 move_s[1] = fr + '1' - (BOARD_HEIGHT > 9);
502 move_s[2] = tf + 'a';
503 move_s[3] = tr + '1' - (BOARD_HEIGHT > 9);
505 if(IS_SHOGI(gameInfo.variant) && p) {
506 if(p == 2) p = 10; // Lion moves, for boards so big that 10 is out of range
507 else if(p != 7) p = 8; // use '+' for all others that do not explicitly defer
510 // kludge: encode drops as special promotion code
511 if(gameInfo.holdingsSize && p == 9) {
512 move_s[0] = f + '@'; // from square encodes piece type
513 move_s[1] = '@'; // drop symbol
515 } else if(p == 10) { // decode Lion move
520 // add promotion piece, if any
522 move_s[4] = promote_pieces[p];
528 if(gameInfo.variant != VariantNormal) return;
530 // correct FRC-style castlings in variant normal.
531 // [HGM] This is buggy code! e1h1 could very well be a normal R or Q move.
532 if(!strcmp(move_s,"e1h1")){
533 safeStrCpy(move_s,"e1g1", 6);
534 }else if(!strcmp(move_s,"e1a1")){
535 safeStrCpy(move_s,"e1c1", 6);
536 }else if(!strcmp(move_s,"e8h8")){
537 safeStrCpy(move_s,"e8g8", 6);
538 }else if(!strcmp(move_s,"e8a8")){
539 safeStrCpy(move_s,"e8c8", 6);
544 GetBookMoves (FILE *f, int moveNr, entry_t entries[], int max)
545 { // retrieve all entries for given position from book in 'entries', return number.
553 if(appData.debugMode) fprintf(debugFP, "book key = %08x%08x\n", (unsigned int)(key>>32), (unsigned int)key);
555 offset=find_key(f, key, &entry);
556 if(entry.key != key) {
561 fsseek(f, 16*(offset+1), SEEK_SET);
563 ret=entry_from_file(f, &entry);
567 if(entry.key != key){
570 if(count == max) break;
571 entries[count++] = entry;
577 ReadFromBookFile (int moveNr, char *book, entry_t entries[])
578 { // retrieve all entries for given position from book in 'entries', return number.
579 static FILE *f = NULL;
580 static char curBook[MSG_SIZ];
582 if(book == NULL) return -1;
583 if(!f || strcmp(book, curBook)){ // keep book file open until book changed
584 strncpy(curBook, book, MSG_SIZ);
586 f = fopen(book,"rb");
589 DisplayError(_("Polyglot book not valid"), 0);
590 appData.usePolyglotBook = FALSE;
594 return GetBookMoves(f, moveNr, entries, MOVE_BUF);
597 // next three made into subroutines to facilitate future changes in storage scheme (e.g. 2 x 3 bytes)
602 return e->learnPoints;
608 return e->learnCount;
612 CountMove (entry_t *e, int result)
615 case 0: e->learnCount ++; break;
616 case 1: e->learnCount ++; // count draw as win + loss
617 case 2: e->learnPoints ++; break;
621 #define MERGESIZE 2048
622 #define HASHSIZE 1024*1024*4
624 entry_t *memBook, *hashTab, *mergeBuf;
625 int bookSize=1, mergeSize=1, mask = HASHSIZE-1;
630 static int initDone = FALSE;
632 memBook = (entry_t *) calloc(1024*1024, sizeof(entry_t));
633 hashTab = (entry_t *) calloc(HASHSIZE, sizeof(entry_t));
634 mergeBuf = (entry_t *) calloc(MERGESIZE+5, sizeof(entry_t));
635 memBook[0].key = -1LL;
636 mergeBuf[0].key = -1LL;
643 int count, count2, games, i, choice=0;
644 entry_t entries[MOVE_BUF];
645 float nominal[MOVE_BUF], tot, deficit, max, min;
646 static char move_s[6];
649 memBuf = (unsigned char*) memBook; bufSize = bookSize; // in MC mode book resides in memory
650 count = GetBookMoves(NULL, moveNr, entries, MOVE_BUF);
651 if(count < 0) count = 0; // don't care about miss yet
652 memBuf = (unsigned char*) mergeBuf; bufSize = mergeSize; // there could be moves still waiting to be merged
653 count2 = count + GetBookMoves(NULL, moveNr, entries+count, MOVE_BUF - count);
654 if(appData.debugMode) fprintf(debugFP, "MC probe: %d/%d (%d+%d)\n", count, count2,bookSize,mergeSize);
655 if(!count2) return NULL;
657 for(i=0; i<count2; i++) {
658 float w = wins(entries+i) + 10., l = losses(entries+i) + 10.;
659 float h = (w*w*w*w + 22500.*w*w) / (l*l*l*l + 22500.*l*l);
660 tot += nominal[i] = h;
661 games += wins(entries+i) + losses(entries+i);
663 tot = games / tot; max = min = 0;
664 for(i=0; i<count2; i++) {
665 nominal[i] *= tot; // normalize so they sum to games
666 deficit = nominal[i] - (wins(entries+i) + losses(entries+i));
667 if(deficit > max) max = deficit, choice = i;
668 if(deficit < min) min = deficit;
669 } // note that a single move will never be underplayed
670 if(max - min > 0.5*sqrt(nominal[choice])) { // if one of the listed moves is significantly under-played, play it now.
671 move_to_string(move_s, entries[choice].move);
672 if(appData.debugMode) fprintf(debugFP, "book move field = %d\n", entries[choice].move);
675 return NULL; // otherwise fake book miss to force engine think, hoping for hitherto unplayed move.
679 *ProbeBook (int moveNr, char *book)
681 entry_t entries[MOVE_BUF];
684 static char move_s[6];
687 if(moveNr >= 2*appData.bookDepth) return NULL;
688 if(mcMode) return MCprobe(moveNr);
690 if((count = ReadFromBookFile(moveNr, book, entries)) <= 0) return NULL; // no book, or no hit
692 if(appData.bookStrength != 50) { // transform weights
693 double power = 0, maxWeight = 0.0;
694 if(appData.bookStrength) power = (100.-appData.bookStrength)/appData.bookStrength;
695 for(i=0; i<count; i++) if(entries[i].weight > maxWeight) maxWeight = entries[i].weight;
696 for(i=0; i<count; i++){
697 double weight = entries[i].weight / maxWeight;
699 entries[i].weight = appData.bookStrength || weight == 1.0 ? 1e4*exp(power * log(weight)) + 0.5 : 0.0;
703 for(i=0; i<count; i++){
704 total_weight += entries[i].weight;
706 if(total_weight == 0) return NULL; // force book miss rather than playing moves with weight 0.
707 j = (random() & 0xFFF) * total_weight >> 12; // create random < total_weight
709 for(i=0; i<count; i++){
710 total_weight += entries[i].weight;
711 if(total_weight > j) break;
713 if(i >= count) DisplayFatalError(_("Book Fault"), 0, 1); // safety catch, cannot happen
714 move_to_string(move_s, entries[i].move);
715 if(appData.debugMode) fprintf(debugFP, "book move field = %d\n", entries[i].move);
720 extern char yy_textstr[];
721 entry_t lastEntries[MOVE_BUF];
724 MovesToText(int count, entry_t *entries)
726 int i, totalWeight = 0;
728 char *p = (char*) malloc(40*count+1);
729 for(i=0; i<count; i++) totalWeight += entries[i].weight;
731 for(i=0; i<count; i++) {
733 move_to_string(algMove, entries[i].move);
735 if(entries[i].learnCount || entries[i].learnPoints)
736 snprintf(buf, MSG_SIZ, " {%d/%d}", entries[i].learnPoints, entries[i].learnCount);
737 snprintf(p+strlen(p), 40, "%5.1f%% %5d %s%s\n", 100*entries[i].weight/(totalWeight+0.001),
738 entries[i].weight, algMove, buf);
739 //lastEntries[i] = entries[i];
745 CoordsToMove (int fromX, int fromY, int toX, int toY, char promoChar)
747 int i, width = BOARD_RGHT - BOARD_LEFT;
748 int to = toX - BOARD_LEFT + toY * width;
749 int from = fromX - BOARD_LEFT + fromY * width;
750 for(i=0; promote_pieces[i]; i++) if(promote_pieces[i] == promoChar) break;
751 if(!promote_pieces[i]) i = 0;
752 else if(i == 9 && gameInfo.variant == VariantChu) i = 1; // on 12x12 only 3 promotion codes available, so use 1 to indicate promotion
753 if(fromY == DROP_RANK) i = 9, from = ToUpper(PieceToChar(fromX)) - '@';
754 return to + (i * width * BOARD_HEIGHT + from) * width * BOARD_HEIGHT;
758 TextToMoves (char *text, int moveNum, entry_t *entries)
761 uint64 hashKey = hash(moveNum);
762 int fromX, fromY, toX, toY;
764 char promoChar, valid;
767 entries[0].key = hashKey; // make sure key is returned even if no moves
768 while((i=sscanf(text, "%f%%%d", &dummy, &w))==2 || (i=sscanf(text, "%d", &w))==1) {
769 if(i == 2) text = strchr(text, '%') + 1; // skip percentage
770 if(w == 1) text = strstr(text, "1 ") + 2; // skip weight that could be recognized as move number one
771 valid = ParseOneMove(text, moveNum, &moveType, &fromX, &fromY, &toX, &toY, &promoChar);
772 text = strstr(text, yy_textstr) + strlen(yy_textstr); // skip what we parsed
773 if(!valid || moveType != NormalMove && moveType != WhiteDrop && moveType != BlackDrop
774 && moveType != WhitePromotion && moveType != BlackPromotion
775 && moveType != WhiteCapturesEnPassant && moveType != BlackCapturesEnPassant
776 && moveType != WhiteKingSideCastle && moveType != BlackKingSideCastle
777 && moveType != WhiteQueenSideCastle && moveType != BlackQueenSideCastle
778 && moveType != WhiteNonPromotion && moveType != BlackNonPromotion) continue;
779 if(*text == ' ' && sscanf(text+1, "{%hd/%hd}", &entries[count].learnPoints, &entries[count].learnCount) == 2) {
780 text = strchr(text+1, '}') + 1;
782 entries[count].learnPoints = 0;
783 entries[count].learnCount = 0;
785 entries[count].move = CoordsToMove(fromX, fromY, toX, toY, promoChar);
786 entries[count].key = hashKey;
787 entries[count].weight = w;
797 DisplayBook (int moveNr)
799 entry_t entries[MOVE_BUF];
802 if(!bookUp) return FALSE;
803 count = currentCount = ReadFromBookFile(moveNr, appData.polyglotBook, entries);
804 if(count < 0) return FALSE;
805 p = MovesToText(count, entries);
806 EditTagsPopUp(p, NULL);
808 addToBookFlag = FALSE;
816 bookUp = DisplayBook(currentMove);
820 int_to_file (FILE *f, int l, uint64 r)
823 for(i=l-1;i>=0;i--) fputc(r>>8*i & 255, f);
827 entry_to_file (FILE *f, entry_t *entry)
829 int_to_file(f,8,entry->key);
830 int_to_file(f,2,entry->move);
831 int_to_file(f,2,entry->weight);
832 int_to_file(f,2,entry->learnCount);
833 int_to_file(f,2,entry->learnPoints);
836 char buf1[4096], buf2[4096];
839 SaveToBook (char *text)
841 entry_t entries[MOVE_BUF], entry;
842 int count = TextToMoves(text, currentMove, entries);
843 int offset, i, len1=0, len2, readpos=0, writepos=0;
845 if(!count && !currentCount) return;
846 f=fopen(appData.polyglotBook, "rb+");
847 if(!f){ DisplayError(_("Polyglot book not valid"), 0); return; }
848 offset=find_key(f, entries[0].key, &entry);
849 if(entries[0].key != entry.key && currentCount) {
850 DisplayError(_("Hash keys are different"), 0);
854 if(count != currentCount) {
855 readpos = 16*(offset + currentCount);
856 writepos = 16*(offset + count);
857 fsseek(f, readpos, SEEK_SET);
858 readpos += len1 = fread(buf1, 1, 4096 - 16*currentCount, f); // salvage some entries immediately behind change
860 fsseek(f, 16*(offset), SEEK_SET);
861 for(i=0; i<count; i++) entry_to_file(f, entries + i); // save the change
862 if(count != currentCount) {
864 for(i=0; i<len1; i++) buf2[i] = buf1[i]; len2 = len1;
865 if(readpos > writepos) {
866 fsseek(f, readpos, SEEK_SET);
867 readpos += len1 = fread(buf1, 1, 4096, f);
868 } else len1 = 0; // wrote already past old EOF
869 fsseek(f, writepos, SEEK_SET);
870 fwrite(buf2, 1, len2, f);
878 NewEntry (entry_t *e, uint64 key, int move, int result)
884 CountMove(e, result);
892 if(appData.debugMode) fprintf(debugFP, "book merge %d moves (old size %d)\n", mergeSize, bookSize);
894 bookSize += --mergeSize;
895 for(i=bookSize-1; mergeSize; i--) {
896 while(mergeSize && (i < mergeSize || mergeBuf[mergeSize-1].key >= memBook[i-mergeSize].key))
897 memBook[i--] = mergeBuf[--mergeSize];
899 memBook[i] = memBook[i-mergeSize];
901 if(mergeSize) DisplayFatalError("merge error", 0, 0); // impossible
903 mergeBuf[0].key = -1LL;
907 AddToBook (int moveNr, int result)
910 int offset, start, move;
912 int i, j, fromY, toY;
913 char fromX, toX, promo;
914 extern char moveList[][MOVE_LEN];
916 if(!moveList[moveNr][0] || moveList[moveNr][0] == '\n') return; // could be terminal position
918 if(appData.debugMode) fprintf(debugFP, "add move %d to book %s", moveNr, moveList[moveNr]);
920 // calculate key and book representation of move
922 if(moveList[moveNr][1] == '@') {
923 sscanf(moveList[moveNr], "%c@%c%d", &promo, &toX, &toY);
924 fromX = CharToPiece(WhiteOnMove(moveNr) ? ToUpper(promo) : ToLower(promo));
925 fromY = DROP_RANK; promo = NULLCHAR;
926 } else sscanf(moveList[moveNr], "%c%d%c%d%c", &fromX, &fromY, &toX, &toY, &promo), fromX -= AAA, fromY -= ONE - '0';
927 move = CoordsToMove(fromX, fromY, toX-AAA, toY-ONE+'0', promo);
929 // if move already in book, just add count
930 memBuf = (unsigned char*) memBook; bufSize = bookSize; // in MC mode book resides in memory
931 offset = find_key(NULL, key, &entry);
932 while(memBook[offset].key == key) {
933 if(memBook[offset].move == move) {
934 CountMove(memBook+offset, result); return;
937 // move did not occur in the main book
938 memBuf = (unsigned char*) mergeBuf; bufSize = mergeSize; // it could be amongst moves still waiting to be merged
939 start = offset = find_key(NULL, key, &entry);
940 while(mergeBuf[offset].key == key) {
941 if(mergeBuf[offset].move == move) {
942 if(appData.debugMode) fprintf(debugFP, "found in book merge buf @ %d\n", offset);
943 CountMove(mergeBuf+offset, result); return;
946 if(start != offset) { // position was in mergeBuf, but move is new
947 if(appData.debugMode) fprintf(debugFP, "add in book merge buf @ %d\n", offset);
948 for(i=mergeSize++; i>offset; i--) mergeBuf[i] = mergeBuf[i-1]; // make room
949 NewEntry(mergeBuf+offset, key, move, result);
952 // position was not in mergeBuf; look in hash table
953 i = (key & mask); offset = -1;
954 while(hashTab[i].key) { // search in hash table (necessary because sought item could be re-hashed)
955 if(hashTab[i].key == 1 && offset < 0) offset = i; // remember first invalidated entry we pass
956 if(!((hashTab[i].key - key) & ~1)) { // hit
957 if(hashTab[i].move == move) {
958 CountMove(hashTab+i, result);
959 for(j=mergeSize++; j>start; j--) mergeBuf[j] = mergeBuf[j-1];
961 // position already in hash now occurs with different move; move both moves to mergeBuf
962 for(j=mergeSize+1; j>start+1; j--) mergeBuf[j] = mergeBuf[j-2];
963 NewEntry(mergeBuf+start+1, key, move, result); mergeSize += 2;
965 hashTab[i].key = 1; // kludge to invalidate hash entry
966 mergeBuf[start] = hashTab[i]; mergeBuf[start].key = key;
967 if(mergeSize >= MERGESIZE) Merge();
970 i = i+1 & mask; // wrap!
972 // position did not yet occur in hash table. Put it there
973 if(offset < 0) offset = i;
974 NewEntry(hashTab+offset, key, move, result);
975 if(appData.debugMode)
976 fprintf(debugFP, "book hash @ %d (%d-%d)\n", offset, hashTab[offset].learnPoints, hashTab[offset].learnCount);
980 AddGameToBook (int always)
984 if(!mcMode && !always) return;
987 switch(gameInfo.result) {
988 case GameIsDrawn: result = 1; break;
989 case WhiteWins: result = 2; break;
990 case BlackWins: result = 0; break;
991 default: return; // don't treat games with unknown result
994 if(appData.debugMode) fprintf(debugFP, "add game to book (%d-%d)\n", backwardMostMove, forwardMostMove);
995 for(i=backwardMostMove; i<forwardMostMove && i < 2*appData.bookDepth; i++)
996 AddToBook(i, WhiteOnMove(i) ? result : 2-result); // flip result when black moves
1000 PlayBookMove(char *text, int index)
1002 char *start = text+index, *end = start;
1003 while(start > text && start[-1] != ' ' && start[-1] != '\t') start--;
1004 while(*end && *++end != ' ' && *end != '\n'); *end = NULLCHAR; // find clicked word
1005 if(start != end) TypeInDoneEvent(start); // fake it was typed in move type-in
1015 Merge(); // flush merge buffer to memBook
1017 if(f = fopen(appData.polyglotBook, "wb")) {
1018 for(i=0; i<bookSize; i++) {
1019 entry_t entry = memBook[i];
1020 entry.weight = entry.learnPoints;
1021 // entry.learnPoints = 0;
1022 // entry.learnCount = 0;
1023 entry_to_file(f, &entry);
1025 } else DisplayError(_("Could not create book"), 0);