Subversion Repositories Games.Chess Giants

Rev

Rev 108 | Go to most recent revision | 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;
154 pmbaty 296
    cpev = synth_mate(distance);
33 pmbaty 297
  } else if (score <= (MAXPLY - MATE)) {
298
/* convert forced loss score */
299
    distance = (MATE + score) / 2;
154 pmbaty 300
    cpev = synth_loss(distance);
33 pmbaty 301
  } else {
302
/* convert regular score */
154 pmbaty 303
    cpev = score;
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++)
154 pmbaty 490
    tree->position.board[EGMapToHostSq(sq)] = EGMapToHostCP(rb.rbv[sq]);
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
154 pmbaty 508
    tree->status[0].enpassant_target = EGMapToHostSq(epsq);
33 pmbaty 509
/* copy the halfmove clock */
154 pmbaty 510
  tree->status[0].reversible = hmvc;
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 */
154 pmbaty 659
        sprintf(tv, "c%05hd.pgn", ((siT) getpid()));
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
      };
154 pmbaty 674
      sprintf(tv, "h%05hd.pml", ((siT) getpid()));
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
      };
154 pmbaty 689
      sprintf(tv, "h%05hd.pml", ((siT) getpid()));
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
      };
154 pmbaty 827
      sprintf(tv, "h%05hd.pml", ((siT) getpid()));
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);
154 pmbaty 1080
        length = strlen(san);
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 */
154 pmbaty 1740
          host_acn = tree->nodes_searched;
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 */
154 pmbaty 1746
          host_acs = time(NULL) - start_time;
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 */