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)
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 */
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
EGPrint(charptrT s)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
EGPrintTB(void)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
EGPL(charptrT s)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 */
EGLocateCommand(charptrT s)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 */
EGMapFromHostColor(siT color)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 */
EGMapToHostColor(cT c)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 */
EGMapFromHostCP(siT hostcp)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 */
EGMapToHostCP(cpT cp)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 */
EGMapFromHostSq(siT index)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 */
EGMapToHostSq(sqT sq)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 */
EGMapFromHostScore(liT score)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;
296 cpev = synth_mate(distance);
297 } else if (score <= (MAXPLY - MATE)) {
298 /* convert forced loss score */
299 distance = (MATE + score) / 2;
300 cpev = synth_loss(distance);
301 } else {
302 /* convert regular score */
303 cpev = score;
304 };
305 return cpev;
306 }
307
308 /*--> EGMapFromHostMove: map move from host style to EPD style */
EGMapFromHostMove(liT move)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
EGGetIndexedHostPosition(TREE * RESTRICT tree,siT posdex,int active)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
EGGetHostPosition(void)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
EGPutHostPosition(void)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++)
490 tree->position.board[EGMapToHostSq(sq)] = EGMapToHostCP(rb.rbv[sq]);
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
508 tree->status[0].enpassant_target = EGMapToHostSq(epsq);
509 /* copy the halfmove clock */
510 tree->status[0].reversible = hmvc;
511 /* copy the fullmove number */
512 move_number = fmvn;
513 /* set secondary host data items */
514 SetChessBitBoards(tree);
515 rep_index = 0;
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 */
EGEncodeHostHistory(void)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
EGIterate(siT wtm_flag,siT think_flag)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 */
EGCommHandler(epdptrT epdptr0,siptrT flagptr)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 */
659 sprintf(tv, "c%05hd.pgn", ((siT) getpid()));
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 };
674 sprintf(tv, "h%05hd.pml", ((siT) getpid()));
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 };
689 sprintf(tv, "h%05hd.pml", ((siT) getpid()));
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);
700 move = InputMove(tree, 0, game_wtm, 0, 0, eopptr->eop_headeov->eov_str);
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 }
706 MakeMoveRoot(tree, game_wtm, move);
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 =
742 InputMove(tree, 0, game_wtm, 0, 0, eopptr->eop_headeov->eov_str);
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 }
748 MakeMoveRoot(tree, game_wtm, move);
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 */
770 EGIterate((siT) game_wtm, (siT) think);
771 /* process search result */
772 strcpy(tv, OutputMove(tree, 0, game_wtm, last_pv.path[1]));
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 */
785 MakeMoveRoot(tree, game_wtm, move);
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);
819 InitializeHashTables(0);
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 };
827 sprintf(tv, "h%05hd.pml", ((siT) getpid()));
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 */
EGProcessAPGN(void)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 */
EGProcessBFIX(void)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 */
EGProcessCICS(void)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 */
EGProcessCOMM(void)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 */
EGProcessDPGN(void)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 */
EGProcessDSML(void)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);
1080 length = strlen(san);
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 */
EGProcessDSTR(void)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 */
EGProcessDTPV(void)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 */
EGProcessENUM(void)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 */
EGProcessHELP(void)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 */
1197 getchar();
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");
1213 getchar();
1214 EGPL("");
1215 };
1216 };
1217 };
1218 return flag;
1219 }
1220
1221 /*--> EGProcessLINK: process the EG command epdlink */
EGProcessLINK(void)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 */
EGProcessLPGN(void)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 */
EGProcessLREC(void)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 */
EGProcessMORE(void)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:
1492 EGPL("epdpfdn: Process file: data normalization");
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:
1501 EGPL("epdpfdr: Process file: data repair");
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:
1511 EGPL("epdpfga: Process file: general analysis");
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:
1520 EGPL("epdpflc: Process file: locate cooks");
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:
1532 EGPL("epdpfop: Process file: operation purge");
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:
1541 EGPL("epdscor: Score EPD analysis file");
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:
1549 EGPL("epdshow: Show EPD four fields for the current position");
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:
1575 EGPL("epdtest: Developer testing");
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 */
EGProcessNOOP(void)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 */
EGProcessPFDN(void)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 */
EGProcessPFDR(void)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 */
EGProcessPFGA(void)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)) {
1708 EGPrint(" ID: ");
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];
1725 iteration = 0;
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 */
1734 host_acd = iteration;
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 */
1740 host_acn = tree->nodes_searched;
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 */
1746 host_acs = time(NULL) - start_time;
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 */
EGProcessPFLC(void)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 */
EGProcessPFOP(void)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 */
EGProcessSCOR(void)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 */
EGProcessSHOW(void)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 */
EGProcessSPGN(void)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 */
EGProcessSTPV(void)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 */
EGProcessTEST(void)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 */
EGCommandCheck(char * s)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 */
EGCommand(char * s)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 */
EGInit(void)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 */
EGTerm(void)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 */
2358