Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1805 | yogev_ezra | 1 | #ifndef _HEADER_HISTORY_H |
2 | #define _HEADER_HISTORY_H |
||
3 | |||
4 | #ifndef __MENUET__ |
||
5 | #include |
||
6 | #include |
||
7 | #include |
||
8 | #include |
||
9 | #endif |
||
10 | #include "position.h" |
||
11 | #include "hash.h" |
||
12 | #include "sysproc.h" |
||
13 | |||
14 | class THistory |
||
15 | { |
||
16 | #ifndef __MENUET__ |
||
17 | public: |
||
18 | static char FileName[1024]; |
||
19 | #endif |
||
20 | public: |
||
21 | THistory(int id = 0) {if (id >= 0) Hid = NHid++; else Hid = id;} |
||
22 | |||
23 | int GetId() const {return Hid;} |
||
24 | static int GetNId() {return NHid;} |
||
25 | |||
26 | int Start(const Position &pos) const; |
||
27 | int Move(const Position &pos, const unsigned char mv[], int nmove) const; |
||
28 | int Play(const PlayWrite &play) const; |
||
29 | |||
30 | #ifndef __MENUET__ |
||
31 | static int InitHFile(char *dname = 0); |
||
32 | static int HRead(FILE *f, PlayWrite *&play); |
||
33 | protected: |
||
34 | int Print(const char *str) const; |
||
35 | #endif |
||
36 | |||
37 | int Hid; |
||
38 | |||
39 | static int NHid; |
||
40 | protected: |
||
41 | struct TStr |
||
42 | { |
||
43 | TStr(const char *ss = 0) : s(0) {(*this) = ss;} |
||
44 | TStr(const TStr &ss) : s(0) {(*this) = ss.s;} |
||
45 | ~TStr() {(*this) = 0;} |
||
46 | |||
47 | TStr &operator=(const char *ss); |
||
48 | TStr &operator=(const TStr &ss) {return (*this) = ss.s;} |
||
49 | |||
50 | operator char*() {return s;} |
||
51 | operator const char*() const {return s;} |
||
52 | char &operator*() {return *s;} |
||
53 | const char &operator*() const {return *s;} |
||
54 | char &operator[](int i) {return s[i];} |
||
55 | const char &operator[](int i) const {return s[i];} |
||
56 | void Extend(int n); |
||
57 | |||
58 | friend int operator==(const TStr &s1, const TStr &s2) |
||
59 | {return strcmp(s1, s2) == 0;} |
||
60 | friend int operator==(const char *s1, const TStr &s2) |
||
61 | {return strcmp(s1, s2) == 0;} |
||
62 | friend int operator==(const TStr &s1, const char *s2) |
||
63 | {return strcmp(s1, s2) == 0;} |
||
64 | friend int operator!=(const TStr &s1, const TStr &s2) |
||
65 | {return strcmp(s1, s2) != 0;} |
||
66 | friend int operator!=(const char *s1, const TStr &s2) |
||
67 | {return strcmp(s1, s2) != 0;} |
||
68 | friend int operator!=(const TStr &s1, const char *s2) |
||
69 | {return strcmp(s1, s2) != 0;} |
||
70 | friend int operator>=(const TStr &s1, const TStr &s2) |
||
71 | {return strcmp(s1, s2) >= 0;} |
||
72 | friend int operator>=(const char *s1, const TStr &s2) |
||
73 | {return strcmp(s1, s2) >= 0;} |
||
74 | friend int operator>=(const TStr &s1, const char *s2) |
||
75 | {return strcmp(s1, s2) >= 0;} |
||
76 | friend int operator<=(const TStr &s1, const TStr &s2) |
||
77 | {return strcmp(s1, s2) <= 0;} |
||
78 | friend int operator<=(const char *s1, const TStr &s2) |
||
79 | {return strcmp(s1, s2) <= 0;} |
||
80 | friend int operator<=(const TStr &s1, const char *s2) |
||
81 | {return strcmp(s1, s2) <= 0;} |
||
82 | friend int operator>(const TStr &s1, const TStr &s2) |
||
83 | {return strcmp(s1, s2) > 0;} |
||
84 | friend int operator>(const char *s1, const TStr &s2) |
||
85 | {return strcmp(s1, s2) > 0;} |
||
86 | friend int operator>(const TStr &s1, const char *s2) |
||
87 | {return strcmp(s1, s2) > 0;} |
||
88 | friend int operator<(const TStr &s1, const TStr &s2) |
||
89 | {return strcmp(s1, s2) < 0;} |
||
90 | friend int operator<(const char *s1, const TStr &s2) |
||
91 | {return strcmp(s1, s2) < 0;} |
||
92 | friend int operator<(const TStr &s1, const char *s2) |
||
93 | {return strcmp(s1, s2) < 0;} |
||
94 | |||
95 | char *s; |
||
96 | }; |
||
97 | |||
98 | class THash |
||
99 | { |
||
100 | public: |
||
101 | void init(int _m); |
||
102 | int operator()(const TStr &str) const; |
||
103 | protected: |
||
104 | int m; |
||
105 | int K[16]; |
||
106 | }; |
||
107 | |||
108 | struct TTableItem |
||
109 | { |
||
110 | TTableItem(const char *s = 0, int k = 0) : str(s), k(k) {} |
||
111 | TTableItem(const TStr &s, int k = 0) : str(s), k(k) {} |
||
112 | TTableItem(const TTableItem &t) : str(t.str), k(t.k) {} |
||
113 | |||
114 | operator TStr&() {return str;} |
||
115 | operator const TStr&() const {return str;} |
||
116 | |||
117 | TStr str; |
||
118 | int k; |
||
119 | }; |
||
120 | }; |
||
121 | |||
122 | #ifndef __MENUET__ |
||
123 | char THistory::FileName[1024] = "history.che"; |
||
124 | #endif |
||
125 | int THistory::NHid = 0; |
||
126 | |||
127 | #ifndef __MENUET__ |
||
128 | int THistory::Print(const char *str) const |
||
129 | { |
||
130 | char *line = new char[30 + strlen(str)]; |
||
131 | if (!line) return 0; |
||
132 | unsigned long pr_id = GetProcessId(); |
||
133 | if (Hid == -1) sprintf(line, "%lu %s\n", pr_id, str); |
||
134 | else if (Hid < 0) sprintf(line, "%lu%c %s\n", pr_id, (char)Hid, str); |
||
135 | else sprintf(line, "%lu:%d %s\n", pr_id, Hid, str); |
||
136 | FILE *f = fopen(FileName, "at"); |
||
137 | if (!f) |
||
138 | { |
||
139 | clock_t cc = clock(); |
||
140 | do {f = fopen(FileName, "at");} |
||
141 | while(!f && (clock() - cc) <= 0.05 * CLOCKS_PER_SEC); |
||
142 | } |
||
143 | if (!f) {delete[] line; return 0;} |
||
144 | fputs(line, f); |
||
145 | fclose(f); |
||
146 | delete[] line; |
||
147 | return 1; |
||
148 | } |
||
149 | #endif |
||
150 | |||
151 | int THistory::Start(const Position &pos) const |
||
152 | { |
||
153 | char str[20 + NUM_CELL] = "Start "; |
||
154 | if (!pos.Write(str + strlen(str), 1)) return 0; |
||
155 | #ifndef __MENUET__ |
||
156 | if (!Print(str)) return 0; |
||
157 | #endif |
||
158 | return 1; |
||
159 | } |
||
160 | |||
161 | int THistory::Move(const Position &pos, const unsigned char mv[], int nmove) const |
||
162 | { |
||
163 | char *str = new char[15 + pos.GetLenMvEx(mv, 11)]; |
||
164 | if (!str) return 0; |
||
165 | sprintf(str, "%d.%s ", (nmove + 1) / 2, (nmove % 2 == 0) ? ".." : ""); |
||
166 | pos.WriteMvEx(mv, str + strlen(str), 11); |
||
167 | #ifndef __MENUET__ |
||
168 | if (!Print(str)) {delete[] str; return 0;} |
||
169 | #endif |
||
170 | delete[] str; |
||
171 | return 1; |
||
172 | } |
||
173 | |||
174 | int THistory::Play(const PlayWrite &play) const |
||
175 | { |
||
176 | if (play.GetN() <= 0) return 0; |
||
177 | Position pos; |
||
178 | if (play.GetPos(pos, 0) < 0) return 0; |
||
179 | if (!Start(pos)) return 0; |
||
180 | int i; |
||
181 | unsigned char mv[NUM_CELL]; |
||
182 | for (i = 1; i < play.GetN(); i++) |
||
183 | { |
||
184 | if (play.GetPos(pos, i - 1) < 0) return 0; |
||
185 | if (play.GetMove(mv, i) < 0) return 0; |
||
186 | if (!Move(pos, mv, i)) return 0; |
||
187 | } |
||
188 | return 1; |
||
189 | } |
||
190 | |||
191 | #ifndef __MENUET__ |
||
192 | int THistory::InitHFile(char *dname) |
||
193 | { |
||
194 | if (dname && dname[0]) |
||
195 | { |
||
196 | char fnm[1024]; |
||
197 | strcpy(fnm, dname); |
||
198 | int i; |
||
199 | for (i = strlen(fnm) - 1; i >= 0; i--) |
||
200 | { |
||
201 | if (fnm[i] == DIR_SEPARATOR) break; |
||
202 | } |
||
203 | if (i >= 0) |
||
204 | { |
||
205 | strcpy(fnm + i + 1, FileName); |
||
206 | strcpy(FileName, fnm); |
||
207 | } |
||
208 | } |
||
209 | int e = 1; |
||
210 | FILE *f = fopen(FileName, "rt"); |
||
211 | if (f) {e = feof(f); fclose(f);} |
||
212 | if (!e) return 0; |
||
213 | f = fopen(FileName, "wt"); |
||
214 | if (!f) return -1; |
||
215 | fputs("checkers-history_1.1\n", f); |
||
216 | fclose(f); |
||
217 | return 1; |
||
218 | } |
||
219 | #endif |
||
220 | |||
221 | THistory::TStr &THistory::TStr::operator=(const char *ss) |
||
222 | { |
||
223 | if (s) delete[] s; |
||
224 | if (ss) |
||
225 | { |
||
226 | s = new char[strlen(ss) + 1]; |
||
227 | strcpy(s, ss); |
||
228 | } |
||
229 | else s = 0; |
||
230 | return *this; |
||
231 | } |
||
232 | |||
233 | void THistory::TStr::Extend(int n) |
||
234 | { |
||
235 | if (n <= 0) {(*this) = 0; return;} |
||
236 | char *ss = s; |
||
237 | s = new char[n+1]; |
||
238 | if (ss) |
||
239 | { |
||
240 | strncpy(s, ss, n); |
||
241 | s[n] = 0; |
||
242 | delete[] ss; |
||
243 | } |
||
244 | else s[0] = 0; |
||
245 | } |
||
246 | |||
247 | void THistory::THash::init(int _m) |
||
248 | { |
||
249 | m = _m; |
||
250 | for (int i = 0; i < 16; i++) |
||
251 | { |
||
252 | K[i] = (2*random(32767) + 1) & ((1 << m) - 1); |
||
253 | } |
||
254 | } |
||
255 | |||
256 | int THistory::THash::operator()(const TStr &str) const |
||
257 | { |
||
258 | int i, r = 0; |
||
259 | const char *s = str; |
||
260 | for (i = 0; *s; i = (i+1) & 15) r += *(s++) * K[i]; |
||
261 | r &= (1 << m) - 1; |
||
262 | return r; |
||
263 | } |
||
264 | |||
265 | #ifndef __MENUET__ |
||
266 | int THistory::HRead(FILE *f, PlayWrite *&play) |
||
267 | { |
||
268 | const int MAX_INP_WORD = 100; |
||
269 | int nplay = 0, mplay = 10; |
||
270 | play = new PlayWrite[mplay]; |
||
271 | THashTable |
||
272 | TStr word; |
||
273 | char inp_word[MAX_INP_WORD + 1]; |
||
274 | int r, maxword = 0; |
||
275 | unsigned char ch; |
||
276 | int i, k = 0, kind = 0, wasspace = 1, nmove = 0; |
||
277 | for (;;) |
||
278 | { |
||
279 | r = (fread(&ch, 1, 1, f) == 1); |
||
280 | if (!r || isspace(ch)) |
||
281 | { |
||
282 | if (!wasspace) |
||
283 | { |
||
284 | if (kind == 0) kind = 1; |
||
285 | else if (kind == 2) |
||
286 | { |
||
287 | for (i = 0; inp_word[i]; i++) |
||
288 | { |
||
289 | inp_word[i] = (char)tolower((unsigned char)inp_word[i]); |
||
290 | } |
||
291 | if (strcmp(inp_word, "start") == 0) kind = 5; |
||
292 | else kind = -1; |
||
293 | inp_word[0] = 0; k = 0; |
||
294 | } |
||
295 | else if (kind == 3) |
||
296 | { |
||
297 | nmove *= 2; |
||
298 | if (k <= 1) nmove--; |
||
299 | inp_word[0] = 0; |
||
300 | k = 0; kind = 4; |
||
301 | } |
||
302 | else if (kind == 4) |
||
303 | { |
||
304 | TTableItem *n_pl = table.find(word); |
||
305 | if (!n_pl) kind = -1; |
||
306 | else if (nmove < 1 || nmove > play[n_pl->k].GetN()) kind = -1; |
||
307 | else |
||
308 | { |
||
309 | PlayWrite::PMv pmv; |
||
310 | if (play[n_pl->k].GetPos(pmv.pos, nmove - 1) < 0) kind = -1; |
||
311 | else if (!pmv.pos.ReadMv(pmv.mv, inp_word, 1)) kind = -1; |
||
312 | else |
||
313 | { |
||
314 | play[n_pl->k].ClearFrom(nmove); |
||
315 | if (play[n_pl->k].Add(pmv.mv) != 0) kind = -1; |
||
316 | else {k = n_pl->k; kind = 11;} |
||
317 | } |
||
318 | } |
||
319 | } |
||
320 | else if (kind == 5) |
||
321 | { |
||
322 | Position pos; |
||
323 | pos.Read(inp_word, 1); |
||
324 | if (pos.IsNull()) kind = -1; |
||
325 | else |
||
326 | { |
||
327 | TTableItem *n_pl = table.find(word); |
||
328 | if (!n_pl) |
||
329 | { |
||
330 | table.push(TTableItem(word, nplay)); |
||
331 | n_pl = table.find(word); |
||
332 | } |
||
333 | if (!n_pl) kind = -1; |
||
334 | else |
||
335 | { |
||
336 | if (nplay >= mplay) |
||
337 | { |
||
338 | PlayWrite *play0 = play; |
||
339 | int mplay0 = mplay; |
||
340 | mplay = 2*nplay + 3; |
||
341 | play = new PlayWrite[mplay]; |
||
342 | if (play0) |
||
343 | { |
||
344 | for (i = 0; i < mplay0; i++) play[i] = play0[i]; |
||
345 | delete[] play0; |
||
346 | } |
||
347 | } |
||
348 | n_pl->k = nplay++; |
||
349 | play[n_pl->k].Add(0, pos); |
||
350 | k = n_pl->k; kind = 12; |
||
351 | } |
||
352 | } |
||
353 | } |
||
354 | } |
||
355 | if (!r || ch == '\n' || ch == '\r') |
||
356 | { |
||
357 | k = 0; |
||
358 | kind = 0; |
||
359 | if (!r) break; |
||
360 | } |
||
361 | wasspace = 1; |
||
362 | } |
||
363 | else |
||
364 | { |
||
365 | if (kind == 0) |
||
366 | { |
||
367 | if (k >= maxword) word.Extend(2*k + 3); |
||
368 | word[k++] = ch; |
||
369 | word[k] = 0; |
||
370 | } |
||
371 | else if (kind == 1) |
||
372 | { |
||
373 | if (isdigit(ch)) {nmove = ch - '0'; k = 0; kind = 3;} |
||
374 | else |
||
375 | { |
||
376 | inp_word[0] = ch; |
||
377 | inp_word[1] = 0; |
||
378 | k = 1; kind = 2; |
||
379 | } |
||
380 | } |
||
381 | else if (kind == 2 || kind == 4 || kind == 5) |
||
382 | { |
||
383 | if (k < MAX_INP_WORD) |
||
384 | { |
||
385 | inp_word[k++] = ch; |
||
386 | inp_word[k] = 0; |
||
387 | } |
||
388 | } |
||
389 | else if (kind == 3) |
||
390 | { |
||
391 | if (k == 0 && isdigit(ch)) nmove = 10 * nmove + ch - '0'; |
||
392 | else if (ch == '.') k++; |
||
393 | else kind = -1; |
||
394 | } |
||
395 | wasspace = 0; |
||
396 | } |
||
397 | } |
||
398 | return nplay; |
||
399 | } |
||
400 | #endif |
||
401 | |||
402 | #endif //_HEADER_HISTORY_H>>>>=>><>><>>=>>>>>=>=>>>(const>>(const>>(const>=>=(const>=>=(const>=>=(const> |