home *** CD-ROM | disk | FTP | other *** search
/ CD PowerPlay 6 / TheCompleteAdventureCollection1995 / CDPP6.ISO / hints / 7thg / winmicro / game2.c next >
Encoding:
C/C++ Source or Header  |  1995-07-01  |  17.9 KB  |  692 lines

  1. /***********************************************************
  2. T7G microscope program using recursive minimax method
  3. with alpha-beta pruning.  Move getmoves function inside/inline
  4. of find/eval moves.  Add "stability" factor to scoring.
  5. A square is considered stable when it is completely surrounded by other
  6. pieces.
  7.                   Overall scoring.
  8. GREEN WIN = -1000... > 0=tie > ...1000 = BLUE WIN
  9. Score = 2*(#blue - #green) + (#blue stable - #green stable)
  10. */
  11.  
  12. #include "protos.h"
  13.  
  14. char dummy[80];
  15. extern unsigned _stklen=0x9000u; //0xffe0u;   // extra stack
  16. char far Gmaxlevel = 0;                       // search depth
  17. unsigned long far Gmovecount;
  18. unsigned long far Gmovesanalyzed;
  19. Tmovelist far Gbestmoves;
  20. int Gcountmovelist=0;
  21. TWindow2 far *window2;
  22. TWindow1 far *window1;
  23. char endgame = FALSE;
  24.  
  25. // ******** MAIN *********
  26. void main(void){
  27.  
  28. Tcurrent far *game,*lastgame;
  29. Tmovelist far *movelist;
  30. Tmovelist yourmove;
  31. clock_t first, second;
  32. int bestscore;
  33.  
  34. init_stack_count();
  35. game=allocTboard();
  36. lastgame=allocTboard();
  37.  
  38. window2=(TWindow2 *) farmalloc(sizeof(TWindow2));
  39. if(window2==NULL) abort();
  40. window1=(TWindow1 *)farmalloc(sizeof(TWindow1));
  41. if(window1==NULL) abort();
  42. initwindow1(); // must call before initwindow2()
  43. initwindow2();
  44. initboard(game);
  45.  
  46.  
  47. while(Gmaxlevel<1 || Gmaxlevel>8)
  48.     {
  49.     puts("Enter maximum level");
  50.     scanf("%d",&Gmaxlevel);
  51.     }
  52. *lastgame=*game;
  53. printboard(game);
  54. yourmove = getmove(game);
  55. makemove(game,&yourmove);
  56.  
  57. while(TRUE)   // Loop until end of game
  58.     {
  59.     printboard(game);
  60.     yourmove = getmove(game);
  61.     if(yourmove.from == -1) {*game=*lastgame; continue;}
  62.     *lastgame = *game;
  63.     makemove(game,&yourmove);
  64.     printboard(game);
  65.     Gmovesanalyzed = Gmovecount=0;
  66.     bestscore = 999;
  67.     if( (49-game->counttotal)<=3 && endgame==FALSE)
  68.         {
  69.         endgame = TRUE;
  70.         Gmaxlevel +=2;
  71.         }
  72.     _setcursortype(_NOCURSOR);
  73.     first = clock();
  74.     movelist = findmoves(game,Gmaxlevel,&bestscore);
  75.     second = clock();
  76.     printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
  77.     if(movelist != NULL)
  78.     {
  79.     printf("Level %d: %lu total moves,%lu analyzed.  Score= %+d  Time= %f\n",
  80.                         Gmaxlevel,
  81.                         Gmovecount,
  82.                         Gmovesanalyzed,
  83.                         bestscore,
  84.                         (second-first)/CLK_TCK);
  85.     printf("Thinking: ");
  86.     printmovelist(movelist);
  87.     printf("\n");
  88.     }
  89.     makemove(game,movelist);
  90.     printf("Current Score: Blue= %d, Green= %d, Net= %+d, Stability= %d\n",
  91.         game->countblue, game->counttotal-game->countblue,
  92.         2*game->countblue-game->counttotal, getboardscore(game));
  93.     _setcursortype(_NORMALCURSOR);
  94.     if(movelist == NULL) {
  95.         puts("*** GAME OVER ***");
  96.         exit(0);
  97.         }
  98.     freelist(movelist);
  99.     }
  100. }
  101.  
  102. //******** FINDMOVES ********
  103. Tmovelist* findmoves(Tcurrent far *a,char level,int far *bestscore)
  104. // IN:bestscore = opponents bestscore so for this branch
  105. // OUT:bestscore = this colors new bestscore for this branch
  106. {
  107. Tcurrent *current_board;
  108. Tmovelist *bestmove;
  109. Tmovelist *current_move;
  110. Tmovelist *reply;
  111. Tsquare color;
  112. int opponent_score;
  113. int current_score;
  114. char j,k;
  115. char moveto,movefrom;
  116. char rowfrom, colfrom,rowto,colto;
  117. char anymove;
  118. char exists[49];
  119.  
  120. if(level==0)   // Analyze and return the final score
  121.     {
  122.     *bestscore = getboardscore(a);
  123.     *bestscore += PIECEWEIGHT*(2*a->countblue- a->counttotal);
  124.     Gmovesanalyzed++;
  125.     return NULL;
  126.     }
  127.  
  128. color = a->color;
  129. bestmove = allocmovelist();
  130. current_move = allocmovelist();
  131. anymove = FALSE;
  132.  
  133. // Set the opponents score to beat
  134. // +-999 insures leftmost branch is always analyzed
  135. if(color==BLUESQ) current_score = opponent_score = -999;
  136. else current_score = opponent_score = 999;
  137.  
  138. current_board=(Tcurrent *) farmalloc(sizeof(Tcurrent));
  139. if(current_board==NULL) abort();
  140.  
  141. *current_board = *a;                // set current_board
  142.  
  143. // Get all moves
  144. for(k=0;k<49;k++) exists[k]=0;
  145. for(k=0;k<49;k++)
  146.     {
  147.     // if square contains color to be moved
  148.     if(a->board.b[k] == color)
  149.         {
  150.         rowfrom = k/7; colfrom = k%7;
  151.         for(j=1;j<=window2->a[k][0];j++)
  152.             {
  153.             if(a->board.b[ window2->a[k][j] ] == EMPTYSQ)
  154.                 { // found possible move
  155.                 rowto = window2->a[k][j]/7; colto = window2->a[k][j]%7;
  156.                 movefrom = k;
  157.                 moveto = window2->a[k][j];
  158.                 // Is move a jump?
  159.                 if(abs(rowto-rowfrom)<=1 && abs(colto-colfrom)<=1)
  160.                     {
  161.                     // move is not a jump ; search for duplicate
  162.                     if(exists[moveto]==1) continue;
  163.                     exists[moveto]=1;
  164.                     current_move->jump = FALSE;
  165.                     }
  166.                 else current_move->jump = TRUE;
  167.                 // store current_move
  168.                 Gmovecount++;
  169.                 anymove = TRUE;
  170.                 current_move->next = NULL;
  171.                 current_move->to = moveto;
  172.                 current_move->from = movefrom;
  173.  
  174.             makemove(current_board,current_move);
  175.             reply = findmoves(current_board,level-1,&opponent_score);
  176.             *current_board =*a;                       // restore current board
  177.             if(level == Gmaxlevel)
  178.                  {
  179.                  printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
  180.                  printf("Best=%d  ",current_score);
  181.                  if(abs(current_score)!=999)
  182.                     printmove(bestmove);
  183.                  printf(" Current=%d  ",opponent_score);
  184.                  printmove(current_move);
  185.                  printf("  ");
  186.                  }
  187.             if(color==BLUESQ && opponent_score>current_score)
  188.                 {
  189.                 current_score = opponent_score;      // update best score so far
  190.                 freelist(bestmove->next);            // free old reply
  191.                 *bestmove = *current_move;           // store new best move
  192.                 bestmove->next = reply;              // store new reply
  193.                 if(opponent_score>=*bestscore)
  194.                     goto nextstep; // dont bother evaluating rest of moves!
  195.                 }
  196.             else if(color==GREENSQ && opponent_score<current_score)
  197.                 {
  198.                 current_score = opponent_score;
  199.                 freelist(bestmove->next);
  200.                 *bestmove = *current_move;
  201.                 bestmove->next = reply;
  202.                 if(opponent_score<=*bestscore)
  203.                     goto nextstep;  // dont bother evaluating rest of moves!
  204.                 }
  205.             else  freelist(reply);     // free bad reply
  206.  
  207.             opponent_score = current_score; // reset "best score" sent to next search
  208.                 } //endif possible move
  209.             } //end for(j=startcol...
  210.         } // end if square contains color to be moved
  211.     } //end get all moves (for k)
  212.  
  213. // If no moves (movelist == NULL) return win/loss
  214. if(anymove==FALSE)
  215.     {
  216.     // Set score equal to the absolute count...no stability factor
  217.     current_score = PIECEWEIGHT*(2*a->countblue - a->counttotal);
  218.     //if any empty squares on board
  219.     if(emptysquare(a)==TRUE)
  220.         {
  221.         if(color==BLUESQ) current_score = -1000;   //NO MOVE:BLUE LOSS
  222.         }
  223.     else
  224.         {
  225.         if(color==BLUESQ)
  226.             {
  227.             if(current_score>0) current_score = 1000;   //BLUE WIN
  228.             else current_score = -1000;              //BLUE LOSS
  229.             }
  230.         else
  231.         // Figure for GREEN
  232.             {
  233.             if(current_score<0) current_score = -1000;  //GREEN WIN
  234.             else current_score = 1000;               //GREEN LOSS
  235.             }
  236.         }
  237.     Gmovesanalyzed++;
  238.     freelist(bestmove);
  239.     bestmove = NULL;
  240.     }
  241.  
  242. nextstep:   // label for alpha/beta pruning jump
  243. ;
  244.  
  245. freelist(current_move);          // free movelist
  246. *bestscore = current_score;  // return bestscore found
  247. farfree(current_board);      // free current_board
  248. return bestmove;             // return bestmove
  249. }
  250.  
  251.  
  252. // Makemove and return resulting board
  253. void makemove(Tcurrent *a,Tmovelist *movelist)
  254. {
  255. Tsquare opponent;
  256. Tsquare color=a->color;
  257. char countflipped=0;
  258. char row;
  259. if(movelist==NULL) return;
  260. //Set opponent color
  261. if(color == BLUESQ) opponent=GREENSQ;
  262. else opponent=BLUESQ;
  263.  
  264. // Move piece into new square
  265. a->board.b[movelist->to] = color;
  266.  
  267. if(movelist->jump == TRUE) a->board.b[movelist->from] = EMPTYSQ;
  268. else a->counttotal++;  // move is not a jump add one to total pieces
  269.  
  270. // Flip opponents pieces
  271. for(row=1;row<=window1->a[movelist->to][0];row++)
  272.     if(a->board.b[window1->a[movelist->to][row]] == opponent)
  273.             {
  274.             a->board.b[window1->a[movelist->to][row]] = color;
  275.             countflipped++;
  276.             }
  277.  
  278. // calculate score
  279. if(color == BLUESQ)
  280.     {
  281.     a->countblue += countflipped;
  282.     if(movelist->jump==FALSE) a->countblue++;
  283.     }
  284. else a->countblue -= countflipped;
  285. a->color = opponent;                  // set turn to opponent
  286. return;
  287. }
  288.  
  289. int getboardscore(Tcurrent *a)
  290. // return net "stability" score
  291. // number stable blue minus stable green
  292. {
  293. char stable;
  294. char i,j;
  295. int score = 0;
  296. Tsquare square;
  297.  
  298. for(i=0;i<49;i++)
  299.     {
  300.     // if square contains color
  301.     square = a->board.b[i];
  302.     if(square == EMPTYSQ)
  303.         continue;
  304.     else
  305.         {
  306.         // is square stable?
  307.         for(stable=TRUE,j=1; j<=window1->a[i][0]; j++)
  308.             {
  309.             if(a->board.b[window1->a[i][j]] == EMPTYSQ)
  310.                 {
  311.                 stable = FALSE;
  312.                 break;
  313.                 }
  314.             }
  315.         if(stable == FALSE) continue;
  316.         }
  317.     if(square == BLUESQ)
  318.         score++;
  319.     else
  320.         score--;
  321.     }
  322. return score;
  323. }
  324.  
  325. void printmovelist(Tmovelist *movelist)  // print entire move list
  326. {
  327. if (movelist==NULL) return;
  328. if(movelist->jump == TRUE)
  329.     printf("%c%d-",
  330.             'A'+(movelist->from / (MAXROW+1)),
  331.             (movelist->from % (MAXROW+1))+1);
  332. printf("%c%d ",
  333.             'A'+ (movelist->to / (MAXROW+1)),
  334.             (movelist->to % (MAXROW+1))+1);
  335. printmovelist(movelist->next);
  336. }
  337.  
  338. void printmove(Tmovelist *movelist)  // print only first move in list
  339. {
  340. if(movelist == NULL) return;
  341. if(movelist->jump == TRUE)
  342.     printf("%c%d-",
  343.             'A'+(movelist->from / (MAXROW+1)),
  344.             (movelist->from % (MAXROW+1))+1);
  345. printf("%c%d ",
  346.             'A'+ (movelist->to / (MAXROW+1)),
  347.             (movelist->to % (MAXROW+1))+1);
  348. }
  349.  
  350. Tmovelist getmove(Tcurrent* a)  // Get a move from the keyboard
  351. {
  352. Tmovelist move;
  353. char legal=FALSE;
  354.  
  355. move.next = NULL;
  356. while(legal==FALSE)
  357.     {
  358.     puts("From? (RowCol) TB for takeback");
  359.     move.from = getsquare();
  360.     if(move.from == -1) return move;
  361.     puts("To?");
  362.     move.to = getsquare();
  363.     if((a->board.board[move.from/7][move.from %7] == a->color)
  364.             &&
  365.         (a->board.board[move.to/7][move.to %7] == EMPTYSQ) )
  366.                 legal = TRUE;
  367.     }
  368. if(abs(move.from/7 - move.to/7) == 2 || abs(move.to%7 - move.from%7) == 2)
  369.     move.jump = TRUE;
  370. else move.jump = FALSE;
  371. return move;
  372. }
  373.  
  374. char getsquare(void)
  375. {
  376. char input[80];
  377. char row = -1;
  378. char col = -1;
  379. while((row<MINROW || row>MAXROW) && (col<MINCOL || col>MAXCOL))
  380.     {
  381.     gets(input);
  382.     row = toupper(input[0])-'A';
  383.     col = toupper(input[1]) - '1';
  384.     if(row==19 && col==17) return -1;
  385.     }
  386. return row*(MAXROW+1)+col;
  387. }
  388.  
  389. void initboard(Tcurrent *a)
  390. // Initialize board for start of game
  391. {
  392. int row,col;
  393. for(row=MINROW;row<=MAXROW;row++)
  394.     for(col=MINCOL;col<=MAXCOL;col++)
  395.         {
  396.         a->board.board[row][col] = EMPTYSQ;
  397.         }
  398. a->board.board[MINROW][MINCOL] = BLUESQ;
  399. a->board.board[MINROW][MAXCOL] = GREENSQ;
  400. a->board.board[MAXROW][MINCOL] = GREENSQ;
  401. a->board.board[MAXROW][MAXCOL] = BLUESQ;
  402. a->countblue = 2;
  403. a->counttotal = 4;
  404. a->color = BLUESQ;
  405. }
  406.  
  407. void printboard(Tcurrent *a)
  408. {
  409. int i,j;
  410. printf("    1 2 3 4 5 6 7\n");
  411. printf("    * * * * * * *\n");
  412. for(i=MINROW;i<=MAXROW;i++)
  413.     {
  414.     printf(" %c* ",'A'+i);
  415.     for(j=MINCOL;j<=MAXCOL;j++)
  416.         {
  417.         switch(a->board.board[i][j])
  418.             {
  419.             case (EMPTYSQ):
  420.                 printf("  ");
  421.                 break;
  422.             case (GREENSQ):
  423.                 printf("G ");
  424.                 break;
  425.             case (BLUESQ) :
  426.                 printf("B ");
  427.                 break;
  428.             default :
  429.                 printf("? ");
  430.             }
  431.         }
  432.     printf("*\n");
  433.     }
  434. printf("    * * * * * * *\n");
  435. }
  436.  
  437. char emptysquare(Tcurrent *a)
  438. // Check for any empty square on the board
  439. {
  440. char i;
  441.  
  442. for(i=0;i<49;i++) if(a->board.b[i] == EMPTYSQ)  return TRUE;
  443. return FALSE;
  444. }
  445.  
  446. void initwindow1(void)                // precompute 1 square "windows"
  447. {
  448. char i,j,k,count,row,col,index;
  449. char startrow,endrow,startcol,endcol;
  450.  
  451. count=0;
  452. for(k=0;k<49;k++)
  453.         {
  454.         // determine limits of search
  455.         row = k/7; col=k%7;
  456.         startrow = row - 1;
  457.         if(startrow<MINROW) startrow = MINROW;
  458.         endrow = row + 1;
  459.         if(endrow>MAXROW) endrow = MAXROW;
  460.         startcol = col - 1;
  461.         if(startcol<MINCOL) startcol = MINCOL;
  462.         endcol = col + 1;
  463.         if(endcol>MAXCOL) endcol = MAXCOL;
  464.  
  465.             // search for empty squares
  466.  
  467.         for(i=startrow;i<=endrow;i++)
  468.             for(j=startcol;j<=endcol;j++)
  469.                 {
  470.                 index = 7*i+j;
  471.                 if(index!=k)
  472.                     {
  473.                     count++;
  474.                     if(k<0 || k>49 || count<0 || count>8) abort();
  475.                     window1->a[k][count] = index;
  476.                     }
  477.                 }
  478.         if(k<0 || k>49) abort();
  479.         window1->a[k][0] = count;
  480.         count=0;
  481.         }
  482. }
  483.  
  484. void initwindow2(void)                // precompute 2 square "windows"
  485. {
  486. char i,j,k,count,row,col,index;
  487. char startrow,endrow,startcol,endcol;
  488.  
  489. count=0;
  490. for(k=0;k<49;k++)
  491.         {
  492.         // determine limits of search
  493.         row = k/7; col=k%7;
  494.         startrow = row - 2;
  495.         if(startrow<MINROW) startrow = MINROW;
  496.         endrow = row + 2;
  497.         if(endrow>MAXROW) endrow = MAXROW;
  498.         startcol = col - 2;
  499.         if(startcol<MINCOL) startcol = MINCOL;
  500.         endcol = col + 2;
  501.         if(endcol>MAXCOL) endcol = MAXCOL;
  502.         count = window1->a[k][0];
  503.         // load all squares next to this square first
  504.         for(i=1;i<=count;i++) window2->a[k][i] = window1->a[k][i];
  505.         // search for empty squares
  506.         for(i=startrow;i<=endrow;i++)
  507.             for(j=startcol;j<=endcol;j++)
  508.                 {
  509.                 // Eliminate adjacent squares (we already have them)
  510.                 if(abs(i-row)<=1 && abs(j-col)<=1) continue;
  511.                 index = 7*i+j;
  512.                 if(index!=k)
  513.                     {
  514.                     count++;
  515.                     if(k<0 || k>49 || count<0 || count>25) abort();
  516.                     window2->a[k][count] = index;
  517.                     }
  518.                 }
  519.         if(k<0 || k>49) abort();
  520.         window2->a[k][0] = count;
  521.         }
  522. }
  523.  
  524. Tmovelist *allocmovelist(void)
  525. {
  526. Tmovelist *newmovelist;
  527.  
  528. newmovelist = (Tmovelist *) farmalloc(sizeof(Tmovelist));
  529. if (newmovelist==NULL) abort();
  530. newmovelist->next=NULL;
  531. newmovelist->jump = FALSE;
  532. return newmovelist;
  533. }
  534.  
  535. Tcurrent *allocTboard(void)
  536. {
  537. Tcurrent *newTboard;
  538.  
  539. newTboard = (Tcurrent *) farmalloc(sizeof(Tcurrent));
  540. if (newTboard==NULL) abort();
  541. return newTboard;
  542. }
  543.  
  544. void freeTboard(Tcurrent *aboard)
  545. {
  546. farfree(aboard);
  547. aboard = NULL;
  548. }
  549.  
  550. void freelist(Tmovelist* movelist)
  551. {
  552. if(movelist == NULL) return;
  553. freelist(movelist->next);
  554. movelist->next=NULL;
  555. farfree(movelist);
  556. }
  557.  
  558.   #define SIZE_OF_EMULATOR 415            // Account for floating
  559.                                                         // point emulator
  560.   #define FILL_CHAR 0xFF                  // Character used to mark
  561.                                                         // the stack
  562.  
  563.   #pragma warn -aus                       // Turn off unecessary
  564.   #pragma warn -use                       // warnings
  565.  
  566. /*
  567.   / ************************************************************* \
  568.   |    Marks all possible stack space not currently in use by     |
  569.   |    setting the values   to 0xff.                              |
  570.   \ ************************************************************* / */
  571.   void init_stack_count(void)
  572.   {
  573.          char far *sp;                 // far memory model stack
  574.                                                  // pointer
  575.          //char near *nsp;               // near memory model stack
  576.                                                  // pointer
  577.          extern  unsigned __brklvl;    // Internal variable marking
  578.                                                  // top of
  579.                                                  // the near heap.
  580.  
  581.   #if  defined(__COMPACT__)     ||   \
  582.          defined(__LARGE__)       ||   \
  583.          defined(__HUGE__)
  584.   #undef    _HEAP_
  585.  
  586. sp = MK_FP( _SS, _SP - 1 );   // initialize sp to point to
  587.                                                  // the next available space on
  588.                                                  // the stack.
  589.  
  590.          while( sp > (char far *)SIZE_OF_EMULATOR ) //Check
  591.                                                  // for stack overflow
  592.          {
  593.                 *sp = FILL_CHAR;         // Initialize unused stack
  594.                                                  // space
  595.                 sp--;
  596.          }
  597.   #else                              // similar for near data
  598.                                                  // memory model
  599.          nsp = (char *) _SP - 1;       // Initialize pointer
  600.          while( nsp > (char *)__brklvl)// Check for stack overflow
  601.          {
  602.                 *nsp = FILL_CHAR;        // Assign fill character
  603.                 nsp--;                   // advance pointer
  604.          }
  605.   #endif
  606.          return;
  607.   }
  608. /*
  609.   / ************************************************************* \
  610.   |    Goes though stack space counting unused (unmodified)       |
  611.   |    values meaning that space on the stack was not used.       |
  612.   \ ************************************************************* / */
  613.   void stack_count( void )
  614.   {
  615.          unsigned count= 0;            // Amount of unused stack
  616.                                                  // space
  617.          //unsigned mcount = 0;          // Amount of used Heap space
  618.          char far *sp;                 // Far memory model pointer
  619.          //char *nsp;                    // Near memory model pointer
  620.  
  621.  
  622.   #if  defined(__COMPACT__)     ||   \
  623.          defined(__LARGE__)       ||   \
  624.          defined(__HUGE__)
  625.  
  626.          sp = MK_FP( _SS, SIZE_OF_EMULATOR+1);   // Initialize the
  627.                                                               // pointer
  628.          if( _SP >  SIZE_OF_EMULATOR )           // Check for stack
  629.                                                               // overflow
  630.          {
  631.                 while( sp < MK_FP(_SS,_SP)  )      // Check for stack
  632.                                                               // overflow
  633.                 {
  634.                       if( *sp != (char) FILL_CHAR ) // compare pointer
  635.                                                               //value to
  636.                                                               // fill character
  637.                              break;
  638.                       count++;                      // count unused
  639.                                                               // stack space
  640.                       sp++;                         // increment pointer
  641.                 }
  642.          }
  643.   #else
  644.          extern unsigned __brklvl;          // End of near heap
  645.          extern unsigned __heapbase;        // Beginning of near heap
  646.          if( _SP > __brklvl  )              // Check for stack
  647.                                                         // overflow
  648.          {
  649.                 nsp = (char *) __brklvl + 1;
  650.                 while( nsp < (char *)_SP )    // While we don't run
  651.                                                         // into the
  652.                                                         // current stack.
  653.                 {
  654.                       if( *nsp != (char) FILL_CHAR && count < 3)
  655.                                                         // Count near heap used
  656.                              mcount++;
  657.                                                         // else count unused
  658. 9                                                        // stack
  659.                       else if( *(nsp + 1) == (char)FILL_CHAR &&
  660.                                   *(nsp + 2) == (char) FILL_CHAR  )
  661.                              count++;            // Count unused bytes
  662.                       nsp++;
  663.                 }
  664.          }
  665.          count += 2;
  666.   #endif
  667.  
  668.  
  669.   #ifdef    _HEAP_                        // print amount of used
  670.                                                         // stack
  671.          printf("\nHeap Used = %u bytes", (__brklvl - __heapbase +
  672.                                                         mcount));
  673.   #endif                                  // print amount of unused
  674.                                                         // stack
  675.          printf("\nStack not used = %u bytes" , count);
  676.          return;
  677.   }
  678.  
  679. void heapchk(void){
  680. stack_count();
  681. printf("coreleft=%lu \n",farcoreleft());
  682. printf("Movelists allocated = %d, %d bytes\n",Gcountmovelist,Gcountmovelist*sizeof(Tmovelist));
  683. if( heapcheck() == _HEAPCORRUPT )
  684.     {
  685.     printf( " **** Heap is corrupted. ****\n" );
  686.     abort();
  687.     }
  688. else
  689.     printf( "Heap is OK.\n" );
  690. getch();
  691. }
  692.