home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / BORLAND TURBO / CHESS.PAK / SMALL.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  8.6 KB  |  424 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1991, 1993 by Borland International
  3. //----------------------------------------------------------------------------
  4. #include <owl/pch.h>
  5. #include <owl/defs.h>
  6. #include <time.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include "wcdefs.h"
  10. #include "wchess.h"
  11. #include "externs.h"
  12.  
  13. //
  14. //  Global Variables
  15. //
  16. MOVETYPE  ZeroMove = { 8, 8, 0, empty, empty };
  17. CLOCKTYPE ChessTime[2];
  18. MOVETYPE  KeyMove;
  19. BOOL      Running;
  20. COLORTYPE RunColor;
  21. BOOL      Analysis, Opan;
  22. double    WantedTime;
  23. BOOL      GameOver = FALSE;
  24. char      EndGameMessage[80];
  25.  
  26. extern double AverageTime;
  27.  
  28.  
  29. void EndMessage(char *);
  30.  
  31. //
  32. //  Initialize the chess clocks
  33. //
  34. void
  35. InitChessTime()
  36. {
  37.   InitTime(&ChessTime[white]);
  38.   InitTime(&ChessTime[black]);
  39. }
  40.  
  41. void
  42. StopChessTime()
  43. {
  44.   if (Running) {
  45.     StopTime(&ChessTime[RunColor]);
  46.     KillTimer(hWndMain, TIMEID);
  47.     Running = FALSE;
  48.   }
  49. }
  50.  
  51. //
  52. //  Stop the running chess clock and start the clock for color
  53. //
  54. void
  55. StartChessTime(COLORTYPE color)
  56. {
  57.   RunColor = color;
  58.   Running = TRUE;
  59.   StartTime(&ChessTime[RunColor]);
  60.   SetTimer(hWndMain, TIMEID, 1000, 0);
  61. }
  62.  
  63. //
  64. //  reset MovTab
  65. //
  66. void
  67. ResetMoves()
  68. {
  69.   Depth = -1;
  70.   MovTab[-1] = ZeroMove;
  71. }
  72.  
  73. //
  74. //  Clear HintLine
  75. //
  76. void
  77. ClearHint()
  78. {
  79.   HintLine[0] = ZeroMove;
  80.   HintEvalu = 0;
  81. }
  82.  
  83. void
  84. InitNode(NODEVAL* nodes)
  85. {
  86.   nodes->nodebase = 0;
  87.   nodes->nodeoffset = 0;
  88. }
  89.  
  90. //
  91. //  Test if the move is legal for Programcolor == player in the
  92. //  given position
  93. //
  94. BOOL
  95. IllegalMove(MOVETYPE* move)
  96. {
  97.   Perform(move, 0);
  98.   BOOL illegal = Attacks(Opponent, PieceTab[Player][0].isquare);
  99.   Perform(move, 1);
  100.   return illegal;
  101. }
  102.  
  103. //
  104. //  Make move for programcolor = player and updates variables
  105. //
  106. void
  107. MakeMove(MOVETYPE* move)
  108. {
  109.   Depth++;
  110.   MoveNo++;
  111.   Perform(move, 0);
  112.   ProgramColor = Opponent;
  113.   Opponent = Player;
  114.   Player = ProgramColor;
  115. }
  116.  
  117. //
  118. //  Prints comment to the game (check, mate, draw, resign)
  119. //
  120. void
  121. PrintComment()
  122. {
  123.   short check, possiblemove, checkmate;
  124.   int nummoves;
  125.  
  126.   Message("");
  127.   checkmate = 0;
  128.   Depth++;
  129.   possiblemove = 0;
  130.   InitMovGen();
  131.   do {
  132.     MovGen();
  133.     if (Next.movpiece != empty)
  134.       if (!IllegalMove(&Next))
  135.         possiblemove = 1;
  136.   } while (Next.movpiece != empty && !possiblemove);
  137.  
  138.   Depth--;
  139.   check = Attacks(Opponent, PieceTab[Player][0].isquare); // calculate check
  140.   //  No possible move means checkmate or stalemate 
  141.   if (!possiblemove) {
  142.     if (check) {
  143.       checkmate = 1;
  144.       EndMessage("CheckMate");
  145.     } else
  146.       EndMessage("Stalemate!");
  147.  
  148.   } else
  149.     if (HintEvalu >= MATEVALUE - DEPTHFACTOR * 16) {
  150.       nummoves = (MATEVALUE - HintEvalu + 0x40) / (DEPTHFACTOR * 2);
  151.       sprintf(buf, "Mate in %d Move%s", nummoves, (nummoves > 1) ? "s!" : "!");
  152.       Message(buf);
  153.     }
  154.   if (check && !checkmate)
  155.     Message("Check!");
  156.   else { //  test 50 move rule and repetition of moves 
  157.     if (FiftyMoveCnt() >= 100) {
  158.       EndMessage("50 Move rule");
  159.     } else
  160.      if (Repetition(0) >= 3) {
  161.        EndMessage("3 fold Repetition");
  162.      } else        //  Resign if the position is hopeless 
  163.       if (-25500 < HintEvalu && HintEvalu < -0x880) {
  164.         switch (Opponent) {
  165.           case white:
  166.             EndMessage(" White resigns");
  167.             break;
  168.           case black:
  169.             EndMessage(" Black resigns");
  170.         }
  171.       }
  172.   }
  173. }
  174.  
  175. void
  176. EnterMove(MOVETYPE* move)
  177. {
  178.    StopChessTime();
  179.    PrintMove(MoveNo, ProgramColor, move, ChessTime[RunColor].totaltime);
  180.    MakeMove(move);
  181.    UpdateBoard();
  182.    PrintComment();
  183.    StartChessTime(ProgramColor);
  184. }
  185.  
  186. void
  187. RemoveMove(MOVETYPE* move)
  188. {
  189.    StopChessTime();
  190.    PrintMove(MoveNo, ProgramColor, move, ChessTime[RunColor].totaltime);
  191.    TakeBackMove(move);
  192.    UpdateBoard();
  193.    PrintComment();
  194.    StartChessTime(ProgramColor);
  195. }
  196.  
  197. //
  198. //  perform the move entered by the user
  199. //
  200. void
  201. EnterKeyMove()
  202. {
  203.   MovTab[Depth+1] = KeyMove;
  204.   PlayerMove = KeyMove;
  205.   ClearHint();
  206.   DragEnd(TRUE);
  207.   EnterMove(&MovTab[Depth+1]);
  208. }
  209.  
  210. //
  211. //  move movtab to depth = -1
  212. //
  213. void
  214. AdjustMoves()
  215. {
  216.   for (int i = Depth; i >= BACK; i--)
  217.     MovTab[i-(Depth+1)] = MovTab[i];
  218.   Depth = -1;
  219. }
  220.  
  221. //
  222. //  Move movtab one move BACK
  223. //
  224. void
  225. StoreMoves()
  226. {
  227.   Depth--;
  228.   for (int i = BACK; i <= Depth; i++)
  229.     MovTab[i] = MovTab[i+1];
  230.   MovTab[BACK] = ZeroMove;
  231. }
  232.   
  233. //
  234. //  Check to see if the input move is legal
  235. //
  236. BOOL
  237. MoveCheck(SQUARETYPE startsq, SQUARETYPE endsq)
  238. {
  239.   Depth++;
  240.   KeyMove = ZeroMove;
  241.   InitMovGen();
  242.   do {
  243.     MovGen();
  244.     if (Next.new1 == endsq && Next.old == startsq) {
  245.       KeyMove = Next;
  246.       break;
  247.     }
  248.   } while (Next.movpiece != empty);
  249.  
  250.   if (KeyMove.movpiece == empty) {
  251.     Warning("Impossible move");
  252.     Depth--;
  253.     return FALSE;
  254.   }
  255.   if (IllegalMove(&KeyMove)) {
  256.     Warning("Illegal move. Check!");
  257.     Depth--;
  258.     return FALSE;
  259.   }
  260.   Depth--;
  261.   if (!ComputerThinking) {
  262.     AdjustMoves();
  263.     EnterKeyMove();
  264.     StoreMoves();
  265.   }
  266.   return TRUE;
  267. }
  268.  
  269. //
  270. //  calculate the WANTED response time
  271. //
  272. void
  273. StartAnalysis()
  274. {
  275.   int            timecontrol;
  276.   extern HWND    hWndMain;
  277.   extern HCURSOR hWaitCursor;
  278.  
  279.   Analysis = 1;
  280.   Opan = 0;
  281.   SetClassWindowCursor(hWndMain, hWaitCursor);
  282.  
  283.   switch (Level) {
  284.     case easygame:
  285.     case normal:
  286.       //  Divides the Time left till nest time control between moves left.
  287.       //  There is a margin of 4 moves to make sure that the program does
  288.       //  not lose on time 
  289.       timecontrol = (((MoveNo >> 1) + 20) / 20) * 20;
  290.       if (timecontrol <= 40)
  291.         timecontrol = 40;
  292.       WantedTime = (AverageTime * timecontrol - ChessTime[ProgramColor].totaltime) /
  293.             (timecontrol + 4 - (MoveNo >> 1));
  294.  
  295.       //  In the begining of the game the program thinks
  296.       //  around twice as long, since the early middle
  297.       //  game is normally the most crucial part of
  298.       //  a game 
  299.       if ((MoveNo >> 1) <= 40)
  300.         WantedTime = 5.0 + (WantedTime - 5.0) * ((80 - (MoveNo >> 1)) / 40);
  301.       break;
  302.  
  303.     case fullgametime:
  304.       //  Assumes that the game will last for around 40 moves and
  305.       //  divides the time left accordingly 
  306.       WantedTime = (AverageTime * 60.0 - ChessTime[ProgramColor].totaltime) / 44;
  307.  
  308.       //  In the begining of the game the program thinks around twice as long,
  309.       //  since the early middle game is normally the most crucial part of a
  310.       //  game 
  311.       if ((MoveNo >> 1) <= 40)
  312.         WantedTime = 5.0 + (WantedTime - 5.0) * ((80 - (MoveNo >> 1)) /40);
  313.       break;
  314.  
  315.     case matching:
  316.       //  Spend as much time as the Opponent does 
  317.       if (MoveNo >= 2)
  318.         WantedTime = ChessTime[Opponent].totaltime / (MoveNo >> 1);
  319.       else
  320.         WantedTime = 5.0;
  321.       WantedTime += (ChessTime[Opponent].totaltime - 
  322.                      ChessTime[ProgramColor].totaltime) * 0.25;
  323.  
  324.       //break; //wasn't here???
  325.  
  326.     default:
  327.       WantedTime = 1000000.0;
  328.   }
  329. }
  330.  
  331. //
  332. //  take BACK move and update variables
  333. //
  334. void
  335. TakeBackMove(MOVETYPE* move)
  336. {
  337.   ProgramColor = Opponent;
  338.   Opponent = Player;
  339.   Player = ProgramColor;
  340.   Perform(move, 1);
  341.   MoveNo--;
  342.   Depth--;
  343. }
  344.  
  345. void
  346. IncNode(NODEVAL *nodes)
  347. {
  348.   if (nodes->nodeoffset >= MAXINT) {
  349.     nodes->nodebase++;
  350.     nodes->nodeoffset = 0;
  351.  
  352.   } else
  353.     nodes->nodeoffset++;
  354. }
  355.  
  356.  
  357. void
  358. Wait(int tenths)
  359. {
  360.   clock_t NumTicksToWait;
  361.  
  362.   // two ticks == approx. 1/10 second, since 18.2 clocks is approx a
  363.   // second
  364.   NumTicksToWait = tenths*2 + clock();
  365.   while (NumTicksToWait > clock())
  366.     ;
  367. }
  368.  
  369. //
  370. //  Flash a move once on the screen
  371. //
  372. void
  373. FlashMove(MOVETYPE* move)
  374. {
  375.   MakeMove(move);
  376.   UpdateBoard();
  377.   Wait(4);
  378.   TakeBackMove(move);
  379.   UpdateBoard();
  380.   Wait(4);
  381. }
  382.  
  383. void
  384. DoSlideMove(MOVETYPE& move)
  385. {
  386.   SQUARETYPE castsquare, cornersquare;
  387.   SlidePiece(move.new1, move.old);
  388.   if (move.spe) {
  389.     if (move.movpiece == king) {
  390.       GenCastSquare(move.new1, &castsquare, &cornersquare);
  391.       SlidePiece(castsquare, cornersquare);
  392.     }
  393.   }
  394. }
  395.  
  396. void
  397. EndMessage(char* message)
  398. {
  399.   strcpy(EndGameMessage, message);
  400.   GameOver = TRUE;
  401. }
  402.  
  403. void
  404. ShowHint()
  405. {
  406.   DEPTHTYPE dep = 0;
  407.   *buf = 0;
  408.   Message(buf);
  409.   while (HintLine[dep].movpiece != empty) {
  410.     strcat(buf, MoveStr(&HintLine[dep]));
  411.     strcat(buf, " ");
  412.     Message(buf);
  413.     MakeMove(&HintLine[dep]);
  414.     UpdateBoard();
  415.     Wait(6);
  416.     dep++;
  417.   }
  418.   while (dep > 0) {
  419.     dep--;
  420.     TakeBackMove(&HintLine[dep]);
  421.   }
  422.   UpdateBoard();
  423. }
  424.