home *** CD-ROM | disk | FTP | other *** search
/ Dream 57 / Amiga_Dream_57.iso / Amiga / Jeux / Reflexion / Crafty-15.19.lha / crafty-15.19 / src / epd.c < prev    next >
C/C++ Source or Header  |  1998-09-13  |  146KB  |  8,064 lines

  1. /*>>> epd.c: Extended Position Description routines */
  2.  
  3. /* Revised: 1996.06.23 */
  4.  
  5. /*
  6. Copyright (C) 1996 by Steven J. Edwards (sje@mv.mv.com)
  7. All rights reserved.  This code may be freely redistibuted and used by
  8. both research and commerical applications.  No warranty exists.
  9. */
  10.  
  11. /*
  12. Everything in this source file is independent of the host program, as
  13. are the prototypes in the epd.h include file.  Requests for changes
  14. and additions should be communicated to the author via the e-mail
  15. address given above.
  16. */
  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.3.20 and using the gcc 2.7.0 compiler.
  23. */
  24.  
  25. /* system includes */
  26.  
  27. #include <stdlib.h>
  28. #include <stdio.h>
  29. #include <ctype.h>
  30. #include <string.h>
  31. #include <time.h>
  32.  
  33. /* EPD definitions (host independent) */
  34.  
  35. #include "epddefs.h"
  36.  
  37. /* EPD routine prototypes (host independent) */
  38.  
  39. #include "epd.h"
  40. #include "chess.h"
  41. #include "data.h"
  42.  
  43. /* ASCII character constants */
  44.  
  45. #define ascii_nul ((char) 0x00)
  46. #define ascii_sp  ((char) 0x20)
  47.  
  48. /* tree limit; adjust according to memory availability */
  49.  
  50. #define treeL 16384
  51.  
  52. /* tree overrun safety margin */
  53.  
  54. #define treemarginL 256
  55.  
  56. /* played moves history limit; adjust according to memory availability */
  57.  
  58. #define pmhL 512
  59.  
  60. /* data flows (input and output) */
  61.  
  62. #define flowL 2
  63.  
  64. /* character case mapping */
  65.  
  66. #define map_lower(ch) (isupper((ch)) ? tolower((ch)) : (ch))
  67. #define map_upper(ch) (islower((ch)) ? toupper((ch)) : (ch))
  68.  
  69. /* identifier character check */
  70.  
  71. #define IdentChar(ch) (isalpha((ch)) || isdigit((ch)) || ((ch) == '_'))
  72.  
  73. /* vacancy check */
  74.  
  75. #define Vacant(sq) (EPDboard.rbv[(sq)] == cp_v0)
  76.  
  77. /* token record type (for token chain) */
  78.  
  79. typedef struct tknS
  80.     {
  81.     charptrT     tkn_str;  /* allocated token string value */
  82.     struct tknS *tkn_prev; /* previous record */
  83.     struct tknS *tkn_next; /* next record */
  84.     } tknT, *tknptrT;
  85.  
  86. /* tree stack entry record type */
  87.  
  88. typedef struct tseS
  89.     {
  90.     siT   tse_count; /* entry count for this level */
  91.     mptrT tse_base;  /* first move in moveset */
  92.     mptrT tse_curr;  /* current move of interest in moveset */
  93.     } tseT, *tseptrT;
  94.  
  95. /* color to move strings */
  96.  
  97. static charptrT ctmext_strv[rcL];
  98.  
  99. /* global game chain anchors */
  100.  
  101. static gamptrT head_gamptr;
  102. static gamptrT tail_gamptr;
  103.  
  104. /* EPD standard opcode mnemonics */
  105.  
  106. static charptrT epdsostrv[epdsoL];
  107.  
  108. /* EPD refcom operand strings */
  109.  
  110. static charptrT refcomstrv[refcomL];
  111.  
  112. /* EPD refreq operand strings */
  113.  
  114. static charptrT refreqstrv[refreqL];
  115.  
  116. /* PGN Seven Tag Roster names */
  117.  
  118. static charptrT pgnstrstrv[pgnstrL];
  119.  
  120. /* game termination indication marker strings */
  121.  
  122. static charptrT gtimstrv[gtimL];
  123.  
  124. /* player name strings */
  125.  
  126. static charptrT playerstrv[rcL];
  127.  
  128. /* character conversion vectors (colors and pieces) */
  129.  
  130. static char asccv[rcL];
  131. static char ascpv[rpL];
  132.  
  133. /* character conversion vectors (ranks and files) */
  134.  
  135. static char ascrv[rankL];
  136. static char ascfv[fileL];
  137.  
  138. /* promotion piece from special case move code coversion vector */
  139.  
  140. static pT cv_p_scmvv[scmvL];
  141.  
  142. /* various color and piece conversion vectors */
  143.  
  144. static cpT cv_cp_c_pv[rcL][rpL];
  145. static cT cv_c_cpv[cpL];
  146. static pT cv_p_cpv[cpL];
  147. static cT inv_cv[rcL];
  148.  
  149. /* direction vectors */
  150.  
  151. static dvT dvv[dxL];
  152. static xdvT xdvv[dxL];
  153.  
  154. /* extension board (border detection) */
  155.  
  156. static xbT xb;
  157.  
  158. /* maps */
  159.  
  160. static siT flank_mapv[sqL];
  161. static siT triangle_mapv[sqL];
  162.  
  163. /* token chain anchors */
  164.  
  165. static tknptrT head_tknptr;
  166. static tknptrT tail_tknptr;
  167.  
  168. /* local SAN vector and its index */
  169.  
  170. static sanT lsan;
  171. static siT lsani;
  172.  
  173. /* census vectors */
  174.  
  175. static siT count_cv[rcL];
  176. static siT count_cpv[rcL][rpL];
  177.  
  178. /* the current board */
  179.  
  180. static rbT EPDboard;
  181.  
  182. /* the current environment stack entry  */
  183.  
  184. static eseT ese;
  185.  
  186. /* the current tree stack entry */
  187.  
  188. static tseT tse;
  189.  
  190. /* the master ply index */
  191.  
  192. static siT ply;
  193.  
  194. /* the base of the move tree and its current pointer */
  195.  
  196. static mptrT treebaseptr;
  197. static mptrT treeptr;
  198.  
  199. /* the base of the tree stack entry stack and its current pointer */
  200.  
  201. static tseptrT tsebaseptr;
  202. static tseptrT tseptr;
  203.  
  204. /* base of the environment stack and its current pointer */
  205.  
  206. static eseptrT esebaseptr;
  207. static eseptrT eseptr;
  208.  
  209. /* tablebase information record vector storage base */
  210.  
  211. static tbptrT tbbaseptr;
  212.  
  213. /* tablebase file pointer cache vector */
  214.  
  215. static tbcT tbcv[tbcL];
  216.  
  217. /* return area for board data */
  218.  
  219. static rbT ret_rb;
  220.  
  221. /* return area for move data */
  222.  
  223. static mT ret_m;
  224.  
  225. /*--> EPDFatal: emit fatal diagnostic and quit */
  226. nonstatic
  227. void
  228. EPDFatal(charptrT s)
  229. {
  230. fprintf(stderr, "EPD Fatal error: %s.\n", s);
  231. exit(1);
  232. }
  233.  
  234. /*--> EPDSwitchFault: emit switch fault diagnostic and quit */
  235. nonstatic
  236. void
  237. EPDSwitchFault(charptrT s)
  238. {
  239. fprintf(stderr, "Switch fault detected.\n");
  240. EPDFatal(s);
  241.  
  242. return;
  243. }
  244.  
  245. /*--> EPDMemoryGrab: allocate memory */
  246. nonstatic
  247. voidptrT
  248. EPDMemoryGrab(liT n)
  249. {
  250. voidptrT ptr;
  251.  
  252. ptr = (voidptrT) malloc((n == 0) ? 1 : n);
  253. if (ptr == NULL)
  254.     EPDFatal("EPDMemoryGrab");
  255.  
  256. return (ptr);
  257. }
  258.  
  259. /*--> EPDMemoryFree: deallocate memory */
  260. nonstatic
  261. void
  262. EPDMemoryFree(voidptrT ptr)
  263. {
  264. if (ptr != NULL)
  265.     free(ptr);
  266.  
  267. return;
  268. }
  269.  
  270. /*--> EPDStringGrab: allocate and copy a string */
  271. nonstatic
  272. charptrT
  273. EPDStringGrab(charptrT s)
  274. {
  275. charptrT ptr;
  276.  
  277. ptr = (charptrT) EPDMemoryGrab(strlen(s) + 1);
  278. strcpy(ptr, s);
  279.  
  280. return (ptr);
  281. }
  282.  
  283. /*--> EPDStringFree: deallocate a string */
  284. nonstatic
  285. void
  286. EPDStringFree(charptrT s)
  287. {
  288. EPDMemoryFree(s);
  289.  
  290. return;
  291. }
  292.  
  293. /*--> EPDStringAppendChar: append a character to a string */
  294. nonstatic
  295. charptrT
  296. EPDStringAppendChar(charptrT s, char c)
  297. {
  298. charptrT ptr;
  299. liT length;
  300.  
  301. /* the first argument is deallocated */
  302.  
  303. length = strlen(s);
  304. ptr = (charptrT) EPDMemoryGrab(length + 2);
  305. strcpy(ptr, s);
  306. EPDMemoryFree(s);
  307. *(ptr + length) = c;
  308. *(ptr + length + 1) = ascii_nul;
  309.  
  310. return (ptr);
  311. }
  312.  
  313. /*--> EPDStringAppendStr: append a string to a string */
  314. nonstatic
  315. charptrT
  316. EPDStringAppendStr(charptrT s0, charptrT s1)
  317. {
  318. charptrT ptr;
  319. liT length;
  320.  
  321. /* the first argument is deallocated */
  322.  
  323. length = strlen(s0) + strlen(s1);
  324. ptr = (charptrT) EPDMemoryGrab(length + 1);
  325. strcpy(ptr, s0);
  326. strcat(ptr, s1);
  327. EPDMemoryFree(s0);
  328.  
  329. return (ptr);
  330. }
  331.  
  332. /*--> EPDMapFromDuration: convert from duration to seconds */
  333. nonstatic
  334. liT
  335. EPDMapFromDuration(charptrT s)
  336. {
  337. liT seconds;
  338. siT scs, mns, hrs, dys;
  339.  
  340. sscanf(s, "%04hd:%02hd:%02hd:%02hd", &dys, &hrs, &mns, &scs);
  341.  
  342. seconds = ((liT) dys * 86400) +
  343.     ((liT) hrs * 3600) + ((liT) mns * 60) + (liT) scs;
  344.  
  345. return (seconds);
  346. }
  347.  
  348. /*--> EPDMapToDuration: convert from seconds to duration */
  349. nonstatic
  350. charptrT
  351. EPDMapToDuration(liT seconds)
  352. {
  353. charptrT s;
  354. siT scs, mns, hrs, dys;
  355.  
  356. s = (charptrT) EPDMemoryGrab(durationL);
  357.  
  358. scs = seconds % 60;
  359. mns = (seconds / 60) % 60;
  360. hrs = (seconds / 3600) % 24;
  361. dys = (seconds / 86400) % 10000;
  362.  
  363. sprintf(s, "%04hd:%02hd:%02hd:%02hd", dys, hrs, mns, scs);
  364.  
  365. return (s);
  366. }
  367.  
  368. /*--> EPDNewGPM: allocate and initialize a new GPM record */
  369. static
  370. gpmptrT
  371. EPDNewGPM(mptrT mptr)
  372. {
  373. gpmptrT gpmptr;
  374. cT c;
  375. sqT sq;
  376. cpT cp0, cp1;
  377.  
  378. gpmptr = (gpmptrT) EPDMemoryGrab(sizeof(gpmT));
  379.  
  380. gpmptr->gpm_m = *mptr;
  381.  
  382. gpmptr->gpm_ese.ese_actc = ese.ese_actc;
  383. gpmptr->gpm_ese.ese_cast = ese.ese_cast;
  384. gpmptr->gpm_ese.ese_epsq = ese.ese_epsq;
  385. gpmptr->gpm_ese.ese_hmvc = ese.ese_hmvc;
  386. gpmptr->gpm_ese.ese_fmvn = ese.ese_fmvn;
  387.  
  388. for (c = c_w; c <= c_b; c++)
  389.     gpmptr->gpm_ese.ese_ksqv[c] = ese.ese_ksqv[c];
  390.  
  391. for (sq = sq_a1; sq <= sq_h8; sq += 2)
  392.     {
  393.     cp0 = EPDboard.rbv[sq + 0];
  394.     cp1 = EPDboard.rbv[sq + 1];
  395.     gpmptr->gpm_nbv[sq >> 1] = ((cp1 << nybbW) | cp0);
  396.     };
  397.  
  398. gpmptr->gpm_prev = gpmptr->gpm_next = NULL;
  399.  
  400. return (gpmptr);
  401. }
  402.  
  403. /*--> EPDReleaseGPM: release a GPM record */
  404. static
  405. void
  406. EPDReleaseGPM(gpmptrT gpmptr)
  407. {
  408. if (gpmptr != NULL)
  409.     EPDMemoryFree(gpmptr);
  410.  
  411. return;
  412. }
  413.  
  414. /*--> EPDAppendGPM: append a GPM record to a game  */
  415. static
  416. void
  417. EPDAppendGPM(gamptrT gamptr, gpmptrT gpmptr)
  418. {
  419. if (gamptr->gam_tailgpm == NULL)
  420.     gamptr->gam_headgpm = gpmptr;
  421. else
  422.     gamptr->gam_tailgpm->gpm_next = gpmptr;
  423.  
  424. gpmptr->gpm_prev = gamptr->gam_tailgpm;
  425. gpmptr->gpm_next = NULL;
  426.  
  427. gamptr->gam_tailgpm = gpmptr;
  428.  
  429. return;
  430. }
  431.  
  432. /*--> EPDUnthreadGPM: unthread a GPM record from a game */
  433. static
  434. void
  435. EPDUnthreadGPM(gamptrT gamptr, gpmptrT gpmptr)
  436. {
  437. if (gpmptr->gpm_prev == NULL)
  438.     gamptr->gam_headgpm = gpmptr->gpm_next;
  439. else
  440.     gpmptr->gpm_prev->gpm_next = gpmptr->gpm_next;
  441.  
  442. if (gpmptr->gpm_next == NULL)
  443.     gamptr->gam_tailgpm = gpmptr->gpm_prev;
  444. else
  445.     gpmptr->gpm_next->gpm_prev = gpmptr->gpm_prev;
  446.  
  447. return;
  448. }
  449.  
  450. /*--> EPDReleaseGPMoveChain: release the game played moves chain */
  451. static
  452. void
  453. EPDReleaseGPMoveChain(gamptrT gamptr)
  454. {
  455. gpmptrT gpmptr;
  456.  
  457. while (gamptr->gam_headgpm != NULL)
  458.     {
  459.     gpmptr = gamptr->gam_tailgpm;
  460.     EPDUnthreadGPM(gamptr, gpmptr);
  461.     EPDReleaseGPM(gpmptr);
  462.     };
  463.  
  464. return;
  465. }
  466.  
  467. /*--> EPDNewGAM: allocate and initialize a new GAM record */
  468. static
  469. gamptrT
  470. EPDNewGAM(void)
  471. {
  472. gamptrT gamptr;
  473. pgnstrT pgnstr;
  474.  
  475. gamptr = (gamptrT) EPDMemoryGrab(sizeof(gamT));
  476.  
  477. for (pgnstr = 0; pgnstr < pgnstrL; pgnstr++)
  478.     gamptr->gam_strv[pgnstr] = EPDStringGrab("");
  479.  
  480. gamptr->gam_gtim = gtim_u;
  481.  
  482. gamptr->gam_headgpm = gamptr->gam_tailgpm = NULL;
  483. gamptr->gam_prev = gamptr->gam_next = NULL;
  484.  
  485. return (gamptr);
  486. }
  487.  
  488. /*--> EPDReleaseGAM: release a GAM record */
  489. static
  490. void
  491. EPDReleaseGAM(gamptrT gamptr)
  492. {
  493. pgnstrT pgnstr;
  494.  
  495. if (gamptr != NULL)
  496.     {
  497.     for (pgnstr = 0; pgnstr < pgnstrL; pgnstr++)
  498.         if (gamptr->gam_strv[pgnstr] != NULL)
  499.             EPDMemoryFree(gamptr->gam_strv[pgnstr]);
  500.     EPDReleaseGPMoveChain(gamptr);
  501.     EPDMemoryFree(gamptr);
  502.     };
  503.  
  504. return;
  505. }
  506.  
  507. /*--> EPDAppendGAM: append a GAM record to the game chain */
  508. static
  509. void
  510. EPDAppendGAM(gamptrT gamptr)
  511. {
  512. if (tail_gamptr == NULL)
  513.     head_gamptr = gamptr;
  514. else
  515.     tail_gamptr->gam_next = gamptr;
  516.  
  517. gamptr->gam_prev = tail_gamptr;
  518. gamptr->gam_next = NULL;
  519.  
  520. tail_gamptr = gamptr;
  521.  
  522. return;
  523. }
  524.  
  525. /*--> EPDUnthreadGAM: unthread a GAM record from the game chain */
  526. static
  527. void
  528. EPDUnthreadGAM(gamptrT gamptr)
  529. {
  530. if (gamptr->gam_prev == NULL)
  531.     head_gamptr = gamptr->gam_next;
  532. else
  533.     gamptr->gam_prev->gam_next = gamptr->gam_next;
  534.  
  535. if (gamptr->gam_next == NULL)
  536.     tail_gamptr = gamptr->gam_prev;
  537. else
  538.     gamptr->gam_next->gam_prev = gamptr->gam_prev;
  539.  
  540. return;
  541. }
  542.  
  543. /*--> EPDReleaseGameChain: release the game chain */
  544. static
  545. void
  546. EPDReleaseGameChain(void)
  547. {
  548. gamptrT gamptr;
  549.  
  550. while (head_gamptr != NULL)
  551.     {
  552.     gamptr = tail_gamptr;
  553.     EPDUnthreadGAM(gamptr);
  554.     EPDReleaseGAM(gamptr);
  555.     };
  556.  
  557. return;
  558. }
  559.  
  560. /*--> EPDGamePlyCount: return ply count of a game */
  561. static
  562. siT
  563. EPDGamePlyCount(gamptrT gamptr)
  564. {
  565. siT count;
  566. gpmptrT gpmptr;
  567.  
  568. count = 0;
  569. gpmptr = gamptr->gam_headgpm;
  570.  
  571. while (gpmptr != NULL)
  572.     {
  573.     count++;
  574.     gpmptr = gpmptr->gpm_next;
  575.     };
  576.  
  577. return (count);
  578. }
  579.  
  580. /*--> EPDGameOpen: create/open a new game structure */
  581. nonstatic
  582. gamptrT
  583. EPDGameOpen(void)
  584. {
  585. gamptrT gamptr;
  586.  
  587. gamptr = EPDNewGAM();
  588. EPDAppendGAM(gamptr);
  589.  
  590. return (gamptr);
  591. }
  592.  
  593. /*--> EPDGameClose: close/destroy a game structure */
  594. nonstatic
  595. void
  596. EPDGameClose(gamptrT gamptr)
  597. {
  598. if (gamptr != NULL)
  599.     {
  600.     EPDUnthreadGAM(gamptr);
  601.     EPDReleaseGAM(gamptr);
  602.     };
  603.  
  604. return;
  605. }
  606.  
  607. /*--> EPDGameAppendMove: append a move to a game structure */
  608. nonstatic
  609. void
  610. EPDGameAppendMove(gamptrT gamptr, mptrT mptr)
  611. {
  612. gpmptrT gpmptr;
  613.  
  614. gpmptr = EPDNewGPM(mptr);
  615. EPDAppendGPM(gamptr, gpmptr);
  616.  
  617. return;
  618. }
  619.  
  620. /*--> EPDNewTKN: allocate and initialize a new TKN record */
  621. static
  622. tknptrT
  623. EPDNewTKN(charptrT s)
  624. {
  625. tknptrT tknptr;
  626.  
  627. tknptr = (tknptrT) EPDMemoryGrab(sizeof(tknT));
  628.  
  629. tknptr->tkn_str = EPDStringGrab(s);
  630. tknptr->tkn_prev = tknptr->tkn_next = NULL;
  631.  
  632. return (tknptr);
  633. }
  634.  
  635. /*--> EPDReleaseTKN: release a TKN record */
  636. static
  637. void
  638. EPDReleaseTKN(tknptrT tknptr)
  639. {
  640. if (tknptr != NULL)
  641.     {
  642.     if (tknptr->tkn_str != NULL)
  643.         EPDMemoryFree(tknptr->tkn_str);
  644.     EPDMemoryFree(tknptr);
  645.     };
  646.  
  647. return;
  648. }
  649.  
  650. /*--> EPDAppendTKN: append a TKN record to the token chain */
  651. static
  652. void
  653. EPDAppendTKN(tknptrT tknptr)
  654. {
  655. if (tail_tknptr == NULL)
  656.     head_tknptr = tknptr;
  657. else
  658.     tail_tknptr->tkn_next = tknptr;
  659.  
  660. tknptr->tkn_prev = tail_tknptr;
  661. tknptr->tkn_next = NULL;
  662.  
  663. tail_tknptr = tknptr;
  664.  
  665. return;
  666. }
  667.  
  668. /*--> EPDUnthreadTKN: unthread a TKN record from the token chain */
  669. static
  670. void
  671. EPDUnthreadTKN(tknptrT tknptr)
  672. {
  673. if (tknptr->tkn_prev == NULL)
  674.     head_tknptr = tknptr->tkn_next;
  675. else
  676.     tknptr->tkn_prev->tkn_next = tknptr->tkn_next;
  677.  
  678. if (tknptr->tkn_next == NULL)
  679.     tail_tknptr = tknptr->tkn_prev;
  680. else
  681.     tknptr->tkn_next->tkn_prev = tknptr->tkn_prev;
  682.  
  683. return;
  684. }
  685.  
  686. /*--> EPDReleaseTokenChain: release the token chain */
  687. static
  688. void
  689. EPDReleaseTokenChain(void)
  690. {
  691. tknptrT tknptr;
  692.  
  693. while (head_tknptr != NULL)
  694.     {
  695.     tknptr = tail_tknptr;
  696.     EPDUnthreadTKN(tknptr);
  697.     EPDReleaseTKN(tknptr);
  698.     };
  699.  
  700. return;
  701. }
  702.  
  703. /*--> EPDTokenize: create the token chain */
  704. nonstatic
  705. void
  706. EPDTokenize(charptrT s)
  707. {
  708. siT i;
  709. char c;
  710. tknptrT tknptr;
  711. charptrT str;
  712.  
  713. /* first, release any existing chain */
  714.  
  715. EPDReleaseTokenChain();
  716.  
  717. /* scan the input until end of string */
  718.  
  719. i = 0;
  720. c = *(s + i++);
  721. while (c != ascii_nul)
  722.     {
  723.     /* skip leading whitespace */
  724.  
  725.     while ((c != ascii_nul) && isspace(c))
  726.         c = *(s + i++);
  727.  
  728.     /* if not at end of string, then a token has started */
  729.  
  730.     if (c != ascii_nul)
  731.         {
  732.         str = EPDStringGrab("");
  733.  
  734.         while ((c != ascii_nul) && !isspace(c))
  735.             {
  736.             str = EPDStringAppendChar(str, c);
  737.             c = *(s + i++);
  738.             };
  739.  
  740.         tknptr = EPDNewTKN(str);
  741.         EPDAppendTKN(tknptr);
  742.         EPDMemoryFree(str);
  743.         };
  744.     };
  745.  
  746. return;
  747. }
  748.  
  749. /*--> EPDTokenCount: count the tokens in the token chain */
  750. nonstatic
  751. siT
  752. EPDTokenCount(void)
  753. {
  754. siT n;
  755. tknptrT tknptr;
  756.  
  757. n = 0;
  758. tknptr = head_tknptr;
  759. while (tknptr != NULL)
  760.     {
  761.     n++;
  762.     tknptr = tknptr->tkn_next;
  763.     };
  764.  
  765. return (n);
  766. }
  767.  
  768. /*--> EPDTokenFetch: fetch n-th (zero origin) token from the token chain */
  769. nonstatic
  770. charptrT
  771. EPDTokenFetch(siT n)
  772. {
  773. charptrT s;
  774. siT i;
  775. tknptrT tknptr;
  776.  
  777. i = 0;
  778. tknptr = head_tknptr;
  779. while ((tknptr != NULL) && (i < n))
  780.     {
  781.     i++;
  782.     tknptr = tknptr->tkn_next;
  783.     };
  784.  
  785. if (tknptr == NULL)
  786.     s = NULL;
  787. else
  788.     s = tknptr->tkn_str;
  789.  
  790. return (s);
  791. }
  792.  
  793. /*--> EPDCICharEqual: test for case independent character equality */
  794. nonstatic
  795. siT
  796. EPDCICharEqual(char ch0, char ch1)
  797. {
  798. siT flag;
  799.  
  800. if (map_lower(ch0) == map_lower(ch1))
  801.     flag = 1;
  802. else
  803.     flag = 0;
  804.  
  805. return (flag);
  806. }
  807.  
  808. /*--> EPDPieceFromCP: fetch piece from color-piece */
  809. nonstatic
  810. pT
  811. EPDPieceFromCP(cpT cp)
  812. {
  813. pT p;
  814.  
  815. p = cv_p_cpv[cp];
  816.  
  817. return (p);
  818. }
  819.  
  820. /*--> EPDCheckPiece: test if a character is a piece letter */
  821. nonstatic
  822. siT
  823. EPDCheckPiece(char ch)
  824. {
  825. siT flag;
  826. pT p;
  827.  
  828. flag = 0;
  829. p = p_p;
  830. while (!flag && (p <= p_k))
  831.     if (EPDCICharEqual(ch, ascpv[p]))
  832.         flag = 1;
  833.     else
  834.         p++;
  835.  
  836. return (flag);
  837. }
  838.  
  839. /*--> EPDEvaluatePiece: evaluate a piece letter character */
  840. nonstatic
  841. pT
  842. EPDEvaluatePiece(char ch)
  843. {
  844. pT p;
  845. siT flag;
  846.  
  847. flag = 0;
  848. p = p_p;
  849. while (!flag && (p <= p_k))
  850.     if (EPDCICharEqual(ch, ascpv[p]))
  851.         flag = 1;
  852.     else
  853.         p++;
  854.  
  855. if (!flag)
  856.     p = p_nil;
  857.  
  858. return (p);
  859. }
  860.  
  861. /*--> EPDCheckColor: test if a character is a color letter */
  862. nonstatic
  863. siT
  864. EPDCheckColor(char ch)
  865. {
  866. siT flag;
  867. cT c;
  868.  
  869. flag = 0;
  870. c = c_w;
  871. while (!flag && (c <= c_b))
  872.     if (EPDCICharEqual(ch, asccv[c]))
  873.         flag = 1;
  874.     else
  875.         c++;
  876.  
  877. return (flag);
  878. }
  879.  
  880. /*--> EPDEvaluateColor: evaluate a color letter character */
  881. nonstatic
  882. cT
  883. EPDEvaluateColor(char ch)
  884. {
  885. cT c;
  886. siT flag;
  887.  
  888. flag = 0;
  889. c = c_w;
  890. while (!flag && (c <= c_b))
  891.     if (EPDCICharEqual(ch, asccv[c]))
  892.         flag = 1;
  893.     else
  894.         c++;
  895.  
  896. if (!flag)
  897.     c = c_nil;
  898.  
  899. return (c);
  900. }
  901.  
  902. /*--> EPDCheckRank: test if a character is a rank character */
  903. nonstatic
  904. siT
  905. EPDCheckRank(char ch)
  906. {
  907. siT flag;
  908. rankT rank;
  909.  
  910. flag = 0;
  911. rank = rank_1;
  912. while (!flag && (rank <= rank_8))
  913.     if (EPDCICharEqual(ch, ascrv[rank]))
  914.         flag = 1;
  915.     else
  916.         rank++;
  917.  
  918. return (flag);
  919. }
  920.  
  921. /*--> EPDEvaluateRank: evaluate a color rank character */
  922. nonstatic
  923. rankT
  924. EPDEvaluateRank(char ch)
  925. {
  926. rankT rank;
  927. siT flag;
  928.  
  929. flag = 0;
  930. rank = rank_1;
  931. while (!flag && (rank <= rank_8))
  932.     if (EPDCICharEqual(ch, ascrv[rank]))
  933.         flag = 1;
  934.     else
  935.         rank++;
  936.  
  937. if (!flag)
  938.     rank = rank_nil;
  939.  
  940. return (rank);
  941. }
  942.  
  943. /*--> EPDCheckFile: test if a character is a file character */
  944. nonstatic
  945. siT
  946. EPDCheckFile(char ch)
  947. {
  948. siT flag;
  949. fileT file;
  950.  
  951. flag = 0;
  952. file = file_a;
  953. while (!flag && (file <= file_h))
  954.     if (EPDCICharEqual(ch, ascfv[file]))
  955.         flag = 1;
  956.     else
  957.         file++;
  958.  
  959. return (flag);
  960. }
  961.  
  962. /*--> EPDEvaluateFile: evaluate a color file character */
  963. nonstatic
  964. rankT
  965. EPDEvaluateFile(char ch)
  966. {
  967. fileT file;
  968. siT flag;
  969.  
  970. flag = 0;
  971. file = file_a;
  972. while (!flag && (file <= file_h))
  973.     if (EPDCICharEqual(ch, ascfv[file]))
  974.         flag = 1;
  975.     else
  976.         file++;
  977.  
  978. if (!flag)
  979.     file = file_nil;
  980.  
  981. return (file);
  982. }
  983.  
  984. /*--> EPDNewEOV: allocate a new EOV record */
  985. nonstatic
  986. eovptrT
  987. EPDNewEOV(void)
  988. {
  989. eovptrT eovptr;
  990.  
  991. eovptr = (eovptrT) EPDMemoryGrab(sizeof(eovT));
  992.  
  993. eovptr->eov_eob = eob_nil;
  994. eovptr->eov_str = NULL;
  995. eovptr->eov_prev = eovptr->eov_next = NULL;
  996.  
  997. return (eovptr);
  998. }
  999.  
  1000. /*--> EPDReleaseEOV: release an EOV record */
  1001. nonstatic
  1002. void
  1003. EPDReleaseEOV(eovptrT eovptr)
  1004. {
  1005. if (eovptr != NULL)
  1006.     {
  1007.     if (eovptr->eov_str != NULL)
  1008.         EPDMemoryFree(eovptr->eov_str);
  1009.     EPDMemoryFree(eovptr);
  1010.     };
  1011.  
  1012. return;
  1013. }
  1014.  
  1015. /*--> EPDAppendEOV: append an EOV record */
  1016. nonstatic
  1017. void
  1018. EPDAppendEOV(eopptrT eopptr, eovptrT eovptr)
  1019. {
  1020. if (eopptr->eop_taileov == NULL)
  1021.     eopptr->eop_headeov = eovptr;
  1022. else
  1023.     eopptr->eop_taileov->eov_next = eovptr;
  1024.  
  1025. eovptr->eov_prev = eopptr->eop_taileov;
  1026. eovptr->eov_next = NULL;
  1027.  
  1028. eopptr->eop_taileov = eovptr;
  1029.  
  1030. return;
  1031. }
  1032.  
  1033. /*--> EPDUnthreadEOV: unthread an EOV record */
  1034. static
  1035. void
  1036. EPDUnthreadEOV(eopptrT eopptr, eovptrT eovptr)
  1037. {
  1038. if (eovptr->eov_prev == NULL)
  1039.     eopptr->eop_headeov = eovptr->eov_next;
  1040. else
  1041.     eovptr->eov_prev->eov_next = eovptr->eov_next;
  1042.  
  1043. if (eovptr->eov_next == NULL)
  1044.     eopptr->eop_taileov = eovptr->eov_prev;
  1045. else
  1046.     eovptr->eov_next->eov_prev = eovptr->eov_prev;
  1047.  
  1048. return;
  1049. }
  1050.  
  1051. /*--> EPDCreateEOVStr: create a new EOV record with a string value */
  1052. nonstatic
  1053. eovptrT
  1054. EPDCreateEOVStr(charptrT str)
  1055. {
  1056. eovptrT eovptr;
  1057.  
  1058. eovptr = EPDNewEOV();
  1059. eovptr->eov_eob = eob_string;
  1060. eovptr->eov_str = EPDStringGrab(str);
  1061.  
  1062. return (eovptr);
  1063. }
  1064.  
  1065. /*--> EPDCreateEOVSym: create a new EOV record with a symbol value */
  1066. nonstatic
  1067. eovptrT
  1068. EPDCreateEOVSym(charptrT sym)
  1069. {
  1070. eovptrT eovptr;
  1071.  
  1072. eovptr = EPDNewEOV();
  1073. eovptr->eov_eob = eob_symbol;
  1074. eovptr->eov_str = EPDStringGrab(sym);
  1075.  
  1076. return (eovptr);
  1077. }
  1078.  
  1079. /*--> EPDCreateEOVInt: create a new EOV record with an integer value */
  1080. nonstatic
  1081. eovptrT
  1082. EPDCreateEOVInt(liT lval)
  1083. {
  1084. eovptrT eovptr;
  1085. char tv[tL];
  1086.  
  1087. sprintf(tv, "%ld", lval);
  1088. eovptr = EPDNewEOV();
  1089. eovptr->eov_eob = eob_symbol;
  1090. eovptr->eov_str = EPDStringGrab(tv);
  1091.  
  1092. return (eovptr);
  1093. }
  1094.  
  1095. /*--> EPDLocateEOV: try to locate 1st EOV record with given string value */
  1096. nonstatic
  1097. eovptrT
  1098. EPDLocateEOV(eopptrT eopptr, charptrT strval)
  1099. {
  1100. eovptrT eovptr;
  1101. siT flag;
  1102.  
  1103. flag = 0;
  1104. eovptr = eopptr->eop_headeov;
  1105. while (!flag && (eovptr != NULL))
  1106.     if (strcmp(strval, eovptr->eov_str) == 0)
  1107.         flag = 1;
  1108.     else
  1109.         eovptr = eovptr->eov_next;
  1110.  
  1111. if (!flag)
  1112.     eovptr = NULL;
  1113.  
  1114. return (eovptr);
  1115. }
  1116.  
  1117. /*--> EPDCountEOV: count EOV entries in EOP */
  1118. nonstatic
  1119. siT
  1120. EPDCountEOV(eopptrT eopptr)
  1121. {
  1122. eovptrT eovptr;
  1123. siT count;
  1124.  
  1125. count = 0;
  1126. eovptr = eopptr->eop_headeov;
  1127. while (eovptr != NULL)
  1128.     {
  1129.     count++;
  1130.     eovptr = eovptr->eov_next;
  1131.     };
  1132.  
  1133. return (count);
  1134. }
  1135.  
  1136. /*--> EPDReplaceEOVStr: replace EOV string value with given string value */
  1137. nonstatic
  1138. void
  1139. EPDReplaceEOVStr(eovptrT eovptr, charptrT str)
  1140. {
  1141. if (eovptr->eov_str != NULL)
  1142.     {
  1143.     EPDMemoryFree(eovptr->eov_str);
  1144.     eovptr->eov_str = NULL;
  1145.     };
  1146.  
  1147. if (str != NULL)
  1148.     eovptr->eov_str = EPDStringGrab(str);
  1149.  
  1150. return;
  1151. }
  1152.  
  1153. /*--> EPDNewEOP: allocate a new EOP record */
  1154. nonstatic
  1155. eopptrT
  1156. EPDNewEOP(void)
  1157. {
  1158. eopptrT eopptr;
  1159.  
  1160. eopptr = (eopptrT) EPDMemoryGrab(sizeof(eopT));
  1161.  
  1162. eopptr->eop_opsym = NULL;
  1163. eopptr->eop_headeov = eopptr->eop_taileov = NULL;
  1164. eopptr->eop_prev = eopptr->eop_next = NULL;
  1165.  
  1166. return (eopptr);
  1167. }
  1168.  
  1169. /*--> EPDReleaseEOP: release an EOP record */
  1170. nonstatic
  1171. void
  1172. EPDReleaseEOP(eopptrT eopptr)
  1173. {
  1174. eovptrT eovptr0, eovptr1;
  1175.  
  1176. if (eopptr != NULL)
  1177.     {
  1178.     if (eopptr->eop_opsym != NULL)
  1179.         EPDMemoryFree(eopptr->eop_opsym);
  1180.     eovptr0 = eopptr->eop_headeov;
  1181.     while (eovptr0 != NULL)
  1182.         {
  1183.         eovptr1 = eovptr0->eov_next;
  1184.         EPDUnthreadEOV(eopptr, eovptr0);
  1185.         EPDReleaseEOV(eovptr0);
  1186.         eovptr0 = eovptr1;
  1187.         };
  1188.     EPDMemoryFree(eopptr);
  1189.     };
  1190.  
  1191. return;
  1192. }
  1193.  
  1194. /*--> EPDAppendEOP: append an EOP record */
  1195. nonstatic
  1196. void
  1197. EPDAppendEOP(epdptrT epdptr, eopptrT eopptr)
  1198. {
  1199. if (epdptr->epd_taileop == NULL)
  1200.     epdptr->epd_headeop = eopptr;
  1201. else
  1202.     epdptr->epd_taileop->eop_next = eopptr;
  1203.  
  1204. eopptr->eop_prev = epdptr->epd_taileop;
  1205. eopptr->eop_next = NULL;
  1206.  
  1207. epdptr->epd_taileop = eopptr;
  1208.  
  1209. return;
  1210. }
  1211.  
  1212. /*--> EPDUnthreadEOP: unthread an EOP record */
  1213. static
  1214. void
  1215. EPDUnthreadEOP(epdptrT epdptr, eopptrT eopptr)
  1216. {
  1217. if (eopptr->eop_prev == NULL)
  1218.     epdptr->epd_headeop = eopptr->eop_next;
  1219. else
  1220.     eopptr->eop_prev->eop_next = eopptr->eop_next;
  1221.  
  1222. if (eopptr->eop_next == NULL)
  1223.     epdptr->epd_taileop = eopptr->eop_prev;
  1224. else
  1225.     eopptr->eop_next->eop_prev = eopptr->eop_prev;
  1226.  
  1227. return;
  1228. }
  1229.  
  1230. /*--> EPDCreateEOP: create a new EOP record with opsym */
  1231. nonstatic
  1232. eopptrT
  1233. EPDCreateEOP(charptrT opsym)
  1234. {
  1235. eopptrT eopptr;
  1236.  
  1237. eopptr = EPDNewEOP();
  1238. eopptr->eop_opsym = EPDStringGrab(opsym);
  1239.  
  1240. return (eopptr);
  1241. }
  1242.  
  1243. /*--> EPDCreateEOPCode: create a new EOP record using opsym index */
  1244. nonstatic
  1245. eopptrT
  1246. EPDCreateEOPCode(epdsoT epdso)
  1247. {
  1248. eopptrT eopptr;
  1249.  
  1250. eopptr = EPDCreateEOP(EPDFetchOpsym(epdso));
  1251.  
  1252. return (eopptr);
  1253. }
  1254.  
  1255. /*--> EPDLocateEOP: attempt to locate EOP record with given opsym */
  1256. nonstatic
  1257. eopptrT
  1258. EPDLocateEOP(epdptrT epdptr, charptrT opsym)
  1259. {
  1260. eopptrT eopptr;
  1261. siT flag;
  1262.  
  1263. flag = 0;
  1264. eopptr = epdptr->epd_headeop;
  1265. while (!flag && (eopptr != NULL))
  1266.     if (strcmp(opsym, eopptr->eop_opsym) == 0)
  1267.         flag = 1;
  1268.     else
  1269.         eopptr = eopptr->eop_next;
  1270.  
  1271. if (!flag)
  1272.     eopptr = NULL;
  1273.  
  1274. return (eopptr);
  1275. }
  1276.  
  1277. /*--> EPDLocateEOPCode: attempt to locate EOP record with given code */
  1278. nonstatic
  1279. eopptrT
  1280. EPDLocateEOPCode(epdptrT epdptr, epdsoT epdso)
  1281. {
  1282.  
  1283. return (EPDLocateEOP(epdptr, epdsostrv[epdso]));
  1284. }
  1285.  
  1286. /*--> EPDCountEOP: count EOP entries in EPD */
  1287. nonstatic
  1288. siT
  1289. EPDCountEOP(epdptrT epdptr)
  1290. {
  1291. eopptrT eopptr;
  1292. siT count;
  1293.  
  1294. count = 0;
  1295. eopptr = epdptr->epd_headeop;
  1296. while (eopptr != NULL)
  1297.     {
  1298.     count++;
  1299.     eopptr = eopptr->eop_next;
  1300.     };
  1301.  
  1302. return (count);
  1303. }
  1304.  
  1305. /*--> EPDDropIfLocEOP: try to locate/drop EOP record with given opsym */
  1306. nonstatic
  1307. void
  1308. EPDDropIfLocEOP(epdptrT epdptr, charptrT opsym)
  1309. {
  1310. eopptrT eopptr;
  1311.  
  1312. eopptr = EPDLocateEOP(epdptr, opsym);
  1313. if (eopptr != NULL)
  1314.     {
  1315.     EPDUnthreadEOP(epdptr, eopptr);
  1316.     EPDReleaseEOP(eopptr);
  1317.     };
  1318.  
  1319. return;
  1320. }
  1321.  
  1322. /*--> EPDDropIfLocEOPCode: try to locate/drop EOP record with given code */
  1323. nonstatic
  1324. void
  1325. EPDDropIfLocEOPCode(epdptrT epdptr, epdsoT epdso)
  1326. {
  1327. eopptrT eopptr;
  1328.  
  1329. eopptr = EPDLocateEOP(epdptr, epdsostrv[epdso]);
  1330. if (eopptr != NULL)
  1331.     {
  1332.     EPDUnthreadEOP(epdptr, eopptr);
  1333.     EPDReleaseEOP(eopptr);
  1334.     };
  1335.  
  1336. return;
  1337. }
  1338.  
  1339. /*--> EPDAddOpInt: add a single integer operand operation */
  1340. nonstatic
  1341. void
  1342. EPDAddOpInt(epdptrT epdptr, epdsoT epdso, liT val)
  1343. {
  1344. eopptrT eopptr;
  1345. eovptrT eovptr;
  1346.  
  1347. eovptr = EPDCreateEOVInt(val);
  1348. eopptr = EPDCreateEOPCode(epdso);
  1349. EPDAppendEOV(eopptr, eovptr);
  1350. EPDDropIfLocEOPCode(epdptr, epdso);
  1351. EPDAppendEOP(epdptr, eopptr);
  1352.  
  1353. return;
  1354. }
  1355.  
  1356. /*--> EPDAddOpStr: add a single string operand operation */
  1357. nonstatic
  1358. void
  1359. EPDAddOpStr(epdptrT epdptr, epdsoT epdso, charptrT s)
  1360. {
  1361. eopptrT eopptr;
  1362. eovptrT eovptr;
  1363.  
  1364. eovptr = EPDCreateEOVStr(s);
  1365. eopptr = EPDCreateEOPCode(epdso);
  1366. EPDAppendEOV(eopptr, eovptr);
  1367. EPDDropIfLocEOPCode(epdptr, epdso);
  1368. EPDAppendEOP(epdptr, eopptr);
  1369.  
  1370. return;
  1371. }
  1372.  
  1373. /*--> EPDAddOpSym: add a single symbol operand operation */
  1374. nonstatic
  1375. void
  1376. EPDAddOpSym(epdptrT epdptr, epdsoT epdso, charptrT s)
  1377. {
  1378. eopptrT eopptr;
  1379. eovptrT eovptr;
  1380.  
  1381. eovptr = EPDCreateEOVSym(s);
  1382. eopptr = EPDCreateEOPCode(epdso);
  1383. EPDAppendEOV(eopptr, eovptr);
  1384. EPDDropIfLocEOPCode(epdptr, epdso);
  1385. EPDAppendEOP(epdptr, eopptr);
  1386.  
  1387. return;
  1388. }
  1389.  
  1390. /*--> EPDNewEPD: allocate a new EPD record */
  1391. nonstatic
  1392. epdptrT
  1393. EPDNewEPD(void)
  1394. {
  1395. epdptrT epdptr;
  1396. siT i;
  1397.  
  1398. epdptr = (epdptrT) EPDMemoryGrab(sizeof(epdT));
  1399.  
  1400. for (i = 0; i < nbL; i++)
  1401.     epdptr->epd_nbv[i] = ((cp_v0 << nybbW) | cp_v0);
  1402.  
  1403. epdptr->epd_actc = c_v;
  1404. epdptr->epd_cast = 0;
  1405. epdptr->epd_epsq = sq_nil;
  1406. epdptr->epd_headeop = epdptr->epd_taileop = NULL;
  1407.  
  1408. return (epdptr);
  1409. }
  1410.  
  1411. /*--> EPDReleaseOperations: release EPD operation list */
  1412. nonstatic
  1413. void
  1414. EPDReleaseOperations(epdptrT epdptr)
  1415. {
  1416. eopptrT eopptr0, eopptr1;
  1417.  
  1418. if (epdptr != NULL)
  1419.     {
  1420.     eopptr0 = epdptr->epd_headeop;
  1421.     while (eopptr0 != NULL)
  1422.         {
  1423.         eopptr1 = eopptr0->eop_next;
  1424.         EPDUnthreadEOP(epdptr, eopptr0);
  1425.         EPDReleaseEOP(eopptr0);
  1426.         eopptr0 = eopptr1;
  1427.         };
  1428.     epdptr->epd_headeop = NULL;
  1429.     epdptr->epd_taileop = NULL;
  1430.     };
  1431.  
  1432. return;
  1433. }
  1434.  
  1435. /*--> EPDReleaseEPD: release an EPD record */
  1436. nonstatic
  1437. void
  1438. EPDReleaseEPD(epdptrT epdptr)
  1439. {
  1440. if (epdptr != NULL)
  1441.     {
  1442.     EPDReleaseOperations(epdptr);
  1443.     EPDMemoryFree(epdptr);
  1444.     };
  1445.  
  1446. return;
  1447. }
  1448.  
  1449. /*--> EPDFetchOpsym: return a pointer to the indicated mnemonic */
  1450. nonstatic
  1451. charptrT
  1452. EPDFetchOpsym(epdsoT epdso)
  1453. {
  1454. return (epdsostrv[epdso]);
  1455. }
  1456.  
  1457. /*--> EPDCountOperands: count operands */
  1458. static
  1459. siT
  1460. EPDCountOperands(eopptrT eopptr)
  1461. {
  1462. siT count;
  1463. eovptrT eovptr;
  1464.  
  1465. count = 0;
  1466. eovptr = eopptr->eop_headeov;
  1467. while (eovptr != NULL)
  1468.     {
  1469.     count++;
  1470.     eovptr = eovptr->eov_next;
  1471.     };
  1472.  
  1473. return (count);
  1474. }
  1475.  
  1476. /*--> EPDCountOperations: count operations */
  1477. static
  1478. siT
  1479. EPDCountOperations(epdptrT epdptr)
  1480. {
  1481. siT count;
  1482. eopptrT eopptr;
  1483.  
  1484. count = 0;
  1485. eopptr = epdptr->epd_headeop;
  1486. while (eopptr != NULL)
  1487.     {
  1488.     count++;
  1489.     eopptr = eopptr->eop_next;
  1490.     };
  1491.  
  1492. return (count);
  1493. }
  1494.  
  1495. /*--> EPDSortOperands: sort operands according to string value */
  1496. static
  1497. void
  1498. EPDSortOperands(eopptrT eopptr)
  1499. {
  1500. siT count;
  1501. siT pass, flag;
  1502. eovptrT ptr0, ptr1, ptr2, ptr3;
  1503.  
  1504. count = EPDCountOperands(eopptr);
  1505. if (count > 1)
  1506.     {
  1507.     flag = 1;
  1508.     pass = 0;
  1509.     while (flag && (pass < (count - 1)))
  1510.         {
  1511.         flag = 0;
  1512.         ptr0 = eopptr->eop_headeov;
  1513.         ptr1 = ptr0->eov_next;
  1514.         while (ptr1 != NULL)
  1515.             {
  1516.             if (strcmp(ptr0->eov_str, ptr1->eov_str) > 0)
  1517.                 {
  1518.                 flag = 1;
  1519.  
  1520.                 ptr2 = ptr0->eov_prev;
  1521.                 ptr3 = ptr1->eov_next;
  1522.  
  1523.                 ptr0->eov_prev = ptr1;
  1524.                 ptr0->eov_next = ptr3;
  1525.  
  1526.                 ptr1->eov_prev = ptr2;
  1527.                 ptr1->eov_next = ptr0;
  1528.  
  1529.                 if (ptr2 == NULL)
  1530.                     eopptr->eop_headeov = ptr1;
  1531.                 else
  1532.                     ptr2->eov_next = ptr1;
  1533.  
  1534.                 if (ptr3 == NULL)
  1535.                     eopptr->eop_taileov = ptr0;
  1536.                 else
  1537.                     ptr3->eov_prev = ptr0;
  1538.                 }
  1539.             else
  1540.                 ptr0 = ptr1;
  1541.  
  1542.             ptr1 = ptr0->eov_next;
  1543.             };
  1544.         pass++;
  1545.         };
  1546.     };
  1547.  
  1548. return;
  1549. }
  1550.  
  1551. /*--> EPDSortOperations: sort operations according to opcode */
  1552. static
  1553. void
  1554. EPDSortOperations(epdptrT epdptr)
  1555. {
  1556. siT count;
  1557. siT pass, flag;
  1558. eopptrT ptr0, ptr1, ptr2, ptr3;
  1559.  
  1560. count = EPDCountOperations(epdptr);
  1561. if (count > 1)
  1562.     {
  1563.     flag = 1;
  1564.     pass = 0;
  1565.     while (flag && (pass < (count - 1)))
  1566.         {
  1567.         flag = 0;
  1568.         ptr0 = epdptr->epd_headeop;
  1569.         ptr1 = ptr0->eop_next;
  1570.         while (ptr1 != NULL)
  1571.             {
  1572.             if (strcmp(ptr0->eop_opsym, ptr1->eop_opsym) > 0)
  1573.                 {
  1574.                 flag = 1;
  1575.  
  1576.                 ptr2 = ptr0->eop_prev;
  1577.                 ptr3 = ptr1->eop_next;
  1578.  
  1579.                 ptr0->eop_prev = ptr1;
  1580.                 ptr0->eop_next = ptr3;
  1581.  
  1582.                 ptr1->eop_prev = ptr2;
  1583.                 ptr1->eop_next = ptr0;
  1584.  
  1585.                 if (ptr2 == NULL)
  1586.                     epdptr->epd_headeop = ptr1;
  1587.                 else
  1588.                     ptr2->eop_next = ptr1;
  1589.  
  1590.                 if (ptr3 == NULL)
  1591.                     epdptr->epd_taileop = ptr0;
  1592.                 else
  1593.                     ptr3->eop_prev = ptr0;
  1594.                 }
  1595.             else
  1596.                 ptr0 = ptr1;
  1597.  
  1598.             ptr1 = ptr0->eop_next;
  1599.             };
  1600.         pass++;
  1601.         };
  1602.     };
  1603.  
  1604. return;
  1605. }
  1606.  
  1607. /*--> EPDNormalize: apply normalizing sorts */
  1608. static
  1609. void
  1610. EPDNormalize(epdptrT epdptr)
  1611. {
  1612. eopptrT eopptr;
  1613. charptrT opsym;
  1614. siT flag;
  1615.  
  1616. /* sort all operations */
  1617.  
  1618. EPDSortOperations(epdptr);
  1619.  
  1620. /* sort operands for selected standard operations */
  1621.  
  1622. eopptr = epdptr->epd_headeop;
  1623. while (eopptr != NULL)
  1624.     {
  1625.     flag = 0;
  1626.     opsym = eopptr->eop_opsym;
  1627.  
  1628.     if (!flag && (strcmp(opsym, epdsostrv[epdso_am]) == 0))
  1629.         {
  1630.         EPDSortOperands(eopptr);
  1631.         flag = 1;
  1632.         };
  1633.  
  1634.     if (!flag && (strcmp(opsym, epdsostrv[epdso_bm]) == 0))
  1635.         {
  1636.         EPDSortOperands(eopptr);
  1637.         flag = 1;
  1638.         };
  1639.  
  1640.     eopptr = eopptr->eop_next;
  1641.     };
  1642.  
  1643. return;
  1644. }
  1645.  
  1646. /*--> EPDCloneEPDBase: clone an EPD structure, base items only */
  1647. nonstatic
  1648. epdptrT
  1649. EPDCloneEPDBase(epdptrT epdptr)
  1650. {
  1651. epdptrT nptr;
  1652. siT index;
  1653.  
  1654. nptr = EPDNewEPD();
  1655.  
  1656. for (index = 0; index < nbL; index++)
  1657.     nptr->epd_nbv[index] = epdptr->epd_nbv[index];
  1658.  
  1659. nptr->epd_actc = epdptr->epd_actc;
  1660. nptr->epd_cast = epdptr->epd_cast;
  1661. nptr->epd_epsq = epdptr->epd_epsq;
  1662.  
  1663. return (nptr);
  1664. }
  1665.  
  1666. /*--> EPDCloneEOV: clone an EOV structure */
  1667. nonstatic
  1668. eovptrT
  1669. EPDCloneEOV(eovptrT eovptr)
  1670. {
  1671. eovptrT nptr;
  1672.  
  1673. nptr = EPDNewEOV();
  1674.  
  1675. nptr->eov_eob = eovptr->eov_eob;
  1676.  
  1677. if (eovptr->eov_str != NULL)
  1678.     nptr->eov_str = EPDStringGrab(eovptr->eov_str);
  1679.  
  1680. return (nptr);
  1681. }
  1682.  
  1683. /*--> EPDCloneEOP: clone an EOP structure */
  1684. nonstatic
  1685. eopptrT
  1686. EPDCloneEOP(eopptrT eopptr)
  1687. {
  1688. eopptrT nptr;
  1689. eovptrT eovptr, rptr;
  1690.  
  1691. nptr = EPDNewEOP();
  1692.  
  1693. if (eopptr->eop_opsym != NULL)
  1694.     nptr->eop_opsym = EPDStringGrab(eopptr->eop_opsym);
  1695.  
  1696. rptr = eopptr->eop_headeov;
  1697. while (rptr != NULL)
  1698.     {
  1699.     eovptr = EPDCloneEOV(rptr);
  1700.     EPDAppendEOV(nptr, eovptr);
  1701.     rptr = rptr->eov_next;
  1702.     };
  1703.  
  1704. return (nptr);
  1705. }
  1706.  
  1707. /*--> EPDCloneEPD: clone an EPD structure */
  1708. nonstatic
  1709. epdptrT
  1710. EPDCloneEPD(epdptrT epdptr)
  1711. {
  1712. epdptrT nptr;
  1713. eopptrT eopptr, rptr;
  1714.  
  1715. nptr = EPDCloneEPDBase(epdptr);
  1716.  
  1717. rptr = epdptr->epd_headeop;
  1718. while (rptr != NULL)
  1719.     {
  1720.     eopptr = EPDCloneEOP(rptr);
  1721.     EPDAppendEOP(nptr, eopptr);
  1722.     rptr = rptr->eop_next;
  1723.     };
  1724.  
  1725. return (nptr);
  1726. }
  1727.  
  1728. /*--> EPDSetKings: set the king location vector */
  1729. static
  1730. void
  1731. EPDSetKings(void)
  1732. {
  1733. sqT sq;
  1734.  
  1735. /* this operates only on the local environment */
  1736.  
  1737. ese.ese_ksqv[c_w] = ese.ese_ksqv[c_b] = sq_nil;
  1738.  
  1739. for (sq = sq_a1; sq <= sq_h8; sq++)
  1740.     switch (EPDboard.rbv[sq])
  1741.         {
  1742.         case cp_wk:
  1743.             ese.ese_ksqv[c_w] = sq;
  1744.             break;
  1745.         case cp_bk:
  1746.             ese.ese_ksqv[c_b] = sq;
  1747.             break;
  1748.         default:
  1749.             break;
  1750.         };
  1751.  
  1752. return;
  1753. }
  1754.  
  1755. /*--> EPDSet: set up an EPD structure for the given position */
  1756. nonstatic
  1757. epdptrT
  1758. EPDSet(rbptrT rbptr, cT actc, castT cast, sqT epsq)
  1759. {
  1760. epdptrT epdptr;
  1761. sqT sq;
  1762. cpT cp0, cp1;
  1763.  
  1764. /* this does not reference the current position */
  1765.  
  1766. epdptr = EPDNewEPD();
  1767.  
  1768. for (sq = sq_a1; sq <= sq_h8; sq += 2)
  1769.     {
  1770.     cp0 = rbptr->rbv[sq + 0];
  1771.     cp1 = rbptr->rbv[sq + 1];
  1772.     epdptr->epd_nbv[sq >> 1] = ((cp1 << nybbW) | cp0);
  1773.     };
  1774.  
  1775. epdptr->epd_actc = actc;
  1776. epdptr->epd_cast = cast;
  1777. epdptr->epd_epsq = epsq;
  1778.  
  1779. return (epdptr);
  1780. }
  1781.  
  1782. /*--> EPDSetCurrentPosition: set current position */
  1783. nonstatic
  1784. void
  1785. EPDSetCurrentPosition(rbptrT rbptr, cT actc, castT cast, sqT epsq, siT hmvc, siT fmvn)
  1786. {
  1787. sqT sq;
  1788.  
  1789. /* this changes the current position */
  1790.  
  1791. for (sq = sq_a1; sq <= sq_h8; sq++)
  1792.     EPDboard.rbv[sq] = rbptr->rbv[sq];
  1793.  
  1794. ese.ese_actc = actc;
  1795. ese.ese_cast = cast;
  1796. ese.ese_epsq = epsq;
  1797. ese.ese_hmvc = hmvc;
  1798. ese.ese_fmvn = fmvn;
  1799.  
  1800. EPDSetKings();
  1801.  
  1802. return;
  1803. }
  1804.  
  1805. /*--> EPDGetCurrentPosition: return EPD structure for current position */
  1806. nonstatic
  1807. epdptrT
  1808. EPDGetCurrentPosition(void)
  1809. {
  1810. epdptrT epdptr;
  1811. sqT sq;
  1812. cpT cp0, cp1;
  1813.  
  1814. epdptr = EPDNewEPD();
  1815.  
  1816. for (sq = sq_a1; sq <= sq_h8; sq += 2)
  1817.     {
  1818.     cp0 = EPDboard.rbv[sq + 0];
  1819.     cp1 = EPDboard.rbv[sq + 1];
  1820.     epdptr->epd_nbv[sq >> 1] = ((cp1 << nybbW) | cp0);
  1821.     };
  1822.  
  1823. epdptr->epd_actc = ese.ese_actc;
  1824. epdptr->epd_cast = ese.ese_cast;
  1825. epdptr->epd_epsq = ese.ese_epsq;
  1826.  
  1827. return (epdptr);
  1828. }
  1829.  
  1830. /*--> EPDFetchACTC: fetch current active color */
  1831. nonstatic
  1832. cT
  1833. EPDFetchACTC(void)
  1834. {
  1835. /* return the value of the current active color */
  1836.  
  1837. return (ese.ese_actc);
  1838. }
  1839.  
  1840. /*--> EPDFetchCAST: fetch current castling availability */
  1841. nonstatic
  1842. castT
  1843. EPDFetchCAST(void)
  1844. {
  1845. /* return the value of the current castling availability */
  1846.  
  1847. return (ese.ese_cast);
  1848. }
  1849.  
  1850. /*--> EPDFetchEPSQ: fetch current en passant target square */
  1851. nonstatic
  1852. sqT
  1853. EPDFetchEPSQ(void)
  1854. {
  1855. /* return the value of the current en passant target square */
  1856.  
  1857. return (ese.ese_epsq);
  1858. }
  1859.  
  1860. /*--> EPDFetchHMVC: fetch current halfmove clock */
  1861. nonstatic
  1862. siT
  1863. EPDFetchHMVC(void)
  1864. {
  1865. /* return the value of the current halfmove clock */
  1866.  
  1867. return (ese.ese_hmvc);
  1868. }
  1869.  
  1870. /*--> EPDFetchFMVN: fetch current fullmove number */
  1871. nonstatic
  1872. siT
  1873. EPDFetchFMVN(void)
  1874. {
  1875. /* return the value of the current fullmove number */
  1876.  
  1877. return (ese.ese_fmvn);
  1878. }
  1879.  
  1880. /*--> EPDFetchBoard: fetch current board */
  1881. nonstatic
  1882. rbptrT
  1883. EPDFetchBoard(void)
  1884. {
  1885. /* copy from the local board into the designated static return area */
  1886.  
  1887. ret_rb = EPDboard;
  1888.  
  1889. return (&ret_rb);
  1890. }
  1891.  
  1892. /*--> EPDFetchCP: fetch color-piece */
  1893. nonstatic
  1894. cpT
  1895. EPDFetchCP(sqT sq)
  1896. {
  1897. cpT cp;
  1898.  
  1899. /* fetch from the local board */
  1900.  
  1901. cp = EPDboard.rbv[sq];
  1902.  
  1903. return (cp);
  1904. }
  1905.  
  1906. /*--> EPDFetchBoardString: create and return a board diagram */
  1907. nonstatic
  1908. charptrT
  1909. EPDFetchBoardString(void)
  1910. {
  1911. charptrT s;
  1912. charptrT r;
  1913. rankT rank;
  1914. fileT file;
  1915. cpT cp;
  1916.  
  1917. /* allocate */
  1918.  
  1919. s = (charptrT) EPDMemoryGrab((rankL * ((fileL * 2) + 1)) + 1);
  1920.  
  1921. /* fill */
  1922.  
  1923. r = s;
  1924. for (rank = rank_8; rank >= rank_1; rank--)
  1925.     {
  1926.     for (file = file_a; file <= file_h; file++)
  1927.         {
  1928.         cp = EPDboard.rbm[rank][file];
  1929.         if (cp == cp_v0) {
  1930.             if ((rank % 2) == (file % 2))
  1931.                 {
  1932.                 *r++ = ':';
  1933.                 *r++ = ':';
  1934.                 }
  1935.             else
  1936.                 {
  1937.                 *r++ = ascii_sp;
  1938.                 *r++ = ascii_sp;
  1939.                 }
  1940.                 }
  1941.         else
  1942.             {
  1943.             *r++ = asccv[cv_c_cpv[cp]];
  1944.             *r++ = ascpv[cv_p_cpv[cp]];
  1945.             };
  1946.         };
  1947.     *r++ = '\n';
  1948.     };
  1949.  
  1950. /* terminating NUL */
  1951.  
  1952. *r = ascii_nul;
  1953.  
  1954. return (s);
  1955. }
  1956.  
  1957. /*--> EPDGetGTIM: get game termination marker indicator */
  1958. nonstatic
  1959. gtimT
  1960. EPDGetGTIM(gamptrT gamptr)
  1961. {
  1962.  
  1963. return (gamptr->gam_gtim);
  1964. }
  1965.  
  1966. /*--> EPDPutGTIM: put game termination marker indicator */
  1967. nonstatic
  1968. void
  1969. EPDPutGTIM(gamptrT gamptr, gtimT gtim)
  1970. {
  1971. gamptr->gam_gtim = gtim;
  1972.  
  1973. return;
  1974. }
  1975.  
  1976. /*--> EPDGenBasic: generate basic EPD notation for a given position */
  1977. nonstatic
  1978. charptrT
  1979. EPDGenBasic(rbptrT rbptr, cT actc, castT cast, sqT epsq)
  1980. {
  1981. charptrT ptr;
  1982. epdptrT epdptr;
  1983.  
  1984. /* this does not reference the current position */
  1985.  
  1986. epdptr = EPDSet(rbptr, actc, cast, epsq);
  1987. ptr = EPDEncode(epdptr);
  1988.  
  1989. EPDReleaseEPD(epdptr);
  1990.  
  1991. return (ptr);
  1992. }
  1993.  
  1994. /*--> EPDGenBasicCurrent: generate basic EPD for current position */
  1995. nonstatic
  1996. charptrT
  1997. EPDGenBasicCurrent(void)
  1998. {
  1999. charptrT ptr;
  2000.  
  2001. /* this references but does not change the current position */
  2002.  
  2003. ptr = EPDGenBasic(&EPDboard, ese.ese_actc, ese.ese_cast, ese.ese_epsq);
  2004.  
  2005. return (ptr);
  2006. }
  2007.  
  2008. /*--> EPDDecodeFEN: read a FEN string to make an EPD structure */
  2009. nonstatic
  2010. epdptrT
  2011. EPDDecodeFEN(charptrT s)
  2012. {
  2013. epdptrT epdptr;
  2014. siT flag;
  2015. tknptrT save_head_tknptr, save_tail_tknptr;
  2016. charptrT tptr;
  2017.  
  2018. /* this does not reference the current position */
  2019.  
  2020. flag = 1;
  2021. epdptr = NULL;
  2022. tptr = NULL;
  2023.  
  2024. /* save the initial token chain pointers */
  2025.  
  2026. save_head_tknptr = head_tknptr;
  2027. save_tail_tknptr = tail_tknptr;
  2028.  
  2029. /* clear the token chain pointers */
  2030.  
  2031. head_tknptr = NULL;
  2032. tail_tknptr = NULL;
  2033.  
  2034. /* tokenize the input */
  2035.  
  2036. EPDTokenize(s);
  2037.  
  2038. /* check for six tokens */
  2039.  
  2040. if (flag)
  2041.     if (EPDTokenCount() != 6)
  2042.         flag = 0;
  2043.  
  2044. /* construct an input string from the tokens */
  2045.  
  2046. if (flag)
  2047.     {
  2048.     /* handle the first four common fields */
  2049.  
  2050.     tptr = EPDStringGrab("");
  2051.     tptr = EPDStringAppendStr(tptr, EPDTokenFetch(0));
  2052.     tptr = EPDStringAppendChar(tptr, ascii_sp);
  2053.     tptr = EPDStringAppendStr(tptr, EPDTokenFetch(1));
  2054.     tptr = EPDStringAppendChar(tptr, ascii_sp);
  2055.     tptr = EPDStringAppendStr(tptr, EPDTokenFetch(2));
  2056.     tptr = EPDStringAppendChar(tptr, ascii_sp);
  2057.     tptr = EPDStringAppendStr(tptr, EPDTokenFetch(3));
  2058.     tptr = EPDStringAppendChar(tptr, ascii_sp);
  2059.  
  2060.     /* append the halfmove clock operation */
  2061.  
  2062.     tptr = EPDStringAppendStr(tptr, epdsostrv[epdso_hmvc]);
  2063.     tptr = EPDStringAppendChar(tptr, ascii_sp);
  2064.     tptr = EPDStringAppendStr(tptr, EPDTokenFetch(4));
  2065.     tptr = EPDStringAppendChar(tptr, ';');
  2066.     tptr = EPDStringAppendChar(tptr, ascii_sp);
  2067.  
  2068.     /* append the fullmove number operation */
  2069.  
  2070.     tptr = EPDStringAppendStr(tptr, epdsostrv[epdso_fmvn]);
  2071.     tptr = EPDStringAppendChar(tptr, ascii_sp);
  2072.     tptr = EPDStringAppendStr(tptr, EPDTokenFetch(5));
  2073.     tptr = EPDStringAppendChar(tptr, ';');
  2074.     };
  2075.  
  2076. /* release the temporary token chain */
  2077.  
  2078. EPDReleaseTokenChain();
  2079.  
  2080. /* restore the initial token chain pointers */
  2081.  
  2082. head_tknptr = save_head_tknptr;
  2083. tail_tknptr = save_tail_tknptr;
  2084.  
  2085. /* read the resulting EPD input string */
  2086.  
  2087. if (flag)
  2088.     {
  2089.     epdptr = EPDDecode(tptr);
  2090.     if (epdptr == NULL)
  2091.         flag = 0;
  2092.     };
  2093.  
  2094. /* cancellations if a problem occurred */
  2095.  
  2096. if (!flag)
  2097.     {
  2098.     if (tptr != NULL)
  2099.         EPDMemoryFree(tptr);
  2100.  
  2101.     if (epdptr != NULL)
  2102.         {
  2103.         EPDReleaseEPD(epdptr);
  2104.         epdptr = NULL;
  2105.         };
  2106.     };
  2107.  
  2108. return (epdptr);
  2109. }
  2110.  
  2111. /*--> EPDEncodeFEN: make a FEN string from an EPD structure */
  2112. nonstatic
  2113. charptrT
  2114. EPDEncodeFEN(epdptrT epdptr)
  2115. {
  2116. charptrT s;
  2117. char ch;
  2118. siT bi;
  2119. siT ps;
  2120. sqT sq;
  2121. cpT cp;
  2122. rankT rank;
  2123. fileT file;
  2124. eopptrT eopptr;
  2125. char nv[tL];
  2126. char bv[tL];
  2127.  
  2128. /* this does not reference the current position */
  2129.  
  2130. bi = 0;
  2131.  
  2132. /* output board */
  2133.  
  2134. for (rank = rank_8; rank >= rank_1; rank--)
  2135.     {
  2136.     ps = 0;
  2137.     for (file = file_a; file <= file_h; file++)
  2138.         {
  2139.         sq = map_sq(rank, file);
  2140.         if ((sq % 2) == 0)
  2141.             cp = (epdptr->epd_nbv[sq >> 1] & nybbM);
  2142.         else
  2143.             cp = ((epdptr->epd_nbv[sq >> 1] >> nybbW) & nybbM);
  2144.  
  2145.         if (cp == cp_v0)
  2146.             ps++;
  2147.         else
  2148.             {
  2149.             if (ps != 0)
  2150.                 {
  2151.                 bv[bi++] = '0' + ps;
  2152.                 ps = 0;
  2153.                 };
  2154.             ch = ascpv[cv_p_cpv[cp]];
  2155.             if (cv_c_cpv[cp] == c_w)
  2156.                 ch = map_upper(ch);
  2157.             else
  2158.                 ch = map_lower(ch);
  2159.             bv[bi++] = ch;
  2160.             };
  2161.         };
  2162.     if (ps != 0)
  2163.         {
  2164.         bv[bi++] = '0' + ps;
  2165.         ps = 0;
  2166.         };
  2167.     if (rank != rank_1)
  2168.         bv[bi++] = '/';
  2169.     };
  2170. bv[bi++] = ascii_sp;
  2171.  
  2172. /* output active color (lower case) */
  2173.  
  2174. bv[bi++] = map_lower(asccv[epdptr->epd_actc]);
  2175. bv[bi++] = ascii_sp;
  2176.  
  2177. /* output castling availablility */
  2178.  
  2179. if (epdptr->epd_cast == 0)
  2180.     bv[bi++] = '-';
  2181. else
  2182.     {
  2183.     if (epdptr->epd_cast & cf_wk)
  2184.         bv[bi++] = map_upper(ascpv[p_k]);
  2185.     if (epdptr->epd_cast & cf_wq)
  2186.         bv[bi++] = map_upper(ascpv[p_q]);
  2187.     if (epdptr->epd_cast & cf_bk)
  2188.         bv[bi++] = map_lower(ascpv[p_k]);
  2189.     if (epdptr->epd_cast & cf_bq)
  2190.         bv[bi++] = map_lower(ascpv[p_q]);
  2191.     };
  2192. bv[bi++] = ascii_sp;
  2193.  
  2194. /* output ep capture square */
  2195.  
  2196. if (epdptr->epd_epsq == sq_nil)
  2197.     bv[bi++] = '-';
  2198. else
  2199.     {
  2200.     bv[bi++] = ascfv[map_file(epdptr->epd_epsq)];
  2201.     bv[bi++] = ascrv[map_rank(epdptr->epd_epsq)];
  2202.     };
  2203. bv[bi++] = ascii_sp;
  2204.  
  2205. /* output halfmove clock */
  2206.  
  2207. eopptr = EPDLocateEOP(epdptr, epdsostrv[epdso_hmvc]);
  2208. if ((eopptr != NULL) && (eopptr->eop_headeov != NULL) &&
  2209.     (eopptr->eop_headeov->eov_str != NULL))
  2210.     sprintf(nv, "%ld", atol(eopptr->eop_headeov->eov_str));
  2211. else
  2212.     sprintf(nv, "0");
  2213. strcpy(&bv[bi], nv);
  2214. bi += strlen(nv);
  2215. bv[bi++] = ascii_sp;
  2216.  
  2217. /* output fullmove number */
  2218.  
  2219. eopptr = EPDLocateEOP(epdptr, epdsostrv[epdso_fmvn]);
  2220. if ((eopptr != NULL) && (eopptr->eop_headeov != NULL) &&
  2221.     (eopptr->eop_headeov->eov_str != NULL))
  2222.     sprintf(nv, "%ld", atol(eopptr->eop_headeov->eov_str));
  2223. else
  2224.     sprintf(nv, "1");
  2225. strcpy(&bv[bi], nv);
  2226. bi += strlen(nv);
  2227.  
  2228. /* NUL termination */
  2229.  
  2230. bv[bi++] = ascii_nul;
  2231.  
  2232. /* allocate result */
  2233.  
  2234. s = EPDStringGrab(bv);
  2235.  
  2236. return (s);
  2237. }
  2238.  
  2239. /*--> EPDDecode: read an EPD structure from a string */
  2240. nonstatic
  2241. epdptrT
  2242. EPDDecode(charptrT s)
  2243. {
  2244. epdptrT epdptr;
  2245. eopptrT eopptr;
  2246. eovptrT eovptr;
  2247. siT flag, quoteflag;
  2248. siT ch;
  2249. liT i;
  2250. siT j, d;
  2251. byteptrT bptr;
  2252. fileT file;
  2253. rankT rank;
  2254. sqT sq;
  2255. cT c;
  2256. pT p;
  2257. cpT cp;
  2258.  
  2259. /* this does not reference the current position */
  2260.  
  2261. /* set up */
  2262.  
  2263. flag = 1;
  2264. i = 0;
  2265. ch = *(s + i++);
  2266.  
  2267. /* initialize the return structure */
  2268.  
  2269. epdptr = EPDNewEPD();
  2270.  
  2271. /* skip whitespace */
  2272.  
  2273. if (flag)
  2274.     {
  2275.     while (flag && (ch != ascii_nul) && isspace(ch))
  2276.         ch = *(s + i++);
  2277.     if (ch == ascii_nul)
  2278.         flag = 0;
  2279.     };
  2280.  
  2281. /* process piece placement data */
  2282.  
  2283. if (flag)
  2284.     {
  2285.     rank = rank_8;
  2286.     file = file_a;
  2287.  
  2288.     while (flag && (ch != ascii_nul) && !isspace(ch))
  2289.         {
  2290.         switch (ch)
  2291.             {
  2292.             case '/':
  2293.                 if ((file != fileL) || (rank == rank_1))
  2294.                     flag = 0;
  2295.                 else
  2296.                     {
  2297.                     rank--;
  2298.                     file = file_a;
  2299.                     };
  2300.                 break;
  2301.  
  2302.             case '1':
  2303.             case '2':
  2304.             case '3':
  2305.             case '4':
  2306.             case '5':
  2307.             case '6':
  2308.             case '7':
  2309.             case '8':
  2310.                 d = ch - '0';
  2311.                 if ((file + d) > fileL)
  2312.                     flag = 0;
  2313.                 else
  2314.                     for (j = 0; j < d; j++)
  2315.                         {
  2316.                         sq = map_sq(rank, file);
  2317.                         bptr = &epdptr->epd_nbv[sq >> 1];
  2318.                         if ((sq % 2) == 0)
  2319.                             {
  2320.                             *bptr &= ~nybbM;
  2321.                             *bptr |= cp_v0;
  2322.                             }
  2323.                         else
  2324.                             {
  2325.                             *bptr &= ~(nybbM << nybbW);
  2326.                             *bptr |= (cp_v0 << nybbW);
  2327.                             };
  2328.                         file++;
  2329.                         };
  2330.                 break;
  2331.  
  2332.             default:
  2333.                 if (!EPDCheckPiece((char)ch) || (file >= fileL))
  2334.                     flag = 0;
  2335.                 else
  2336.                     {
  2337.                     p = EPDEvaluatePiece((char)ch);
  2338.                     if (isupper(ch))
  2339.                         c = c_w;
  2340.                     else
  2341.                         c = c_b;
  2342.                     sq = map_sq(rank, file);
  2343.                     bptr = &epdptr->epd_nbv[sq >> 1];
  2344.                     cp = cv_cp_c_pv[c][p];
  2345.                     if ((sq % 2) == 0)
  2346.                         {
  2347.                         *bptr &= ~nybbM;
  2348.                         *bptr |= cp;
  2349.                         }
  2350.                     else
  2351.                         {
  2352.                         *bptr &= ~(nybbM << nybbW);
  2353.                         *bptr |= (cp << nybbW);
  2354.                         };
  2355.                     file++;
  2356.                     };
  2357.                 break;
  2358.             };
  2359.  
  2360.         ch = *(s + i++);
  2361.         };
  2362.  
  2363.     if (flag)
  2364.         if ((file != fileL) || (rank != rank_1))
  2365.             flag = 0;
  2366.     };
  2367.  
  2368. /* need at least one whitespace character */
  2369.  
  2370. if (flag)
  2371.     if ((ch == ascii_nul) || !isspace(ch))
  2372.         flag = 0;
  2373.  
  2374. /* skip whitespace */
  2375.  
  2376. if (flag)
  2377.     {
  2378.     while (flag && (ch != ascii_nul) && isspace(ch))
  2379.         ch = *(s + i++);
  2380.     if (ch == ascii_nul)
  2381.         flag = 0;
  2382.     };
  2383.  
  2384. /* process active color */
  2385.  
  2386. if (flag)
  2387.     {
  2388.     if (!EPDCheckColor((char)ch))
  2389.         flag = 0;
  2390.     else
  2391.         {
  2392.         epdptr->epd_actc = EPDEvaluateColor((char)ch);
  2393.         ch = *(s + i++);
  2394.         };
  2395.     };
  2396.  
  2397. /* need at least one whitespace character */
  2398.  
  2399. if (flag)
  2400.     if ((ch == ascii_nul) || !isspace(ch))
  2401.         flag = 0;
  2402.  
  2403. /* skip whitespace */
  2404.  
  2405. if (flag)
  2406.     {
  2407.     while (flag && (ch != ascii_nul) && isspace(ch))
  2408.         ch = *(s + i++);
  2409.     if (ch == ascii_nul)
  2410.         flag = 0;
  2411.     };
  2412.  
  2413. /* process castling availability */
  2414.  
  2415. if (flag)
  2416.     {
  2417.     epdptr->epd_cast = 0;
  2418.     if (ch == '-')
  2419.         ch = *(s + i++);
  2420.     else
  2421.         {
  2422.         /* white kingside castling availability */
  2423.  
  2424.         if (flag && (ch == map_upper(ascpv[p_k])))
  2425.             {
  2426.             epdptr->epd_cast |= cf_wk;
  2427.             ch = *(s + i++);
  2428.             if (ch == ascii_nul)
  2429.                 flag = 0;
  2430.             };
  2431.  
  2432.         /* white queenside castling availability */
  2433.  
  2434.         if (flag && (ch == map_upper(ascpv[p_q])))
  2435.             {
  2436.             epdptr->epd_cast |= cf_wq;
  2437.             ch = *(s + i++);
  2438.             if (ch == ascii_nul)
  2439.                 flag = 0;
  2440.             };
  2441.  
  2442.         /* black kingside castling availability */
  2443.  
  2444.         if (flag && (ch == map_lower(ascpv[p_k])))
  2445.             {
  2446.             epdptr->epd_cast |= cf_bk;
  2447.             ch = *(s + i++);
  2448.             if (ch == ascii_nul)
  2449.                 flag = 0;
  2450.             };
  2451.  
  2452.         /* black queenside castling availability */
  2453.  
  2454.         if (flag && (ch == map_lower(ascpv[p_q])))
  2455.             {
  2456.             epdptr->epd_cast |= cf_bq;
  2457.             ch = *(s + i++);
  2458.             if (ch == ascii_nul)
  2459.                 flag = 0;
  2460.             };
  2461.         };
  2462.     };
  2463.  
  2464. /* need at least one whitespace character */
  2465.  
  2466. if (flag)
  2467.     if ((ch == ascii_nul) || !isspace(ch))
  2468.         flag = 0;
  2469.  
  2470. /* skip whitespace */
  2471.  
  2472. if (flag)
  2473.     {
  2474.     while (flag && (ch != ascii_nul) && isspace(ch))
  2475.         ch = *(s + i++);
  2476.     if (ch == ascii_nul)
  2477.         flag = 0;
  2478.     };
  2479.  
  2480. /* process en passant target */
  2481.  
  2482. if (flag) {
  2483.     if (ch == '-')
  2484.         {
  2485.         epdptr->epd_epsq = sq_nil;
  2486.         ch = *(s + i++);
  2487.         if ((ch != ascii_nul) && !isspace(ch))
  2488.             flag = 0;
  2489.         }
  2490.     else {
  2491.         if (!EPDCheckFile((char)ch))
  2492.             flag = 0;
  2493.         else
  2494.             {
  2495.             file = EPDEvaluateFile((char)ch);
  2496.             ch = *(s + i++);
  2497.             if ((ch == ascii_nul) || !EPDCheckRank((char)ch))
  2498.                 flag = 0;
  2499.             else
  2500.                 {
  2501.                 epdptr->epd_epsq = map_sq(EPDEvaluateRank((char)ch), file);
  2502.                 ch = *(s + i++);
  2503.                 if ((ch != ascii_nul) && !isspace(ch))
  2504.                     flag = 0;
  2505.                 };
  2506.             };
  2507.                 }
  2508. }
  2509.  
  2510. /* skip whitespace (end-of-line is not an error) */
  2511.  
  2512. if (flag)
  2513.     while ((ch != ascii_nul) && isspace(ch))
  2514.         ch = *(s + i++);
  2515.  
  2516. /* process operation sequence (if any) */
  2517.  
  2518. if (flag)
  2519.     {
  2520.     while (flag && (ch != ascii_nul))
  2521.         {
  2522.         /* allocate a new operation */
  2523.  
  2524.         eopptr = EPDNewEOP();
  2525.  
  2526.         /* form opsym (first character) */
  2527.  
  2528.         if (IdentChar(ch))
  2529.             {
  2530.             eopptr->eop_opsym = EPDStringGrab("");
  2531.             eopptr->eop_opsym = EPDStringAppendChar(eopptr->eop_opsym, (char)ch);
  2532.             ch = *(s + i++);
  2533.             }
  2534.         else
  2535.             flag = 0;
  2536.  
  2537.         /* form remainder of opsym */
  2538.  
  2539.         while (IdentChar(ch))
  2540.             {
  2541.             eopptr->eop_opsym = EPDStringAppendChar(eopptr->eop_opsym, (char)ch);
  2542.             ch = *(s + i++);
  2543.             };
  2544.  
  2545.         /* skip whitespace */
  2546.  
  2547.         if (flag)
  2548.             {
  2549.             while (flag && (ch != ascii_nul) && isspace(ch))
  2550.                 ch = *(s + i++);
  2551.             if (ch == ascii_nul)
  2552.                 flag = 0;
  2553.             };
  2554.  
  2555.         /* process operand list */
  2556.  
  2557.         while (flag && (ch != ';'))
  2558.             {
  2559.             /* allocate operand value */
  2560.  
  2561.             eovptr = EPDNewEOV();
  2562.  
  2563.             /* set quoted string as appropriate */
  2564.  
  2565.             if (ch == '"')
  2566.                 {
  2567.                 quoteflag = 1;
  2568.                 eovptr->eov_eob = eob_string;
  2569.                 ch = *(s + i++);
  2570.                 }
  2571.             else
  2572.                 {
  2573.                 quoteflag = 0;
  2574.                 eovptr->eov_eob = eob_symbol;
  2575.                 };
  2576.  
  2577.             eovptr->eov_str = EPDStringGrab("");
  2578.  
  2579.             if (quoteflag)
  2580.                 {
  2581.                 while (flag && (ch != '"'))
  2582.                     {
  2583.                     if (ch == ascii_nul)
  2584.                         flag = 0;
  2585.                     else
  2586.                         {
  2587.                         eovptr->eov_str =
  2588.                             EPDStringAppendChar(eovptr->eov_str, (char)ch);
  2589.                         ch = *(s + i++);
  2590.                         };
  2591.                     };
  2592.                 if (ch == '"')
  2593.                     ch = *(s + i++);
  2594.                 }
  2595.             else
  2596.                 {
  2597.                 while (flag && !isspace(ch) && (ch != ';'))
  2598.                     {
  2599.                     if (ch == ascii_nul)
  2600.                         flag = 0;
  2601.                     else
  2602.                         {
  2603.                         eovptr->eov_str =
  2604.                             EPDStringAppendChar(eovptr->eov_str, (char)ch);
  2605.                         ch = *(s + i++);
  2606.                         };
  2607.                     };
  2608.                 };
  2609.  
  2610.             /* append operand onto operation */
  2611.  
  2612.             if (flag)
  2613.                 EPDAppendEOV(eopptr, eovptr);
  2614.             else
  2615.                 EPDReleaseEOV(eovptr);
  2616.  
  2617.             /* skip whitespace */
  2618.  
  2619.             while (flag && (ch != ascii_nul) && isspace(ch))
  2620.                 ch = *(s + i++);
  2621.             };
  2622.  
  2623.         /* process semicolon */
  2624.  
  2625.         if (flag) {
  2626.             if (ch == ';')
  2627.                 ch = *(s + i++);
  2628.             else
  2629.                 flag = 0;
  2630.                 }
  2631.  
  2632.         /* append operation */
  2633.  
  2634.         if (flag)
  2635.             EPDAppendEOP(epdptr, eopptr);
  2636.         else
  2637.             EPDReleaseEOP(eopptr);
  2638.  
  2639.         /* skip whitespace (end-of-line is not an error) */
  2640.  
  2641.         if (flag)
  2642.             while (flag && (ch != ascii_nul) && isspace(ch))
  2643.                 ch = *(s + i++);
  2644.         };
  2645.     };
  2646.  
  2647. /* check for fault */
  2648.  
  2649. if (!flag)
  2650.     {
  2651.     EPDReleaseEPD(epdptr);
  2652.     epdptr = NULL;
  2653.     };
  2654.  
  2655. /* normalize */
  2656.  
  2657. if (epdptr != NULL)
  2658.     EPDNormalize(epdptr);
  2659.  
  2660. return (epdptr);
  2661. }
  2662.  
  2663. /*--> EPDEncode: write an EPD structure to a string */
  2664. nonstatic
  2665. charptrT
  2666. EPDEncode(epdptrT epdptr)
  2667. {
  2668. charptrT ptr;
  2669. sqT sq;
  2670. cpT cp;
  2671. rankT rank;
  2672. fileT file;
  2673. siT bi, ps, ch;
  2674. char bv[tL];
  2675. eopptrT eopptr;
  2676. eovptrT eovptr;
  2677. charptrT s0, s1;
  2678.  
  2679. /* this does not reference the current position */
  2680.  
  2681. bi = 0;
  2682.  
  2683. /* normalize */
  2684.  
  2685. EPDNormalize(epdptr);
  2686.  
  2687. /* output board */
  2688.  
  2689. for (rank = rank_8; rank >= rank_1; rank--)
  2690.     {
  2691.     ps = 0;
  2692.     for (file = file_a; file <= file_h; file++)
  2693.         {
  2694.         sq = map_sq(rank, file);
  2695.         if ((sq % 2) == 0)
  2696.             cp = (epdptr->epd_nbv[sq >> 1] & nybbM);
  2697.         else
  2698.             cp = ((epdptr->epd_nbv[sq >> 1] >> nybbW) & nybbM);
  2699.  
  2700.         if (cp == cp_v0)
  2701.             ps++;
  2702.         else
  2703.             {
  2704.             if (ps != 0)
  2705.                 {
  2706.                 bv[bi++] = '0' + ps;
  2707.                 ps = 0;
  2708.                 };
  2709.             ch = ascpv[cv_p_cpv[cp]];
  2710.             if (cv_c_cpv[cp] == c_w)
  2711.                 ch = map_upper(ch);
  2712.             else
  2713.                 ch = map_lower(ch);
  2714.             bv[bi++] = ch;
  2715.             };
  2716.         };
  2717.     if (ps != 0)
  2718.         {
  2719.         bv[bi++] = '0' + ps;
  2720.         ps = 0;
  2721.         };
  2722.     if (rank != rank_1)
  2723.         bv[bi++] = '/';
  2724.     };
  2725. bv[bi++] = ascii_sp;
  2726.  
  2727. /* output active color (lower case) */
  2728.  
  2729. bv[bi++] = map_lower(asccv[epdptr->epd_actc]);
  2730. bv[bi++] = ascii_sp;
  2731.  
  2732. /* output castling availablility */
  2733.  
  2734. if (epdptr->epd_cast == 0)
  2735.     bv[bi++] = '-';
  2736. else
  2737.     {
  2738.     if (epdptr->epd_cast & cf_wk)
  2739.         bv[bi++] = map_upper(ascpv[p_k]);
  2740.     if (epdptr->epd_cast & cf_wq)
  2741.         bv[bi++] = map_upper(ascpv[p_q]);
  2742.     if (epdptr->epd_cast & cf_bk)
  2743.         bv[bi++] = map_lower(ascpv[p_k]);
  2744.     if (epdptr->epd_cast & cf_bq)
  2745.         bv[bi++] = map_lower(ascpv[p_q]);
  2746.     };
  2747. bv[bi++] = ascii_sp;
  2748.  
  2749. /* output ep capture square */
  2750.  
  2751. if (epdptr->epd_epsq == sq_nil)
  2752.     bv[bi++] = '-';
  2753. else
  2754.     {
  2755.     bv[bi++] = ascfv[map_file(epdptr->epd_epsq)];
  2756.     bv[bi++] = ascrv[map_rank(epdptr->epd_epsq)];
  2757.     };
  2758.  
  2759. /* NUL termination */
  2760.  
  2761. bv[bi++] = ascii_nul;
  2762.  
  2763. /* allocate and copy basic result */
  2764.  
  2765. ptr = EPDStringGrab(bv);
  2766.  
  2767. /* construct and append operations */
  2768.  
  2769. eopptr = epdptr->epd_headeop;
  2770. while (eopptr != NULL)
  2771.     {
  2772.     /* leading space */
  2773.  
  2774.     s0 = EPDStringGrab(" ");
  2775.  
  2776.     /* opcode */
  2777.  
  2778.     s0 = EPDStringAppendStr(s0, eopptr->eop_opsym);
  2779.  
  2780.     /* construct and append operands */
  2781.  
  2782.     eovptr = eopptr->eop_headeov;
  2783.     while (eovptr != NULL)
  2784.         {
  2785.         /* leading space */
  2786.  
  2787.         s1 = EPDStringGrab(" ");
  2788.  
  2789.         /* conjure operand value */
  2790.  
  2791.         switch (eovptr->eov_eob)
  2792.             {
  2793.             case eob_string:
  2794.                 s1 = EPDStringAppendChar(s1, '"');
  2795.                 s1 = EPDStringAppendStr(s1, eovptr->eov_str);
  2796.                 s1 = EPDStringAppendChar(s1, '"');
  2797.                 break;
  2798.  
  2799.             case eob_symbol:
  2800.                 s1 = EPDStringAppendStr(s1, eovptr->eov_str);
  2801.                 break;
  2802.  
  2803.             default:
  2804.                 EPDSwitchFault("EPDEncode");
  2805.                 break;
  2806.             };
  2807.  
  2808.         /* append */
  2809.  
  2810.         s0 = EPDStringAppendStr(s0, s1);
  2811.         EPDMemoryFree(s1);
  2812.  
  2813.         /* next operand */
  2814.  
  2815.         eovptr = eovptr->eov_next;
  2816.         };
  2817.  
  2818.     /* trailing semicolon */
  2819.  
  2820.     s0 = EPDStringAppendChar(s0, ';');
  2821.  
  2822.     /* append operation */
  2823.  
  2824.     ptr = EPDStringAppendStr(ptr, s0);
  2825.     EPDMemoryFree(s0);
  2826.  
  2827.     /* advance */
  2828.  
  2829.     eopptr = eopptr->eop_next;
  2830.     };
  2831.  
  2832. return (ptr);
  2833. }
  2834.  
  2835. /*--> EPDRealize: set the current position according to EPD */
  2836. nonstatic
  2837. void
  2838. EPDRealize(epdptrT epdptr)
  2839. {
  2840. sqT sq;
  2841. cpT cp;
  2842. eopptrT eopptr;
  2843. eovptrT eovptr;
  2844.  
  2845. /* this changes the current position */
  2846.  
  2847. for (sq = sq_a1; sq <= sq_h8; sq++)
  2848.     {
  2849.     if ((sq % 2) == 0)
  2850.         cp = (epdptr->epd_nbv[sq >> 1] & nybbM);
  2851.     else
  2852.         cp = ((epdptr->epd_nbv[sq >> 1] >> nybbW) & nybbM);
  2853.     EPDboard.rbv[sq] = cp;
  2854.     };
  2855.  
  2856. ese.ese_actc = epdptr->epd_actc;
  2857. ese.ese_cast = epdptr->epd_cast;
  2858. ese.ese_epsq = epdptr->epd_epsq;
  2859.  
  2860. eopptr = EPDLocateEOPCode(epdptr, epdso_hmvc);
  2861. if ((eopptr != NULL) && ((eovptr = eopptr->eop_headeov) != NULL))
  2862.     ese.ese_hmvc = atoi(eovptr->eov_str);
  2863. else
  2864.     ese.ese_hmvc = 0;
  2865.  
  2866. eopptr = EPDLocateEOPCode(epdptr, epdso_fmvn);
  2867. if ((eopptr != NULL) && ((eovptr = eopptr->eop_headeov) != NULL))
  2868.     ese.ese_fmvn = atoi(eovptr->eov_str);
  2869. else
  2870.     ese.ese_fmvn = 1;
  2871.  
  2872. EPDSetKings();
  2873.  
  2874. return;
  2875. }
  2876.  
  2877. /*--> EPDInitArray: set the current position to the initial array */
  2878. nonstatic
  2879. void
  2880. EPDInitArray(void)
  2881. {
  2882. sqT sq;
  2883.  
  2884. /* this changes the current position */
  2885.  
  2886. for (sq = sq_a1; sq <= sq_h8; sq++)
  2887.     EPDboard.rbv[sq] = cp_v0;
  2888.  
  2889. EPDboard.rbv[sq_a1] = EPDboard.rbv[sq_h1] = cp_wr;
  2890. EPDboard.rbv[sq_b1] = EPDboard.rbv[sq_g1] = cp_wn;
  2891. EPDboard.rbv[sq_c1] = EPDboard.rbv[sq_f1] = cp_wb;
  2892. EPDboard.rbv[sq_d1] = cp_wq;
  2893. EPDboard.rbv[sq_e1] = cp_wk;
  2894.  
  2895. for (sq = sq_a2; sq <= sq_h2; sq++)
  2896.     EPDboard.rbv[sq] = cp_wp;
  2897.  
  2898. EPDboard.rbv[sq_a8] = EPDboard.rbv[sq_h8] = cp_br;
  2899. EPDboard.rbv[sq_b8] = EPDboard.rbv[sq_g8] = cp_bn;
  2900. EPDboard.rbv[sq_c8] = EPDboard.rbv[sq_f8] = cp_bb;
  2901. EPDboard.rbv[sq_d8] = cp_bq;
  2902. EPDboard.rbv[sq_e8] = cp_bk;
  2903.  
  2904. for (sq = sq_a7; sq <= sq_h7; sq++)
  2905.     EPDboard.rbv[sq] = cp_bp;
  2906.  
  2907. ese.ese_actc = c_w;
  2908. ese.ese_cast = cf_wk | cf_wq | cf_bk | cf_bq;
  2909. ese.ese_epsq = sq_nil;
  2910. ese.ese_hmvc = 0;
  2911. ese.ese_fmvn = 1;
  2912.  
  2913. EPDSetKings();
  2914.  
  2915. return;
  2916. }
  2917.  
  2918. /*--> EPDPlayerString: return a pointer to the player name string */
  2919. nonstatic
  2920. charptrT
  2921. EPDPlayerString(cT c)
  2922. {
  2923.  
  2924. return (playerstrv[c]);
  2925. }
  2926.  
  2927. /*--> EPDSANEncodeChar: encode SAN character */
  2928. static
  2929. void
  2930. EPDSANEncodeChar(char ch)
  2931. {
  2932. if ((lsani < (sanL - 1)) || ((ch == '\0') && (lsani < sanL)))
  2933.     lsan[lsani++] = ch;
  2934. else
  2935.     EPDFatal("EPDSANEncodeChar: overflow");
  2936.  
  2937. return;
  2938. }
  2939.  
  2940. /*--> EPDSANEncodeStr: encode a SAN string */
  2941. static
  2942. void
  2943. EPDSANEncodeStr(charptrT s)
  2944. {
  2945. charptrT p;
  2946.  
  2947. p = s;
  2948. while (*p)
  2949.     EPDSANEncodeChar(*p++);
  2950.  
  2951. return;
  2952. }
  2953.  
  2954. /*--> EPDSANEncodeFile: encode SAN file from square */
  2955. static
  2956. void
  2957. EPDSANEncodeFile(sqT sq)
  2958. {
  2959. EPDSANEncodeChar(ascfv[map_file(sq)]);
  2960.  
  2961. return;
  2962. }
  2963.  
  2964. /*--> EPDSANEncodeRank: encode SAN rank from square */
  2965. static
  2966. void
  2967. EPDSANEncodeRank(sqT sq)
  2968. {
  2969. EPDSANEncodeChar(ascrv[map_rank(sq)]);
  2970.  
  2971. return;
  2972. }
  2973.  
  2974. /*--> EPDSANEncodeSq: encode SAN square */
  2975. static
  2976. void
  2977. EPDSANEncodeSq(sqT sq)
  2978. {
  2979. EPDSANEncodeFile(sq);
  2980. EPDSANEncodeRank(sq);
  2981.  
  2982. return;
  2983. }
  2984.  
  2985. /*--> EPDSANEncodeCI: encode an appropriate capture indicator */
  2986. static
  2987. void
  2988. EPDSANEncodeCI(siT index)
  2989. {
  2990. switch (index)
  2991.     {
  2992.     case 0:
  2993.         EPDSANEncodeChar('x');
  2994.         break;
  2995.  
  2996.     case 1:
  2997.         break;
  2998.  
  2999.     case 2:
  3000.         EPDSANEncodeChar(':');
  3001.         break;
  3002.  
  3003.     case 3:
  3004.         EPDSANEncodeChar('*');
  3005.         break;
  3006.  
  3007.     case 4:
  3008.         EPDSANEncodeChar('-');
  3009.         break;
  3010.     };
  3011.  
  3012. return;
  3013. }
  3014.  
  3015. /*--> EPDSANEncodeAux: encode SAN format move with variants */
  3016. static
  3017. void
  3018. EPDSANEncodeAux(mptrT mptr, sanT san, ssavT ssav)
  3019. {
  3020. siT i;
  3021.  
  3022. /* reset local index */
  3023.  
  3024. lsani = 0;
  3025.  
  3026. /* busted? */
  3027.  
  3028. if (mptr->m_flag & mf_bust)
  3029.     EPDSANEncodeChar('*');
  3030.  
  3031. /* process according to moving piece */
  3032.  
  3033. switch (cv_p_cpv[mptr->m_frcp])
  3034.     {
  3035.     case p_p:
  3036.         switch (mptr->m_scmv)
  3037.             {
  3038.             case scmv_reg:
  3039.                 if (mptr->m_tocp != cp_v0)
  3040.                     {
  3041.                     EPDSANEncodeFile(mptr->m_frsq);
  3042.                     if (ssav[ssa_edcr] == 1)
  3043.                         EPDSANEncodeRank(mptr->m_frsq);
  3044.                     EPDSANEncodeCI(ssav[ssa_capt]);
  3045.                     if (ssav[ssa_ptar] == 0)
  3046.                         EPDSANEncodeSq(mptr->m_tosq);
  3047.                     else
  3048.                         EPDSANEncodeFile(mptr->m_tosq);
  3049.                     }
  3050.                 else
  3051.                     {
  3052.                     EPDSANEncodeFile(mptr->m_frsq);
  3053.                     if (ssav[ssa_edcr] == 1)
  3054.                         EPDSANEncodeRank(mptr->m_frsq);
  3055.                     if (ssav[ssa_move] == 1)
  3056.                         EPDSANEncodeChar('-');
  3057.                     if (ssav[ssa_edcf] == 1)
  3058.                         EPDSANEncodeFile(mptr->m_tosq);
  3059.                     EPDSANEncodeRank(mptr->m_tosq);
  3060.                     };
  3061.                 break;
  3062.  
  3063.             case scmv_epc:
  3064.                 EPDSANEncodeFile(mptr->m_frsq);
  3065.                 if (ssav[ssa_edcr] == 1)
  3066.                     EPDSANEncodeRank(mptr->m_frsq);
  3067.                 EPDSANEncodeCI(ssav[ssa_capt]);
  3068.                 if (ssav[ssa_ptar] == 0)
  3069.                     EPDSANEncodeSq(mptr->m_tosq);
  3070.                 else
  3071.                     EPDSANEncodeFile(mptr->m_tosq);
  3072.                 if (ssav[ssa_epct] == 1)
  3073.                     EPDSANEncodeStr("ep");
  3074.                 break;
  3075.  
  3076.             case scmv_ppn:
  3077.             case scmv_ppb:
  3078.             case scmv_ppr:
  3079.             case scmv_ppq:
  3080.                 if (mptr->m_tocp != cp_v0)
  3081.                     {
  3082.                     EPDSANEncodeFile(mptr->m_frsq);
  3083.                     if (ssav[ssa_edcr] == 1)
  3084.                         EPDSANEncodeRank(mptr->m_frsq);
  3085.                     EPDSANEncodeCI(ssav[ssa_capt]);
  3086.                     if (ssav[ssa_ptar] == 0)
  3087.                         EPDSANEncodeSq(mptr->m_tosq);
  3088.                     else
  3089.                         EPDSANEncodeFile(mptr->m_tosq);
  3090.                     }
  3091.                 else
  3092.                     {
  3093.                     EPDSANEncodeFile(mptr->m_frsq);
  3094.                     if (ssav[ssa_edcr] == 1)
  3095.                         EPDSANEncodeRank(mptr->m_frsq);
  3096.                     if (ssav[ssa_move] == 1)
  3097.                         EPDSANEncodeChar('-');
  3098.                     if (ssav[ssa_edcf] == 1)
  3099.                         EPDSANEncodeFile(mptr->m_tosq);
  3100.                     EPDSANEncodeRank(mptr->m_tosq);
  3101.                     };
  3102.                 switch (ssav[ssa_prom])
  3103.                     {
  3104.                     case 0:
  3105.                         EPDSANEncodeChar('=');
  3106.                         EPDSANEncodeChar(ascpv[cv_p_scmvv[mptr->m_scmv]]);
  3107.                         break;
  3108.                     case 1:
  3109.                         EPDSANEncodeChar(ascpv[cv_p_scmvv[mptr->m_scmv]]);
  3110.                         break;
  3111.                     case 2:
  3112.                         EPDSANEncodeChar('/');
  3113.                         EPDSANEncodeChar(ascpv[cv_p_scmvv[mptr->m_scmv]]);
  3114.                         break;
  3115.                     case 3:
  3116.                         EPDSANEncodeChar('(');
  3117.                         EPDSANEncodeChar(ascpv[cv_p_scmvv[mptr->m_scmv]]);
  3118.                         EPDSANEncodeChar(')');
  3119.                         break;
  3120.                     };
  3121.                 break;
  3122.             };
  3123.         break;
  3124.  
  3125.     case p_n:
  3126.     case p_b:
  3127.     case p_r:
  3128.     case p_q:
  3129.         EPDSANEncodeChar(ascpv[cv_p_cpv[mptr->m_frcp]]);
  3130.  
  3131.         if (((mptr->m_flag & mf_sanf) || (ssav[ssa_edcf] == 1)) ||
  3132.             ((mptr->m_flag & mf_sanr) && (ssav[ssa_edcf] == 2)))
  3133.             EPDSANEncodeFile(mptr->m_frsq);
  3134.  
  3135.         if (((mptr->m_flag & mf_sanr) || (ssav[ssa_edcr] == 1)) ||
  3136.             ((mptr->m_flag & mf_sanf) && (ssav[ssa_edcr] == 2)))
  3137.             EPDSANEncodeRank(mptr->m_frsq);
  3138.  
  3139.         if (mptr->m_tocp != cp_v0)
  3140.             EPDSANEncodeCI(ssav[ssa_capt]);
  3141.         else
  3142.             if (ssav[ssa_move] == 1)
  3143.                 EPDSANEncodeChar('-');
  3144.         EPDSANEncodeSq(mptr->m_tosq);
  3145.         break;
  3146.  
  3147.     case p_k:
  3148.         switch (mptr->m_scmv)
  3149.             {
  3150.             case scmv_reg:
  3151.                 EPDSANEncodeChar(ascpv[p_k]);
  3152.                 if (ssav[ssa_edcf] == 1)
  3153.                     EPDSANEncodeFile(mptr->m_frsq);
  3154.                 if (ssav[ssa_edcr] == 1)
  3155.                     EPDSANEncodeRank(mptr->m_frsq);
  3156.                 if (mptr->m_tocp != cp_v0)
  3157.                     EPDSANEncodeCI(ssav[ssa_capt]);
  3158.                 else
  3159.                     if (ssav[ssa_move] == 1)
  3160.                         EPDSANEncodeChar('-');
  3161.                 EPDSANEncodeSq(mptr->m_tosq);
  3162.                 break;
  3163.  
  3164.             case scmv_cks:
  3165.                 switch (ssav[ssa_cast])
  3166.                     {
  3167.                     case 0:
  3168.                         EPDSANEncodeStr("O-O");
  3169.                         break;
  3170.                     case 1:
  3171.                         EPDSANEncodeStr("0-0");
  3172.                         break;
  3173.                     case 2:
  3174.                         EPDSANEncodeStr("OO");
  3175.                         break;
  3176.                     case 3:
  3177.                         EPDSANEncodeStr("00");
  3178.                         break;
  3179.                     case 4:
  3180.                         EPDSANEncodeChar(ascpv[p_k]);
  3181.                         if (ssav[ssa_edcf] == 1)
  3182.                             EPDSANEncodeFile(mptr->m_frsq);
  3183.                         if (ssav[ssa_edcr] == 1)
  3184.                             EPDSANEncodeRank(mptr->m_frsq);
  3185.                         if (ssav[ssa_move] == 1)
  3186.                             EPDSANEncodeChar('-');
  3187.                         EPDSANEncodeSq(mptr->m_tosq);
  3188.                         break;
  3189.                     };
  3190.                 break;
  3191.  
  3192.             case scmv_cqs:
  3193.                 switch (ssav[ssa_cast])
  3194.                     {
  3195.                     case 0:
  3196.                         EPDSANEncodeStr("O-O-O");
  3197.                         break;
  3198.                     case 1:
  3199.                         EPDSANEncodeStr("0-0-0");
  3200.                         break;
  3201.                     case 2:
  3202.                         EPDSANEncodeStr("OOO");
  3203.                         break;
  3204.                     case 3:
  3205.                         EPDSANEncodeStr("000");
  3206.                         break;
  3207.                     case 4:
  3208.                         EPDSANEncodeChar(ascpv[p_k]);
  3209.                         if (ssav[ssa_edcf] == 1)
  3210.                             EPDSANEncodeFile(mptr->m_frsq);
  3211.                         if (ssav[ssa_edcr] == 1)
  3212.                             EPDSANEncodeRank(mptr->m_frsq);
  3213.                         if (ssav[ssa_move] == 1)
  3214.                             EPDSANEncodeChar('-');
  3215.                         EPDSANEncodeSq(mptr->m_tosq);
  3216.                         break;
  3217.                     };
  3218.                 break;
  3219.             };
  3220.         break;
  3221.     };
  3222.  
  3223. /* insert markers */
  3224.  
  3225. if ((mptr->m_flag & mf_chec) && !(mptr->m_flag & mf_chmt))
  3226.     switch (ssav[ssa_chec])
  3227.         {
  3228.         case 0:
  3229.             EPDSANEncodeChar('+');
  3230.             break;
  3231.         case 1:
  3232.             break;
  3233.         case 2:
  3234.             EPDSANEncodeStr("ch");
  3235.             break;
  3236.         };
  3237.  
  3238. if (mptr->m_flag & mf_chmt)
  3239.     switch (ssav[ssa_chmt])
  3240.         {
  3241.         case 0:
  3242.             EPDSANEncodeChar('#');
  3243.             break;
  3244.         case 1:
  3245.             break;
  3246.         case 2:
  3247.             EPDSANEncodeChar('+');
  3248.             break;
  3249.         case 3:
  3250.             EPDSANEncodeStr("++");
  3251.             break;
  3252.         };
  3253.  
  3254. if (mptr->m_flag & mf_draw)
  3255.     if (ssav[ssa_draw] == 1)
  3256.         EPDSANEncodeChar('=');
  3257.  
  3258. /* map to lower case if indicated */
  3259.  
  3260. if (ssav[ssa_case] == 1)
  3261.     for (i = 0; i < lsani; i++)
  3262.         lsan[i] = map_lower(lsan[i]);
  3263.  
  3264. /* pad and copy */
  3265.  
  3266. while (lsani < sanL)
  3267.     EPDSANEncodeChar('\0');
  3268.  
  3269. for (i = 0; i < sanL; i++)
  3270.     san[i] = lsan[i];
  3271.  
  3272. return;
  3273. }
  3274.  
  3275. /*--> EPDSANEncode: encode a move into a SAN string */
  3276. nonstatic
  3277. void
  3278. EPDSANEncode(mptrT mptr, sanT san)
  3279. {
  3280. ssaT ssa;
  3281. ssavT ssav;
  3282.  
  3283. /* select canonical encoding (zero point in variant space) */
  3284.  
  3285. for (ssa = 0; ssa < ssaL; ssa++)
  3286.     ssav[ssa] = 0;
  3287. EPDSANEncodeAux(mptr, san, ssav);
  3288.  
  3289. return;
  3290. }
  3291.  
  3292. /*--> EPDSANDecodeBump: increment a style vector and return overflow */
  3293. static
  3294. siT
  3295. EPDSANDecodeBump(ssavT ssav, ssavT bssav)
  3296. {
  3297. siT flag;
  3298. ssaT ssa;
  3299.  
  3300. flag = 1;
  3301. ssa = 0;
  3302. while (flag && (ssa < ssaL))
  3303.     {
  3304.     flag = 0;
  3305.     ssav[ssa]++;
  3306.     if (ssav[ssa] == bssav[ssa])
  3307.         {
  3308.         flag = 1;
  3309.         ssav[ssa] = 0;
  3310.         };
  3311.     ssa++;
  3312.     };
  3313.  
  3314. return (flag);
  3315. }
  3316.  
  3317. /*--> EPDSANDecodeFlex: locate a move from SAN (flexible interpretation) */
  3318. static
  3319. mptrT
  3320. EPDSANDecodeFlex(sanT san)
  3321. {
  3322. mptrT mptr;
  3323. ssavT ssav, bssav;
  3324. siT i, flag;
  3325. mptrT rmptr;
  3326. sanT lcsan, rsan;
  3327.  
  3328. /* set default return value */
  3329.  
  3330. mptr = NULL;
  3331.  
  3332. /* set minimal upper bounds */
  3333.  
  3334. for (i = 0; i < ssaL; i++)
  3335.     bssav[i] = 1;
  3336.  
  3337. /* scan for upper bound conditions */
  3338.  
  3339. rmptr = tse.tse_base;
  3340. for (i = 0; i < tse.tse_count; i++)
  3341.     {
  3342.     /* letter case */
  3343.  
  3344.     bssav[ssa_case] = 2;
  3345.  
  3346.     /* capturing */
  3347.  
  3348.     if ((rmptr->m_tocp != cp_v0) || (rmptr->m_scmv == scmv_epc))
  3349.         bssav[ssa_capt] = 5;
  3350.  
  3351.     /* checking */
  3352.  
  3353.     if (rmptr->m_flag & mf_chec)
  3354.         bssav[ssa_chec] = 3;
  3355.  
  3356.     /* castling */
  3357.  
  3358.     if ((rmptr->m_scmv == scmv_cks) || (rmptr->m_scmv == scmv_cqs))
  3359.         bssav[ssa_cast] = 5;
  3360.  
  3361.     /* promoting */
  3362.  
  3363.     if ((rmptr->m_scmv == scmv_ppn) || (rmptr->m_scmv == scmv_ppb) ||
  3364.         (rmptr->m_scmv == scmv_ppr) || (rmptr->m_scmv == scmv_ppq))
  3365.         bssav[ssa_prom] = 4;
  3366.  
  3367.     /* pawn destination target */
  3368.  
  3369.     if (cv_p_cpv[rmptr->m_frcp] == p_p)
  3370.         bssav[ssa_ptar] = 2;
  3371.  
  3372.     /* checkmating */
  3373.  
  3374.     if (rmptr->m_flag & mf_chmt)
  3375.         bssav[ssa_chmt] = 4;
  3376.  
  3377.     /* en passant capturing */
  3378.  
  3379.     if (rmptr->m_scmv == scmv_epc)
  3380.         bssav[ssa_epct] = 2;
  3381.  
  3382.     /* drawing */
  3383.  
  3384.     if (rmptr->m_flag & mf_draw)
  3385.         bssav[ssa_draw] = 2;
  3386.  
  3387.     /* moving (non-capturing) */
  3388.  
  3389.     if ((rmptr->m_tocp == cp_v0) &&
  3390.         (rmptr->m_scmv != scmv_epc))
  3391.         bssav[ssa_move] = 2;
  3392.  
  3393.     /* extra disambiguation: file */
  3394.  
  3395.     if (!(rmptr->m_flag & mf_sanf))
  3396.         bssav[ssa_edcf] = 3;
  3397.  
  3398.     /* extra disambiguation: rank */
  3399.  
  3400.     if (!(rmptr->m_flag & mf_sanr))
  3401.         bssav[ssa_edcr] = 3;
  3402.  
  3403.     rmptr++;
  3404.     };
  3405.  
  3406. /* make a lower case copy of the input */
  3407.  
  3408. for (i = 0; i < sanL; i++)
  3409.     lcsan[i] = map_lower(san[i]);
  3410.  
  3411. /* initialize the index style vector */
  3412.  
  3413. for (i = 0; i < ssaL; i++)
  3414.     ssav[i] = 0;
  3415.  
  3416. /* search */
  3417.  
  3418. flag = 0;
  3419. while (!flag && (mptr == NULL))
  3420.     {
  3421.     rmptr = tse.tse_base;
  3422.     i = 0;
  3423.  
  3424.     /* scan candidate moves */
  3425.  
  3426.     while ((mptr == NULL) && (i < tse.tse_count))
  3427.         {
  3428.         /* encode the current style version of a candidate */
  3429.  
  3430.         EPDSANEncodeAux(rmptr, rsan, ssav);
  3431.  
  3432.         /* select either original or lower case comparison */
  3433.  
  3434.         if (ssav[ssa_case] == 0)
  3435.             {
  3436.             if (strcmp(san, rsan) == 0)
  3437.                 mptr = rmptr;
  3438.             }
  3439.         else
  3440.             {
  3441.             if (strcmp(lcsan, rsan) == 0)
  3442.                 mptr = rmptr;
  3443.             };
  3444.  
  3445.         /* next candidate */
  3446.  
  3447.         rmptr++;
  3448.         i++;
  3449.         };
  3450.  
  3451.     /* update the overflow termination flag    */
  3452.  
  3453.     flag = EPDSANDecodeBump(ssav, bssav);
  3454.     };
  3455.  
  3456. return (mptr);
  3457. }
  3458.  
  3459. /*--> EPDSANDecode: locate a move from SAN (strict interpretation) */
  3460. static
  3461. mptrT
  3462. EPDSANDecode(sanT san)
  3463. {
  3464. mptrT mptr;
  3465. mptrT rmptr;
  3466. sanT rsan;
  3467. siT i;
  3468.  
  3469. /* set default return value */
  3470.  
  3471. mptr = NULL;
  3472.  
  3473. /* assume current moveset properly generated */
  3474.  
  3475. rmptr = tse.tse_base;
  3476. i = 0;
  3477.  
  3478. /* search */
  3479.  
  3480. while ((mptr == NULL) && (i < tse.tse_count))
  3481.     {
  3482.     EPDSANEncode(rmptr, rsan);
  3483.     if (strcmp(san, rsan) == 0)
  3484.         mptr = rmptr;
  3485.     else
  3486.         {
  3487.         rmptr++;
  3488.         i++;
  3489.         };
  3490.     };
  3491.  
  3492. return (mptr);
  3493. }
  3494.  
  3495. /*--> EPDSANDecodeAux: locate a move from SAN */
  3496. nonstatic
  3497. mptrT
  3498. EPDSANDecodeAux(sanT san, siT strict)
  3499. {
  3500. mptrT mptr;
  3501.  
  3502. if (strict)
  3503.     mptr = EPDSANDecode(san);
  3504. else
  3505.     mptr = EPDSANDecodeFlex(san);
  3506.  
  3507. return (mptr);
  3508. }
  3509.  
  3510. /*--> EPDAttack: determine if a color attacks a square */
  3511. static
  3512. siT
  3513. EPDAttack(cT c, sqT sq)
  3514. {
  3515. siT flag;
  3516. dxT dx;
  3517. dvT dv;
  3518. xdvT xdv;
  3519. sqptrT sqptr0, sqptr1;
  3520. xsqptrT xsqptr0, xsqptr1;
  3521.  
  3522. /* clear result */
  3523.  
  3524. flag = 0;
  3525.  
  3526. /* set origin square pointers  */
  3527.  
  3528. sqptr0 = &EPDboard.rbv[sq];
  3529. xsqptr0 = &xb.xbv[map_xsq_sq(sq)];
  3530.  
  3531. /* process according to specified color */
  3532.  
  3533. if (c == c_w)
  3534.     {
  3535.     /* pawn attacks */
  3536.  
  3537.     if ((*(xsqptr0 + xdv_7) == cp_v0) && (*(sqptr0 + dv_7) == cp_wp))
  3538.         flag = 1;
  3539.     else
  3540.         if ((*(xsqptr0 + xdv_6) == cp_v0) && (*(sqptr0 + dv_6) == cp_wp))
  3541.             flag = 1;
  3542.  
  3543.     /* knight attacks */
  3544.  
  3545.     if (!flag)
  3546.         {
  3547.         dx = dx_8;
  3548.         while (!flag && (dx <= dx_f))
  3549.             if ((*(xsqptr0 + xdvv[dx]) == cp_v0) &&
  3550.                 (*(sqptr0 + dvv[dx]) == cp_wn))
  3551.                 flag = 1;
  3552.             else
  3553.                 dx++;
  3554.         };
  3555.  
  3556.     /* orthogonal sweeps */
  3557.  
  3558.     if (!flag)
  3559.         {
  3560.         dx = dx_0;
  3561.         while (!flag && (dx <= dx_3))
  3562.             {
  3563.             dv = dvv[dx];
  3564.             xdv = xdvv[dx];
  3565.             sqptr1 = sqptr0;
  3566.             xsqptr1 = xsqptr0;
  3567.             while ((*(xsqptr1 += xdv) == cp_v0) &&
  3568.                 (*(sqptr1 += dv) == cp_v0))
  3569.                 ;
  3570.             if ((*xsqptr1 == cp_v0) &&
  3571.                 ((*sqptr1 == cp_wq) || (*sqptr1 == cp_wr)))
  3572.                 flag = 1;
  3573.             else
  3574.                 dx++;
  3575.             };
  3576.         };
  3577.  
  3578.     /* diagonal sweeps */
  3579.  
  3580.     if (!flag)
  3581.         {
  3582.         dx = dx_4;
  3583.         while (!flag && (dx <= dx_7))
  3584.             {
  3585.             dv = dvv[dx];
  3586.             xdv = xdvv[dx];
  3587.             sqptr1 = sqptr0;
  3588.             xsqptr1 = xsqptr0;
  3589.             while ((*(xsqptr1 += xdv) == cp_v0) &&
  3590.                 (*(sqptr1 += dv) == cp_v0))
  3591.                 ;
  3592.             if ((*xsqptr1 == cp_v0) &&
  3593.                 ((*sqptr1 == cp_wq) || (*sqptr1 == cp_wb)))
  3594.                 flag = 1;
  3595.             else
  3596.                 dx++;
  3597.             };
  3598.         };
  3599.  
  3600.     /* king attacks */
  3601.  
  3602.     if (!flag)
  3603.         {
  3604.         dx = dx_0;
  3605.         while (!flag && (dx <= dx_7))
  3606.             if ((*(xsqptr0 + xdvv[dx]) == cp_v0) &&
  3607.                 (*(sqptr0 + dvv[dx]) == cp_wk))
  3608.                 flag = 1;
  3609.             else
  3610.                 dx++;
  3611.         };
  3612.     }
  3613. else
  3614.     {
  3615.     /* pawn attacks */
  3616.  
  3617.     if ((*(xsqptr0 + xdv_4) == cp_v0) && (*(sqptr0 + dv_4) == cp_bp))
  3618.         flag = 1;
  3619.     else
  3620.         if ((*(xsqptr0 + xdv_5) == cp_v0) && (*(sqptr0 + dv_5) == cp_bp))
  3621.             flag = 1;
  3622.  
  3623.     /* knight attacks */
  3624.  
  3625.     if (!flag)
  3626.         {
  3627.         dx = dx_8;
  3628.         while (!flag && (dx <= dx_f))
  3629.             if ((*(xsqptr0 + xdvv[dx]) == cp_v0) &&
  3630.                 (*(sqptr0 + dvv[dx]) == cp_bn))
  3631.                 flag = 1;
  3632.             else
  3633.                 dx++;
  3634.         };
  3635.  
  3636.     /* orthogonal sweeps */
  3637.  
  3638.     if (!flag)
  3639.         {
  3640.         dx = dx_0;
  3641.         while (!flag && (dx <= dx_3))
  3642.             {
  3643.             dv = dvv[dx];
  3644.             xdv = xdvv[dx];
  3645.             sqptr1 = sqptr0;
  3646.             xsqptr1 = xsqptr0;
  3647.             while ((*(xsqptr1 += xdv) == cp_v0) &&
  3648.                 (*(sqptr1 += dv) == cp_v0))
  3649.                 ;
  3650.             if ((*xsqptr1 == cp_v0) &&
  3651.                 ((*sqptr1 == cp_bq) || (*sqptr1 == cp_br)))
  3652.                 flag = 1;
  3653.             else
  3654.                 dx++;
  3655.             };
  3656.         };
  3657.  
  3658.     /* diagonal sweeps */
  3659.  
  3660.     if (!flag)
  3661.         {
  3662.         dx = dx_4;
  3663.         while (!flag && (dx <= dx_7))
  3664.             {
  3665.             dv = dvv[dx];
  3666.             xdv = xdvv[dx];
  3667.             sqptr1 = sqptr0;
  3668.             xsqptr1 = xsqptr0;
  3669.             while ((*(xsqptr1 += xdv) == cp_v0) &&
  3670.                 (*(sqptr1 += dv) == cp_v0))
  3671.                 ;
  3672.             if ((*xsqptr1 == cp_v0) &&
  3673.                 ((*sqptr1 == cp_bq) || (*sqptr1 == cp_bb)))
  3674.                 flag = 1;
  3675.             else
  3676.                 dx++;
  3677.             };
  3678.         };
  3679.  
  3680.     /* king attacks */
  3681.  
  3682.     if (!flag)
  3683.         {
  3684.         dx = dx_0;
  3685.         while (!flag && (dx <= dx_7))
  3686.             if ((*(xsqptr0 + xdvv[dx]) == cp_v0) &&
  3687.                 (*(sqptr0 + dvv[dx]) == cp_bk))
  3688.                 flag = 1;
  3689.             else
  3690.                 dx++;
  3691.         };
  3692.     };
  3693.  
  3694. return (flag);
  3695. }
  3696.  
  3697. /*--> EPDWhiteAttacks: check if White attacks a square */
  3698. static
  3699. siT
  3700. EPDWhiteAttacks(sqT sq)
  3701. {
  3702.  
  3703. return (EPDAttack(c_w, sq));
  3704. }
  3705.  
  3706. /*--> EPDBlackAttacks: check if White attacks a square */
  3707. static
  3708. siT
  3709. EPDBlackAttacks(sqT sq)
  3710. {
  3711.  
  3712. return (EPDAttack(c_b, sq));
  3713. }
  3714.  
  3715. /*--> EPDTestAKIC: test for active king in check */
  3716. static
  3717. siT
  3718. EPDTestAKIC(void)
  3719. {
  3720. siT flag;
  3721.  
  3722. if (ese.ese_actc == c_w)
  3723.     flag = EPDBlackAttacks(ese.ese_ksqv[c_w]);
  3724. else
  3725.     flag = EPDWhiteAttacks(ese.ese_ksqv[c_b]);
  3726.  
  3727. return (flag);
  3728. }
  3729.  
  3730. /*--> EPDTestPKIC: test for passive king in check */
  3731. static
  3732. siT
  3733. EPDTestPKIC(void)
  3734. {
  3735. siT flag;
  3736.  
  3737. if (ese.ese_actc == c_b)
  3738.     flag = EPDBlackAttacks(ese.ese_ksqv[c_w]);
  3739. else
  3740.     flag = EPDWhiteAttacks(ese.ese_ksqv[c_b]);
  3741.  
  3742. return (flag);
  3743. }
  3744.  
  3745. /*--> EPDCensus: calculate local census vectors */
  3746. static
  3747. void
  3748. EPDCensus(void)
  3749. {
  3750. cT c;
  3751. pT p;
  3752. sqT sq;
  3753. cpT cp;
  3754.  
  3755. /* clear census vectors */
  3756.  
  3757. for (c = c_w; c <= c_b; c++)
  3758.     {
  3759.     count_cv[c] = 0;
  3760.     for (p = p_p; p <= p_k; p++)
  3761.         count_cpv[c][p] = 0;
  3762.     };
  3763.  
  3764. /* calculate census vectors */
  3765.  
  3766. for (sq = sq_a1; sq <= sq_h8; sq++)
  3767.     {
  3768.     cp = EPDboard.rbv[sq];
  3769.     if (cp != cp_v0)
  3770.         {
  3771.         c = cv_c_cpv[cp];
  3772.         count_cv[c]++;
  3773.         count_cpv[c][cv_p_cpv[cp]]++;
  3774.         };
  3775.     };
  3776.  
  3777. return;
  3778. }
  3779.  
  3780. /*--> EPDIsLegal: determine if current position is legal */
  3781. nonstatic
  3782. siT
  3783. EPDIsLegal(void)
  3784. {
  3785. siT flag;
  3786. cT c;
  3787. fileT file;
  3788. siT apv[rcL];
  3789.  
  3790. /* set default return value: legal position */
  3791.  
  3792. flag = 1;
  3793.  
  3794. /* calculate the local census vectors */
  3795.  
  3796. EPDCensus();
  3797.  
  3798. /* calculate available promoted pawns */
  3799.  
  3800. for (c = c_w; c <= c_b; c++)
  3801.     apv[c] = fileL - count_cpv[c][p_p];
  3802.  
  3803. /* check white pawn count */
  3804.  
  3805. if (flag && (count_cpv[c_w][p_p] > fileL))
  3806.     flag = 0;
  3807.  
  3808. /* check black pawn count */
  3809.  
  3810. if (flag && (count_cpv[c_b][p_p] > fileL))
  3811.     flag = 0;
  3812.  
  3813. /* check white knight count */
  3814.  
  3815. if (flag && (count_cpv[c_w][p_n] > 2))
  3816.     {
  3817.     apv[c_w] -= (count_cpv[c_w][p_n] - 2);
  3818.     if (apv[c_w] < 0)
  3819.         flag = 0;
  3820.     };
  3821.  
  3822. /* check black knight count */
  3823.  
  3824. if (flag && (count_cpv[c_b][p_n] > 2))
  3825.     {
  3826.     apv[c_b] -= (count_cpv[c_b][p_n] - 2);
  3827.     if (apv[c_b] < 0)
  3828.         flag = 0;
  3829.     };
  3830.  
  3831. /* check white bishop count */
  3832.  
  3833. if (flag && (count_cpv[c_w][p_b] > 2))
  3834.     {
  3835.     apv[c_w] -= (count_cpv[c_w][p_b] - 2);
  3836.     if (apv[c_w] < 0)
  3837.         flag = 0;
  3838.     };
  3839.  
  3840. /* check black bishop count */
  3841.  
  3842. if (flag && (count_cpv[c_b][p_b] > 2))
  3843.     {
  3844.     apv[c_b] -= (count_cpv[c_b][p_b] - 2);
  3845.     if (apv[c_b] < 0)
  3846.         flag = 0;
  3847.     };
  3848.  
  3849. /* check white rook count */
  3850.  
  3851. if (flag && (count_cpv[c_w][p_r] > 2))
  3852.     {
  3853.     apv[c_w] -= (count_cpv[c_w][p_r] - 2);
  3854.     if (apv[c_w] < 0)
  3855.         flag = 0;
  3856.     };
  3857.  
  3858. /* check black rook count */
  3859.  
  3860. if (flag && (count_cpv[c_b][p_r] > 2))
  3861.     {
  3862.     apv[c_b] -= (count_cpv[c_b][p_r] - 2);
  3863.     if (apv[c_b] < 0)
  3864.         flag = 0;
  3865.     };
  3866.  
  3867. /* check white queen count */
  3868.  
  3869. if (flag && (count_cpv[c_w][p_q] > 1))
  3870.     {
  3871.     apv[c_w] -= (count_cpv[c_w][p_q] - 1);
  3872.     if (apv[c_w] < 0)
  3873.         flag = 0;
  3874.     };
  3875.  
  3876. /* check black queen count */
  3877.  
  3878. if (flag && (count_cpv[c_b][p_q] > 1))
  3879.     {
  3880.     apv[c_b] -= (count_cpv[c_b][p_q] - 1);
  3881.     if (apv[c_b] < 0)
  3882.         flag = 0;
  3883.     };
  3884.  
  3885. /* check white king count */
  3886.  
  3887. if (flag && (count_cpv[c_w][p_k] != 1))
  3888.     flag = 0;
  3889.  
  3890. /* check black king count */
  3891.  
  3892. if (flag && (count_cpv[c_b][p_k] != 1))
  3893.     flag = 0;
  3894.  
  3895. /* check pawn placement */
  3896.  
  3897. if (flag)
  3898.     {
  3899.     file = file_a;
  3900.     while (flag && (file <= file_h))
  3901.         if ((EPDboard.rbm[rank_1][file] == cp_wp) ||
  3902.             (EPDboard.rbm[rank_1][file] == cp_bp) ||
  3903.             (EPDboard.rbm[rank_8][file] == cp_wp) ||
  3904.             (EPDboard.rbm[rank_8][file] == cp_bp))
  3905.             flag = 0;
  3906.         else
  3907.             file++;
  3908.     };
  3909.  
  3910. /* check white kingside castling availability */
  3911.  
  3912. if (flag && (ese.ese_cast & cf_wk))
  3913.     if ((EPDboard.rbv[sq_e1] != cp_wk) || (EPDboard.rbv[sq_h1] != cp_wr))
  3914.         flag = 0;
  3915.  
  3916. /* check white queenside castling availability */
  3917.  
  3918. if (flag && (ese.ese_cast & cf_wq))
  3919.     if ((EPDboard.rbv[sq_e1] != cp_wk) || (EPDboard.rbv[sq_a1] != cp_wr))
  3920.         flag = 0;
  3921.  
  3922. /* check black kingside castling availability */
  3923.  
  3924. if (flag && (ese.ese_cast & cf_bk))
  3925.     if ((EPDboard.rbv[sq_e8] != cp_bk) || (EPDboard.rbv[sq_h8] != cp_br))
  3926.         flag = 0;
  3927.  
  3928. /* check black queenside castling availability */
  3929.  
  3930. if (flag && (ese.ese_cast & cf_bq))
  3931.     if ((EPDboard.rbv[sq_e8] != cp_bk) || (EPDboard.rbv[sq_a8] != cp_br))
  3932.         flag = 0;
  3933.  
  3934. /* check en passant target square */
  3935.  
  3936. if (flag && (ese.ese_epsq != sq_nil)) {
  3937.     if (ese.ese_actc == c_w)
  3938.         {
  3939.         if (map_rank(ese.ese_epsq) != rank_6)
  3940.             flag = 0;
  3941.         else
  3942.             if (EPDboard.rbv[ese.ese_epsq + dv_3] != cp_bp)
  3943.                 flag = 0;
  3944.             else
  3945.                 if (EPDboard.rbv[ese.ese_epsq] != cp_v0)
  3946.                     flag = 0;
  3947.                 else
  3948.                     if (EPDboard.rbv[ese.ese_epsq + dv_1] != cp_v0)
  3949.                         flag = 0;
  3950.         }
  3951.     else
  3952.         {
  3953.         if (map_rank(ese.ese_epsq) != rank_3)
  3954.             flag = 0;
  3955.         else
  3956.             if (EPDboard.rbv[ese.ese_epsq + dv_1] != cp_wp)
  3957.                 flag = 0;
  3958.             else
  3959.                 if (EPDboard.rbv[ese.ese_epsq] != cp_v0)
  3960.                     flag = 0;
  3961.                 else
  3962.                     if (EPDboard.rbv[ese.ese_epsq + dv_3] != cp_v0)
  3963.                         flag = 0;
  3964.         }
  3965. }
  3966.  
  3967. /* check for passive king in check */
  3968.  
  3969. if (flag && EPDTestPKIC())
  3970.     flag = 0;
  3971.  
  3972. return (flag);
  3973. }
  3974.  
  3975. /*--> EPDIsCheckmate: test for checkmate status */
  3976. nonstatic
  3977. siT
  3978. EPDIsCheckmate(void)
  3979. {
  3980. siT flag;
  3981.  
  3982. /* set default return value: no checkmate */
  3983.  
  3984. flag = 0;
  3985.  
  3986. /* generate legal moves (assume legal position) */
  3987.  
  3988. EPDGenMoves();
  3989.  
  3990. /* no legal moves and in check? */
  3991.  
  3992. if ((tse.tse_count == 0) && EPDTestAKIC())
  3993.     flag = 1;
  3994.  
  3995. return (flag);
  3996. }
  3997.  
  3998. /*--> EPDIsStalemate: test for stalemate status */
  3999. nonstatic
  4000. siT
  4001. EPDIsStalemate(void)
  4002. {
  4003. siT flag;
  4004.  
  4005. /* set default return value: no stalemate */
  4006.  
  4007. flag = 0;
  4008.  
  4009. /* generate legal moves (assume legal position) */
  4010.  
  4011. EPDGenMoves();
  4012.  
  4013. /* no legal moves and not in check? */
  4014.  
  4015. if ((tse.tse_count == 0) && !EPDTestAKIC())
  4016.     flag = 1;
  4017.  
  4018. return (flag);
  4019. }
  4020.  
  4021. /*--> EPDIsInsufficientMaterial: test for insufficient material */
  4022. nonstatic
  4023. siT
  4024. EPDIsInsufficientMaterial(void)
  4025. {
  4026. siT flag;
  4027.  
  4028. /* set default return value: no draw by insufficient material */
  4029.  
  4030. flag = 0;
  4031.  
  4032. /* calculate local census (assume legal position) */
  4033.  
  4034. EPDCensus();
  4035.  
  4036. /* only K vs K, K+N vs K, and K+B vs K are considered draws here */
  4037.  
  4038. if ((count_cv[c_w] == 1) && (count_cv[c_b] == 1))
  4039.     flag = 1;
  4040. else
  4041.     if ((count_cv[c_w] == 2) && (count_cv[c_b] == 1) &&
  4042.         ((count_cpv[c_w][p_n] == 1) || (count_cpv[c_w][p_b] == 1)))
  4043.         flag = 1;
  4044.     else
  4045.         if ((count_cv[c_b] == 2) && (count_cv[c_w] == 1) &&
  4046.             ((count_cpv[c_b][p_n] == 1) || (count_cpv[c_b][p_b] == 1)))
  4047.             flag = 1;
  4048.  
  4049. return (flag);
  4050. }
  4051.  
  4052. /*--> EPDIsFiftyMoveDraw: test for 50 move draw */
  4053. nonstatic
  4054. siT
  4055. EPDIsFiftyMoveDraw(void)
  4056. {
  4057. siT flag;
  4058.  
  4059. if (ese.ese_hmvc >= 100)
  4060.     flag = 1;
  4061. else
  4062.     flag = 0;
  4063.  
  4064. return (flag);
  4065. }
  4066.  
  4067. /*--> EPDIsThirdRepetition: test for third repetition */
  4068. nonstatic
  4069. siT
  4070. EPDIsThirdRepetition(gamptrT gamptr)
  4071. {
  4072. siT flag;
  4073. gpmptrT gpmptr;
  4074. siT count, limit, index, match;
  4075. sqT sq;
  4076. cpT cp0, cp1;
  4077. nbvT nbv;
  4078.  
  4079. /* point to the last game played move record */
  4080.  
  4081. gpmptr = gamptr->gam_tailgpm;
  4082.  
  4083. /* set the repetion count (current position counts as one) */
  4084.  
  4085. count = 1;
  4086.  
  4087. /* set the limit on the number of records to check */
  4088.  
  4089. limit = ese.ese_hmvc;
  4090.  
  4091. /* construct the nybble board for the current position */
  4092.  
  4093. for (sq = sq_a1; sq <= sq_h8; sq += 2)
  4094.     {
  4095.     cp0 = EPDboard.rbv[sq + 0];
  4096.     cp1 = EPDboard.rbv[sq + 1];
  4097.     nbv[sq >> 1] = ((cp1 << nybbW) | cp0);
  4098.     };
  4099.  
  4100. /* loop backwards */
  4101.  
  4102. while ((gpmptr != NULL) && (limit > 0) && (count < 3))
  4103.     {
  4104.     /* check for match against current position */
  4105.  
  4106.     if ((ese.ese_actc == gpmptr->gpm_ese.ese_actc) &&
  4107.         (ese.ese_cast == gpmptr->gpm_ese.ese_cast) &&
  4108.         (ese.ese_epsq == gpmptr->gpm_ese.ese_epsq))
  4109.         {
  4110.         /* scalars matched, check for board match */
  4111.  
  4112.         match = 1;
  4113.         index = 0;
  4114.         while (match && (index < nbL))
  4115.             {
  4116.             if (nbv[index] == gpmptr->gpm_nbv[index])
  4117.                 index++;
  4118.             else
  4119.                 match = 0;
  4120.             };
  4121.  
  4122.         /* complete match? */
  4123.  
  4124.         if (match)
  4125.             count++;
  4126.         };
  4127.  
  4128.     /* retreat to previous played move record */
  4129.  
  4130.     gpmptr = gpmptr->gpm_prev;
  4131.  
  4132.     /* one less to go */
  4133.  
  4134.     limit--;
  4135.     };
  4136.  
  4137. /* set return value */
  4138.  
  4139. if (count == 3)
  4140.     flag = 1;
  4141. else
  4142.     flag = 0;
  4143.  
  4144. return (flag);
  4145. }
  4146.  
  4147. /*--> EPDIsDraw: determine if the current position is a draw */
  4148. nonstatic
  4149. siT
  4150. EPDIsDraw(gamptrT gamptr)
  4151. {
  4152. siT flag;
  4153.  
  4154. if (EPDIsFiftyMoveDraw() ||
  4155.     EPDIsInsufficientMaterial() ||
  4156.     EPDIsStalemate() ||
  4157.     EPDIsThirdRepetition(gamptr))
  4158.     flag = 1;
  4159. else
  4160.     flag = 0;
  4161.  
  4162. return (flag);
  4163. }
  4164.  
  4165. /*--> EPDMateInOne: return a mating move if one exists */
  4166. nonstatic
  4167. mptrT
  4168. EPDMateInOne(void)
  4169. {
  4170. mptrT mptr;
  4171. mptrT rmptr;
  4172. siT index;
  4173.  
  4174. /* set default return value (no mate in one) */
  4175.  
  4176. mptr = NULL;
  4177.  
  4178. /* generate legal moves (assume legal position) */
  4179.  
  4180. EPDGenMoves();
  4181.  
  4182. /* try to locate a mating move */
  4183.  
  4184. rmptr = tse.tse_base;
  4185. index = 0;
  4186. while ((mptr == NULL) && (index < tse.tse_count))
  4187.     if (rmptr->m_flag & mf_chmt)
  4188.         {
  4189.         ret_m = *rmptr;
  4190.         mptr = &ret_m;
  4191.         }
  4192.     else
  4193.         {
  4194.         rmptr++;
  4195.         index++;
  4196.         };
  4197.  
  4198. return (mptr);
  4199. }
  4200.  
  4201. /*--> EPDGeneratePL: generate psuedolegal moves */
  4202. static
  4203. void
  4204. EPDGeneratePL(void)
  4205. {
  4206. dxT dx;
  4207. dvT dv;
  4208. xdvT xdv;
  4209. xsqptrT xsqptr0, xsqptr1;
  4210. fileT frfile;
  4211. rankT frrank;
  4212. mT gen_m;
  4213.  
  4214. /* set up the generation base */
  4215.  
  4216. if (ply == 0)
  4217.     treeptr = tse.tse_base = treebaseptr;
  4218. else
  4219.     treeptr = tse.tse_base =
  4220.         (tseptr - 1)->tse_base + (tseptr - 1)->tse_count;
  4221.  
  4222. /* test against safety margin */
  4223.  
  4224. if ((treeptr - treebaseptr) >= (treeL - treemarginL))
  4225.     EPDFatal("EPDGeneratePL: move tree size safety limit exceeded");
  4226.  
  4227. /* set up current generation items */
  4228.  
  4229. tse.tse_curr = treeptr;
  4230. tse.tse_count = 0;
  4231.  
  4232. /* set the psuedoinvariant generated move template components */
  4233.  
  4234. gen_m.m_scmv = scmv_reg;
  4235. gen_m.m_flag = 0;
  4236.  
  4237. /* look at each origin square of the active color */
  4238.  
  4239. for (gen_m.m_frsq = sq_a1; gen_m.m_frsq <= sq_h8; gen_m.m_frsq++)
  4240.     {
  4241.     /* get origin square and moving piece */
  4242.  
  4243.     gen_m.m_frcp = EPDboard.rbv[gen_m.m_frsq];
  4244.  
  4245.     /* continue if it is an active piece */
  4246.  
  4247.     if (cv_c_cpv[gen_m.m_frcp] == ese.ese_actc)
  4248.         {
  4249.  
  4250.         /* generate moves for active color piece */
  4251.  
  4252.         xsqptr0 = &xb.xbv[map_xsq_sq(gen_m.m_frsq)];
  4253.         switch (cv_p_cpv[gen_m.m_frcp])
  4254.             {
  4255.             case p_p:
  4256.                 /* pawn moves: a bit tricky; colors done separately */
  4257.  
  4258.                 frfile = map_file(gen_m.m_frsq);
  4259.                 frrank = map_rank(gen_m.m_frsq);
  4260.                 if (ese.ese_actc == c_w)
  4261.                     {
  4262.                     /* one square non-capture */
  4263.  
  4264.                     gen_m.m_tocp = EPDboard.rbv[gen_m.m_tosq = gen_m.m_frsq + dv_1];
  4265.                     if (gen_m.m_tocp == cp_v0) {
  4266.                         if (frrank != rank_7)
  4267.                             {
  4268.                             /* non-promotion */
  4269.  
  4270.                             *treeptr++ = gen_m;
  4271.                             tse.tse_count++;
  4272.                             }
  4273.                         else
  4274.                             {
  4275.                             /* promotion */
  4276.  
  4277.                             for (gen_m.m_scmv = scmv_ppn;
  4278.                                 gen_m.m_scmv <= scmv_ppq; gen_m.m_scmv++)
  4279.                                 {
  4280.                                 *treeptr++ = gen_m;
  4281.                                 tse.tse_count++;
  4282.                                 }
  4283.                             gen_m.m_scmv = scmv_reg;
  4284.                             };
  4285.                                         }
  4286.  
  4287.                     /* two squares forward */
  4288.  
  4289.                     if ((frrank == rank_2) &&
  4290.                         Vacant(gen_m.m_frsq + dv_1) &&
  4291.                         Vacant(gen_m.m_frsq + (2 * dv_1)))
  4292.                         {
  4293.                         gen_m.m_tosq = gen_m.m_frsq + (2 * dv_1);
  4294.                         gen_m.m_tocp = cp_v0;
  4295.                         *treeptr++ = gen_m;
  4296.                         tse.tse_count++;
  4297.                         };
  4298.  
  4299.                     /* capture to left */
  4300.  
  4301.                     if (frfile != file_a)
  4302.                         {
  4303.                         gen_m.m_tosq = gen_m.m_frsq + dv_5;
  4304.                         gen_m.m_tocp = EPDboard.rbv[gen_m.m_tosq];
  4305.                         if (cv_c_cpv[gen_m.m_tocp] == inv_cv[ese.ese_actc]) {
  4306.                             if (frrank != rank_7)
  4307.                                 {
  4308.                                 /* non-promote */
  4309.  
  4310.                                 *treeptr++ = gen_m;
  4311.                                 tse.tse_count++;
  4312.                                 }
  4313.                             else
  4314.                                 {
  4315.                                 /* promote */
  4316.  
  4317.                                 for (gen_m.m_scmv = scmv_ppn;
  4318.                                     gen_m.m_scmv <= scmv_ppq; gen_m.m_scmv++)
  4319.                                     {
  4320.                                     *treeptr++ = gen_m;
  4321.                                     tse.tse_count++;
  4322.                                     };
  4323.                                 gen_m.m_scmv = scmv_reg;
  4324.                                 };
  4325.                                            }
  4326.                         };
  4327.  
  4328.                     /* capture to right */
  4329.  
  4330.                     if (frfile != file_h)
  4331.                         {
  4332.                         gen_m.m_tosq = gen_m.m_frsq + dv_4;
  4333.                         gen_m.m_tocp = EPDboard.rbv[gen_m.m_tosq];
  4334.                         if (cv_c_cpv[gen_m.m_tocp] == inv_cv[ese.ese_actc]) {
  4335.                             if (frrank != rank_7)
  4336.                                 {
  4337.                                 /* non-promote */
  4338.  
  4339.                                 *treeptr++ = gen_m;
  4340.                                 tse.tse_count++;
  4341.                                 }
  4342.                             else
  4343.                                 {
  4344.                                 /* promote */
  4345.  
  4346.                                 for (gen_m.m_scmv = scmv_ppn;
  4347.                                     gen_m.m_scmv <= scmv_ppq; gen_m.m_scmv++)
  4348.                                     {
  4349.                                     *treeptr++ = gen_m;
  4350.                                     tse.tse_count++;
  4351.                                     };
  4352.                                 gen_m.m_scmv = scmv_reg;
  4353.                                 };
  4354.                                                          }
  4355.                         };
  4356.  
  4357.                     /* en passant */
  4358.  
  4359.                     if ((frrank == rank_5) && (ese.ese_epsq != sq_nil))
  4360.                         {
  4361.                         /* capture to left */
  4362.  
  4363.                         if ((frfile != file_a) &&
  4364.                             ((gen_m.m_tosq = gen_m.m_frsq + dv_5) ==
  4365.                             ese.ese_epsq))
  4366.                             {
  4367.                             gen_m.m_tocp = cp_v0;
  4368.                             gen_m.m_scmv = scmv_epc;
  4369.                             *treeptr++ = gen_m;
  4370.                             tse.tse_count++;
  4371.                             gen_m.m_scmv = scmv_reg;
  4372.                             };
  4373.  
  4374.                         /* capture to right */
  4375.  
  4376.                         if ((frfile != file_h) &&
  4377.                             ((gen_m.m_tosq = gen_m.m_frsq + dv_4) ==
  4378.                             ese.ese_epsq))
  4379.                             {
  4380.                             gen_m.m_tocp = cp_v0;
  4381.                             gen_m.m_scmv = scmv_epc;
  4382.                             *treeptr++ = gen_m;
  4383.                             tse.tse_count++;
  4384.                             gen_m.m_scmv = scmv_reg;
  4385.                             };
  4386.                         };
  4387.                     }
  4388.                 else
  4389.                     {
  4390.                     /* one square non-capture */
  4391.  
  4392.                     gen_m.m_tocp = EPDboard.rbv[gen_m.m_tosq = gen_m.m_frsq + dv_3];
  4393.                     if (gen_m.m_tocp == cp_v0) {
  4394.                         if (frrank != rank_2)
  4395.                             {
  4396.                             /* non-promotion */
  4397.  
  4398.                             *treeptr++ = gen_m;
  4399.                             tse.tse_count++;
  4400.                             }
  4401.                         else
  4402.                             {
  4403.                             /* promotion */
  4404.  
  4405.                             for (gen_m.m_scmv = scmv_ppn;
  4406.                                 gen_m.m_scmv <= scmv_ppq; gen_m.m_scmv++)
  4407.                                 {
  4408.                                 *treeptr++ = gen_m;
  4409.                                 tse.tse_count++;
  4410.                                 }
  4411.                             gen_m.m_scmv = scmv_reg;
  4412.                             };
  4413.                                         }
  4414.  
  4415.                     /* two squares forward */
  4416.  
  4417.                     if ((frrank == rank_7) &&
  4418.                         Vacant(gen_m.m_frsq + dv_3) &&
  4419.                         Vacant(gen_m.m_frsq + (2 * dv_3)))
  4420.                         {
  4421.                         gen_m.m_tosq = gen_m.m_frsq + (2 * dv_3);
  4422.                         gen_m.m_tocp = cp_v0;
  4423.                         *treeptr++ = gen_m;
  4424.                         tse.tse_count++;
  4425.                         };
  4426.  
  4427.                     /* capture to left */
  4428.  
  4429.                     if (frfile != file_a)
  4430.                         {
  4431.                         gen_m.m_tosq = gen_m.m_frsq + dv_6;
  4432.                         gen_m.m_tocp = EPDboard.rbv[gen_m.m_tosq];
  4433.                         if (cv_c_cpv[gen_m.m_tocp] == inv_cv[ese.ese_actc]) {
  4434.                             if (frrank != rank_2)
  4435.                                 {
  4436.                                 /* non-promote */
  4437.  
  4438.                                 *treeptr++ = gen_m;
  4439.                                 tse.tse_count++;
  4440.                                 }
  4441.                             else
  4442.                                 {
  4443.                                 /* promote */
  4444.  
  4445.                                 for (gen_m.m_scmv = scmv_ppn;
  4446.                                     gen_m.m_scmv <= scmv_ppq; gen_m.m_scmv++)
  4447.                                     {
  4448.                                     *treeptr++ = gen_m;
  4449.                                     tse.tse_count++;
  4450.                                     };
  4451.                                 gen_m.m_scmv = scmv_reg;
  4452.                                 };
  4453.                                                 }
  4454.                         };
  4455.  
  4456.                     /* capture to right */
  4457.  
  4458.                     if (frfile != file_h)
  4459.                         {
  4460.                         gen_m.m_tosq = gen_m.m_frsq + dv_7;
  4461.                         gen_m.m_tocp = EPDboard.rbv[gen_m.m_tosq];
  4462.                         if (cv_c_cpv[gen_m.m_tocp] == inv_cv[ese.ese_actc]) {
  4463.                             if (frrank != rank_2)
  4464.                                 {
  4465.                                 /* non-promote */
  4466.  
  4467.                                 *treeptr++ = gen_m;
  4468.                                 tse.tse_count++;
  4469.                                 }
  4470.                             else
  4471.                                 {
  4472.                                 /* promote */
  4473.  
  4474.                                 for (gen_m.m_scmv = scmv_ppn;
  4475.                                     gen_m.m_scmv <= scmv_ppq; gen_m.m_scmv++)
  4476.                                     {
  4477.                                     *treeptr++ = gen_m;
  4478.                                     tse.tse_count++;
  4479.                                     };
  4480.                                 gen_m.m_scmv = scmv_reg;
  4481.                                 };
  4482.                                                        }
  4483.                         };
  4484.  
  4485.                     /* en passant */
  4486.  
  4487.                     if ((frrank == rank_4) && (ese.ese_epsq != sq_nil))
  4488.                         {
  4489.                         /* capture to left */
  4490.  
  4491.                         if ((frfile != file_a) &&
  4492.                             ((gen_m.m_tosq = gen_m.m_frsq + dv_6) ==
  4493.                             ese.ese_epsq))
  4494.                             {
  4495.                             gen_m.m_tocp = cp_v0;
  4496.                             gen_m.m_scmv = scmv_epc;
  4497.                             *treeptr++ = gen_m;
  4498.                             tse.tse_count++;
  4499.                             gen_m.m_scmv = scmv_reg;
  4500.                             };
  4501.  
  4502.                         /* capture to right */
  4503.  
  4504.                         if ((frfile != file_h) &&
  4505.                             ((gen_m.m_tosq = gen_m.m_frsq + dv_7) ==
  4506.                             ese.ese_epsq))
  4507.                             {
  4508.                             gen_m.m_tocp = cp_v0;
  4509.                             gen_m.m_scmv = scmv_epc;
  4510.                             *treeptr++ = gen_m;
  4511.                             tse.tse_count++;
  4512.                             gen_m.m_scmv = scmv_reg;
  4513.                             };
  4514.                         };
  4515.                     };
  4516.                 break;
  4517.  
  4518.             case p_n:
  4519.                 /* knight moves: very simple */
  4520.  
  4521.                 for (dx = dx_8; dx <= dx_f; dx++)
  4522.                     if (*(xsqptr0 + xdvv[dx]) == cp_v0)
  4523.                         {
  4524.                         gen_m.m_tocp =
  4525.                             EPDboard.rbv[gen_m.m_tosq = gen_m.m_frsq + dvv[dx]];
  4526.                         if (cv_c_cpv[gen_m.m_tocp] != ese.ese_actc)
  4527.                             {
  4528.                             *treeptr++ = gen_m;
  4529.                             tse.tse_count++;
  4530.                             };
  4531.                         };
  4532.                 break;
  4533.  
  4534.             case p_b:
  4535.                 /* bishop moves: diagonal sweeper */
  4536.  
  4537.                 for (dx = dx_4; dx <= dx_7; dx++)
  4538.                     {
  4539.                     dv = dvv[dx];
  4540.                     xdv = xdvv[dx];
  4541.                     gen_m.m_tosq = gen_m.m_frsq;
  4542.                     xsqptr1 = xsqptr0;
  4543.                     while ((*(xsqptr1 += xdv) == cp_v0) &&
  4544.                         ((gen_m.m_tocp = EPDboard.rbv[gen_m.m_tosq += dv]) ==
  4545.                         cp_v0))
  4546.                         {
  4547.                         *treeptr++ = gen_m;
  4548.                         tse.tse_count++;
  4549.                         };
  4550.                     if ((*xsqptr1 == cp_v0) &&
  4551.                         (cv_c_cpv[gen_m.m_tocp] == inv_cv[ese.ese_actc]))
  4552.                         {
  4553.                         *treeptr++ = gen_m;
  4554.                         tse.tse_count++;
  4555.                         };
  4556.                     };
  4557.                 break;
  4558.  
  4559.             case p_r:
  4560.                 /* rook moves: orthogonal sweeper */
  4561.  
  4562.                 for (dx = dx_0; dx <= dx_3; dx++)
  4563.                     {
  4564.                     dv = dvv[dx];
  4565.                     xdv = xdvv[dx];
  4566.                     gen_m.m_tosq = gen_m.m_frsq;
  4567.                     xsqptr1 = xsqptr0;
  4568.                     while ((*(xsqptr1 += xdv) == cp_v0) &&
  4569.                         ((gen_m.m_tocp = EPDboard.rbv[gen_m.m_tosq += dv]) ==
  4570.                         cp_v0))
  4571.                         {
  4572.                         *treeptr++ = gen_m;
  4573.                         tse.tse_count++;
  4574.                         };
  4575.                     if ((*xsqptr1 == cp_v0) &&
  4576.                         (cv_c_cpv[gen_m.m_tocp] == inv_cv[ese.ese_actc]))
  4577.                         {
  4578.                         *treeptr++ = gen_m;
  4579.                         tse.tse_count++;
  4580.                         };
  4581.                     };
  4582.                 break;
  4583.  
  4584.             case p_q:
  4585.                 /* queen moves: orthogonal and diagonal sweeper */
  4586.  
  4587.                 for (dx = dx_0; dx <= dx_7; dx++)
  4588.                     {
  4589.                     dv = dvv[dx];
  4590.                     xdv = xdvv[dx];
  4591.                     gen_m.m_tosq = gen_m.m_frsq;
  4592.                     xsqptr1 = xsqptr0;
  4593.                     while ((*(xsqptr1 += xdv) == cp_v0) &&
  4594.                         ((gen_m.m_tocp = EPDboard.rbv[gen_m.m_tosq += dv]) ==
  4595.                         cp_v0))
  4596.                         {
  4597.                         *treeptr++ = gen_m;
  4598.                         tse.tse_count++;
  4599.                         };
  4600.                     if ((*xsqptr1 == cp_v0) &&
  4601.                         (cv_c_cpv[gen_m.m_tocp] == inv_cv[ese.ese_actc]))
  4602.                         {
  4603.                         *treeptr++ = gen_m;
  4604.                         tse.tse_count++;
  4605.                         };
  4606.                     };
  4607.                 break;
  4608.  
  4609.             case p_k:
  4610.                 /* king moves: one square adjacent regular */
  4611.  
  4612.                 for (dx = dx_0; dx <= dx_7; dx++)
  4613.                     if (*(xsqptr0 + xdvv[dx]) == cp_v0)
  4614.                         {
  4615.                         gen_m.m_tocp =
  4616.                             EPDboard.rbv[gen_m.m_tosq = gen_m.m_frsq + dvv[dx]];
  4617.                         if (cv_c_cpv[gen_m.m_tocp] != ese.ese_actc)
  4618.                             {
  4619.                             *treeptr++ = gen_m;
  4620.                             tse.tse_count++;
  4621.                             };
  4622.                         };
  4623.  
  4624.                 /* castling; process according to active color */
  4625.  
  4626.                 if (ese.ese_actc == c_w)
  4627.                     {
  4628.                     if ((ese.ese_cast & cf_wk) && !EPDBlackAttacks(sq_e1) &&
  4629.                         Vacant(sq_f1) && !EPDBlackAttacks(sq_f1) &&
  4630.                         Vacant(sq_g1) && !EPDBlackAttacks(sq_g1))
  4631.                         {
  4632.                         gen_m.m_tosq = sq_g1;
  4633.                         gen_m.m_tocp = cp_v0;
  4634.                         gen_m.m_scmv = scmv_cks;
  4635.                         *treeptr++ = gen_m;
  4636.                         tse.tse_count++;
  4637.                         gen_m.m_scmv = scmv_reg;
  4638.                         };
  4639.  
  4640.                     if ((ese.ese_cast & cf_wq) && !EPDBlackAttacks(sq_e1) &&
  4641.                         Vacant(sq_d1) && !EPDBlackAttacks(sq_d1) &&
  4642.                         Vacant(sq_c1) && !EPDBlackAttacks(sq_c1) &&
  4643.                         Vacant(sq_b1))
  4644.                         {
  4645.                         gen_m.m_tosq = sq_c1;
  4646.                         gen_m.m_tocp = cp_v0;
  4647.                         gen_m.m_scmv = scmv_cqs;
  4648.                         *treeptr++ = gen_m;
  4649.                         tse.tse_count++;
  4650.                         gen_m.m_scmv = scmv_reg;
  4651.                         };
  4652.                     }
  4653.                 else
  4654.                     {
  4655.                     if ((ese.ese_cast & cf_bk) && !EPDWhiteAttacks(sq_e8) &&
  4656.                         Vacant(sq_f8) && !EPDWhiteAttacks(sq_f8) &&
  4657.                         Vacant(sq_g8) && !EPDWhiteAttacks(sq_g8))
  4658.                         {
  4659.                         gen_m.m_tosq = sq_g8;
  4660.                         gen_m.m_tocp = cp_v0;
  4661.                         gen_m.m_scmv = scmv_cks;
  4662.                         *treeptr++ = gen_m;
  4663.                         tse.tse_count++;
  4664.                         gen_m.m_scmv = scmv_reg;
  4665.                         };
  4666.  
  4667.                     if ((ese.ese_cast & cf_bq) && !EPDWhiteAttacks(sq_e8) &&
  4668.                         Vacant(sq_d8) && !EPDWhiteAttacks(sq_d8) &&
  4669.                         Vacant(sq_c8) && !EPDWhiteAttacks(sq_c8) &&
  4670.                         Vacant(sq_b8))
  4671.                         {
  4672.                         gen_m.m_tosq = sq_c8;
  4673.                         gen_m.m_tocp = cp_v0;
  4674.                         gen_m.m_scmv = scmv_cqs;
  4675.                         *treeptr++ = gen_m;
  4676.                         tse.tse_count++;
  4677.                         gen_m.m_scmv = scmv_reg;
  4678.                         };
  4679.                     };
  4680.                 break;
  4681.             };
  4682.         };
  4683.     };
  4684.  
  4685. return;
  4686. }
  4687.  
  4688. /*--> EPDSameMoveRef: check if two move references are the same move */
  4689. static
  4690. siT
  4691. EPDSameMoveRef(mptrT mptr0, mptrT mptr1)
  4692. {
  4693. siT flag;
  4694.  
  4695. if ((mptr0->m_tosq == mptr1->m_tosq) &&
  4696.     (mptr0->m_frsq == mptr1->m_frsq) &&
  4697.     (mptr0->m_frcp == mptr1->m_frcp) &&
  4698.     (mptr0->m_tocp == mptr1->m_tocp) &&
  4699.     (mptr0->m_scmv == mptr1->m_scmv))
  4700.     flag = 1;
  4701. else
  4702.     flag = 0;
  4703.  
  4704. return (flag);
  4705. }
  4706.  
  4707. /*--> EPDFindMove: locate the move in the current generation set */
  4708. static
  4709. mptrT
  4710. EPDFindMove(mptrT mptr)
  4711. {
  4712. mptrT rmptr;
  4713. siT flag;
  4714. siT index;
  4715.  
  4716. rmptr = tse.tse_base;
  4717. flag = 0;
  4718. index = 0;
  4719.  
  4720. while (!flag && (index < tse.tse_count))
  4721.     if (EPDSameMoveRef(mptr, rmptr))
  4722.         flag = 1;
  4723.     else
  4724.         {
  4725.         rmptr++;
  4726.         index++;
  4727.         };
  4728.  
  4729. if (!flag)
  4730.     rmptr = NULL;
  4731.  
  4732. return (rmptr);
  4733. }
  4734.  
  4735. /*--> EPDExecute: execute the supplied move */
  4736. static
  4737. void
  4738. EPDExecute(mptrT mptr)
  4739. {
  4740. sqT pcsq;
  4741. cpT ppcp;
  4742.  
  4743. /* test for overflow */
  4744.  
  4745. if (ply == (pmhL - 1))
  4746.     EPDFatal("EPDExecute: played move history overflow");
  4747.  
  4748. /* save old environment and generation records */
  4749.  
  4750. *eseptr++ = ese;
  4751. *tseptr++ = tse;
  4752.  
  4753. /* set the legality tested flag */
  4754.  
  4755. mptr->m_flag |= mf_exec;
  4756.  
  4757. /* process according to move case */
  4758.  
  4759. switch (mptr->m_scmv)
  4760.     {
  4761.     case scmv_reg:
  4762.         EPDboard.rbv[mptr->m_frsq] = cp_v0;
  4763.         EPDboard.rbv[mptr->m_tosq] = mptr->m_frcp;
  4764.         break;
  4765.  
  4766.     case scmv_epc:
  4767.         if (ese.ese_actc == c_w)
  4768.             pcsq = mptr->m_tosq + dv_3;
  4769.         else
  4770.             pcsq = mptr->m_tosq + dv_1;
  4771.         EPDboard.rbv[mptr->m_frsq] = cp_v0;
  4772.         EPDboard.rbv[mptr->m_tosq] = mptr->m_frcp;
  4773.         EPDboard.rbv[pcsq] = cp_v0;
  4774.         break;
  4775.  
  4776.     case scmv_cks:
  4777.         if (ese.ese_actc == c_w)
  4778.             {
  4779.             EPDboard.rbv[sq_e1] = cp_v0;
  4780.             EPDboard.rbv[sq_g1] = cp_wk;
  4781.             EPDboard.rbv[sq_h1] = cp_v0;
  4782.             EPDboard.rbv[sq_f1] = cp_wr;
  4783.             }
  4784.         else
  4785.             {
  4786.             EPDboard.rbv[sq_e8] = cp_v0;
  4787.             EPDboard.rbv[sq_g8] = cp_bk;
  4788.             EPDboard.rbv[sq_h8] = cp_v0;
  4789.             EPDboard.rbv[sq_f8] = cp_br;
  4790.             };
  4791.         break;
  4792.  
  4793.     case scmv_cqs:
  4794.         if (ese.ese_actc == c_w)
  4795.             {
  4796.             EPDboard.rbv[sq_e1] = cp_v0;
  4797.             EPDboard.rbv[sq_c1] = cp_wk;
  4798.             EPDboard.rbv[sq_a1] = cp_v0;
  4799.             EPDboard.rbv[sq_d1] = cp_wr;
  4800.             }
  4801.         else
  4802.             {
  4803.             EPDboard.rbv[sq_e8] = cp_v0;
  4804.             EPDboard.rbv[sq_c8] = cp_bk;
  4805.             EPDboard.rbv[sq_a8] = cp_v0;
  4806.             EPDboard.rbv[sq_d8] = cp_br;
  4807.             };
  4808.         break;
  4809.  
  4810.     case scmv_ppn:
  4811.         if (ese.ese_actc == c_w)
  4812.             ppcp = cp_wn;
  4813.         else
  4814.             ppcp = cp_bn;
  4815.         EPDboard.rbv[mptr->m_frsq] = cp_v0;
  4816.         EPDboard.rbv[mptr->m_tosq] = ppcp;
  4817.         break;
  4818.  
  4819.     case scmv_ppb:
  4820.         if (ese.ese_actc == c_w)
  4821.             ppcp = cp_wb;
  4822.         else
  4823.             ppcp = cp_bb;
  4824.         EPDboard.rbv[mptr->m_frsq] = cp_v0;
  4825.         EPDboard.rbv[mptr->m_tosq] = ppcp;
  4826.         break;
  4827.  
  4828.     case scmv_ppr:
  4829.         if (ese.ese_actc == c_w)
  4830.             ppcp = cp_wr;
  4831.         else
  4832.             ppcp = cp_br;
  4833.         EPDboard.rbv[mptr->m_frsq] = cp_v0;
  4834.         EPDboard.rbv[mptr->m_tosq] = ppcp;
  4835.         break;
  4836.  
  4837.     case scmv_ppq:
  4838.         if (ese.ese_actc == c_w)
  4839.             ppcp = cp_wq;
  4840.         else
  4841.             ppcp = cp_bq;
  4842.         EPDboard.rbv[mptr->m_frsq] = cp_v0;
  4843.         EPDboard.rbv[mptr->m_tosq] = ppcp;
  4844.         break;
  4845.     };
  4846.  
  4847. /* set values for updated environment record: active color */
  4848.  
  4849. ese.ese_actc = inv_cv[ese.ese_actc];
  4850.  
  4851. /* set values for updated environment record: castling availablity */
  4852.  
  4853. if (ese.ese_cast != 0)
  4854.     {
  4855.     if (ese.ese_cast & cf_wk)
  4856.         if ((mptr->m_frsq == sq_e1) || (mptr->m_frsq == sq_h1) ||
  4857.             (mptr->m_tosq == sq_h1))
  4858.             ese.ese_cast &= ~cf_wk;
  4859.  
  4860.     if (ese.ese_cast & cf_wq)
  4861.         if ((mptr->m_frsq == sq_e1) || (mptr->m_frsq == sq_a1) ||
  4862.             (mptr->m_tosq == sq_a1))
  4863.             ese.ese_cast &= ~cf_wq;
  4864.  
  4865.     if (ese.ese_cast & cf_bk)
  4866.         if ((mptr->m_frsq == sq_e8) || (mptr->m_frsq == sq_h8) ||
  4867.             (mptr->m_tosq == sq_h8))
  4868.             ese.ese_cast &= ~cf_bk;
  4869.  
  4870.     if (ese.ese_cast & cf_bq)
  4871.         if ((mptr->m_frsq == sq_e8) || (mptr->m_frsq == sq_a8) ||
  4872.             (mptr->m_tosq == sq_a8))
  4873.             ese.ese_cast &= ~cf_bq;
  4874.     };
  4875.  
  4876. /* set values for updated environment record: en passant */
  4877.  
  4878. if (ese.ese_actc == c_b) {
  4879.     if ((mptr->m_frcp == cp_wp) &&
  4880.         (map_rank(mptr->m_frsq) == rank_2) &&
  4881.         (map_rank(mptr->m_tosq) == rank_4))
  4882.         ese.ese_epsq = mptr->m_frsq + dv_1;
  4883.     else
  4884.         ese.ese_epsq = sq_nil;
  4885. }
  4886. else {
  4887.     if ((mptr->m_frcp == cp_bp) &&
  4888.         (map_rank(mptr->m_frsq) == rank_7) &&
  4889.         (map_rank(mptr->m_tosq) == rank_5))
  4890.         ese.ese_epsq = mptr->m_frsq + dv_3;
  4891.     else
  4892.         ese.ese_epsq = sq_nil;
  4893. }
  4894.  
  4895. /* set values for updated environment record: halfmove clock */
  4896.  
  4897. if ((mptr->m_tocp != cp_v0) || (cv_p_cpv[mptr->m_frcp] == p_p))
  4898.     ese.ese_hmvc = 0;
  4899. else
  4900.     ese.ese_hmvc++;
  4901.  
  4902. /* set values for updated environment record: fullmove number */
  4903.  
  4904. if (ese.ese_actc == c_w)
  4905.     ese.ese_fmvn++;
  4906.  
  4907. /* set values for updated environment record: king locations */
  4908.  
  4909. switch (mptr->m_frcp)
  4910.     {
  4911.     case cp_wk:
  4912.         ese.ese_ksqv[c_w] = mptr->m_tosq;
  4913.         break;
  4914.     case cp_bk:
  4915.         ese.ese_ksqv[c_b] = mptr->m_tosq;
  4916.         break;
  4917.     default:
  4918.         break;
  4919.     };
  4920.  
  4921. /* check/bust flags */
  4922.  
  4923. if (EPDTestAKIC())
  4924.     mptr->m_flag |= mf_chec;
  4925. if (EPDTestPKIC())
  4926.     mptr->m_flag |= mf_bust;
  4927.  
  4928. /* increment ply index */
  4929.  
  4930. ply++;
  4931.  
  4932. return;
  4933. }
  4934.  
  4935. /*--> EPDExecuteUpdate: update the current move pointer, then execute */
  4936. nonstatic
  4937. void
  4938. EPDExecuteUpdate(mptrT mptr)
  4939. {
  4940. tse.tse_curr = EPDFindMove(mptr);
  4941. if (tse.tse_curr == NULL)
  4942.     EPDFatal("EPDExecuteUpdate: can't find move");
  4943.  
  4944. EPDExecute(tse.tse_curr);
  4945.  
  4946. return;
  4947. }
  4948.  
  4949. /*--> EPDRetract: retract the supplied move */
  4950. static
  4951. void
  4952. EPDRetract(mptrT mptr)
  4953. {
  4954. /* decrement ply */
  4955.  
  4956. ply--;
  4957.  
  4958. /* restore the current environment and generation */
  4959.  
  4960. ese = *--eseptr;
  4961. tse = *--tseptr;
  4962.  
  4963. /* process by move case */
  4964.  
  4965. switch (mptr->m_scmv)
  4966.     {
  4967.     case scmv_reg:
  4968.         EPDboard.rbv[mptr->m_tosq] = mptr->m_tocp;
  4969.         EPDboard.rbv[mptr->m_frsq] = mptr->m_frcp;
  4970.         break;
  4971.  
  4972.     case scmv_epc:
  4973.         EPDboard.rbv[mptr->m_tosq] = cp_v0;
  4974.         EPDboard.rbv[mptr->m_frsq] = mptr->m_frcp;
  4975.         if (ese.ese_actc == c_w)
  4976.             EPDboard.rbv[mptr->m_tosq + dv_3] = cp_bp;
  4977.         else
  4978.             EPDboard.rbv[mptr->m_tosq + dv_1] = cp_wp;
  4979.         break;
  4980.  
  4981.     case scmv_cks:
  4982.         if (ese.ese_actc == c_w)
  4983.             {
  4984.             EPDboard.rbv[sq_g1] = cp_v0;
  4985.             EPDboard.rbv[sq_e1] = cp_wk;
  4986.             EPDboard.rbv[sq_f1] = cp_v0;
  4987.             EPDboard.rbv[sq_h1] = cp_wr;
  4988.             }
  4989.         else
  4990.             {
  4991.             EPDboard.rbv[sq_g8] = cp_v0;
  4992.             EPDboard.rbv[sq_e8] = cp_bk;
  4993.             EPDboard.rbv[sq_f8] = cp_v0;
  4994.             EPDboard.rbv[sq_h8] = cp_br;
  4995.             }
  4996.         break;
  4997.  
  4998.     case scmv_cqs:
  4999.         if (ese.ese_actc == c_w)
  5000.             {
  5001.             EPDboard.rbv[sq_c1] = cp_v0;
  5002.             EPDboard.rbv[sq_e1] = cp_wk;
  5003.             EPDboard.rbv[sq_d1] = cp_v0;
  5004.             EPDboard.rbv[sq_a1] = cp_wr;
  5005.             }
  5006.         else
  5007.             {
  5008.             EPDboard.rbv[sq_c8] = cp_v0;
  5009.             EPDboard.rbv[sq_e8] = cp_bk;
  5010.             EPDboard.rbv[sq_d8] = cp_v0;
  5011.             EPDboard.rbv[sq_a8] = cp_br;
  5012.             };
  5013.         break;
  5014.  
  5015.     case scmv_ppn:
  5016.     case scmv_ppb:
  5017.     case scmv_ppr:
  5018.     case scmv_ppq:
  5019.         EPDboard.rbv[mptr->m_tosq] = mptr->m_tocp;
  5020.         EPDboard.rbv[mptr->m_frsq] = mptr->m_frcp;
  5021.         break;
  5022.     };
  5023.  
  5024. return;
  5025. }
  5026.  
  5027. /*--> EPDRetractUpdate: retract last executed move */
  5028. nonstatic
  5029. void
  5030. EPDRetractUpdate(void)
  5031. {
  5032. mptrT mptr;
  5033.  
  5034. mptr = (tseptr - 1)->tse_curr;
  5035. EPDRetract(mptr);
  5036.  
  5037. return;
  5038. }
  5039.  
  5040. /*--> EPDRetractAll: retract all moves in current variation */
  5041. nonstatic
  5042. void
  5043. EPDRetractAll(void)
  5044. {
  5045. while (ply > 0)
  5046.     EPDRetractUpdate();
  5047.  
  5048. return;
  5049. }
  5050.  
  5051. /*--> EPDCollapse: collapse the played move stack */
  5052. nonstatic
  5053. void
  5054. EPDCollapse(void)
  5055. {
  5056. /* process for nonzero ply */
  5057.  
  5058. if (ply > 0)
  5059.     {
  5060.     /* reset the stack pointers */
  5061.  
  5062.     treeptr = treebaseptr;
  5063.     eseptr = esebaseptr;
  5064.     tseptr = tsebaseptr;
  5065.  
  5066.     /* reset the ply */
  5067.  
  5068.     ply = 0;
  5069.     };
  5070.  
  5071. return;
  5072. }
  5073.  
  5074. /*--> EPDReset: collapse, then reset starting position */
  5075. nonstatic
  5076. void
  5077. EPDReset(void)
  5078. {
  5079. EPDCollapse();
  5080. EPDInitArray();
  5081.  
  5082. return;
  5083. }
  5084.  
  5085. /*--> EPDMLExec: execute the current move list */
  5086. static
  5087. void
  5088. EPDMLExec(void)
  5089. {
  5090. siT i;
  5091. mptrT mptr;
  5092.  
  5093. /* test and mark each move for legality and checking status */
  5094.  
  5095. mptr = tse.tse_base;
  5096. for (i = 0; i < tse.tse_count; i++)
  5097.     {
  5098.     tse.tse_curr = mptr;
  5099.     EPDExecute(mptr);
  5100.     EPDRetract(mptr);
  5101.     mptr++;
  5102.     };
  5103.  
  5104. return;
  5105. }
  5106.  
  5107. /*--> EPDMLPolice: remove illegal moves the current move list */
  5108. static
  5109. void
  5110. EPDMLPolice(void)
  5111. {
  5112. mptrT tptr, mptr;
  5113. siT i, bust;
  5114. mT t_m;
  5115.  
  5116. /* move illegal moves to end of list */
  5117.  
  5118. mptr = tse.tse_base;
  5119. bust = 0;
  5120. i = 0;
  5121. while (i < (tse.tse_count - bust))
  5122.     if (mptr->m_flag & mf_bust)
  5123.         {
  5124.         tptr = (tse.tse_base + (tse.tse_count - 1)) - bust;
  5125.         t_m = *mptr;
  5126.         *mptr = *tptr;
  5127.         *tptr = t_m;
  5128.         bust++;
  5129.         }
  5130.     else
  5131.         {
  5132.         mptr++;
  5133.         i++;
  5134.         };
  5135.  
  5136. /* shrink */
  5137.  
  5138. tse.tse_count -= bust;
  5139.  
  5140. return;
  5141. }
  5142.  
  5143. /*--> EPDMLDisambiguate: insert disambiguation flags in move list */
  5144. static
  5145. void
  5146. EPDMLDisambiguate(void)
  5147. {
  5148. siT i, j, tmc, rmc, fmc;
  5149. mptrT mptr0, mptr1;
  5150. pT p;
  5151. rankT rank;
  5152. fileT file;
  5153.  
  5154. /* it's magic */
  5155.  
  5156. mptr0 = tse.tse_base;
  5157. for (i = 0; i < tse.tse_count; i++)
  5158.     {
  5159.     /* the outer loop disambiguates a single move per cycle */
  5160.  
  5161.     p = cv_p_cpv[mptr0->m_frcp];
  5162.     if ((p != p_p) && (p != p_k))
  5163.         {
  5164.         rank = map_rank(mptr0->m_frsq);
  5165.         file = map_file(mptr0->m_frsq);
  5166.         tmc = rmc = fmc = 0;
  5167.         mptr1 = tse.tse_base;
  5168.         for (j = 0; j < tse.tse_count; j++)
  5169.             {
  5170.             /* the inner loop examines all possible sibling puns */
  5171.  
  5172.             if ((i != j) && (mptr0->m_frcp == mptr1->m_frcp) &&
  5173.                 (mptr0->m_tosq == mptr1->m_tosq))
  5174.                 {
  5175.                 tmc++;
  5176.                 if (map_rank(mptr1->m_frsq) == rank)
  5177.                     rmc++;
  5178.                 if (map_file(mptr1->m_frsq) == file)
  5179.                     fmc++;
  5180.                 };
  5181.             mptr1++;
  5182.             };
  5183.  
  5184.         /* check pun count for outer loop move */
  5185.  
  5186.         if (tmc > 0)
  5187.             {
  5188.             /* file disambiguation has priority */
  5189.  
  5190.             if ((rmc > 0) || ((rmc == 0) && (fmc == 0)))
  5191.                 mptr0->m_flag |= mf_sanf;
  5192.  
  5193.             /* rank disambiguation may be needed */
  5194.  
  5195.             if (fmc > 0)
  5196.                 mptr0->m_flag |= mf_sanr;
  5197.             };
  5198.         };
  5199.     mptr0++;
  5200.     };
  5201.  
  5202. return;
  5203. }
  5204.  
  5205. /*--> EPDMLScanMate: scan current move list for mating moves */
  5206. static
  5207. void
  5208. EPDMLScanMate(void)
  5209. {
  5210. siT i, j, mateflag, drawflag, moveflag;
  5211. mptrT mptr0, mptr1;
  5212.  
  5213. /* scan */
  5214.  
  5215. mptr0 = tse.tse_base;
  5216. for (i = 0; i < tse.tse_count; i++)
  5217.     {
  5218.     tse.tse_curr = mptr0;
  5219.     EPDExecute(mptr0);
  5220.  
  5221.     /* now at next higher ply, generate psuedolegal set */
  5222.  
  5223.     EPDGeneratePL();
  5224.  
  5225.     /* try to find at least one legal move */
  5226.  
  5227.     mptr1 = tse.tse_base;
  5228.     moveflag = 0;
  5229.     j = 0;
  5230.     while (!moveflag && (j < tse.tse_count))
  5231.         {
  5232.         tse.tse_curr = mptr1;
  5233.         EPDExecute(mptr1);
  5234.         EPDRetract(mptr1);
  5235.         if (!(mptr1->m_flag & mf_bust))
  5236.             moveflag = 1;
  5237.         else
  5238.             {
  5239.             mptr1++;
  5240.             j++;
  5241.             };
  5242.         };
  5243.  
  5244.     /* any second level moves detected? */
  5245.  
  5246.     if (moveflag != 0)
  5247.         {
  5248.         /* not a mate */
  5249.  
  5250.         mateflag = drawflag = 0;
  5251.         }
  5252.     else
  5253.         {
  5254.         /* a mating move is detected */
  5255.  
  5256.         if (EPDTestAKIC())
  5257.             {
  5258.             mateflag = 1;
  5259.             drawflag = 0;
  5260.             }
  5261.         else
  5262.             {
  5263.             drawflag = 1;
  5264.             mateflag = 0;
  5265.             };
  5266.         };
  5267.  
  5268.     /* undo execution */
  5269.  
  5270.     EPDRetract(mptr0);
  5271.  
  5272.     /* now back at lower ply */
  5273.  
  5274.     if (mateflag)
  5275.         mptr0->m_flag |= mf_chmt;
  5276.     else
  5277.         if (drawflag)
  5278.             mptr0->m_flag |= (mf_draw | mf_stmt);
  5279.  
  5280.     /* next move */
  5281.  
  5282.     mptr0++;
  5283.     };
  5284.  
  5285. return;
  5286. }
  5287.  
  5288. /*--> EPDGenClean: generate move list with first level processing */
  5289. static
  5290. void
  5291. EPDGenClean(void)
  5292. {
  5293. /* basic psuedolegal generation */
  5294.  
  5295. EPDGeneratePL();
  5296.  
  5297. /* set legality flags, remove illegal moves, and disambiguate */
  5298.  
  5299. EPDMLExec();
  5300. EPDMLPolice();
  5301. EPDMLDisambiguate();
  5302.  
  5303. return;
  5304. }
  5305.  
  5306. /*--> EPDGenMoves: generate legal moves and set mate flags */
  5307. nonstatic
  5308. void
  5309. EPDGenMoves(void)
  5310. {
  5311. /* perform basic first level generation */
  5312.  
  5313. EPDGenClean();
  5314.  
  5315. /* handle two ply draw and checkmate detection */
  5316.  
  5317. EPDMLScanMate();
  5318.  
  5319. return;
  5320. }
  5321.  
  5322. /*--> EPDFetchMoveCount: fetch the move count */
  5323. nonstatic
  5324. siT
  5325. EPDFetchMoveCount(void)
  5326. {
  5327.  
  5328. return (tse.tse_count);
  5329. }
  5330.  
  5331. /*--> EPDFetchMove: fetch the nth move */
  5332. nonstatic
  5333. mptrT
  5334. EPDFetchMove(siT index)
  5335. {
  5336. ret_m = *(tse.tse_base + index);
  5337.  
  5338. return (&ret_m);
  5339. }
  5340.  
  5341. /*--> EPDSetMoveFlags: set move flags from current generation set */
  5342. nonstatic
  5343. void
  5344. EPDSetMoveFlags(mptrT mptr)
  5345. {
  5346. mptrT rmptr;
  5347.  
  5348. rmptr = EPDFindMove(mptr);
  5349. if (rmptr != NULL)
  5350.     mptr->m_flag = rmptr->m_flag;
  5351.  
  5352. return;
  5353. }
  5354.  
  5355. /*--> EPDSortSAN: ASCII SAN sort move list */
  5356. nonstatic
  5357. void
  5358. EPDSortSAN(void)
  5359. {
  5360. mptrT mptr, mptr0, mptr1;
  5361. siT i, j, pair, pass, flag;
  5362. sanptrT sanptr, sptr0, sptr1;
  5363. char t_ch;
  5364. mT t_m;
  5365.  
  5366. /* allocate the SAN string vector */
  5367.  
  5368. sanptr = (sanptrT) EPDMemoryGrab(sizeof(sanT) * tse.tse_count);
  5369.  
  5370. /* construct the SAN string entries */
  5371.  
  5372. mptr = tse.tse_base;
  5373. for (i = 0; i < tse.tse_count; i++)
  5374.     EPDSANEncode(mptr++, *(sanptr + i));
  5375.  
  5376. /* a low tech bubble sort */
  5377.  
  5378. flag = 1;
  5379. pass = 0;
  5380. while (flag && (pass < (tse.tse_count - 1)))
  5381.     {
  5382.     sptr0 = sanptr;
  5383.     sptr1 = sanptr + 1;
  5384.     mptr0 = tse.tse_base;
  5385.     mptr1 = tse.tse_base + 1;
  5386.     flag = 0;
  5387.     pair = 0;
  5388.     while (pair < (tse.tse_count - pass - 1))
  5389.         {
  5390.         /* case sensitive ascending order */
  5391.  
  5392.         if (strcmp((charptrT) sptr0, (charptrT) sptr1) > 0)
  5393.             {
  5394.             flag = 1;
  5395.             for (j = 0; j < sanL; j++)
  5396.                 {
  5397.                 t_ch = (*sptr0)[j];
  5398.                 (*sptr0)[j] = (*sptr1)[j];
  5399.                 (*sptr1)[j] = t_ch;
  5400.                 };
  5401.             t_m = *mptr0;
  5402.             *mptr0 = *mptr1;
  5403.             *mptr1 = t_m;
  5404.             };
  5405.         sptr0++;
  5406.         sptr1++;
  5407.         mptr0++;
  5408.         mptr1++;
  5409.         pair++;
  5410.         };
  5411.     pass++;
  5412.     };
  5413.  
  5414. EPDMemoryFree(sanptr);
  5415.  
  5416. return;
  5417. }
  5418.  
  5419. /*--> EPDRepairMove: repair a move operation */
  5420. static
  5421. void
  5422. EPDRepairMove(eopptrT eopptr)
  5423. {
  5424. eovptrT eovptr;
  5425. mptrT mptr;
  5426. mT m;
  5427. sanT san;
  5428.  
  5429. /* repair a single move from the current position */
  5430.  
  5431. eovptr = eopptr->eop_headeov;
  5432. if (eovptr != NULL)
  5433.     {
  5434.     mptr = EPDSANDecodeAux(eovptr->eov_str, 0);
  5435.     if (mptr != NULL)
  5436.         {
  5437.         m = *mptr;
  5438.         EPDSANEncode(&m, san);
  5439.         if (strcmp(eovptr->eov_str, san) != 0)
  5440.             EPDReplaceEOVStr(eovptr, san);
  5441.         };
  5442.     };
  5443.  
  5444. return;
  5445. }
  5446.  
  5447. /*--> EPDRepairMoveset: repair a moveset operation */
  5448. static
  5449. void
  5450. EPDRepairMoveset(eopptrT eopptr)
  5451. {
  5452. eovptrT eovptr;
  5453. mptrT mptr;
  5454. mT m;
  5455. sanT san;
  5456.  
  5457. /* check each move from the current position */
  5458.  
  5459. eovptr = eopptr->eop_headeov;
  5460. while (eovptr != NULL)
  5461.     {
  5462.     mptr = EPDSANDecodeAux(eovptr->eov_str, 0);
  5463.     if (mptr != NULL)
  5464.         {
  5465.         m = *mptr;
  5466.         EPDSANEncode(&m, san);
  5467.         if (strcmp(eovptr->eov_str, san) != 0)
  5468.             EPDReplaceEOVStr(eovptr, san);
  5469.         };
  5470.  
  5471.     eovptr = eovptr->eov_next;
  5472.     };
  5473.  
  5474. return;
  5475. }
  5476.  
  5477. /*--> EPDRepairVariation: repair a variation operation */
  5478. static
  5479. void
  5480. EPDRepairVariation(eopptrT eopptr)
  5481. {
  5482. eovptrT eovptr;
  5483. mptrT mptr;
  5484. mT m;
  5485. sanT san;
  5486.  
  5487. /* play move sequence from the current position */
  5488.  
  5489. eovptr = eopptr->eop_headeov;
  5490. while (eovptr != NULL)
  5491.     {
  5492.     mptr = EPDSANDecodeAux(eovptr->eov_str, 0);
  5493.     if (mptr == NULL)
  5494.         eovptr = NULL;
  5495.     else
  5496.         {
  5497.         m = *mptr;
  5498.         EPDSANEncode(&m, san);
  5499.         if (strcmp(eovptr->eov_str, san) != 0)
  5500.             EPDReplaceEOVStr(eovptr, san);
  5501.  
  5502.         tse.tse_curr = EPDFindMove(mptr);
  5503.         if (tse.tse_curr == NULL)
  5504.             EPDFatal("EPDRepairVariation: can't find move");
  5505.  
  5506.         EPDExecute(mptr);
  5507.         EPDGenMoves();
  5508.  
  5509.         eovptr = eovptr->eov_next;
  5510.         }
  5511.     };
  5512.  
  5513. /* retract any executed moves */
  5514.  
  5515. EPDRetractAll();
  5516.  
  5517. return;
  5518. }
  5519.  
  5520. /*--> EPDPurgeOpFile: purge operation from input file to output file */
  5521. nonstatic
  5522. siT
  5523. EPDPurgeOpFile(charptrT opsym, charptrT fn0, charptrT fn1)
  5524. {
  5525. siT flag;
  5526. fptrT fptr0, fptr1;
  5527. epdptrT epdptr;
  5528. eopptrT eopptr;
  5529. charptrT eptr;
  5530. char ev[epdL];
  5531.  
  5532. /* set default return value (success) */
  5533.  
  5534. flag = 1;
  5535.  
  5536. /* clear the input and output file pointers */
  5537.  
  5538. fptr0 = fptr1 = NULL;
  5539.  
  5540. /* open the input file for reading */
  5541.  
  5542. if (flag)
  5543.     {
  5544.     fptr0 = fopen(fn0, "r");
  5545.     if (fptr0 == NULL)
  5546.         flag = 0;
  5547.     };
  5548.  
  5549. /* open the output file for writing */
  5550.  
  5551. if (flag)
  5552.     {
  5553.     fptr1 = fopen(fn1, "w");
  5554.     if (fptr1 == NULL)
  5555.         flag = 0;
  5556.     };
  5557.  
  5558. /* scan entire file */
  5559.  
  5560. while (flag && (fgets(ev, (epdL - 1), fptr0) != NULL))
  5561.     {
  5562.     /* decode a record */
  5563.  
  5564.     epdptr = EPDDecode(ev);
  5565.  
  5566.     /* check record decode validity */
  5567.  
  5568.     if (epdptr == NULL)
  5569.         flag = 0;
  5570.     else
  5571.         {
  5572.         /* locate the operation to be purged */
  5573.  
  5574.         eopptr = EPDLocateEOP(epdptr, opsym);
  5575.         if (eopptr != NULL)
  5576.             {
  5577.             EPDUnthreadEOP(epdptr, eopptr);
  5578.             EPDReleaseEOP(eopptr);
  5579.             };
  5580.  
  5581.         /* encode the record (includes normalization) */
  5582.  
  5583.         eptr = EPDEncode(epdptr);
  5584.  
  5585.         /* release EPD structure */
  5586.  
  5587.         EPDReleaseEPD(epdptr);
  5588.  
  5589.         /* check result */
  5590.  
  5591.         if (eptr == NULL)
  5592.             flag = 0;
  5593.         else
  5594.             {
  5595.             fprintf(fptr1, "%s\n", eptr);
  5596.             EPDMemoryFree(eptr);
  5597.             };
  5598.         };
  5599.     };
  5600.  
  5601. /* close input and output files */
  5602.  
  5603. if (fptr0 != NULL)
  5604.     fclose(fptr0);
  5605.  
  5606. if (fptr1 != NULL)
  5607.     fclose(fptr1);
  5608.  
  5609. return (flag);
  5610. }
  5611.  
  5612. /*--> EPDRepairEPD: repair an EPD structure */
  5613. nonstatic
  5614. siT
  5615. EPDRepairEPD(epdptrT epdptr)
  5616. {
  5617. siT flag;
  5618. eopptrT eopptr;
  5619.  
  5620. /* set default return value: repair successful */
  5621.  
  5622. flag = 1;
  5623.  
  5624. /* set up the position as the current position */
  5625.  
  5626. EPDRealize(epdptr);
  5627.  
  5628. /* check legality */
  5629.  
  5630. if (!EPDIsLegal())
  5631.     flag = 0;
  5632. else
  5633.     {
  5634.     /* generate moves and notation */
  5635.  
  5636.     EPDGenMoves();
  5637.  
  5638.     /* repair moveset "am" */
  5639.  
  5640.     eopptr = EPDLocateEOP(epdptr, epdsostrv[epdso_am]);
  5641.     if (eopptr != NULL)
  5642.         EPDRepairMoveset(eopptr);
  5643.  
  5644.     /* repair moveset "bm" */
  5645.  
  5646.     eopptr = EPDLocateEOP(epdptr, epdsostrv[epdso_bm]);
  5647.     if (eopptr != NULL)
  5648.         EPDRepairMoveset(eopptr);
  5649.  
  5650.     /* repair move "pm" */
  5651.  
  5652.     eopptr = EPDLocateEOP(epdptr, epdsostrv[epdso_pm]);
  5653.     if (eopptr != NULL)
  5654.         EPDRepairMove(eopptr);
  5655.  
  5656.     /* repair variation "pv" */
  5657.  
  5658.     eopptr = EPDLocateEOP(epdptr, epdsostrv[epdso_pv]);
  5659.     if (eopptr != NULL)
  5660.         EPDRepairVariation(eopptr);
  5661.  
  5662.     /* repair move "sm" */
  5663.  
  5664.     eopptr = EPDLocateEOP(epdptr, epdsostrv[epdso_sm]);
  5665.     if (eopptr != NULL)
  5666.         EPDRepairMove(eopptr);
  5667.  
  5668.     /* repair variation "sv" */
  5669.  
  5670.     eopptr = EPDLocateEOP(epdptr, epdsostrv[epdso_sv]);
  5671.     if (eopptr != NULL)
  5672.         EPDRepairVariation(eopptr);
  5673.     };
  5674.  
  5675. return (flag);
  5676. }
  5677.  
  5678. /*--> EPDRepairFile: repair input file to output file */
  5679. nonstatic
  5680. siT
  5681. EPDRepairFile(charptrT fn0, charptrT fn1)
  5682. {
  5683. siT flag;
  5684. fptrT fptr0, fptr1;
  5685. epdptrT epdptr;
  5686. charptrT eptr;
  5687. char ev[epdL];
  5688.  
  5689. /* set default return value (success) */
  5690.  
  5691. flag = 1;
  5692.  
  5693. /* clear the input and output file pointers */
  5694.  
  5695. fptr0 = fptr1 = NULL;
  5696.  
  5697. /* open the input file for reading */
  5698.  
  5699. if (flag)
  5700.     {
  5701.     fptr0 = fopen(fn0, "r");
  5702.     if (fptr0 == NULL)
  5703.         flag = 0;
  5704.     };
  5705.  
  5706. /* open the output file for writing */
  5707.  
  5708. if (flag)
  5709.     {
  5710.     fptr1 = fopen(fn1, "w");
  5711.     if (fptr1 == NULL)
  5712.         flag = 0;
  5713.     };
  5714.  
  5715. /* scan entire file */
  5716.  
  5717. while (flag && (fgets(ev, (epdL - 1), fptr0) != NULL))
  5718.     {
  5719.     /* decode a record */
  5720.  
  5721.     epdptr = EPDDecode(ev);
  5722.  
  5723.     /* check record decode validity */
  5724.  
  5725.     if (epdptr == NULL)
  5726.         flag = 0;
  5727.     else
  5728.         {
  5729.         /* make repairs */
  5730.  
  5731.         flag = EPDRepairEPD(epdptr);
  5732.  
  5733.         /* continue if repair okay */
  5734.  
  5735.         if (flag)
  5736.             {
  5737.             /* encode the normalized record */
  5738.  
  5739.             eptr = EPDEncode(epdptr);
  5740.  
  5741.             /* check result */
  5742.  
  5743.             if (eptr == NULL)
  5744.                 flag = 0;
  5745.             else
  5746.                 {
  5747.                 fprintf(fptr1, "%s\n", eptr);
  5748.                 EPDMemoryFree(eptr);
  5749.                 };
  5750.             };
  5751.  
  5752.         /* release EPD structure */
  5753.  
  5754.         EPDReleaseEPD(epdptr);
  5755.         };
  5756.     };
  5757.  
  5758. /* close input and output files */
  5759.  
  5760. if (fptr0 != NULL)
  5761.     fclose(fptr0);
  5762.  
  5763. if (fptr1 != NULL)
  5764.     fclose(fptr1);
  5765.  
  5766. return (flag);
  5767. }
  5768.  
  5769. /*--> EPDNormalizeFile: normalize input file to output file */
  5770. nonstatic
  5771. siT
  5772. EPDNormalizeFile(charptrT fn0, charptrT fn1)
  5773. {
  5774. siT flag;
  5775. fptrT fptr0, fptr1;
  5776. epdptrT epdptr;
  5777. charptrT eptr;
  5778. char ev[epdL];
  5779.  
  5780. /* set default return value (success) */
  5781.  
  5782. flag = 1;
  5783.  
  5784. /* clear the input and output file pointers */
  5785.  
  5786. fptr0 = fptr1 = NULL;
  5787.  
  5788. /* open the input file for reading */
  5789.  
  5790. if (flag)
  5791.     {
  5792.     fptr0 = fopen(fn0, "r");
  5793.     if (fptr0 == NULL)
  5794.         flag = 0;
  5795.     };
  5796.  
  5797. /* open the output file for writing */
  5798.  
  5799. if (flag)
  5800.     {
  5801.     fptr1 = fopen(fn1, "w");
  5802.     if (fptr1 == NULL)
  5803.         flag = 0;
  5804.     };
  5805.  
  5806. /* scan entire file */
  5807.  
  5808. while (flag && (fgets(ev, (epdL - 1), fptr0) != NULL))
  5809.     {
  5810.     /* decode a record */
  5811.  
  5812.     epdptr = EPDDecode(ev);
  5813.  
  5814.     /* check record decode validity */
  5815.  
  5816.     if (epdptr == NULL)
  5817.         flag = 0;
  5818.     else
  5819.         {
  5820.         /* encode the record (this includes normalization) */
  5821.  
  5822.         eptr = EPDEncode(epdptr);
  5823.  
  5824.         /* release EPD structure */
  5825.  
  5826.         EPDReleaseEPD(epdptr);
  5827.  
  5828.         /* check result */
  5829.  
  5830.         if (eptr == NULL)
  5831.             flag = 0;
  5832.         else
  5833.             {
  5834.             fprintf(fptr1, "%s\n", eptr);
  5835.             EPDMemoryFree(eptr);
  5836.             };
  5837.         };
  5838.     };
  5839.  
  5840. /* close input and output files */
  5841.  
  5842. if (fptr0 != NULL)
  5843.     fclose(fptr0);
  5844.  
  5845. if (fptr1 != NULL)
  5846.     fclose(fptr1);
  5847.  
  5848. return (flag);
  5849. }
  5850.  
  5851. /*--> EPDScoreFile: score a benchmark file */
  5852. nonstatic
  5853. siT
  5854. EPDScoreFile(charptrT fn, bmsptrT bmsptr)
  5855. {
  5856. siT flag;
  5857. siT skipflag;
  5858. siT am_flag, bm_flag;
  5859. siT solved;
  5860. fptrT fptr;
  5861. epdptrT epdptr;
  5862. eopptrT am_eopptr, bm_eopptr, acd_eopptr, acn_eopptr, acs_eopptr;
  5863. eopptrT sm_eopptr, sv_eopptr, pm_eopptr, pv_eopptr;
  5864. charptrT result;
  5865. char ev[epdL];
  5866.  
  5867. /* set default return value (success) */
  5868.  
  5869. flag = 1;
  5870.  
  5871. /* clear the input file pointer */
  5872.  
  5873. fptr = NULL;
  5874.  
  5875. /* preset the summary structure */
  5876.  
  5877. bmsptr->bms_acdflag = bmsptr->bms_acnflag = bmsptr->bms_acsflag = 1;
  5878. bmsptr->bms_total = bmsptr->bms_solve = bmsptr->bms_unsol = 0;
  5879. bmsptr->bms_total_acd = bmsptr->bms_solve_acd = bmsptr->bms_unsol_acd = 0;
  5880. bmsptr->bms_total_acn = bmsptr->bms_solve_acn = bmsptr->bms_unsol_acn = 0;
  5881. bmsptr->bms_total_acs = bmsptr->bms_solve_acs = bmsptr->bms_unsol_acs = 0;
  5882.  
  5883. /* open the input file for reading */
  5884.  
  5885. if (flag)
  5886.     {
  5887.     fptr = fopen(fn, "r");
  5888.     if (fptr == NULL)
  5889.         flag = 0;
  5890.     };
  5891.  
  5892. /* scan entire file */
  5893.  
  5894. while (flag && (fgets(ev, (epdL - 1), fptr) != NULL))
  5895.     {
  5896.     /* decode a record */
  5897.  
  5898.     epdptr = EPDDecode(ev);
  5899.  
  5900.     /* check record decode validity */
  5901.  
  5902.     if (epdptr == NULL)
  5903.         flag = 0;
  5904.     else
  5905.         {
  5906.         /* clear the move result pointer */
  5907.  
  5908.         result = NULL;
  5909.  
  5910.         /* initialize various operation pointers */
  5911.  
  5912.         am_eopptr = EPDLocateEOPCode(epdptr, epdso_am);
  5913.         bm_eopptr = EPDLocateEOPCode(epdptr, epdso_bm);
  5914.         acd_eopptr = EPDLocateEOPCode(epdptr, epdso_acd);
  5915.         acn_eopptr = EPDLocateEOPCode(epdptr, epdso_acn);
  5916.         acs_eopptr = EPDLocateEOPCode(epdptr, epdso_acs);
  5917.         sm_eopptr = EPDLocateEOPCode(epdptr, epdso_sm);
  5918.         sv_eopptr = EPDLocateEOPCode(epdptr, epdso_sv);
  5919.         pm_eopptr = EPDLocateEOPCode(epdptr, epdso_pm);
  5920.         pv_eopptr = EPDLocateEOPCode(epdptr, epdso_pv);
  5921.  
  5922.         /* test for am/bm existence */
  5923.  
  5924.         if ((am_eopptr == NULL) && (bm_eopptr == NULL))
  5925.             skipflag = 1;
  5926.         else
  5927.             skipflag = 0;
  5928.  
  5929.         /* try to locate a result move (note priority) */
  5930.  
  5931.         if (!skipflag)
  5932.             {
  5933.             if (result == NULL)
  5934.                 if ((pv_eopptr != NULL) && (pv_eopptr->eop_headeov != NULL))
  5935.                     result = pv_eopptr->eop_headeov->eov_str;
  5936.  
  5937.             if (result == NULL)
  5938.                 if ((pm_eopptr != NULL) && (pm_eopptr->eop_headeov != NULL))
  5939.                     result = pm_eopptr->eop_headeov->eov_str;
  5940.  
  5941.             if (result == NULL)
  5942.                 if ((sv_eopptr != NULL) && (sv_eopptr->eop_headeov != NULL))
  5943.                     result = sv_eopptr->eop_headeov->eov_str;
  5944.  
  5945.             if (result == NULL)
  5946.                 if ((sm_eopptr != NULL) && (sm_eopptr->eop_headeov != NULL))
  5947.                     result = sm_eopptr->eop_headeov->eov_str;
  5948.  
  5949.             if (result == NULL)
  5950.                 skipflag = 1;
  5951.             };
  5952.  
  5953.         /* determine solve status */
  5954.  
  5955.         if (!skipflag)
  5956.             {
  5957.             /* check for clearance with the am set */
  5958.  
  5959.             if ((am_eopptr == NULL) ||
  5960.                 (EPDLocateEOV(am_eopptr, result) == NULL))
  5961.                 am_flag = 1;
  5962.             else
  5963.                 am_flag = 0;
  5964.  
  5965.             /* check for clearance with the bm set */
  5966.  
  5967.             if ((bm_eopptr == NULL) ||
  5968.                 (EPDLocateEOV(bm_eopptr, result) != NULL))
  5969.                 bm_flag = 1;
  5970.             else
  5971.                 bm_flag = 0;
  5972.  
  5973.             /* set solution flag */
  5974.  
  5975.             solved = am_flag && bm_flag;
  5976.             };
  5977.  
  5978.         /* update statistics block */
  5979.  
  5980.         if (!skipflag)
  5981.             {
  5982.             /* clear acd flag if acd is missing */
  5983.  
  5984.             if ((acd_eopptr == NULL) || (acd_eopptr->eop_headeov == NULL))
  5985.                 bmsptr->bms_acdflag = 0;
  5986.  
  5987.             /* clear acn flag if acn is missing */
  5988.  
  5989.             if ((acn_eopptr == NULL) || (acn_eopptr->eop_headeov == NULL))
  5990.                 bmsptr->bms_acnflag = 0;
  5991.  
  5992.             /* clear acs flag if acs is missing */
  5993.  
  5994.             if ((acs_eopptr == NULL) || (acs_eopptr->eop_headeov == NULL))
  5995.                 bmsptr->bms_acsflag = 0;
  5996.  
  5997.             /* increment record count */
  5998.  
  5999.             bmsptr->bms_total++;
  6000.  
  6001.             /* fold in acd value */
  6002.  
  6003.             if (bmsptr->bms_acdflag)
  6004.                 {
  6005.                 bmsptr->bms_total_acd +=
  6006.                     atoi(acd_eopptr->eop_headeov->eov_str);
  6007.                 if (solved)
  6008.                     bmsptr->bms_solve_acd +=
  6009.                         atoi(acd_eopptr->eop_headeov->eov_str);
  6010.                 else
  6011.                     bmsptr->bms_unsol_acd +=
  6012.                         atoi(acd_eopptr->eop_headeov->eov_str);
  6013.                 };
  6014.  
  6015.             /* fold in acn value */
  6016.  
  6017.             if (bmsptr->bms_acnflag)
  6018.                 {
  6019.                 bmsptr->bms_total_acn +=
  6020.                     atoi(acn_eopptr->eop_headeov->eov_str);
  6021.                 if (solved)
  6022.                     bmsptr->bms_solve_acn +=
  6023.                         atoi(acn_eopptr->eop_headeov->eov_str);
  6024.                 else
  6025.                     bmsptr->bms_unsol_acn +=
  6026.                         atoi(acn_eopptr->eop_headeov->eov_str);
  6027.                 };
  6028.  
  6029.             /* fold in acs value */
  6030.  
  6031.             if (bmsptr->bms_acsflag)
  6032.                 {
  6033.                 bmsptr->bms_total_acs +=
  6034.                     atoi(acs_eopptr->eop_headeov->eov_str);
  6035.                 if (solved)
  6036.                     bmsptr->bms_solve_acs +=
  6037.                         atoi(acs_eopptr->eop_headeov->eov_str);
  6038.                 else
  6039.                     bmsptr->bms_unsol_acs +=
  6040.                         atoi(acs_eopptr->eop_headeov->eov_str);
  6041.                 };
  6042.  
  6043.             /* update remaining items according to solved status */
  6044.  
  6045.             if (solved)
  6046.                 bmsptr->bms_solve++;
  6047.             else
  6048.                 bmsptr->bms_unsol++;
  6049.             };
  6050.  
  6051.         /* release EPD structure */
  6052.  
  6053.         EPDReleaseEPD(epdptr);
  6054.         };
  6055.     };
  6056.  
  6057. /* close input file */
  6058.  
  6059. if (fptr != NULL)
  6060.     fclose(fptr);
  6061.  
  6062. return (flag);
  6063. }
  6064.  
  6065. /*--> EPDEnumerate: enumeration of current position */
  6066. static
  6067. liT
  6068. EPDEnumerate(siT depth)
  6069. {
  6070. liT total;
  6071. mptrT mptr;
  6072. siT i;
  6073.  
  6074. /* enumerate current position to the indicated depth */
  6075.  
  6076. if (depth == 0)
  6077.     total = 1;
  6078. else
  6079.     {
  6080.     total = 0;
  6081.     EPDGeneratePL();
  6082.     mptr = tse.tse_base;
  6083.     for (i = 0; i < tse.tse_count; i++)
  6084.         {
  6085.         tse.tse_curr = mptr;
  6086.         EPDExecute(mptr);
  6087.         if (!(mptr->m_flag & mf_bust))
  6088.             total += EPDEnumerate((siT)(depth - 1));
  6089.         EPDRetract(mptr);
  6090.         mptr++;
  6091.         };
  6092.     };
  6093.  
  6094. return (total);
  6095. }
  6096.  
  6097. /*--> EPDEnumerateFile: enumerate input file to output file */
  6098. nonstatic
  6099. siT
  6100. EPDEnumerateFile(siT depth, charptrT fn0, charptrT fn1, liptrT totalptr)
  6101. {
  6102. siT flag;
  6103. fptrT fptr0, fptr1;
  6104. time_t start_time;
  6105. liT acn, acs;
  6106. epdptrT epdptr;
  6107. charptrT eptr;
  6108. char ev[epdL];
  6109.  
  6110. /* set default return value (success) */
  6111.  
  6112. flag = 1;
  6113.  
  6114. /* clear the grand total */
  6115.  
  6116. *totalptr = 0;
  6117.  
  6118. /* clear the input and output file pointers */
  6119.  
  6120. fptr0 = fptr1 = NULL;
  6121.  
  6122. /* open the input file for reading */
  6123.  
  6124. if (flag)
  6125.     {
  6126.     fptr0 = fopen(fn0, "r");
  6127.     if (fptr0 == NULL)
  6128.         flag = 0;
  6129.     };
  6130.  
  6131. /* open the output file for writing */
  6132.  
  6133. if (flag)
  6134.     {
  6135.     fptr1 = fopen(fn1, "w");
  6136.     if (fptr1 == NULL)
  6137.         flag = 0;
  6138.     };
  6139.  
  6140. /* scan entire file */
  6141.  
  6142. while (flag && (fgets(ev, (epdL - 1), fptr0) != NULL))
  6143.     {
  6144.     /* decode a record */
  6145.  
  6146.     epdptr = EPDDecode(ev);
  6147.  
  6148.     /* check record decode validity */
  6149.  
  6150.     if (epdptr == NULL)
  6151.         flag = 0;
  6152.     else
  6153.         {
  6154.         /* set up the current position */
  6155.  
  6156.         EPDRealize(epdptr);
  6157.  
  6158.         /* check legality */
  6159.  
  6160.         if (!EPDIsLegal())
  6161.             flag = 0;
  6162.         else
  6163.             {
  6164.             /* perform enumeration */
  6165.  
  6166.             start_time = time(NULL);
  6167.             acn = EPDEnumerate(depth);
  6168.             acs = time(NULL) - start_time;
  6169.  
  6170.             /* update the grand total */
  6171.  
  6172.             *totalptr += acn;
  6173.  
  6174.             /* record the updated field: acd */
  6175.  
  6176.             EPDAddOpInt(epdptr, epdso_acd, depth);
  6177.  
  6178.             /* record the updated field: acn */
  6179.  
  6180.             EPDAddOpInt(epdptr, epdso_acn, acn);
  6181.  
  6182.             /* record the updated field: acs */
  6183.  
  6184.             EPDAddOpInt(epdptr, epdso_acs, acs);
  6185.  
  6186.             /* encode the record */
  6187.  
  6188.             EPDNormalize(epdptr);
  6189.             eptr = EPDEncode(epdptr);
  6190.  
  6191.             /* check result */
  6192.  
  6193.             if (eptr == NULL)
  6194.                 flag = 0;
  6195.             else
  6196.                 {
  6197.                 fprintf(fptr1, "%s\n", eptr);
  6198.                 EPDMemoryFree(eptr);
  6199.                 };
  6200.             };
  6201.  
  6202.         /* release EPD structure */
  6203.  
  6204.         EPDReleaseEPD(epdptr);
  6205.         };
  6206.     };
  6207.  
  6208. /* close input and output files */
  6209.  
  6210. if (fptr0 != NULL)
  6211.     fclose(fptr0);
  6212.  
  6213. if (fptr1 != NULL)
  6214.     fclose(fptr1);
  6215.  
  6216. return (flag);
  6217. }
  6218.  
  6219. /*--> EPDMoveList: generate a string representation of a move list */
  6220. nonstatic
  6221. charptrT
  6222. EPDMoveList(gamptrT gamptr)
  6223. {
  6224. charptrT s;
  6225. charptrT b;
  6226. siT count;
  6227. gpmptrT gpmptr;
  6228. mT m;
  6229. siT sn;
  6230. cT sc, c;
  6231. siT pi, index, limit, length, n, column;
  6232. sanT san;
  6233. char tv[tL];
  6234.  
  6235. /* calculate upper bound on storage requirement */
  6236.  
  6237. count = EPDGamePlyCount(gamptr);
  6238. limit = (((count + 1) / 2) * 5) + 4 + (count * 8) + 8 + 1;
  6239. b = (charptrT) EPDMemoryGrab(limit);
  6240.  
  6241. /* set the inital played move pointer */
  6242.  
  6243. gpmptr = gamptr->gam_headgpm;
  6244.  
  6245. /* set up starting color and starting move number */
  6246.  
  6247. if (count == 0)
  6248.     sc = c_w;
  6249. else
  6250.     sc = gpmptr->gpm_ese.ese_actc;
  6251.  
  6252. if (count == 0)
  6253.     sn = 1;
  6254. else
  6255.     sn = gpmptr->gpm_ese.ese_fmvn;
  6256.  
  6257. /* more set up */
  6258.  
  6259. pi = 0;
  6260. index = 0;
  6261. c = sc;
  6262. n = sn;
  6263. column = 0;
  6264.  
  6265. /* loop through moves */
  6266.  
  6267. for (pi = 0; pi < count; pi++)
  6268.     {
  6269.     /* handle move number indication */
  6270.  
  6271.     if ((c == c_w) || ((pi == 0) && (sc == c_b)))
  6272.         {
  6273.         sprintf(tv, "%hd.", n);
  6274.         length = strlen(tv);
  6275.  
  6276.         if ((column + 1 + length) >= columnL)
  6277.             {
  6278.             strcpy((b + index), "\n");
  6279.             index++;
  6280.             column = 0;
  6281.             };
  6282.  
  6283.         if (column != 0)
  6284.             {
  6285.             strcpy((b + index), " ");
  6286.             index++;
  6287.             column++;
  6288.             };
  6289.  
  6290.         strcpy((b + index), tv);
  6291.         index += length;
  6292.         column += length;
  6293.  
  6294.         n++;
  6295.         };
  6296.  
  6297.     /* handle ellipsis */
  6298.  
  6299.     if ((pi == 0) && (sc == c_b))
  6300.         {
  6301.         sprintf(tv, "...");
  6302.         length = strlen(tv);
  6303.  
  6304.         if ((column + 1 + length) >= columnL)
  6305.             {
  6306.             strcpy((b + index), "\n");
  6307.             index++;
  6308.             column = 0;
  6309.             };
  6310.  
  6311.         if (column != 0)
  6312.             {
  6313.             strcpy((b + index), " ");
  6314.             index++;
  6315.             column++;
  6316.             };
  6317.  
  6318.         strcpy((b + index), tv);
  6319.         index += length;
  6320.         column += length;
  6321.         };
  6322.  
  6323.     /* handle move */
  6324.  
  6325.     m = gpmptr->gpm_m;
  6326.     EPDSANEncode(&m, san);
  6327.     length = strlen(san);
  6328.  
  6329.     if ((column + 1 + length) >= columnL)
  6330.         {
  6331.         strcpy((b + index), "\n");
  6332.         index++;
  6333.         column = 0;
  6334.         };
  6335.  
  6336.     if (column != 0)
  6337.         {
  6338.         strcpy((b + index), " ");
  6339.         index++;
  6340.         column++;
  6341.         };
  6342.  
  6343.     strcpy((b + index), san);
  6344.     index += length;
  6345.     column += length;
  6346.  
  6347.     gpmptr = gpmptr->gpm_next;
  6348.     c = inv_cv[c];
  6349.     };
  6350.  
  6351. /* append game termination marker */
  6352.  
  6353. sprintf(tv, "%s", gtimstrv[gamptr->gam_gtim]);
  6354. length = strlen(tv);
  6355.  
  6356. if ((column + 1 + length) >= columnL)
  6357.     {
  6358.     strcpy((b + index), "\n");
  6359.     index++;
  6360.     column = 0;
  6361.     };
  6362.  
  6363. if (column != 0)
  6364.     {
  6365.     strcpy((b + index), " ");
  6366.     index++;
  6367.     column++;
  6368.     };
  6369.  
  6370. strcpy((b + index), tv);
  6371. index += length;
  6372. column += length;
  6373.  
  6374. /* closing newline */
  6375.  
  6376. if (column != 0)
  6377.     strcpy((b + index), "\n");
  6378.  
  6379. /* allocate and copy to result */
  6380.  
  6381. s = EPDStringGrab(b);
  6382. EPDMemoryFree(b);
  6383.  
  6384. return (s);
  6385. }
  6386.  
  6387. /*--> EPDPGNFetchTagIndex: return a PGN Seven Tag Roster tag index */
  6388. nonstatic
  6389. pgnstrT
  6390. EPDPGNFetchTagIndex(charptrT s)
  6391. {
  6392. pgnstrT pgnstr;
  6393. pgnstrT rstr;
  6394.  
  6395. pgnstr = pgnstr_nil;
  6396. rstr = 0;
  6397. while ((pgnstr == pgnstr_nil) && (rstr < pgnstrL))
  6398.     if (strcmp(s, EPDPGNFetchTagName(rstr)) == 0)
  6399.         pgnstr = rstr;
  6400.     else
  6401.         rstr++;
  6402.  
  6403. return (pgnstr);
  6404. }
  6405.  
  6406. /*--> EPDPGNFetchTagName: return a PGN Seven Tag Roster tag name */
  6407. nonstatic
  6408. charptrT
  6409. EPDPGNFetchTagName(pgnstrT pgnstr)
  6410. {
  6411.  
  6412. return (pgnstrstrv[pgnstr]);
  6413. }
  6414.  
  6415. /*--> EPDPGNGetSTR: return a string from the Seven Tag Roster */
  6416. nonstatic
  6417. charptrT
  6418. EPDPGNGetSTR(gamptrT gamptr, pgnstrT pgnstr)
  6419. {
  6420.  
  6421. return (gamptr->gam_strv[pgnstr]);
  6422. }
  6423.  
  6424. /*--> EPDPGNPutSTR: enter a string into the Seven Tag Roster */
  6425. nonstatic
  6426. void
  6427. EPDPGNPutSTR(gamptrT gamptr, pgnstrT pgnstr, charptrT s)
  6428. {
  6429. if (gamptr->gam_strv[pgnstr] != NULL)
  6430.     EPDMemoryFree(gamptr->gam_strv[pgnstr]);
  6431.  
  6432. gamptr->gam_strv[pgnstr] = EPDStringGrab(s);
  6433.  
  6434. return;
  6435. }
  6436.  
  6437. /*--> EPDPGNGenSTR: return a string with the entire STR */
  6438. nonstatic
  6439. charptrT
  6440. EPDPGNGenSTR(gamptrT gamptr)
  6441. {
  6442. charptrT s;
  6443. pgnstrT pgnstr;
  6444. char tv[tL];
  6445.  
  6446. s = EPDStringGrab("");
  6447.  
  6448. for (pgnstr = 0; pgnstr < pgnstrL; pgnstr++)
  6449.     {
  6450.     sprintf(tv, "[%s \"%s\"]\n",
  6451.         pgnstrstrv[pgnstr], gamptr->gam_strv[pgnstr]);
  6452.     s = EPDStringAppendStr(s, tv);
  6453.     };
  6454.  
  6455. return (s);
  6456. }
  6457.  
  6458. /*--> EPDPGNHistory: generate a string for PGN version of history */
  6459. nonstatic
  6460. charptrT
  6461. EPDPGNHistory(gamptrT gamptr)
  6462. {
  6463. charptrT s;
  6464. charptrT ms;
  6465.  
  6466. s = EPDPGNGenSTR(gamptr);
  6467. s = EPDStringAppendChar(s, '\n');
  6468. ms = EPDMoveList(gamptr);
  6469. s = EPDStringAppendStr(s, ms);
  6470. EPDMemoryFree(ms);
  6471. s = EPDStringAppendChar(s, '\n');
  6472.  
  6473. return (s);
  6474. }
  6475.  
  6476. /*--> EPDCopyInPTP: copy STR into an EDP structure (ptp operation) */
  6477. nonstatic
  6478. void
  6479. EPDCopyInPTP(gamptrT gamptr, epdptrT epdptr)
  6480. {
  6481. eopptrT eopptr;
  6482. pgnstrT pgnstr;
  6483.  
  6484. if (epdptr != NULL)
  6485.     {
  6486.     EPDDropIfLocEOPCode(epdptr, epdso_ptp);
  6487.     eopptr = EPDCreateEOPCode(epdso_ptp);
  6488.  
  6489.     for (pgnstr = 0; pgnstr < pgnstrL; pgnstr++)
  6490.         {
  6491.         EPDAppendEOV(eopptr,
  6492.             EPDCreateEOVSym(EPDPGNFetchTagName(pgnstr)));
  6493.         EPDAppendEOV(eopptr,
  6494.             EPDCreateEOVStr(EPDPGNGetSTR(gamptr, pgnstr)));
  6495.         };
  6496.  
  6497.     EPDAppendEOP(epdptr, eopptr);
  6498.     };
  6499.  
  6500. return;
  6501. }
  6502.  
  6503. /*--> EPDCopyOutPTP: copy STR from an EDP structure (ptp operation) */
  6504. nonstatic
  6505. void
  6506. EPDCopyOutPTP(gamptrT gamptr, epdptrT epdptr)
  6507. {
  6508. eopptrT eopptr;
  6509. eovptrT eovptr;
  6510. pgnstrT pgnstr;
  6511.  
  6512. if (epdptr != NULL)
  6513.     {
  6514.     eopptr = EPDLocateEOPCode(epdptr, epdso_ptp);
  6515.     eovptr = eopptr->eop_headeov;
  6516.     while ((eovptr != NULL) && (eovptr->eov_next != NULL))
  6517.         {
  6518.         pgnstr = EPDPGNFetchTagIndex(eovptr->eov_str);
  6519.         if (pgnstr != pgnstr_nil)
  6520.             EPDPGNPutSTR(gamptr, pgnstr, eovptr->eov_next->eov_str);
  6521.         eovptr = eovptr->eov_next->eov_next;
  6522.         };
  6523.     };
  6524.  
  6525. return;
  6526. }
  6527.  
  6528. /*--> EPDFetchRefcomStr: return  pointer of indicated refcom string */
  6529. nonstatic
  6530. charptrT
  6531. EPDFetchRefcomStr(refcomT refcom)
  6532. {
  6533.  
  6534. return (refcomstrv[refcom]);
  6535. }
  6536.  
  6537. /*--> EPDFetchRefreqStr: return  pointer of indicated refreq string */
  6538. nonstatic
  6539. charptrT
  6540. EPDFetchRefreqStr(refreqT refreq)
  6541. {
  6542.  
  6543. return (refreqstrv[refreq]);
  6544. }
  6545.  
  6546. /*--> EPDFetchRefcomIndex: return a referee command index */
  6547. nonstatic
  6548. refcomT
  6549. EPDFetchRefcomIndex(charptrT s)
  6550. {
  6551. refcomT refcom;
  6552. refcomT rcom;
  6553.  
  6554. refcom = refcom_nil;
  6555. rcom = 0;
  6556. while ((refcom == refcom_nil) && (rcom < refcomL))
  6557.     if (strcmp(s, EPDFetchRefcomStr(rcom)) == 0)
  6558.         refcom = rcom;
  6559.     else
  6560.         rcom++;
  6561.  
  6562. return (refcom);
  6563. }
  6564.  
  6565. /*--> EPDFetchRefreqIndex: return a referee request index */
  6566. nonstatic
  6567. refreqT
  6568. EPDFetchRefreqIndex(charptrT s)
  6569. {
  6570. refreqT refreq;
  6571. refreqT rreq;
  6572.  
  6573. refreq = refreq_nil;
  6574. rreq = 0;
  6575. while ((refreq == refreq_nil) && (rreq < refreqL))
  6576.     if (strcmp(s, EPDFetchRefreqStr(rreq)) == 0)
  6577.         refreq = rreq;
  6578.     else
  6579.         rreq++;
  6580.  
  6581. return (refreq);
  6582. }
  6583.  
  6584. /*--> EPDExtractRefcomIndex: extract a referee command index */
  6585. nonstatic
  6586. refreqT
  6587. EPDExtractRefcomIndex(epdptrT epdptr)
  6588. {
  6589. refcomT refcom;
  6590. eopptrT eopptr;
  6591. eovptrT eovptr;
  6592.  
  6593. /* set default return value */
  6594.  
  6595. refcom = refreq_nil;
  6596.  
  6597. if (epdptr != NULL)
  6598.     if ((eopptr = EPDLocateEOPCode(epdptr, epdso_refcom)) != NULL)
  6599.         if ((eovptr = eopptr->eop_headeov) != NULL)
  6600.             refcom = EPDFetchRefcomIndex(eovptr->eov_str);
  6601.  
  6602. return (refcom);
  6603. }
  6604.  
  6605. /*--> EPDExtractRefreqIndex: extract a referee request index */
  6606. nonstatic
  6607. refreqT
  6608. EPDExtractRefreqIndex(epdptrT epdptr)
  6609. {
  6610. refreqT refreq;
  6611. eopptrT eopptr;
  6612. eovptrT eovptr;
  6613.  
  6614. /* set default return value */
  6615.  
  6616. refreq = refreq_nil;
  6617.  
  6618. if (epdptr != NULL)
  6619.     if ((eopptr = EPDLocateEOPCode(epdptr, epdso_refreq)) != NULL)
  6620.         if ((eovptr = eopptr->eop_headeov) != NULL)
  6621.             refreq = EPDFetchRefreqIndex(eovptr->eov_str);
  6622.  
  6623. return (refreq);
  6624. }
  6625.  
  6626. /*--> EPDComm: slave to Duplex autoplay program */
  6627. nonstatic
  6628. siT
  6629. EPDComm(refintptrT refintptr, charptrT pipebase)
  6630. {
  6631. siT flag;
  6632. siT done;
  6633. siT flow;
  6634. refcomT refcom;
  6635. charptrT pfnv[flowL];
  6636. fptrT pfptrv[flowL];
  6637. epdptrT epdptr0, epdptr1;
  6638. charptrT eptr;
  6639. char ev[epdL];
  6640.  
  6641. /* set default result: success */
  6642.  
  6643. flag = 1;
  6644.  
  6645. /* set up the EPD Kit for a new game */
  6646.  
  6647. EPDInitArray();
  6648.  
  6649. /* generate pipe file names and clear their pointers */
  6650.  
  6651. for (flow = 0; flow < flowL; flow++)
  6652.     {
  6653.     pfnv[flow] = EPDStringGrab(pipebase);
  6654.     pfnv[flow] = EPDStringAppendStr(pfnv[flow], ".pc");
  6655.     pfnv[flow] = EPDStringAppendChar(pfnv[flow], (char)(flow + '0'));
  6656.     pfptrv[flow] = NULL;
  6657.     };
  6658.  
  6659. /* pipe files already created by Duplex, attempt open */
  6660.  
  6661. flow = 0;
  6662. while (flag && (flow < flowL))
  6663.     {
  6664.     pfptrv[flow] = fopen(pfnv[flow], "a+");
  6665.     if (pfptrv[flow] == NULL)
  6666.         flag = 0;
  6667.     else
  6668.         flow++;
  6669.     };
  6670.  
  6671. /* sign on to Duplex */
  6672.  
  6673. if (flag)
  6674.     {
  6675.     epdptr0 = EPDGetCurrentPosition();
  6676.     EPDAddOpSym(epdptr0, epdso_refreq, refreqstrv[refreq_sign_on]);
  6677.     eptr = EPDEncode(epdptr0);
  6678.     EPDReleaseEPD(epdptr0);
  6679.     fprintf(pfptrv[0], "%s\n", eptr);
  6680.     fflush(pfptrv[0]);
  6681.     EPDMemoryFree(eptr);
  6682.     };
  6683.  
  6684. /* run event cycle loop */
  6685.  
  6686. done = 0;
  6687. while (flag && !done)
  6688.     {
  6689.     /* read an incoming EPD message */
  6690.  
  6691.     if (fgets(ev, (epdL - 1), pfptrv[1]) == NULL)
  6692.         flag = 0;
  6693.     else
  6694.         {
  6695.         /* decode the message */
  6696.  
  6697.         epdptr1 = EPDDecode(ev);
  6698.         if ((epdptr1 == NULL) ||
  6699.             ((refcom = EPDExtractRefcomIndex(epdptr1)) == refcom_nil))
  6700.             flag = 0;
  6701.         else
  6702.             {
  6703.             /* send the message to the callback routine */
  6704.  
  6705.             epdptr0 = (*refintptr)(epdptr1, &flag);
  6706.  
  6707.             /* release input storage */
  6708.  
  6709.             EPDReleaseEPD(epdptr1);
  6710.  
  6711.             /* construct and transmit output string */
  6712.  
  6713.             if (flag && (epdptr0 != NULL))
  6714.                 {
  6715.                 eptr = EPDEncode(epdptr0);
  6716.                 fprintf(pfptrv[0], "%s\n", eptr);
  6717.                 fflush(pfptrv[0]);
  6718.                 EPDMemoryFree(eptr);
  6719.                 };
  6720.  
  6721.             /* release output storage */
  6722.  
  6723.             if (epdptr0 != NULL)
  6724.                 EPDReleaseEPD(epdptr0);
  6725.  
  6726.             /* set the completion flag on disconnect */
  6727.  
  6728.             if (flag && !done && (refcom == refcom_disconnect))
  6729.                 done = 1;
  6730.             };
  6731.         };
  6732.     };
  6733.  
  6734. /* close pipes and release pipe file names */
  6735.  
  6736. for (flow = 0; flow < flowL; flow++)
  6737.     {
  6738.     if (pfptrv[flow] != NULL)
  6739.         fclose(pfptrv[flow]);
  6740.     EPDMemoryFree(pfnv[flow]);
  6741.     };
  6742.  
  6743. return (flag);
  6744. }
  6745.  
  6746. /*--> EPDTBClassFileName: return an allocated class name */
  6747. static
  6748. charptrT
  6749. EPDTBClassFileName(charptrT dirstr, tbidT tbid, cT c)
  6750. {
  6751. charptrT name;
  6752.  
  6753. #if (!defined(__MWERKS__))
  6754. if (dirstr == NULL)
  6755.     name = EPDStringGrab("");
  6756. else
  6757.     {
  6758.     name = EPDStringGrab(dirstr);
  6759.     name = EPDStringAppendChar(name, '/');
  6760.     };
  6761. #else
  6762. if (dirstr == NULL)
  6763.     name = EPDStringGrab("");
  6764. else
  6765.     {
  6766.     name = EPDStringGrab(":");
  6767.     name = EPDStringAppendStr(name, dirstr);
  6768.     name = EPDStringAppendChar(name, ':');
  6769.     };
  6770. #endif
  6771.  
  6772. name = EPDStringAppendStr(name, (tbbaseptr + tbid)->tb_name);
  6773. name = EPDStringAppendStr(name, ctmext_strv[c]);
  6774.  
  6775. return (name);
  6776. }
  6777.  
  6778. /*--> EPDTBGetSignature: get the signature for a distribution */
  6779. static
  6780. liT
  6781. EPDTBGetSignature(distvT distv)
  6782. {
  6783. liT sig;
  6784. cT c;
  6785. pT p;
  6786.  
  6787. sig = 0;
  6788. for (c = c_w; c <= c_b; c++)
  6789.     for (p = p_p; p <= p_q; p++)
  6790.         sig = (sig << 3) | distv[c][p];
  6791.  
  6792. return (sig);
  6793. }
  6794.  
  6795. /*--> EPDTBGetInvertedSignature: get the inverted signature for a distribution */
  6796. static
  6797. liT
  6798. EPDTBGetInvertedSignature(distvT distv)
  6799. {
  6800. liT sig;
  6801. cT c;
  6802. pT p;
  6803.  
  6804. sig = 0;
  6805. for (c = c_w; c <= c_b; c++)
  6806.     for (p = p_p; p <= p_q; p++)
  6807.         sig = (sig << 3) | distv[inv_cv[c]][p];
  6808.  
  6809. return (sig);
  6810. }
  6811.  
  6812. /*--> EPDTBLocateClass: locate a class for a piece distribution */
  6813. static
  6814. tbidT
  6815. EPDTBLocateClass(distvT distv, siptrT invertptr)
  6816. {
  6817. tbidT tbid;
  6818. siT flag;
  6819. tbptrT classptr;
  6820. liT sig;
  6821.  
  6822. /* set "not found" */
  6823.  
  6824. flag = 0;
  6825.  
  6826. /* get the piece distribution signature */
  6827.  
  6828. sig = EPDTBGetSignature(distv);
  6829.  
  6830. /* search for signature match */
  6831.  
  6832. classptr = tbbaseptr;
  6833. tbid = 0;
  6834. while (!flag && (tbid < tbidL))
  6835.     if (sig == classptr->tb_sig0)
  6836.         {
  6837.         flag = 1;
  6838.         *invertptr = 0;
  6839.         }
  6840.     else
  6841.         if (sig == classptr->tb_sig1)
  6842.             {
  6843.             flag = 1;
  6844.             *invertptr = 1;
  6845.             }
  6846.         else
  6847.             {
  6848.             classptr++;
  6849.             tbid++;
  6850.             };
  6851.  
  6852. /* if not found, set return to nil */
  6853.  
  6854. if (!flag)
  6855.     tbid = tbid_nil;
  6856.  
  6857. return (tbid);
  6858. }
  6859.  
  6860. /*--> EPDTBCopyPosition: copy a position vector */
  6861. static
  6862. void
  6863. EPDTBCopyPosition(posvT posv0, posvT posv1)
  6864. {
  6865. cT c;
  6866. siT i;
  6867.  
  6868. for (c = c_w; c <= c_b; c++)
  6869.     for (i = 0; i < tbmecL; i++)
  6870.         posv1[c][i] = posv0[c][i];
  6871.  
  6872. return;
  6873. }
  6874.  
  6875. /*--> EPDTBReflectX: reflect a position along the X axis */
  6876. static
  6877. void
  6878. EPDTBReflectX(tbptrT classptr, posvT posv)
  6879. {
  6880. cT c;
  6881. siT i;
  6882.  
  6883. for (c = c_w; c <= c_b; c++)
  6884.     for (i = 0; i < classptr->tb_mcv[c]; i++)
  6885.         posv[c][i] ^= 0x38;
  6886.  
  6887. return;
  6888. }
  6889.  
  6890. /*--> EPDTBReflectY: reflect a position along the Y axis */
  6891. static
  6892. void
  6893. EPDTBReflectY(tbptrT classptr, posvT posv)
  6894. {
  6895. cT c;
  6896. siT i;
  6897.  
  6898. for (c = c_w; c <= c_b; c++)
  6899.     for (i = 0; i < classptr->tb_mcv[c]; i++)
  6900.         posv[c][i] ^= 0x07;
  6901.  
  6902. return;
  6903. }
  6904.  
  6905. /*--> EPDTBReflectXY: reflect a position along the X=Y axis */
  6906. static
  6907. void
  6908. EPDTBReflectXY(tbptrT classptr, posvT posv)
  6909. {
  6910. cT c;
  6911. siT i;
  6912. rankT rank;
  6913. fileT file;
  6914.  
  6915. for (c = c_w; c <= c_b; c++)
  6916.     for (i = 0; i < classptr->tb_mcv[c]; i++)
  6917.         {
  6918.         rank = map_rank(posv[c][i]);
  6919.         file = map_file(posv[c][i]);
  6920.         posv[c][i] = map_sq(file, rank);
  6921.         };
  6922.  
  6923. return;
  6924. }
  6925.  
  6926. /*--> EPDTBNormalize: normalize a position */
  6927. static
  6928. void
  6929. EPDTBNormalize(tbptrT classptr, posvT posv)
  6930. {
  6931. sqT sq;
  6932. cT pivot_c;
  6933. siT pivot_slot;
  6934.  
  6935. /* get pivot color and slot */
  6936.  
  6937. pivot_c = classptr->tb_pivot_c;
  6938. pivot_slot = classptr->tb_pivot_slot;
  6939.  
  6940. /* determine normalization mode */
  6941.  
  6942. if (classptr->tb_fold == fold_flank)
  6943.     {
  6944.     /* class has at least one pawn */
  6945.  
  6946.     sq = posv[pivot_c][pivot_slot];
  6947.     if (map_file(sq) > file_d)
  6948.         EPDTBReflectY(classptr, posv);
  6949.     }
  6950. else
  6951.     {
  6952.     /* class has no pawns */
  6953.  
  6954.     sq = posv[pivot_c][pivot_slot];
  6955.     if (map_rank(sq) > rank_4)
  6956.         EPDTBReflectX(classptr, posv);
  6957.  
  6958.     sq = posv[pivot_c][pivot_slot];
  6959.     if (map_file(sq) > file_d)
  6960.         EPDTBReflectY(classptr, posv);
  6961.  
  6962.     sq = posv[pivot_c][pivot_slot];
  6963.     if (map_rank(sq) > map_file(sq))
  6964.         EPDTBReflectXY(classptr, posv);
  6965.     };
  6966.  
  6967. return;
  6968. }
  6969.  
  6970. /*--> EPDTBGenIndex: generate a file index for a class and position */
  6971. static
  6972. indexT
  6973. EPDTBGenIndex(tbptrT classptr, posvT posv)
  6974. {
  6975. indexT index;
  6976. liT factor=0;
  6977. posvT nposv;
  6978. cT c;
  6979. siT i;
  6980.  
  6981. EPDTBCopyPosition(posv, nposv);
  6982. EPDTBNormalize(classptr, nposv);
  6983.  
  6984. index = 0;
  6985. for (c = c_w; c <= c_b; c++)
  6986.     for (i = 0; i < classptr->tb_mcv[c]; i++)
  6987.         {
  6988.         switch (classptr->tb_scalev[c][i])
  6989.             {
  6990.             case sqL:
  6991.                 factor = nposv[c][i];
  6992.                 break;
  6993.             case ff_flankL:
  6994.                 factor = flank_mapv[nposv[c][i]];
  6995.                 break;
  6996.             case ff_triangleL:
  6997.                 factor = triangle_mapv[nposv[c][i]];
  6998.                 break;
  6999.             default:
  7000.                 EPDSwitchFault("EPDTBGenIndex");
  7001.                 break;
  7002.             };
  7003.         index += factor * classptr->tb_multv[c][i];
  7004.         };
  7005.  
  7006. return (index);
  7007. }
  7008.  
  7009. /*--> EPDTBGenInvertIndex: generate a file index for a class and position (inverted) */
  7010. static
  7011. indexT
  7012. EPDTBGenInvertIndex(tbptrT classptr, posvT posv)
  7013. {
  7014. indexT index;
  7015. liT factor=0;
  7016. posvT nposv;
  7017. cT c, invc;
  7018. siT i;
  7019.  
  7020. for (c = c_w; c <= c_b; c++)
  7021.     {
  7022.     invc = inv_cv[c];
  7023.     for (i = 0; i < classptr->tb_mcv[invc]; i++)
  7024.         nposv[invc][i] = posv[c][i];
  7025.     };
  7026.  
  7027. if (classptr->tb_flags & tbf_has_pawns)
  7028.     EPDTBReflectX(classptr, nposv);
  7029.  
  7030. EPDTBNormalize(classptr, nposv);
  7031.  
  7032. index = 0;
  7033. for (c = c_w; c <= c_b; c++)
  7034.     {
  7035.     for (i = 0; i < classptr->tb_mcv[c]; i++)
  7036.         {
  7037.         switch (classptr->tb_scalev[c][i])
  7038.             {
  7039.             case sqL:
  7040.                 factor = nposv[c][i];
  7041.                 break;
  7042.             case ff_flankL:
  7043.                 factor = flank_mapv[nposv[c][i]];
  7044.                 break;
  7045.             case ff_triangleL:
  7046.                 factor = triangle_mapv[nposv[c][i]];
  7047.                 break;
  7048.             default:
  7049.                 EPDSwitchFault("EPDTBGenInvertIndex");
  7050.                 break;
  7051.             };
  7052.         index += factor * classptr->tb_multv[c][i];
  7053.         };
  7054.     };
  7055.  
  7056. return (index);
  7057. }
  7058.  
  7059. /*--> EPDTBMapFromBEV: convert to centipawns from byte evaluation */
  7060. static
  7061. cpevT
  7062. EPDTBMapFromBEV(bevT bev)
  7063. {
  7064. cpevT cpev;
  7065. siT distance;
  7066.  
  7067. switch (bev)
  7068.     {
  7069.     case bev_broken:
  7070.     case bev_reserved:
  7071.     case bev_unknown:
  7072.         cpev = cpev_wrck;
  7073.         break;
  7074.  
  7075.     case bev_draw:
  7076.         cpev = cpev_draw;
  7077.         break;
  7078.  
  7079.     default:
  7080.         if (tbe_mating(bev))
  7081.             {
  7082.             distance = ((bev_mi1 - bev) * 2) + 1;
  7083.             cpev = cpev_best - distance;
  7084.             }
  7085.         else
  7086.             {
  7087.             distance = -((bev_li0 - bev) * 2);
  7088.             cpev = cpev_bust + distance;
  7089.             };
  7090.         break;
  7091.     };
  7092.  
  7093. return (cpev);
  7094. }
  7095.  
  7096. /*--> EPDTBProbeFile: return a centipawn value from a probe */
  7097. static
  7098. cpevT
  7099. EPDTBProbeFile(tbidT tbid, cT c, liT index)
  7100. {
  7101. cpevT cpev;
  7102. siT i, slot;
  7103. bevT bev;
  7104. tbcT tbc;
  7105. charptrT fnptr;
  7106.  
  7107. /* set default return value: no evaluation found */
  7108.  
  7109. cpev = cpev_wrck;
  7110.  
  7111. /* search cache for a slot with currently open file */
  7112.  
  7113. slot = -1;
  7114. i = 0;
  7115. while ((slot == -1) && (i < tbcL))
  7116.     if (tbcv[i].tbc_inuse &&
  7117.         (tbcv[i].tbc_tbid == tbid) && (tbcv[i].tbc_c == c))
  7118.         slot = i;
  7119.     else
  7120.         i++;
  7121.  
  7122. /* if no slot was found, try to find an empty one */
  7123.  
  7124. if (slot == -1)
  7125.     {
  7126.     /* look for a free slot */
  7127.  
  7128.     i = 0;
  7129.     while ((slot == -1) && (i < tbcL))
  7130.         if (!tbcv[i].tbc_inuse)
  7131.             slot = i;
  7132.         else
  7133.             i++;
  7134.  
  7135.     /* if no empty slot, drop the bottom (LRU) entry */
  7136.  
  7137.     if (slot == -1)
  7138.         {
  7139.         slot = tbcL - 1;
  7140.         if (tbcv[slot].tbc_fptr != NULL)
  7141.             fclose(tbcv[slot].tbc_fptr);
  7142.         };
  7143.  
  7144.     /* initialize the slot */
  7145.  
  7146.     tbcv[slot].tbc_inuse = 1;
  7147.     tbcv[slot].tbc_tbid = tbid;
  7148.     tbcv[slot].tbc_c = c;
  7149.     fnptr = EPDTBClassFileName(tb_path, tbid, c);
  7150.     tbcv[slot].tbc_fptr = fopen(fnptr, "rb");
  7151.     EPDStringFree(fnptr);
  7152.     };
  7153.  
  7154. /* move slot entry to top */
  7155.  
  7156. if (slot != 0)
  7157.     {
  7158.     tbc = tbcv[slot];
  7159.     for (i = slot; i > 0; i--)
  7160.         tbcv[i] = tbcv[i - 1];
  7161.     slot = 0;
  7162.     tbcv[slot] = tbc;
  7163.     };
  7164.  
  7165. /* file probe */
  7166.  
  7167. if (tbcv[slot].tbc_fptr != NULL)
  7168.     if (fseek(tbcv[slot].tbc_fptr, index, SEEK_SET) == 0)
  7169.         if (fread(&bev, sizeof(bevT), 1, tbcv[slot].tbc_fptr) ==
  7170.             sizeof(bevT))
  7171.             cpev = EPDTBMapFromBEV(bev);
  7172.  
  7173. return (cpev);
  7174. }
  7175.  
  7176. /*--> EPDTBIsFilePresent: test if the given TB file is readable */
  7177. nonstatic
  7178. siT
  7179. EPDTBIsFilePresent(tbidT tbid, cT c)
  7180. {
  7181. siT flag;
  7182. fptrT fptr;
  7183. charptrT fnptr;
  7184.  
  7185. fnptr = EPDTBClassFileName(tb_path, tbid, c);
  7186. fptr = fopen(fnptr, "rb");
  7187. EPDStringFree(fnptr);
  7188. if (fptr == NULL)
  7189.     flag = 0;
  7190. else
  7191.     {
  7192.     fclose(fptr);
  7193.     flag = 1;
  7194.     };
  7195.  
  7196. return (flag);
  7197. }
  7198.  
  7199. /*--> EPDTBScore: return tablebase certain score (if possible) */
  7200. nonstatic
  7201. cpevT
  7202. EPDTBScore(void)
  7203. {
  7204. cpevT cpev;
  7205. tbidT tbid;
  7206. siT invert;
  7207. cT probe_c;
  7208. liT index;
  7209. distvT distv;
  7210. cT c;
  7211. pT p;
  7212. sqT sq;
  7213. cpT cp;
  7214. cT invc;
  7215. siT flag;
  7216. siT i;
  7217. tbptrT classptr;
  7218. posvT posv, nposv;
  7219. rbT rb;
  7220.  
  7221. /* set default return value: score unfound */
  7222.  
  7223. cpev = cpev_wrck;
  7224.  
  7225. /* clear the distribution */
  7226.  
  7227. for (c = c_w; c <= c_b; c++)
  7228.     for (p = p_p; p <= p_k; p++)
  7229.         distv[c][p] = 0;
  7230.  
  7231. /* calculate the distribution */
  7232.  
  7233. for (sq = sq_a1; sq <= sq_h8; sq++)
  7234.     if ((cp = EPDboard.rbv[sq]) != cp_v0)
  7235.         distv[cv_c_cpv[cp]][cv_p_cpv[cp]]++;
  7236.  
  7237. /* locate the class */
  7238.  
  7239. tbid = EPDTBLocateClass(distv, &invert);
  7240.  
  7241. /* was a class identified? */
  7242.  
  7243. if (tbid != tbid_nil)
  7244.     {
  7245.     /* get the class pointer */
  7246.     
  7247.     classptr = tbbaseptr + tbid;
  7248.     
  7249.     /* calculate probe color */
  7250.  
  7251.     if (!invert)
  7252.         probe_c = ese.ese_actc;
  7253.     else
  7254.         probe_c = inv_cv[ese.ese_actc];
  7255.  
  7256.     /* set up the position vector */
  7257.     
  7258.     for (sq = sq_a1; sq <= sq_h8; sq++)
  7259.         {
  7260.         cp = EPDboard.rbv[sq];
  7261.         if ((cp != cp_v0) && invert)
  7262.             cp = cv_cp_c_pv[inv_cv[cv_c_cpv[cp]]][cv_p_cpv[cp]];
  7263.         rb.rbv[sq] = cp;
  7264.         };
  7265.  
  7266.     for (c = c_w; c <= c_b; c++)
  7267.         for (i = 0; i < classptr->tb_mcv[c]; i++)
  7268.             {
  7269.             /* which color-piece to match? */
  7270.             
  7271.             cp = classptr->tb_cpv[c][i];
  7272.             
  7273.             /* find it */
  7274.             
  7275.             flag = 0;
  7276.             sq = sq_a1;
  7277.             while (!flag)
  7278.                 if (rb.rbv[sq] == cp)
  7279.                     {
  7280.                     posv[c][i] = sq;
  7281.                     rb.rbv[sq] = cp_v0;
  7282.                     flag = 1;
  7283.                     }
  7284.                 else
  7285.                     sq++;
  7286.             };
  7287.  
  7288.     /* calculate index */
  7289.  
  7290.     if (!invert)
  7291.         index = EPDTBGenIndex(classptr, posv);
  7292.     else
  7293.         {
  7294.         for (c = c_w; c <= c_b; c++)
  7295.             {
  7296.             invc = inv_cv[c];
  7297.             for (i = 0; i < classptr->tb_mcv[c]; i++)
  7298.                 nposv[invc][i] = posv[c][i];
  7299.             };
  7300.  
  7301.         index = EPDTBGenInvertIndex(classptr, nposv);
  7302.         };
  7303.  
  7304.     /* probe */
  7305.  
  7306.     cpev = EPDTBProbeFile(tbid, probe_c, index);
  7307.     };
  7308.  
  7309. return (cpev);
  7310. }
  7311.  
  7312. /*--> EPDTBInitTBID: initialize an entry in the tablebase vector */
  7313. static
  7314. void
  7315. EPDTBInitTBID(tbidT tbid, charptrT name)
  7316. {
  7317. cT c;
  7318. pT p;
  7319. siT i, slot;
  7320. liT mult;
  7321. char ch;
  7322. tbptrT classptr;
  7323.  
  7324. classptr = tbbaseptr + tbid;
  7325.  
  7326. /* clear flags and set name items */
  7327.  
  7328. classptr->tb_flags = 0;
  7329. classptr->tb_name = EPDStringGrab(name);
  7330. classptr->tb_count = strlen(name);
  7331.  
  7332. /* clear various vectors */
  7333.  
  7334. for (c = c_w; c <= c_b; c++)
  7335.     {
  7336.     classptr->tb_mcv[c] = 0;
  7337.     for (p = p_p; p <= p_k; p++)
  7338.         classptr->tb_distv[c][p] = 0;
  7339.     };
  7340.  
  7341. /* scan through pieces in class names */
  7342.  
  7343. c = c_b;
  7344. for (i = 0; i < classptr->tb_count; i++)
  7345.     {
  7346.     /* identify current piece */
  7347.  
  7348.     ch = *(name + i);
  7349.     switch (ch)
  7350.         {
  7351.         case 'P':
  7352.             p = p_p;
  7353.             break;
  7354.         case 'N':
  7355.             p = p_n;
  7356.             break;
  7357.         case 'B':
  7358.             p = p_b;
  7359.             break;
  7360.         case 'R':
  7361.             p = p_r;
  7362.             break;
  7363.         case 'Q':
  7364.             p = p_q;
  7365.             break;
  7366.         case 'K':
  7367.             p = p_k;
  7368.             break;
  7369.         default:
  7370.             EPDSwitchFault("EPDTBInitTBID");
  7371.             break;
  7372.         };
  7373.  
  7374.     /* swap color if current piece is a king */
  7375.  
  7376.     if (p == p_k)
  7377.         c = inv_cv[c];
  7378.  
  7379.     /* set various flags if current piece is a pawn */
  7380.  
  7381.     if (p == p_p)
  7382.         {
  7383.         classptr->tb_flags |= tbf_has_pawns;
  7384.         if (c == c_w)
  7385.             {
  7386.             classptr->tb_flags |= tbf_has_white_pawn;
  7387.             if (classptr->tb_flags & tbf_has_black_pawn)
  7388.                 classptr->tb_flags |= tbf_ep_captures;
  7389.             }
  7390.         else
  7391.             {
  7392.             classptr->tb_flags |= tbf_has_black_pawn;
  7393.             if (classptr->tb_flags & tbf_has_white_pawn)
  7394.                 classptr->tb_flags |= tbf_ep_captures;
  7395.             };
  7396.         };
  7397.  
  7398.     /* adjust count and distribution for this color */
  7399.  
  7400.     classptr->tb_mcv[c]++;
  7401.     classptr->tb_distv[c][p]++;
  7402.  
  7403.     /* set piece and color-piece vector for this color */
  7404.  
  7405.     if (c == c_w)
  7406.         slot = i;
  7407.     else
  7408.         slot = i - classptr->tb_mcv[c_w];
  7409.     classptr->tb_pv[c][slot] = p;
  7410.     classptr->tb_cpv[c][slot] = cv_cp_c_pv[c][p];
  7411.     };
  7412.  
  7413. /* set the distribution signatures */
  7414.  
  7415. classptr->tb_sig0 = EPDTBGetSignature(classptr->tb_distv);
  7416. classptr->tb_sig1 = EPDTBGetInvertedSignature(classptr->tb_distv);
  7417.  
  7418. /* set fold mode information */
  7419.  
  7420. if (classptr->tb_flags & tbf_has_pawns)
  7421.     {
  7422.     classptr->tb_flags |= tbf_fold_flank;
  7423.     classptr->tb_fold = fold_flank;
  7424.     }
  7425. else
  7426.     {
  7427.     classptr->tb_flags |= tbf_fold_triangle;
  7428.     classptr->tb_fold = fold_triangle;
  7429.     };
  7430.  
  7431. /* calculate file length */
  7432.  
  7433. classptr->tb_length = 1;
  7434. for (i = 1; i < classptr->tb_count; i++)
  7435.     classptr->tb_length *= sqL;
  7436. if (classptr->tb_fold == fold_flank)
  7437.     classptr->tb_length *= ff_flankL;
  7438. else
  7439.     classptr->tb_length *= ff_triangleL;
  7440.  
  7441. /* calculate pivot color and slot */
  7442.  
  7443. if (classptr->tb_fold == fold_triangle)
  7444.     {
  7445.     classptr->tb_pivot_c = c_b;
  7446.     classptr->tb_pivot_slot = classptr->tb_mcv[c_b] - 1;
  7447.     }
  7448. else
  7449.     {
  7450.     if (classptr->tb_flags & tbf_has_black_pawn)
  7451.         {
  7452.         classptr->tb_pivot_c = c_b;
  7453.         i = classptr->tb_count - 1;
  7454.         while (*(name + i) != ascpv[p_p])
  7455.             i--;
  7456.         classptr->tb_pivot_slot = i - classptr->tb_mcv[c_w];
  7457.         }
  7458.     else
  7459.         {
  7460.         classptr->tb_pivot_c = c_w;
  7461.         i = classptr->tb_mcv[c_w] - 1;
  7462.         while (*(name + i) != ascpv[p_p])
  7463.             i--;
  7464.         classptr->tb_pivot_slot = i;
  7465.         };
  7466.     };
  7467.  
  7468. /* calculate scale factors */
  7469.  
  7470. for (c = c_w; c <= c_b; c++)
  7471.     for (i = 0; i < classptr->tb_mcv[c]; i++)
  7472.         if ((c != classptr->tb_pivot_c) || (i != classptr->tb_pivot_slot))
  7473.             classptr->tb_scalev[c][i] = sqL;
  7474.         else
  7475.             if (classptr->tb_fold == fold_triangle)
  7476.                 classptr->tb_scalev[c][i] = ff_triangleL;
  7477.             else
  7478.                 classptr->tb_scalev[c][i] = ff_flankL;
  7479.  
  7480. /* calculate multipliers */
  7481.  
  7482. mult = 1;
  7483. for (c = c_w; c <= c_b; c++)
  7484.     for (i = 0; i < classptr->tb_mcv[c]; i++)
  7485.         {
  7486.         classptr->tb_multv[c][i] = mult;
  7487.         mult *= classptr->tb_scalev[c][i];
  7488.         };
  7489.  
  7490. return;
  7491. }
  7492.  
  7493. /*--> EPDTBCacheFlush: flush the tablebase file pointer cache */
  7494. nonstatic
  7495. void
  7496. EPDTBCacheFlush(void)
  7497. {
  7498. siT i;
  7499.  
  7500. for (i = 0; i < tbcL; i++)
  7501.     if (tbcv[i].tbc_inuse)
  7502.         {
  7503.         if (tbcv[i].tbc_fptr != NULL)
  7504.             fclose(tbcv[i].tbc_fptr);
  7505.         tbcv[i].tbc_inuse = 0;
  7506.         };
  7507.  
  7508. return;
  7509. }
  7510.  
  7511. /*--> EPDTBInit: one time initialization for the tablebase subsystem */
  7512. static
  7513. void
  7514. EPDTBInit(void)
  7515. {
  7516. siT i;
  7517. sqT sq;
  7518.  
  7519. /* initialize the flank map */
  7520.  
  7521. for (sq = sq_a1; sq <= sq_h8; sq++)
  7522.     flank_mapv[sq] = -1;
  7523.  
  7524. flank_mapv[sq_a1] =  0;
  7525. flank_mapv[sq_b1] =  1;
  7526. flank_mapv[sq_c1] =  2;
  7527. flank_mapv[sq_d1] =  3;
  7528. flank_mapv[sq_a2] =  4;
  7529. flank_mapv[sq_b2] =  5;
  7530. flank_mapv[sq_c2] =  6;
  7531. flank_mapv[sq_d2] =  7;
  7532. flank_mapv[sq_a3] =  8;
  7533. flank_mapv[sq_b3] =  9;
  7534. flank_mapv[sq_c3] = 10;
  7535. flank_mapv[sq_d3] = 11;
  7536. flank_mapv[sq_a4] = 12;
  7537. flank_mapv[sq_b4] = 13;
  7538. flank_mapv[sq_c4] = 14;
  7539. flank_mapv[sq_d4] = 15;
  7540. flank_mapv[sq_a5] = 16;
  7541. flank_mapv[sq_b5] = 17;
  7542. flank_mapv[sq_c5] = 18;
  7543. flank_mapv[sq_d5] = 19;
  7544. flank_mapv[sq_a6] = 20;
  7545. flank_mapv[sq_b6] = 21;
  7546. flank_mapv[sq_c6] = 22;
  7547. flank_mapv[sq_d6] = 23;
  7548. flank_mapv[sq_a7] = 24;
  7549. flank_mapv[sq_b7] = 25;
  7550. flank_mapv[sq_c7] = 26;
  7551. flank_mapv[sq_d7] = 27;
  7552. flank_mapv[sq_a8] = 28;
  7553. flank_mapv[sq_b8] = 29;
  7554. flank_mapv[sq_c8] = 30;
  7555. flank_mapv[sq_d8] = 31;
  7556.  
  7557. /* initialize the triangle map */
  7558.  
  7559. for (sq = sq_a1; sq <= sq_h8; sq++)
  7560.     triangle_mapv[sq] = -1;
  7561.  
  7562. triangle_mapv[sq_a1] = 0;
  7563. triangle_mapv[sq_b1] = 1;
  7564. triangle_mapv[sq_c1] = 2;
  7565. triangle_mapv[sq_d1] = 3;
  7566. triangle_mapv[sq_b2] = 4;
  7567. triangle_mapv[sq_c2] = 5;
  7568. triangle_mapv[sq_d2] = 6;
  7569. triangle_mapv[sq_c3] = 7;
  7570. triangle_mapv[sq_d3] = 8;
  7571. triangle_mapv[sq_d4] = 9;
  7572.  
  7573. /* set the color to move tablebase file name suffixes */
  7574.  
  7575. ctmext_strv[c_w] = ".tbw";
  7576. ctmext_strv[c_b] = ".tbb";
  7577.  
  7578. /* allocate tablebase information vector */
  7579.  
  7580. tbbaseptr = (tbptrT) EPDMemoryGrab(sizeof(tbT) * tbidL);
  7581.  
  7582. /* initialize the tablebase vector */
  7583.  
  7584. EPDTBInitTBID(tbid_kk,    "KK");
  7585. EPDTBInitTBID(tbid_kpk,   "KPK");
  7586. EPDTBInitTBID(tbid_knk,   "KNK");
  7587. EPDTBInitTBID(tbid_kbk,   "KBK");
  7588. EPDTBInitTBID(tbid_krk,   "KRK");
  7589. EPDTBInitTBID(tbid_kqk,   "KQK");
  7590. EPDTBInitTBID(tbid_kpkp,  "KPKP");
  7591. EPDTBInitTBID(tbid_knkp,  "KNKP");
  7592. EPDTBInitTBID(tbid_knkn,  "KNKN");
  7593. EPDTBInitTBID(tbid_kbkp,  "KBKP");
  7594. EPDTBInitTBID(tbid_kbkn,  "KBKN");
  7595. EPDTBInitTBID(tbid_kbkb,  "KBKB");
  7596. EPDTBInitTBID(tbid_krkp,  "KRKP");
  7597. EPDTBInitTBID(tbid_krkn,  "KRKN");
  7598. EPDTBInitTBID(tbid_krkb,  "KRKB");
  7599. EPDTBInitTBID(tbid_krkr,  "KRKR");
  7600. EPDTBInitTBID(tbid_kqkp,  "KQKP");
  7601. EPDTBInitTBID(tbid_kqkn,  "KQKN");
  7602. EPDTBInitTBID(tbid_kqkb,  "KQKB");
  7603. EPDTBInitTBID(tbid_kqkr,  "KQKR");
  7604. EPDTBInitTBID(tbid_kqkq,  "KQKQ");
  7605. EPDTBInitTBID(tbid_kppk,  "KPPK");
  7606. EPDTBInitTBID(tbid_knpk,  "KNPK");
  7607. EPDTBInitTBID(tbid_knnk,  "KNNK");
  7608. EPDTBInitTBID(tbid_kbpk,  "KBPK");
  7609. EPDTBInitTBID(tbid_kbnk,  "KBNK");
  7610. EPDTBInitTBID(tbid_kbbk,  "KBBK");
  7611. EPDTBInitTBID(tbid_krpk,  "KRPK");
  7612. EPDTBInitTBID(tbid_krnk,  "KRNK");
  7613. EPDTBInitTBID(tbid_krbk,  "KRBK");
  7614. EPDTBInitTBID(tbid_krrk,  "KRRK");
  7615. EPDTBInitTBID(tbid_kqpk,  "KQPK");
  7616. EPDTBInitTBID(tbid_kqnk,  "KQNK");
  7617. EPDTBInitTBID(tbid_kqbk,  "KQBK");
  7618. EPDTBInitTBID(tbid_kqrk,  "KQRK");
  7619. EPDTBInitTBID(tbid_kqqk,  "KQQK");
  7620. EPDTBInitTBID(tbid_kppkp, "KPPKP");
  7621. EPDTBInitTBID(tbid_kppkn, "KPPKN");
  7622. EPDTBInitTBID(tbid_kppkb, "KPPKB");
  7623. EPDTBInitTBID(tbid_kppkr, "KPPKR");
  7624. EPDTBInitTBID(tbid_kppkq, "KPPKQ");
  7625. EPDTBInitTBID(tbid_knpkp, "KNPKP");
  7626. EPDTBInitTBID(tbid_knpkn, "KNPKN");
  7627. EPDTBInitTBID(tbid_knpkb, "KNPKB");
  7628. EPDTBInitTBID(tbid_knpkr, "KNPKR");
  7629. EPDTBInitTBID(tbid_knpkq, "KNPKQ");
  7630. EPDTBInitTBID(tbid_knnkp, "KNNKP");
  7631. EPDTBInitTBID(tbid_knnkn, "KNNKN");
  7632. EPDTBInitTBID(tbid_knnkb, "KNNKB");
  7633. EPDTBInitTBID(tbid_knnkr, "KNNKR");
  7634. EPDTBInitTBID(tbid_knnkq, "KNNKQ");
  7635. EPDTBInitTBID(tbid_kbpkp, "KBPKP");
  7636. EPDTBInitTBID(tbid_kbpkn, "KBPKN");
  7637. EPDTBInitTBID(tbid_kbpkb, "KBPKB");
  7638. EPDTBInitTBID(tbid_kbpkr, "KBPKR");
  7639. EPDTBInitTBID(tbid_kbpkq, "KBPKQ");
  7640. EPDTBInitTBID(tbid_kbnkp, "KBNKP");
  7641. EPDTBInitTBID(tbid_kbnkn, "KBNKN");
  7642. EPDTBInitTBID(tbid_kbnkb, "KBNKB");
  7643. EPDTBInitTBID(tbid_kbnkr, "KBNKR");
  7644. EPDTBInitTBID(tbid_kbnkq, "KBNKQ");
  7645. EPDTBInitTBID(tbid_kbbkp, "KBBKP");
  7646. EPDTBInitTBID(tbid_kbbkn, "KBBKN");
  7647. EPDTBInitTBID(tbid_kbbkb, "KBBKB");
  7648. EPDTBInitTBID(tbid_kbbkr, "KBBKR");
  7649. EPDTBInitTBID(tbid_kbbkq, "KBBKQ");
  7650. EPDTBInitTBID(tbid_krpkp, "KRPKP");
  7651. EPDTBInitTBID(tbid_krpkn, "KRPKN");
  7652. EPDTBInitTBID(tbid_krpkb, "KRPKB");
  7653. EPDTBInitTBID(tbid_krpkr, "KRPKR");
  7654. EPDTBInitTBID(tbid_krpkq, "KRPKQ");
  7655. EPDTBInitTBID(tbid_krnkp, "KRNKP");
  7656. EPDTBInitTBID(tbid_krnkn, "KRNKN");
  7657. EPDTBInitTBID(tbid_krnkb, "KRNKB");
  7658. EPDTBInitTBID(tbid_krnkr, "KRNKR");
  7659. EPDTBInitTBID(tbid_krnkq, "KRNKQ");
  7660. EPDTBInitTBID(tbid_krbkp, "KRBKP");
  7661. EPDTBInitTBID(tbid_krbkn, "KRBKN");
  7662. EPDTBInitTBID(tbid_krbkb, "KRBKB");
  7663. EPDTBInitTBID(tbid_krbkr, "KRBKR");
  7664. EPDTBInitTBID(tbid_krbkq, "KRBKQ");
  7665. EPDTBInitTBID(tbid_krrkp, "KRRKP");
  7666. EPDTBInitTBID(tbid_krrkn, "KRRKN");
  7667. EPDTBInitTBID(tbid_krrkb, "KRRKB");
  7668. EPDTBInitTBID(tbid_krrkr, "KRRKR");
  7669. EPDTBInitTBID(tbid_krrkq, "KRRKQ");
  7670. EPDTBInitTBID(tbid_kqpkp, "KQPKP");
  7671. EPDTBInitTBID(tbid_kqpkn, "KQPKN");
  7672. EPDTBInitTBID(tbid_kqpkb, "KQPKB");
  7673. EPDTBInitTBID(tbid_kqpkr, "KQPKR");
  7674. EPDTBInitTBID(tbid_kqpkq, "KQPKQ");
  7675. EPDTBInitTBID(tbid_kqnkp, "KQNKP");
  7676. EPDTBInitTBID(tbid_kqnkn, "KQNKN");
  7677. EPDTBInitTBID(tbid_kqnkb, "KQNKB");
  7678. EPDTBInitTBID(tbid_kqnkr, "KQNKR");
  7679. EPDTBInitTBID(tbid_kqnkq, "KQNKQ");
  7680. EPDTBInitTBID(tbid_kqbkp, "KQBKP");
  7681. EPDTBInitTBID(tbid_kqbkn, "KQBKN");
  7682. EPDTBInitTBID(tbid_kqbkb, "KQBKB");
  7683. EPDTBInitTBID(tbid_kqbkr, "KQBKR");
  7684. EPDTBInitTBID(tbid_kqbkq, "KQBKQ");
  7685. EPDTBInitTBID(tbid_kqrkp, "KQRKP");
  7686. EPDTBInitTBID(tbid_kqrkn, "KQRKN");
  7687. EPDTBInitTBID(tbid_kqrkb, "KQRKB");
  7688. EPDTBInitTBID(tbid_kqrkr, "KQRKR");
  7689. EPDTBInitTBID(tbid_kqrkq, "KQRKQ");
  7690. EPDTBInitTBID(tbid_kqqkp, "KQQKP");
  7691. EPDTBInitTBID(tbid_kqqkn, "KQQKN");
  7692. EPDTBInitTBID(tbid_kqqkb, "KQQKB");
  7693. EPDTBInitTBID(tbid_kqqkr, "KQQKR");
  7694. EPDTBInitTBID(tbid_kqqkq, "KQQKQ");
  7695. EPDTBInitTBID(tbid_kpppk, "KPPPK");
  7696. EPDTBInitTBID(tbid_knppk, "KNPPK");
  7697. EPDTBInitTBID(tbid_knnpk, "KNNPK");
  7698. EPDTBInitTBID(tbid_knnnk, "KNNNK");
  7699. EPDTBInitTBID(tbid_kbppk, "KBPPK");
  7700. EPDTBInitTBID(tbid_kbnpk, "KBNPK");
  7701. EPDTBInitTBID(tbid_kbnnk, "KBNNK");
  7702. EPDTBInitTBID(tbid_kbbpk, "KBBPK");
  7703. EPDTBInitTBID(tbid_kbbnk, "KBBNK");
  7704. EPDTBInitTBID(tbid_kbbbk, "KBBBK");
  7705. EPDTBInitTBID(tbid_krppk, "KRPPK");
  7706. EPDTBInitTBID(tbid_krnpk, "KRNPK");
  7707. EPDTBInitTBID(tbid_krnnk, "KRNNK");
  7708. EPDTBInitTBID(tbid_krbpk, "KRBPK");
  7709. EPDTBInitTBID(tbid_krbnk, "KRBNK");
  7710. EPDTBInitTBID(tbid_krbbk, "KRBBK");
  7711. EPDTBInitTBID(tbid_krrpk, "KRRPK");
  7712. EPDTBInitTBID(tbid_krrnk, "KRRNK");
  7713. EPDTBInitTBID(tbid_krrbk, "KRRBK");
  7714. EPDTBInitTBID(tbid_krrrk, "KRRRK");
  7715. EPDTBInitTBID(tbid_kqppk, "KQPPK");
  7716. EPDTBInitTBID(tbid_kqnpk, "KQNPK");
  7717. EPDTBInitTBID(tbid_kqnnk, "KQNNK");
  7718. EPDTBInitTBID(tbid_kqbpk, "KQBPK");
  7719. EPDTBInitTBID(tbid_kqbnk, "KQBNK");
  7720. EPDTBInitTBID(tbid_kqbbk, "KQBBK");
  7721. EPDTBInitTBID(tbid_kqrpk, "KQRPK");
  7722. EPDTBInitTBID(tbid_kqrnk, "KQRNK");
  7723. EPDTBInitTBID(tbid_kqrbk, "KQRBK");
  7724. EPDTBInitTBID(tbid_kqrrk, "KQRRK");
  7725. EPDTBInitTBID(tbid_kqqpk, "KQQPK");
  7726. EPDTBInitTBID(tbid_kqqnk, "KQQNK");
  7727. EPDTBInitTBID(tbid_kqqbk, "KQQBK");
  7728. EPDTBInitTBID(tbid_kqqrk, "KQQRK");
  7729. EPDTBInitTBID(tbid_kqqqk, "KQQQK");
  7730.  
  7731. /* clear the file pointer cache vector */
  7732.  
  7733. for (i = 0; i < tbcL; i++)
  7734.     tbcv[i].tbc_inuse = 0;
  7735.  
  7736. return;
  7737. }
  7738.  
  7739. /*--> EPDTBTerm: one time termination for the tablebase subsystem */
  7740. static
  7741. void
  7742. EPDTBTerm(void)
  7743. {
  7744. tbidT tbid;
  7745. tbptrT tbptr;
  7746.  
  7747. /* flush the file pointer cache vector */
  7748.  
  7749. EPDTBCacheFlush();
  7750.  
  7751. /* deallocate tablebase information vector entries */
  7752.  
  7753. tbptr = tbbaseptr;
  7754. for (tbid = 0; tbid < tbidL; tbid++)
  7755.     {
  7756.     EPDMemoryFree(tbptr->tb_name);
  7757.     tbptr++;
  7758.     };
  7759.  
  7760. /* deallocate tablebase information vector */
  7761.  
  7762. EPDMemoryFree(tbbaseptr);
  7763.  
  7764. return;
  7765. }
  7766.  
  7767. /*--> EPDInit: one time initialization for EPD */
  7768. nonstatic
  7769. void
  7770. EPDInit(void)
  7771. {
  7772. cpT cp;
  7773. sqT sq;
  7774. xsqT xsq;
  7775.  
  7776. /* this sets up the current position */
  7777.  
  7778. /* initialize ascii color conversion vector */
  7779.  
  7780. asccv[c_w] = 'w';
  7781. asccv[c_b] = 'b';
  7782.  
  7783. /* initialize ascii piece conversion vector */
  7784.  
  7785. ascpv[p_p] = 'P';
  7786. ascpv[p_n] = 'N';
  7787. ascpv[p_b] = 'B';
  7788. ascpv[p_r] = 'R';
  7789. ascpv[p_q] = 'Q';
  7790. ascpv[p_k] = 'K';
  7791.  
  7792. /* initialize ascii rank conversion vector */
  7793.  
  7794. ascrv[rank_1] = '1';
  7795. ascrv[rank_2] = '2';
  7796. ascrv[rank_3] = '3';
  7797. ascrv[rank_4] = '4';
  7798. ascrv[rank_5] = '5';
  7799. ascrv[rank_6] = '6';
  7800. ascrv[rank_7] = '7';
  7801. ascrv[rank_8] = '8';
  7802.  
  7803. /* initialize ascii file conversion vector */
  7804.  
  7805. ascfv[file_a] = 'a';
  7806. ascfv[file_b] = 'b';
  7807. ascfv[file_c] = 'c';
  7808. ascfv[file_d] = 'd';
  7809. ascfv[file_e] = 'e';
  7810. ascfv[file_f] = 'f';
  7811. ascfv[file_g] = 'g';
  7812. ascfv[file_h] = 'h';
  7813.  
  7814. /* initialize piece letter from special case move indicator */
  7815.  
  7816. cv_p_scmvv[scmv_reg] = p_nil;
  7817. cv_p_scmvv[scmv_epc] = p_nil;
  7818. cv_p_scmvv[scmv_cks] = p_nil;
  7819. cv_p_scmvv[scmv_cqs] = p_nil;
  7820. cv_p_scmvv[scmv_ppn] = p_n;
  7821. cv_p_scmvv[scmv_ppb] = p_b;
  7822. cv_p_scmvv[scmv_ppr] = p_r;
  7823. cv_p_scmvv[scmv_ppq] = p_q;
  7824.  
  7825. /* initialize various color piece conversion arrays */
  7826.  
  7827. for (cp = cp_wp; cp <= cp_wk; cp++)
  7828.     cv_c_cpv[cp] = c_w;
  7829. for (cp = cp_bp; cp <= cp_bk; cp++)
  7830.     cv_c_cpv[cp] = c_b;
  7831. cv_c_cpv[cp_v0] = c_v;
  7832. cv_c_cpv[cp_x0] = cv_c_cpv[cp_x1] = cv_c_cpv[cp_x2] = c_x;
  7833.  
  7834. cv_p_cpv[cp_wp] = cv_p_cpv[cp_bp] = p_p;
  7835. cv_p_cpv[cp_wn] = cv_p_cpv[cp_bn] = p_n;
  7836. cv_p_cpv[cp_wb] = cv_p_cpv[cp_bb] = p_b;
  7837. cv_p_cpv[cp_wr] = cv_p_cpv[cp_br] = p_r;
  7838. cv_p_cpv[cp_wq] = cv_p_cpv[cp_bq] = p_q;
  7839. cv_p_cpv[cp_wk] = cv_p_cpv[cp_bk] = p_k;
  7840. cv_p_cpv[cp_v0] = p_v;
  7841. cv_p_cpv[cp_x0] = cv_p_cpv[cp_x1] = cv_p_cpv[cp_x2] = p_x;
  7842.  
  7843. cv_cp_c_pv[c_w][p_p] = cp_wp;
  7844. cv_cp_c_pv[c_w][p_n] = cp_wn;
  7845. cv_cp_c_pv[c_w][p_b] = cp_wb;
  7846. cv_cp_c_pv[c_w][p_r] = cp_wr;
  7847. cv_cp_c_pv[c_w][p_q] = cp_wq;
  7848. cv_cp_c_pv[c_w][p_k] = cp_wk;
  7849. cv_cp_c_pv[c_b][p_p] = cp_bp;
  7850. cv_cp_c_pv[c_b][p_n] = cp_bn;
  7851. cv_cp_c_pv[c_b][p_b] = cp_bb;
  7852. cv_cp_c_pv[c_b][p_r] = cp_br;
  7853. cv_cp_c_pv[c_b][p_q] = cp_bq;
  7854. cv_cp_c_pv[c_b][p_k] = cp_bk;
  7855.  
  7856. inv_cv[c_w] = c_b;
  7857. inv_cv[c_b] = c_w;
  7858.  
  7859. /* initialize directional vectors */
  7860.  
  7861. dvv[dx_0] = dv_0;
  7862. dvv[dx_1] = dv_1;
  7863. dvv[dx_2] = dv_2;
  7864. dvv[dx_3] = dv_3;
  7865. dvv[dx_4] = dv_4;
  7866. dvv[dx_5] = dv_5;
  7867. dvv[dx_6] = dv_6;
  7868. dvv[dx_7] = dv_7;
  7869. dvv[dx_8] = dv_8;
  7870. dvv[dx_9] = dv_9;
  7871. dvv[dx_a] = dv_a;
  7872. dvv[dx_b] = dv_b;
  7873. dvv[dx_c] = dv_c;
  7874. dvv[dx_d] = dv_d;
  7875. dvv[dx_e] = dv_e;
  7876. dvv[dx_f] = dv_f;
  7877.  
  7878. xdvv[dx_0] = xdv_0;
  7879. xdvv[dx_1] = xdv_1;
  7880. xdvv[dx_2] = xdv_2;
  7881. xdvv[dx_3] = xdv_3;
  7882. xdvv[dx_4] = xdv_4;
  7883. xdvv[dx_5] = xdv_5;
  7884. xdvv[dx_6] = xdv_6;
  7885. xdvv[dx_7] = xdv_7;
  7886. xdvv[dx_8] = xdv_8;
  7887. xdvv[dx_9] = xdv_9;
  7888. xdvv[dx_a] = xdv_a;
  7889. xdvv[dx_b] = xdv_b;
  7890. xdvv[dx_c] = xdv_c;
  7891. xdvv[dx_d] = xdv_d;
  7892. xdvv[dx_e] = xdv_e;
  7893. xdvv[dx_f] = xdv_f;
  7894.  
  7895. /* initialize the extended board */
  7896.  
  7897. for (xsq = 0; xsq < xsqL; xsq++)
  7898.     xb.xbv[xsq] = cp_x0;
  7899.  
  7900. for (sq = sq_a1; sq <= sq_h8; sq++)
  7901.     xb.xbv[map_xsq_sq(sq)] = cp_v0;
  7902.  
  7903. /* initialize the standard opcode string vector */
  7904.  
  7905. epdsostrv[epdso_acd        ] = "acd";
  7906. epdsostrv[epdso_acn        ] = "acn";
  7907. epdsostrv[epdso_acs        ] = "acs";
  7908. epdsostrv[epdso_am         ] = "am";
  7909. epdsostrv[epdso_bm         ] = "bm";
  7910. epdsostrv[epdso_c0         ] = "c0";
  7911. epdsostrv[epdso_c1         ] = "c1";
  7912. epdsostrv[epdso_c2         ] = "c2";
  7913. epdsostrv[epdso_c3         ] = "c3";
  7914. epdsostrv[epdso_c4         ] = "c4";
  7915. epdsostrv[epdso_c5         ] = "c5";
  7916. epdsostrv[epdso_c6         ] = "c6";
  7917. epdsostrv[epdso_c7         ] = "c7";
  7918. epdsostrv[epdso_c8         ] = "c8";
  7919. epdsostrv[epdso_c9         ] = "c9";
  7920. epdsostrv[epdso_cc         ] = "cc";
  7921. epdsostrv[epdso_ce         ] = "ce";
  7922. epdsostrv[epdso_dm         ] = "dm";
  7923. epdsostrv[epdso_draw_accept] = "draw_accept";
  7924. epdsostrv[epdso_draw_claim ] = "draw_claim";
  7925. epdsostrv[epdso_draw_offer ] = "draw_offer";
  7926. epdsostrv[epdso_draw_reject] = "draw_reject";
  7927. epdsostrv[epdso_eco        ] = "eco";
  7928. epdsostrv[epdso_fmvn       ] = "fmvn";
  7929. epdsostrv[epdso_hmvc       ] = "hmvc";
  7930. epdsostrv[epdso_id         ] = "id";
  7931. epdsostrv[epdso_nic        ] = "nic";
  7932. epdsostrv[epdso_noop       ] = "noop";
  7933. epdsostrv[epdso_pm         ] = "pm";
  7934. epdsostrv[epdso_ptp        ] = "ptp";
  7935. epdsostrv[epdso_pv         ] = "pv";
  7936. epdsostrv[epdso_rc         ] = "rc";
  7937. epdsostrv[epdso_refcom     ] = "refcom";
  7938. epdsostrv[epdso_refreq     ] = "refreq";
  7939. epdsostrv[epdso_resign     ] = "resign";
  7940. epdsostrv[epdso_sm         ] = "sm";
  7941. epdsostrv[epdso_sv         ] = "sv";
  7942. epdsostrv[epdso_tcgs       ] = "tcgs";
  7943. epdsostrv[epdso_tcri       ] = "tcri";
  7944. epdsostrv[epdso_tcsi       ] = "tcsi";
  7945. epdsostrv[epdso_ts         ] = "ts";
  7946. epdsostrv[epdso_v0         ] = "v0";
  7947. epdsostrv[epdso_v1         ] = "v1";
  7948. epdsostrv[epdso_v2         ] = "v2";
  7949. epdsostrv[epdso_v3         ] = "v3";
  7950. epdsostrv[epdso_v4         ] = "v4";
  7951. epdsostrv[epdso_v5         ] = "v5";
  7952. epdsostrv[epdso_v6         ] = "v6";
  7953. epdsostrv[epdso_v7         ] = "v7";
  7954. epdsostrv[epdso_v8         ] = "v8";
  7955. epdsostrv[epdso_v9         ] = "v9";
  7956.  
  7957. /* set the EPD refcom operand strings */
  7958.  
  7959. refcomstrv[refcom_conclude  ] = "conclude";
  7960. refcomstrv[refcom_disconnect] = "disconnect";
  7961. refcomstrv[refcom_execute   ] = "execute";
  7962. refcomstrv[refcom_fault     ] = "fault";
  7963. refcomstrv[refcom_inform    ] = "inform";
  7964. refcomstrv[refcom_respond   ] = "respond";
  7965. refcomstrv[refcom_reset     ] = "reset";
  7966.  
  7967. /* set the EPD refreq operand strings */
  7968.  
  7969. refreqstrv[refreq_fault   ] = "fault";
  7970. refreqstrv[refreq_reply   ] = "reply";
  7971. refreqstrv[refreq_sign_on ] = "sign_on";
  7972. refreqstrv[refreq_sign_off] = "sign_off";
  7973.  
  7974. /* set the PGN Seven Tag Roster names */
  7975.  
  7976. pgnstrstrv[pgnstr_event ] = "Event";
  7977. pgnstrstrv[pgnstr_site  ] = "Site";
  7978. pgnstrstrv[pgnstr_date  ] = "Date";
  7979. pgnstrstrv[pgnstr_round ] = "Round";
  7980. pgnstrstrv[pgnstr_white ] = "White";
  7981. pgnstrstrv[pgnstr_black ] = "Black";
  7982. pgnstrstrv[pgnstr_result] = "Result";
  7983.  
  7984. /* set the game termination indication marker vector */
  7985.  
  7986. gtimstrv[gtim_w] = "1-0";
  7987. gtimstrv[gtim_b] = "0-1";
  7988. gtimstrv[gtim_d] = "1/2-1/2";
  7989. gtimstrv[gtim_u] = "*";
  7990.  
  7991. /* set the player name string vector */
  7992.  
  7993. playerstrv[c_w] = "White";
  7994. playerstrv[c_b] = "Black";
  7995.  
  7996. /* clear the global game chain anchor pointers */
  7997.  
  7998. head_gamptr = tail_gamptr = NULL;
  7999.  
  8000. /* clear the token chain anchor pointers */
  8001.  
  8002. head_tknptr = tail_tknptr = NULL;
  8003.  
  8004. /* clear the current ply */
  8005.  
  8006. ply = 0;
  8007.  
  8008. /* allocate the move tree */
  8009.  
  8010. treeptr = treebaseptr = (mptrT) EPDMemoryGrab(sizeof(mT) * treeL);
  8011.  
  8012. /* allocate the tree stack entry stack */
  8013.  
  8014. tseptr = tsebaseptr = (tseptrT) EPDMemoryGrab(sizeof(tseT) * pmhL);
  8015.  
  8016. /* allocate the environment stack entry stack */
  8017.  
  8018. eseptr = esebaseptr = (eseptrT) EPDMemoryGrab(sizeof(eseT) * pmhL);
  8019.  
  8020. /* set the current position to be the initial array */
  8021.  
  8022. EPDInitArray();
  8023.  
  8024. /* generation */
  8025.  
  8026. EPDGenMoves();
  8027.  
  8028. /* initialize the tablebase subsystem */
  8029.  
  8030. EPDTBInit();
  8031.  
  8032. return;
  8033. }
  8034.  
  8035. /*--> EPDTerm: one time termination for EPD */
  8036. nonstatic
  8037. void
  8038. EPDTerm(void)
  8039. {
  8040. /* terminate the tablebase subsystem */
  8041.  
  8042. EPDTBTerm();
  8043.  
  8044. /* release any existing game chain */
  8045.  
  8046. EPDReleaseGameChain();
  8047.  
  8048. /* release any existing token chain */
  8049.  
  8050. EPDReleaseTokenChain();
  8051.  
  8052. /* deallocate various stacks */
  8053.  
  8054. EPDMemoryFree(esebaseptr);
  8055. EPDMemoryFree(tsebaseptr);
  8056. EPDMemoryFree(treebaseptr);
  8057.  
  8058. /* "Wanna see my sprocket collection?" */
  8059.  
  8060. return;
  8061. }
  8062.  
  8063. /*<<< epd.c: EOF */
  8064.