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

  1. // ObjectWindows - (C) Copyright 1992 by Borland International
  2.  
  3. //  Owl Chess is based upon the chess program originally released
  4. //  with TURBO PASCAL GameWorks.  The chess engine was ported over
  5. //  to C, and is essentially unchanged here.  This demonstrates
  6. //  how OWL may be used to place a WINDOWS wrapper around
  7. //  DOS code, whether it is written in C or C++.
  8.  
  9.  
  10. #include <static.h>
  11. #include <filedial.h>
  12. #include <inputdia.h>
  13. #include <bwcc.h>
  14. #include <string.h>
  15. #include <stdio.h>
  16.  
  17. #include "wcdefs.h"
  18. #include "info.h"
  19. #include "wchess.h"
  20. #include "edit.h"
  21. #include "colors.h"
  22. #include "pvalue.h"
  23. #include "externs.h"
  24.  
  25. #undef MAXPATH
  26. #define MAXPATH  160
  27.  
  28. /*
  29.  *  Global Variables
  30.  */
  31.  
  32. BYTE WhiteSquareColors[3] = { ~0, ~0, ~0 };  /* white */
  33. BYTE BlackSquareColors[3] = { 0, 128, 0 };   /* green */
  34.  
  35. BOOL ShowBestLine = TRUE;
  36. PTInfoWindow TInfo;
  37. HBRUSH hBlackBrush;
  38. HBRUSH hWhiteBrush;
  39. HWND  hWndMain;
  40. HBITMAP PieceBmpArray[6][2];
  41. HBITMAP MaskArray[6];
  42. HCURSOR hArrowCursor;
  43. HCURSOR hWaitCursor;
  44. HMENU ThinkMenu, MainMenu;
  45. HANDLE hAccel;
  46. COLORTYPE ComputerColor;
  47. short LINESIZE;
  48. short CHARSIZE;
  49. int CAPTIONY;
  50. BOOL Editing;
  51. int BORDERSIZE;
  52. const BORDERYEXTRA = 4; // 4 for spacing
  53. short INFOXSIZE, INFOYSIZE;
  54. BOOL SoundOn;
  55.  
  56. // --------------- TChess ----------------------
  57.  
  58. class TChess: public TApplication
  59. {
  60.   public:
  61.    TChess(LPSTR AName, HINSTANCE hInstance, HINSTANCE hPrevInstance,
  62.       LPSTR lpCmdLine, int nCmdShow) : TApplication(AName, hInstance,
  63.       hPrevInstance, lpCmdLine, nCmdShow)
  64.       {
  65.       }
  66.    virtual void InitMainWindow();
  67.    void InitInstance()
  68.    {
  69.       // always call the base class version first
  70.       TApplication::InitInstance();
  71.       hAccel = HAccTable = LoadAccelerators(hInstance, "ChessCommands");
  72.       BWCCGetVersion();  // init of BWCC required to assure load of BWCC.DLL
  73.    }
  74. };
  75.  
  76. // --------------- TMessageDialog ----------------------
  77.  
  78. // This creates a BWCC style message box using a static template
  79. // from the RC file.  A more versatile version would dynamically
  80. // create the message box to fit the size of each message, and allow
  81. // the user to specify what type of buttons to display, much like
  82. // the windows version of MessageBox
  83.  
  84. _CLASSDEF(TMessageDialog)
  85. class TMessageDialog : public TDialog
  86. {
  87.    LPSTR NewMessage;
  88.    LPSTR NewTitle;
  89.    public:
  90.       TMessageDialog(PTWindowsObject AParent, int ResourceId, LPSTR Message, LPSTR Title);
  91.       virtual void SetupWindow();
  92. };
  93.  
  94. TMessageDialog::TMessageDialog(PTWindowsObject AParent, int ResourceId,
  95.    LPSTR Message, LPSTR Title)
  96.    : TDialog(AParent, ResourceId)
  97. {
  98.    NewMessage = Message;
  99.    NewTitle = Title;
  100. }
  101.  
  102. void TMessageDialog::SetupWindow()
  103. {
  104.    // failure to explicitly call the ancestor version of SetupWindow
  105.    // will result in incorrect behavior.  It should always be done
  106.    // first in any derivation of SetupWindow.
  107.    TDialog::SetupWindow();
  108.    SetDlgItemText(HWindow, ID_INPUT, NewMessage);
  109.    SetWindowText(HWindow, NewTitle);
  110. }
  111.  
  112. // --------------- TEndDialog ----------------------
  113.  
  114. _CLASSDEF(TEndDialog)
  115. class TEndDialog : public TDialog
  116. {
  117.    LPSTR EndMessage;
  118.    public:
  119.       TEndDialog(PTWindowsObject AParent, int ResourceId, LPSTR Message);
  120.       virtual void SetupWindow();
  121.       virtual void Yes(RTMessage) = [ID_FIRST+IDYES]
  122.       {
  123.          CloseWindow(IDYES);
  124.       }
  125.       virtual void No(RTMessage) = [ID_FIRST+IDNO]
  126.       {
  127.          ShutDownWindow();
  128.       }
  129. };
  130.  
  131. TEndDialog::TEndDialog(PTWindowsObject AParent, int ResourceId, LPSTR Message)
  132.    : TDialog(AParent, ResourceId)
  133. {
  134.    EndMessage = Message;
  135. }
  136.  
  137. void TEndDialog::SetupWindow()
  138. {
  139.    TDialog::SetupWindow();
  140.    SetDlgItemText(HWindow, ID_INPUT, EndMessage);
  141. }
  142.  
  143.  
  144. // --------------- TChessWindow ----------------------
  145.  
  146. _CLASSDEF(TChessWindow)
  147.  
  148. class TChessWindow : public TWindow
  149. {
  150.    enum TURNTYPE { player, computer };
  151.    PTInfoWindow TInfo;       // pointer to the information window class
  152.    TEditBarWindow *TEditBar; // pointer to the edit bar class
  153.    BOOL NewGame;             // a new game is being set up?
  154.    char *FileName;           // last saved game
  155.    RECT MainWndRect;         // coordinates for the main window
  156.    RECT InfoAreaRect;        // coordinates for the information window
  157.    HMENU hMenu;              // handle to the main menu
  158.    HMENU hThinkMenu;         // handle to the short (stop) menu
  159.    HMENU hEditMenu;          // handle to the edit (arrange) menu
  160.    TURNTYPE WhoseTurn;       // players or computers turn?
  161.    SQUARETYPE MoveStartSquare; // starting square for move
  162.    SQUARETYPE MoveEndSquare; // ending square for move
  163.    COLORTYPE CurPlayer;      // current player
  164.    BOOL GotStartSquare;      // did the user select a valid piece to move?
  165.    HBRUSH hBKBrush;          // handle to brush to paint main window backgnd
  166.    HBITMAP hBKBrushBmp;      // small bitmap used to paint main window bkgnd
  167.    BOOL Modified;            // has the board been changed in edit mode?
  168.    BOOL EditingBoard;        // is the user editing the board
  169.    BOOL Dragging;            // in drag mode?
  170.    BOARDTYPE *SaveBoard;     // saved board setup in case user cancels edit
  171.   public:
  172.    TChessWindow(PTWindowsObject AParent, LPSTR ATitle);
  173.    ~TChessWindow();
  174.    virtual void SetupWindow();
  175.    virtual void GetWindowClass(WNDCLASS& WndClass)
  176.    {
  177.       // Again, call the ancestor version first, as must also
  178.       // be done with SetupWindow and InitInstance
  179.       TWindow::GetWindowClass( WndClass );
  180.  
  181.       // this allows you to specify your own values for the
  182.       // window class, which OWL will register for you
  183.  
  184.       ::hArrowCursor = WndClass.hCursor = LoadCursor(0, IDC_ARROW);
  185.       hBKBrushBmp = LoadBitmap(GetApplication()->hInstance, "BKBrushBmp");
  186.       hBKBrush = CreatePatternBrush(hBKBrushBmp);
  187.  
  188.       WndClass.hbrBackground = hBKBrush;
  189.       WndClass.lpszMenuName = "TChessMenu";
  190.       WndClass.hIcon = LoadIcon(GetApplication()->hInstance, "ChessIcon");
  191.    }
  192.    virtual void Paint( HDC PaintDC, PAINTSTRUCT& PaintInfo );
  193.    virtual void WMLButtonDown( TMessage& Message ) = [ WM_FIRST + WM_LBUTTONDOWN ];
  194.    virtual void WMMouseMove( RTMessage ) = [ WM_FIRST + WM_MOUSEMOVE ];
  195.    virtual void CMNewGame(RTMessage Msg) = [CM_FIRST + CM_FILENEW];
  196.    virtual void CMRestoreGame(RTMessage Msg) = [CM_FIRST + CM_FILEOPEN];
  197.    virtual void CMSaveGame(RTMessage Msg) = [CM_FIRST + CM_FILESAVE];
  198.    virtual void CMSaveGameAs(RTMessage Msg) = [CM_FIRST + CM_FILESAVEAS];
  199.    virtual void Exit(RTMessage) = [CM_FIRST + IDM_EXIT]
  200.       {
  201.       CloseWindow();
  202.       }
  203.    virtual void UndoMove(RTMessage Msg) = [CM_FIRST + CM_UNDO];
  204.    virtual void RedoUndo(RTMessage Msg) = [CM_FIRST + CM_REDO];
  205.     virtual void IDMMovePieces(RTMessage) = [CM_FIRST + IDM_MOVEPIECE];
  206.     virtual void IDMMoveTime(RTMessage) = [CM_FIRST + IDM_MOVETIME];
  207.     virtual void IDMTotalTime(RTMessage) = [CM_FIRST + IDM_TOTALTIME];
  208.     virtual void IDMDemo(RTMessage) = [CM_FIRST + IDM_DEMO];
  209.     virtual void IDMInfiniteSearch(RTMessage) = [CM_FIRST + IDM_INFINITE];
  210.     virtual void IDMPlySearch(RTMessage) = [CM_FIRST + IDM_PLY];
  211.     virtual void IDMMateSearch(RTMessage) = [CM_FIRST + IDM_MATE];
  212.     virtual void IDMSinglePlayer(RTMessage) = [CM_FIRST + IDM_SINGLE];
  213.     virtual void IDMTwoPlayer(RTMessage) = [CM_FIRST + IDM_TWOPLAYER];
  214.     virtual void IDMAutoPlay(RTMessage) = [CM_FIRST + IDM_AUTO];
  215.     virtual void IDMReverseBoard(RTMessage) = [CM_FIRST + IDM_REVERSE];
  216.    virtual void IDMEasy(RTMessage) = [CM_FIRST + IDM_EASY];
  217.    virtual void IDMHint(RTMessage) = [CM_FIRST + IDM_HINT];
  218.    virtual void IDMPass(RTMessage) = [CM_FIRST + IDM_PASS];
  219.    virtual void EMDone(RTMessage) = [CM_FIRST + EM_DONE];
  220.    virtual void EMClear(RTMessage) = [CM_FIRST + EM_CLEAR];
  221.    virtual void EMCancel(RTMessage) = [CM_FIRST + EM_CANCEL];
  222.    virtual void EMError(RTMessage) = [CM_FIRST + EM_ERROR];
  223.    virtual void IDMMatching(RTMessage) = [CM_FIRST + IDM_MATCHING];
  224.    virtual void IDMWhiteTurn(RTMessage) = [CM_FIRST + IDM_WHITETURN];
  225.    virtual void IDMBlackTurn(RTMessage) = [CM_FIRST + IDM_BLACKTURN];
  226.    virtual void IDMColors(RTMessage) = [CM_FIRST + IDM_COLORS];
  227.    virtual void IDMPieceValues(RTMessage) = [CM_FIRST + IDM_PIECEVALUES];
  228.    virtual void IDMBestLine(RTMessage) = [CM_FIRST + IDM_BESTLINE];
  229.    virtual void IDMMouseDrag(RTMessage) = [CM_FIRST + IDM_MOUSEDRAG];
  230.    virtual void IDMMouseSelect(RTMessage) = [CM_FIRST + IDM_MOUSESELECT];
  231.    virtual void IDMSound(RTMessage) = [CM_FIRST + IDM_SOUND];
  232.    virtual void WMTimer(RTMessage) = [WM_FIRST + WM_TIMER];
  233.    void EndGame();
  234.    void DoEdit();
  235.    void SaveGameAs();
  236.    void ComputersTurn();
  237.    void UnCheckLevelMenu(LEVELTYPE);
  238.    void NormalSetup();
  239.    void CheckLevelMenu(LEVELTYPE);
  240.    virtual BOOL CanClose()
  241.       {
  242.          if (ComputerThinking || AutoPlay)
  243.             {
  244.             PostMessage(HWindow, WM_COMMAND, CM_STOP, 0L);
  245.             PostMessage(HWindow, WM_COMMAND, IDM_EXIT, 0L);
  246.             return FALSE;
  247.             }
  248.          QuitProgram();
  249.          return TRUE;
  250.       }
  251. };
  252.  
  253.  
  254. // ------------- TChess member functions -----------------------
  255.  
  256. void TChess::InitMainWindow()
  257. {
  258.    MainWindow = new TChessWindow(NULL, "OWL Chess");
  259. }
  260.  
  261. // ------------- TChessWindow member functions -----------------
  262.  
  263. TChessWindow::TChessWindow(PTWindowsObject AParent, LPSTR ATitle) :
  264.    TWindow(AParent, ATitle)
  265. {
  266.    HDC hDC;
  267.    hDC = GetDC(HWindow);
  268.    TEXTMETRIC tm;
  269.    GetTextMetrics(hDC, &tm);
  270.    CHARSIZE = tm.tmAveCharWidth;
  271.    LINESIZE = tm.tmHeight + tm.tmExternalLeading;
  272.    ReleaseDC(HWindow, hDC);
  273.    CAPTIONY = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYMENU);
  274.    BORDERSIZE = LINESIZE + MYFRAMESIZE;
  275.    TInfo = new TInfoWindow(this, "InfoWindow");
  276.    TEditBar = new TEditBarWindow(this, "EditBar");
  277.    SoundOn = TRUE;
  278.    ::TInfo = TInfo;
  279.    Attr.Style = WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX;
  280.    Attr.X = 5;
  281.    Attr.Y = 5;
  282.    Attr.H = CAPTIONY + (BORDERSIZE * 2) + INFOYSIZE + BORDERYEXTRA +
  283.       (2 * GetSystemMetrics(SM_CYBORDER));
  284.  
  285.    Attr.W = (BORDERSIZE * 4) + (MAXBDSIZE * SQUARE_SIZE) + INFOXSIZE +
  286.       (2 * GetSystemMetrics(SM_CXBORDER)) + (2*MYFRAMESIZE);
  287.    FileName = new char[MAXPATH];
  288.    WhoseTurn = player;
  289.    CurPlayer = white;
  290.    ::ComputerColor = black;
  291.    ::Editing = EditingBoard = GotStartSquare = FALSE;
  292.    NewGame = TRUE;
  293. }
  294.  
  295. TChessWindow::~TChessWindow()
  296. {
  297.    delete FileName;
  298.    delete TInfo;
  299.    DeleteObject(hWhiteBrush);
  300.    DeleteObject(hBlackBrush);
  301.    DeleteObject(hBKBrushBmp);
  302.    DestroyMenu(hThinkMenu);
  303.    DestroyMenu(hEditMenu);
  304.    for (int i = 0; i < 6; i++)
  305.       {
  306.       DeleteObject(MaskArray[i]);
  307.       for (int j = 0; j < 2; j++)
  308.          DeleteObject(PieceBmpArray[i][j]);
  309.       }
  310.    KillTimer(HWindow, TIMEID);
  311. }
  312.  
  313.  
  314. void TChessWindow::SetupWindow()
  315. {
  316.    TWindow::SetupWindow();
  317.    ::hWndMain = HWindow;
  318.    ::hWaitCursor = LoadCursor(0, IDC_WAIT);
  319.    ::PieceBmpArray[pawn-1][white] =
  320.       LoadBitmap(GetApplication()->hInstance, "WPawnBmp");
  321.     ::PieceBmpArray[pawn-1][black] =
  322.       LoadBitmap(GetApplication()->hInstance, "BPawnBmp");
  323.    ::PieceBmpArray[rook-1][white] =
  324.       LoadBitmap(GetApplication()->hInstance, "WRookBmp");
  325.    ::PieceBmpArray[rook-1][black] =
  326.       LoadBitmap(GetApplication()->hInstance, "BRookBmp");
  327.    ::PieceBmpArray[knight-1][black] =
  328.       LoadBitmap(GetApplication()->hInstance, "BKnightBmp");
  329.    ::PieceBmpArray[bishop-1][black] =
  330.       LoadBitmap(GetApplication()->hInstance, "BBishopBmp");
  331.    ::PieceBmpArray[queen-1][black] =
  332.       LoadBitmap(GetApplication()->hInstance, "BQueenBmp");
  333.  
  334.  
  335.    ::PieceBmpArray[knight-1][white] =
  336.       LoadBitmap(GetApplication()->hInstance, "WKnightBmp");
  337.    ::PieceBmpArray[bishop-1][white] =
  338.       LoadBitmap(GetApplication()->hInstance, "WBishopBmp");
  339.    ::PieceBmpArray[queen-1][white] =
  340.       LoadBitmap(GetApplication()->hInstance, "WQueenBmp");
  341.  
  342.    ::PieceBmpArray[king-1][white] =
  343.       LoadBitmap(GetApplication()->hInstance, "WKingBmp");
  344.    ::PieceBmpArray[king-1][black] =
  345.       LoadBitmap(GetApplication()->hInstance, "BKingBmp");
  346.  
  347.    ::MaskArray[pawn-1] =
  348.       LoadBitmap(GetApplication()->hInstance, "PMaskBmp");
  349.    ::MaskArray[rook-1] =
  350.       LoadBitmap(GetApplication()->hInstance, "RMaskBmp");
  351.    ::MaskArray[knight-1] =
  352.       LoadBitmap(GetApplication()->hInstance, "KTMaskBmp");
  353.    ::MaskArray[bishop-1] =
  354.       LoadBitmap(GetApplication()->hInstance, "BMaskBmp");
  355.    ::MaskArray[queen-1] =
  356.       LoadBitmap(GetApplication()->hInstance, "QMaskBmp");
  357.    ::MaskArray[king-1] =
  358.       LoadBitmap(GetApplication()->hInstance, "KMaskBmp");
  359.  
  360.     GetClientRect(HWindow, &MainWndRect);
  361.    InfoAreaRect = MainWndRect;
  362.    InfoAreaRect.left = (MainWndRect.right -= ((BORDERSIZE * 2) + INFOXSIZE));
  363.    MainMenu = hMenu = GetMenu(HWindow);
  364.    ::ThinkMenu = hThinkMenu = LoadMenu(GetApplication()->hInstance, "TChessThinkMenu");
  365.    hEditMenu = LoadMenu(GetApplication()->hInstance, "TChessEditMenu");
  366.  
  367.    ::Talk();
  368.    CheckLevelMenu(Level);
  369.    ::hWhiteBrush = CreateSolidBrush(
  370.       RGB(WhiteSquareColors[0], WhiteSquareColors[1], WhiteSquareColors[2]));
  371.    ::hBlackBrush = CreateSolidBrush(
  372.       RGB(BlackSquareColors[0], BlackSquareColors[1], BlackSquareColors[2]));
  373.    Dragging = TRUE;
  374. }
  375.  
  376.  
  377. void TChessWindow::Paint(HDC PaintDC, PAINTSTRUCT&)
  378. {
  379.    DrawFrame(PaintDC, MainWndRect);
  380.    DrawFrame(PaintDC, InfoAreaRect);
  381.    PrintBoard();
  382. }
  383.  
  384.  
  385.  
  386. void TChessWindow::WMLButtonDown( TMessage& )
  387. {
  388.    POINT Point;
  389.    if (EditingBoard)
  390.       {
  391.       DoEdit();
  392.       return;
  393.       }
  394.  
  395.    if (WhoseTurn == computer && NoComputerMove == FALSE)
  396.       return;
  397.    GetCursorPos( &Point );
  398.    ScreenToClient(HWindow, &Point);
  399.  
  400.    if (!GotStartSquare)
  401.       {
  402.       MoveStartSquare = GetValidSquare(Point, CurPlayer, TRUE);
  403.       if (MoveStartSquare == -1)
  404.          return;
  405.       GotStartSquare = TRUE;
  406.       if (!Dragging)
  407.          DrawInvertedBitmap(MoveStartSquare);
  408.       else
  409.          DragStart(MoveStartSquare, Point);
  410.       }
  411.    else
  412.       {
  413.       MoveEndSquare = GetValidSquare(Point, CurPlayer, FALSE);
  414.       GotStartSquare = FALSE;
  415.       if (MoveEndSquare == -1)
  416.          {
  417.          if (Dragging)
  418.               DragEnd(FALSE);
  419.          Warning("Invalid Move");
  420.          DrawNormalBitmap(MoveStartSquare);
  421.          return;
  422.          }
  423.       if (!MoveCheck(MoveStartSquare, MoveEndSquare))
  424.          {
  425.          if (Dragging)
  426.             DragEnd(FALSE);
  427.          DrawNormalBitmap(MoveStartSquare);
  428.          return;
  429.          }
  430.       ::GotValidMove = TRUE;
  431.       EnableMenuItem(hMenu, CM_UNDO, MF_BYCOMMAND | MF_ENABLED);
  432.       if (GameOver)
  433.          EndGame();
  434.       else if (NoComputerMove == FALSE)
  435.          ComputersTurn();
  436.       else if (::MultiMove)
  437.          {
  438.          CurPlayer = (CurPlayer == white) ? black : white;
  439.          }
  440.       }
  441. }
  442.  
  443. void TChessWindow::ComputersTurn()
  444. {
  445.    WhoseTurn = computer;
  446.    SetClassWord(HWindow, GCW_HCURSOR, WORD( ::hWaitCursor ));
  447.    SetCursor(::hWaitCursor);
  448.    SetMenu(HWindow, hThinkMenu);
  449.    ProgramMove();
  450.    SetMenu(HWindow, hMenu);
  451.    WhoseTurn = player;
  452.    SetClassWord( HWindow, GCW_HCURSOR, WORD( hArrowCursor ));
  453.    if (GameOver)
  454.       EndGame();
  455. }
  456.  
  457. void TChessWindow::CMNewGame(RTMessage)
  458. {
  459.    KillTimer(HWindow, TIMEID);
  460.    TInfo->SetTimerText("");
  461.    EnableMenuItem(hMenu, CM_UNDO, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  462.    EnableMenuItem(hMenu, CM_REDO, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  463.    NewGame = TRUE;
  464.    ::NewGame();
  465.    ::PrintBoard();
  466.    CurPlayer = Player;
  467.    ComputerColor = Opponent;
  468. }
  469.  
  470. void TChessWindow::CMRestoreGame(RTMessage)
  471. {
  472.    if (GetApplication()->ExecDialog(new TFileDialog(this,
  473.       SD_FILEOPEN, strcpy(FileName, "*.CHS"))) == IDOK)
  474.       {
  475.       NewGame = FALSE;
  476.       ::RestoreGame(FileName);
  477.       CurPlayer = Player;
  478.       ComputerColor = Opponent;
  479.       EnableMenuItem(hMenu, CM_REDO, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  480.       EnableMenuItem(hMenu, CM_UNDO, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  481.       }
  482. }
  483.  
  484. void TChessWindow::SaveGameAs()
  485. {
  486.    if (GetApplication()->ExecDialog(new TFileDialog(this,
  487.       SD_FILESAVE, strcpy(FileName, "*.CHS")))
  488.          == IDOK)
  489.       {
  490.       NewGame = FALSE;
  491.       ::SaveGame(FileName);
  492.       }
  493. }
  494.  
  495. void TChessWindow::CMSaveGame(RTMessage)
  496. {
  497.    if (NewGame == TRUE)
  498.       SaveGameAs();
  499.    else
  500.       ::SaveGame(FileName);
  501. }
  502.  
  503. void TChessWindow::CMSaveGameAs(RTMessage)
  504. {
  505.    SaveGameAs();
  506. }
  507.  
  508. void TChessWindow::EMError(RTMessage)
  509. {
  510.    GetApplication()->ExecDialog(new TMessageDialog(this, SD_CHESSERROR,
  511.       (LPSTR)buf, "OWL Chess Error"));
  512. }
  513.  
  514. void TChessWindow::DoEdit()
  515. {
  516.    POINT Point;
  517.    SQUARETYPE Square;
  518.    int SelectedItem;
  519.  
  520.    Modified = TRUE;
  521.    GetCursorPos( &Point );
  522.    ScreenToClient(HWindow, &Point);
  523.    Square = GetValidSquare(Point, black, FALSE);
  524.  
  525.    if (Board[Square].piece != empty)
  526.       {
  527.       Board[Square].piece = empty;
  528.       ::UpdateBoard();
  529.       return;
  530.       }
  531.    SelectedItem = TEditBar->GetSelectedItem();
  532.  
  533.    Board[Square].piece = (PIECETYPE)(SelectedItem % 6 + 1);
  534.    Board[Square].color = (SelectedItem < 6) ? white : black;
  535.    ::UpdateBoard();
  536. }
  537.  
  538. void TChessWindow::IDMMovePieces(RTMessage)
  539. {
  540.    SaveBoard = new BOARDTYPE[0x78];
  541.    if (SaveBoard == NULL)
  542.       {
  543.       Error("Not enough memory");
  544.       return;
  545.       }
  546.    memcpy(SaveBoard, Board, sizeof(BOARDTYPE) * 0x78);
  547.    Editing = EditingBoard = TRUE;
  548.    TInfo->Show(SW_HIDE);
  549.    SetMenu(HWindow, hEditMenu);
  550.    Modified = FALSE;
  551.    if (CurPlayer == white)
  552.       {
  553.       CheckMenuItem(hEditMenu, IDM_BLACKTURN, MF_UNCHECKED);
  554.       CheckMenuItem(hEditMenu, IDM_WHITETURN, MF_CHECKED);
  555.       }
  556.    else
  557.       {
  558.       CheckMenuItem(hEditMenu, IDM_BLACKTURN, MF_CHECKED);
  559.       CheckMenuItem(hEditMenu, IDM_WHITETURN, MF_UNCHECKED);
  560.       }
  561.    TEditBar->Show(SW_NORMAL);
  562. }
  563.  
  564. void TChessWindow::EMDone(RTMessage)
  565. {
  566.    SQUARETYPE sq;
  567.    int KingCount[2] = { 0, 0 };
  568.    int TotalCount[2] = { 0, 0 };
  569.    BOOL Done = FALSE;
  570.  
  571.    if (Modified)
  572.       {
  573.       for (sq = 0; sq < 0x78; sq++)
  574.          if (!(sq & 0x88))
  575.             {
  576.             if (Board[sq].piece != empty)
  577.                {
  578.                TotalCount[Board[sq].color]++;
  579.                if (Board[sq].piece == king)
  580.                   KingCount[Board[sq].color]++;
  581.                }
  582.             }
  583.       if (TotalCount[white] <= 16 && KingCount[white] == 1
  584.          && TotalCount[black] <= 16 && KingCount[black] == 1)
  585.          {
  586.          ResetNewPos();
  587.          if (!Attacks(Player, PieceTab[Opponent][0].isquare))
  588.             Done = TRUE;
  589.          else
  590.             Error("Illegal King position");
  591.           }
  592.       else
  593.           Error("Wrong number of pieces");
  594.       }
  595.    else
  596.       NormalSetup();
  597.  
  598.    if (Done)
  599.       NormalSetup();
  600. }
  601.  
  602. void TChessWindow::EMClear(RTMessage)
  603. {
  604.    SQUARETYPE sq;
  605.  
  606.    Modified = TRUE;
  607.    for (sq = 0; sq <= 0x77; sq++)
  608.       Board[sq].piece = empty;
  609.    ::UpdateBoard();
  610. }
  611.  
  612. void TChessWindow::EMCancel(RTMessage)
  613. {
  614.    memcpy(Board, SaveBoard, sizeof(BOARDTYPE) * 0x78);
  615.    ResetNewPos();
  616.    NormalSetup();
  617. }
  618.  
  619.  
  620. void TChessWindow::NormalSetup()
  621. {
  622.    TEditBar->Show(SW_HIDE);
  623.    TInfo->Show(SW_NORMAL);
  624.    SetMenu(HWindow, hMenu);
  625.    delete[] SaveBoard;
  626.    Editing = EditingBoard = FALSE;
  627.    ::UpdateBoard();
  628. }
  629.  
  630. void TChessWindow::IDMMoveTime(RTMessage)
  631. {
  632.    char *SecsPerMove = new char[40];
  633.  
  634.    sprintf(SecsPerMove, "%.2lf", ::AverageTime);
  635.    if (GetApplication()->ExecDialog(new TInputDialog(this, "Set Seconds per Move",
  636.       "Seconds Per Move:", SecsPerMove, 19)) == IDOK)
  637.       {
  638.       double NewMoveTime = atof(SecsPerMove);
  639.       if (NewMoveTime > 0.)
  640.          {
  641.          if (::Level != normal)
  642.             {
  643.             UnCheckLevelMenu(Level);
  644.             CheckMenuItem(hMenu, IDM_MOVETIME, MF_CHECKED);
  645.             }
  646.          ::Level = normal;
  647.          ::AverageTime = NewMoveTime;
  648.          PrintCurLevel();
  649.          for (COLORTYPE color = white; color <= black; ((int)color)++)
  650.             ::ChessTime[color].totaltime = (::MoveNo / 2) * ::AverageTime;
  651.          ::MaxLevel = MAXPLY;
  652.          }
  653.       else
  654.          Error("Invalid time.  No change made.");
  655.       }
  656.    delete SecsPerMove;
  657. }
  658.  
  659.  
  660. void TChessWindow::IDMTotalTime(RTMessage)
  661. {
  662.    char *TotalMoveTime = new char[40];
  663.    sprintf(TotalMoveTime, "%.2lf", ::AverageTime);
  664.  
  665.    if (GetApplication()->ExecDialog(new TInputDialog(this, "Set Seconds per Game",
  666.       "Seconds Per Game:", TotalMoveTime, 19)) == IDOK)
  667.       {
  668.       double NewMoveTime = atof(TotalMoveTime);
  669.       if (NewMoveTime > 0.)
  670.          {
  671.          if (::Level != fullgametime)
  672.             {
  673.             UnCheckLevelMenu(Level);
  674.             CheckMenuItem(hMenu, IDM_TOTALTIME, MF_CHECKED);
  675.             }
  676.          ::Level = fullgametime;
  677.          ::AverageTime = NewMoveTime;
  678.          ::PrintCurLevel();
  679.          for (COLORTYPE color = white; color <= black; ((int)color)++)
  680.             ::ChessTime[color].totaltime = (::MoveNo / 2) * ::AverageTime;
  681.          ::MaxLevel = MAXPLY;
  682.          }
  683.       else
  684.          Error("Invalid time.  No change made.");
  685.       }
  686.    delete TotalMoveTime;
  687. }
  688.  
  689. void TChessWindow::IDMDemo(RTMessage)
  690. {
  691.    extern BOOL AutoPlay;
  692.    BOOL IsEasy = FALSE;
  693.    if (::Level == easygame)
  694.       {
  695.       IsEasy = TRUE;
  696.       ::Level = normal;
  697.       HideAttacks();
  698.       }
  699.    AutoPlay = TRUE;
  700.    ComputersTurn();
  701.    if (IsEasy)
  702.       {
  703.       ::Level = easygame;
  704.       ::UpdateBoard();
  705.       }
  706.    CurPlayer = Player;
  707.    ComputerColor = Opponent;
  708.    ::PrintCurLevel();
  709. }
  710.  
  711. void TChessWindow::IDMMatching(RTMessage)
  712. {
  713.    if (::Level != matching)
  714.       {
  715.       UnCheckLevelMenu(Level);
  716.       CheckMenuItem(hMenu, IDM_MATCHING, MF_CHECKED);
  717.       }
  718.    ::Level = matching;
  719.    ::PrintCurLevel();
  720. }
  721.  
  722. void TChessWindow::IDMInfiniteSearch(RTMessage)
  723. {
  724.    if (::Level != infinite)
  725.       {
  726.       UnCheckLevelMenu(Level);
  727.       CheckMenuItem(hMenu, IDM_INFINITE, MF_CHECKED);
  728.       }
  729.    ::Level = infinite;
  730.    ::MaxLevel = MAXPLY;
  731.    ::PrintCurLevel();
  732. }
  733.  
  734. void TChessWindow::IDMPlySearch(RTMessage)
  735. {
  736.    char *PlySearchDepth = new char[40];
  737.    sprintf(PlySearchDepth, "%d", ::MaxLevel);
  738.    if (GetApplication()->ExecDialog(new TInputDialog(this, "Set ply depth", "Number of plys:",
  739.       PlySearchDepth, 19)) == IDOK)
  740.       {
  741.       int NewPlyDepth = atoi(PlySearchDepth);
  742.       if (NewPlyDepth > 0)
  743.          {
  744.          if (::Level != plysearch)
  745.             {
  746.             UnCheckLevelMenu(Level);
  747.             CheckMenuItem(hMenu, IDM_PLY, MF_CHECKED);
  748.             }
  749.          ::MaxLevel = (BYTE)((NewPlyDepth > MAXPLY) ? MAXPLY : NewPlyDepth);
  750.          ::Level = plysearch;
  751.          ::PrintCurLevel();
  752.          }
  753.       else
  754.         ::Error("Invalid time.  No change made.");
  755.       }
  756.    delete PlySearchDepth;
  757. }
  758.  
  759. void TChessWindow::IDMMateSearch(RTMessage)
  760. {
  761.    if (::Level != matesearch)
  762.       {
  763.       UnCheckLevelMenu(Level);
  764.       CheckMenuItem(hMenu, IDM_MATE, MF_CHECKED);
  765.       }
  766.    ::Level = matesearch;
  767.    ::PrintCurLevel();
  768.    ComputersTurn();
  769. }
  770.  
  771. void TChessWindow::IDMSinglePlayer(RTMessage)
  772. {
  773. }
  774.  
  775. void TChessWindow::IDMTwoPlayer(RTMessage)
  776. {
  777.    static LEVELTYPE OldLevel = normal;
  778.    ::MultiMove = !::MultiMove;
  779.  
  780.  
  781.    if (::MultiMove)
  782.       {
  783.       OldLevel = ::Level;
  784.       ModifyMenu(hMenu, IDM_TWOPLAYER, MF_BYCOMMAND | MF_STRING,
  785.          IDM_TWOPLAYER, "&Single Player");
  786.       EnableMenuItem(hMenu, 2, MF_GRAYED | MF_BYPOSITION);
  787.       DrawMenuBar(HWindow);
  788.       ::Level = normal;
  789.       ::PrintCurLevel();
  790.       }
  791.    else
  792.       {
  793.       ModifyMenu(hMenu, IDM_TWOPLAYER, MF_BYCOMMAND | MF_STRING,
  794.          IDM_TWOPLAYER, "&Two Player");
  795.       EnableMenuItem(hMenu, 2, MF_ENABLED | MF_BYPOSITION);
  796.       DrawMenuBar(HWindow);
  797.       ::Level = OldLevel;
  798.       ::PrintCurLevel();
  799.       }
  800. }
  801.  
  802. void TChessWindow::IDMAutoPlay(RTMessage)
  803. {
  804. }
  805.  
  806. void TChessWindow::IDMReverseBoard(RTMessage)
  807. {
  808.    ::Turned = !::Turned;
  809.    ::PrintBoard();
  810. }
  811.  
  812. void TChessWindow::UndoMove(RTMessage)
  813. {
  814.  
  815.    if (ComputerThinking)
  816.       {
  817.       MessageToPost = CM_UNDO;
  818.       return;
  819.       }
  820.    if (!Undo())
  821.       EnableMenuItem(hMenu, CM_UNDO, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  822.    EnableMenuItem(hMenu, CM_REDO, MF_BYCOMMAND | MF_ENABLED);
  823.    CurPlayer = Player;
  824.    ComputerColor = Opponent;
  825. }
  826.  
  827.  
  828. void TChessWindow::RedoUndo(RTMessage)
  829. {
  830.    if (ComputerThinking)
  831.       {
  832.       MessageToPost = CM_REDO;
  833.       return;
  834.       }
  835.    if (!Redo())
  836.       EnableMenuItem(hMenu, CM_REDO, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  837.    EnableMenuItem(hMenu, CM_UNDO, MF_BYCOMMAND | MF_ENABLED);
  838.    CurPlayer = Player;
  839.    ComputerColor = Opponent;
  840. }
  841.  
  842.  
  843. void TChessWindow::UnCheckLevelMenu(LEVELTYPE level)
  844. {
  845.    WORD CheckItem = IDM_EASY;
  846.  
  847.    switch (level)
  848.       {
  849.       case normal :
  850.          CheckItem = IDM_MOVETIME;
  851.          break;
  852.       case fullgametime :
  853.          CheckItem = IDM_TOTALTIME;
  854.          break;
  855.       case plysearch :
  856.          CheckItem = IDM_PLY;
  857.          break;
  858.       case easygame :
  859.          CheckItem = IDM_EASY;
  860.          break;
  861.       case infinite :
  862.          CheckItem = IDM_INFINITE;
  863.          break;
  864.       case matesearch :
  865.          CheckItem = IDM_MATE;
  866.          break;
  867.       case matching :
  868.          CheckItem = IDM_MATCHING;
  869.          break;
  870.       }
  871.    CheckMenuItem(hMenu, CheckItem, MF_UNCHECKED);
  872. }
  873.  
  874. void TChessWindow::CheckLevelMenu(LEVELTYPE level)
  875. {
  876.    WORD CheckItem = IDM_EASY;
  877.  
  878.    switch (level)
  879.       {
  880.       case normal :
  881.          CheckItem = IDM_MOVETIME;
  882.          break;
  883.       case fullgametime :
  884.          CheckItem = IDM_TOTALTIME;
  885.          break;
  886.       case plysearch :
  887.          CheckItem = IDM_PLY;
  888.          break;
  889.       case easygame :
  890.          CheckItem = IDM_EASY;
  891.          break;
  892.       case infinite :
  893.          CheckItem = IDM_INFINITE;
  894.          break;
  895.       case matesearch :
  896.          CheckItem = IDM_MATE;
  897.          break;
  898.       case matching :
  899.          CheckItem = IDM_MATCHING;
  900.          break;
  901.       }
  902.    CheckMenuItem(hMenu, CheckItem, MF_CHECKED);
  903. }
  904.  
  905.  
  906. void TChessWindow::IDMEasy(RTMessage)
  907. {
  908.    if (::Level != easygame)
  909.       {
  910.       UnCheckLevelMenu(Level);
  911.       CheckMenuItem(hMenu, IDM_EASY, MF_CHECKED);
  912.       }
  913.    ::Level = easygame;
  914.    ::AverageTime = 5.;
  915.    ::MaxLevel = MAXPLY;
  916.    ::PrintCurLevel();
  917. }
  918.  
  919. void TChessWindow::EndGame()
  920. {
  921.    if (GetApplication()->ExecDialog(new TEndDialog(this, SD_ENDGAMEDLG,
  922.       (LPSTR) EndGameMessage)) != IDYES)
  923.       {
  924.       PostMessage(hWndMain, WM_COMMAND, CM_EXIT, 0L);
  925.       return;
  926.       }
  927.    GameOver = FALSE;
  928.    PostMessage(hWndMain, WM_COMMAND, CM_FILENEW, 0L);
  929.    return;
  930. }
  931.  
  932. void TChessWindow::IDMHint(RTMessage)
  933. {
  934.    FindHintMove();
  935.    ShowHint();
  936. }
  937.  
  938. void TChessWindow::IDMPass(RTMessage)
  939. {
  940.    if (::Level == easygame)
  941.       HideAttacks();
  942.    CurPlayer = Opponent;
  943.    ComputerColor = Player;
  944.    ComputersTurn();
  945. }
  946.  
  947. void TChessWindow::IDMWhiteTurn(RTMessage)
  948. {
  949.    CheckMenuItem(hEditMenu, IDM_BLACKTURN, MF_UNCHECKED);
  950.    CheckMenuItem(hEditMenu, IDM_WHITETURN, MF_CHECKED);
  951.    CurPlayer = white;
  952.    ComputerColor = black;
  953.    if (CurPlayer != Player)
  954.       {
  955.       Opponent = ComputerColor;
  956.       Player = ProgramColor = CurPlayer;
  957.       }
  958. }
  959.  
  960.  
  961. void TChessWindow::IDMBlackTurn(RTMessage)
  962. {
  963.    CheckMenuItem(hEditMenu, IDM_BLACKTURN, MF_CHECKED);
  964.    CheckMenuItem(hEditMenu, IDM_WHITETURN, MF_UNCHECKED);
  965.    CurPlayer = black;
  966.    ComputerColor = white;
  967.    if (CurPlayer != Player)
  968.       {
  969.       Opponent = ComputerColor;
  970.       Player = ProgramColor = CurPlayer;
  971.       }
  972. }
  973.  
  974. void TChessWindow::IDMColors(RTMessage)
  975. {
  976.    GetApplication()->ExecDialog(new TColorsDialog(this, "ColorsDialog"));
  977.    DeleteObject(hWhiteBrush);
  978.    DeleteObject(hBlackBrush);
  979.    ::hWhiteBrush = CreateSolidBrush(
  980.       RGB(WhiteSquareColors[0], WhiteSquareColors[1], WhiteSquareColors[2]));
  981.    ::hBlackBrush = CreateSolidBrush(
  982.       RGB(BlackSquareColors[0], BlackSquareColors[1], BlackSquareColors[2]));
  983. }
  984.  
  985. void TChessWindow::IDMPieceValues(RTMessage)
  986. {
  987.    GetApplication()->ExecDialog(new TPieceValueDialog(this, "PieceValueDlg"));
  988. }
  989.  
  990. void TChessWindow::IDMBestLine(RTMessage)
  991. {
  992.    ShowBestLine = !ShowBestLine;
  993.  
  994.    if (ShowBestLine)
  995.       CheckMenuItem(hMenu, IDM_BESTLINE, MF_CHECKED);
  996.    else
  997.       {
  998.       CheckMenuItem(hMenu, IDM_BESTLINE, MF_UNCHECKED);
  999.       TInfo->SetBestLineText("");
  1000.       }
  1001. }
  1002.  
  1003. void TChessWindow::WMMouseMove(RTMessage msg)
  1004. {
  1005.    if (!GotStartSquare || !Dragging)
  1006.       return;
  1007.    Drag(MAKEPOINT(msg.LParam));
  1008. }
  1009.  
  1010. void TChessWindow::IDMMouseDrag(RTMessage)
  1011. {
  1012.    POINT Point;
  1013.  
  1014.    if (!Dragging && GotStartSquare)
  1015.       {
  1016.          DrawNormalBitmap(MoveStartSquare);
  1017.          GetCursorPos(&Point);
  1018.          DragStart(MoveStartSquare, Point);
  1019.       }
  1020.  
  1021.    Dragging = TRUE;
  1022.    CheckMenuItem(hMenu, IDM_MOUSEDRAG, MF_CHECKED);
  1023.    CheckMenuItem(hMenu, IDM_MOUSESELECT, MF_UNCHECKED);
  1024. }
  1025.  
  1026. void TChessWindow::IDMMouseSelect(RTMessage)
  1027. {
  1028.    DragEnd(TRUE);
  1029.    Dragging = FALSE;
  1030.    CheckMenuItem(hMenu, IDM_MOUSEDRAG, MF_UNCHECKED);
  1031.    CheckMenuItem(hMenu, IDM_MOUSESELECT, MF_CHECKED);
  1032.    if (GotStartSquare)
  1033.          DrawInvertedBitmap(MoveStartSquare);
  1034. }
  1035.  
  1036. void TChessWindow::IDMSound(RTMessage)
  1037. {
  1038.    SoundOn = !SoundOn;
  1039.    if (SoundOn)
  1040.       CheckMenuItem(hMenu, IDM_SOUND, MF_CHECKED);
  1041.    else
  1042.       CheckMenuItem(hMenu, IDM_SOUND, MF_UNCHECKED);
  1043. }
  1044.  
  1045. void TChessWindow::WMTimer(RTMessage)
  1046. {
  1047.    DisplayTime();
  1048. }
  1049.  
  1050.  
  1051. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  1052.                       LPSTR lpCmdLine, int nCmdShow)
  1053. {
  1054.    TChess ChessApp("ChessApp", hInstance, hPrevInstance, lpCmdLine,
  1055.       nCmdShow);
  1056.    ChessApp.Run();
  1057.    return ChessApp.Status;
  1058. }
  1059.  
  1060.