Rev 154 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
33 | pmbaty | 1 | /*>>> epdglue.c: glue to connect Crafty to the EPD Kit routines */ |
2 | #if defined(EPD) |
||
3 | /* Revised: 1996.04.21 */ |
||
4 | /* |
||
5 | Copyright (C) 1996 by Steven J. Edwards (sje@mv.mv.com) |
||
6 | All rights reserved. This code may be freely redistibuted and used by |
||
7 | both research and commerical applications. No warranty exists. |
||
8 | */ |
||
9 | /* |
||
10 | The contents of this source file form the programmatic glue between |
||
11 | the host program Crafty and the EPD Kit. Therefore, this file will |
||
12 | have to be changed if used with a different host program. Also, the |
||
13 | contents of the prototype include file (epdglue.h) may also require |
||
14 | modification for a different host. |
||
15 | The contents of the other source files in the EPD Kit (epddefs.h, |
||
16 | epd.h, and epd.c) should not have to be changed for different hosts. |
||
17 | */ |
||
18 | /* |
||
19 | This file was originally prepared on an Apple Macintosh using the |
||
20 | Metrowerks CodeWarrior 6 ANSI C compiler. Tabs are set at every |
||
21 | four columns. Further testing and development was performed on a |
||
22 | generic PC running Linux 1.2.9 and using the gcc 2.6.3 compiler. |
||
23 | */ |
||
24 | /* system includes */ |
||
25 | # if defined(UNIX) |
||
26 | # include <unistd.h> |
||
27 | # endif |
||
28 | # include <ctype.h> |
||
29 | # include <time.h> |
||
30 | # if !defined(UNIX) |
||
31 | # include <process.h> |
||
32 | # endif |
||
33 | /* Crafty includes */ |
||
34 | # include "chess.h" |
||
35 | # include "data.h" |
||
36 | /* EPD Kit definitions (host program independent) */ |
||
37 | # include "epddefs.h" |
||
38 | /* EPD Kit routine prototypes (host program independent) */ |
||
39 | # include "epd.h" |
||
40 | /* prototypes for this file (host program dependent) */ |
||
41 | # include "epdglue.h" |
||
42 | /* EPD glue command type */ |
||
43 | typedef siT egcommT, *egcommptrT; |
||
44 | |||
45 | # define egcommL 26 |
||
46 | # define egcomm_nil (-1) |
||
108 | pmbaty | 47 | # define egcomm_epdapgn 0 /* append a PGN game to a file */ |
48 | # define egcomm_epdbfix 1 /* fix file for Bookup import */ |
||
49 | # define egcomm_epdcert 2 /* display certain evaluation (if possible) */ |
||
50 | # define egcomm_epdcics 3 /* slave to an Internet Chess Server */ |
||
51 | # define egcomm_epdcomm 4 /* slave to the Duplex referee program */ |
||
52 | # define egcomm_epddpgn 5 /* display the current game in PGN */ |
||
53 | # define egcomm_epddsml 6 /* display SAN move list */ |
||
54 | # define egcomm_epddstr 7 /* display PGN Seven Tag Roster */ |
||
55 | # define egcomm_epddtpv 8 /* display PGN tag pair value */ |
||
56 | # define egcomm_epdenum 9 /* enumerate EPD file */ |
||
57 | # define egcomm_epdhelp 10 /* display EPD help */ |
||
58 | # define egcomm_epdlink 11 /* slave to the Argus referee program */ |
||
59 | # define egcomm_epdlpgn 12 /* load a PGN game from a file */ |
||
60 | # define egcomm_epdlrec 13 /* load an EPD record form a file */ |
||
61 | # define egcomm_epdmore 14 /* more help */ |
||
62 | # define egcomm_epdnoop 15 /* no operation */ |
||
63 | # define egcomm_epdpfdn 16 /* process file: data normalization */ |
||
64 | # define egcomm_epdpfdr 17 /* process file: data repair */ |
||
65 | # define egcomm_epdpfga 18 /* process file: general analysis */ |
||
66 | # define egcomm_epdpflc 19 /* process file: locate cooks */ |
||
67 | # define egcomm_epdpfop 20 /* process file: operation purge */ |
||
68 | # define egcomm_epdscor 21 /* score EPD benchmark result file */ |
||
69 | # define egcomm_epdshow 22 /* show EPD four fields for current position */ |
||
70 | # define egcomm_epdspgn 23 /* save a PGN game to a file */ |
||
71 | # define egcomm_epdstpv 24 /* set PGN tag pair value */ |
||
72 | # define egcomm_epdtest 25 /* developer testing */ |
||
33 | pmbaty | 73 | /* output text buffer */ |
74 | # define tbufL 256 |
||
75 | static char tbufv[tbufL]; |
||
76 | |||
77 | /* EPD glue command strings */ |
||
78 | static charptrT egcommstrv[egcommL]; |
||
79 | |||
80 | /* EPD glue command string descriptions */ |
||
81 | static charptrT eghelpstrv[egcommL]; |
||
82 | |||
83 | /* EPD glue command parameter counts (includes command token) */ |
||
84 | /* the current (default) EPD game structure */ |
||
85 | static gamptrT default_gamptr; |
||
86 | |||
87 | /*--> EGPrint: print a string to the output */ |
||
88 | static |
||
89 | void EGPrint(charptrT s) { |
||
90 | /* this is an internal EPD glue routine */ |
||
91 | /* |
||
92 | This routine is provided as an alternative to direct writing to the |
||
93 | standard output. All EPD glue printing output goes through here. The |
||
94 | idea is that the host program may have some special requirements for |
||
95 | printing output (like a window display), so a convenient single point |
||
96 | is provided to handle this. |
||
97 | Note that there is no corresponding routine for reading from the |
||
98 | standard input because the EPD glue does no interactive reading, except |
||
99 | for a single getchar() call in the epdhelp display pager. |
||
100 | */ |
||
101 | /* for Crafty, the standard output is used */ |
||
102 | printf("%s", s); |
||
103 | return; |
||
104 | } |
||
105 | |||
106 | /*--> EGPrintTB: print the contents of the text buffer */ |
||
107 | static |
||
108 | void EGPrintTB(void) { |
||
109 | /* this is an internal EPD glue routine */ |
||
110 | EGPrint(tbufv); |
||
111 | return; |
||
112 | } |
||
113 | |||
114 | /*--> EGPL: print a string followed by a newline */ |
||
115 | static |
||
116 | void EGPL(charptrT s) { |
||
117 | /* this is an internal EPD glue routine */ |
||
118 | EGPrint(s); |
||
119 | EGPrint("\n"); |
||
120 | return; |
||
121 | } |
||
122 | |||
123 | /*--> EGLocateCommand: locate an EPD glue command from a token */ |
||
124 | static egcommT EGLocateCommand(charptrT s) { |
||
125 | egcommT egcomm, index; |
||
126 | |||
127 | /* this is an internal EPD glue routine */ |
||
128 | /* set the default return value: no match */ |
||
129 | egcomm = egcomm_nil; |
||
130 | /* scan the EPD glue command string vector */ |
||
131 | index = 0; |
||
132 | while ((index < egcommL) && (egcomm == egcomm_nil)) |
||
133 | if (strcmp(s, egcommstrv[index]) == 0) |
||
134 | egcomm = index; |
||
135 | else |
||
136 | index++; |
||
137 | return egcomm; |
||
138 | } |
||
139 | |||
140 | /*--> EGMapFromHostColor: map a color from the host to the EPD style */ |
||
141 | static cT EGMapFromHostColor(siT color) { |
||
142 | cT c; |
||
143 | |||
144 | /* this is an internal glue routine */ |
||
145 | /* map from Crafty's color representation */ |
||
146 | if (color == 1) |
||
147 | c = c_w; |
||
148 | else |
||
149 | c = c_b; |
||
150 | return c; |
||
151 | } |
||
152 | |||
153 | /*--> EGMapToHostColor: map a color to the host from the EPD style */ |
||
154 | static siT EGMapToHostColor(cT c) { |
||
155 | siT color; |
||
156 | |||
157 | /* this is an internal glue routine */ |
||
158 | /* map to Crafty's color representation */ |
||
159 | if (c == c_w) |
||
160 | color = 1; |
||
161 | else |
||
162 | color = 0; |
||
163 | return color; |
||
164 | } |
||
165 | |||
166 | /*--> EGMapFromHostCP: map a color piece from the host to the EPD style */ |
||
167 | static cpT EGMapFromHostCP(siT hostcp) { |
||
168 | cpT cp = 0; |
||
169 | |||
170 | /* this is an internal glue routine */ |
||
171 | /* map from Crafty's color-piece representation */ |
||
172 | switch (hostcp) { |
||
173 | case -queen: |
||
174 | cp = cp_bq; |
||
175 | break; |
||
176 | case -rook: |
||
177 | cp = cp_br; |
||
178 | break; |
||
179 | case -bishop: |
||
180 | cp = cp_bb; |
||
181 | break; |
||
182 | case -king: |
||
183 | cp = cp_bk; |
||
184 | break; |
||
185 | case -knight: |
||
186 | cp = cp_bn; |
||
187 | break; |
||
188 | case -pawn: |
||
189 | cp = cp_bp; |
||
190 | break; |
||
191 | case 0: |
||
192 | cp = cp_v0; |
||
193 | break; |
||
194 | case pawn: |
||
195 | cp = cp_wp; |
||
196 | break; |
||
197 | case knight: |
||
198 | cp = cp_wn; |
||
199 | break; |
||
200 | case king: |
||
201 | cp = cp_wk; |
||
202 | break; |
||
203 | case bishop: |
||
204 | cp = cp_wb; |
||
205 | break; |
||
206 | case rook: |
||
207 | cp = cp_wr; |
||
208 | break; |
||
209 | case queen: |
||
210 | cp = cp_wq; |
||
211 | break; |
||
212 | }; |
||
213 | return cp; |
||
214 | } |
||
215 | |||
216 | /*--> EGMapToHostCP: map a color piece to the host from the EPD style */ |
||
217 | static siT EGMapToHostCP(cpT cp) { |
||
218 | siT hostcp = 0; |
||
219 | |||
220 | /* this is an internal glue routine */ |
||
221 | /* map to Crafty's color-piece representation */ |
||
222 | switch (cp) { |
||
223 | case cp_wp: |
||
224 | hostcp = pawn; |
||
225 | break; |
||
226 | case cp_wn: |
||
227 | hostcp = knight; |
||
228 | break; |
||
229 | case cp_wb: |
||
230 | hostcp = bishop; |
||
231 | break; |
||
232 | case cp_wr: |
||
233 | hostcp = rook; |
||
234 | break; |
||
235 | case cp_wq: |
||
236 | hostcp = queen; |
||
237 | break; |
||
238 | case cp_wk: |
||
239 | hostcp = king; |
||
240 | break; |
||
241 | case cp_bp: |
||
242 | hostcp = -pawn; |
||
243 | break; |
||
244 | case cp_bn: |
||
245 | hostcp = -knight; |
||
246 | break; |
||
247 | case cp_bb: |
||
248 | hostcp = -bishop; |
||
249 | break; |
||
250 | case cp_br: |
||
251 | hostcp = -rook; |
||
252 | break; |
||
253 | case cp_bq: |
||
254 | hostcp = -queen; |
||
255 | break; |
||
256 | case cp_bk: |
||
257 | hostcp = -king; |
||
258 | break; |
||
259 | case cp_v0: |
||
260 | hostcp = 0; |
||
261 | break; |
||
262 | }; |
||
263 | return hostcp; |
||
264 | } |
||
265 | |||
266 | /*--> EGMapFromHostSq: map square index from host style */ |
||
267 | static sqT EGMapFromHostSq(siT index) { |
||
268 | sqT sq; |
||
269 | |||
270 | /* this is an internal glue routine */ |
||
271 | /* Crafty's square index is the same as the EPD Kit square index */ |
||
272 | sq = index; |
||
273 | return sq; |
||
274 | } |
||
275 | |||
276 | /*--> EGMapToHostSq: map square index to host style */ |
||
277 | static siT EGMapToHostSq(sqT sq) { |
||
278 | siT index; |
||
279 | |||
280 | /* this is an internal glue routine */ |
||
281 | /* Crafty's square index is the same as the EPD Kit square index */ |
||
282 | index = sq; |
||
283 | return index; |
||
284 | } |
||
285 | |||
286 | /*--> EGMapFromHostScore: map score from host style */ |
||
287 | static cpevT EGMapFromHostScore(liT score) { |
||
288 | cpevT cpev; |
||
289 | liT distance; |
||
290 | |||
291 | /* this is an internal EPD glue routine */ |
||
292 | /* check for a forced mate */ |
||
293 | if (score >= (MATE - MAXPLY)) { |
||
294 | /* convert forced mate score */ |
||
295 | distance = (MATE - score) / 2; |
||
156 | pmbaty | 296 | cpev = (cpevT) synth_mate(distance); // Pierre-Marie Baty -- added type cast |
33 | pmbaty | 297 | } else if (score <= (MAXPLY - MATE)) { |
298 | /* convert forced loss score */ |
||
299 | distance = (MATE + score) / 2; |
||
156 | pmbaty | 300 | cpev = (cpevT) synth_loss(distance); // Pierre-Marie Baty -- added type cast |
33 | pmbaty | 301 | } else { |
302 | /* convert regular score */ |
||
156 | pmbaty | 303 | cpev = (cpevT) score; // Pierre-Marie Baty -- added type cast |
33 | pmbaty | 304 | }; |
305 | return cpev; |
||
306 | } |
||
307 | |||
308 | /*--> EGMapFromHostMove: map move from host style to EPD style */ |
||
309 | static mT EGMapFromHostMove(liT move) { |
||
310 | mT m; |
||
311 | siT flag; |
||
312 | |||
313 | /* this is an internal EPD glue routine */ |
||
314 | /* the EPD current position must be properly set */ |
||
315 | m.m_flag = 0; |
||
316 | m.m_frsq = EGMapFromHostSq((siT) From(move)); |
||
317 | m.m_tosq = EGMapFromHostSq((siT) To(move)); |
||
318 | m.m_frcp = EPDFetchCP(m.m_frsq); |
||
319 | m.m_tocp = EPDFetchCP(m.m_tosq); |
||
320 | /* determine special case move indication */ |
||
321 | flag = 0; |
||
322 | if (!flag) |
||
323 | if ((m.m_frcp == cp_wk) && (m.m_frsq == sq_e1) && (m.m_tosq == sq_g1)) { |
||
324 | m.m_scmv = scmv_cks; |
||
325 | flag = 1; |
||
326 | }; |
||
327 | if (!flag) |
||
328 | if ((m.m_frcp == cp_bk) && (m.m_frsq == sq_e8) && (m.m_tosq == sq_g8)) { |
||
329 | m.m_scmv = scmv_cks; |
||
330 | flag = 1; |
||
331 | }; |
||
332 | if (!flag) |
||
333 | if ((m.m_frcp == cp_wk) && (m.m_frsq == sq_e1) && (m.m_tosq == sq_c1)) { |
||
334 | m.m_scmv = scmv_cqs; |
||
335 | flag = 1; |
||
336 | }; |
||
337 | if (!flag) |
||
338 | if ((m.m_frcp == cp_bk) && (m.m_frsq == sq_e8) && (m.m_tosq == sq_c8)) { |
||
339 | m.m_scmv = scmv_cqs; |
||
340 | flag = 1; |
||
341 | }; |
||
342 | if (!flag) |
||
343 | if ((m.m_frcp == cp_wp) && (m.m_tosq == EPDFetchEPSQ())) { |
||
344 | m.m_scmv = scmv_epc; |
||
345 | flag = 1; |
||
346 | }; |
||
347 | if (!flag) |
||
348 | if ((m.m_frcp == cp_bp) && (m.m_tosq == EPDFetchEPSQ())) { |
||
349 | m.m_scmv = scmv_epc; |
||
350 | flag = 1; |
||
351 | }; |
||
352 | if (!flag) |
||
353 | if (Promote(move) != 0) { |
||
354 | switch (Promote(move)) { |
||
355 | case knight: |
||
356 | m.m_scmv = scmv_ppn; |
||
357 | break; |
||
358 | case bishop: |
||
359 | m.m_scmv = scmv_ppb; |
||
360 | break; |
||
361 | case rook: |
||
362 | m.m_scmv = scmv_ppr; |
||
363 | break; |
||
364 | case queen: |
||
365 | m.m_scmv = scmv_ppq; |
||
366 | break; |
||
367 | }; |
||
368 | flag = 1; |
||
369 | }; |
||
370 | if (!flag) |
||
371 | m.m_scmv = scmv_reg; |
||
372 | return m; |
||
373 | } |
||
374 | |||
375 | /*--> EGGetIndexedHostPosition: copy from indexed host position */ |
||
376 | static |
||
377 | void EGGetIndexedHostPosition(TREE * RESTRICT tree, siT posdex, int active) { |
||
378 | sqT sq; |
||
379 | rbT rb; |
||
380 | cT actc; |
||
381 | castT cast; |
||
382 | sqT epsq; |
||
383 | siT hmvc; |
||
384 | siT fmvn; |
||
385 | |||
386 | /* this is an internal EPD glue routine */ |
||
387 | /* |
||
388 | This routine is called from within the EPD glue to copy the host program's |
||
389 | current position at the given dpeth into the EPD Kit. Information about |
||
390 | the previous EPD Kit current position is lost. |
||
391 | */ |
||
392 | /* read from the host piece placement */ |
||
393 | for (sq = sq_a1; sq <= sq_h8; sq++) |
||
394 | rb.rbv[sq] = EGMapFromHostCP(tree->position.board[EGMapToHostSq(sq)]); |
||
395 | /* read from the host piece active color */ |
||
396 | actc = EGMapFromHostColor((siT) active); |
||
397 | /* read from the host piece castling availability */ |
||
398 | cast = 0; |
||
399 | switch (tree->status[posdex].castle[1]) { |
||
400 | case 0: |
||
401 | break; |
||
402 | case 1: |
||
403 | cast |= cf_wk; |
||
404 | break; |
||
405 | case 2: |
||
406 | cast |= cf_wq; |
||
407 | break; |
||
408 | case 3: |
||
409 | cast |= cf_wk | cf_wq; |
||
410 | break; |
||
411 | }; |
||
412 | switch (tree->status[posdex].castle[0]) { |
||
413 | case 0: |
||
414 | break; |
||
415 | case 1: |
||
416 | cast |= cf_bk; |
||
417 | break; |
||
418 | case 2: |
||
419 | cast |= cf_bq; |
||
420 | break; |
||
421 | case 3: |
||
422 | cast |= cf_bk | cf_bq; |
||
423 | break; |
||
424 | }; |
||
425 | /* read from the host piece en passant target square */ |
||
426 | epsq = sq_nil; |
||
427 | if (tree->status[posdex].enpassant_target != 0) { |
||
428 | sq = sq_a1; |
||
429 | while ((epsq == sq_nil) && (sq <= sq_h8)) |
||
430 | if (tree->status[posdex].enpassant_target == EGMapToHostSq(sq)) |
||
431 | epsq = sq; |
||
432 | else |
||
433 | sq++; |
||
434 | }; |
||
435 | /* read from the host halfmove clock */ |
||
436 | hmvc = tree->status[posdex].reversible; |
||
437 | /* read from the host fullmove number */ |
||
438 | fmvn = move_number; |
||
439 | /* set the EPD current position */ |
||
440 | EPDSetCurrentPosition(&rb, actc, cast, epsq, hmvc, fmvn); |
||
441 | return; |
||
442 | } |
||
443 | |||
444 | /*--> EGGetHostPosition: copy from host position to EPD Kit position */ |
||
445 | static |
||
446 | void EGGetHostPosition(void) { |
||
447 | /* this is an internal EPD glue routine */ |
||
448 | /* |
||
449 | This routine is called from within the EPD glue to copy the host program's |
||
450 | current position into the EPD Kit. Information about the previous EPD Kit |
||
451 | current position is lost. |
||
452 | */ |
||
453 | /* transfer from ply zero host position */ |
||
454 | EGGetIndexedHostPosition(block[0], 0, game_wtm); |
||
455 | return; |
||
456 | } |
||
457 | |||
458 | /*--> EGPutHostPosition: copy from EPD Kit position to host position */ |
||
459 | static |
||
460 | void EGPutHostPosition(void) { |
||
461 | sqT sq; |
||
462 | rbT rb; |
||
463 | cT actc; |
||
464 | castT cast; |
||
465 | sqT epsq; |
||
466 | siT hmvc; |
||
467 | siT fmvn; |
||
468 | siT index; |
||
469 | TREE *tree = block[0]; |
||
470 | |||
471 | /* this is an internal EPD glue routine */ |
||
472 | /* |
||
473 | This routine is called from within the EPD glue to copy the EPD Kit's current |
||
474 | position into the host program. If the previous host program current position |
||
475 | is different from the new position, then information about the previous host |
||
476 | program current position is lost. This means that the host program preserves |
||
477 | history information if and only if such preservation is appropriate. |
||
478 | Actually, the host position data is completely overwritten, so the above |
||
479 | comment is temporarily false, but will be true as developement proceeds. |
||
480 | */ |
||
481 | /* fetch the EPD current position data items */ |
||
482 | rb = *EPDFetchBoard(); |
||
483 | actc = EPDFetchACTC(); |
||
484 | cast = EPDFetchCAST(); |
||
485 | epsq = EPDFetchEPSQ(); |
||
486 | hmvc = EPDFetchHMVC(); |
||
487 | fmvn = EPDFetchFMVN(); |
||
488 | /* copy the board into the host board */ |
||
489 | for (sq = sq_a1; sq <= sq_h8; sq++) |
||
156 | pmbaty | 490 | tree->position.board[EGMapToHostSq(sq)] = (int8_t) EGMapToHostCP(rb.rbv[sq]); // Pierre-Marie Baty -- added type cast |
33 | pmbaty | 491 | /* copy the active color */ |
492 | game_wtm = EGMapToHostColor(actc); |
||
493 | /* copy the castling availibility */ |
||
494 | tree->status[0].castle[1] = 0; |
||
495 | if (cast & cf_wk) |
||
496 | tree->status[0].castle[1] += 1; |
||
497 | if (cast & cf_wq) |
||
498 | tree->status[0].castle[1] += 2; |
||
499 | tree->status[0].castle[0] = 0; |
||
500 | if (cast & cf_bk) |
||
501 | tree->status[0].castle[0] += 1; |
||
502 | if (cast & cf_bq) |
||
503 | tree->status[0].castle[0] += 2; |
||
504 | /* copy the en passant target square */ |
||
505 | if (epsq == sq_nil) |
||
506 | tree->status[0].enpassant_target = 0; |
||
507 | else |
||
156 | pmbaty | 508 | tree->status[0].enpassant_target = (uint8_t) EGMapToHostSq(epsq); // Pierre-Marie Baty -- added type cast |
33 | pmbaty | 509 | /* copy the halfmove clock */ |
156 | pmbaty | 510 | tree->status[0].reversible = (uint8_t) hmvc; // Pierre-Marie Baty -- added type cast |
33 | pmbaty | 511 | /* copy the fullmove number */ |
512 | move_number = fmvn; |
||
513 | /* set secondary host data items */ |
||
514 | SetChessBitBoards(tree); |
||
108 | pmbaty | 515 | rep_index = 0; |
33 | pmbaty | 516 | tree->rep_list[0] = HashKey; |
517 | moves_out_of_book = 0; |
||
518 | last_mate_score = 0; |
||
519 | /* clear the host killer information */ |
||
520 | for (index = 0; index < MAXPLY; index++) { |
||
521 | tree->killers[index].move1 = 0; |
||
522 | tree->killers[index].move2 = 0; |
||
523 | } |
||
524 | /* clear miscellaneous host items */ |
||
525 | ponder_move = 0; |
||
526 | last_pv.pathd = 0; |
||
527 | last_pv.pathl = 0; |
||
528 | over = 0; |
||
529 | return; |
||
530 | } |
||
531 | |||
532 | /*--> EGEncodeHostHistory: generate a string from host move history */ |
||
533 | static charptrT EGEncodeHostHistory(void) { |
||
534 | charptrT sptr; |
||
535 | gamptrT gamptr; |
||
536 | pgnstrT pgnstr; |
||
537 | mptrT mptr; |
||
538 | siT flag; |
||
539 | siT ch = 0; |
||
540 | charptrT s; |
||
541 | mT m; |
||
542 | |||
543 | /* this works only for games starting form the initial position */ |
||
544 | /* set default return value: failure */ |
||
545 | sptr = NULL; |
||
546 | /* set okay */ |
||
547 | flag = 1; |
||
548 | /* reset the EPD current position */ |
||
549 | EPDReset(); |
||
550 | /* make sure the host history file exists */ |
||
551 | if (history_file == NULL) |
||
552 | flag = 0; |
||
553 | else { |
||
554 | rewind(history_file); |
||
555 | ch = fgetc(history_file); |
||
556 | }; |
||
557 | /* open a game structure */ |
||
558 | gamptr = EPDGameOpen(); |
||
559 | /* copy tag data from default game structure */ |
||
560 | if (default_gamptr != NULL) |
||
561 | for (pgnstr = 0; pgnstr < pgnstrL; pgnstr++) |
||
562 | EPDPGNPutSTR(gamptr, pgnstr, EPDPGNGetSTR(default_gamptr, pgnstr)); |
||
563 | /* copy GTIM from default game structure */ |
||
564 | if (default_gamptr != NULL) |
||
565 | EPDPutGTIM(gamptr, EPDGetGTIM(default_gamptr)); |
||
566 | /* read the host history file */ |
||
567 | while (flag && (ch != EOF)) { |
||
568 | /* skip whitespace */ |
||
569 | while ((ch != EOF) && isspace(ch)) |
||
570 | ch = fgetc(history_file); |
||
571 | /* if not EOF, then construct a move */ |
||
572 | if (ch != EOF) { |
||
573 | /* attach the first character */ |
||
574 | s = EPDStringGrab(""); |
||
575 | s = EPDStringAppendChar(s, (char) ch); |
||
576 | ch = fgetc(history_file); |
||
577 | /* attach the remaining characters */ |
||
578 | while ((ch != EOF) && !isspace(ch)) { |
||
579 | s = EPDStringAppendChar(s, (char) ch); |
||
580 | ch = fgetc(history_file); |
||
581 | }; |
||
582 | /* match the move */ |
||
583 | EPDGenMoves(); |
||
584 | mptr = EPDSANDecodeAux(s, 0); |
||
585 | if (mptr == NULL) |
||
586 | flag = 0; |
||
587 | else { |
||
588 | /* execute the move */ |
||
589 | m = *mptr; |
||
590 | EPDGameAppendMove(gamptr, &m); |
||
591 | EPDExecuteUpdate(&m); |
||
592 | EPDCollapse(); |
||
593 | }; |
||
594 | /* release move buffer storage */ |
||
595 | EPDMemoryFree(s); |
||
596 | }; |
||
597 | }; |
||
598 | /* construct the string representation of the game */ |
||
599 | if (flag) |
||
600 | sptr = EPDPGNHistory(gamptr); |
||
601 | /* clean up if there was a problem */ |
||
602 | if (!flag) |
||
603 | if (sptr != NULL) { |
||
604 | EPDMemoryFree(sptr); |
||
605 | sptr = NULL; |
||
606 | }; |
||
607 | /* close the game structure */ |
||
608 | EPDGameClose(gamptr); |
||
609 | return sptr; |
||
610 | } |
||
611 | |||
612 | /*--> EGIterate: wrapper function for host Iterate() call */ |
||
613 | static |
||
614 | int EGIterate(siT wtm_flag, siT think_flag) { |
||
615 | int value; |
||
616 | epdptrT epdptr; |
||
617 | TREE *tree = block[0]; |
||
618 | |||
619 | EPDGenMoves(); |
||
620 | /* save current kit position */ |
||
621 | epdptr = EPDGetCurrentPosition(); |
||
622 | /* more than one move, execute regular search */ |
||
623 | value = Iterate(wtm_flag, think_flag, 0); |
||
624 | /* restore kit position */ |
||
625 | EPDRealize(epdptr); |
||
626 | EPDReleaseEPD(epdptr); |
||
627 | EPDGenMoves(); |
||
628 | last_pv = tree->pv[0]; |
||
629 | last_value = value; |
||
630 | return value; |
||
631 | } |
||
632 | |||
633 | /*--> EGCommHandler: callback routine for handling Duplex events */ |
||
634 | static epdptrT EGCommHandler(epdptrT epdptr0, siptrT flagptr) { |
||
635 | epdptrT epdptr1; |
||
636 | eopptrT eopptr; |
||
637 | charptrT s; |
||
638 | fptrT fptr; |
||
639 | mptrT mptr; |
||
640 | mT m; |
||
641 | sanT san; |
||
642 | int move; |
||
643 | char tv[tL]; |
||
644 | TREE *tree = block[0]; |
||
645 | |||
646 | /* set flag: no errors (so far) */ |
||
647 | *flagptr = 1; |
||
648 | /* clear result */ |
||
649 | epdptr1 = NULL; |
||
650 | /* process according to input referee command */ |
||
651 | switch (EPDExtractRefcomIndex(epdptr0)) { |
||
652 | case refcom_conclude: |
||
653 | /* end of game */ |
||
654 | s = EPDPGNHistory(default_gamptr); |
||
655 | if (s == NULL) |
||
656 | *flagptr = 0; |
||
657 | else { |
||
658 | /* append game to PGN output file */ |
||
156 | pmbaty | 659 | sprintf(tv, "c%05hd.pgn", ((siT) _getpid())); // Pierre-Marie Baty -- ISO C++ name conformance fix |
33 | pmbaty | 660 | fptr = fopen(tv, "a"); |
661 | if (fptr == NULL) |
||
662 | *flagptr = 0; |
||
663 | else { |
||
664 | fprintf(fptr, "%s", s); |
||
665 | fclose(fptr); |
||
666 | }; |
||
667 | EPDMemoryFree(s); |
||
668 | }; |
||
669 | /* clean up and remove the temporary history file */ |
||
670 | if (history_file != NULL) { |
||
671 | fclose(history_file); |
||
672 | history_file = NULL; |
||
673 | }; |
||
156 | pmbaty | 674 | sprintf(tv, "h%05hd.pml", ((siT) _getpid())); // Pierre-Marie Baty -- ISO C++ name conformance fix |
33 | pmbaty | 675 | remove(tv); |
676 | /* close the game structure */ |
||
677 | if (default_gamptr != NULL) { |
||
678 | EPDGameClose(default_gamptr); |
||
679 | default_gamptr = NULL; |
||
680 | }; |
||
681 | break; |
||
682 | case refcom_disconnect: |
||
683 | /* channel shutdown */ |
||
684 | /* clean up and remove the temporary history file */ |
||
685 | if (history_file != NULL) { |
||
686 | fclose(history_file); |
||
687 | history_file = NULL; |
||
688 | }; |
||
156 | pmbaty | 689 | sprintf(tv, "h%05hd.pml", ((siT) _getpid())); // Pierre-Marie Baty -- ISO C++ name conformance fix |
33 | pmbaty | 690 | remove(tv); |
691 | /* ensure game structure is closed */ |
||
692 | if (default_gamptr != NULL) { |
||
693 | EPDGameClose(default_gamptr); |
||
694 | default_gamptr = NULL; |
||
695 | }; |
||
696 | break; |
||
697 | case refcom_execute: |
||
698 | /* execute the supplied move */ |
||
699 | eopptr = EPDLocateEOPCode(epdptr0, epdso_sm); |
||
108 | pmbaty | 700 | move = InputMove(tree, 0, game_wtm, 0, 0, eopptr->eop_headeov->eov_str); |
33 | pmbaty | 701 | if (history_file) { |
702 | fseek(history_file, ((((move_number - 1) * 2) + 1 - game_wtm) * 10), |
||
703 | SEEK_SET); |
||
704 | fprintf(history_file, "%9s\n", eopptr->eop_headeov->eov_str); |
||
705 | } |
||
108 | pmbaty | 706 | MakeMoveRoot(tree, game_wtm, move); |
33 | pmbaty | 707 | game_wtm = Flip(game_wtm); |
708 | if (game_wtm) |
||
709 | move_number++; |
||
710 | /* execute the move in the EPD Kit */ |
||
711 | EPDGenMoves(); |
||
712 | mptr = EPDSANDecodeAux(eopptr->eop_headeov->eov_str, 0); |
||
713 | m = *mptr; |
||
714 | EPDGameAppendMove(default_gamptr, &m); |
||
715 | EPDExecuteUpdate(&m); |
||
716 | EPDCollapse(); |
||
717 | break; |
||
718 | case refcom_fault: |
||
719 | /* a problem occurred */ |
||
720 | EGPL("EPDCommHandler: refcom fault"); |
||
721 | *flagptr = 0; |
||
722 | break; |
||
723 | case refcom_inform: |
||
724 | /* process incidental information */ |
||
725 | EPDCopyOutPTP(default_gamptr, epdptr0); |
||
726 | /* update the current game termination marker */ |
||
727 | s = EPDPGNGetSTR(default_gamptr, pgnstr_result); |
||
728 | if ((s == NULL) || (strcmp(s, "*") == 0)) |
||
729 | EPDPutGTIM(default_gamptr, gtim_u); |
||
730 | else if (strcmp(s, "1-0") == 0) |
||
731 | EPDPutGTIM(default_gamptr, gtim_w); |
||
732 | else if (strcmp(s, "0-1") == 0) |
||
733 | EPDPutGTIM(default_gamptr, gtim_b); |
||
734 | else if (strcmp(s, "1/2-1/2") == 0) |
||
735 | EPDPutGTIM(default_gamptr, gtim_d); |
||
736 | break; |
||
737 | case refcom_respond: |
||
738 | /* execute the supplied move (if any) */ |
||
739 | eopptr = EPDLocateEOPCode(epdptr0, epdso_sm); |
||
740 | if (eopptr != NULL) { |
||
741 | move = |
||
108 | pmbaty | 742 | InputMove(tree, 0, game_wtm, 0, 0, eopptr->eop_headeov->eov_str); |
33 | pmbaty | 743 | if (history_file) { |
744 | fseek(history_file, ((((move_number - 1) * 2) + 1 - game_wtm) * 10), |
||
745 | SEEK_SET); |
||
746 | fprintf(history_file, "%9s\n", eopptr->eop_headeov->eov_str); |
||
747 | } |
||
108 | pmbaty | 748 | MakeMoveRoot(tree, game_wtm, move); |
33 | pmbaty | 749 | game_wtm = Flip(game_wtm); |
750 | if (game_wtm) |
||
751 | move_number++; |
||
752 | /* execute the move in the EPD Kit */ |
||
753 | EPDGenMoves(); |
||
754 | mptr = EPDSANDecodeAux(eopptr->eop_headeov->eov_str, 0); |
||
755 | m = *mptr; |
||
756 | EPDGameAppendMove(default_gamptr, &m); |
||
757 | EPDExecuteUpdate(&m); |
||
758 | EPDCollapse(); |
||
759 | }; |
||
760 | /* calculate move + respond */ |
||
761 | EPDGenMoves(); |
||
762 | if (EPDFetchMoveCount() > 0) { |
||
763 | /* at least one move exists, set up for search */ |
||
764 | ponder_move = 0; |
||
765 | thinking = 1; |
||
766 | last_pv.pathd = 0; |
||
767 | last_pv.pathl = 0; |
||
768 | tree->status[1] = tree->status[0]; |
||
769 | /* search */ |
||
108 | pmbaty | 770 | EGIterate((siT) game_wtm, (siT) think); |
33 | pmbaty | 771 | /* process search result */ |
108 | pmbaty | 772 | strcpy(tv, OutputMove(tree, 0, game_wtm, last_pv.path[1])); |
33 | pmbaty | 773 | move = last_pv.path[1]; |
774 | /* locate SAN move */ |
||
775 | mptr = EPDSANDecodeAux(tv, 0); |
||
776 | m = *mptr; |
||
777 | EPDSANEncode(&m, san); |
||
778 | /* output to temporary history file */ |
||
779 | if (history_file) { |
||
780 | fseek(history_file, ((((move_number - 1) * 2) + 1 - game_wtm) * 10), |
||
781 | SEEK_SET); |
||
782 | fprintf(history_file, "%9s\n", san); |
||
783 | } |
||
784 | /* update host position */ |
||
108 | pmbaty | 785 | MakeMoveRoot(tree, game_wtm, move); |
33 | pmbaty | 786 | game_wtm = Flip(game_wtm); |
787 | if (game_wtm) |
||
788 | move_number++; |
||
789 | /* create reply EPD structure */ |
||
790 | epdptr1 = EPDGetCurrentPosition(); |
||
791 | /* add in referee request */ |
||
792 | EPDAddOpSym(epdptr1, epdso_refreq, EPDFetchRefreqStr(refreq_reply)); |
||
793 | /* add in supplied move */ |
||
794 | EPDAddOpSym(epdptr1, epdso_sm, san); |
||
795 | /* execute the move in the EPD Kit */ |
||
796 | mptr = EPDSANDecodeAux(san, 0); |
||
797 | m = *mptr; |
||
798 | EPDGameAppendMove(default_gamptr, &m); |
||
799 | EPDExecuteUpdate(&m); |
||
800 | EPDCollapse(); |
||
801 | } else { |
||
802 | /* no moves exist, so no move response possible */ |
||
803 | epdptr1 = EPDGetCurrentPosition(); |
||
804 | eopptr = EPDCreateEOPCode(epdso_refreq); |
||
805 | EPDAppendEOV(eopptr, |
||
806 | EPDCreateEOVSym(EPDFetchRefreqStr(refreq_reply))); |
||
807 | EPDAppendEOP(epdptr1, eopptr); |
||
808 | }; |
||
809 | break; |
||
810 | case refcom_reset: |
||
811 | /* reset EPD Kit */ |
||
812 | EPDReset(); |
||
813 | /* reset host for a new game */ |
||
814 | ponder = 0; |
||
815 | ponder_move = 0; |
||
816 | last_pv.pathd = 0; |
||
817 | last_pv.pathl = 0; |
||
818 | InitializeChessBoard(tree); |
||
108 | pmbaty | 819 | InitializeHashTables(0); |
33 | pmbaty | 820 | game_wtm = 1; |
821 | move_number = 1; |
||
822 | /* open the temporary history file */ |
||
823 | if (history_file != NULL) { |
||
824 | fclose(history_file); |
||
825 | history_file = NULL; |
||
826 | }; |
||
156 | pmbaty | 827 | sprintf(tv, "h%05hd.pml", ((siT) _getpid())); // Pierre-Marie Baty -- ISO C++ name conformance fix |
33 | pmbaty | 828 | remove(tv); |
829 | history_file = fopen(tv, "w+"); |
||
830 | /* open the current game structure */ |
||
831 | if (default_gamptr != NULL) |
||
832 | EPDGameClose(default_gamptr); |
||
833 | default_gamptr = EPDGameOpen(); |
||
834 | break; |
||
835 | case refcom_nil: |
||
836 | *flagptr = 0; |
||
837 | break; |
||
838 | }; |
||
839 | /* clean up if there was a problem */ |
||
840 | if (!(*flagptr)) |
||
841 | if (epdptr1 != NULL) { |
||
842 | EPDReleaseEPD(epdptr1); |
||
843 | epdptr1 = NULL; |
||
844 | }; |
||
845 | return epdptr1; |
||
846 | } |
||
847 | |||
848 | /*--> EGProcessAPGN: process the EG command epdapgn */ |
||
849 | static siT EGProcessAPGN(void) { |
||
850 | siT flag; |
||
851 | charptrT s; |
||
852 | fptrT fptr; |
||
853 | |||
854 | /* this is an internal EPD glue routine */ |
||
855 | /* set the default return value: success */ |
||
856 | flag = 1; |
||
857 | /* parameter count check */ |
||
858 | if (EPDTokenCount() != 2) { |
||
859 | EGPL("This command takes one parameter."); |
||
860 | flag = 0; |
||
861 | }; |
||
862 | /* process the epdapgn command */ |
||
863 | if (flag) { |
||
864 | s = EGEncodeHostHistory(); |
||
865 | if (s == NULL) |
||
866 | flag = 0; |
||
867 | else { |
||
868 | fptr = fopen(EPDTokenFetch(1), "a"); |
||
869 | if (fptr == NULL) |
||
870 | flag = 0; |
||
871 | else { |
||
872 | fprintf(fptr, "%s", s); |
||
873 | fclose(fptr); |
||
874 | }; |
||
875 | EPDMemoryFree(s); |
||
876 | }; |
||
877 | }; |
||
878 | return flag; |
||
879 | } |
||
880 | |||
881 | /*--> EGProcessBFIX: process the EG command epdbfix */ |
||
882 | static siT EGProcessBFIX(void) { |
||
883 | siT flag; |
||
884 | fptrT fptr0, fptr1; |
||
885 | eopptrT eopptr; |
||
886 | epdptrT epdptr, nptr; |
||
887 | charptrT s; |
||
888 | char ev[epdL]; |
||
889 | |||
890 | /* this is an internal EPD glue routine */ |
||
891 | /* set the default return value: success */ |
||
892 | flag = 1; |
||
893 | /* clear the file pointers */ |
||
894 | fptr0 = fptr1 = NULL; |
||
895 | /* parameter count check */ |
||
896 | if (EPDTokenCount() != 3) { |
||
897 | EGPL("This command takes two parameters"); |
||
898 | flag = 0; |
||
899 | }; |
||
900 | /* set up the input file */ |
||
901 | if (flag) { |
||
902 | fptr0 = fopen(EPDTokenFetch(1), "r"); |
||
903 | if (fptr0 == NULL) { |
||
904 | sprintf(tbufv, "Can't open %s for reading\n", EPDTokenFetch(1)); |
||
905 | EGPrintTB(); |
||
906 | flag = 0; |
||
907 | }; |
||
908 | }; |
||
909 | /* set up the output file */ |
||
910 | if (flag) { |
||
911 | fptr1 = fopen(EPDTokenFetch(2), "w"); |
||
912 | if (fptr1 == NULL) { |
||
913 | sprintf(tbufv, "Can't open %s for writing\n", EPDTokenFetch(2)); |
||
914 | EGPrintTB(); |
||
915 | flag = 0; |
||
916 | }; |
||
917 | }; |
||
918 | /* scan the file */ |
||
919 | if (flag) |
||
920 | while (flag && (fgets(ev, (epdL - 1), fptr0) != NULL)) { |
||
921 | /* decode the record into an EPD structure */ |
||
922 | epdptr = EPDDecode(ev); |
||
923 | /* check record decode validity */ |
||
924 | if (epdptr == NULL) |
||
925 | flag = 0; |
||
926 | else { |
||
927 | /* clone the input EPD structure base */ |
||
928 | nptr = EPDCloneEPDBase(epdptr); |
||
929 | /* copy the ce operation */ |
||
930 | eopptr = EPDLocateEOPCode(epdptr, epdso_ce); |
||
931 | if (eopptr != NULL) |
||
932 | EPDAppendEOP(nptr, EPDCloneEOP(eopptr)); |
||
933 | /* copy the pv operation */ |
||
934 | eopptr = EPDLocateEOPCode(epdptr, epdso_pv); |
||
935 | if (eopptr != NULL) |
||
936 | EPDAppendEOP(nptr, EPDCloneEOP(eopptr)); |
||
937 | /* output the new EPD strucutre */ |
||
938 | s = EPDEncode(nptr); |
||
939 | fprintf(fptr1, "%s\n", s); |
||
940 | EPDMemoryFree(s); |
||
941 | /* deallocate both EPD structures */ |
||
942 | EPDReleaseEPD(epdptr); |
||
943 | EPDReleaseEPD(nptr); |
||
944 | }; |
||
945 | }; |
||
946 | /* ensure file close */ |
||
947 | if (fptr0 != NULL) |
||
948 | fclose(fptr0); |
||
949 | if (fptr1 != NULL) |
||
950 | fclose(fptr1); |
||
951 | return flag; |
||
952 | } |
||
953 | |||
954 | /*--> EGProcessCICS: process the EG command epdcics */ |
||
955 | static siT EGProcessCICS(void) { |
||
956 | siT flag; |
||
957 | |||
958 | /* this is an internal EPD glue routine */ |
||
959 | /* set the default return value: success */ |
||
960 | flag = 1; |
||
961 | /* parameter count check */ |
||
962 | if (EPDTokenCount() != 3) { |
||
963 | EGPL("This command takes two parameters"); |
||
964 | flag = 0; |
||
965 | }; |
||
966 | /* process the epdcics command */ |
||
967 | if (flag) { |
||
968 | EGPL("This command is not yet implemented."); |
||
969 | flag = 0; |
||
970 | }; |
||
971 | return flag; |
||
972 | } |
||
973 | |||
974 | /*--> EGProcessCOMM: process the EG command epdcomm */ |
||
975 | static siT EGProcessCOMM(void) { |
||
976 | siT flag; |
||
977 | fptrT save_history_file; |
||
978 | gamptrT save_default_gamptr; |
||
979 | |||
980 | /* this is an internal EPD glue routine */ |
||
981 | /* set the default return value: success */ |
||
982 | flag = 1; |
||
983 | /* parameter count check */ |
||
984 | if (EPDTokenCount() != 2) { |
||
985 | EGPL("This command takes one parameter."); |
||
986 | flag = 0; |
||
987 | }; |
||
988 | /* process the epdcomm command */ |
||
989 | if (flag) { |
||
990 | /* save the history file pointer */ |
||
991 | save_history_file = history_file; |
||
992 | history_file = NULL; |
||
993 | /* save the game structure */ |
||
994 | save_default_gamptr = default_gamptr; |
||
995 | default_gamptr = NULL; |
||
996 | /* process via callback */ |
||
997 | EGPL("Duplex slave mode begin"); |
||
998 | flag = EPDComm(EGCommHandler, EPDTokenFetch(1)); |
||
999 | EGPL("Duplex slave mode end"); |
||
1000 | /* restore the game structure */ |
||
1001 | if (default_gamptr != NULL) { |
||
1002 | EPDGameClose(default_gamptr); |
||
1003 | default_gamptr = NULL; |
||
1004 | }; |
||
1005 | default_gamptr = save_default_gamptr; |
||
1006 | /* restore the history file pointer */ |
||
1007 | history_file = save_history_file; |
||
1008 | }; |
||
1009 | return flag; |
||
1010 | } |
||
1011 | |||
1012 | /*--> EGProcessDPGN: process the EG command epddpgn */ |
||
1013 | static siT EGProcessDPGN(void) { |
||
1014 | siT flag; |
||
1015 | charptrT s; |
||
1016 | |||
1017 | /* this is an internal EPD glue routine */ |
||
1018 | /* set the default return value: success */ |
||
1019 | flag = 1; |
||
1020 | /* parameter count check */ |
||
1021 | if (EPDTokenCount() != 1) { |
||
1022 | EGPL("This command takes no parameters."); |
||
1023 | flag = 0; |
||
1024 | }; |
||
1025 | /* process the epddpgn command */ |
||
1026 | if (flag) { |
||
1027 | s = EGEncodeHostHistory(); |
||
1028 | if (s == NULL) |
||
1029 | flag = 0; |
||
1030 | else { |
||
1031 | EGPrint(s); |
||
1032 | EPDMemoryFree(s); |
||
1033 | }; |
||
1034 | }; |
||
1035 | return flag; |
||
1036 | } |
||
1037 | |||
1038 | /*--> EGProcessDSML: process the EG command epddsml */ |
||
1039 | static siT EGProcessDSML(void) { |
||
1040 | siT flag; |
||
1041 | siT count, index; |
||
1042 | siT length, column; |
||
1043 | mT m; |
||
1044 | sanT san; |
||
1045 | |||
1046 | /* this is an internal EPD glue routine */ |
||
1047 | /* set the default return value: success */ |
||
1048 | flag = 1; |
||
1049 | /* parameter count check */ |
||
1050 | if (EPDTokenCount() != 1) { |
||
1051 | EGPL("This command takes no parameters."); |
||
1052 | flag = 0; |
||
1053 | }; |
||
1054 | /* process the epddsml command */ |
||
1055 | if (flag) { |
||
1056 | /* copy the current host position into the EPD Kit */ |
||
1057 | EGGetHostPosition(); |
||
1058 | /* generate and count */ |
||
1059 | EPDGenMoves(); |
||
1060 | count = EPDFetchMoveCount(); |
||
1061 | switch (count) { |
||
1062 | case 0: |
||
1063 | EGPL("No moves are available."); |
||
1064 | break; |
||
1065 | case 1: |
||
1066 | EGPL("There is 1 move available."); |
||
1067 | break; |
||
1068 | default: |
||
1069 | sprintf(tbufv, "There are %hd moves available.\n", count); |
||
1070 | EGPrintTB(); |
||
1071 | break; |
||
1072 | }; |
||
1073 | /* list moves */ |
||
1074 | if (count > 0) { |
||
1075 | column = 0; |
||
1076 | EPDSortSAN(); |
||
1077 | for (index = 0; index < count; index++) { |
||
1078 | m = *EPDFetchMove(index); |
||
1079 | EPDSANEncode(&m, san); |
||
156 | pmbaty | 1080 | length = (siT) strlen(san); // Pierre-Marie Baty -- added type cast |
33 | pmbaty | 1081 | if ((column + 1 + length) < columnL) { |
1082 | sprintf(tbufv, " %s", san); |
||
1083 | EGPrintTB(); |
||
1084 | column += 1 + length; |
||
1085 | } else { |
||
1086 | EGPrint("\n"); |
||
1087 | EGPrint(san); |
||
1088 | column = length; |
||
1089 | }; |
||
1090 | }; |
||
1091 | if (column > 0) |
||
1092 | EGPrint("\n"); |
||
1093 | }; |
||
1094 | }; |
||
1095 | return flag; |
||
1096 | } |
||
1097 | |||
1098 | /*--> EGProcessDSTR: process the EG command epddstr */ |
||
1099 | static siT EGProcessDSTR(void) { |
||
1100 | siT flag; |
||
1101 | charptrT s; |
||
1102 | |||
1103 | /* this is an internal EPD glue routine */ |
||
1104 | /* set the default return value: success */ |
||
1105 | flag = 1; |
||
1106 | /* parameter count check */ |
||
1107 | if (EPDTokenCount() != 1) { |
||
1108 | EGPL("This command takes no parameters."); |
||
1109 | flag = 0; |
||
1110 | }; |
||
1111 | /* process the epddstr command */ |
||
1112 | if (flag) { |
||
1113 | s = EPDPGNGenSTR(default_gamptr); |
||
1114 | EGPrint(s); |
||
1115 | EPDMemoryFree(s); |
||
1116 | }; |
||
1117 | return flag; |
||
1118 | } |
||
1119 | |||
1120 | /*--> EGProcessDTPV: process the EG command epddtpv */ |
||
1121 | static siT EGProcessDTPV(void) { |
||
1122 | siT flag; |
||
1123 | pgnstrT pgnstr; |
||
1124 | |||
1125 | /* this is an internal EPD glue routine */ |
||
1126 | /* set the default return value: success */ |
||
1127 | flag = 1; |
||
1128 | /* parameter count check */ |
||
1129 | if (EPDTokenCount() != 2) { |
||
1130 | EGPL("This command takes one parameter."); |
||
1131 | flag = 0; |
||
1132 | }; |
||
1133 | /* process the epddtpv command */ |
||
1134 | if (flag) { |
||
1135 | pgnstr = EPDPGNFetchTagIndex(EPDTokenFetch(1)); |
||
1136 | if (pgnstr == pgnstr_nil) { |
||
1137 | EGPL("Unknown tag name; available tag names are:"); |
||
1138 | for (pgnstr = 0; pgnstr < pgnstrL; pgnstr++) { |
||
1139 | EGPrint(" "); |
||
1140 | EGPrint(EPDPGNFetchTagName(pgnstr)); |
||
1141 | }; |
||
1142 | EGPrint("\n"); |
||
1143 | flag = 0; |
||
1144 | } else { |
||
1145 | sprintf(tbufv, "[%s \"%s\"]\n", EPDPGNFetchTagName(pgnstr), |
||
1146 | EPDPGNGetSTR(default_gamptr, pgnstr)); |
||
1147 | EGPrintTB(); |
||
1148 | }; |
||
1149 | }; |
||
1150 | return flag; |
||
1151 | } |
||
1152 | |||
1153 | /*--> EGProcessENUM: process the EG command epdenum */ |
||
1154 | static siT EGProcessENUM(void) { |
||
1155 | siT flag; |
||
1156 | liT total; |
||
1157 | |||
1158 | /* this is an internal EPD glue routine */ |
||
1159 | /* set the default return value: success */ |
||
1160 | flag = 1; |
||
1161 | /* parameter count check */ |
||
1162 | if (EPDTokenCount() != 4) { |
||
1163 | EGPL("This command takes three parameters"); |
||
1164 | flag = 0; |
||
1165 | }; |
||
1166 | /* process the epdenum command */ |
||
1167 | if (flag) { |
||
1168 | flag = |
||
1169 | EPDEnumerateFile((siT) atol(EPDTokenFetch(1)), EPDTokenFetch(2), |
||
1170 | EPDTokenFetch(3), &total); |
||
1171 | if (flag) { |
||
1172 | sprintf(tbufv, "Enumeration to depth %ld totals %ld\n", |
||
1173 | atol(EPDTokenFetch(1)), total); |
||
1174 | EGPrintTB(); |
||
1175 | }; |
||
1176 | }; |
||
1177 | return flag; |
||
1178 | } |
||
1179 | |||
1180 | /*--> EGProcessHELP: process the EG command epdhelp */ |
||
1181 | static siT EGProcessHELP(void) { |
||
1182 | siT flag; |
||
1183 | siT i; |
||
1184 | egcommT egcomm; |
||
1185 | |||
1186 | /* this is an internal EPD glue routine */ |
||
1187 | /* set the default return value: success */ |
||
1188 | flag = 1; |
||
1189 | /* parameter count check */ |
||
1190 | if (EPDTokenCount() != 1) { |
||
1191 | EGPL("This command takes no parameters."); |
||
1192 | flag = 0; |
||
1193 | }; |
||
1194 | /* process the epdhelp command */ |
||
1195 | if (flag) { |
||
1196 | /* it is not clear exactly why the next statment is needed */ |
||
108 | pmbaty | 1197 | getchar(); |
33 | pmbaty | 1198 | /* list all the commands */ |
1199 | egcomm = 0; |
||
1200 | while (egcomm < egcommL) { |
||
1201 | EGPL("Available EPD glue command list"); |
||
1202 | EGPL("-------------------------------"); |
||
1203 | i = 0; |
||
1204 | while ((egcomm < egcommL) && (i < 10)) { |
||
1205 | sprintf(tbufv, "%s: %s\n", egcommstrv[egcomm], eghelpstrv[egcomm]); |
||
1206 | EGPrintTB(); |
||
1207 | i++; |
||
1208 | egcomm++; |
||
1209 | }; |
||
1210 | if (egcomm < egcommL) { |
||
1211 | EGPL(""); |
||
1212 | EGPL("Press <return> for more command help"); |
||
108 | pmbaty | 1213 | getchar(); |
33 | pmbaty | 1214 | EGPL(""); |
1215 | }; |
||
1216 | }; |
||
1217 | }; |
||
1218 | return flag; |
||
1219 | } |
||
1220 | |||
1221 | /*--> EGProcessLINK: process the EG command epdlink */ |
||
1222 | static siT EGProcessLINK(void) { |
||
1223 | siT flag; |
||
1224 | |||
1225 | /* this is an internal EPD glue routine */ |
||
1226 | /* set the default return value: success */ |
||
1227 | flag = 1; |
||
1228 | /* parameter count check */ |
||
1229 | if (EPDTokenCount() != 3) { |
||
1230 | EGPL("This command takes two parameters"); |
||
1231 | flag = 0; |
||
1232 | }; |
||
1233 | /* process the epdlink command */ |
||
1234 | if (flag) { |
||
1235 | EGPL("This command is not yet implemented."); |
||
1236 | flag = 0; |
||
1237 | }; |
||
1238 | return flag; |
||
1239 | } |
||
1240 | |||
1241 | /*--> EGProcessLPGN: process the EG command epdlpgn */ |
||
1242 | static siT EGProcessLPGN(void) { |
||
1243 | siT flag; |
||
1244 | |||
1245 | /* this is an internal EPD glue routine */ |
||
1246 | /* set the default return value: success */ |
||
1247 | flag = 1; |
||
1248 | /* parameter count check */ |
||
1249 | if (EPDTokenCount() != 2) { |
||
1250 | EGPL("This command takes one parameter."); |
||
1251 | flag = 0; |
||
1252 | }; |
||
1253 | /* process the epdlpgn command */ |
||
1254 | if (flag) { |
||
1255 | EGPL("This command is not yet implemented."); |
||
1256 | flag = 0; |
||
1257 | }; |
||
1258 | return flag; |
||
1259 | } |
||
1260 | |||
1261 | /*--> EGProcessLREC: process the EG command epdlrec */ |
||
1262 | static siT EGProcessLREC(void) { |
||
1263 | siT flag; |
||
1264 | fptrT fptr; |
||
1265 | liT i, n; |
||
1266 | epdptrT epdptr; |
||
1267 | char ev[epdL]; |
||
1268 | |||
1269 | /* this is an internal EPD glue routine */ |
||
1270 | /* set the default return value: success */ |
||
1271 | flag = 1; |
||
1272 | /* parameter count check */ |
||
1273 | if (EPDTokenCount() != 3) { |
||
1274 | EGPL("This command takes two parameters"); |
||
1275 | flag = 0; |
||
1276 | }; |
||
1277 | /* process the epdlrec command */ |
||
1278 | if (flag) { |
||
1279 | fptr = fopen(EPDTokenFetch(1), "r"); |
||
1280 | if (fptr == NULL) |
||
1281 | flag = 0; |
||
1282 | else { |
||
1283 | /* read the indicated record */ |
||
1284 | i = 0; |
||
1285 | n = atol(EPDTokenFetch(2)); |
||
1286 | while (flag && (i < n)) |
||
1287 | if (fgets(ev, (epdL - 1), fptr) == NULL) |
||
1288 | flag = 0; |
||
1289 | else |
||
1290 | i++; |
||
1291 | fclose(fptr); |
||
1292 | /* set the current position */ |
||
1293 | if (flag) { |
||
1294 | epdptr = EPDDecode(ev); |
||
1295 | if (epdptr == NULL) |
||
1296 | flag = 0; |
||
1297 | else { |
||
1298 | EPDRealize(epdptr); |
||
1299 | EPDReleaseEPD(epdptr); |
||
1300 | EGPutHostPosition(); |
||
1301 | }; |
||
1302 | }; |
||
1303 | }; |
||
1304 | }; |
||
1305 | return flag; |
||
1306 | } |
||
1307 | |||
1308 | /*--> EGProcessMORE: process the EG command epdmore */ |
||
1309 | static siT EGProcessMORE(void) { |
||
1310 | siT flag; |
||
1311 | |||
1312 | /* this is an internal EPD glue routine */ |
||
1313 | /* set the default return value: success */ |
||
1314 | flag = 1; |
||
1315 | /* parameter count check */ |
||
1316 | if (EPDTokenCount() != 2) { |
||
1317 | EGPL("This command takes one parameter."); |
||
1318 | flag = 0; |
||
1319 | }; |
||
1320 | /* process the epdmore command */ |
||
1321 | if (flag) |
||
1322 | switch (EGLocateCommand(EPDTokenFetch(1))) { |
||
1323 | case egcomm_epdapgn: |
||
1324 | EGPL("epdapgn: Append the game to a PGN file"); |
||
1325 | EGPL(""); |
||
1326 | EGPL("This command is used to append the current game to a file"); |
||
1327 | EGPL("using Portable Game Notation (PGN) format. It takes one"); |
||
1328 | EGPL("parameter which is the file name of interest."); |
||
1329 | break; |
||
1330 | case egcomm_epdbfix: |
||
1331 | EGPL("epdbfix: Fix an EPD file for import into Bookup"); |
||
1332 | EGPL(""); |
||
1333 | EGPL("This command takes two parameters. Both parameters are"); |
||
1334 | EGPL("names of EPD files. The first is an existing EPD file with"); |
||
1335 | EGPL("analysis data. The second is the EPD file to be created"); |
||
1336 | EGPL("from the first by removing all operations except the ce and"); |
||
1337 | EGPL("pv operations. This second file can then be imported into"); |
||
1338 | EGPL("the Bookup program."); |
||
1339 | break; |
||
1340 | case egcomm_epdcert: |
||
1341 | EGPL("epdcert: Try to display a certain evaluation"); |
||
1342 | EGPL(""); |
||
1343 | EGPL("This command takes no parameters. The current position is"); |
||
1344 | EGPL("examined for legality, and if legal, an attempt is made to"); |
||
1345 | EGPL("return an absolute certain evaluation. An absolute certain"); |
||
1346 | EGPL("evaluation is available for checkmates, stalemates, draws by"); |
||
1347 | EGPL("insufficient material, and mate in one positions. Also,"); |
||
1348 | EGPL("if there are only a few chessmen on the board, then the"); |
||
1349 | EGPL("current position is used as an index into an external file"); |
||
1350 | EGPL("corresponding to the active color and the distribution of"); |
||
1351 | EGPL("pieces. If the appropriate external file is available, the"); |
||
1352 | EGPL("position is evaluated by a single file look-up operation."); |
||
1353 | EGPL("These files are called tablebases and they should appear in"); |
||
1354 | EGPL("the TB subdirectory of the current working directory. These"); |
||
1355 | EGPL("files may be obtained via ftp from the chess.onenet.net site"); |
||
1356 | EGPL("in the pub/chess/TB directory."); |
||
1357 | break; |
||
1358 | case egcomm_epdcics: |
||
1359 | EGPL("epdcics: Slave to an Internet Chess Server"); |
||
1360 | EGPL(""); |
||
1361 | EGPL("This command causes the host program Crafty to becomed slaved"); |
||
1362 | EGPL("to an Internet Chess Server (ICS). This means that the host"); |
||
1363 | EGPL("program will follow directions from the indicated Internet"); |
||
1364 | EGPL("Chess Server until either the ICS tells the program to exit"); |
||
1365 | EGPL("slave mode or the program is interrupted by the user. This"); |
||
1366 | EGPL("command takes two parameters. The first is the name of the"); |
||
1367 | EGPL("machine running the ICS and the second is the port number in"); |
||
1368 | EGPL("use by the ICS."); |
||
1369 | break; |
||
1370 | case egcomm_epdcomm: |
||
1371 | EGPL("epdcomm: Slave to the Duplex referee program"); |
||
1372 | EGPL(""); |
||
1373 | EGPL("This command causes the host program Crafty to becomed slaved"); |
||
1374 | EGPL("to the simple referee program Duplex. Duplex must be started"); |
||
1375 | EGPL("prior to entering this command. Once the host program is"); |
||
1376 | EGPL("slaved to Duplex, it will remain so until it is instructed"); |
||
1377 | EGPL("by Duplex to terminate or is interrupted by the user. This"); |
||
1378 | EGPL("command is used to support the Duplex function of controlling"); |
||
1379 | EGPL("automatic play between two host programs on the same Unix"); |
||
1380 | EGPL("system. The communication used is based on named pipes which"); |
||
1381 | EGPL("are special files that support FIFO data operation. This"); |
||
1382 | EGPL("command takes one parameter which is a base name for a pair"); |
||
1383 | EGPL("of named pipes. The host output pipe name is generated by"); |
||
1384 | EGPL("adding a \".pc0\" suffix to the base name and the host input"); |
||
1385 | EGPL("pipe name is generated by addint a \".pc1\" suffix to the"); |
||
1386 | EGPL("base name. (Both pipe files are created and later removed"); |
||
1387 | EGPL("automatically by the Duplex program.) The Duplex program is"); |
||
1388 | EGPL("given three parameters to run a series of games between two"); |
||
1389 | EGPL("host programs: the first is the base name given to the first"); |
||
1390 | EGPL("host program, the second is the base name given to the second"); |
||
1391 | EGPL("host program, and the third is the count of the number of"); |
||
1392 | EGPL("games to be played."); |
||
1393 | break; |
||
1394 | case egcomm_epddpgn: |
||
1395 | EGPL("epddpgn: Display the game using PGN"); |
||
1396 | EGPL(""); |
||
1397 | EGPL("This command displays the current game using Portable Game"); |
||
1398 | EGPL("Notation (PGN). It takes no parameters."); |
||
1399 | break; |
||
1400 | case egcomm_epddsml: |
||
1401 | EGPL("epddsml: Display SAN move list"); |
||
1402 | EGPL(""); |
||
1403 | EGPL("This command displays the ASCII sorted list of available"); |
||
1404 | EGPL("moves using SAN (Standard Algebraic Notation). The count"); |
||
1405 | EGPL("of moves is also displayed. This command takes no"); |
||
1406 | EGPL("parameters."); |
||
1407 | break; |
||
1408 | case egcomm_epddstr: |
||
1409 | EGPL("epddstr: Display the PGN Seven Tag Roster"); |
||
1410 | EGPL(""); |
||
1411 | EGPL("This command displays the current values of each of the tag"); |
||
1412 | EGPL("pairs of the PGN Seven Tag Roster. These tags are: Event, "); |
||
1413 | EGPL("Site, Date, Round, White, Black, and Result. This command"); |
||
1414 | EGPL("takes no parameters."); |
||
1415 | break; |
||
1416 | case egcomm_epddtpv: |
||
1417 | EGPL("epddtpv: Display a PGN tag pair value"); |
||
1418 | EGPL(""); |
||
1419 | EGPL("This command displays the current value for the indicated"); |
||
1420 | EGPL("PGN tag pair. These available tag pair names are: Event, "); |
||
1421 | EGPL("Site, Date, Round, White, Black, and Result. This command"); |
||
1422 | EGPL("takes a single parameter which is the name of the tag pair"); |
||
1423 | EGPL("to be displayed."); |
||
1424 | break; |
||
1425 | case egcomm_epdenum: |
||
1426 | EGPL("epdenum: Enumerate positions in an EPD file"); |
||
1427 | EGPL(""); |
||
1428 | EGPL("This command takes three parameters. The first is a non-"); |
||
1429 | EGPL("negative integer that gives a ply depth limit. The second"); |
||
1430 | EGPL("is an input EPD file with positions to be enumerated to the"); |
||
1431 | EGPL("given depth. The third parameter is the result EPD file"); |
||
1432 | EGPL("with enumeration data given with the acd, acn, and acs"); |
||
1433 | EGPL("operations. The grand total of all enumerations is printed"); |
||
1434 | EGPL("to the standard output."); |
||
1435 | break; |
||
1436 | case egcomm_epdhelp: |
||
1437 | EGPL("epdhelp: Display available epdglue commands"); |
||
1438 | EGPL(""); |
||
1439 | EGPL("This command takes no parameters. It displays a list"); |
||
1440 | EGPL("of all the epdglue commands with a single line description"); |
||
1441 | EGPL("of each command. The epdmore command gives a detailed"); |
||
1442 | EGPL("description of a specified command."); |
||
1443 | break; |
||
1444 | case egcomm_epdlink: |
||
1445 | EGPL("epdlink: Slave to the Argus moderator program"); |
||
1446 | EGPL(""); |
||
1447 | EGPL("This command used to slave the host program to the Argus"); |
||
1448 | EGPL("tournament referee program. It takes two parameters. The"); |
||
1449 | EGPL("first is the name of the machine running the Argus referee"); |
||
1450 | EGPL("and the second is the port number in use by Argus on the"); |
||
1451 | EGPL("indicated machine. The Argus program must be started prior"); |
||
1452 | EGPL("to using this command. Argus acts as a general tournament"); |
||
1453 | EGPL("supervisor and mediator for any number of chessplaying"); |
||
1454 | EGPL("programs competing in a compuer chess event. It supplies"); |
||
1455 | EGPL("the participating program entrants with everything needed"); |
||
1456 | EGPL("for an entire tournament."); |
||
1457 | break; |
||
1458 | case egcomm_epdlpgn: |
||
1459 | EGPL("epdlpgn: Load the game from a PGN file"); |
||
1460 | EGPL(""); |
||
1461 | EGPL("This command loads a single game from a Portable Game"); |
||
1462 | EGPL("Notation (PGN) file. If there is more than one game in the"); |
||
1463 | EGPL("file, then only the first one is loaded. This command tales"); |
||
1464 | EGPL("a single parameter which is the name of the file containing"); |
||
1465 | EGPL("the PGN data of interest."); |
||
1466 | break; |
||
1467 | case egcomm_epdlrec: |
||
1468 | EGPL("epdlpgn: Load a selected EPD record from a file"); |
||
1469 | EGPL(""); |
||
1470 | EGPL("This command loads an EPD record from a file and causes it"); |
||
1471 | EGPL("to become the current position in the host program. This"); |
||
1472 | EGPL("command takes two parameters. The first is the name of the"); |
||
1473 | EGPL("file with EPD records and the second is the record number"); |
||
1474 | EGPL("of interest. The epdlrec command is intended to assist with"); |
||
1475 | EGPL("benchmark analysis by making it easy to select and load the"); |
||
1476 | EGPL("Nth record of a benchmark file."); |
||
1477 | break; |
||
1478 | case egcomm_epdmore: |
||
1479 | EGPL("epdmore: Display detailed help for a given command"); |
||
1480 | EGPL(""); |
||
1481 | EGPL("This command takes a single parameter which is the name"); |
||
1482 | EGPL("of one of the available epdglue commands. A brief paragraph"); |
||
1483 | EGPL("of helpful assistance is displayed."); |
||
1484 | break; |
||
1485 | case egcomm_epdnoop: |
||
1486 | EGPL("epdnoop: No operation"); |
||
1487 | EGPL(""); |
||
1488 | EGPL("This command performs no operation. It is provided for"); |
||
1489 | EGPL("development purposes."); |
||
1490 | break; |
||
1491 | case egcomm_epdpfdn: |
||
108 | pmbaty | 1492 | EGPL("epdpfdn: Process file: data normalization"); |
33 | pmbaty | 1493 | EGPL(""); |
1494 | EGPL("This command takes two parameters. The first is the name of"); |
||
1495 | EGPL("an input EPD data file. The second is the name of the EPD"); |
||
1496 | EGPL("output file to be produced from normalizing the input. The"); |
||
1497 | EGPL("normalization process produces a canonical external"); |
||
1498 | EGPL("representation for each EPD input record."); |
||
1499 | break; |
||
1500 | case egcomm_epdpfdr: |
||
108 | pmbaty | 1501 | EGPL("epdpfdr: Process file: data repair"); |
33 | pmbaty | 1502 | EGPL(""); |
1503 | EGPL("This command takes two parameters. The first is the name of"); |
||
1504 | EGPL("an input EPD data file. The second is the name of the EPD"); |
||
1505 | EGPL("output file to be produced from repairing the input. The"); |
||
1506 | EGPL("repair process attempts to map all chess move data present"); |
||
1507 | EGPL("in the input into Standard Algebraic Notation. This repair"); |
||
1508 | EGPL("effort affects the am, bm, pm, pv, sm, and sv operations."); |
||
1509 | break; |
||
1510 | case egcomm_epdpfga: |
||
108 | pmbaty | 1511 | EGPL("epdpfga: Process file: general analysis"); |
33 | pmbaty | 1512 | EGPL(""); |
1513 | EGPL("This command takes two parameters. The first is the name of"); |
||
1514 | EGPL("an input EPD data file. The second is the name of the EPD"); |
||
1515 | EGPL("output file to be produced from applying general analysis"); |
||
1516 | EGPL("to each position in the input file. The output analysis is"); |
||
1517 | EGPL("contained in the acd, acn, acs, ce, and pv operations."); |
||
1518 | break; |
||
1519 | case egcomm_epdpflc: |
||
108 | pmbaty | 1520 | EGPL("epdpflc: Process file: locate cooks"); |
33 | pmbaty | 1521 | EGPL(""); |
1522 | EGPL("This command is used to scan an EPD file and report on any"); |
||
1523 | EGPL("checkmating cooks. The signle parameter is the name of the"); |
||
1524 | EGPL("EPD file to be scanned. Each record is scanned and if the"); |
||
1525 | EGPL("centipawn evaluation indicates a forced mate, then the move"); |
||
1526 | EGPL("appearing as the result of a search is checked against the"); |
||
1527 | EGPL("moves appearing in the bm (best moves) operation on the same"); |
||
1528 | EGPL("record. If the result move does not appear in the bm list,"); |
||
1529 | EGPL("then the record is reported as a cook."); |
||
1530 | break; |
||
1531 | case egcomm_epdpfop: |
||
108 | pmbaty | 1532 | EGPL("epdpfop: Process file: operation purge"); |
33 | pmbaty | 1533 | EGPL(""); |
1534 | EGPL("This command takes threee parameters. The first is the name"); |
||
1535 | EGPL("of an EPD operation mnemonic to be purged. The second is the"); |
||
1536 | EGPL("name fo the input EPD file, and the third is the name of the"); |
||
1537 | EGPL("EPD output to be produced by purging the specified operation"); |
||
1538 | EGPL("from the input file."); |
||
1539 | break; |
||
1540 | case egcomm_epdscor: |
||
108 | pmbaty | 1541 | EGPL("epdscor: Score EPD analysis file"); |
33 | pmbaty | 1542 | EGPL(""); |
1543 | EGPL("This command takes one parameter. It is the name of an input"); |
||
1544 | EGPL("EPD data file containing analysis result data. The input"); |
||
1545 | EGPL("data analysis is scanned and a brief statistical report is"); |
||
1546 | EGPL("displayed."); |
||
1547 | break; |
||
1548 | case egcomm_epdshow: |
||
108 | pmbaty | 1549 | EGPL("epdshow: Show EPD four fields for the current position"); |
33 | pmbaty | 1550 | EGPL(""); |
1551 | EGPL("This command takes no parameters. It causes the EPD four"); |
||
1552 | EGPL("data fields for the current position to be displayed."); |
||
1553 | break; |
||
1554 | case egcomm_epdspgn: |
||
1555 | EGPL("epdspgn: Save the game to a PGN file"); |
||
1556 | EGPL(""); |
||
1557 | EGPL("This command is used to save the current game to a file"); |
||
1558 | EGPL("using Portable Game Notation (PGN) format. It takes one"); |
||
1559 | EGPL("parameter which is the file name of interest. The previous"); |
||
1560 | EGPL("copy of the file, if any, is overwritten."); |
||
1561 | break; |
||
1562 | case egcomm_epdstpv: |
||
1563 | EGPL("epdstpv: Set a PGN tag pair value"); |
||
1564 | EGPL(""); |
||
1565 | EGPL("This command sets the current value for the indicated"); |
||
1566 | EGPL("PGN tag pair. These available tag pair names are: Event, "); |
||
1567 | EGPL("Site, Date, Round, White, Black, and Result. This command"); |
||
1568 | EGPL("takes two parameters. The first which is the name of the"); |
||
1569 | EGPL("tag pair of interest and the second is the value to be"); |
||
1570 | EGPL("assigned. Underscore characters in the value are mapped"); |
||
1571 | EGPL("to blanks; this allows embedded spaces to appear in the"); |
||
1572 | EGPL("received value."); |
||
1573 | break; |
||
1574 | case egcomm_epdtest: |
||
108 | pmbaty | 1575 | EGPL("epdtest: Developer testing"); |
33 | pmbaty | 1576 | EGPL(""); |
1577 | EGPL("This command takes no parameters. It is used for developer"); |
||
1578 | EGPL("testing purposes."); |
||
1579 | break; |
||
1580 | case egcomm_nil: |
||
1581 | sprintf(tbufv, "Unknown command: %s\n", EPDTokenFetch(1)); |
||
1582 | EGPrintTB(); |
||
1583 | flag = 0; |
||
1584 | break; |
||
1585 | }; |
||
1586 | return flag; |
||
1587 | } |
||
1588 | |||
1589 | /*--> EGProcessNOOP: process the EG command epdnoop */ |
||
1590 | static siT EGProcessNOOP(void) { |
||
1591 | siT flag; |
||
1592 | |||
1593 | /* this is an internal EPD glue routine */ |
||
1594 | /* set the default return value: success */ |
||
1595 | flag = 1; |
||
1596 | /* process the epdnoop command */ |
||
1597 | return flag; |
||
1598 | } |
||
1599 | |||
1600 | /*--> EGProcessPFDN: process the EG command epdpfdn */ |
||
1601 | static siT EGProcessPFDN(void) { |
||
1602 | siT flag; |
||
1603 | |||
1604 | /* this is an internal EPD glue routine */ |
||
1605 | /* set the default return value: success */ |
||
1606 | flag = 1; |
||
1607 | /* parameter count check */ |
||
1608 | if (EPDTokenCount() != 3) { |
||
1609 | EGPL("This command takes two parameters"); |
||
1610 | flag = 0; |
||
1611 | }; |
||
1612 | /* process the epdpfdn command */ |
||
1613 | if (flag) |
||
1614 | flag = EPDNormalizeFile(EPDTokenFetch(1), EPDTokenFetch(2)); |
||
1615 | return flag; |
||
1616 | } |
||
1617 | |||
1618 | /*--> EGProcessPFDR: process the EG command epdpfdr */ |
||
1619 | static siT EGProcessPFDR(void) { |
||
1620 | siT flag; |
||
1621 | |||
1622 | /* this is an internal EPD glue routine */ |
||
1623 | /* set the default return value: success */ |
||
1624 | flag = 1; |
||
1625 | /* parameter count check */ |
||
1626 | if (EPDTokenCount() != 3) { |
||
1627 | EGPL("This command takes two parameters"); |
||
1628 | flag = 0; |
||
1629 | }; |
||
1630 | /* process the epdpfdr command */ |
||
1631 | if (flag) |
||
1632 | flag = EPDRepairFile(EPDTokenFetch(1), EPDTokenFetch(2)); |
||
1633 | return flag; |
||
1634 | } |
||
1635 | |||
1636 | /*--> EGProcessPFGA: process the EG command epdpfga */ |
||
1637 | static siT EGProcessPFGA(void) { |
||
1638 | siT flag; |
||
1639 | fptrT fptr0, fptr1; |
||
1640 | liT record; |
||
1641 | time_t start_time; |
||
1642 | liT result; |
||
1643 | siT index; |
||
1644 | liT host_acd, host_acn, host_acs; |
||
1645 | cpevT host_ce; |
||
1646 | charptrT s; |
||
1647 | liT move; |
||
1648 | mT m; |
||
1649 | sanT san; |
||
1650 | eovptrT eovptr; |
||
1651 | eopptrT eopptr; |
||
1652 | epdptrT epdptr; |
||
1653 | char ev[epdL]; |
||
1654 | TREE *tree = block[0]; |
||
1655 | |||
1656 | /* this is an internal EPD glue routine */ |
||
1657 | /* set the default return value: success */ |
||
1658 | flag = 1; |
||
1659 | /* clear the file pointers */ |
||
1660 | fptr0 = fptr1 = NULL; |
||
1661 | /* parameter count check */ |
||
1662 | if (EPDTokenCount() != 3) { |
||
1663 | EGPL("This command takes two parameters"); |
||
1664 | flag = 0; |
||
1665 | }; |
||
1666 | /* set up the input file */ |
||
1667 | if (flag) { |
||
1668 | fptr0 = fopen(EPDTokenFetch(1), "r"); |
||
1669 | if (fptr0 == NULL) { |
||
1670 | sprintf(tbufv, "Can't open %s for reading\n", EPDTokenFetch(1)); |
||
1671 | EGPrintTB(); |
||
1672 | flag = 0; |
||
1673 | }; |
||
1674 | }; |
||
1675 | /* set up the output file */ |
||
1676 | if (flag) { |
||
1677 | fptr1 = fopen(EPDTokenFetch(2), "w"); |
||
1678 | if (fptr1 == NULL) { |
||
1679 | sprintf(tbufv, "Can't open %s for writing\n", EPDTokenFetch(2)); |
||
1680 | EGPrintTB(); |
||
1681 | flag = 0; |
||
1682 | }; |
||
1683 | }; |
||
1684 | /* scan the file */ |
||
1685 | if (flag) { |
||
1686 | /* initialize the record count */ |
||
1687 | record = 0; |
||
1688 | /* read one record per loop */ |
||
1689 | while (flag && (fgets(ev, (epdL - 1), fptr0) != NULL)) { |
||
1690 | /* decode the record into an EPD structure */ |
||
1691 | epdptr = EPDDecode(ev); |
||
1692 | /* check record decode validity */ |
||
1693 | if (epdptr == NULL) |
||
1694 | flag = 0; |
||
1695 | else { |
||
1696 | /* set up the position in the EPD Kit */ |
||
1697 | EPDRealize(epdptr); |
||
1698 | /* legality test */ |
||
1699 | if (!EPDIsLegal()) |
||
1700 | flag = 0; |
||
1701 | else { |
||
1702 | /* output record information to the display */ |
||
1703 | sprintf(tbufv, "PFGA: EPD record: %ld", (record + 1)); |
||
1704 | EGPrintTB(); |
||
1705 | if (((eopptr = EPDLocateEOPCode(epdptr, epdso_id)) != NULL) |
||
1706 | && ((eovptr = eopptr->eop_headeov) != NULL) |
||
1707 | && ((s = eovptr->eov_str) != NULL)) { |
||
108 | pmbaty | 1708 | EGPrint(" ID: "); |
33 | pmbaty | 1709 | EGPrint(s); |
1710 | }; |
||
1711 | EGPrint("\n"); |
||
1712 | /* output record information to the log file */ |
||
1713 | if (log_file != NULL) { |
||
1714 | fprintf(log_file, "PFGA: EPD record: %ld", (record + 1)); |
||
1715 | if (((eopptr = EPDLocateEOPCode(epdptr, epdso_id)) != NULL) |
||
1716 | && ((eovptr = eopptr->eop_headeov) != NULL) |
||
1717 | && ((s = eovptr->eov_str) != NULL)) |
||
1718 | fprintf(log_file, " ID: %s", s); |
||
1719 | fprintf(log_file, "\n"); |
||
1720 | }; |
||
1721 | /* set up the host current position */ |
||
1722 | EGPutHostPosition(); |
||
1723 | /* set host search parameters */ |
||
1724 | tree->status[1] = tree->status[0]; |
||
108 | pmbaty | 1725 | iteration = 0; |
33 | pmbaty | 1726 | ponder = 0; |
1727 | /* get the starting time */ |
||
1728 | start_time = time(NULL); |
||
1729 | /* run host search; EPD Kit position may be changed */ |
||
1730 | result = EGIterate(EGMapToHostColor(EPDFetchACTC()), think); |
||
1731 | /* refresh the EPD Kit current position */ |
||
1732 | EGGetHostPosition(); |
||
1733 | /* extract analysis count: depth */ |
||
108 | pmbaty | 1734 | host_acd = iteration; |
33 | pmbaty | 1735 | if (host_acd == 0) |
1736 | host_acd = 1; |
||
1737 | /* insert analysis count: depth */ |
||
1738 | EPDAddOpInt(epdptr, epdso_acd, host_acd); |
||
1739 | /* extract analysis count: nodes */ |
||
156 | pmbaty | 1740 | host_acn = (liT) tree->nodes_searched; // Pierre-Marie Baty -- added type cast |
33 | pmbaty | 1741 | if (host_acn == 0) |
1742 | host_acn = 1; |
||
1743 | /* insert analysis count: nodes */ |
||
1744 | EPDAddOpInt(epdptr, epdso_acn, host_acn); |
||
1745 | /* extract analysis count: seconds */ |
||
156 | pmbaty | 1746 | host_acs = (liT) (time(NULL) - start_time); // Pierre-Marie Baty -- added type cast |
33 | pmbaty | 1747 | if (host_acs == 0) |
1748 | host_acs = 1; |
||
1749 | /* insert analysis count: seconds */ |
||
1750 | EPDAddOpInt(epdptr, epdso_acs, host_acs); |
||
1751 | /* extract centipawn evaluation */ |
||
1752 | host_ce = EGMapFromHostScore(result); |
||
1753 | /* |
||
1754 | host_ce = (EGMapToHostColor(EPDFetchACTC())) ? result : -result; |
||
1755 | */ |
||
1756 | /* insert centipawn evaluation */ |
||
1757 | EPDAddOpInt(epdptr, epdso_ce, host_ce); |
||
1758 | /* delete predicted move */ |
||
1759 | EPDDropIfLocEOPCode(epdptr, epdso_pm); |
||
1760 | /* extract/insert predicted variation */ |
||
1761 | EPDDropIfLocEOPCode(epdptr, epdso_pv); |
||
1762 | eopptr = EPDCreateEOPCode(epdso_pv); |
||
1763 | for (index = 1; index < (int) tree->pv[0].pathl; index++) { |
||
1764 | /* generate moves for the current position */ |
||
1765 | EPDGenMoves(); |
||
1766 | /* fetch the predicted move at this ply */ |
||
1767 | move = tree->pv[0].path[index]; |
||
1768 | /* map the host move to EPD style */ |
||
1769 | m = EGMapFromHostMove(move); |
||
1770 | /* set the flag bits in the EPD move */ |
||
1771 | EPDSetMoveFlags(&m); |
||
1772 | /* construct the SAN for the move */ |
||
1773 | EPDSANEncode(&m, san); |
||
1774 | /* create and append the SAN move */ |
||
1775 | eovptr = EPDCreateEOVSym(san); |
||
1776 | EPDAppendEOV(eopptr, eovptr); |
||
1777 | /* execute the move to update the EPD position */ |
||
1778 | EPDExecuteUpdate(&m); |
||
1779 | }; |
||
1780 | /* retract predicted variation moves */ |
||
1781 | EPDRetractAll(); |
||
1782 | /* append the pv operation to the EPD structure */ |
||
1783 | EPDAppendEOP(epdptr, eopptr); |
||
1784 | /* encode the EPD into a string, write, and release */ |
||
1785 | s = EPDEncode(epdptr); |
||
1786 | fprintf(fptr1, "%s\n", s); |
||
1787 | fflush(fptr1); |
||
1788 | EPDMemoryFree(s); |
||
1789 | }; |
||
1790 | /* deallocate the EPD structure */ |
||
1791 | EPDReleaseEPD(epdptr); |
||
1792 | }; |
||
1793 | /* increment EPD record count */ |
||
1794 | record++; |
||
1795 | }; |
||
1796 | }; |
||
1797 | /* ensure file close */ |
||
1798 | if (fptr0 != NULL) |
||
1799 | fclose(fptr0); |
||
1800 | if (fptr1 != NULL) |
||
1801 | fclose(fptr1); |
||
1802 | return flag; |
||
1803 | } |
||
1804 | |||
1805 | /*--> EGProcessPFLC: process the EG command epdpflc */ |
||
1806 | static siT EGProcessPFLC(void) { |
||
1807 | siT flag; |
||
1808 | fptrT fptr; |
||
1809 | epdptrT epdptr; |
||
1810 | eopptrT eopptr; |
||
1811 | eovptrT eovptr; |
||
1812 | liT record; |
||
1813 | charptrT s; |
||
1814 | char ev[epdL]; |
||
1815 | |||
1816 | /* this is an internal EPD glue routine */ |
||
1817 | /* set the default return value: success */ |
||
1818 | flag = 1; |
||
1819 | /* parameter count check */ |
||
1820 | if (EPDTokenCount() != 2) { |
||
1821 | EGPL("This command takes one parameter."); |
||
1822 | flag = 0; |
||
1823 | }; |
||
1824 | /* clear the file pointer */ |
||
1825 | fptr = NULL; |
||
1826 | /* set up the input file */ |
||
1827 | if (flag) { |
||
1828 | fptr = fopen(EPDTokenFetch(1), "r"); |
||
1829 | if (fptr == NULL) { |
||
1830 | sprintf(tbufv, "Can't open %s for reading\n", EPDTokenFetch(1)); |
||
1831 | EGPrintTB(); |
||
1832 | flag = 0; |
||
1833 | }; |
||
1834 | }; |
||
1835 | /* scan the file */ |
||
1836 | if (flag) { |
||
1837 | /* clear record count */ |
||
1838 | record = 0; |
||
1839 | /* scan each record */ |
||
1840 | while (flag && (fgets(ev, (epdL - 1), fptr) != NULL)) { |
||
1841 | /* decode the record into an EPD structure */ |
||
1842 | epdptr = EPDDecode(ev); |
||
1843 | /* check record decode validity */ |
||
1844 | if (epdptr == NULL) |
||
1845 | flag = 0; |
||
1846 | else { |
||
1847 | /* did the expectation indicate a forced mate? */ |
||
1848 | if (((eopptr = EPDLocateEOPCode(epdptr, epdso_ce)) != NULL) |
||
1849 | && ((eovptr = eopptr->eop_headeov) != NULL) |
||
1850 | && forced_mate(atol(eovptr->eov_str))) { |
||
1851 | /* get the analysis result move from the pv */ |
||
1852 | eopptr = EPDLocateEOPCode(epdptr, epdso_pv); |
||
1853 | if ((eopptr != NULL) && ((eovptr = eopptr->eop_headeov) != NULL)) { |
||
1854 | /* get a pointer to the result move */ |
||
1855 | s = eovptr->eov_str; |
||
1856 | /* get the best move operation */ |
||
1857 | eopptr = EPDLocateEOPCode(epdptr, epdso_bm); |
||
1858 | if (eopptr != NULL) { |
||
1859 | /* check for a matching best move */ |
||
1860 | eovptr = EPDLocateEOV(eopptr, s); |
||
1861 | /* if not found, then it's a cook */ |
||
1862 | if (eovptr == NULL) { |
||
1863 | /* issue report */ |
||
1864 | sprintf(tbufv, "PFLC: record %ld: cook: %s", (record + 1), |
||
1865 | s); |
||
1866 | EGPrintTB(); |
||
1867 | eopptr = EPDLocateEOPCode(epdptr, epdso_id); |
||
1868 | if ((eopptr != NULL) |
||
1869 | && ((eovptr = eopptr->eop_headeov) != NULL)) { |
||
1870 | EGPrint(" ID: "); |
||
1871 | EGPrint(eovptr->eov_str); |
||
1872 | }; |
||
1873 | EGPrint("\n"); |
||
1874 | }; |
||
1875 | }; |
||
1876 | }; |
||
1877 | }; |
||
1878 | /* deallocate the EPD structure */ |
||
1879 | EPDReleaseEPD(epdptr); |
||
1880 | }; |
||
1881 | /* next record */ |
||
1882 | record++; |
||
1883 | }; |
||
1884 | }; |
||
1885 | /* ensure input file closed */ |
||
1886 | if (fptr != NULL) |
||
1887 | fclose(fptr); |
||
1888 | return flag; |
||
1889 | } |
||
1890 | |||
1891 | /*--> EGProcessPFOP: process the EG command epdpfop */ |
||
1892 | static siT EGProcessPFOP(void) { |
||
1893 | siT flag; |
||
1894 | |||
1895 | /* this is an internal EPD glue routine */ |
||
1896 | /* set the default return value: success */ |
||
1897 | flag = 1; |
||
1898 | /* parameter count check */ |
||
1899 | if (EPDTokenCount() != 4) { |
||
1900 | EGPL("This command takes three parameters"); |
||
1901 | flag = 0; |
||
1902 | }; |
||
1903 | /* process the epdpfop command */ |
||
1904 | if (flag) |
||
1905 | flag = |
||
1906 | EPDPurgeOpFile(EPDTokenFetch(1), EPDTokenFetch(2), EPDTokenFetch(3)); |
||
1907 | return flag; |
||
1908 | } |
||
1909 | |||
1910 | /*--> EGProcessSCOR: process the EG command epdscor */ |
||
1911 | static siT EGProcessSCOR(void) { |
||
1912 | siT flag; |
||
1913 | bmsT bms; |
||
1914 | |||
1915 | /* this is an internal EPD glue routine */ |
||
1916 | /* set the default return value: success */ |
||
1917 | flag = 1; |
||
1918 | /* parameter count check */ |
||
1919 | if (EPDTokenCount() != 2) { |
||
1920 | EGPL("This command takes one parameter."); |
||
1921 | flag = 0; |
||
1922 | }; |
||
1923 | /* process the epdscor command */ |
||
1924 | if (flag) { |
||
1925 | flag = EPDScoreFile(EPDTokenFetch(1), &bms); |
||
1926 | if (flag) { |
||
1927 | sprintf(tbufv, "total: %ld\n", bms.bms_total); |
||
1928 | EGPrintTB(); |
||
1929 | if (bms.bms_total != 0) { |
||
1930 | if (bms.bms_acdflag) { |
||
1931 | sprintf(tbufv, "total acd: %ld mean total acd: %.2f\n", |
||
1932 | bms.bms_total_acd, ((lrT) bms.bms_total_acd / bms.bms_total)); |
||
1933 | EGPrintTB(); |
||
1934 | }; |
||
1935 | if (bms.bms_acnflag) { |
||
1936 | sprintf(tbufv, "total acn: %ld mean total acn: %.2f\n", |
||
1937 | bms.bms_total_acn, ((lrT) bms.bms_total_acn / bms.bms_total)); |
||
1938 | EGPrintTB(); |
||
1939 | }; |
||
1940 | if (bms.bms_acsflag) { |
||
1941 | sprintf(tbufv, "total acs: %ld mean total acs: %.2f\n", |
||
1942 | bms.bms_total_acs, ((lrT) bms.bms_total_acs / bms.bms_total)); |
||
1943 | EGPrintTB(); |
||
1944 | }; |
||
1945 | if (bms.bms_acnflag && bms.bms_acsflag) |
||
1946 | if (bms.bms_total_acs != 0) { |
||
1947 | sprintf(tbufv, "total mean node frequency: %.2f Hz\n", |
||
1948 | ((lrT) bms.bms_total_acn / bms.bms_total_acs)); |
||
1949 | EGPrintTB(); |
||
1950 | }; |
||
1951 | sprintf(tbufv, "solve: %ld solve percent: %.2f\n", bms.bms_solve, |
||
1952 | (((lrT) bms.bms_solve * 100.0) / bms.bms_total)); |
||
1953 | EGPrintTB(); |
||
1954 | if (bms.bms_solve != 0) { |
||
1955 | if (bms.bms_acdflag) { |
||
1956 | sprintf(tbufv, "solve acd: %ld mean solve acd: %.2f\n", |
||
1957 | bms.bms_solve_acd, ((lrT) bms.bms_solve_acd / bms.bms_solve)); |
||
1958 | EGPrintTB(); |
||
1959 | }; |
||
1960 | if (bms.bms_acnflag) { |
||
1961 | sprintf(tbufv, "solve acn: %ld mean solve acn: %.2f\n", |
||
1962 | bms.bms_solve_acn, ((lrT) bms.bms_solve_acn / bms.bms_solve)); |
||
1963 | EGPrintTB(); |
||
1964 | }; |
||
1965 | if (bms.bms_acsflag) { |
||
1966 | sprintf(tbufv, "solve acs: %ld mean solve acs: %.2f\n", |
||
1967 | bms.bms_solve_acs, ((lrT) bms.bms_solve_acs / bms.bms_solve)); |
||
1968 | EGPrintTB(); |
||
1969 | }; |
||
1970 | if (bms.bms_acnflag && bms.bms_acsflag) |
||
1971 | if (bms.bms_solve_acs != 0) { |
||
1972 | sprintf(tbufv, "solve mean node frequency: %.2f Hz\n", |
||
1973 | ((lrT) bms.bms_solve_acn / bms.bms_solve_acs)); |
||
1974 | EGPrintTB(); |
||
1975 | }; |
||
1976 | }; |
||
1977 | sprintf(tbufv, "unsol: %ld unsol percent: %.2f\n", bms.bms_unsol, |
||
1978 | (((lrT) bms.bms_unsol * 100.0) / bms.bms_total)); |
||
1979 | EGPrintTB(); |
||
1980 | if (bms.bms_unsol != 0) { |
||
1981 | if (bms.bms_acdflag) { |
||
1982 | sprintf(tbufv, "unsol acd: %ld mean unsol acd: %.2f\n", |
||
1983 | bms.bms_unsol_acd, ((lrT) bms.bms_unsol_acd / bms.bms_unsol)); |
||
1984 | EGPrintTB(); |
||
1985 | }; |
||
1986 | if (bms.bms_acnflag) { |
||
1987 | sprintf(tbufv, "unsol acn: %ld mean unsol acn: %.2f\n", |
||
1988 | bms.bms_unsol_acn, ((lrT) bms.bms_unsol_acn / bms.bms_unsol)); |
||
1989 | EGPrintTB(); |
||
1990 | }; |
||
1991 | if (bms.bms_acsflag) { |
||
1992 | sprintf(tbufv, "unsol acs: %ld mean unsol acs: %.2f\n", |
||
1993 | bms.bms_unsol_acs, ((lrT) bms.bms_unsol_acs / bms.bms_unsol)); |
||
1994 | EGPrintTB(); |
||
1995 | }; |
||
1996 | if (bms.bms_acnflag && bms.bms_acsflag) |
||
1997 | if (bms.bms_unsol_acs != 0) { |
||
1998 | sprintf(tbufv, "unsol mean node frequency: %.2f Hz\n", |
||
1999 | ((lrT) bms.bms_unsol_acn / bms.bms_unsol_acs)); |
||
2000 | EGPrintTB(); |
||
2001 | }; |
||
2002 | }; |
||
2003 | }; |
||
2004 | }; |
||
2005 | }; |
||
2006 | return flag; |
||
2007 | } |
||
2008 | |||
2009 | /*--> EGProcessSHOW: process the EG command epdshow */ |
||
2010 | static siT EGProcessSHOW(void) { |
||
2011 | siT flag; |
||
2012 | charptrT s; |
||
2013 | |||
2014 | /* this is an internal EPD glue routine */ |
||
2015 | /* set the default return value: success */ |
||
2016 | flag = 1; |
||
2017 | /* parameter count check */ |
||
2018 | if (EPDTokenCount() != 1) { |
||
2019 | EGPL("This command takes no parameters."); |
||
2020 | flag = 0; |
||
2021 | }; |
||
2022 | /* process the epdshow command */ |
||
2023 | if (flag) { |
||
2024 | /* load the host pointion into the EPD Kit */ |
||
2025 | EGGetHostPosition(); |
||
2026 | /* get the EPD string for the current position */ |
||
2027 | s = EPDGenBasicCurrent(); |
||
2028 | /* print and release */ |
||
2029 | sprintf(tbufv, "%s\n", s); |
||
2030 | EGPrintTB(); |
||
2031 | EPDMemoryFree(s); |
||
2032 | }; |
||
2033 | return flag; |
||
2034 | } |
||
2035 | |||
2036 | /*--> EGProcessSPGN: process the EG command epdspgn */ |
||
2037 | static siT EGProcessSPGN(void) { |
||
2038 | siT flag; |
||
2039 | charptrT s; |
||
2040 | fptrT fptr; |
||
2041 | |||
2042 | /* this is an internal EPD glue routine */ |
||
2043 | /* set the default return value: success */ |
||
2044 | flag = 1; |
||
2045 | /* parameter count check */ |
||
2046 | if (EPDTokenCount() != 2) { |
||
2047 | EGPL("This command takes one parameter."); |
||
2048 | flag = 0; |
||
2049 | }; |
||
2050 | /* process the epdspgn command */ |
||
2051 | if (flag) { |
||
2052 | s = EGEncodeHostHistory(); |
||
2053 | if (s == NULL) |
||
2054 | flag = 0; |
||
2055 | else { |
||
2056 | fptr = fopen(EPDTokenFetch(1), "w"); |
||
2057 | if (fptr == NULL) |
||
2058 | flag = 0; |
||
2059 | else { |
||
2060 | fprintf(fptr, "%s", s); |
||
2061 | fclose(fptr); |
||
2062 | }; |
||
2063 | EPDMemoryFree(s); |
||
2064 | }; |
||
2065 | }; |
||
2066 | return flag; |
||
2067 | } |
||
2068 | |||
2069 | /*--> EGProcessSTPV: process the EG command epdstpv */ |
||
2070 | static siT EGProcessSTPV(void) { |
||
2071 | siT flag; |
||
2072 | pgnstrT pgnstr; |
||
2073 | charptrT s; |
||
2074 | liT i, length; |
||
2075 | |||
2076 | /* this is an internal EPD glue routine */ |
||
2077 | /* set the default return value: success */ |
||
2078 | flag = 1; |
||
2079 | /* parameter count check */ |
||
2080 | if (EPDTokenCount() != 3) { |
||
2081 | EGPL("This command takes two parameters"); |
||
2082 | flag = 0; |
||
2083 | }; |
||
2084 | /* process the epdstpv command */ |
||
2085 | if (flag) { |
||
2086 | pgnstr = EPDPGNFetchTagIndex(EPDTokenFetch(1)); |
||
2087 | if (pgnstr == pgnstr_nil) { |
||
2088 | EGPL("Unknown tag name; available tag names are:"); |
||
2089 | for (pgnstr = 0; pgnstr < pgnstrL; pgnstr++) { |
||
2090 | EGPrint(" "); |
||
2091 | EGPrint(EPDPGNFetchTagName(pgnstr)); |
||
2092 | }; |
||
2093 | EGPrint("\n"); |
||
2094 | flag = 0; |
||
2095 | } else { |
||
2096 | /* change underscore characters to blanks */ |
||
2097 | s = EPDStringGrab(EPDTokenFetch(2)); |
||
2098 | length = strlen(s); |
||
2099 | for (i = 0; i < length; i++) |
||
2100 | if (*(s + i) == '_') |
||
2101 | *(s + i) = ' '; |
||
2102 | EPDPGNPutSTR(default_gamptr, pgnstr, s); |
||
2103 | EPDMemoryFree(s); |
||
2104 | }; |
||
2105 | }; |
||
2106 | return flag; |
||
2107 | } |
||
2108 | |||
2109 | /*--> EGProcessTEST: process the EG command epdtest */ |
||
2110 | static siT EGProcessTEST(void) { |
||
2111 | siT flag; |
||
2112 | |||
2113 | /* this is an internal EPD glue routine */ |
||
2114 | /* set the default return value: success */ |
||
2115 | flag = 1; |
||
2116 | /* parameter count check */ |
||
2117 | if (EPDTokenCount() != 1) { |
||
2118 | EGPL("This command takes no parameters."); |
||
2119 | flag = 0; |
||
2120 | }; |
||
2121 | /* process the epdtest command */ |
||
2122 | if (flag) { |
||
2123 | EGPL("This command is not yet implemented."); |
||
2124 | flag = 0; |
||
2125 | }; |
||
2126 | return flag; |
||
2127 | } |
||
2128 | |||
2129 | /*--> EGCommandCheck: check if a string starts with an EPD command token */ |
||
2130 | nonstatic int EGCommandCheck(char *s) { |
||
2131 | siT flag; |
||
2132 | charptrT tokenptr; |
||
2133 | egcommT egcomm; |
||
2134 | |||
2135 | /* this routine is called from Option() in option.c */ |
||
2136 | /* |
||
2137 | This routine is used to quickly check if an input command line starts with |
||
2138 | one of the available EPD glue command tokens. The idea is that EPD action |
||
2139 | can be quickly selected (or deselected) for any command input text string. |
||
2140 | Because Crafty distributes command input one token at a time, the calls to |
||
2141 | this routine in this implementation will only have a single token for input. |
||
2142 | Other implementations that use an entire input command line will use the |
||
2143 | full power of this routine which includes token scanning and recording |
||
2144 | which is handled by the EPD Kit routines in the epd.c file. |
||
2145 | */ |
||
2146 | /* set default return value: no match */ |
||
2147 | flag = 0; |
||
2148 | /* tokenize the input string */ |
||
2149 | EPDTokenize(s); |
||
2150 | /* was there at least one token? */ |
||
2151 | if (EPDTokenCount() > 0) { |
||
2152 | /* get a pointer to the first token (origin zero) */ |
||
2153 | tokenptr = EPDTokenFetch(0); |
||
2154 | /* get the glue command indicator */ |
||
2155 | egcomm = EGLocateCommand(tokenptr); |
||
2156 | /* was there a command match? */ |
||
2157 | if (egcomm != egcomm_nil) |
||
2158 | flag = 1; |
||
2159 | }; |
||
2160 | return flag; |
||
2161 | } |
||
2162 | |||
2163 | /*--> EGCommand: process an EPD command string */ |
||
2164 | nonstatic int EGCommand(char *s) { |
||
2165 | siT flag; |
||
2166 | egcommT egcomm; |
||
2167 | |||
2168 | /* this routine is called from Option() in option.c */ |
||
2169 | /* |
||
2170 | This routine actviates EPD glue command processing. it is called with a |
||
2171 | string that represents an entire EPD glue command input, including any |
||
2172 | parameters following the command. |
||
2173 | Because Crafty distributes command input one token at a time, it is |
||
2174 | necessary for the host calling code to assemble a command line from the |
||
2175 | input token stream. See the code in Option() for details. |
||
2176 | */ |
||
2177 | /* set the default return value: success */ |
||
2178 | flag = 1; |
||
2179 | /* check the command string (this also tokenizes it) */ |
||
2180 | if (EGCommandCheck(s)) |
||
2181 | egcomm = EGLocateCommand(EPDTokenFetch(0)); |
||
2182 | else |
||
2183 | egcomm = egcomm_nil; |
||
2184 | /* was a valid EPD glue command located? */ |
||
2185 | if (egcomm == egcomm_nil) { |
||
2186 | EGPL("EG fault: can't locate valid EG command"); |
||
2187 | flag = 0; |
||
2188 | } else { |
||
2189 | /* a valid command token was found; perform command dispatch */ |
||
2190 | switch (egcomm) { |
||
2191 | case egcomm_epdapgn: |
||
2192 | flag = EGProcessAPGN(); |
||
2193 | break; |
||
2194 | case egcomm_epdbfix: |
||
2195 | flag = EGProcessBFIX(); |
||
2196 | break; |
||
2197 | case egcomm_epdcics: |
||
2198 | flag = EGProcessCICS(); |
||
2199 | break; |
||
2200 | case egcomm_epdcomm: |
||
2201 | flag = EGProcessCOMM(); |
||
2202 | break; |
||
2203 | case egcomm_epddpgn: |
||
2204 | flag = EGProcessDPGN(); |
||
2205 | break; |
||
2206 | case egcomm_epddsml: |
||
2207 | flag = EGProcessDSML(); |
||
2208 | break; |
||
2209 | case egcomm_epddstr: |
||
2210 | flag = EGProcessDSTR(); |
||
2211 | break; |
||
2212 | case egcomm_epddtpv: |
||
2213 | flag = EGProcessDTPV(); |
||
2214 | break; |
||
2215 | case egcomm_epdenum: |
||
2216 | flag = EGProcessENUM(); |
||
2217 | break; |
||
2218 | case egcomm_epdhelp: |
||
2219 | flag = EGProcessHELP(); |
||
2220 | break; |
||
2221 | case egcomm_epdlink: |
||
2222 | flag = EGProcessLINK(); |
||
2223 | break; |
||
2224 | case egcomm_epdlpgn: |
||
2225 | flag = EGProcessLPGN(); |
||
2226 | break; |
||
2227 | case egcomm_epdlrec: |
||
2228 | flag = EGProcessLREC(); |
||
2229 | break; |
||
2230 | case egcomm_epdmore: |
||
2231 | flag = EGProcessMORE(); |
||
2232 | break; |
||
2233 | case egcomm_epdnoop: |
||
2234 | flag = EGProcessNOOP(); |
||
2235 | break; |
||
2236 | case egcomm_epdpfdn: |
||
2237 | flag = EGProcessPFDN(); |
||
2238 | break; |
||
2239 | case egcomm_epdpfdr: |
||
2240 | flag = EGProcessPFDR(); |
||
2241 | break; |
||
2242 | case egcomm_epdpfga: |
||
2243 | flag = EGProcessPFGA(); |
||
2244 | break; |
||
2245 | case egcomm_epdpflc: |
||
2246 | flag = EGProcessPFLC(); |
||
2247 | break; |
||
2248 | case egcomm_epdpfop: |
||
2249 | flag = EGProcessPFOP(); |
||
2250 | break; |
||
2251 | case egcomm_epdscor: |
||
2252 | flag = EGProcessSCOR(); |
||
2253 | break; |
||
2254 | case egcomm_epdshow: |
||
2255 | flag = EGProcessSHOW(); |
||
2256 | break; |
||
2257 | case egcomm_epdspgn: |
||
2258 | flag = EGProcessSPGN(); |
||
2259 | break; |
||
2260 | case egcomm_epdstpv: |
||
2261 | flag = EGProcessSTPV(); |
||
2262 | break; |
||
2263 | case egcomm_epdtest: |
||
2264 | flag = EGProcessTEST(); |
||
2265 | break; |
||
2266 | }; |
||
2267 | /* check result */ |
||
2268 | if (!flag) { |
||
2269 | sprintf(tbufv, "EG fault: a problem occurred during %s processing\n", |
||
2270 | EPDTokenFetch(0)); |
||
2271 | EGPrintTB(); |
||
2272 | }; |
||
2273 | }; |
||
2274 | return flag; |
||
2275 | } |
||
2276 | |||
2277 | /*--> EGInit: one time EPD glue initialization */ |
||
2278 | nonstatic void EGInit(void) { |
||
2279 | /* this is called by Initialize() in init.c */ |
||
2280 | EGPL("EPD Kit revision date: 1996.04.21"); |
||
2281 | /* call the EPD one time set up code */ |
||
2282 | EPDInit(); |
||
2283 | /* initialize the EPD glue command strings vector */ |
||
2284 | egcommstrv[egcomm_epdapgn] = "epdapgn"; |
||
2285 | egcommstrv[egcomm_epdbfix] = "epdbfix"; |
||
2286 | egcommstrv[egcomm_epdcert] = "epdcert"; |
||
2287 | egcommstrv[egcomm_epdcics] = "epdcics"; |
||
2288 | egcommstrv[egcomm_epdcomm] = "epdcomm"; |
||
2289 | egcommstrv[egcomm_epddpgn] = "epddpgn"; |
||
2290 | egcommstrv[egcomm_epddsml] = "epddsml"; |
||
2291 | egcommstrv[egcomm_epddstr] = "epddstr"; |
||
2292 | egcommstrv[egcomm_epddtpv] = "epddtpv"; |
||
2293 | egcommstrv[egcomm_epdenum] = "epdenum"; |
||
2294 | egcommstrv[egcomm_epdhelp] = "epdhelp"; |
||
2295 | egcommstrv[egcomm_epdlink] = "epdlink"; |
||
2296 | egcommstrv[egcomm_epdlpgn] = "epdlpgn"; |
||
2297 | egcommstrv[egcomm_epdlrec] = "epdlrec"; |
||
2298 | egcommstrv[egcomm_epdmore] = "epdmore"; |
||
2299 | egcommstrv[egcomm_epdnoop] = "epdnoop"; |
||
2300 | egcommstrv[egcomm_epdpfdn] = "epdpfdn"; |
||
2301 | egcommstrv[egcomm_epdpfdr] = "epdpfdr"; |
||
2302 | egcommstrv[egcomm_epdpfga] = "epdpfga"; |
||
2303 | egcommstrv[egcomm_epdpflc] = "epdpflc"; |
||
2304 | egcommstrv[egcomm_epdpfop] = "epdpfop"; |
||
2305 | egcommstrv[egcomm_epdscor] = "epdscor"; |
||
2306 | egcommstrv[egcomm_epdshow] = "epdshow"; |
||
2307 | egcommstrv[egcomm_epdspgn] = "epdspgn"; |
||
2308 | egcommstrv[egcomm_epdstpv] = "epdstpv"; |
||
2309 | egcommstrv[egcomm_epdtest] = "epdtest"; |
||
2310 | /* initialize the EPD glue command string descriptions vector */ |
||
2311 | eghelpstrv[egcomm_epdapgn] = "Append PGN game to <file>"; |
||
2312 | eghelpstrv[egcomm_epdbfix] = "Fix <file1> data for Bookup input <file2>"; |
||
2313 | eghelpstrv[egcomm_epdcert] = |
||
2314 | "Display certain score for the current position"; |
||
2315 | eghelpstrv[egcomm_epdcics] = "Slave to ICS at <hostname> and <portnumber>"; |
||
2316 | eghelpstrv[egcomm_epdcomm] = "Slave to Duplex using <pipefile-basename>"; |
||
2317 | eghelpstrv[egcomm_epddpgn] = "Display game using PGN"; |
||
2318 | eghelpstrv[egcomm_epddsml] = "Display SAN move list"; |
||
2319 | eghelpstrv[egcomm_epddstr] = "Display PGN Seven Tag Roster"; |
||
2320 | eghelpstrv[egcomm_epddtpv] = "Display PGN tag pair <tag-name> value"; |
||
2321 | eghelpstrv[egcomm_epdenum] = "Enumerate to <depth> from <file1> to <file2>"; |
||
2322 | eghelpstrv[egcomm_epdhelp] = "Display EPD glue command descriptions"; |
||
2323 | eghelpstrv[egcomm_epdlink] = |
||
2324 | "Slave to Argus at <hostname> and <portnumber>"; |
||
2325 | eghelpstrv[egcomm_epdlpgn] = "Load PGN game from <file>"; |
||
2326 | eghelpstrv[egcomm_epdlrec] = "Load EPD record from <file> <line-number>"; |
||
2327 | eghelpstrv[egcomm_epdmore] = "Display more help for <command>"; |
||
2328 | eghelpstrv[egcomm_epdnoop] = "No operation"; |
||
2329 | eghelpstrv[egcomm_epdpfdn] = "Normalize EPD data from <file1> to <file2>"; |
||
2330 | eghelpstrv[egcomm_epdpfdr] = "Repair EPD data from <file1> to <file2>"; |
||
2331 | eghelpstrv[egcomm_epdpfga] = "Analyze EPD data from <file1> to <file2>"; |
||
2332 | eghelpstrv[egcomm_epdpflc] = "Locate mating cooks in result <file>"; |
||
2333 | eghelpstrv[egcomm_epdpfop] = "Purge EPD <opcode> from <file1> to <file2>"; |
||
2334 | eghelpstrv[egcomm_epdscor] = "Score benchmark EPD results from <file>"; |
||
2335 | eghelpstrv[egcomm_epdshow] = |
||
2336 | "Show EPD four fields for the current position"; |
||
2337 | eghelpstrv[egcomm_epdspgn] = "Save PGN game to <file>"; |
||
2338 | eghelpstrv[egcomm_epdstpv] = "Set PGN tag pair <tag-name> to <value>"; |
||
2339 | eghelpstrv[egcomm_epdtest] = "EPD glue developer testing"; |
||
2340 | /* initialize the EPD glue command parameter counts vector */ |
||
2341 | /* set up the default game structure */ |
||
2342 | default_gamptr = EPDGameOpen(); |
||
2343 | return; |
||
2344 | } |
||
2345 | |||
2346 | /*--> EGTerm: one time EPD glue termination */ |
||
2347 | nonstatic void EGTerm(void) { |
||
2348 | /* this is called by Option() in option.c */ |
||
2349 | /* release the default game structure */ |
||
2350 | if (default_gamptr != NULL) |
||
2351 | EPDGameClose(default_gamptr); |
||
2352 | /* call the EPD one time close down code */ |
||
2353 | EPDTerm(); |
||
2354 | return; |
||
2355 | } |
||
2356 | #endif |
||
2357 | /*<<< epdglue.c: EOF */ |