home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_144 / 2.ddi / CHESS.ZIP / TALK.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-10  |  14.3 KB  |  612 lines

  1. // ObjectWindows - (C) Copyright 1992 by Borland International
  2.  
  3. #include <windows.h>
  4. #include <fstream.h>
  5. #include <string.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <math.h>
  9. #include <dos.h>
  10. #include <time.h>
  11. #include <ctype.h>
  12.  
  13. #include "wchess.h"
  14. #include "wcdefs.h"
  15. #include "externs.h"
  16.  
  17. /*
  18.  *  Global declarations
  19.  */
  20.  
  21. char *INIFile = "wchess.ini";
  22. BOOL InLibrary;          // True if program is in the opening library
  23. BOOL MultiMove,      // True if multimove mode
  24.      AutoPlay,           // True if AutoPlay mode
  25.       SingleStep;        // Single Step mode, used for debugging purposes
  26. LEVELTYPE Level;
  27. double AverageTime = 5.0;
  28. PIECETYPE Pieces[8]  = { rook, knight, bishop, queen,
  29.                               king, bishop, knight, rook};
  30. BYTE MaxLevel;
  31. BOOL Turned;
  32. BOOL UseLib;
  33. LIBTYPE Openings;
  34. COLORTYPE ProgramColor;
  35. int MoveNo;
  36. int PVTable[2][7][0x78];
  37. MOVETYPE PlayerMove;
  38. BOOL Logging;
  39. NODEVAL Nodes;             // Number of analysed nodes
  40. CLOCKTYPE ChessClock;
  41. extern int LegalMoves;
  42. LINETYPE HintLine;            /*  suggested hint line  */
  43. MAXTYPE HintEvalu;            /*  Evaluation for hintline  */
  44. enum ANALYSISCONTROL {Start, Return, Continue};
  45.  
  46. int OpCount, LibNo;
  47.  
  48. static DEPTHTYPE LibDepth;
  49. static BOOL Found;
  50. static DEPTHTYPE dep;
  51.  
  52. ofstream *OutputFile;
  53.  
  54. typedef enum {readmove, checkmove, gamemove} CONTROLVAR;
  55. static CONTROLVAR Control;
  56.  
  57.  
  58.  
  59. void InsertPiece(PIECETYPE p, COLORTYPE c, SQUARETYPE sq)
  60. {
  61.     Board[sq].piece = p;
  62.     Board[sq].color = c;
  63. }
  64.  
  65.  
  66. void ClearPVTable()
  67. {
  68.     COLORTYPE color;
  69.     PIECETYPE piece;
  70.     SQUARETYPE square;
  71.  
  72.     for (color = white; color <= black; ((int)color)++)
  73.         for (piece = king; piece <= pawn; ((int)piece)++)
  74.             for (square = 0; square <= 0x77; square++)
  75.                 PVTable[color][piece][square] = 0;
  76. }
  77.  
  78.  
  79. void ResetGame()
  80. {
  81.     ClearBoard();
  82.    Running = FALSE;
  83.    for (int i = 0; i < 8; i++)
  84.       {
  85.         InsertPiece(Pieces[i], white, i);
  86.         InsertPiece(pawn, white, i + 0x10);
  87.         InsertPiece(pawn, black, i + 0x60);
  88.         InsertPiece(Pieces[i], black, i + 0x70);
  89.       }
  90.    CalcPieceTab();
  91.    Player = white;
  92.    ClearDisplay();
  93.    InitDisplay();
  94.    ColorToPlay(Player);
  95.    Opponent = black;
  96. }
  97.  
  98.  
  99. void NewGame()
  100. {
  101.     SingleStep = InLibrary = FALSE;
  102.    GameOver = FALSE;
  103.    ResetGame();
  104.    PrintCurLevel();
  105.    ResetMoves();
  106.    if (!*Openings)
  107.          UseLib = 0;
  108.    else
  109.       UseLib = 200;
  110.    MovTab[-1].content = king;
  111.    InitChessTime();
  112.    ProgramColor = white;
  113.    MoveNo = 0;
  114.    ClearHint();
  115.    ClearPVTable();
  116.    PlayerMove = ZeroMove;
  117.    if (Logging && !AutoPlay)
  118.       *OutputFile << "\n No  Player Program      Hint      Value Level       Nodes    Time\n";
  119.    InitNode(&Nodes);
  120.    ChessClock.totaltime = 0.0;
  121.    Control = (AutoPlay) ? gamemove : readmove;
  122. }
  123.  
  124.  
  125. void ResetNewPos(void)
  126. {
  127.     ResetMoves();
  128.     CalcPieceTab();
  129.     UseLib = FALSE;
  130.     Running = FALSE;
  131.     ClearHint();
  132. }
  133.  
  134.  
  135. void ResetOpening()
  136. {
  137.    const char *libfilename = "opening.lib";
  138.    ifstream fin(libfilename, ios::in | ios::binary);
  139.  
  140.    if (!fin)
  141.       {
  142.       MessageBox(NULL,"Cannot find Openings Library", "Error",
  143.                  MB_ICONHAND | MB_OK);
  144.         Openings = new unsigned char;
  145.         *Openings = 0;
  146.       return;
  147.       }
  148.    Openings = new unsigned char[32000];
  149.    fin.read(Openings, 32000);
  150.    fin.close();
  151.    *Openings = 0xFF;
  152. }
  153.  
  154.  
  155. static void StartUp()
  156. {
  157.    long color;
  158.    randomize();
  159.  
  160.    Level = (LEVELTYPE)GetPrivateProfileInt("WCHESS", "Level",
  161.       (int)easygame, INIFile);
  162.  
  163.    if (GetPrivateProfileString("WCHESS", "AverageTime", "5.0", buf,
  164.       80, INIFile))
  165.       sscanf(buf, "%lf", &AverageTime);
  166.  
  167.    if (GetPrivateProfileString("WCHESS", "WhiteSquare", "", buf, 80, INIFile))
  168.       {
  169.       sscanf(buf, "%ld", &color);
  170.       WhiteSquareColors[0] = color & 0xffL;
  171.       WhiteSquareColors[1] = (BYTE)((color & 0xff00L) >> 8);
  172.       WhiteSquareColors[2] = (BYTE)((color & 0xff0000L) >> 16);
  173.       }
  174.  
  175.    if (GetPrivateProfileString("WCHESS", "BlackSquare", "", buf, 80, INIFile))
  176.       {
  177.       sscanf(buf, "%ld", &color);
  178.       BlackSquareColors[0] = color & 0xff;
  179.       BlackSquareColors[1] = ((color & 0xff00L) >> 8);
  180.       BlackSquareColors[2] = ((color & 0xff0000L) >> 16);
  181.       }
  182.  
  183.    MaxLevel = GetPrivateProfileInt("WCHESS", "MaxLevel", MAXPLY, INIFile);
  184.    SoundOn = (BOOL)GetPrivateProfileInt("WCHESS", "SoundOn", 1, INIFile);
  185.  
  186.    if (!SoundOn)  // defaults to checked at startup
  187.       CheckMenuItem(MainMenu, IDM_SOUND, MF_UNCHECKED);
  188.    CalcAttackTab();
  189.    MultiMove = FALSE;
  190.    AutoPlay = FALSE;
  191.    Turned = FALSE;
  192.    ResetOpening();
  193.    OutputFile = new ofstream("Chess.log");
  194.    if (!OutputFile)
  195.       {
  196.       MessageBox(NULL, "Unable to open log file.\nLogging disabled", "OWL Chess", MB_OK | MB_ICONEXCLAMATION);
  197.       Logging = FALSE;
  198.       }
  199.    else
  200.       {
  201.       *OutputFile << endl;
  202.       *OutputFile << "            OWL CHESS by Borland International\n";
  203.       *OutputFile << "            ==================================\n" << endl;
  204.       }
  205. }
  206.  
  207. const UNPLAYMARK = 0x3f;
  208.  
  209.  
  210. /*
  211.  *  Sets libno to the previous move in the block
  212.  */
  213.  
  214. void PreviousLibNo(void)
  215. {
  216.     int n;
  217.  
  218.     n = 0;
  219.     do
  220.     {
  221.         LibNo--;
  222.         if (Openings[LibNo] >= 128) n++;
  223.         if (Openings[LibNo] & 64) n--;
  224.     } while (n);
  225. }
  226.  
  227.  
  228. /*
  229.  *  Set libno to the first move in the block
  230.  */
  231.  
  232. void FirstLibNo()
  233. {
  234.     while (!(Openings[LibNo - 1] & 64))
  235.         PreviousLibNo();
  236. }
  237.  
  238.  
  239. /*
  240.  *  set libno to the next move in the block.  Unplayable
  241.  *  moves are skipped if skip is set
  242.  */
  243.  
  244. void NextLibNo(short skip)
  245. {
  246.     int n;
  247.  
  248.     if (Openings[LibNo] >= 128) FirstLibNo();
  249.     else
  250.     {
  251.         n = 0;
  252.         do
  253.         {
  254.             if (Openings[LibNo] & 64) n++;
  255.             if (Openings[LibNo] >= 128) n--;
  256.             LibNo++;
  257.         } while (n);
  258.         if (skip && (Openings[LibNo] == UNPLAYMARK))
  259.             FirstLibNo();
  260.     }
  261. }
  262.  
  263.  
  264. /*
  265.  *  find the node corresponding to the correct block
  266.  */
  267.  
  268. static void FindNode(void)
  269. {
  270.     LibNo++;
  271.     if (Depth > LibDepth)
  272.     {
  273.         Found = TRUE;
  274.         return;
  275.     }
  276.     OpCount = -1;
  277.     InitMovGen();
  278.     do
  279.     {
  280.         OpCount++;
  281.         MovGen();
  282.     } while (Next.movpiece != empty && !EqMove(&Next, &MovTab[Depth]));
  283.     if (Next.movpiece != empty)
  284.     {
  285.         while (((Openings[LibNo] & 63) != OpCount) &&
  286.                 (Openings[LibNo] < 128))
  287.             NextLibNo(0);
  288.         if ((Openings[LibNo] & 127) == 64 + OpCount)
  289.         {
  290.             MakeMove(&MovTab[Depth]);
  291.             FindNode();
  292.             TakeBackMove(&MovTab[Depth-1]);
  293.         }
  294.     }
  295. }
  296.  
  297.  
  298. /*
  299.  *  Set LibNo to the block corresponding to the position
  300.  */
  301.  
  302. void CalcLibNo(void)
  303. {
  304.     LibNo = 0;
  305.     if (MoveNo < UseLib)
  306.     {
  307.         LibDepth = Depth;
  308.         while (MovTab[Depth].movpiece != empty)
  309.             TakeBackMove(&MovTab[Depth]);
  310.         Found = FALSE;
  311.         if (MovTab[Depth].content == king)
  312.         {
  313.             Depth++;
  314.             FindNode();
  315.             Depth--;
  316.         }
  317.         while(Depth < LibDepth)
  318.             MakeMove(&MovTab[Depth + 1]);
  319.         if (Found)
  320.             UseLib = 200;
  321.         else
  322.         {
  323.             UseLib = MoveNo;
  324.             LibNo = 0;
  325.         }
  326.     }
  327. }
  328.  
  329.  
  330. /*
  331.  *  find an opening move from the library
  332.  */
  333.  
  334. static void FindOpeningMove(void)
  335. {
  336.     const unsigned char weight[7] = {7, 10, 12, 13, 14, 15, 16};
  337.     unsigned char cnt, r, p, countp;
  338.  
  339.     r = random(16);   /*  calculate weighted random number in 0..16  */
  340.     p = 0;
  341.     while (r >= weight[p]) p++;
  342.     for (countp = 1; countp <= p; countp++)  /* find corresponding node */
  343.         NextLibNo(1);
  344.     OpCount = Openings[LibNo] & 63;  /*  generate the move  */
  345.     InitMovGen();
  346.     for (cnt = 0; cnt <= OpCount; cnt++)
  347.         MovGen();
  348.                           /* store the move in mainline  */
  349.     MainLine[0] = Next;
  350.     MainLine[1] = ZeroMove;
  351.     MainEvalu = 0;
  352.     MaxDepth = 0;
  353.     LegalMoves = 0;
  354.     InitNode(&Nodes);
  355. }
  356.  
  357.  
  358.  
  359. void OutputNode(NODEVAL *nodes)
  360. {
  361.    double nodereal;
  362.    if (!Logging)
  363.       return;
  364.    char buf[20];
  365.    nodereal = (nodes->nodebase * MAXINT) + nodes->nodeoffset;
  366.    sprintf(buf, "%12.1f", nodereal);
  367.    *OutputFile << buf;
  368. }
  369.  
  370. static void ThinkAwhile();
  371. void StartMove();
  372.  
  373. void ReturnAnalysis()
  374. {
  375.    int myx;
  376.    char str[8];
  377.    char buf[40];
  378.  
  379.    MovTab[0] = MainLine[0];   /*  copy the MainLine to HintLine  */
  380.    for (myx = 1; myx <= MAXPLY; myx++)
  381.        HintLine[myx - 1] = MainLine[myx];
  382.    dep = MAXPLY;
  383.    HintEvalu = MainEvalu;
  384.    if (MovTab[0].movpiece == empty)
  385.    {
  386.        HintLine[0] = ZeroMove;   /*  No possible move  */
  387.        if (AutoPlay)
  388.        {
  389.            NewGame();
  390.            PrintBoard();
  391.            StartMove();
  392.        }
  393.        return;
  394.    }
  395.  
  396. //   FlashMove(&MovTab[Depth+1]);  /*  flash and perform the move  */
  397.    DoSlideMove(MovTab[Depth+1]);
  398.    EnterMove(&MovTab[Depth+1]);
  399.    if (SoundOn)
  400.       MessageBeep(0);
  401.    StoreMoves();
  402.    if (Logging && !AutoPlay)
  403.       {
  404.       sprintf(buf, "%3d. ",(MoveNo+1) / 2);
  405.       *OutputFile << buf;
  406.       strcpy(str, MoveStr(&MovTab[0]));
  407.       if ((PlayerMove.movpiece == empty) && (Opponent == white))
  408.           sprintf(buf, "%8.8s ", str);
  409.       else
  410.           sprintf(buf, "%s%8.8s",MoveStr(&PlayerMove), str);
  411.       *OutputFile << buf;
  412.       sprintf(buf, "    (%s)%9.2f%3d:%2d", MoveStr(&MainLine[1]),
  413.            MainEvalu / 256.0, MaxDepth, LegalMoves);
  414.       *OutputFile << buf;
  415.       OutputNode(&Nodes);
  416.       sprintf(buf, "%8.1lf\n", ChessClock.totaltime);
  417.       *OutputFile << buf;
  418.       }
  419.    PlayerMove = ZeroMove;
  420.    ColorToPlay(Player);
  421.    if (AutoPlay)
  422.    {
  423.         if ((MoveNo >= 120) || (FiftyMoveCnt() >= 100) ||
  424.             (Repetition(0) >= 3) || (MainEvalu <= -0x880))
  425.             {
  426.             NewGame();
  427.             PrintBoard();
  428.             }
  429.         StartMove();
  430.         return;
  431.     }
  432.    if (Level != easygame && !GameOver)
  433.        ThinkAwhile();
  434. }
  435.  
  436.  
  437. /*
  438.  *  Perform analysis in the opponents time of reflection.
  439.  *  The program assumes that the opponent will perform the
  440.  *  Hint move, and starts analysing on it for a counter move
  441.  */
  442.  
  443.  
  444. static void ThinkAwhile()
  445. {
  446. extern HCURSOR hArrowCursor;
  447.  
  448.    SetClassWord(hWndMain, GCW_HCURSOR, WORD( hArrowCursor ));
  449.    SetCursor(hArrowCursor);
  450.    SetMenu(hWndMain, MainMenu);
  451.     if ((HintLine[0].movpiece == empty) || MultiMove)
  452.         return;
  453.     Analysis = FALSE;
  454.     Opan = TRUE;
  455.     AdjustMoves();          /*  Setup surroundings as if the  */
  456.     MovTab[Depth+1] = HintLine[0];  /*  Opponent had performed  */
  457.     MakeMove(&MovTab[Depth+1]);        /*  The hint move  */
  458.     StoreMoves();
  459.     AdjustMoves();
  460.     Depth = 0;          /*  analyse until something is entered from by */
  461.     FindMove(MaxLevel); /*  the user */
  462.     Depth = -1;
  463.     Opan = FALSE;
  464.     if (Analysis)          /*  If the Opponent did make the  */
  465.     {                      /*  Hint move then go and  */
  466.         ReturnAnalysis();  /*  perform the counter move  */
  467.         return;
  468.     }
  469.     TakeBackMove(&MovTab[Depth]);  /*  restore the surroundings  */
  470.     if (GotValidMove)
  471.       {
  472.       AdjustMoves();
  473.       EnterKeyMove();
  474.       StoreMoves();
  475.       SetMenu(hWndMain, ThinkMenu);
  476.       SetClassWord(hWndMain, GCW_HCURSOR, WORD( hWaitCursor ));
  477.       SetCursor(hWaitCursor);
  478.       }
  479.     return;
  480. }
  481.  
  482.  
  483. void StartMove()
  484. {
  485.    MSG msg;
  486.    StartAnalysis();
  487.    AdjustMoves();
  488.    CalcLibNo();            /*  Try to find a move in the opening library  */
  489.    Depth = 0;
  490.    if (LibNo > 0)
  491.    {
  492.        OpeningLibMsg();
  493.        InLibrary = TRUE;
  494.        FindOpeningMove();
  495.        if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
  496.          {
  497.             if (msg.message == WM_COMMAND && msg.wParam == CM_STOP)
  498.                return;
  499.             TranslateMessage(&msg);
  500.             DispatchMessage(&msg);
  501.          }
  502.    }
  503.    else
  504.    {
  505.        if (InLibrary)
  506.        {
  507.            InLibrary = FALSE;
  508.            ClearMessage();
  509.        }
  510.        FindMove(MaxLevel);
  511.    }
  512.    Depth = -1;
  513.    ReturnAnalysis();
  514. }
  515.  
  516.  
  517. void ProgramMove()
  518. {
  519.    do
  520.       {
  521.       GotValidMove = FALSE;
  522.       ColorToPlay(Player);
  523.       StartMove();
  524.       }
  525.    while (GotValidMove);
  526. }
  527.  
  528.  
  529. void Talk()
  530. {
  531.    StartUp();
  532.    NewGame();
  533. }
  534.  
  535.  
  536. BOOL Redo()
  537. {
  538. //   MakeMove(&MovTab[Depth+1]);
  539.    EnterMove(&MovTab[Depth+1]);
  540.    ClearHint();
  541. //   UpdateBoard();
  542.    ClearBestLine();
  543.    ColorToPlay(Player);
  544.    if (Depth >= -1)
  545.       return FALSE;  // cannot redo again
  546.    return TRUE;  // can redo again
  547. }
  548.  
  549. BOOL Undo()
  550. {
  551. // TakeBackMove(&MovTab[Depth]);
  552.    extern void RemoveMove(MOVETYPE *);
  553.    RemoveMove(&MovTab[Depth]);
  554.    ClearHint();
  555. //   UpdateBoard();
  556.    ClearBestLine();
  557.    ColorToPlay(Player);
  558.    if (MovTab[Depth].movpiece == empty)
  559.       return FALSE;  // Can't undo anymore
  560.    return TRUE;  // Can still undo
  561. }
  562.  
  563. void QuitProgram()
  564. {
  565.    long color;
  566.  
  567.    if (Logging)
  568.       OutputFile->close();
  569.    color = RGB(WhiteSquareColors[0], WhiteSquareColors[1],
  570.       WhiteSquareColors[2]);
  571.    sprintf(buf, "%ld", color);
  572.    WritePrivateProfileString("WCHESS", "WhiteSquare", buf, INIFile);
  573.    color = RGB(BlackSquareColors[0], BlackSquareColors[1],
  574.       BlackSquareColors[2]);
  575.    sprintf(buf, "%ld", color);
  576.    WritePrivateProfileString("WCHESS", "BlackSquare", buf, INIFile);
  577.    sprintf(buf, "%d", Level);
  578.    WritePrivateProfileString("WCHESS", "Level", buf, INIFile);
  579.    sprintf(buf, "%lf", AverageTime);
  580.    WritePrivateProfileString("WCHESS", "AverageTime", buf, INIFile);
  581.    sprintf(buf, "%d", (int)MaxLevel);
  582.    WritePrivateProfileString("WCHESS", "MaxLevel", buf, INIFile);
  583.    sprintf(buf, "%d", (int)SoundOn);
  584.    WritePrivateProfileString("WCHESS", "SoundOn", buf, INIFile);
  585. }
  586.  
  587.  
  588. void FindHintMove()
  589. {
  590.     /*  If hintline is empty the get the move from the
  591.         opening library or perform a 1 - ply search  */
  592.     if (HintLine[0].movpiece == empty)
  593.     {
  594.         AdjustMoves();
  595.         CalcLibNo();
  596.         Depth = 0;
  597.         if (LibNo > 0)
  598.             FindOpeningMove();
  599.         else
  600.         {
  601.             Analysis = 1;
  602.             Opan = 0;
  603.             FindMove(1);
  604.         }
  605.         Depth = -1;
  606.         HintLine[0] = MainLine[0];
  607.         HintLine[1] = ZeroMove;
  608.         HintEvalu = -MainEvalu;
  609.     }
  610. }
  611.  
  612.